Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cdf5316b authored by Dave Airlie's avatar Dave Airlie
Browse files

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

This series is MT2701 DRM support.

* 'drm-next-4.12' of https://github.com/ckhu-mediatek/linux.git-tags:
  drm/mediatek: add support for Mediatek SoC MT2701
  drm/mediatek: update DSI sub driver flow for sending commands to panel
  drm/mediatek: add non-continuous clock mode and EOT packet control
  drm/mediatek: add dsi transfer function
  drm/mediatek: add dsi interrupt control
  drm/mediatek: cleaning up and refine
  drm/mediatek: update display module connections
  drm/mediatek: add BLS component
  drm/mediatek: add shadow register support
  drm/mediatek: add *driver_data for different hardware settings
  drm/mediatek: add helpers for coverting from the generic components
  dt-bindings: display: mediatek: update supported chips
parents 01687781 84a5ead1
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ Required properties (all function blocks):
	"mediatek,<chip>-dpi"        - DPI controller, see mediatek,dpi.txt
	"mediatek,<chip>-disp-mutex" - display mutex
	"mediatek,<chip>-disp-od"    - overdrive
  the supported chips are mt2701 and mt8173.
- reg: Physical base address and length of the function block register space
- interrupts: The interrupt signal from the function block (required, except for
  merge and split function blocks).
@@ -54,6 +55,7 @@ Required properties (DMA function blocks):
	"mediatek,<chip>-disp-ovl"
	"mediatek,<chip>-disp-rdma"
	"mediatek,<chip>-disp-wdma"
  the supported chips are mt2701 and mt8173.
- larb: Should contain a phandle pointing to the local arbiter device as defined
  in Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt
- iommus: Should point to the respective IOMMU block with master port as
+2 −0
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@ channel output.

Required properties:
- compatible: "mediatek,<chip>-dsi"
  the supported chips are mt2701 and mt8173.
- reg: Physical base address and length of the controller's registers
- interrupts: The interrupt signal from the function block.
- clocks: device clocks
@@ -25,6 +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.
- 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
+47 −17
Original line number Diff line number Diff line
@@ -35,18 +35,28 @@
#define DISP_REG_OVL_PITCH(n)			(0x0044 + 0x20 * (n))
#define DISP_REG_OVL_RDMA_CTRL(n)		(0x00c0 + 0x20 * (n))
#define DISP_REG_OVL_RDMA_GMC(n)		(0x00c8 + 0x20 * (n))
#define DISP_REG_OVL_ADDR(n)			(0x0f40 + 0x20 * (n))
#define DISP_REG_OVL_ADDR_MT2701		0x0040
#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 OVL_CON_BYTE_SWAP	BIT(24)
#define OVL_CON_CLRFMT_RGB565	(0 << 12)
#define OVL_CON_CLRFMT_RGB888	(1 << 12)
#define OVL_CON_CLRFMT_RGB	(1 << 12)
#define OVL_CON_CLRFMT_RGBA8888	(2 << 12)
#define OVL_CON_CLRFMT_ARGB8888	(3 << 12)
#define OVL_CON_CLRFMT_RGB565(ovl)	((ovl)->data->fmt_rgb565_is_0 ? \
					0 : OVL_CON_CLRFMT_RGB)
#define OVL_CON_CLRFMT_RGB888(ovl)	((ovl)->data->fmt_rgb565_is_0 ? \
					OVL_CON_CLRFMT_RGB : 0)
#define	OVL_CON_AEN		BIT(8)
#define	OVL_CON_ALPHA		0xff

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

