Commit b07bcf34 authored by Kevin Tang's avatar Kevin Tang Committed by Maarten Lankhorst

drm/sprd: add Unisoc's drm display controller driver

Adds DPU(Display Processor Unit) support for the Unisoc's display
subsystem.
It's support multi planes, scaler, rotation, PQ(Picture Quality) and more.

v2:
  - Use drm_xxx to replace all DRM_XXX.
  - Use kzalloc to replace devm_kzalloc for sprd_dpu structure init.

v3:
  - Remove dpu_layer stuff layer and commit layers by aotmic_update

v4:
  - Use drmm_helpers to allocate crtc and planes.
  - Move rotation enum definitions to crtc layer reg bitfields.
  - Move allocate crtc and planes to bind function.

v5:
  - Fix the checkpatch warnings.
  - Use mode_set_nofb instead of mode_valid callback.
  - Follow the OF-Graph bindings, use of_graph_get_port_by_id
    instead of of_parse_phandle.
  - Use zpos to represent the layer position.
  - Rebase to last drm misc branch.

v6:
  - Disable and clear interrupts before register dpu IRQ
  - Init dpi config used by crtc_state->adjusted_mode on mode_set_nofb
  - Remove enable_irq and disable_irq function call.
  - Remove drm_format_info function call.

v7:
  - Remove iommu error interrupt handling function.

Cc: Orson Zhai <orsonzhai@gmail.com>
Cc: Chunyan Zhang <zhang.lyra@gmail.com>
Signed-off-by: default avatarKevin Tang <kevin.tang@unisoc.com>
Reviewed-by: default avatarMaxime Ripard <maxime@cerno.tech>
Signed-off-by: default avatarMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20211207142717.30296-5-kevin3.tang@gmail.com
parent 8cae15c6
......@@ -5,6 +5,7 @@ config DRM_SPRD
select DRM_GEM_CMA_HELPER
select DRM_KMS_CMA_HELPER
select DRM_KMS_HELPER
select VIDEOMODE_HELPERS
help
Choose this option if you have a Unisoc chipset.
If M is selected the module will be called sprd_drm.
......
# SPDX-License-Identifier: GPL-2.0
obj-y := sprd_drm.o
obj-y := sprd_drm.o \
sprd_dpu.o
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2020 Unisoc Inc.
*/
#ifndef __SPRD_DPU_H__
#define __SPRD_DPU_H__
#include <linux/bug.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/string.h>
#include <video/videomode.h>
#include <drm/drm_crtc.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_print.h>
#include <drm/drm_vblank.h>
#include <uapi/drm/drm_mode.h>
/* DPU Layer registers offset */
#define DPU_LAY_REG_OFFSET 0x30
enum {
SPRD_DPU_IF_DPI,
SPRD_DPU_IF_EDPI,
SPRD_DPU_IF_LIMIT
};
/**
* Sprd DPU context structure
*
* @base: DPU controller base address
* @irq: IRQ number to install the handler for
* @if_type: The type of DPI interface, default is DPI mode.
* @vm: videomode structure to use for DPU and DPI initialization
* @stopped: indicates whether DPU are stopped
* @wait_queue: wait queue, used to wait for DPU shadow register update done and
* DPU stop register done interrupt signal.
* @evt_update: wait queue condition for DPU shadow register
* @evt_stop: wait queue condition for DPU stop register
*/
struct dpu_context {
void __iomem *base;
int irq;
u8 if_type;
struct videomode vm;
bool stopped;
wait_queue_head_t wait_queue;
bool evt_update;
bool evt_stop;
};
/**
* Sprd DPU device structure
*
* @crtc: crtc object
* @drm: A point to drm device
* @ctx: DPU's implementation specific context object
*/
struct sprd_dpu {
struct drm_crtc base;
struct drm_device *drm;
struct dpu_context ctx;
};
static inline struct sprd_dpu *to_sprd_crtc(struct drm_crtc *crtc)
{
return container_of(crtc, struct sprd_dpu, base);
}
static inline void
dpu_reg_set(struct dpu_context *ctx, u32 offset, u32 set_bits)
{
u32 bits = readl_relaxed(ctx->base + offset);
writel(bits | set_bits, ctx->base + offset);
}
static inline void
dpu_reg_clr(struct dpu_context *ctx, u32 offset, u32 clr_bits)
{
u32 bits = readl_relaxed(ctx->base + offset);
writel(bits & ~clr_bits, ctx->base + offset);
}
static inline u32
layer_reg_rd(struct dpu_context *ctx, u32 offset, int index)
{
u32 layer_offset = offset + index * DPU_LAY_REG_OFFSET;
return readl(ctx->base + layer_offset);
}
static inline void
layer_reg_wr(struct dpu_context *ctx, u32 offset, u32 cfg_bits, int index)
{
u32 layer_offset = offset + index * DPU_LAY_REG_OFFSET;
writel(cfg_bits, ctx->base + layer_offset);
}
void sprd_dpu_run(struct sprd_dpu *dpu);
void sprd_dpu_stop(struct sprd_dpu *dpu);
#endif
......@@ -180,6 +180,7 @@ static struct platform_driver sprd_drm_driver = {
static struct platform_driver *sprd_drm_drivers[] = {
&sprd_drm_driver,
&sprd_dpu_driver,
};
static int __init sprd_drm_init(void)
......
......@@ -13,4 +13,6 @@ struct sprd_drm {
struct drm_device drm;
};
extern struct platform_driver sprd_dpu_driver;
#endif /* _SPRD_DRM_H_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment