Commit 55bf1496 authored by Daniel Vetter's avatar Daniel Vetter
Browse files

Merge tag 'mediatek-drm-next-6.4' of...

Merge tag 'mediatek-drm-next-6.4' of https://git.kernel.org/pub/scm/linux/kernel/git/chunkuang.hu/linux

 into drm-next

Mediatek DRM Next for Linux 6.4

1. Add support for 10-bit overlays
2. Add MediaTek SoC DRM (vdosys1) support for mt8195
3. Change mmsys compatible for mt8195 mediatek-drm
4. Only trigger DRM HPD events if bridge is attached
5. Change the aux retries times when receiving AUX_DEFER

Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
From: Chun-Kuang Hu <chunkuang.hu@kernel.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20230410233005.2572-1-chunkuang.hu@kernel.org
parents b8d85bb5 9243d70e
Loading
Loading
Loading
Loading
+1 −4
Original line number Diff line number Diff line
@@ -27,13 +27,10 @@ properties:
          - const: mediatek,mt8192-disp-ccorr
      - items:
          - enum:
              - mediatek,mt8186-disp-ccorr
              - mediatek,mt8188-disp-ccorr
              - mediatek,mt8195-disp-ccorr
          - const: mediatek,mt8192-disp-ccorr
      - items:
          - enum:
              - mediatek,mt8186-disp-ccorr
          - const: mediatek,mt8192-disp-ccorr

  reg:
    maxItems: 1
+182 −0
Original line number Diff line number Diff line
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/display/mediatek/mediatek,ethdr.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#

title: MediaTek Ethdr Device

maintainers:
  - Chun-Kuang Hu <chunkuang.hu@kernel.org>
  - Philipp Zabel <p.zabel@pengutronix.de>

description:
  ETHDR (ET High Dynamic Range) is a MediaTek internal HDR engine and is
  designed for HDR video and graphics conversion in the external display path.
  It handles multiple HDR input types and performs tone mapping, color
  space/color format conversion, and then combine different layers,
  output the required HDR or SDR signal to the subsequent display path.
  This engine is composed of two video frontends, two graphic frontends,
  one video backend and a mixer. ETHDR has two DMA function blocks, DS and ADL.
  These two function blocks read the pre-programmed registers from DRAM and
  set them to HW in the v-blanking period.

properties:
  compatible:
    const: mediatek,mt8195-disp-ethdr

  reg:
    maxItems: 7

  reg-names:
    items:
      - const: mixer
      - const: vdo_fe0
      - const: vdo_fe1
      - const: gfx_fe0
      - const: gfx_fe1
      - const: vdo_be
      - const: adl_ds

  interrupts:
    maxItems: 1

  iommus:
    minItems: 1
    maxItems: 2

  clocks:
    items:
      - description: mixer clock
      - description: video frontend 0 clock
      - description: video frontend 1 clock
      - description: graphic frontend 0 clock
      - description: graphic frontend 1 clock
      - description: video backend clock
      - description: autodownload and menuload clock
      - description: video frontend 0 async clock
      - description: video frontend 1 async clock
      - description: graphic frontend 0 async clock
      - description: graphic frontend 1 async clock
      - description: video backend async clock
      - description: ethdr top clock

  clock-names:
    items:
      - const: mixer
      - const: vdo_fe0
      - const: vdo_fe1
      - const: gfx_fe0
      - const: gfx_fe1
      - const: vdo_be
      - const: adl_ds
      - const: vdo_fe0_async
      - const: vdo_fe1_async
      - const: gfx_fe0_async
      - const: gfx_fe1_async
      - const: vdo_be_async
      - const: ethdr_top

  power-domains:
    maxItems: 1

  resets:
    items:
      - description: video frontend 0 async reset
      - description: video frontend 1 async reset
      - description: graphic frontend 0 async reset
      - description: graphic frontend 1 async reset
      - description: video backend async reset

  reset-names:
    items:
      - const: vdo_fe0_async
      - const: vdo_fe1_async
      - const: gfx_fe0_async
      - const: gfx_fe1_async
      - const: vdo_be_async

  mediatek,gce-client-reg:
    $ref: /schemas/types.yaml#/definitions/phandle-array
    minItems: 1
    maxItems: 7
    description: The register of display function block to be set by gce.
      There are 4 arguments in this property, gce node, subsys id, offset and
      register size. The subsys id is defined in the gce header of each chips
      include/dt-bindings/gce/<chip>-gce.h, mapping to the register of display
      function block.