/**
 * struct mtk_disp_ovl - DISP_OVL driver structure
 * @ddp_comp - structure containing type enum and hardware resources
@@ -55,8 +65,14 @@
struct mtk_disp_ovl {
	struct mtk_ddp_comp		ddp_comp;
	struct drm_crtc			*crtc;
	const struct mtk_disp_ovl_data	*data;
};

static inline struct mtk_disp_ovl *comp_to_ovl(struct mtk_ddp_comp *comp)
{
	return container_of(comp, struct mtk_disp_ovl, ddp_comp);
}

static irqreturn_t mtk_disp_ovl_irq_handler(int irq, void *dev_id)
{
	struct mtk_disp_ovl *priv = dev_id;
@@ -76,20 +92,18 @@ static irqreturn_t mtk_disp_ovl_irq_handler(int irq, void *dev_id)
static void mtk_ovl_enable_vblank(struct mtk_ddp_comp *comp,
				  struct drm_crtc *crtc)
{
	struct mtk_disp_ovl *priv = container_of(comp, struct mtk_disp_ovl,
						 ddp_comp);
	struct mtk_disp_ovl *ovl = comp_to_ovl(comp);

	priv->crtc = crtc;
	ovl->crtc = crtc;
	writel(0x0, comp->regs + DISP_REG_OVL_INTSTA);
	writel_relaxed(OVL_FME_CPL_INT, comp->regs + DISP_REG_OVL_INTEN);
}

static void mtk_ovl_disable_vblank(struct mtk_ddp_comp *comp)
{
	struct mtk_disp_ovl *priv = container_of(comp, struct mtk_disp_ovl,
						 ddp_comp);
	struct mtk_disp_ovl *ovl = comp_to_ovl(comp);

	priv->crtc = NULL;
	ovl->crtc = NULL;
	writel_relaxed(0x0, comp->regs + DISP_REG_OVL_INTEN);
}

@@ -138,18 +152,18 @@ static void mtk_ovl_layer_off(struct mtk_ddp_comp *comp, unsigned int idx)
	writel(0x0, comp->regs + DISP_REG_OVL_RDMA_CTRL(idx));
}

static unsigned int ovl_fmt_convert(unsigned int fmt)
static unsigned int ovl_fmt_convert(struct mtk_disp_ovl *ovl, unsigned int fmt)
{
	switch (fmt) {
	default:
	case DRM_FORMAT_RGB565:
		return OVL_CON_CLRFMT_RGB565;
		return OVL_CON_CLRFMT_RGB565(ovl);
	case DRM_FORMAT_BGR565:
		return OVL_CON_CLRFMT_RGB565 | OVL_CON_BYTE_SWAP;
		return OVL_CON_CLRFMT_RGB565(ovl) | OVL_CON_BYTE_SWAP;
	case DRM_FORMAT_RGB888:
		return OVL_CON_CLRFMT_RGB888;
		return OVL_CON_CLRFMT_RGB888(ovl);
	case DRM_FORMAT_BGR888:
		return OVL_CON_CLRFMT_RGB888 | OVL_CON_BYTE_SWAP;
		return OVL_CON_CLRFMT_RGB888(ovl) | OVL_CON_BYTE_SWAP;
	case DRM_FORMAT_RGBX8888:
	case DRM_FORMAT_RGBA8888:
		return OVL_CON_CLRFMT_ARGB8888;
@@ -168,6 +182,7 @@ static unsigned int ovl_fmt_convert(unsigned int fmt)
static void mtk_ovl_layer_config(struct mtk_ddp_comp *comp, unsigned int idx,
				 struct mtk_plane_state *state)
{
	struct mtk_disp_ovl *ovl = comp_to_ovl(comp);
	struct mtk_plane_pending_state *pending = &state->pending;
	unsigned int addr = pending->addr;
	unsigned int pitch = pending->pitch & 0xffff;
@@ -179,7 +194,7 @@ static void mtk_ovl_layer_config(struct mtk_ddp_comp *comp, unsigned int idx,
	if (!pending->enable)
		mtk_ovl_layer_off(comp, idx);

	con = ovl_fmt_convert(fmt);
	con = ovl_fmt_convert(ovl, fmt);
	if (idx != 0)
		con |= OVL_CON_AEN | OVL_CON_ALPHA;

@@ -187,7 +202,7 @@ static void mtk_ovl_layer_config(struct mtk_ddp_comp *comp, unsigned int idx,
	writel_relaxed(pitch, comp->regs + DISP_REG_OVL_PITCH(idx));
	writel_relaxed(src_size, comp->regs + DISP_REG_OVL_SRC_SIZE(idx));
	writel_relaxed(offset, comp->regs + DISP_REG_OVL_OFFSET(idx));
	writel_relaxed(addr, comp->regs + DISP_REG_OVL_ADDR(idx));
	writel_relaxed(addr, comp->regs + DISP_REG_OVL_ADDR(ovl, idx));

	if (pending->enable)
		mtk_ovl_layer_on(comp, idx);
@@ -264,6 +279,8 @@ 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,
@@ -287,8 +304,21 @@ static int mtk_disp_ovl_remove(struct platform_device *pdev)
	return 0;
}

static const struct mtk_disp_ovl_data mt2701_ovl_driver_data = {
	.addr = DISP_REG_OVL_ADDR_MT2701,
	.fmt_rgb565_is_0 = false,
};

static const struct mtk_disp_ovl_data mt8173_ovl_driver_data = {
	.addr = DISP_REG_OVL_ADDR_MT8173,
	.fmt_rgb565_is_0 = true,
};

static const struct of_device_id mtk_disp_ovl_driver_dt_match[] = {
	{ .compatible = "mediatek,mt8173-disp-ovl", },
	{ .compatible = "mediatek,mt2701-disp-ovl",
	  .data = &mt2701_ovl_driver_data},
	{ .compatible = "mediatek,mt8173-disp-ovl",
	  .data = &mt8173_ovl_driver_data},
	{},
};
MODULE_DEVICE_TABLE(of, mtk_disp_ovl_driver_dt_match);
+31 −8
Original line number Diff line number Diff line
@@ -38,6 +38,11 @@
#define RDMA_FIFO_UNDERFLOW_EN				BIT(31)
#define RDMA_FIFO_PSEUDO_SIZE(bytes)			(((bytes) / 16) << 16)
#define RDMA_OUTPUT_VALID_FIFO_THRESHOLD(bytes)		((bytes) / 16)
#define RDMA_FIFO_SIZE(rdma)			((rdma)->data->fifo_size)

struct mtk_disp_rdma_data {
	unsigned int fifo_size;
};

/**
 * struct mtk_disp_rdma - DISP_RDMA driver structure
@@ -47,8 +52,14 @@
struct mtk_disp_rdma {
	struct mtk_ddp_comp		ddp_comp;
	struct drm_crtc			*crtc;
	const struct mtk_disp_rdma_data	*data;
};

static inline struct mtk_disp_rdma *comp_to_rdma(struct mtk_ddp_comp *comp)
{
	return container_of(comp, struct mtk_disp_rdma, ddp_comp);
}

static irqreturn_t mtk_disp_rdma_irq_handler(int irq, void *dev_id)
{
	struct mtk_disp_rdma *priv = dev_id;
@@ -77,20 +88,18 @@ static void rdma_update_bits(struct mtk_ddp_comp *comp, unsigned int reg,
static void mtk_rdma_enable_vblank(struct mtk_ddp_comp *comp,
				   struct drm_crtc *crtc)
{
	struct mtk_disp_rdma *priv = container_of(comp, struct mtk_disp_rdma,
						  ddp_comp);
	struct mtk_disp_rdma *rdma = comp_to_rdma(comp);

	priv->crtc = crtc;
	rdma->crtc = crtc;
	rdma_update_bits(comp, DISP_REG_RDMA_INT_ENABLE, RDMA_FRAME_END_INT,
			 RDMA_FRAME_END_INT);
}

static void mtk_rdma_disable_vblank(struct mtk_ddp_comp *comp)
{
	struct mtk_disp_rdma *priv = container_of(comp, struct mtk_disp_rdma,
						  ddp_comp);
	struct mtk_disp_rdma *rdma = comp_to_rdma(comp);

	priv->crtc = NULL;
	rdma->crtc = NULL;
	rdma_update_bits(comp, DISP_REG_RDMA_INT_ENABLE, RDMA_FRAME_END_INT, 0);
}

@@ -111,6 +120,7 @@ static void mtk_rdma_config(struct mtk_ddp_comp *comp, unsigned int width,
{
	unsigned int threshold;
	unsigned int reg;
	struct mtk_disp_rdma *rdma = comp_to_rdma(comp);

	rdma_update_bits(comp, DISP_REG_RDMA_SIZE_CON_0, 0xfff, width);
	rdma_update_bits(comp, DISP_REG_RDMA_SIZE_CON_1, 0xfffff, height);
@@ -123,7 +133,7 @@ static void mtk_rdma_config(struct mtk_ddp_comp *comp, unsigned int width,
	 */
	threshold = width * height * vrefresh * 4 * 7 / 1000000;
	reg = RDMA_FIFO_UNDERFLOW_EN |
	      RDMA_FIFO_PSEUDO_SIZE(SZ_8K) |
	      RDMA_FIFO_PSEUDO_SIZE(RDMA_FIFO_SIZE(rdma)) |
	      RDMA_OUTPUT_VALID_FIFO_THRESHOLD(threshold);
	writel(reg, comp->regs + DISP_REG_RDMA_FIFO_CON);
}
@@ -208,6 +218,8 @@ static int mtk_disp_rdma_probe(struct platform_device *pdev)
		return ret;
	}

	priv->data = of_device_get_match_data(dev);

	platform_set_drvdata(pdev, priv);

	ret = component_add(dev, &mtk_disp_rdma_component_ops);
