Commit 400e9134 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'mediatek-drm-next-5.5' of https://github.com/ckhu-mediatek/linux.git-tags into drm-next



Mediatek DRM next for Linux 5.5

This include mipi_tx, dsi, and partial crtc for MT8183 SoC.

Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: CK Hu <ck.hu@mediatek.com>
Link: https://patchwork.freedesktop.org/patch/msgid/1571103548.4416.6.camel@mtksdaap41
parents 89910e62 631005b2
Loading
Loading
Loading
Loading
+17 −13
Original line number Diff line number Diff line
@@ -28,9 +28,12 @@ Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.txt.
Required properties (all function blocks):
- compatible: "mediatek,<chip>-disp-<function>", one of
	"mediatek,<chip>-disp-ovl"   		- overlay (4 layers, blending, csc)
	"mediatek,<chip>-disp-ovl-2l"           - overlay (2 layers, blending, csc)
	"mediatek,<chip>-disp-rdma"  		- read DMA / line buffer
	"mediatek,<chip>-disp-wdma"  		- write DMA
	"mediatek,<chip>-disp-ccorr"            - color correction
	"mediatek,<chip>-disp-color" 		- color processor
	"mediatek,<chip>-disp-dither"           - dither
	"mediatek,<chip>-disp-aal"   		- adaptive ambient light controller
	"mediatek,<chip>-disp-gamma" 		- gamma correction
	"mediatek,<chip>-disp-merge" 		- merge streams from two RDMA sources
@@ -49,6 +52,7 @@ Required properties (all function blocks):
  For most function blocks this is just a single clock input. Only the DSI and
  DPI controller nodes have multiple clock inputs. These are documented in
  mediatek,dsi.txt and mediatek,dpi.txt, respectively.
  An exception is that the mt8183 mutex is always free running with no clocks property.

Required properties (DMA function blocks):
- compatible: Should be one of
+2 −2
Original line number Diff line number Diff line
@@ -7,7 +7,7 @@ channel output.

Required properties:
- compatible: "mediatek,<chip>-dsi"
  the supported chips are mt2701 and mt8173.
  the supported chips are mt2701, mt8173 and mt8183.
- reg: Physical base address and length of the controller's registers
- interrupts: The interrupt signal from the function block.
- clocks: device clocks
@@ -26,7 +26,7 @@ The MIPI TX configuration module controls the MIPI D-PHY.

Required properties:
- compatible: "mediatek,<chip>-mipi-tx"
  the supported chips are mt2701 and mt8173.
  the supported chips are mt2701, mt8173 and mt8183.
- reg: Physical base address and length of the controller's registers
- clocks: PLL reference clock
- clock-output-names: name of the output clock line to the DSI encoder
+2 −0
Original line number Diff line number Diff line
@@ -12,6 +12,8 @@ mediatek-drm-y := mtk_disp_color.o \
		  mtk_drm_plane.o \
		  mtk_dsi.o \
		  mtk_mipi_tx.o \
		  mtk_mt8173_mipi_tx.o \
		  mtk_mt8183_mipi_tx.o \
		  mtk_dpi.o

obj-$(CONFIG_DRM_MEDIATEK) += mediatek-drm.o
+55 −6
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@
#define DISP_REG_OVL_EN				0x000c
#define DISP_REG_OVL_RST			0x0014
#define DISP_REG_OVL_ROI_SIZE			0x0020
#define DISP_REG_OVL_DATAPATH_CON		0x0024
#define OVL_BGCLR_SEL_IN				BIT(2)
#define DISP_REG_OVL_ROI_BGCLR			0x0028
#define DISP_REG_OVL_SRC_CON			0x002c
#define DISP_REG_OVL_CON(n)			(0x0030 + 0x20 * (n))
@@ -31,7 +33,9 @@
#define DISP_REG_OVL_ADDR_MT8173		0x0f40
#define DISP_REG_OVL_ADDR(ovl, n)		((ovl)->data->addr + 0x20 * (n))

#define	OVL_RDMA_MEM_GMC	0x40402020
#define GMC_THRESHOLD_BITS	16
#define GMC_THRESHOLD_HIGH	((1 << GMC_THRESHOLD_BITS) / 4)
#define GMC_THRESHOLD_LOW	((1 << GMC_THRESHOLD_BITS) / 8)