required:
  - compatible
  - reg
  - clocks
  - clock-names
  - interrupts
  - power-domains
  - resets
  - mediatek,gce-client-reg

additionalProperties: false

examples:
  - |
    #include <dt-bindings/interrupt-controller/arm-gic.h>
    #include <dt-bindings/clock/mt8195-clk.h>
    #include <dt-bindings/gce/mt8195-gce.h>
    #include <dt-bindings/memory/mt8195-memory-port.h>
    #include <dt-bindings/power/mt8195-power.h>
    #include <dt-bindings/reset/mt8195-resets.h>

    soc {
        #address-cells = <2>;
        #size-cells = <2>;

        hdr-engine@1c114000 {
                compatible = "mediatek,mt8195-disp-ethdr";
                reg = <0 0x1c114000 0 0x1000>,
                      <0 0x1c115000 0 0x1000>,
                      <0 0x1c117000 0 0x1000>,
                      <0 0x1c119000 0 0x1000>,
                      <0 0x1c11a000 0 0x1000>,
                      <0 0x1c11b000 0 0x1000>,
                      <0 0x1c11c000 0 0x1000>;
                reg-names = "mixer", "vdo_fe0", "vdo_fe1", "gfx_fe0", "gfx_fe1",
                            "vdo_be", "adl_ds";
                mediatek,gce-client-reg = <&gce0 SUBSYS_1c11XXXX 0x4000 0x1000>,
                                          <&gce0 SUBSYS_1c11XXXX 0x5000 0x1000>,
                                          <&gce0 SUBSYS_1c11XXXX 0x7000 0x1000>,
                                          <&gce0 SUBSYS_1c11XXXX 0x9000 0x1000>,
                                          <&gce0 SUBSYS_1c11XXXX 0xa000 0x1000>,
                                          <&gce0 SUBSYS_1c11XXXX 0xb000 0x1000>,
                                          <&gce0 SUBSYS_1c11XXXX 0xc000 0x1000>;
                clocks = <&vdosys1 CLK_VDO1_DISP_MIXER>,
                         <&vdosys1 CLK_VDO1_HDR_VDO_FE0>,
                         <&vdosys1 CLK_VDO1_HDR_VDO_FE1>,
                         <&vdosys1 CLK_VDO1_HDR_GFX_FE0>,
                         <&vdosys1 CLK_VDO1_HDR_GFX_FE1>,
                         <&vdosys1 CLK_VDO1_HDR_VDO_BE>,
                         <&vdosys1 CLK_VDO1_26M_SLOW>,
                         <&vdosys1 CLK_VDO1_HDR_VDO_FE0_DL_ASYNC>,
                         <&vdosys1 CLK_VDO1_HDR_VDO_FE1_DL_ASYNC>,
                         <&vdosys1 CLK_VDO1_HDR_GFX_FE0_DL_ASYNC>,
                         <&vdosys1 CLK_VDO1_HDR_GFX_FE1_DL_ASYNC>,
                         <&vdosys1 CLK_VDO1_HDR_VDO_BE_DL_ASYNC>,
                         <&topckgen CLK_TOP_ETHDR>;
                clock-names = "mixer", "vdo_fe0", "vdo_fe1", "gfx_fe0", "gfx_fe1",
                              "vdo_be", "adl_ds", "vdo_fe0_async", "vdo_fe1_async",
                              "gfx_fe0_async", "gfx_fe1_async","vdo_be_async",
                              "ethdr_top";
                power-domains = <&spm MT8195_POWER_DOMAIN_VDOSYS1>;
                iommus = <&iommu_vpp M4U_PORT_L3_HDR_DS>,
                         <&iommu_vpp M4U_PORT_L3_HDR_ADL>;
                interrupts = <GIC_SPI 517 IRQ_TYPE_LEVEL_HIGH 0>; /* disp mixer */
                resets = <&vdosys1 MT8195_VDOSYS1_SW1_RST_B_HDR_VDO_FE0_DL_ASYNC>,
                         <&vdosys1 MT8195_VDOSYS1_SW1_RST_B_HDR_VDO_FE1_DL_ASYNC>,
                         <&vdosys1 MT8195_VDOSYS1_SW1_RST_B_HDR_GFX_FE0_DL_ASYNC>,
                         <&vdosys1 MT8195_VDOSYS1_SW1_RST_B_HDR_GFX_FE1_DL_ASYNC>,
                         <&vdosys1 MT8195_VDOSYS1_SW1_RST_B_HDR_VDO_BE_DL_ASYNC>;
                reset-names = "vdo_fe0_async", "vdo_fe1_async", "gfx_fe0_async",
                              "gfx_fe1_async", "vdo_be_async";
        };
    };