@@ -224,8 +236,19 @@ static int mtk_disp_rdma_remove(struct platform_device *pdev)
	return 0;
}

static const struct mtk_disp_rdma_data mt2701_rdma_driver_data = {
	.fifo_size = SZ_4K,
};

static const struct mtk_disp_rdma_data mt8173_rdma_driver_data = {
	.fifo_size = SZ_8K,
};

static const struct of_device_id mtk_disp_rdma_driver_dt_match[] = {
	{ .compatible = "mediatek,mt8173-disp-rdma", },
	{ .compatible = "mediatek,mt2701-disp-rdma",
	  .data = &mt2701_rdma_driver_data},
	{ .compatible = "mediatek,mt8173-disp-rdma",
	  .data = &mt8173_rdma_driver_data},
	{},
};
MODULE_DEVICE_TABLE(of, mtk_disp_rdma_driver_dt_match);
+46 −29
Original line number Diff line number Diff line
@@ -327,6 +327,42 @@ static void mtk_crtc_ddp_hw_fini(struct mtk_drm_crtc *mtk_crtc)
	pm_runtime_put(drm->dev);
}

static void mtk_crtc_ddp_config(struct drm_crtc *crtc)
{
	struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
	struct mtk_crtc_state *state = to_mtk_crtc_state(mtk_crtc->base.state);
	struct mtk_ddp_comp *ovl = mtk_crtc->ddp_comp[0];
	unsigned int i;

	/*
	 * TODO: instead of updating the registers here, we should prepare
	 * working registers in atomic_commit and let the hardware command
	 * queue update module registers on vblank.
	 */
	if (state->pending_config) {
		mtk_ddp_comp_config(ovl, state->pending_width,
				    state->pending_height,
				    state->pending_vrefresh, 0);

		state->pending_config = false;
	}

	if (mtk_crtc->pending_planes) {
		for (i = 0; i < OVL_LAYER_NR; i++) {
			struct drm_plane *plane = &mtk_crtc->planes[i];
			struct mtk_plane_state *plane_state;

			plane_state = to_mtk_plane_state(plane->state);

			if (plane_state->pending.config) {
				mtk_ddp_comp_layer_config(ovl, i, plane_state);
				plane_state->pending.config = false;
			}
		}
		mtk_crtc->pending_planes = false;
	}
}