#define OVL_CON_BYTE_SWAP	BIT(24)
#define OVL_CON_MTX_YUV_TO_RGB	(6 << 16)
@@ -49,6 +53,8 @@

struct mtk_disp_ovl_data {
	unsigned int addr;
	unsigned int gmc_bits;
	unsigned int layer_nr;
	bool fmt_rgb565_is_0;
};

@@ -126,15 +132,31 @@ static void mtk_ovl_config(struct mtk_ddp_comp *comp, unsigned int w,

static unsigned int mtk_ovl_layer_nr(struct mtk_ddp_comp *comp)
{
	return 4;
	struct mtk_disp_ovl *ovl = comp_to_ovl(comp);

	return ovl->data->layer_nr;
}

static void mtk_ovl_layer_on(struct mtk_ddp_comp *comp, unsigned int idx)
{
	unsigned int reg;
	unsigned int gmc_thrshd_l;
	unsigned int gmc_thrshd_h;
	unsigned int gmc_value;
	struct mtk_disp_ovl *ovl = comp_to_ovl(comp);

	writel(0x1, comp->regs + DISP_REG_OVL_RDMA_CTRL(idx));
	writel(OVL_RDMA_MEM_GMC, comp->regs + DISP_REG_OVL_RDMA_GMC(idx));

	gmc_thrshd_l = GMC_THRESHOLD_LOW >>
		      (GMC_THRESHOLD_BITS - ovl->data->gmc_bits);
	gmc_thrshd_h = GMC_THRESHOLD_HIGH >>
		      (GMC_THRESHOLD_BITS - ovl->data->gmc_bits);
	if (ovl->data->gmc_bits == 10)
		gmc_value = gmc_thrshd_h | gmc_thrshd_h << 16;
	else
		gmc_value = gmc_thrshd_l | gmc_thrshd_l << 8 |
			    gmc_thrshd_h << 16 | gmc_thrshd_h << 24;
	writel(gmc_value, comp->regs + DISP_REG_OVL_RDMA_GMC(idx));

	reg = readl(comp->regs + DISP_REG_OVL_SRC_CON);
	reg = reg | BIT(idx);
@@ -217,6 +239,24 @@ static void mtk_ovl_layer_config(struct mtk_ddp_comp *comp, unsigned int idx,
		mtk_ovl_layer_on(comp, idx);
}

static void mtk_ovl_bgclr_in_on(struct mtk_ddp_comp *comp)
{
	unsigned int reg;

	reg = readl(comp->regs + DISP_REG_OVL_DATAPATH_CON);
	reg = reg | OVL_BGCLR_SEL_IN;
	writel(reg, comp->regs + DISP_REG_OVL_DATAPATH_CON);
}

static void mtk_ovl_bgclr_in_off(struct mtk_ddp_comp *comp)
{
	unsigned int reg;

	reg = readl(comp->regs + DISP_REG_OVL_DATAPATH_CON);
	reg = reg & ~OVL_BGCLR_SEL_IN;
	writel(reg, comp->regs + DISP_REG_OVL_DATAPATH_CON);
}

static const struct mtk_ddp_comp_funcs mtk_disp_ovl_funcs = {
	.config = mtk_ovl_config,
	.start = mtk_ovl_start,
@@ -227,6 +267,8 @@ static const struct mtk_ddp_comp_funcs mtk_disp_ovl_funcs = {
	.layer_on = mtk_ovl_layer_on,
	.layer_off = mtk_ovl_layer_off,
	.layer_config = mtk_ovl_layer_config,
	.bgclr_in_on = mtk_ovl_bgclr_in_on,
	.bgclr_in_off = mtk_ovl_bgclr_in_off,
};

static int mtk_disp_ovl_bind(struct device *dev, struct device *master,
@@ -276,7 +318,12 @@ static int mtk_disp_ovl_probe(struct platform_device *pdev)
	if (irq < 0)
		return irq;

	comp_id = mtk_ddp_comp_get_id(dev->of_node, MTK_DISP_OVL);
	priv->data = of_device_get_match_data(dev);

	comp_id = mtk_ddp_comp_get_id(dev->of_node,
				      priv->data->layer_nr == 4 ?
				      MTK_DISP_OVL :
				      MTK_DISP_OVL_2L);
	if (comp_id < 0) {
		dev_err(dev, "Failed to identify by alias: %d\n", comp_id);
		return comp_id;
@@ -289,8 +336,6 @@ static int mtk_disp_ovl_probe(struct platform_device *pdev)
		return ret;
	}

	priv->data = of_device_get_match_data(dev);

	platform_set_drvdata(pdev, priv);

	ret = devm_request_irq(dev, irq, mtk_disp_ovl_irq_handler,
@@ -316,11 +361,15 @@ static int mtk_disp_ovl_remove(struct platform_device *pdev)

static const struct mtk_disp_ovl_data mt2701_ovl_driver_data = {
	.addr = DISP_REG_OVL_ADDR_MT2701,
	.gmc_bits = 8,
	.layer_nr = 4,
	.fmt_rgb565_is_0 = false,
};

static const struct mtk_disp_ovl_data mt8173_ovl_driver_data = {
	.addr = DISP_REG_OVL_ADDR_MT8173,
	.gmc_bits = 8,
	.layer_nr = 4,
	.fmt_rgb565_is_0 = true,
};

+34 −3
Original line number Diff line number Diff line
@@ -272,6 +272,9 @@ static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc)
	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
		struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[i];

		if (i == 1)
			mtk_ddp_comp_bgclr_in_on(comp);

		mtk_ddp_comp_config(comp, width, height, vrefresh, bpc);
		mtk_ddp_comp_start(comp);
	}
@@ -280,9 +283,18 @@ static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc)
	for (i = 0; i < mtk_crtc->layer_nr; i++) {
		struct drm_plane *plane = &mtk_crtc->planes[i];
		struct mtk_plane_state *plane_state;
		struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0];
		unsigned int comp_layer_nr = mtk_ddp_comp_layer_nr(comp);
		unsigned int local_layer;

		plane_state = to_mtk_plane_state(plane->state);
		mtk_ddp_comp_layer_config(mtk_crtc->ddp_comp[0], i,

		if (i >= comp_layer_nr) {
			comp = mtk_crtc->ddp_comp[1];
			local_layer = i - comp_layer_nr;
		} else
			local_layer = i;
		mtk_ddp_comp_layer_config(comp, local_layer,
					  plane_state);
	}

@@ -301,8 +313,12 @@ static void mtk_crtc_ddp_hw_fini(struct mtk_drm_crtc *mtk_crtc)
	int i;

	DRM_DEBUG_DRIVER("%s\n", __func__);
	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
		mtk_ddp_comp_stop(mtk_crtc->ddp_comp[i]);
		if (i == 1)
			mtk_ddp_comp_bgclr_in_off(mtk_crtc->ddp_comp[i]);
	}

	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
		mtk_disp_mutex_remove_comp(mtk_crtc->mutex,
					   mtk_crtc->ddp_comp[i]->id);
@@ -327,6 +343,8 @@ static void mtk_crtc_ddp_config(struct drm_crtc *crtc)
	struct mtk_crtc_state *state = to_mtk_crtc_state(mtk_crtc->base.state);
	struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0];
	unsigned int i;
	unsigned int comp_layer_nr = mtk_ddp_comp_layer_nr(comp);
	unsigned int local_layer;

	/*
	 * TODO: instead of updating the registers here, we should prepare
@@ -349,7 +367,14 @@ static void mtk_crtc_ddp_config(struct drm_crtc *crtc)
			plane_state = to_mtk_plane_state(plane->state);

			if (plane_state->pending.config) {
				mtk_ddp_comp_layer_config(comp, i, plane_state);
				if (i >= comp_layer_nr) {
					comp = mtk_crtc->ddp_comp[1];
					local_layer = i - comp_layer_nr;
				} else
					local_layer = i;

				mtk_ddp_comp_layer_config(comp, local_layer,
							  plane_state);
				plane_state->pending.config = false;
			}
		}
@@ -582,6 +607,12 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
	}

	mtk_crtc->layer_nr = mtk_ddp_comp_layer_nr(mtk_crtc->ddp_comp[0]);
	if (mtk_crtc->ddp_comp_nr > 1) {
		struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[1];

		if (comp->funcs->bgclr_in_on)
			mtk_crtc->layer_nr += mtk_ddp_comp_layer_nr(comp);
	}
	mtk_crtc->planes = devm_kcalloc(dev, mtk_crtc->layer_nr,
					sizeof(struct drm_plane),
					GFP_KERNEL);
Loading