...
+2 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@ mediatek-drm-y := mtk_disp_aal.o \
		  mtk_disp_gamma.o \
		  mtk_disp_merge.o \
		  mtk_disp_ovl.o \
		  mtk_disp_ovl_adaptor.o \
		  mtk_disp_rdma.o \
		  mtk_drm_crtc.o \
		  mtk_drm_ddp_comp.o \
@@ -14,6 +15,7 @@ mediatek-drm-y := mtk_disp_aal.o \
		  mtk_drm_plane.o \
		  mtk_dsi.o \
		  mtk_dpi.o \
		  mtk_ethdr.o \
		  mtk_mdp_rdma.o

obj-$(CONFIG_DRM_MEDIATEK) += mediatek-drm.o
+35 −0
Original line number Diff line number Diff line
@@ -7,6 +7,8 @@
#define _MTK_DISP_DRV_H_

#include <linux/soc/mediatek/mtk-cmdq.h>
#include <linux/soc/mediatek/mtk-mmsys.h>
#include <linux/soc/mediatek/mtk-mutex.h>
#include "mtk_drm_plane.h"
#include "mtk_mdp_rdma.h"

@@ -96,6 +98,34 @@ void mtk_ovl_register_vblank_cb(struct device *dev,
void mtk_ovl_unregister_vblank_cb(struct device *dev);
void mtk_ovl_enable_vblank(struct device *dev);
void mtk_ovl_disable_vblank(struct device *dev);
const u32 *mtk_ovl_get_formats(struct device *dev);
size_t mtk_ovl_get_num_formats(struct device *dev);

void mtk_ovl_adaptor_add_comp(struct device *dev, struct mtk_mutex *mutex);
void mtk_ovl_adaptor_remove_comp(struct device *dev, struct mtk_mutex *mutex);
void mtk_ovl_adaptor_connect(struct device *dev, struct device *mmsys_dev,
			     unsigned int next);
void mtk_ovl_adaptor_disconnect(struct device *dev, struct device *mmsys_dev,
				unsigned int next);
int mtk_ovl_adaptor_clk_enable(struct device *dev);
void mtk_ovl_adaptor_clk_disable(struct device *dev);
void mtk_ovl_adaptor_config(struct device *dev, unsigned int w,
			    unsigned int h, unsigned int vrefresh,
			    unsigned int bpc, struct cmdq_pkt *cmdq_pkt);
void mtk_ovl_adaptor_layer_config(struct device *dev, unsigned int idx,
				  struct mtk_plane_state *state,
				  struct cmdq_pkt *cmdq_pkt);
void mtk_ovl_adaptor_register_vblank_cb(struct device *dev, void (*vblank_cb)(void *),
					void *vblank_cb_data);
void mtk_ovl_adaptor_unregister_vblank_cb(struct device *dev);
void mtk_ovl_adaptor_enable_vblank(struct device *dev);
void mtk_ovl_adaptor_disable_vblank(struct device *dev);
void mtk_ovl_adaptor_start(struct device *dev);
void mtk_ovl_adaptor_stop(struct device *dev);
unsigned int mtk_ovl_adaptor_layer_nr(struct device *dev);
struct device *mtk_ovl_adaptor_dma_dev_get(struct device *dev);
const u32 *mtk_ovl_adaptor_get_formats(struct device *dev);
size_t mtk_ovl_adaptor_get_num_formats(struct device *dev);

void mtk_rdma_bypass_shadow(struct device *dev);
int mtk_rdma_clk_enable(struct device *dev);
@@ -115,6 +145,8 @@ void mtk_rdma_register_vblank_cb(struct device *dev,
void mtk_rdma_unregister_vblank_cb(struct device *dev);
void mtk_rdma_enable_vblank(struct device *dev);
void mtk_rdma_disable_vblank(struct device *dev);
const u32 *mtk_rdma_get_formats(struct device *dev);
size_t mtk_rdma_get_num_formats(struct device *dev);

int mtk_mdp_rdma_clk_enable(struct device *dev);
void mtk_mdp_rdma_clk_disable(struct device *dev);
@@ -122,4 +154,7 @@ void mtk_mdp_rdma_start(struct device *dev, struct cmdq_pkt *cmdq_pkt);
void mtk_mdp_rdma_stop(struct device *dev, struct cmdq_pkt *cmdq_pkt);
void mtk_mdp_rdma_config(struct device *dev, struct mtk_mdp_rdma_cfg *cfg,
			 struct cmdq_pkt *cmdq_pkt);
const u32 *mtk_mdp_rdma_get_formats(struct device *dev);
size_t mtk_mdp_rdma_get_num_formats(struct device *dev);

#endif
+94 −0
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@
#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_MT2701		0x0040
#define DISP_REG_OVL_CLRFMT_EXT			0x02D0
#define DISP_REG_OVL_ADDR_MT8173		0x0f40
#define DISP_REG_OVL_ADDR(ovl, n)		((ovl)->data->addr + 0x20 * (n))
#define DISP_REG_OVL_HDR_ADDR(ovl, n)		((ovl)->data->addr + 0x20 * (n) + 0x04)
@@ -62,11 +63,45 @@
					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_CLRFMT_BIT_DEPTH_MASK(ovl)	(0xFF << 4 * (ovl))
#define OVL_CON_CLRFMT_BIT_DEPTH(depth, ovl)	(depth << 4 * (ovl))
#define OVL_CON_CLRFMT_8_BIT			0x00
#define OVL_CON_CLRFMT_10_BIT			0x01
#define	OVL_CON_AEN		BIT(8)
#define	OVL_CON_ALPHA		0xff
#define	OVL_CON_VIRT_FLIP	BIT(9)
#define	OVL_CON_HORZ_FLIP	BIT(10)

static const u32 mt8173_formats[] = {
	DRM_FORMAT_XRGB8888,
	DRM_FORMAT_ARGB8888,
	DRM_FORMAT_BGRX8888,
	DRM_FORMAT_BGRA8888,
	DRM_FORMAT_ABGR8888,
	DRM_FORMAT_XBGR8888,
	DRM_FORMAT_RGB888,
	DRM_FORMAT_BGR888,
	DRM_FORMAT_RGB565,
	DRM_FORMAT_UYVY,
	DRM_FORMAT_YUYV,
};

static const u32 mt8195_formats[] = {
	DRM_FORMAT_XRGB8888,
	DRM_FORMAT_ARGB8888,
	DRM_FORMAT_ARGB2101010,
	DRM_FORMAT_BGRX8888,
	DRM_FORMAT_BGRA8888,
	DRM_FORMAT_BGRA1010102,
	DRM_FORMAT_ABGR8888,
	DRM_FORMAT_XBGR8888,
	DRM_FORMAT_RGB888,
	DRM_FORMAT_BGR888,
	DRM_FORMAT_RGB565,
	DRM_FORMAT_UYVY,
	DRM_FORMAT_YUYV,
};

struct mtk_disp_ovl_data {
	unsigned int addr;
	unsigned int gmc_bits;
@@ -74,6 +109,9 @@ struct mtk_disp_ovl_data {
	bool fmt_rgb565_is_0;
	bool smi_id_en;
	bool supports_afbc;
	const u32 *formats;
	size_t num_formats;
	bool supports_clrfmt_ext;
};

/*
@@ -139,6 +177,20 @@ void mtk_ovl_disable_vblank(struct device *dev)
	writel_relaxed(0x0, ovl->regs + DISP_REG_OVL_INTEN);
}

const u32 *mtk_ovl_get_formats(struct device *dev)
{
	struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);

	return ovl->data->formats;
}

size_t mtk_ovl_get_num_formats(struct device *dev)
{
	struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);

	return ovl->data->num_formats;
}

int mtk_ovl_clk_enable(struct device *dev)
{
	struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);
@@ -189,6 +241,30 @@ static void mtk_ovl_set_afbc(struct mtk_disp_ovl *ovl, struct cmdq_pkt *cmdq_pkt
			   DISP_REG_OVL_DATAPATH_CON, OVL_LAYER_AFBC_EN(idx));
}

static void mtk_ovl_set_bit_depth(struct device *dev, int idx, u32 format,
				  struct cmdq_pkt *cmdq_pkt)
{
	struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);
	unsigned int reg;
	unsigned int bit_depth = OVL_CON_CLRFMT_8_BIT;

	if (!ovl->data->supports_clrfmt_ext)
		return;

	reg = readl(ovl->regs + DISP_REG_OVL_CLRFMT_EXT);
	reg &= ~OVL_CON_CLRFMT_BIT_DEPTH_MASK(idx);

	if (format == DRM_FORMAT_RGBA1010102 ||
	    format == DRM_FORMAT_BGRA1010102 ||
	    format == DRM_FORMAT_ARGB2101010)
		bit_depth = OVL_CON_CLRFMT_10_BIT;

	reg |= OVL_CON_CLRFMT_BIT_DEPTH(bit_depth, idx);

	mtk_ddp_write(cmdq_pkt, reg, &ovl->cmdq_reg,
		      ovl->regs, DISP_REG_OVL_CLRFMT_EXT);
}

void mtk_ovl_config(struct device *dev, unsigned int w,
		    unsigned int h, unsigned int vrefresh,
		    unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
@@ -303,9 +379,11 @@ static unsigned int ovl_fmt_convert(struct mtk_disp_ovl *ovl, unsigned int fmt)
		return OVL_CON_CLRFMT_ARGB8888;
	case DRM_FORMAT_BGRX8888:
	case DRM_FORMAT_BGRA8888:
	case DRM_FORMAT_BGRA1010102:
		return OVL_CON_CLRFMT_ARGB8888 | OVL_CON_BYTE_SWAP;
	case DRM_FORMAT_XRGB8888:
	case DRM_FORMAT_ARGB8888:
	case DRM_FORMAT_ARGB2101010:
		return OVL_CON_CLRFMT_RGBA8888;
	case DRM_FORMAT_XBGR8888:
	case DRM_FORMAT_ABGR8888:
@@ -389,6 +467,7 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
				      &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_PITCH_MSB(idx));
	}

	mtk_ovl_set_bit_depth(dev, idx, fmt, cmdq_pkt);
	mtk_ovl_layer_on(dev, idx, cmdq_pkt);
}

@@ -496,6 +575,8 @@ static const struct mtk_disp_ovl_data mt2701_ovl_driver_data = {
	.gmc_bits = 8,
	.layer_nr = 4,
	.fmt_rgb565_is_0 = false,
	.formats = mt8173_formats,
	.num_formats = ARRAY_SIZE(mt8173_formats),
};

static const struct mtk_disp_ovl_data mt8173_ovl_driver_data = {
@@ -503,6 +584,8 @@ static const struct mtk_disp_ovl_data mt8173_ovl_driver_data = {
	.gmc_bits = 8,
	.layer_nr = 4,
	.fmt_rgb565_is_0 = true,
	.formats = mt8173_formats,
	.num_formats = ARRAY_SIZE(mt8173_formats),
};

static const struct mtk_disp_ovl_data mt8183_ovl_driver_data = {
@@ -510,6 +593,8 @@ static const struct mtk_disp_ovl_data mt8183_ovl_driver_data = {
	.gmc_bits = 10,
	.layer_nr = 4,
	.fmt_rgb565_is_0 = true,
	.formats = mt8173_formats,
	.num_formats = ARRAY_SIZE(mt8173_formats),
};

static const struct mtk_disp_ovl_data mt8183_ovl_2l_driver_data = {
@@ -517,6 +602,8 @@ static const struct mtk_disp_ovl_data mt8183_ovl_2l_driver_data = {
	.gmc_bits = 10,
	.layer_nr = 2,
	.fmt_rgb565_is_0 = true,
	.formats = mt8173_formats,
	.num_formats = ARRAY_SIZE(mt8173_formats),
};

static const struct mtk_disp_ovl_data mt8192_ovl_driver_data = {
@@ -525,6 +612,8 @@ static const struct mtk_disp_ovl_data mt8192_ovl_driver_data = {
	.layer_nr = 4,
	.fmt_rgb565_is_0 = true,
	.smi_id_en = true,
	.formats = mt8173_formats,
	.num_formats = ARRAY_SIZE(mt8173_formats),
};

static const struct mtk_disp_ovl_data mt8192_ovl_2l_driver_data = {
@@ -533,6 +622,8 @@ static const struct mtk_disp_ovl_data mt8192_ovl_2l_driver_data = {
	.layer_nr = 2,
	.fmt_rgb565_is_0 = true,
	.smi_id_en = true,
	.formats = mt8173_formats,
	.num_formats = ARRAY_SIZE(mt8173_formats),
};

static const struct mtk_disp_ovl_data mt8195_ovl_driver_data = {
@@ -542,6 +633,9 @@ static const struct mtk_disp_ovl_data mt8195_ovl_driver_data = {
	.fmt_rgb565_is_0 = true,
	.smi_id_en = true,
	.supports_afbc = true,
	.formats = mt8195_formats,
	.num_formats = ARRAY_SIZE(mt8195_formats),
	.supports_clrfmt_ext = true,
};

static const struct of_device_id mtk_disp_ovl_driver_dt_match[] = {
Loading