static void mtk_drm_crtc_enable(struct drm_crtc *crtc)
{
	struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
@@ -403,6 +439,7 @@ static void mtk_drm_crtc_atomic_flush(struct drm_crtc *crtc,
				      struct drm_crtc_state *old_crtc_state)
{
	struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
	struct mtk_drm_private *priv = crtc->dev->dev_private;
	unsigned int pending_planes = 0;
	int i;

@@ -424,6 +461,12 @@ static void mtk_drm_crtc_atomic_flush(struct drm_crtc *crtc,
	if (crtc->state->color_mgmt_changed)
		for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
			mtk_ddp_gamma_set(mtk_crtc->ddp_comp[i], crtc->state);

	if (priv->data->shadow_register) {
		mtk_disp_mutex_acquire(mtk_crtc->mutex);
		mtk_crtc_ddp_config(crtc);
		mtk_disp_mutex_release(mtk_crtc->mutex);
	}
}

static const struct drm_crtc_funcs mtk_crtc_funcs = {
@@ -471,36 +514,10 @@ static int mtk_drm_crtc_init(struct drm_device *drm,
void mtk_crtc_ddp_irq(struct drm_crtc *crtc, struct mtk_ddp_comp *ovl)
{
	struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
	struct mtk_crtc_state *state = to_mtk_crtc_state(mtk_crtc->base.state);
	unsigned int i;
	struct mtk_drm_private *priv = crtc->dev->dev_private;

	/*
	 * TODO: instead of updating the registers here, we should prepare
	 * working registers in atomic_commit and let the hardware command
	 * queue update module registers on vblank.
	 */
	if (state->pending_config) {
		mtk_ddp_comp_config(ovl, state->pending_width,
				    state->pending_height,
				    state->pending_vrefresh, 0);

		state->pending_config = false;
	}

	if (mtk_crtc->pending_planes) {
		for (i = 0; i < OVL_LAYER_NR; i++) {
			struct drm_plane *plane = &mtk_crtc->planes[i];
			struct mtk_plane_state *plane_state;

			plane_state = to_mtk_plane_state(plane->state);

			if (plane_state->pending.config) {
				mtk_ddp_comp_layer_config(ovl, i, plane_state);
				plane_state->pending.config = false;
			}
		}
		mtk_crtc->pending_planes = false;
	}
	if (!priv->data->shadow_register)
		mtk_crtc_ddp_config(crtc);

	mtk_drm_finish_page_flip(mtk_crtc);
}
Loading