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

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
...@@ -27,13 +27,10 @@ properties: ...@@ -27,13 +27,10 @@ properties:
- const: mediatek,mt8192-disp-ccorr - const: mediatek,mt8192-disp-ccorr
- items: - items:
- enum: - enum:
- mediatek,mt8186-disp-ccorr
- mediatek,mt8188-disp-ccorr - mediatek,mt8188-disp-ccorr
- mediatek,mt8195-disp-ccorr - mediatek,mt8195-disp-ccorr
- const: mediatek,mt8192-disp-ccorr - const: mediatek,mt8192-disp-ccorr
- items:
- enum:
- mediatek,mt8186-disp-ccorr
- const: mediatek,mt8192-disp-ccorr
reg: reg:
maxItems: 1 maxItems: 1
......
# 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";
};
};
...
...@@ -6,6 +6,7 @@ mediatek-drm-y := mtk_disp_aal.o \ ...@@ -6,6 +6,7 @@ mediatek-drm-y := mtk_disp_aal.o \
mtk_disp_gamma.o \ mtk_disp_gamma.o \
mtk_disp_merge.o \ mtk_disp_merge.o \
mtk_disp_ovl.o \ mtk_disp_ovl.o \
mtk_disp_ovl_adaptor.o \
mtk_disp_rdma.o \ mtk_disp_rdma.o \
mtk_drm_crtc.o \ mtk_drm_crtc.o \
mtk_drm_ddp_comp.o \ mtk_drm_ddp_comp.o \
...@@ -14,6 +15,7 @@ mediatek-drm-y := mtk_disp_aal.o \ ...@@ -14,6 +15,7 @@ mediatek-drm-y := mtk_disp_aal.o \
mtk_drm_plane.o \ mtk_drm_plane.o \
mtk_dsi.o \ mtk_dsi.o \
mtk_dpi.o \ mtk_dpi.o \
mtk_ethdr.o \
mtk_mdp_rdma.o mtk_mdp_rdma.o
obj-$(CONFIG_DRM_MEDIATEK) += mediatek-drm.o obj-$(CONFIG_DRM_MEDIATEK) += mediatek-drm.o
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
#define _MTK_DISP_DRV_H_ #define _MTK_DISP_DRV_H_
#include <linux/soc/mediatek/mtk-cmdq.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_drm_plane.h"
#include "mtk_mdp_rdma.h" #include "mtk_mdp_rdma.h"
...@@ -96,6 +98,34 @@ void mtk_ovl_register_vblank_cb(struct device *dev, ...@@ -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_unregister_vblank_cb(struct device *dev);
void mtk_ovl_enable_vblank(struct device *dev); void mtk_ovl_enable_vblank(struct device *dev);
void mtk_ovl_disable_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); void mtk_rdma_bypass_shadow(struct device *dev);
int mtk_rdma_clk_enable(struct device *dev); int mtk_rdma_clk_enable(struct device *dev);
...@@ -115,6 +145,8 @@ void mtk_rdma_register_vblank_cb(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_unregister_vblank_cb(struct device *dev);
void mtk_rdma_enable_vblank(struct device *dev); void mtk_rdma_enable_vblank(struct device *dev);
void mtk_rdma_disable_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); int mtk_mdp_rdma_clk_enable(struct device *dev);
void mtk_mdp_rdma_clk_disable(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); ...@@ -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_stop(struct device *dev, struct cmdq_pkt *cmdq_pkt);
void mtk_mdp_rdma_config(struct device *dev, struct mtk_mdp_rdma_cfg *cfg, void mtk_mdp_rdma_config(struct device *dev, struct mtk_mdp_rdma_cfg *cfg,
struct cmdq_pkt *cmdq_pkt); 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 #endif
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#define DISP_REG_OVL_RDMA_CTRL(n) (0x00c0 + 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_RDMA_GMC(n) (0x00c8 + 0x20 * (n))
#define DISP_REG_OVL_ADDR_MT2701 0x0040 #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_MT8173 0x0f40
#define DISP_REG_OVL_ADDR(ovl, n) ((ovl)->data->addr + 0x20 * (n)) #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) #define DISP_REG_OVL_HDR_ADDR(ovl, n) ((ovl)->data->addr + 0x20 * (n) + 0x04)
...@@ -62,11 +63,45 @@ ...@@ -62,11 +63,45 @@
0 : OVL_CON_CLRFMT_RGB) 0 : OVL_CON_CLRFMT_RGB)
#define OVL_CON_CLRFMT_RGB888(ovl) ((ovl)->data->fmt_rgb565_is_0 ? \ #define OVL_CON_CLRFMT_RGB888(ovl) ((ovl)->data->fmt_rgb565_is_0 ? \
OVL_CON_CLRFMT_RGB : 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_AEN BIT(8)
#define OVL_CON_ALPHA 0xff #define OVL_CON_ALPHA 0xff
#define OVL_CON_VIRT_FLIP BIT(9) #define OVL_CON_VIRT_FLIP BIT(9)
#define OVL_CON_HORZ_FLIP BIT(10) #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 { struct mtk_disp_ovl_data {
unsigned int addr; unsigned int addr;
unsigned int gmc_bits; unsigned int gmc_bits;
...@@ -74,6 +109,9 @@ struct mtk_disp_ovl_data { ...@@ -74,6 +109,9 @@ struct mtk_disp_ovl_data {
bool fmt_rgb565_is_0; bool fmt_rgb565_is_0;
bool smi_id_en; bool smi_id_en;
bool supports_afbc; 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) ...@@ -139,6 +177,20 @@ void mtk_ovl_disable_vblank(struct device *dev)
writel_relaxed(0x0, ovl->regs + DISP_REG_OVL_INTEN); 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) int mtk_ovl_clk_enable(struct device *dev)
{ {
struct mtk_disp_ovl *ovl = dev_get_drvdata(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 ...@@ -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)); 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, void mtk_ovl_config(struct device *dev, unsigned int w,
unsigned int h, unsigned int vrefresh, unsigned int h, unsigned int vrefresh,
unsigned int bpc, struct cmdq_pkt *cmdq_pkt) 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) ...@@ -303,9 +379,11 @@ static unsigned int ovl_fmt_convert(struct mtk_disp_ovl *ovl, unsigned int fmt)
return OVL_CON_CLRFMT_ARGB8888; return OVL_CON_CLRFMT_ARGB8888;
case DRM_FORMAT_BGRX8888: case DRM_FORMAT_BGRX8888:
case DRM_FORMAT_BGRA8888: case DRM_FORMAT_BGRA8888:
case DRM_FORMAT_BGRA1010102:
return OVL_CON_CLRFMT_ARGB8888 | OVL_CON_BYTE_SWAP; return OVL_CON_CLRFMT_ARGB8888 | OVL_CON_BYTE_SWAP;
case DRM_FORMAT_XRGB8888: case DRM_FORMAT_XRGB8888:
case DRM_FORMAT_ARGB8888: case DRM_FORMAT_ARGB8888:
case DRM_FORMAT_ARGB2101010:
return OVL_CON_CLRFMT_RGBA8888; return OVL_CON_CLRFMT_RGBA8888;
case DRM_FORMAT_XBGR8888: case DRM_FORMAT_XBGR8888:
case DRM_FORMAT_ABGR8888: case DRM_FORMAT_ABGR8888:
...@@ -389,6 +467,7 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx, ...@@ -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)); &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); mtk_ovl_layer_on(dev, idx, cmdq_pkt);
} }
...@@ -496,6 +575,8 @@ static const struct mtk_disp_ovl_data mt2701_ovl_driver_data = { ...@@ -496,6 +575,8 @@ static const struct mtk_disp_ovl_data mt2701_ovl_driver_data = {
.gmc_bits = 8, .gmc_bits = 8,
.layer_nr = 4, .layer_nr = 4,
.fmt_rgb565_is_0 = false, .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 = { 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 = { ...@@ -503,6 +584,8 @@ static const struct mtk_disp_ovl_data mt8173_ovl_driver_data = {
.gmc_bits = 8, .gmc_bits = 8,
.layer_nr = 4, .layer_nr = 4,
.fmt_rgb565_is_0 = true, .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 = { 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 = { ...@@ -510,6 +593,8 @@ static const struct mtk_disp_ovl_data mt8183_ovl_driver_data = {
.gmc_bits = 10, .gmc_bits = 10,
.layer_nr = 4, .layer_nr = 4,
.fmt_rgb565_is_0 = true, .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 = { 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 = { ...@@ -517,6 +602,8 @@ static const struct mtk_disp_ovl_data mt8183_ovl_2l_driver_data = {
.gmc_bits = 10, .gmc_bits = 10,
.layer_nr = 2, .layer_nr = 2,
.fmt_rgb565_is_0 = true, .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 = { 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 = { ...@@ -525,6 +612,8 @@ static const struct mtk_disp_ovl_data mt8192_ovl_driver_data = {
.layer_nr = 4, .layer_nr = 4,
.fmt_rgb565_is_0 = true, .fmt_rgb565_is_0 = true,
.smi_id_en = 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 = { 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 = { ...@@ -533,6 +622,8 @@ static const struct mtk_disp_ovl_data mt8192_ovl_2l_driver_data = {
.layer_nr = 2, .layer_nr = 2,
.fmt_rgb565_is_0 = true, .fmt_rgb565_is_0 = true,
.smi_id_en = 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 = { 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 = { ...@@ -542,6 +633,9 @@ static const struct mtk_disp_ovl_data mt8195_ovl_driver_data = {
.fmt_rgb565_is_0 = true, .fmt_rgb565_is_0 = true,
.smi_id_en = true, .smi_id_en = true,
.supports_afbc = 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[] = { static const struct of_device_id mtk_disp_ovl_driver_dt_match[] = {
......
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2021 MediaTek Inc.
*/
#include <drm/drm_fourcc.h>
#include <drm/drm_of.h>
#include <linux/clk.h>
#include <linux/component.h>
#include <linux/of_device.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/reset.h>
#include <linux/soc/mediatek/mtk-cmdq.h>
#include <linux/soc/mediatek/mtk-mmsys.h>
#include <linux/soc/mediatek/mtk-mutex.h>
#include "mtk_disp_drv.h"
#include "mtk_drm_crtc.h"
#include "mtk_drm_ddp_comp.h"
#include "mtk_drm_drv.h"
#include "mtk_ethdr.h"
#define MTK_OVL_ADAPTOR_RDMA_MAX_WIDTH 1920
#define MTK_OVL_ADAPTOR_LAYER_NUM 4
enum mtk_ovl_adaptor_comp_type {
OVL_ADAPTOR_TYPE_RDMA = 0,
OVL_ADAPTOR_TYPE_MERGE,
OVL_ADAPTOR_TYPE_ETHDR,
OVL_ADAPTOR_TYPE_NUM,
};
enum mtk_ovl_adaptor_comp_id {
OVL_ADAPTOR_MDP_RDMA0,
OVL_ADAPTOR_MDP_RDMA1,
OVL_ADAPTOR_MDP_RDMA2,
OVL_ADAPTOR_MDP_RDMA3,
OVL_ADAPTOR_MDP_RDMA4,
OVL_ADAPTOR_MDP_RDMA5,
OVL_ADAPTOR_MDP_RDMA6,
OVL_ADAPTOR_MDP_RDMA7,
OVL_ADAPTOR_MERGE0,
OVL_ADAPTOR_MERGE1,
OVL_ADAPTOR_MERGE2,
OVL_ADAPTOR_MERGE3,
OVL_ADAPTOR_ETHDR0,
OVL_ADAPTOR_ID_MAX
};
struct ovl_adaptor_comp_match {
enum mtk_ovl_adaptor_comp_type type;
int alias_id;
};
struct mtk_disp_ovl_adaptor {
struct device *ovl_adaptor_comp[OVL_ADAPTOR_ID_MAX];
struct device *mmsys_dev;
bool children_bound;
};
static const char * const private_comp_stem[OVL_ADAPTOR_TYPE_NUM] = {
[OVL_ADAPTOR_TYPE_RDMA] = "vdo1-rdma",
[OVL_ADAPTOR_TYPE_MERGE] = "merge",
[OVL_ADAPTOR_TYPE_ETHDR] = "ethdr",
};
static const struct ovl_adaptor_comp_match comp_matches[OVL_ADAPTOR_ID_MAX] = {
[OVL_ADAPTOR_MDP_RDMA0] = { OVL_ADAPTOR_TYPE_RDMA, 0 },
[OVL_ADAPTOR_MDP_RDMA1] = { OVL_ADAPTOR_TYPE_RDMA, 1 },
[OVL_ADAPTOR_MDP_RDMA2] = { OVL_ADAPTOR_TYPE_RDMA, 2 },
[OVL_ADAPTOR_MDP_RDMA3] = { OVL_ADAPTOR_TYPE_RDMA, 3 },
[OVL_ADAPTOR_MDP_RDMA4] = { OVL_ADAPTOR_TYPE_RDMA, 4 },
[OVL_ADAPTOR_MDP_RDMA5] = { OVL_ADAPTOR_TYPE_RDMA, 5 },
[OVL_ADAPTOR_MDP_RDMA6] = { OVL_ADAPTOR_TYPE_RDMA, 6 },
[OVL_ADAPTOR_MDP_RDMA7] = { OVL_ADAPTOR_TYPE_RDMA, 7 },
[OVL_ADAPTOR_MERGE0] = { OVL_ADAPTOR_TYPE_MERGE, 1 },
[OVL_ADAPTOR_MERGE1] = { OVL_ADAPTOR_TYPE_MERGE, 2 },
[OVL_ADAPTOR_MERGE2] = { OVL_ADAPTOR_TYPE_MERGE, 3 },
[OVL_ADAPTOR_MERGE3] = { OVL_ADAPTOR_TYPE_MERGE, 4 },
[OVL_ADAPTOR_ETHDR0] = { OVL_ADAPTOR_TYPE_ETHDR, 0 },
};
void mtk_ovl_adaptor_layer_config(struct device *dev, unsigned int idx,
struct mtk_plane_state *state,
struct cmdq_pkt *cmdq_pkt)
{
struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev);
struct mtk_plane_pending_state *pending = &state->pending;
struct mtk_mdp_rdma_cfg rdma_config = {0};
struct device *rdma_l;
struct device *rdma_r;
struct device *merge;
struct device *ethdr;
const struct drm_format_info *fmt_info = drm_format_info(pending->format);
bool use_dual_pipe = false;
unsigned int align_width;
unsigned int l_w = 0;
unsigned int r_w = 0;
dev_dbg(dev, "%s+ idx:%d, enable:%d, fmt:0x%x\n", __func__, idx,
pending->enable, pending->format);
dev_dbg(dev, "addr 0x%pad, fb w:%d, {%d,%d,%d,%d}\n",
&pending->addr, (pending->pitch / fmt_info->cpp[0]),
pending->x, pending->y, pending->width, pending->height);
rdma_l = ovl_adaptor->ovl_adaptor_comp[OVL_ADAPTOR_MDP_RDMA0 + 2 * idx];
rdma_r = ovl_adaptor->ovl_adaptor_comp[OVL_ADAPTOR_MDP_RDMA0 + 2 * idx + 1];
merge = ovl_adaptor->ovl_adaptor_comp[OVL_ADAPTOR_MERGE0 + idx];
ethdr = ovl_adaptor->ovl_adaptor_comp[OVL_ADAPTOR_ETHDR0];
if (!pending->enable) {
mtk_merge_stop_cmdq(merge, cmdq_pkt);
mtk_mdp_rdma_stop(rdma_l, cmdq_pkt);
mtk_mdp_rdma_stop(rdma_r, cmdq_pkt);
mtk_ethdr_layer_config(ethdr, idx, state, cmdq_pkt);
return;
}
/* ETHDR is in 1T2P domain, width needs to be 2 pixels align */
align_width = ALIGN_DOWN(pending->width, 2);
if (align_width > MTK_OVL_ADAPTOR_RDMA_MAX_WIDTH)
use_dual_pipe = true;
if (use_dual_pipe) {
l_w = (align_width / 2) + ((pending->width / 2) % 2);
r_w = align_width - l_w;
} else {
l_w = align_width;
}
mtk_merge_advance_config(merge, l_w, r_w, pending->height, 0, 0, cmdq_pkt);
mtk_mmsys_merge_async_config(ovl_adaptor->mmsys_dev, idx, align_width / 2,
pending->height, cmdq_pkt);
rdma_config.width = l_w;
rdma_config.height = pending->height;
rdma_config.addr0 = pending->addr;
rdma_config.pitch = pending->pitch;
rdma_config.fmt = pending->format;
rdma_config.color_encoding = pending->color_encoding;
mtk_mdp_rdma_config(rdma_l, &rdma_config, cmdq_pkt);
if (use_dual_pipe) {
rdma_config.x_left = l_w;
rdma_config.width = r_w;
mtk_mdp_rdma_config(rdma_r, &rdma_config, cmdq_pkt);
}
mtk_merge_start_cmdq(merge, cmdq_pkt);
mtk_mdp_rdma_start(rdma_l, cmdq_pkt);
if (use_dual_pipe)
mtk_mdp_rdma_start(rdma_r, cmdq_pkt);
else
mtk_mdp_rdma_stop(rdma_r, cmdq_pkt);
mtk_ethdr_layer_config(ethdr, idx, state, cmdq_pkt);
}
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)
{
struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev);
mtk_ethdr_config(ovl_adaptor->ovl_adaptor_comp[OVL_ADAPTOR_ETHDR0], w, h,
vrefresh, bpc, cmdq_pkt);
}
void mtk_ovl_adaptor_start(struct device *dev)
{
struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev);
mtk_ethdr_start(ovl_adaptor->ovl_adaptor_comp[OVL_ADAPTOR_ETHDR0]);
}
void mtk_ovl_adaptor_stop(struct device *dev)
{
struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev);
mtk_ethdr_stop(ovl_adaptor->ovl_adaptor_comp[OVL_ADAPTOR_ETHDR0]);
}
int mtk_ovl_adaptor_clk_enable(struct device *dev)
{
struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev);
struct device *comp;
int ret;
int i;
for (i = 0; i < OVL_ADAPTOR_MERGE0; i++) {
comp = ovl_adaptor->ovl_adaptor_comp[i];
ret = pm_runtime_get_sync(comp);
if (ret < 0) {
dev_err(dev, "Failed to enable power domain %d, err %d\n", i, ret);
goto pwr_err;
}
}
for (i = 0; i < OVL_ADAPTOR_ID_MAX; i++) {
comp = ovl_adaptor->ovl_adaptor_comp[i];
if (i < OVL_ADAPTOR_MERGE0)
ret = mtk_mdp_rdma_clk_enable(comp);
else if (i < OVL_ADAPTOR_ETHDR0)
ret = mtk_merge_clk_enable(comp);
else
ret = mtk_ethdr_clk_enable(comp);
if (ret) {
dev_err(dev, "Failed to enable clock %d, err %d\n", i, ret);
goto clk_err;
}
}
return ret;
clk_err:
while (--i >= 0) {
comp = ovl_adaptor->ovl_adaptor_comp[i];
if (i < OVL_ADAPTOR_MERGE0)
mtk_mdp_rdma_clk_disable(comp);
else if (i < OVL_ADAPTOR_ETHDR0)
mtk_merge_clk_disable(comp);
else
mtk_ethdr_clk_disable(comp);
}
i = OVL_ADAPTOR_MERGE0;
pwr_err:
while (--i >= 0)
pm_runtime_put(ovl_adaptor->ovl_adaptor_comp[i]);
return ret;
}
void mtk_ovl_adaptor_clk_disable(struct device *dev)
{
struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev);
struct device *comp;
int i;
for (i = 0; i < OVL_ADAPTOR_ID_MAX; i++) {
comp = ovl_adaptor->ovl_adaptor_comp[i];
if (i < OVL_ADAPTOR_MERGE0) {
mtk_mdp_rdma_clk_disable(comp);
pm_runtime_put(comp);
} else if (i < OVL_ADAPTOR_ETHDR0) {
mtk_merge_clk_disable(comp);
} else {
mtk_ethdr_clk_disable(comp);
}
}
}
unsigned int mtk_ovl_adaptor_layer_nr(struct device *dev)
{
return MTK_OVL_ADAPTOR_LAYER_NUM;
}
struct device *mtk_ovl_adaptor_dma_dev_get(struct device *dev)
{
struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev);
return ovl_adaptor->ovl_adaptor_comp[OVL_ADAPTOR_MDP_RDMA0];
}
void mtk_ovl_adaptor_register_vblank_cb(struct device *dev, void (*vblank_cb)(void *),
void *vblank_cb_data)
{
struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev);
mtk_ethdr_register_vblank_cb(ovl_adaptor->ovl_adaptor_comp[OVL_ADAPTOR_ETHDR0],
vblank_cb, vblank_cb_data);
}
void mtk_ovl_adaptor_unregister_vblank_cb(struct device *dev)
{
struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev);
mtk_ethdr_unregister_vblank_cb(ovl_adaptor->ovl_adaptor_comp[OVL_ADAPTOR_ETHDR0]);
}
void mtk_ovl_adaptor_enable_vblank(struct device *dev)
{
struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev);
mtk_ethdr_enable_vblank(ovl_adaptor->ovl_adaptor_comp[OVL_ADAPTOR_ETHDR0]);
}
void mtk_ovl_adaptor_disable_vblank(struct device *dev)
{
struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev);
mtk_ethdr_disable_vblank(ovl_adaptor->ovl_adaptor_comp[OVL_ADAPTOR_ETHDR0]);
}
const u32 *mtk_ovl_adaptor_get_formats(struct device *dev)
{
struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev);
return mtk_mdp_rdma_get_formats(ovl_adaptor->ovl_adaptor_comp[OVL_ADAPTOR_MDP_RDMA0]);
}
size_t mtk_ovl_adaptor_get_num_formats(struct device *dev)
{
struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev);
return mtk_mdp_rdma_get_num_formats(ovl_adaptor->ovl_adaptor_comp[OVL_ADAPTOR_MDP_RDMA0]);
}
void mtk_ovl_adaptor_add_comp(struct device *dev, struct mtk_mutex *mutex)
{
mtk_mutex_add_comp(mutex, DDP_COMPONENT_MDP_RDMA0);
mtk_mutex_add_comp(mutex, DDP_COMPONENT_MDP_RDMA1);
mtk_mutex_add_comp(mutex, DDP_COMPONENT_MDP_RDMA2);
mtk_mutex_add_comp(mutex, DDP_COMPONENT_MDP_RDMA3);
mtk_mutex_add_comp(mutex, DDP_COMPONENT_MDP_RDMA4);
mtk_mutex_add_comp(mutex, DDP_COMPONENT_MDP_RDMA5);
mtk_mutex_add_comp(mutex, DDP_COMPONENT_MDP_RDMA6);
mtk_mutex_add_comp(mutex, DDP_COMPONENT_MDP_RDMA7);
mtk_mutex_add_comp(mutex, DDP_COMPONENT_MERGE1);
mtk_mutex_add_comp(mutex, DDP_COMPONENT_MERGE2);
mtk_mutex_add_comp(mutex, DDP_COMPONENT_MERGE3);
mtk_mutex_add_comp(mutex, DDP_COMPONENT_MERGE4);
mtk_mutex_add_comp(mutex, DDP_COMPONENT_ETHDR_MIXER);
}
void mtk_ovl_adaptor_remove_comp(struct device *dev, struct mtk_mutex *mutex)
{
mtk_mutex_remove_comp(mutex, DDP_COMPONENT_MDP_RDMA0);
mtk_mutex_remove_comp(mutex, DDP_COMPONENT_MDP_RDMA1);
mtk_mutex_remove_comp(mutex, DDP_COMPONENT_MDP_RDMA2);
mtk_mutex_remove_comp(mutex, DDP_COMPONENT_MDP_RDMA3);
mtk_mutex_remove_comp(mutex, DDP_COMPONENT_MDP_RDMA4);
mtk_mutex_remove_comp(mutex, DDP_COMPONENT_MDP_RDMA5);
mtk_mutex_remove_comp(mutex, DDP_COMPONENT_MDP_RDMA6);
mtk_mutex_remove_comp(mutex, DDP_COMPONENT_MDP_RDMA7);
mtk_mutex_remove_comp(mutex, DDP_COMPONENT_MERGE1);
mtk_mutex_remove_comp(mutex, DDP_COMPONENT_MERGE2);
mtk_mutex_remove_comp(mutex, DDP_COMPONENT_MERGE3);
mtk_mutex_remove_comp(mutex, DDP_COMPONENT_MERGE4);
mtk_mutex_remove_comp(mutex, DDP_COMPONENT_ETHDR_MIXER);
}
void mtk_ovl_adaptor_connect(struct device *dev, struct device *mmsys_dev, unsigned int next)
{
mtk_mmsys_ddp_connect(mmsys_dev, DDP_COMPONENT_MDP_RDMA0, DDP_COMPONENT_MERGE1);
mtk_mmsys_ddp_connect(mmsys_dev, DDP_COMPONENT_MDP_RDMA1, DDP_COMPONENT_MERGE1);
mtk_mmsys_ddp_connect(mmsys_dev, DDP_COMPONENT_MDP_RDMA2, DDP_COMPONENT_MERGE2);
mtk_mmsys_ddp_connect(mmsys_dev, DDP_COMPONENT_MERGE1, DDP_COMPONENT_ETHDR_MIXER);
mtk_mmsys_ddp_connect(mmsys_dev, DDP_COMPONENT_MERGE2, DDP_COMPONENT_ETHDR_MIXER);
mtk_mmsys_ddp_connect(mmsys_dev, DDP_COMPONENT_MERGE3, DDP_COMPONENT_ETHDR_MIXER);
mtk_mmsys_ddp_connect(mmsys_dev, DDP_COMPONENT_MERGE4, DDP_COMPONENT_ETHDR_MIXER);
mtk_mmsys_ddp_connect(mmsys_dev, DDP_COMPONENT_ETHDR_MIXER, next);
}
void mtk_ovl_adaptor_disconnect(struct device *dev, struct device *mmsys_dev, unsigned int next)
{
mtk_mmsys_ddp_disconnect(mmsys_dev, DDP_COMPONENT_MDP_RDMA0, DDP_COMPONENT_MERGE1);
mtk_mmsys_ddp_disconnect(mmsys_dev, DDP_COMPONENT_MDP_RDMA1, DDP_COMPONENT_MERGE1);
mtk_mmsys_ddp_disconnect(mmsys_dev, DDP_COMPONENT_MDP_RDMA2, DDP_COMPONENT_MERGE2);
mtk_mmsys_ddp_disconnect(mmsys_dev, DDP_COMPONENT_MERGE1, DDP_COMPONENT_ETHDR_MIXER);
mtk_mmsys_ddp_disconnect(mmsys_dev, DDP_COMPONENT_MERGE2, DDP_COMPONENT_ETHDR_MIXER);
mtk_mmsys_ddp_disconnect(mmsys_dev, DDP_COMPONENT_MERGE3, DDP_COMPONENT_ETHDR_MIXER);
mtk_mmsys_ddp_disconnect(mmsys_dev, DDP_COMPONENT_MERGE4, DDP_COMPONENT_ETHDR_MIXER);
mtk_mmsys_ddp_disconnect(mmsys_dev, DDP_COMPONENT_ETHDR_MIXER, next);
}
static int ovl_adaptor_comp_get_id(struct device *dev, struct device_node *node,
enum mtk_ovl_adaptor_comp_type type)
{
int alias_id = of_alias_get_id(node, private_comp_stem[type]);
int i;
for (i = 0; i < ARRAY_SIZE(comp_matches); i++)
if (comp_matches[i].type == type &&
comp_matches[i].alias_id == alias_id)
return i;
dev_warn(dev, "Failed to get id. type: %d, alias: %d\n", type, alias_id);
return -EINVAL;
}
static const struct of_device_id mtk_ovl_adaptor_comp_dt_ids[] = {
{
.compatible = "mediatek,mt8195-vdo1-rdma",
.data = (void *)OVL_ADAPTOR_TYPE_RDMA,
}, {
.compatible = "mediatek,mt8195-disp-merge",
.data = (void *)OVL_ADAPTOR_TYPE_MERGE,
}, {
.compatible = "mediatek,mt8195-disp-ethdr",
.data = (void *)OVL_ADAPTOR_TYPE_ETHDR,
},
{},
};
static int compare_of(struct device *dev, void *data)
{
return dev->of_node == data;
}
static int ovl_adaptor_comp_init(struct device *dev, struct component_match **match)
{
struct mtk_disp_ovl_adaptor *priv = dev_get_drvdata(dev);
struct device_node *node, *parent;
struct platform_device *comp_pdev;
parent = dev->parent->parent->of_node->parent;
for_each_child_of_node(parent, node) {
const struct of_device_id *of_id;
enum mtk_ovl_adaptor_comp_type type;
int id;
of_id = of_match_node(mtk_ovl_adaptor_comp_dt_ids, node);
if (!of_id)
continue;
if (!of_device_is_available(node)) {
dev_dbg(dev, "Skipping disabled component %pOF\n",
node);
continue;
}
type = (enum mtk_ovl_adaptor_comp_type)of_id->data;
id = ovl_adaptor_comp_get_id(dev, node, type);
if (id < 0) {
dev_warn(dev, "Skipping unknown component %pOF\n",
node);
continue;
}
comp_pdev = of_find_device_by_node(node);
if (!comp_pdev)
return -EPROBE_DEFER;
priv->ovl_adaptor_comp[id] = &comp_pdev->dev;
drm_of_component_match_add(dev, match, compare_of, node);
dev_dbg(dev, "Adding component match for %pOF\n", node);
}
if (!*match) {
dev_err(dev, "No match device for ovl_adaptor\n");
return -ENODEV;
}
return 0;
}
static int mtk_disp_ovl_adaptor_comp_bind(struct device *dev, struct device *master,
void *data)
{
struct mtk_disp_ovl_adaptor *priv = dev_get_drvdata(dev);
if (!priv->children_bound)
return -EPROBE_DEFER;
return 0;
}
static void mtk_disp_ovl_adaptor_comp_unbind(struct device *dev, struct device *master,
void *data)
{
}
static const struct component_ops mtk_disp_ovl_adaptor_comp_ops = {
.bind = mtk_disp_ovl_adaptor_comp_bind,
.unbind = mtk_disp_ovl_adaptor_comp_unbind,
};
static int mtk_disp_ovl_adaptor_master_bind(struct device *dev)
{
struct mtk_disp_ovl_adaptor *priv = dev_get_drvdata(dev);
int ret;
ret = component_bind_all(dev, priv->mmsys_dev);
if (ret)
return dev_err_probe(dev, ret, "component_bind_all failed!\n");
priv->children_bound = true;
return 0;
}
static void mtk_disp_ovl_adaptor_master_unbind(struct device *dev)
{
struct mtk_disp_ovl_adaptor *priv = dev_get_drvdata(dev);
priv->children_bound = false;
}
static const struct component_master_ops mtk_disp_ovl_adaptor_master_ops = {
.bind = mtk_disp_ovl_adaptor_master_bind,
.unbind = mtk_disp_ovl_adaptor_master_unbind,
};
static int mtk_disp_ovl_adaptor_probe(struct platform_device *pdev)
{
struct mtk_disp_ovl_adaptor *priv;
struct device *dev = &pdev->dev;
struct component_match *match = NULL;
int ret;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
platform_set_drvdata(pdev, priv);
ret = ovl_adaptor_comp_init(dev, &match);
if (ret < 0)
return ret;
priv->mmsys_dev = pdev->dev.platform_data;
component_master_add_with_match(dev, &mtk_disp_ovl_adaptor_master_ops, match);
pm_runtime_enable(dev);
ret = component_add(dev, &mtk_disp_ovl_adaptor_comp_ops);
if (ret != 0) {
pm_runtime_disable(dev);
dev_err(dev, "Failed to add component: %d\n", ret);
}
return ret;
}
static int mtk_disp_ovl_adaptor_remove(struct platform_device *pdev)
{
component_master_del(&pdev->dev, &mtk_disp_ovl_adaptor_master_ops);
pm_runtime_disable(&pdev->dev);
return 0;
}
struct platform_driver mtk_disp_ovl_adaptor_driver = {
.probe = mtk_disp_ovl_adaptor_probe,
.remove = mtk_disp_ovl_adaptor_remove,
.driver = {
.name = "mediatek-disp-ovl-adaptor",
.owner = THIS_MODULE,
},
};
...@@ -55,8 +55,24 @@ ...@@ -55,8 +55,24 @@
#define RDMA_MEM_GMC 0x40402020 #define RDMA_MEM_GMC 0x40402020
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,
};
struct mtk_disp_rdma_data { struct mtk_disp_rdma_data {
unsigned int fifo_size; unsigned int fifo_size;
const u32 *formats;
size_t num_formats;
}; };
/* /*
...@@ -127,6 +143,20 @@ void mtk_rdma_disable_vblank(struct device *dev) ...@@ -127,6 +143,20 @@ void mtk_rdma_disable_vblank(struct device *dev)
rdma_update_bits(dev, DISP_REG_RDMA_INT_ENABLE, RDMA_FRAME_END_INT, 0); rdma_update_bits(dev, DISP_REG_RDMA_INT_ENABLE, RDMA_FRAME_END_INT, 0);
} }
const u32 *mtk_rdma_get_formats(struct device *dev)
{
struct mtk_disp_rdma *rdma = dev_get_drvdata(dev);
return rdma->data->formats;
}
size_t mtk_rdma_get_num_formats(struct device *dev)
{
struct mtk_disp_rdma *rdma = dev_get_drvdata(dev);
return rdma->data->num_formats;
}
int mtk_rdma_clk_enable(struct device *dev) int mtk_rdma_clk_enable(struct device *dev)
{ {
struct mtk_disp_rdma *rdma = dev_get_drvdata(dev); struct mtk_disp_rdma *rdma = dev_get_drvdata(dev);
...@@ -361,18 +391,26 @@ static int mtk_disp_rdma_remove(struct platform_device *pdev) ...@@ -361,18 +391,26 @@ static int mtk_disp_rdma_remove(struct platform_device *pdev)
static const struct mtk_disp_rdma_data mt2701_rdma_driver_data = { static const struct mtk_disp_rdma_data mt2701_rdma_driver_data = {
.fifo_size = SZ_4K, .fifo_size = SZ_4K,
.formats = mt8173_formats,
.num_formats = ARRAY_SIZE(mt8173_formats),
}; };
static const struct mtk_disp_rdma_data mt8173_rdma_driver_data = { static const struct mtk_disp_rdma_data mt8173_rdma_driver_data = {
.fifo_size = SZ_8K, .fifo_size = SZ_8K,
.formats = mt8173_formats,
.num_formats = ARRAY_SIZE(mt8173_formats),
}; };
static const struct mtk_disp_rdma_data mt8183_rdma_driver_data = { static const struct mtk_disp_rdma_data mt8183_rdma_driver_data = {
.fifo_size = 5 * SZ_1K, .fifo_size = 5 * SZ_1K,
.formats = mt8173_formats,
.num_formats = ARRAY_SIZE(mt8173_formats),
}; };
static const struct mtk_disp_rdma_data mt8195_rdma_driver_data = { static const struct mtk_disp_rdma_data mt8195_rdma_driver_data = {
.fifo_size = 1920, .fifo_size = 1920,
.formats = mt8173_formats,
.num_formats = ARRAY_SIZE(mt8173_formats),
}; };
static const struct of_device_id mtk_disp_rdma_driver_dt_match[] = { static const struct of_device_id mtk_disp_rdma_driver_dt_match[] = {
......
...@@ -806,10 +806,9 @@ static int mtk_dp_aux_wait_for_completion(struct mtk_dp *mtk_dp, bool is_read) ...@@ -806,10 +806,9 @@ static int mtk_dp_aux_wait_for_completion(struct mtk_dp *mtk_dp, bool is_read)
} }
static int mtk_dp_aux_do_transfer(struct mtk_dp *mtk_dp, bool is_read, u8 cmd, static int mtk_dp_aux_do_transfer(struct mtk_dp *mtk_dp, bool is_read, u8 cmd,
u32 addr, u8 *buf, size_t length) u32 addr, u8 *buf, size_t length, u8 *reply_cmd)
{ {
int ret; int ret;
u32 reply_cmd;
if (is_read && (length > DP_AUX_MAX_PAYLOAD_BYTES || if (is_read && (length > DP_AUX_MAX_PAYLOAD_BYTES ||
(cmd == DP_AUX_NATIVE_READ && !length))) (cmd == DP_AUX_NATIVE_READ && !length)))
...@@ -841,10 +840,10 @@ static int mtk_dp_aux_do_transfer(struct mtk_dp *mtk_dp, bool is_read, u8 cmd, ...@@ -841,10 +840,10 @@ static int mtk_dp_aux_do_transfer(struct mtk_dp *mtk_dp, bool is_read, u8 cmd,
/* Wait for feedback from sink device. */ /* Wait for feedback from sink device. */
ret = mtk_dp_aux_wait_for_completion(mtk_dp, is_read); ret = mtk_dp_aux_wait_for_completion(mtk_dp, is_read);
reply_cmd = mtk_dp_read(mtk_dp, MTK_DP_AUX_P0_3624) & *reply_cmd = mtk_dp_read(mtk_dp, MTK_DP_AUX_P0_3624) &
AUX_RX_REPLY_COMMAND_AUX_TX_P0_MASK; AUX_RX_REPLY_COMMAND_AUX_TX_P0_MASK;
if (ret || reply_cmd) { if (ret) {
u32 phy_status = mtk_dp_read(mtk_dp, MTK_DP_AUX_P0_3628) & u32 phy_status = mtk_dp_read(mtk_dp, MTK_DP_AUX_P0_3628) &
AUX_RX_PHY_STATE_AUX_TX_P0_MASK; AUX_RX_PHY_STATE_AUX_TX_P0_MASK;
if (phy_status != AUX_RX_PHY_STATE_AUX_TX_P0_RX_IDLE) { if (phy_status != AUX_RX_PHY_STATE_AUX_TX_P0_RX_IDLE) {
...@@ -1823,6 +1822,7 @@ static irqreturn_t mtk_dp_hpd_event_thread(int hpd, void *dev) ...@@ -1823,6 +1822,7 @@ static irqreturn_t mtk_dp_hpd_event_thread(int hpd, void *dev)
spin_unlock_irqrestore(&mtk_dp->irq_thread_lock, flags); spin_unlock_irqrestore(&mtk_dp->irq_thread_lock, flags);
if (status & MTK_DP_THREAD_CABLE_STATE_CHG) { if (status & MTK_DP_THREAD_CABLE_STATE_CHG) {
if (mtk_dp->bridge.dev)
drm_helper_hpd_irq_event(mtk_dp->bridge.dev); drm_helper_hpd_irq_event(mtk_dp->bridge.dev);
if (!mtk_dp->train_info.cable_plugged_in) { if (!mtk_dp->train_info.cable_plugged_in) {
...@@ -2070,7 +2070,7 @@ static ssize_t mtk_dp_aux_transfer(struct drm_dp_aux *mtk_aux, ...@@ -2070,7 +2070,7 @@ static ssize_t mtk_dp_aux_transfer(struct drm_dp_aux *mtk_aux,
ret = mtk_dp_aux_do_transfer(mtk_dp, is_read, request, ret = mtk_dp_aux_do_transfer(mtk_dp, is_read, request,
msg->address + accessed_bytes, msg->address + accessed_bytes,
msg->buffer + accessed_bytes, msg->buffer + accessed_bytes,
to_access); to_access, &msg->reply);
if (ret) { if (ret) {
drm_info(mtk_dp->drm_dev, drm_info(mtk_dp->drm_dev,
...@@ -2080,7 +2080,6 @@ static ssize_t mtk_dp_aux_transfer(struct drm_dp_aux *mtk_aux, ...@@ -2080,7 +2080,6 @@ static ssize_t mtk_dp_aux_transfer(struct drm_dp_aux *mtk_aux,
accessed_bytes += to_access; accessed_bytes += to_access;
} while (accessed_bytes < msg->size); } while (accessed_bytes < msg->size);
msg->reply = DP_AUX_NATIVE_REPLY_ACK | DP_AUX_I2C_REPLY_ACK;
return msg->size; return msg->size;
err: err:
msg->reply = DP_AUX_NATIVE_REPLY_NACK | DP_AUX_I2C_REPLY_NACK; msg->reply = DP_AUX_NATIVE_REPLY_NACK | DP_AUX_I2C_REPLY_NACK;
......
...@@ -58,6 +58,7 @@ struct mtk_drm_crtc { ...@@ -58,6 +58,7 @@ struct mtk_drm_crtc {
#endif #endif
struct device *mmsys_dev; struct device *mmsys_dev;
struct device *dma_dev;
struct mtk_mutex *mutex; struct mtk_mutex *mutex;
unsigned int ddp_comp_nr; unsigned int ddp_comp_nr;
struct mtk_ddp_comp **ddp_comp; struct mtk_ddp_comp **ddp_comp;
...@@ -378,12 +379,16 @@ static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc) ...@@ -378,12 +379,16 @@ static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc)
} }
for (i = 0; i < mtk_crtc->ddp_comp_nr - 1; i++) { for (i = 0; i < mtk_crtc->ddp_comp_nr - 1; i++) {
if (!mtk_ddp_comp_connect(mtk_crtc->ddp_comp[i], mtk_crtc->mmsys_dev,
mtk_crtc->ddp_comp[i + 1]->id))
mtk_mmsys_ddp_connect(mtk_crtc->mmsys_dev, mtk_mmsys_ddp_connect(mtk_crtc->mmsys_dev,
mtk_crtc->ddp_comp[i]->id, mtk_crtc->ddp_comp[i]->id,
mtk_crtc->ddp_comp[i + 1]->id); mtk_crtc->ddp_comp[i + 1]->id);
if (!mtk_ddp_comp_add(mtk_crtc->ddp_comp[i], mtk_crtc->mutex))
mtk_mutex_add_comp(mtk_crtc->mutex, mtk_mutex_add_comp(mtk_crtc->mutex,
mtk_crtc->ddp_comp[i]->id); mtk_crtc->ddp_comp[i]->id);
} }
if (!mtk_ddp_comp_add(mtk_crtc->ddp_comp[i], mtk_crtc->mutex))
mtk_mutex_add_comp(mtk_crtc->mutex, mtk_crtc->ddp_comp[i]->id); mtk_mutex_add_comp(mtk_crtc->mutex, mtk_crtc->ddp_comp[i]->id);
mtk_mutex_enable(mtk_crtc->mutex); mtk_mutex_enable(mtk_crtc->mutex);
...@@ -433,16 +438,21 @@ static void mtk_crtc_ddp_hw_fini(struct mtk_drm_crtc *mtk_crtc) ...@@ -433,16 +438,21 @@ static void mtk_crtc_ddp_hw_fini(struct mtk_drm_crtc *mtk_crtc)
} }
for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
if (!mtk_ddp_comp_remove(mtk_crtc->ddp_comp[i], mtk_crtc->mutex))
mtk_mutex_remove_comp(mtk_crtc->mutex, mtk_mutex_remove_comp(mtk_crtc->mutex,
mtk_crtc->ddp_comp[i]->id); mtk_crtc->ddp_comp[i]->id);
mtk_mutex_disable(mtk_crtc->mutex); mtk_mutex_disable(mtk_crtc->mutex);
for (i = 0; i < mtk_crtc->ddp_comp_nr - 1; i++) { for (i = 0; i < mtk_crtc->ddp_comp_nr - 1; i++) {
if (!mtk_ddp_comp_disconnect(mtk_crtc->ddp_comp[i], mtk_crtc->mmsys_dev,
mtk_crtc->ddp_comp[i + 1]->id))
mtk_mmsys_ddp_disconnect(mtk_crtc->mmsys_dev, mtk_mmsys_ddp_disconnect(mtk_crtc->mmsys_dev,
mtk_crtc->ddp_comp[i]->id, mtk_crtc->ddp_comp[i]->id,
mtk_crtc->ddp_comp[i + 1]->id); mtk_crtc->ddp_comp[i + 1]->id);
if (!mtk_ddp_comp_remove(mtk_crtc->ddp_comp[i], mtk_crtc->mutex))
mtk_mutex_remove_comp(mtk_crtc->mutex, mtk_mutex_remove_comp(mtk_crtc->mutex,
mtk_crtc->ddp_comp[i]->id); mtk_crtc->ddp_comp[i]->id);
} }
if (!mtk_ddp_comp_remove(mtk_crtc->ddp_comp[i], mtk_crtc->mutex))
mtk_mutex_remove_comp(mtk_crtc->mutex, mtk_crtc->ddp_comp[i]->id); mtk_mutex_remove_comp(mtk_crtc->mutex, mtk_crtc->ddp_comp[i]->id);
mtk_crtc_ddp_clk_disable(mtk_crtc); mtk_crtc_ddp_clk_disable(mtk_crtc);
mtk_mutex_unprepare(mtk_crtc->mutex); mtk_mutex_unprepare(mtk_crtc->mutex);
...@@ -856,7 +866,9 @@ static int mtk_drm_crtc_init_comp_planes(struct drm_device *drm_dev, ...@@ -856,7 +866,9 @@ static int mtk_drm_crtc_init_comp_planes(struct drm_device *drm_dev,
BIT(pipe), BIT(pipe),
mtk_drm_crtc_plane_type(mtk_crtc->layer_nr, mtk_drm_crtc_plane_type(mtk_crtc->layer_nr,
num_planes), num_planes),
mtk_ddp_comp_supported_rotations(comp)); mtk_ddp_comp_supported_rotations(comp),
mtk_ddp_comp_get_formats(comp),
mtk_ddp_comp_get_num_formats(comp));
if (ret) if (ret)
return ret; return ret;
...@@ -865,22 +877,36 @@ static int mtk_drm_crtc_init_comp_planes(struct drm_device *drm_dev, ...@@ -865,22 +877,36 @@ static int mtk_drm_crtc_init_comp_planes(struct drm_device *drm_dev,
return 0; return 0;
} }
struct device *mtk_drm_crtc_dma_dev_get(struct drm_crtc *crtc)
{
struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
return mtk_crtc->dma_dev;
}
int mtk_drm_crtc_create(struct drm_device *drm_dev, int mtk_drm_crtc_create(struct drm_device *drm_dev,
const enum mtk_ddp_comp_id *path, unsigned int path_len) const unsigned int *path, unsigned int path_len,
int priv_data_index)
{ {
struct mtk_drm_private *priv = drm_dev->dev_private; struct mtk_drm_private *priv = drm_dev->dev_private;
struct device *dev = drm_dev->dev; struct device *dev = drm_dev->dev;
struct mtk_drm_crtc *mtk_crtc; struct mtk_drm_crtc *mtk_crtc;
unsigned int num_comp_planes = 0; unsigned int num_comp_planes = 0;
int pipe = priv->num_pipes;
int ret; int ret;
int i; int i;
bool has_ctm = false; bool has_ctm = false;
uint gamma_lut_size = 0; uint gamma_lut_size = 0;
struct drm_crtc *tmp;
int crtc_i = 0;
if (!path) if (!path)
return 0; return 0;
priv = priv->all_drm_private[priv_data_index];
drm_for_each_crtc(tmp, drm_dev)
crtc_i++;
for (i = 0; i < path_len; i++) { for (i = 0; i < path_len; i++) {
enum mtk_ddp_comp_id comp_id = path[i]; enum mtk_ddp_comp_id comp_id = path[i];
struct device_node *node; struct device_node *node;
...@@ -889,10 +915,13 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev, ...@@ -889,10 +915,13 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
node = priv->comp_node[comp_id]; node = priv->comp_node[comp_id];
comp = &priv->ddp_comp[comp_id]; comp = &priv->ddp_comp[comp_id];
if (!node) { /* Not all drm components have a DTS device node, such as ovl_adaptor,
* which is the drm bring up sub driver
*/
if (!node && comp_id != DDP_COMPONENT_DRM_OVL_ADAPTOR) {
dev_info(dev, dev_info(dev,
"Not creating crtc %d because component %d is disabled or missing\n", "Not creating crtc %d because component %d is disabled or missing\n",
pipe, comp_id); crtc_i, comp_id);
return 0; return 0;
} }
...@@ -922,7 +951,7 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev, ...@@ -922,7 +951,7 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
} }
for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) { for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
enum mtk_ddp_comp_id comp_id = path[i]; unsigned int comp_id = path[i];
struct mtk_ddp_comp *comp; struct mtk_ddp_comp *comp;
comp = &priv->ddp_comp[comp_id]; comp = &priv->ddp_comp[comp_id];
...@@ -950,29 +979,35 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev, ...@@ -950,29 +979,35 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) { for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
ret = mtk_drm_crtc_init_comp_planes(drm_dev, mtk_crtc, i, ret = mtk_drm_crtc_init_comp_planes(drm_dev, mtk_crtc, i,
pipe); crtc_i);
if (ret) if (ret)
return ret; return ret;
} }
ret = mtk_drm_crtc_init(drm_dev, mtk_crtc, pipe); /*
* Default to use the first component as the dma dev.
* In the case of ovl_adaptor sub driver, it needs to use the
* dma_dev_get function to get representative dma dev.
*/
mtk_crtc->dma_dev = mtk_ddp_comp_dma_dev_get(&priv->ddp_comp[path[0]]);
ret = mtk_drm_crtc_init(drm_dev, mtk_crtc, crtc_i);
if (ret < 0) if (ret < 0)
return ret; return ret;
if (gamma_lut_size) if (gamma_lut_size)
drm_mode_crtc_set_gamma_size(&mtk_crtc->base, gamma_lut_size); drm_mode_crtc_set_gamma_size(&mtk_crtc->base, gamma_lut_size);
drm_crtc_enable_color_mgmt(&mtk_crtc->base, 0, has_ctm, gamma_lut_size); drm_crtc_enable_color_mgmt(&mtk_crtc->base, 0, has_ctm, gamma_lut_size);
priv->num_pipes++;
mutex_init(&mtk_crtc->hw_lock); mutex_init(&mtk_crtc->hw_lock);
#if IS_REACHABLE(CONFIG_MTK_CMDQ) #if IS_REACHABLE(CONFIG_MTK_CMDQ)
i = priv->mbox_index++;
mtk_crtc->cmdq_client.client.dev = mtk_crtc->mmsys_dev; mtk_crtc->cmdq_client.client.dev = mtk_crtc->mmsys_dev;
mtk_crtc->cmdq_client.client.tx_block = false; mtk_crtc->cmdq_client.client.tx_block = false;
mtk_crtc->cmdq_client.client.knows_txdone = true; mtk_crtc->cmdq_client.client.knows_txdone = true;
mtk_crtc->cmdq_client.client.rx_callback = ddp_cmdq_cb; mtk_crtc->cmdq_client.client.rx_callback = ddp_cmdq_cb;
mtk_crtc->cmdq_client.chan = mtk_crtc->cmdq_client.chan =
mbox_request_channel(&mtk_crtc->cmdq_client.client, mbox_request_channel(&mtk_crtc->cmdq_client.client, i);
drm_crtc_index(&mtk_crtc->base));
if (IS_ERR(mtk_crtc->cmdq_client.chan)) { if (IS_ERR(mtk_crtc->cmdq_client.chan)) {
dev_dbg(dev, "mtk_crtc %d failed to create mailbox client, writing register by CPU now\n", dev_dbg(dev, "mtk_crtc %d failed to create mailbox client, writing register by CPU now\n",
drm_crtc_index(&mtk_crtc->base)); drm_crtc_index(&mtk_crtc->base));
...@@ -982,7 +1017,7 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev, ...@@ -982,7 +1017,7 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
if (mtk_crtc->cmdq_client.chan) { if (mtk_crtc->cmdq_client.chan) {
ret = of_property_read_u32_index(priv->mutex_node, ret = of_property_read_u32_index(priv->mutex_node,
"mediatek,gce-events", "mediatek,gce-events",
drm_crtc_index(&mtk_crtc->base), i,
&mtk_crtc->cmdq_event); &mtk_crtc->cmdq_event);
if (ret) { if (ret) {
dev_dbg(dev, "mtk_crtc %d failed to get mediatek,gce-events property\n", dev_dbg(dev, "mtk_crtc %d failed to get mediatek,gce-events property\n",
......
...@@ -16,11 +16,13 @@ ...@@ -16,11 +16,13 @@
void mtk_drm_crtc_commit(struct drm_crtc *crtc); void mtk_drm_crtc_commit(struct drm_crtc *crtc);
int mtk_drm_crtc_create(struct drm_device *drm_dev, int mtk_drm_crtc_create(struct drm_device *drm_dev,
const enum mtk_ddp_comp_id *path, const unsigned int *path,
unsigned int path_len); unsigned int path_len,
int priv_data_index);
int mtk_drm_crtc_plane_check(struct drm_crtc *crtc, struct drm_plane *plane, int mtk_drm_crtc_plane_check(struct drm_crtc *crtc, struct drm_plane *plane,
struct mtk_plane_state *state); struct mtk_plane_state *state);
void mtk_drm_crtc_async_update(struct drm_crtc *crtc, struct drm_plane *plane, void mtk_drm_crtc_async_update(struct drm_crtc *crtc, struct drm_plane *plane,
struct drm_atomic_state *plane_state); struct drm_atomic_state *plane_state);
struct device *mtk_drm_crtc_dma_dev_get(struct drm_crtc *crtc);
#endif /* MTK_DRM_CRTC_H */ #endif /* MTK_DRM_CRTC_H */
...@@ -359,6 +359,8 @@ static const struct mtk_ddp_comp_funcs ddp_ovl = { ...@@ -359,6 +359,8 @@ static const struct mtk_ddp_comp_funcs ddp_ovl = {
.layer_config = mtk_ovl_layer_config, .layer_config = mtk_ovl_layer_config,
.bgclr_in_on = mtk_ovl_bgclr_in_on, .bgclr_in_on = mtk_ovl_bgclr_in_on,
.bgclr_in_off = mtk_ovl_bgclr_in_off, .bgclr_in_off = mtk_ovl_bgclr_in_off,
.get_formats = mtk_ovl_get_formats,
.get_num_formats = mtk_ovl_get_num_formats,
}; };
static const struct mtk_ddp_comp_funcs ddp_postmask = { static const struct mtk_ddp_comp_funcs ddp_postmask = {
...@@ -381,6 +383,8 @@ static const struct mtk_ddp_comp_funcs ddp_rdma = { ...@@ -381,6 +383,8 @@ static const struct mtk_ddp_comp_funcs ddp_rdma = {
.disable_vblank = mtk_rdma_disable_vblank, .disable_vblank = mtk_rdma_disable_vblank,
.layer_nr = mtk_rdma_layer_nr, .layer_nr = mtk_rdma_layer_nr,
.layer_config = mtk_rdma_layer_config, .layer_config = mtk_rdma_layer_config,
.get_formats = mtk_rdma_get_formats,
.get_num_formats = mtk_rdma_get_num_formats,
}; };
static const struct mtk_ddp_comp_funcs ddp_ufoe = { static const struct mtk_ddp_comp_funcs ddp_ufoe = {
...@@ -389,6 +393,27 @@ static const struct mtk_ddp_comp_funcs ddp_ufoe = { ...@@ -389,6 +393,27 @@ static const struct mtk_ddp_comp_funcs ddp_ufoe = {
.start = mtk_ufoe_start, .start = mtk_ufoe_start,
}; };
static const struct mtk_ddp_comp_funcs ddp_ovl_adaptor = {
.clk_enable = mtk_ovl_adaptor_clk_enable,
.clk_disable = mtk_ovl_adaptor_clk_disable,
.config = mtk_ovl_adaptor_config,
.start = mtk_ovl_adaptor_start,
.stop = mtk_ovl_adaptor_stop,
.layer_nr = mtk_ovl_adaptor_layer_nr,
.layer_config = mtk_ovl_adaptor_layer_config,
.register_vblank_cb = mtk_ovl_adaptor_register_vblank_cb,
.unregister_vblank_cb = mtk_ovl_adaptor_unregister_vblank_cb,
.enable_vblank = mtk_ovl_adaptor_enable_vblank,
.disable_vblank = mtk_ovl_adaptor_disable_vblank,
.dma_dev_get = mtk_ovl_adaptor_dma_dev_get,
.connect = mtk_ovl_adaptor_connect,
.disconnect = mtk_ovl_adaptor_disconnect,
.add = mtk_ovl_adaptor_add_comp,
.remove = mtk_ovl_adaptor_remove_comp,
.get_formats = mtk_ovl_adaptor_get_formats,
.get_num_formats = mtk_ovl_adaptor_get_num_formats,
};
static const char * const mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = { static const char * const mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = {
[MTK_DISP_AAL] = "aal", [MTK_DISP_AAL] = "aal",
[MTK_DISP_BLS] = "bls", [MTK_DISP_BLS] = "bls",
...@@ -402,6 +427,7 @@ static const char * const mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = { ...@@ -402,6 +427,7 @@ static const char * const mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = {
[MTK_DISP_OD] = "od", [MTK_DISP_OD] = "od",
[MTK_DISP_OVL] = "ovl", [MTK_DISP_OVL] = "ovl",
[MTK_DISP_OVL_2L] = "ovl-2l", [MTK_DISP_OVL_2L] = "ovl-2l",
[MTK_DISP_OVL_ADAPTOR] = "ovl_adaptor",
[MTK_DISP_POSTMASK] = "postmask", [MTK_DISP_POSTMASK] = "postmask",
[MTK_DISP_PWM] = "pwm", [MTK_DISP_PWM] = "pwm",
[MTK_DISP_RDMA] = "rdma", [MTK_DISP_RDMA] = "rdma",
...@@ -418,7 +444,7 @@ struct mtk_ddp_comp_match { ...@@ -418,7 +444,7 @@ struct mtk_ddp_comp_match {
const struct mtk_ddp_comp_funcs *funcs; const struct mtk_ddp_comp_funcs *funcs;
}; };
static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_ID_MAX] = { static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_DRM_ID_MAX] = {
[DDP_COMPONENT_AAL0] = { MTK_DISP_AAL, 0, &ddp_aal }, [DDP_COMPONENT_AAL0] = { MTK_DISP_AAL, 0, &ddp_aal },
[DDP_COMPONENT_AAL1] = { MTK_DISP_AAL, 1, &ddp_aal }, [DDP_COMPONENT_AAL1] = { MTK_DISP_AAL, 1, &ddp_aal },
[DDP_COMPONENT_BLS] = { MTK_DISP_BLS, 0, NULL }, [DDP_COMPONENT_BLS] = { MTK_DISP_BLS, 0, NULL },
...@@ -430,6 +456,7 @@ static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_ID_MAX] = { ...@@ -430,6 +456,7 @@ static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_DP_INTF1] = { MTK_DP_INTF, 1, &ddp_dpi }, [DDP_COMPONENT_DP_INTF1] = { MTK_DP_INTF, 1, &ddp_dpi },
[DDP_COMPONENT_DPI0] = { MTK_DPI, 0, &ddp_dpi }, [DDP_COMPONENT_DPI0] = { MTK_DPI, 0, &ddp_dpi },
[DDP_COMPONENT_DPI1] = { MTK_DPI, 1, &ddp_dpi }, [DDP_COMPONENT_DPI1] = { MTK_DPI, 1, &ddp_dpi },
[DDP_COMPONENT_DRM_OVL_ADAPTOR] = { MTK_DISP_OVL_ADAPTOR, 0, &ddp_ovl_adaptor },
[DDP_COMPONENT_DSC0] = { MTK_DISP_DSC, 0, &ddp_dsc }, [DDP_COMPONENT_DSC0] = { MTK_DISP_DSC, 0, &ddp_dsc },
[DDP_COMPONENT_DSC1] = { MTK_DISP_DSC, 1, &ddp_dsc }, [DDP_COMPONENT_DSC1] = { MTK_DISP_DSC, 1, &ddp_dsc },
[DDP_COMPONENT_DSI0] = { MTK_DSI, 0, &ddp_dsi }, [DDP_COMPONENT_DSI0] = { MTK_DSI, 0, &ddp_dsi },
...@@ -464,7 +491,7 @@ static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_ID_MAX] = { ...@@ -464,7 +491,7 @@ static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_ID_MAX] = {
}; };
static bool mtk_drm_find_comp_in_ddp(struct device *dev, static bool mtk_drm_find_comp_in_ddp(struct device *dev,
const enum mtk_ddp_comp_id *path, const unsigned int *path,
unsigned int path_len, unsigned int path_len,
struct mtk_ddp_comp *ddp_comp) struct mtk_ddp_comp *ddp_comp)
{ {
...@@ -517,7 +544,7 @@ unsigned int mtk_drm_find_possible_crtc_by_comp(struct drm_device *drm, ...@@ -517,7 +544,7 @@ unsigned int mtk_drm_find_possible_crtc_by_comp(struct drm_device *drm,
} }
int mtk_ddp_comp_init(struct device_node *node, struct mtk_ddp_comp *comp, int mtk_ddp_comp_init(struct device_node *node, struct mtk_ddp_comp *comp,
enum mtk_ddp_comp_id comp_id) unsigned int comp_id)
{ {
struct platform_device *comp_pdev; struct platform_device *comp_pdev;
enum mtk_ddp_comp_type type; enum mtk_ddp_comp_type type;
...@@ -526,19 +553,24 @@ int mtk_ddp_comp_init(struct device_node *node, struct mtk_ddp_comp *comp, ...@@ -526,19 +553,24 @@ int mtk_ddp_comp_init(struct device_node *node, struct mtk_ddp_comp *comp,
int ret; int ret;
#endif #endif
if (comp_id < 0 || comp_id >= DDP_COMPONENT_ID_MAX) if (comp_id < 0 || comp_id >= DDP_COMPONENT_DRM_ID_MAX)
return -EINVAL; return -EINVAL;
type = mtk_ddp_matches[comp_id].type; type = mtk_ddp_matches[comp_id].type;
comp->id = comp_id; comp->id = comp_id;
comp->funcs = mtk_ddp_matches[comp_id].funcs; comp->funcs = mtk_ddp_matches[comp_id].funcs;
/* Not all drm components have a DTS device node, such as ovl_adaptor,
* which is the drm bring up sub driver
*/
if (node) {
comp_pdev = of_find_device_by_node(node); comp_pdev = of_find_device_by_node(node);
if (!comp_pdev) { if (!comp_pdev) {
DRM_INFO("Waiting for device %s\n", node->full_name); DRM_INFO("Waiting for device %s\n", node->full_name);
return -EPROBE_DEFER; return -EPROBE_DEFER;
} }
comp->dev = &comp_pdev->dev; comp->dev = &comp_pdev->dev;
}
if (type == MTK_DISP_AAL || if (type == MTK_DISP_AAL ||
type == MTK_DISP_BLS || type == MTK_DISP_BLS ||
...@@ -548,6 +580,7 @@ int mtk_ddp_comp_init(struct device_node *node, struct mtk_ddp_comp *comp, ...@@ -548,6 +580,7 @@ int mtk_ddp_comp_init(struct device_node *node, struct mtk_ddp_comp *comp,
type == MTK_DISP_MERGE || type == MTK_DISP_MERGE ||
type == MTK_DISP_OVL || type == MTK_DISP_OVL ||
type == MTK_DISP_OVL_2L || type == MTK_DISP_OVL_2L ||
type == MTK_DISP_OVL_ADAPTOR ||
type == MTK_DISP_PWM || type == MTK_DISP_PWM ||
type == MTK_DISP_RDMA || type == MTK_DISP_RDMA ||
type == MTK_DPI || type == MTK_DPI ||
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/soc/mediatek/mtk-cmdq.h> #include <linux/soc/mediatek/mtk-cmdq.h>
#include <linux/soc/mediatek/mtk-mmsys.h> #include <linux/soc/mediatek/mtk-mmsys.h>
#include <linux/soc/mediatek/mtk-mutex.h>
struct device; struct device;
struct device_node; struct device_node;
...@@ -30,6 +31,7 @@ enum mtk_ddp_comp_type { ...@@ -30,6 +31,7 @@ enum mtk_ddp_comp_type {
MTK_DISP_OD, MTK_DISP_OD,
MTK_DISP_OVL, MTK_DISP_OVL,
MTK_DISP_OVL_2L, MTK_DISP_OVL_2L,
MTK_DISP_OVL_ADAPTOR,
MTK_DISP_POSTMASK, MTK_DISP_POSTMASK,
MTK_DISP_PWM, MTK_DISP_PWM,
MTK_DISP_RDMA, MTK_DISP_RDMA,
...@@ -71,12 +73,19 @@ struct mtk_ddp_comp_funcs { ...@@ -71,12 +73,19 @@ struct mtk_ddp_comp_funcs {
void (*bgclr_in_off)(struct device *dev); void (*bgclr_in_off)(struct device *dev);
void (*ctm_set)(struct device *dev, void (*ctm_set)(struct device *dev,
struct drm_crtc_state *state); struct drm_crtc_state *state);
struct device * (*dma_dev_get)(struct device *dev);
const u32 *(*get_formats)(struct device *dev);
size_t (*get_num_formats)(struct device *dev);
void (*connect)(struct device *dev, struct device *mmsys_dev, unsigned int next);
void (*disconnect)(struct device *dev, struct device *mmsys_dev, unsigned int next);
void (*add)(struct device *dev, struct mtk_mutex *mutex);
void (*remove)(struct device *dev, struct mtk_mutex *mutex);
}; };
struct mtk_ddp_comp { struct mtk_ddp_comp {
struct device *dev; struct device *dev;
int irq; int irq;
enum mtk_ddp_comp_id id; unsigned int id;
const struct mtk_ddp_comp_funcs *funcs; const struct mtk_ddp_comp_funcs *funcs;
}; };
...@@ -203,13 +212,76 @@ static inline void mtk_ddp_ctm_set(struct mtk_ddp_comp *comp, ...@@ -203,13 +212,76 @@ static inline void mtk_ddp_ctm_set(struct mtk_ddp_comp *comp,
comp->funcs->ctm_set(comp->dev, state); comp->funcs->ctm_set(comp->dev, state);
} }
static inline struct device *mtk_ddp_comp_dma_dev_get(struct mtk_ddp_comp *comp)
{
if (comp->funcs && comp->funcs->dma_dev_get)
return comp->funcs->dma_dev_get(comp->dev);
return comp->dev;
}
static inline
const u32 *mtk_ddp_comp_get_formats(struct mtk_ddp_comp *comp)
{
if (comp->funcs && comp->funcs->get_formats)
return comp->funcs->get_formats(comp->dev);
return NULL;
}
static inline
size_t mtk_ddp_comp_get_num_formats(struct mtk_ddp_comp *comp)
{
if (comp->funcs && comp->funcs->get_num_formats)
return comp->funcs->get_num_formats(comp->dev);
return 0;
}
static inline bool mtk_ddp_comp_add(struct mtk_ddp_comp *comp, struct mtk_mutex *mutex)
{
if (comp->funcs && comp->funcs->add) {
comp->funcs->add(comp->dev, mutex);
return true;
}
return false;
}
static inline bool mtk_ddp_comp_remove(struct mtk_ddp_comp *comp, struct mtk_mutex *mutex)
{
if (comp->funcs && comp->funcs->remove) {
comp->funcs->remove(comp->dev, mutex);
return true;
}
return false;
}
static inline bool mtk_ddp_comp_connect(struct mtk_ddp_comp *comp, struct device *mmsys_dev,
unsigned int next)
{
if (comp->funcs && comp->funcs->connect) {
comp->funcs->connect(comp->dev, mmsys_dev, next);
return true;
}
return false;
}
static inline bool mtk_ddp_comp_disconnect(struct mtk_ddp_comp *comp, struct device *mmsys_dev,
unsigned int next)
{
if (comp->funcs && comp->funcs->disconnect) {
comp->funcs->disconnect(comp->dev, mmsys_dev, next);
return true;
}
return false;
}
int mtk_ddp_comp_get_id(struct device_node *node, int mtk_ddp_comp_get_id(struct device_node *node,
enum mtk_ddp_comp_type comp_type); enum mtk_ddp_comp_type comp_type);
unsigned int mtk_drm_find_possible_crtc_by_comp(struct drm_device *drm, unsigned int mtk_drm_find_possible_crtc_by_comp(struct drm_device *drm,
struct device *dev); struct device *dev);
int mtk_ddp_comp_init(struct device_node *comp_node, struct mtk_ddp_comp *comp, int mtk_ddp_comp_init(struct device_node *comp_node, struct mtk_ddp_comp *comp,
enum mtk_ddp_comp_id comp_id); unsigned int comp_id);
enum mtk_ddp_comp_type mtk_ddp_comp_get_type(enum mtk_ddp_comp_id comp_id); enum mtk_ddp_comp_type mtk_ddp_comp_get_type(unsigned int comp_id);
void mtk_ddp_write(struct cmdq_pkt *cmdq_pkt, unsigned int value, void mtk_ddp_write(struct cmdq_pkt *cmdq_pkt, unsigned int value,
struct cmdq_client_reg *cmdq_reg, void __iomem *regs, struct cmdq_client_reg *cmdq_reg, void __iomem *regs,
unsigned int offset); unsigned int offset);
......
...@@ -4,8 +4,6 @@ ...@@ -4,8 +4,6 @@
* Author: YT SHEN <yt.shen@mediatek.com> * Author: YT SHEN <yt.shen@mediatek.com>
*/ */
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/component.h> #include <linux/component.h>
#include <linux/iommu.h> #include <linux/iommu.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -60,7 +58,7 @@ static const struct drm_mode_config_funcs mtk_drm_mode_config_funcs = { ...@@ -60,7 +58,7 @@ static const struct drm_mode_config_funcs mtk_drm_mode_config_funcs = {
.atomic_commit = drm_atomic_helper_commit, .atomic_commit = drm_atomic_helper_commit,
}; };
static const enum mtk_ddp_comp_id mt2701_mtk_ddp_main[] = { static const unsigned int mt2701_mtk_ddp_main[] = {
DDP_COMPONENT_OVL0, DDP_COMPONENT_OVL0,
DDP_COMPONENT_RDMA0, DDP_COMPONENT_RDMA0,
DDP_COMPONENT_COLOR0, DDP_COMPONENT_COLOR0,
...@@ -68,12 +66,12 @@ static const enum mtk_ddp_comp_id mt2701_mtk_ddp_main[] = { ...@@ -68,12 +66,12 @@ static const enum mtk_ddp_comp_id mt2701_mtk_ddp_main[] = {
DDP_COMPONENT_DSI0, DDP_COMPONENT_DSI0,
}; };
static const enum mtk_ddp_comp_id mt2701_mtk_ddp_ext[] = { static const unsigned int mt2701_mtk_ddp_ext[] = {
DDP_COMPONENT_RDMA1, DDP_COMPONENT_RDMA1,
DDP_COMPONENT_DPI0, DDP_COMPONENT_DPI0,
}; };
static const enum mtk_ddp_comp_id mt7623_mtk_ddp_main[] = { static const unsigned int mt7623_mtk_ddp_main[] = {
DDP_COMPONENT_OVL0, DDP_COMPONENT_OVL0,
DDP_COMPONENT_RDMA0, DDP_COMPONENT_RDMA0,
DDP_COMPONENT_COLOR0, DDP_COMPONENT_COLOR0,
...@@ -81,12 +79,12 @@ static const enum mtk_ddp_comp_id mt7623_mtk_ddp_main[] = { ...@@ -81,12 +79,12 @@ static const enum mtk_ddp_comp_id mt7623_mtk_ddp_main[] = {
DDP_COMPONENT_DPI0, DDP_COMPONENT_DPI0,
}; };
static const enum mtk_ddp_comp_id mt7623_mtk_ddp_ext[] = { static const unsigned int mt7623_mtk_ddp_ext[] = {
DDP_COMPONENT_RDMA1, DDP_COMPONENT_RDMA1,
DDP_COMPONENT_DSI0, DDP_COMPONENT_DSI0,
}; };
static const enum mtk_ddp_comp_id mt2712_mtk_ddp_main[] = { static const unsigned int mt2712_mtk_ddp_main[] = {
DDP_COMPONENT_OVL0, DDP_COMPONENT_OVL0,
DDP_COMPONENT_COLOR0, DDP_COMPONENT_COLOR0,
DDP_COMPONENT_AAL0, DDP_COMPONENT_AAL0,
...@@ -96,7 +94,7 @@ static const enum mtk_ddp_comp_id mt2712_mtk_ddp_main[] = { ...@@ -96,7 +94,7 @@ static const enum mtk_ddp_comp_id mt2712_mtk_ddp_main[] = {
DDP_COMPONENT_PWM0, DDP_COMPONENT_PWM0,
}; };
static const enum mtk_ddp_comp_id mt2712_mtk_ddp_ext[] = { static const unsigned int mt2712_mtk_ddp_ext[] = {
DDP_COMPONENT_OVL1, DDP_COMPONENT_OVL1,
DDP_COMPONENT_COLOR1, DDP_COMPONENT_COLOR1,
DDP_COMPONENT_AAL1, DDP_COMPONENT_AAL1,
...@@ -106,13 +104,13 @@ static const enum mtk_ddp_comp_id mt2712_mtk_ddp_ext[] = { ...@@ -106,13 +104,13 @@ static const enum mtk_ddp_comp_id mt2712_mtk_ddp_ext[] = {
DDP_COMPONENT_PWM1, DDP_COMPONENT_PWM1,
}; };
static const enum mtk_ddp_comp_id mt2712_mtk_ddp_third[] = { static const unsigned int mt2712_mtk_ddp_third[] = {
DDP_COMPONENT_RDMA2, DDP_COMPONENT_RDMA2,
DDP_COMPONENT_DSI3, DDP_COMPONENT_DSI3,
DDP_COMPONENT_PWM2, DDP_COMPONENT_PWM2,
}; };
static enum mtk_ddp_comp_id mt8167_mtk_ddp_main[] = { static unsigned int mt8167_mtk_ddp_main[] = {
DDP_COMPONENT_OVL0, DDP_COMPONENT_OVL0,
DDP_COMPONENT_COLOR0, DDP_COMPONENT_COLOR0,
DDP_COMPONENT_CCORR, DDP_COMPONENT_CCORR,
...@@ -123,7 +121,7 @@ static enum mtk_ddp_comp_id mt8167_mtk_ddp_main[] = { ...@@ -123,7 +121,7 @@ static enum mtk_ddp_comp_id mt8167_mtk_ddp_main[] = {
DDP_COMPONENT_DSI0, DDP_COMPONENT_DSI0,
}; };
static const enum mtk_ddp_comp_id mt8173_mtk_ddp_main[] = { static const unsigned int mt8173_mtk_ddp_main[] = {
DDP_COMPONENT_OVL0, DDP_COMPONENT_OVL0,
DDP_COMPONENT_COLOR0, DDP_COMPONENT_COLOR0,
DDP_COMPONENT_AAL0, DDP_COMPONENT_AAL0,
...@@ -134,7 +132,7 @@ static const enum mtk_ddp_comp_id mt8173_mtk_ddp_main[] = { ...@@ -134,7 +132,7 @@ static const enum mtk_ddp_comp_id mt8173_mtk_ddp_main[] = {
DDP_COMPONENT_PWM0, DDP_COMPONENT_PWM0,
}; };
static const enum mtk_ddp_comp_id mt8173_mtk_ddp_ext[] = { static const unsigned int mt8173_mtk_ddp_ext[] = {
DDP_COMPONENT_OVL1, DDP_COMPONENT_OVL1,
DDP_COMPONENT_COLOR1, DDP_COMPONENT_COLOR1,
DDP_COMPONENT_GAMMA, DDP_COMPONENT_GAMMA,
...@@ -142,7 +140,7 @@ static const enum mtk_ddp_comp_id mt8173_mtk_ddp_ext[] = { ...@@ -142,7 +140,7 @@ static const enum mtk_ddp_comp_id mt8173_mtk_ddp_ext[] = {
DDP_COMPONENT_DPI0, DDP_COMPONENT_DPI0,
}; };
static const enum mtk_ddp_comp_id mt8183_mtk_ddp_main[] = { static const unsigned int mt8183_mtk_ddp_main[] = {
DDP_COMPONENT_OVL0, DDP_COMPONENT_OVL0,
DDP_COMPONENT_OVL_2L0, DDP_COMPONENT_OVL_2L0,
DDP_COMPONENT_RDMA0, DDP_COMPONENT_RDMA0,
...@@ -154,13 +152,13 @@ static const enum mtk_ddp_comp_id mt8183_mtk_ddp_main[] = { ...@@ -154,13 +152,13 @@ static const enum mtk_ddp_comp_id mt8183_mtk_ddp_main[] = {
DDP_COMPONENT_DSI0, DDP_COMPONENT_DSI0,
}; };
static const enum mtk_ddp_comp_id mt8183_mtk_ddp_ext[] = { static const unsigned int mt8183_mtk_ddp_ext[] = {
DDP_COMPONENT_OVL_2L1, DDP_COMPONENT_OVL_2L1,
DDP_COMPONENT_RDMA1, DDP_COMPONENT_RDMA1,
DDP_COMPONENT_DPI0, DDP_COMPONENT_DPI0,
}; };
static const enum mtk_ddp_comp_id mt8186_mtk_ddp_main[] = { static const unsigned int mt8186_mtk_ddp_main[] = {
DDP_COMPONENT_OVL0, DDP_COMPONENT_OVL0,
DDP_COMPONENT_RDMA0, DDP_COMPONENT_RDMA0,
DDP_COMPONENT_COLOR0, DDP_COMPONENT_COLOR0,
...@@ -172,13 +170,25 @@ static const enum mtk_ddp_comp_id mt8186_mtk_ddp_main[] = { ...@@ -172,13 +170,25 @@ static const enum mtk_ddp_comp_id mt8186_mtk_ddp_main[] = {
DDP_COMPONENT_DSI0, DDP_COMPONENT_DSI0,
}; };
static const enum mtk_ddp_comp_id mt8186_mtk_ddp_ext[] = { static const unsigned int mt8186_mtk_ddp_ext[] = {
DDP_COMPONENT_OVL_2L0, DDP_COMPONENT_OVL_2L0,
DDP_COMPONENT_RDMA1, DDP_COMPONENT_RDMA1,
DDP_COMPONENT_DPI0, DDP_COMPONENT_DPI0,
}; };
static const enum mtk_ddp_comp_id mt8192_mtk_ddp_main[] = { static const unsigned int mt8188_mtk_ddp_main[] = {
DDP_COMPONENT_OVL0,
DDP_COMPONENT_RDMA0,
DDP_COMPONENT_COLOR0,
DDP_COMPONENT_CCORR,
DDP_COMPONENT_AAL0,
DDP_COMPONENT_GAMMA,
DDP_COMPONENT_POSTMASK0,
DDP_COMPONENT_DITHER0,
DDP_COMPONENT_DP_INTF0,
};
static const unsigned int mt8192_mtk_ddp_main[] = {
DDP_COMPONENT_OVL0, DDP_COMPONENT_OVL0,
DDP_COMPONENT_OVL_2L0, DDP_COMPONENT_OVL_2L0,
DDP_COMPONENT_RDMA0, DDP_COMPONENT_RDMA0,
...@@ -191,13 +201,13 @@ static const enum mtk_ddp_comp_id mt8192_mtk_ddp_main[] = { ...@@ -191,13 +201,13 @@ static const enum mtk_ddp_comp_id mt8192_mtk_ddp_main[] = {
DDP_COMPONENT_DSI0, DDP_COMPONENT_DSI0,
}; };
static const enum mtk_ddp_comp_id mt8192_mtk_ddp_ext[] = { static const unsigned int mt8192_mtk_ddp_ext[] = {
DDP_COMPONENT_OVL_2L2, DDP_COMPONENT_OVL_2L2,
DDP_COMPONENT_RDMA4, DDP_COMPONENT_RDMA4,
DDP_COMPONENT_DPI0, DDP_COMPONENT_DPI0,
}; };
static const enum mtk_ddp_comp_id mt8195_mtk_ddp_main[] = { static const unsigned int mt8195_mtk_ddp_main[] = {
DDP_COMPONENT_OVL0, DDP_COMPONENT_OVL0,
DDP_COMPONENT_RDMA0, DDP_COMPONENT_RDMA0,
DDP_COMPONENT_COLOR0, DDP_COMPONENT_COLOR0,
...@@ -210,19 +220,19 @@ static const enum mtk_ddp_comp_id mt8195_mtk_ddp_main[] = { ...@@ -210,19 +220,19 @@ static const enum mtk_ddp_comp_id mt8195_mtk_ddp_main[] = {
DDP_COMPONENT_DP_INTF0, DDP_COMPONENT_DP_INTF0,
}; };
static const unsigned int mt8195_mtk_ddp_ext[] = {
DDP_COMPONENT_DRM_OVL_ADAPTOR,
DDP_COMPONENT_MERGE5,
DDP_COMPONENT_DP_INTF1,
};
static const struct mtk_mmsys_driver_data mt2701_mmsys_driver_data = { static const struct mtk_mmsys_driver_data mt2701_mmsys_driver_data = {
.main_path = mt2701_mtk_ddp_main, .main_path = mt2701_mtk_ddp_main,
.main_len = ARRAY_SIZE(mt2701_mtk_ddp_main), .main_len = ARRAY_SIZE(mt2701_mtk_ddp_main),
.ext_path = mt2701_mtk_ddp_ext, .ext_path = mt2701_mtk_ddp_ext,
.ext_len = ARRAY_SIZE(mt2701_mtk_ddp_ext), .ext_len = ARRAY_SIZE(mt2701_mtk_ddp_ext),
.shadow_register = true, .shadow_register = true,
}; .mmsys_dev_num = 1,
static const struct mtk_mmsys_match_data mt2701_mmsys_match_data = {
.num_drv_data = 1,
.drv_data = {
&mt2701_mmsys_driver_data,
},
}; };
static const struct mtk_mmsys_driver_data mt7623_mmsys_driver_data = { static const struct mtk_mmsys_driver_data mt7623_mmsys_driver_data = {
...@@ -231,13 +241,7 @@ static const struct mtk_mmsys_driver_data mt7623_mmsys_driver_data = { ...@@ -231,13 +241,7 @@ static const struct mtk_mmsys_driver_data mt7623_mmsys_driver_data = {
.ext_path = mt7623_mtk_ddp_ext, .ext_path = mt7623_mtk_ddp_ext,
.ext_len = ARRAY_SIZE(mt7623_mtk_ddp_ext), .ext_len = ARRAY_SIZE(mt7623_mtk_ddp_ext),
.shadow_register = true, .shadow_register = true,
}; .mmsys_dev_num = 1,
static const struct mtk_mmsys_match_data mt7623_mmsys_match_data = {
.num_drv_data = 1,
.drv_data = {
&mt7623_mmsys_driver_data,
},
}; };
static const struct mtk_mmsys_driver_data mt2712_mmsys_driver_data = { static const struct mtk_mmsys_driver_data mt2712_mmsys_driver_data = {
...@@ -247,25 +251,13 @@ static const struct mtk_mmsys_driver_data mt2712_mmsys_driver_data = { ...@@ -247,25 +251,13 @@ static const struct mtk_mmsys_driver_data mt2712_mmsys_driver_data = {
.ext_len = ARRAY_SIZE(mt2712_mtk_ddp_ext), .ext_len = ARRAY_SIZE(mt2712_mtk_ddp_ext),
.third_path = mt2712_mtk_ddp_third, .third_path = mt2712_mtk_ddp_third,
.third_len = ARRAY_SIZE(mt2712_mtk_ddp_third), .third_len = ARRAY_SIZE(mt2712_mtk_ddp_third),
}; .mmsys_dev_num = 1,
static const struct mtk_mmsys_match_data mt2712_mmsys_match_data = {
.num_drv_data = 1,
.drv_data = {
&mt2712_mmsys_driver_data,
},
}; };
static const struct mtk_mmsys_driver_data mt8167_mmsys_driver_data = { static const struct mtk_mmsys_driver_data mt8167_mmsys_driver_data = {
.main_path = mt8167_mtk_ddp_main, .main_path = mt8167_mtk_ddp_main,
.main_len = ARRAY_SIZE(mt8167_mtk_ddp_main), .main_len = ARRAY_SIZE(mt8167_mtk_ddp_main),
}; .mmsys_dev_num = 1,
static const struct mtk_mmsys_match_data mt8167_mmsys_match_data = {
.num_drv_data = 1,
.drv_data = {
&mt8167_mmsys_driver_data,
},
}; };
static const struct mtk_mmsys_driver_data mt8173_mmsys_driver_data = { static const struct mtk_mmsys_driver_data mt8173_mmsys_driver_data = {
...@@ -273,13 +265,7 @@ static const struct mtk_mmsys_driver_data mt8173_mmsys_driver_data = { ...@@ -273,13 +265,7 @@ static const struct mtk_mmsys_driver_data mt8173_mmsys_driver_data = {
.main_len = ARRAY_SIZE(mt8173_mtk_ddp_main), .main_len = ARRAY_SIZE(mt8173_mtk_ddp_main),
.ext_path = mt8173_mtk_ddp_ext, .ext_path = mt8173_mtk_ddp_ext,
.ext_len = ARRAY_SIZE(mt8173_mtk_ddp_ext), .ext_len = ARRAY_SIZE(mt8173_mtk_ddp_ext),
}; .mmsys_dev_num = 1,
static const struct mtk_mmsys_match_data mt8173_mmsys_match_data = {
.num_drv_data = 1,
.drv_data = {
&mt8173_mmsys_driver_data,
},
}; };
static const struct mtk_mmsys_driver_data mt8183_mmsys_driver_data = { static const struct mtk_mmsys_driver_data mt8183_mmsys_driver_data = {
...@@ -287,13 +273,7 @@ static const struct mtk_mmsys_driver_data mt8183_mmsys_driver_data = { ...@@ -287,13 +273,7 @@ static const struct mtk_mmsys_driver_data mt8183_mmsys_driver_data = {
.main_len = ARRAY_SIZE(mt8183_mtk_ddp_main), .main_len = ARRAY_SIZE(mt8183_mtk_ddp_main),
.ext_path = mt8183_mtk_ddp_ext, .ext_path = mt8183_mtk_ddp_ext,
.ext_len = ARRAY_SIZE(mt8183_mtk_ddp_ext), .ext_len = ARRAY_SIZE(mt8183_mtk_ddp_ext),
}; .mmsys_dev_num = 1,
static const struct mtk_mmsys_match_data mt8183_mmsys_match_data = {
.num_drv_data = 1,
.drv_data = {
&mt8183_mmsys_driver_data,
},
}; };
static const struct mtk_mmsys_driver_data mt8186_mmsys_driver_data = { static const struct mtk_mmsys_driver_data mt8186_mmsys_driver_data = {
...@@ -301,13 +281,12 @@ static const struct mtk_mmsys_driver_data mt8186_mmsys_driver_data = { ...@@ -301,13 +281,12 @@ static const struct mtk_mmsys_driver_data mt8186_mmsys_driver_data = {
.main_len = ARRAY_SIZE(mt8186_mtk_ddp_main), .main_len = ARRAY_SIZE(mt8186_mtk_ddp_main),
.ext_path = mt8186_mtk_ddp_ext, .ext_path = mt8186_mtk_ddp_ext,
.ext_len = ARRAY_SIZE(mt8186_mtk_ddp_ext), .ext_len = ARRAY_SIZE(mt8186_mtk_ddp_ext),
.mmsys_dev_num = 1,
}; };
static const struct mtk_mmsys_match_data mt8186_mmsys_match_data = { static const struct mtk_mmsys_driver_data mt8188_vdosys0_driver_data = {
.num_drv_data = 1, .main_path = mt8188_mtk_ddp_main,
.drv_data = { .main_len = ARRAY_SIZE(mt8188_mtk_ddp_main),
&mt8186_mmsys_driver_data,
},
}; };
static const struct mtk_mmsys_driver_data mt8192_mmsys_driver_data = { static const struct mtk_mmsys_driver_data mt8192_mmsys_driver_data = {
...@@ -315,55 +294,132 @@ static const struct mtk_mmsys_driver_data mt8192_mmsys_driver_data = { ...@@ -315,55 +294,132 @@ static const struct mtk_mmsys_driver_data mt8192_mmsys_driver_data = {
.main_len = ARRAY_SIZE(mt8192_mtk_ddp_main), .main_len = ARRAY_SIZE(mt8192_mtk_ddp_main),
.ext_path = mt8192_mtk_ddp_ext, .ext_path = mt8192_mtk_ddp_ext,
.ext_len = ARRAY_SIZE(mt8192_mtk_ddp_ext), .ext_len = ARRAY_SIZE(mt8192_mtk_ddp_ext),
}; .mmsys_dev_num = 1,
static const struct mtk_mmsys_match_data mt8192_mmsys_match_data = {
.num_drv_data = 1,
.drv_data = {
&mt8192_mmsys_driver_data,
},
}; };
static const struct mtk_mmsys_driver_data mt8195_vdosys0_driver_data = { static const struct mtk_mmsys_driver_data mt8195_vdosys0_driver_data = {
.io_start = 0x1c01a000,
.main_path = mt8195_mtk_ddp_main, .main_path = mt8195_mtk_ddp_main,
.main_len = ARRAY_SIZE(mt8195_mtk_ddp_main), .main_len = ARRAY_SIZE(mt8195_mtk_ddp_main),
.mmsys_dev_num = 2,
}; };
static const struct mtk_mmsys_driver_data mt8195_vdosys1_driver_data = { static const struct mtk_mmsys_driver_data mt8195_vdosys1_driver_data = {
.io_start = 0x1c100000, .ext_path = mt8195_mtk_ddp_ext,
.ext_len = ARRAY_SIZE(mt8195_mtk_ddp_ext),
.mmsys_id = 1,
.mmsys_dev_num = 2,
}; };
static const struct mtk_mmsys_match_data mt8195_mmsys_match_data = { static const struct of_device_id mtk_drm_of_ids[] = {
.num_drv_data = 1, { .compatible = "mediatek,mt2701-mmsys",
.drv_data = { .data = &mt2701_mmsys_driver_data},
&mt8195_vdosys0_driver_data, { .compatible = "mediatek,mt7623-mmsys",
&mt8195_vdosys1_driver_data, .data = &mt7623_mmsys_driver_data},
}, { .compatible = "mediatek,mt2712-mmsys",
.data = &mt2712_mmsys_driver_data},
{ .compatible = "mediatek,mt8167-mmsys",
.data = &mt8167_mmsys_driver_data},
{ .compatible = "mediatek,mt8173-mmsys",
.data = &mt8173_mmsys_driver_data},
{ .compatible = "mediatek,mt8183-mmsys",
.data = &mt8183_mmsys_driver_data},
{ .compatible = "mediatek,mt8186-mmsys",
.data = &mt8186_mmsys_driver_data},
{ .compatible = "mediatek,mt8188-vdosys0",
.data = &mt8188_vdosys0_driver_data},
{ .compatible = "mediatek,mt8192-mmsys",
.data = &mt8192_mmsys_driver_data},
{ .compatible = "mediatek,mt8195-mmsys",
.data = &mt8195_vdosys0_driver_data},
{ .compatible = "mediatek,mt8195-vdosys0",
.data = &mt8195_vdosys0_driver_data},
{ .compatible = "mediatek,mt8195-vdosys1",
.data = &mt8195_vdosys1_driver_data},
{ }
}; };
MODULE_DEVICE_TABLE(of, mtk_drm_of_ids);
static int mtk_drm_kms_init(struct drm_device *drm) static int mtk_drm_match(struct device *dev, void *data)
{ {
struct mtk_drm_private *private = drm->dev_private; if (!strncmp(dev_name(dev), "mediatek-drm", sizeof("mediatek-drm") - 1))
return true;
return false;
}
static bool mtk_drm_get_all_drm_priv(struct device *dev)
{
struct mtk_drm_private *drm_priv = dev_get_drvdata(dev);
struct mtk_drm_private *all_drm_priv[MAX_CRTC];
struct device_node *phandle = dev->parent->of_node;
const struct of_device_id *of_id;
struct device_node *node;
struct device *drm_dev;
int cnt = 0;
int i, j;
for_each_child_of_node(phandle->parent, node) {
struct platform_device *pdev; struct platform_device *pdev;
struct device_node *np;
struct device *dma_dev;
int ret;
if (drm_firmware_drivers_only()) of_id = of_match_node(mtk_drm_of_ids, node);
return -ENODEV; if (!of_id)
continue;
if (!iommu_present(&platform_bus_type)) pdev = of_find_device_by_node(node);
return -EPROBE_DEFER; if (!pdev)
continue;
pdev = of_find_device_by_node(private->mutex_node); drm_dev = device_find_child(&pdev->dev, NULL, mtk_drm_match);
if (!pdev) { if (!drm_dev || !dev_get_drvdata(drm_dev))
dev_err(drm->dev, "Waiting for disp-mutex device %pOF\n", continue;
private->mutex_node);
of_node_put(private->mutex_node); all_drm_priv[cnt] = dev_get_drvdata(drm_dev);
return -EPROBE_DEFER; if (all_drm_priv[cnt] && all_drm_priv[cnt]->mtk_drm_bound)
cnt++;
} }
private->mutex_dev = &pdev->dev;
if (drm_priv->data->mmsys_dev_num == cnt) {
for (i = 0; i < cnt; i++)
for (j = 0; j < cnt; j++)
all_drm_priv[j]->all_drm_private[i] = all_drm_priv[i];
return true;
}
return false;
}
static bool mtk_drm_find_mmsys_comp(struct mtk_drm_private *private, int comp_id)
{
const struct mtk_mmsys_driver_data *drv_data = private->data;
int i;
if (drv_data->main_path)
for (i = 0; i < drv_data->main_len; i++)
if (drv_data->main_path[i] == comp_id)
return true;
if (drv_data->ext_path)
for (i = 0; i < drv_data->ext_len; i++)
if (drv_data->ext_path[i] == comp_id)
return true;
if (drv_data->third_path)
for (i = 0; i < drv_data->third_len; i++)
if (drv_data->third_path[i] == comp_id)
return true;
return false;
}
static int mtk_drm_kms_init(struct drm_device *drm)
{
struct mtk_drm_private *private = drm->dev_private;
struct mtk_drm_private *priv_n;
struct device *dma_dev = NULL;
int ret, i, j;
if (drm_firmware_drivers_only())
return -ENODEV;
ret = drmm_mode_config_init(drm); ret = drmm_mode_config_init(drm);
if (ret) if (ret)
...@@ -382,9 +438,12 @@ static int mtk_drm_kms_init(struct drm_device *drm) ...@@ -382,9 +438,12 @@ static int mtk_drm_kms_init(struct drm_device *drm)
drm->mode_config.funcs = &mtk_drm_mode_config_funcs; drm->mode_config.funcs = &mtk_drm_mode_config_funcs;
drm->mode_config.helper_private = &mtk_drm_mode_config_helpers; drm->mode_config.helper_private = &mtk_drm_mode_config_helpers;
ret = component_bind_all(drm->dev, drm); for (i = 0; i < private->data->mmsys_dev_num; i++) {
drm->dev_private = private->all_drm_private[i];
ret = component_bind_all(private->all_drm_private[i]->dev, drm);
if (ret) if (ret)
goto put_mutex_dev; goto put_mutex_dev;
}
/* /*
* Ensure internal panels are at the top of the connector list before * Ensure internal panels are at the top of the connector list before
...@@ -393,37 +452,53 @@ static int mtk_drm_kms_init(struct drm_device *drm) ...@@ -393,37 +452,53 @@ static int mtk_drm_kms_init(struct drm_device *drm)
drm_helper_move_panel_connectors_to_head(drm); drm_helper_move_panel_connectors_to_head(drm);
/* /*
* We currently support two fixed data streams, each optional, * 1. We currently support two fixed data streams, each optional,
* and each statically assigned to a crtc: * and each statically assigned to a crtc:
* OVL0 -> COLOR0 -> AAL -> OD -> RDMA0 -> UFOE -> DSI0 ... * OVL0 -> COLOR0 -> AAL -> OD -> RDMA0 -> UFOE -> DSI0 ...
* 2. For multi mmsys architecture, crtc path data are located in
* different drm private data structures. Loop through crtc index to
* create crtc from the main path and then ext_path and finally the
* third path.
*/ */
ret = mtk_drm_crtc_create(drm, private->data->main_path, for (i = 0; i < MAX_CRTC; i++) {
private->data->main_len); for (j = 0; j < private->data->mmsys_dev_num; j++) {
if (ret < 0) priv_n = private->all_drm_private[j];
if (i == 0 && priv_n->data->main_len) {
ret = mtk_drm_crtc_create(drm, priv_n->data->main_path,
priv_n->data->main_len, j);
if (ret)
goto err_component_unbind; goto err_component_unbind;
/* ... and OVL1 -> COLOR1 -> GAMMA -> RDMA1 -> DPI0. */
ret = mtk_drm_crtc_create(drm, private->data->ext_path, continue;
private->data->ext_len); } else if (i == 1 && priv_n->data->ext_len) {
if (ret < 0) ret = mtk_drm_crtc_create(drm, priv_n->data->ext_path,
priv_n->data->ext_len, j);
if (ret)
goto err_component_unbind; goto err_component_unbind;
ret = mtk_drm_crtc_create(drm, private->data->third_path, continue;
private->data->third_len); } else if (i == 2 && priv_n->data->third_len) {
if (ret < 0) ret = mtk_drm_crtc_create(drm, priv_n->data->third_path,
priv_n->data->third_len, j);
if (ret)
goto err_component_unbind; goto err_component_unbind;
continue;
}
}
}
/* Use OVL device for all DMA memory allocations */ /* Use OVL device for all DMA memory allocations */
np = private->comp_node[private->data->main_path[0]] ?: dma_dev = mtk_drm_crtc_dma_dev_get(drm_crtc_from_index(drm, 0));
private->comp_node[private->data->ext_path[0]]; if (!dma_dev) {
pdev = of_find_device_by_node(np);
if (!pdev) {
ret = -ENODEV; ret = -ENODEV;
dev_err(drm->dev, "Need at least one OVL device\n"); dev_err(drm->dev, "Need at least one OVL device\n");
goto err_component_unbind; goto err_component_unbind;
} }
dma_dev = &pdev->dev; for (i = 0; i < private->data->mmsys_dev_num; i++)
private->dma_dev = dma_dev; private->all_drm_private[i]->dma_dev = dma_dev;
/* /*
* Configure the DMA segment size to make sure we get contiguous IOVA * Configure the DMA segment size to make sure we get contiguous IOVA
...@@ -445,9 +520,12 @@ static int mtk_drm_kms_init(struct drm_device *drm) ...@@ -445,9 +520,12 @@ static int mtk_drm_kms_init(struct drm_device *drm)
return 0; return 0;
err_component_unbind: err_component_unbind:
component_unbind_all(drm->dev, drm); for (i = 0; i < private->data->mmsys_dev_num; i++)
component_unbind_all(private->all_drm_private[i]->dev, drm);
put_mutex_dev: put_mutex_dev:
put_device(private->mutex_dev); for (i = 0; i < private->data->mmsys_dev_num; i++)
put_device(private->all_drm_private[i]->mutex_dev);
return ret; return ret;
} }
...@@ -492,18 +570,44 @@ static const struct drm_driver mtk_drm_driver = { ...@@ -492,18 +570,44 @@ static const struct drm_driver mtk_drm_driver = {
.minor = DRIVER_MINOR, .minor = DRIVER_MINOR,
}; };
static int compare_dev(struct device *dev, void *data)
{
return dev == (struct device *)data;
}
static int mtk_drm_bind(struct device *dev) static int mtk_drm_bind(struct device *dev)
{ {
struct mtk_drm_private *private = dev_get_drvdata(dev); struct mtk_drm_private *private = dev_get_drvdata(dev);
struct platform_device *pdev;
struct drm_device *drm; struct drm_device *drm;
int ret; int ret, i;
if (!iommu_present(&platform_bus_type))
return -EPROBE_DEFER;
pdev = of_find_device_by_node(private->mutex_node);
if (!pdev) {
dev_err(dev, "Waiting for disp-mutex device %pOF\n",
private->mutex_node);
of_node_put(private->mutex_node);
return -EPROBE_DEFER;
}
private->mutex_dev = &pdev->dev;
private->mtk_drm_bound = true;
private->dev = dev;
if (!mtk_drm_get_all_drm_priv(dev))
return 0;
drm = drm_dev_alloc(&mtk_drm_driver, dev); drm = drm_dev_alloc(&mtk_drm_driver, dev);
if (IS_ERR(drm)) if (IS_ERR(drm))
return PTR_ERR(drm); return PTR_ERR(drm);
private->drm_master = true;
drm->dev_private = private; drm->dev_private = private;
private->drm = drm; for (i = 0; i < private->data->mmsys_dev_num; i++)
private->all_drm_private[i]->drm = drm;
ret = mtk_drm_kms_init(drm); ret = mtk_drm_kms_init(drm);
if (ret < 0) if (ret < 0)
...@@ -529,10 +633,14 @@ static void mtk_drm_unbind(struct device *dev) ...@@ -529,10 +633,14 @@ static void mtk_drm_unbind(struct device *dev)
{ {
struct mtk_drm_private *private = dev_get_drvdata(dev); struct mtk_drm_private *private = dev_get_drvdata(dev);
/* for multi mmsys dev, unregister drm dev in mmsys master */
if (private->drm_master) {
drm_dev_unregister(private->drm); drm_dev_unregister(private->drm);
mtk_drm_kms_deinit(private->drm); mtk_drm_kms_deinit(private->drm);
drm_dev_put(private->drm); drm_dev_put(private->drm);
private->num_pipes = 0; }
private->mtk_drm_bound = false;
private->drm_master = false;
private->drm = NULL; private->drm = NULL;
} }
...@@ -588,6 +696,8 @@ static const struct of_device_id mtk_ddp_comp_dt_ids[] = { ...@@ -588,6 +696,8 @@ static const struct of_device_id mtk_ddp_comp_dt_ids[] = {
.data = (void *)MTK_DISP_MUTEX }, .data = (void *)MTK_DISP_MUTEX },
{ .compatible = "mediatek,mt8186-disp-mutex", { .compatible = "mediatek,mt8186-disp-mutex",
.data = (void *)MTK_DISP_MUTEX }, .data = (void *)MTK_DISP_MUTEX },
{ .compatible = "mediatek,mt8188-disp-mutex",
.data = (void *)MTK_DISP_MUTEX },
{ .compatible = "mediatek,mt8192-disp-mutex", { .compatible = "mediatek,mt8192-disp-mutex",
.data = (void *)MTK_DISP_MUTEX }, .data = (void *)MTK_DISP_MUTEX },
{ .compatible = "mediatek,mt8195-disp-mutex", { .compatible = "mediatek,mt8195-disp-mutex",
...@@ -657,58 +767,15 @@ static const struct of_device_id mtk_ddp_comp_dt_ids[] = { ...@@ -657,58 +767,15 @@ static const struct of_device_id mtk_ddp_comp_dt_ids[] = {
{ } { }
}; };
static const struct of_device_id mtk_drm_of_ids[] = {
{ .compatible = "mediatek,mt2701-mmsys",
.data = &mt2701_mmsys_match_data},
{ .compatible = "mediatek,mt7623-mmsys",
.data = &mt7623_mmsys_match_data},
{ .compatible = "mediatek,mt2712-mmsys",
.data = &mt2712_mmsys_match_data},
{ .compatible = "mediatek,mt8167-mmsys",
.data = &mt8167_mmsys_match_data},
{ .compatible = "mediatek,mt8173-mmsys",
.data = &mt8173_mmsys_match_data},
{ .compatible = "mediatek,mt8183-mmsys",
.data = &mt8183_mmsys_match_data},
{ .compatible = "mediatek,mt8186-mmsys",
.data = &mt8186_mmsys_match_data},
{ .compatible = "mediatek,mt8192-mmsys",
.data = &mt8192_mmsys_match_data},
{ .compatible = "mediatek,mt8195-mmsys",
.data = &mt8195_mmsys_match_data},
{ }
};
MODULE_DEVICE_TABLE(of, mtk_drm_of_ids);
static int mtk_drm_find_match_data(struct device *dev,
const struct mtk_mmsys_match_data *match_data)
{
int i;
struct platform_device *pdev = of_find_device_by_node(dev->parent->of_node);
struct resource *res;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(dev, "failed to get parent resource\n");
return -EINVAL;
}
for (i = 0; i < match_data->num_drv_data; i++)
if (match_data->drv_data[i]->io_start == res->start)
return i;
return -EINVAL;
}
static int mtk_drm_probe(struct platform_device *pdev) static int mtk_drm_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct device_node *phandle = dev->parent->of_node; struct device_node *phandle = dev->parent->of_node;
const struct of_device_id *of_id; const struct of_device_id *of_id;
const struct mtk_mmsys_match_data *match_data;
struct mtk_drm_private *private; struct mtk_drm_private *private;
struct device_node *node; struct device_node *node;
struct component_match *match = NULL; struct component_match *match = NULL;
struct platform_device *ovl_adaptor;
int ret; int ret;
int i; int i;
...@@ -726,18 +793,24 @@ static int mtk_drm_probe(struct platform_device *pdev) ...@@ -726,18 +793,24 @@ static int mtk_drm_probe(struct platform_device *pdev)
if (!of_id) if (!of_id)
return -ENODEV; return -ENODEV;
match_data = of_id->data; private->data = of_id->data;
if (match_data->num_drv_data > 1) {
/* This SoC has multiple mmsys channels */ private->all_drm_private = devm_kmalloc_array(dev, private->data->mmsys_dev_num,
ret = mtk_drm_find_match_data(dev, match_data); sizeof(*private->all_drm_private),
if (ret < 0) { GFP_KERNEL);
dev_err(dev, "Couldn't get match driver data\n"); if (!private->all_drm_private)
return ret; return -ENOMEM;
}
private->data = match_data->drv_data[ret]; /* Bringup ovl_adaptor */
} else { if (mtk_drm_find_mmsys_comp(private, DDP_COMPONENT_DRM_OVL_ADAPTOR)) {
dev_dbg(dev, "Using single mmsys channel\n"); ovl_adaptor = platform_device_register_data(dev, "mediatek-disp-ovl-adaptor",
private->data = match_data->drv_data[0]; PLATFORM_DEVID_AUTO,
(void *)private->mmsys_dev,
sizeof(*private->mmsys_dev));
private->ddp_comp[DDP_COMPONENT_DRM_OVL_ADAPTOR].dev = &ovl_adaptor->dev;
mtk_ddp_comp_init(NULL, &private->ddp_comp[DDP_COMPONENT_DRM_OVL_ADAPTOR],
DDP_COMPONENT_DRM_OVL_ADAPTOR);
component_match_add(dev, &match, compare_dev, &ovl_adaptor->dev);
} }
/* Iterate over sibling DISP function blocks */ /* Iterate over sibling DISP function blocks */
...@@ -759,7 +832,13 @@ static int mtk_drm_probe(struct platform_device *pdev) ...@@ -759,7 +832,13 @@ static int mtk_drm_probe(struct platform_device *pdev)
comp_type = (enum mtk_ddp_comp_type)of_id->data; comp_type = (enum mtk_ddp_comp_type)of_id->data;
if (comp_type == MTK_DISP_MUTEX) { if (comp_type == MTK_DISP_MUTEX) {
int id;
id = of_alias_get_id(node, "mutex");
if (id < 0 || id == private->data->mmsys_id) {
private->mutex_node = of_node_get(node); private->mutex_node = of_node_get(node);
dev_dbg(dev, "get mutex for mmsys %d", private->data->mmsys_id);
}
continue; continue;
} }
...@@ -770,6 +849,9 @@ static int mtk_drm_probe(struct platform_device *pdev) ...@@ -770,6 +849,9 @@ static int mtk_drm_probe(struct platform_device *pdev)
continue; continue;
} }
if (!mtk_drm_find_mmsys_comp(private, comp_id))
continue;
private->comp_node[comp_id] = of_node_get(node); private->comp_node[comp_id] = of_node_get(node);
/* /*
...@@ -784,6 +866,7 @@ static int mtk_drm_probe(struct platform_device *pdev) ...@@ -784,6 +866,7 @@ static int mtk_drm_probe(struct platform_device *pdev)
comp_type == MTK_DISP_MERGE || comp_type == MTK_DISP_MERGE ||
comp_type == MTK_DISP_OVL || comp_type == MTK_DISP_OVL ||
comp_type == MTK_DISP_OVL_2L || comp_type == MTK_DISP_OVL_2L ||
comp_type == MTK_DISP_OVL_ADAPTOR ||
comp_type == MTK_DISP_RDMA || comp_type == MTK_DISP_RDMA ||
comp_type == MTK_DP_INTF || comp_type == MTK_DP_INTF ||
comp_type == MTK_DPI || comp_type == MTK_DPI ||
...@@ -821,7 +904,7 @@ static int mtk_drm_probe(struct platform_device *pdev) ...@@ -821,7 +904,7 @@ static int mtk_drm_probe(struct platform_device *pdev)
pm_runtime_disable(dev); pm_runtime_disable(dev);
err_node: err_node:
of_node_put(private->mutex_node); of_node_put(private->mutex_node);
for (i = 0; i < DDP_COMPONENT_ID_MAX; i++) for (i = 0; i < DDP_COMPONENT_DRM_ID_MAX; i++)
of_node_put(private->comp_node[i]); of_node_put(private->comp_node[i]);
return ret; return ret;
} }
...@@ -834,7 +917,7 @@ static int mtk_drm_remove(struct platform_device *pdev) ...@@ -834,7 +917,7 @@ static int mtk_drm_remove(struct platform_device *pdev)
component_master_del(&pdev->dev, &mtk_drm_ops); component_master_del(&pdev->dev, &mtk_drm_ops);
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
of_node_put(private->mutex_node); of_node_put(private->mutex_node);
for (i = 0; i < DDP_COMPONENT_ID_MAX; i++) for (i = 0; i < DDP_COMPONENT_DRM_ID_MAX; i++)
of_node_put(private->comp_node[i]); of_node_put(private->comp_node[i]);
return 0; return 0;
...@@ -845,15 +928,19 @@ static int mtk_drm_sys_prepare(struct device *dev) ...@@ -845,15 +928,19 @@ static int mtk_drm_sys_prepare(struct device *dev)
struct mtk_drm_private *private = dev_get_drvdata(dev); struct mtk_drm_private *private = dev_get_drvdata(dev);
struct drm_device *drm = private->drm; struct drm_device *drm = private->drm;
if (private->drm_master)
return drm_mode_config_helper_suspend(drm); return drm_mode_config_helper_suspend(drm);
else
return 0;
} }
static void mtk_drm_sys_complete(struct device *dev) static void mtk_drm_sys_complete(struct device *dev)
{ {
struct mtk_drm_private *private = dev_get_drvdata(dev); struct mtk_drm_private *private = dev_get_drvdata(dev);
struct drm_device *drm = private->drm; struct drm_device *drm = private->drm;
int ret; int ret = 0;
if (private->drm_master)
ret = drm_mode_config_helper_resume(drm); ret = drm_mode_config_helper_resume(drm);
if (ret) if (ret)
dev_err(dev, "Failed to resume\n"); dev_err(dev, "Failed to resume\n");
...@@ -879,11 +966,13 @@ static struct platform_driver * const mtk_drm_drivers[] = { ...@@ -879,11 +966,13 @@ static struct platform_driver * const mtk_drm_drivers[] = {
&mtk_disp_color_driver, &mtk_disp_color_driver,
&mtk_disp_gamma_driver, &mtk_disp_gamma_driver,
&mtk_disp_merge_driver, &mtk_disp_merge_driver,
&mtk_disp_ovl_adaptor_driver,
&mtk_disp_ovl_driver, &mtk_disp_ovl_driver,
&mtk_disp_rdma_driver, &mtk_disp_rdma_driver,
&mtk_dpi_driver, &mtk_dpi_driver,
&mtk_drm_platform_driver, &mtk_drm_platform_driver,
&mtk_dsi_driver, &mtk_dsi_driver,
&mtk_ethdr_driver,
&mtk_mdp_rdma_driver, &mtk_mdp_rdma_driver,
}; };
......
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
#define MAX_CRTC 3 #define MAX_CRTC 3
#define MAX_CONNECTOR 2 #define MAX_CONNECTOR 2
#define DDP_COMPONENT_DRM_OVL_ADAPTOR (DDP_COMPONENT_ID_MAX + 1)
#define DDP_COMPONENT_DRM_ID_MAX (DDP_COMPONENT_DRM_OVL_ADAPTOR + 1)
struct device; struct device;
struct device_node; struct device_node;
...@@ -21,35 +23,33 @@ struct drm_property; ...@@ -21,35 +23,33 @@ struct drm_property;
struct regmap; struct regmap;
struct mtk_mmsys_driver_data { struct mtk_mmsys_driver_data {
const resource_size_t io_start; const unsigned int *main_path;
const enum mtk_ddp_comp_id *main_path;
unsigned int main_len; unsigned int main_len;
const enum mtk_ddp_comp_id *ext_path; const unsigned int *ext_path;
unsigned int ext_len; unsigned int ext_len;
const enum mtk_ddp_comp_id *third_path; const unsigned int *third_path;
unsigned int third_len; unsigned int third_len;
bool shadow_register; bool shadow_register;
}; unsigned int mmsys_id;
unsigned int mmsys_dev_num;
struct mtk_mmsys_match_data {
unsigned short num_drv_data;
const struct mtk_mmsys_driver_data *drv_data[];
}; };
struct mtk_drm_private { struct mtk_drm_private {
struct drm_device *drm; struct drm_device *drm;
struct device *dma_dev; struct device *dma_dev;
bool mtk_drm_bound;
unsigned int num_pipes; bool drm_master;
struct device *dev;
struct device_node *mutex_node; struct device_node *mutex_node;
struct device *mutex_dev; struct device *mutex_dev;
struct device *mmsys_dev; struct device *mmsys_dev;
struct device_node *comp_node[DDP_COMPONENT_ID_MAX]; struct device_node *comp_node[DDP_COMPONENT_DRM_ID_MAX];
struct mtk_ddp_comp ddp_comp[DDP_COMPONENT_ID_MAX]; struct mtk_ddp_comp ddp_comp[DDP_COMPONENT_DRM_ID_MAX];
const struct mtk_mmsys_driver_data *data; const struct mtk_mmsys_driver_data *data;
struct drm_atomic_state *suspend_state; struct drm_atomic_state *suspend_state;
unsigned int mbox_index;
struct mtk_drm_private **all_drm_private;
}; };
extern struct platform_driver mtk_disp_aal_driver; extern struct platform_driver mtk_disp_aal_driver;
...@@ -57,10 +57,12 @@ extern struct platform_driver mtk_disp_ccorr_driver; ...@@ -57,10 +57,12 @@ extern struct platform_driver mtk_disp_ccorr_driver;
extern struct platform_driver mtk_disp_color_driver; extern struct platform_driver mtk_disp_color_driver;
extern struct platform_driver mtk_disp_gamma_driver; extern struct platform_driver mtk_disp_gamma_driver;
extern struct platform_driver mtk_disp_merge_driver; extern struct platform_driver mtk_disp_merge_driver;
extern struct platform_driver mtk_disp_ovl_adaptor_driver;
extern struct platform_driver mtk_disp_ovl_driver; extern struct platform_driver mtk_disp_ovl_driver;
extern struct platform_driver mtk_disp_rdma_driver; extern struct platform_driver mtk_disp_rdma_driver;
extern struct platform_driver mtk_dpi_driver; extern struct platform_driver mtk_dpi_driver;
extern struct platform_driver mtk_dsi_driver; extern struct platform_driver mtk_dsi_driver;
extern struct platform_driver mtk_ethdr_driver;
extern struct platform_driver mtk_mdp_rdma_driver; extern struct platform_driver mtk_mdp_rdma_driver;
#endif /* MTK_DRM_DRV_H */ #endif /* MTK_DRM_DRV_H */
...@@ -19,20 +19,6 @@ ...@@ -19,20 +19,6 @@
#include "mtk_drm_gem.h" #include "mtk_drm_gem.h"
#include "mtk_drm_plane.h" #include "mtk_drm_plane.h"
static const u32 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 u64 modifiers[] = { static const u64 modifiers[] = {
DRM_FORMAT_MOD_LINEAR, DRM_FORMAT_MOD_LINEAR,
DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 | DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
...@@ -315,13 +301,19 @@ static const struct drm_plane_helper_funcs mtk_plane_helper_funcs = { ...@@ -315,13 +301,19 @@ static const struct drm_plane_helper_funcs mtk_plane_helper_funcs = {
int mtk_plane_init(struct drm_device *dev, struct drm_plane *plane, int mtk_plane_init(struct drm_device *dev, struct drm_plane *plane,
unsigned long possible_crtcs, enum drm_plane_type type, unsigned long possible_crtcs, enum drm_plane_type type,
unsigned int supported_rotations) unsigned int supported_rotations, const u32 *formats,
size_t num_formats)
{ {
int err; int err;
if (!formats || !num_formats) {
DRM_ERROR("no formats for plane\n");
return -EINVAL;
}
err = drm_universal_plane_init(dev, plane, possible_crtcs, err = drm_universal_plane_init(dev, plane, possible_crtcs,
&mtk_plane_funcs, formats, &mtk_plane_funcs, formats,
ARRAY_SIZE(formats), modifiers, type, NULL); num_formats, modifiers, type, NULL);
if (err) { if (err) {
DRM_ERROR("failed to initialize plane\n"); DRM_ERROR("failed to initialize plane\n");
return err; return err;
......
...@@ -48,6 +48,7 @@ to_mtk_plane_state(struct drm_plane_state *state) ...@@ -48,6 +48,7 @@ to_mtk_plane_state(struct drm_plane_state *state)
int mtk_plane_init(struct drm_device *dev, struct drm_plane *plane, int mtk_plane_init(struct drm_device *dev, struct drm_plane *plane,
unsigned long possible_crtcs, enum drm_plane_type type, unsigned long possible_crtcs, enum drm_plane_type type,
unsigned int supported_rotations); unsigned int supported_rotations, const u32 *formats,
size_t num_formats);
#endif #endif
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2021 MediaTek Inc.
*/
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
#include <linux/clk.h>
#include <linux/component.h>
#include <linux/of_device.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/reset.h>
#include <linux/soc/mediatek/mtk-cmdq.h>
#include <linux/soc/mediatek/mtk-mmsys.h>
#include "mtk_drm_crtc.h"
#include "mtk_drm_ddp_comp.h"
#include "mtk_drm_drv.h"
#include "mtk_ethdr.h"
#define MIX_INTEN 0x4
#define MIX_FME_CPL_INTEN BIT(1)
#define MIX_INTSTA 0x8
#define MIX_EN 0xc
#define MIX_RST 0x14
#define MIX_ROI_SIZE 0x18
#define MIX_DATAPATH_CON 0x1c
#define OUTPUT_NO_RND BIT(3)
#define SOURCE_RGB_SEL BIT(7)
#define BACKGROUND_RELAY (4 << 9)
#define MIX_ROI_BGCLR 0x20
#define BGCLR_BLACK 0xff000000
#define MIX_SRC_CON 0x24
#define MIX_SRC_L0_EN BIT(0)
#define MIX_L_SRC_CON(n) (0x28 + 0x18 * (n))
#define NON_PREMULTI_SOURCE (2 << 12)
#define MIX_L_SRC_SIZE(n) (0x30 + 0x18 * (n))
#define MIX_L_SRC_OFFSET(n) (0x34 + 0x18 * (n))
#define MIX_FUNC_DCM0 0x120
#define MIX_FUNC_DCM1 0x124
#define MIX_FUNC_DCM_ENABLE 0xffffffff
#define HDR_VDO_FE_0804_HDR_DM_FE 0x804
#define HDR_VDO_FE_0804_BYPASS_ALL 0xfd
#define HDR_GFX_FE_0204_GFX_HDR_FE 0x204
#define HDR_GFX_FE_0204_BYPASS_ALL 0xfd
#define HDR_VDO_BE_0204_VDO_DM_BE 0x204
#define HDR_VDO_BE_0204_BYPASS_ALL 0x7e
#define MIXER_INX_MODE_BYPASS 0
#define MIXER_INX_MODE_EVEN_EXTEND 1
#define DEFAULT_9BIT_ALPHA 0x100
#define MIXER_ALPHA_AEN BIT(8)
#define MIXER_ALPHA 0xff
#define ETHDR_CLK_NUM 13
enum mtk_ethdr_comp_id {
ETHDR_MIXER,
ETHDR_VDO_FE0,
ETHDR_VDO_FE1,
ETHDR_GFX_FE0,
ETHDR_GFX_FE1,
ETHDR_VDO_BE,
ETHDR_ADL_DS,
ETHDR_ID_MAX
};
struct mtk_ethdr_comp {
struct device *dev;
void __iomem *regs;
struct cmdq_client_reg cmdq_base;
};
struct mtk_ethdr {
struct mtk_ethdr_comp ethdr_comp[ETHDR_ID_MAX];
struct clk_bulk_data ethdr_clk[ETHDR_CLK_NUM];
struct device *mmsys_dev;
void (*vblank_cb)(void *data);
void *vblank_cb_data;
int irq;
struct reset_control *reset_ctl;
};
static const char * const ethdr_clk_str[] = {
"ethdr_top",
"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",
};
void mtk_ethdr_register_vblank_cb(struct device *dev,
void (*vblank_cb)(void *),
void *vblank_cb_data)
{
struct mtk_ethdr *priv = dev_get_drvdata(dev);
priv->vblank_cb = vblank_cb;
priv->vblank_cb_data = vblank_cb_data;
}
void mtk_ethdr_unregister_vblank_cb(struct device *dev)
{
struct mtk_ethdr *priv = dev_get_drvdata(dev);
priv->vblank_cb = NULL;
priv->vblank_cb_data = NULL;
}
void mtk_ethdr_enable_vblank(struct device *dev)
{
struct mtk_ethdr *priv = dev_get_drvdata(dev);
writel(MIX_FME_CPL_INTEN, priv->ethdr_comp[ETHDR_MIXER].regs + MIX_INTEN);
}
void mtk_ethdr_disable_vblank(struct device *dev)
{
struct mtk_ethdr *priv = dev_get_drvdata(dev);
writel(0x0, priv->ethdr_comp[ETHDR_MIXER].regs + MIX_INTEN);
}
static irqreturn_t mtk_ethdr_irq_handler(int irq, void *dev_id)
{
struct mtk_ethdr *priv = dev_id;
writel(0x0, priv->ethdr_comp[ETHDR_MIXER].regs + MIX_INTSTA);
if (!priv->vblank_cb)
return IRQ_NONE;
priv->vblank_cb(priv->vblank_cb_data);
return IRQ_HANDLED;
}
void mtk_ethdr_layer_config(struct device *dev, unsigned int idx,
struct mtk_plane_state *state,
struct cmdq_pkt *cmdq_pkt)
{
struct mtk_ethdr *priv = dev_get_drvdata(dev);
struct mtk_ethdr_comp *mixer = &priv->ethdr_comp[ETHDR_MIXER];
struct mtk_plane_pending_state *pending = &state->pending;
unsigned int offset = (pending->x & 1) << 31 | pending->y << 16 | pending->x;
unsigned int align_width = ALIGN_DOWN(pending->width, 2);
unsigned int alpha_con = 0;
dev_dbg(dev, "%s+ idx:%d", __func__, idx);
if (idx >= 4)
return;
if (!pending->enable) {
mtk_ddp_write(cmdq_pkt, 0, &mixer->cmdq_base, mixer->regs, MIX_L_SRC_SIZE(idx));
return;
}
if (state->base.fb && state->base.fb->format->has_alpha)
alpha_con = MIXER_ALPHA_AEN | MIXER_ALPHA;
mtk_mmsys_mixer_in_config(priv->mmsys_dev, idx + 1, alpha_con ? false : true,
DEFAULT_9BIT_ALPHA,
pending->x & 1 ? MIXER_INX_MODE_EVEN_EXTEND :
MIXER_INX_MODE_BYPASS, align_width / 2 - 1, cmdq_pkt);
mtk_ddp_write(cmdq_pkt, pending->height << 16 | align_width, &mixer->cmdq_base,
mixer->regs, MIX_L_SRC_SIZE(idx));
mtk_ddp_write(cmdq_pkt, offset, &mixer->cmdq_base, mixer->regs, MIX_L_SRC_OFFSET(idx));
mtk_ddp_write_mask(cmdq_pkt, alpha_con, &mixer->cmdq_base, mixer->regs, MIX_L_SRC_CON(idx),
0x1ff);
mtk_ddp_write_mask(cmdq_pkt, BIT(idx), &mixer->cmdq_base, mixer->regs, MIX_SRC_CON,
BIT(idx));
}
void mtk_ethdr_config(struct device *dev, unsigned int w,
unsigned int h, unsigned int vrefresh,
unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
{
struct mtk_ethdr *priv = dev_get_drvdata(dev);
struct mtk_ethdr_comp *vdo_fe0 = &priv->ethdr_comp[ETHDR_VDO_FE0];
struct mtk_ethdr_comp *vdo_fe1 = &priv->ethdr_comp[ETHDR_VDO_FE1];
struct mtk_ethdr_comp *gfx_fe0 = &priv->ethdr_comp[ETHDR_GFX_FE0];
struct mtk_ethdr_comp *gfx_fe1 = &priv->ethdr_comp[ETHDR_GFX_FE1];
struct mtk_ethdr_comp *vdo_be = &priv->ethdr_comp[ETHDR_VDO_BE];
struct mtk_ethdr_comp *mixer = &priv->ethdr_comp[ETHDR_MIXER];
dev_dbg(dev, "%s-w:%d, h:%d\n", __func__, w, h);
mtk_ddp_write(cmdq_pkt, HDR_VDO_FE_0804_BYPASS_ALL, &vdo_fe0->cmdq_base,
vdo_fe0->regs, HDR_VDO_FE_0804_HDR_DM_FE);
mtk_ddp_write(cmdq_pkt, HDR_VDO_FE_0804_BYPASS_ALL, &vdo_fe1->cmdq_base,
vdo_fe1->regs, HDR_VDO_FE_0804_HDR_DM_FE);
mtk_ddp_write(cmdq_pkt, HDR_GFX_FE_0204_BYPASS_ALL, &gfx_fe0->cmdq_base,
gfx_fe0->regs, HDR_GFX_FE_0204_GFX_HDR_FE);
mtk_ddp_write(cmdq_pkt, HDR_GFX_FE_0204_BYPASS_ALL, &gfx_fe1->cmdq_base,
gfx_fe1->regs, HDR_GFX_FE_0204_GFX_HDR_FE);
mtk_ddp_write(cmdq_pkt, HDR_VDO_BE_0204_BYPASS_ALL, &vdo_be->cmdq_base,
vdo_be->regs, HDR_VDO_BE_0204_VDO_DM_BE);
mtk_ddp_write(cmdq_pkt, MIX_FUNC_DCM_ENABLE, &mixer->cmdq_base, mixer->regs, MIX_FUNC_DCM0);
mtk_ddp_write(cmdq_pkt, MIX_FUNC_DCM_ENABLE, &mixer->cmdq_base, mixer->regs, MIX_FUNC_DCM1);
mtk_ddp_write(cmdq_pkt, h << 16 | w, &mixer->cmdq_base, mixer->regs, MIX_ROI_SIZE);
mtk_ddp_write(cmdq_pkt, BGCLR_BLACK, &mixer->cmdq_base, mixer->regs, MIX_ROI_BGCLR);
mtk_ddp_write(cmdq_pkt, NON_PREMULTI_SOURCE, &mixer->cmdq_base, mixer->regs,
MIX_L_SRC_CON(0));
mtk_ddp_write(cmdq_pkt, NON_PREMULTI_SOURCE, &mixer->cmdq_base, mixer->regs,
MIX_L_SRC_CON(1));
mtk_ddp_write(cmdq_pkt, NON_PREMULTI_SOURCE, &mixer->cmdq_base, mixer->regs,
MIX_L_SRC_CON(2));
mtk_ddp_write(cmdq_pkt, NON_PREMULTI_SOURCE, &mixer->cmdq_base, mixer->regs,
MIX_L_SRC_CON(3));
mtk_ddp_write(cmdq_pkt, 0x0, &mixer->cmdq_base, mixer->regs, MIX_L_SRC_SIZE(0));
mtk_ddp_write(cmdq_pkt, OUTPUT_NO_RND | SOURCE_RGB_SEL | BACKGROUND_RELAY,
&mixer->cmdq_base, mixer->regs, MIX_DATAPATH_CON);
mtk_ddp_write_mask(cmdq_pkt, MIX_SRC_L0_EN, &mixer->cmdq_base, mixer->regs,
MIX_SRC_CON, MIX_SRC_L0_EN);
mtk_mmsys_hdr_config(priv->mmsys_dev, w / 2, h, cmdq_pkt);
mtk_mmsys_mixer_in_channel_swap(priv->mmsys_dev, 4, 0, cmdq_pkt);
}
void mtk_ethdr_start(struct device *dev)
{
struct mtk_ethdr *priv = dev_get_drvdata(dev);
struct mtk_ethdr_comp *mixer = &priv->ethdr_comp[ETHDR_MIXER];
writel(1, mixer->regs + MIX_EN);
}
void mtk_ethdr_stop(struct device *dev)
{
struct mtk_ethdr *priv = dev_get_drvdata(dev);
struct mtk_ethdr_comp *mixer = &priv->ethdr_comp[ETHDR_MIXER];
writel(0, mixer->regs + MIX_EN);
writel(1, mixer->regs + MIX_RST);
reset_control_reset(priv->reset_ctl);
writel(0, mixer->regs + MIX_RST);
}
int mtk_ethdr_clk_enable(struct device *dev)
{
int ret;
struct mtk_ethdr *priv = dev_get_drvdata(dev);
ret = clk_bulk_prepare_enable(ETHDR_CLK_NUM, priv->ethdr_clk);
if (ret)
dev_err(dev,
"ethdr_clk prepare enable failed\n");
return ret;
}
void mtk_ethdr_clk_disable(struct device *dev)
{
struct mtk_ethdr *priv = dev_get_drvdata(dev);
clk_bulk_disable_unprepare(ETHDR_CLK_NUM, priv->ethdr_clk);
}
static int mtk_ethdr_bind(struct device *dev, struct device *master,
void *data)
{
struct mtk_ethdr *priv = dev_get_drvdata(dev);
priv->mmsys_dev = data;
return 0;
}
static void mtk_ethdr_unbind(struct device *dev, struct device *master, void *data)
{
}
static const struct component_ops mtk_ethdr_component_ops = {
.bind = mtk_ethdr_bind,
.unbind = mtk_ethdr_unbind,
};
static int mtk_ethdr_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct mtk_ethdr *priv;
int ret;
int i;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
for (i = 0; i < ETHDR_ID_MAX; i++) {
priv->ethdr_comp[i].dev = dev;
priv->ethdr_comp[i].regs = of_iomap(dev->of_node, i);
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
ret = cmdq_dev_get_client_reg(dev,
&priv->ethdr_comp[i].cmdq_base, i);
if (ret)
dev_dbg(dev, "get mediatek,gce-client-reg fail!\n");
#endif
dev_dbg(dev, "[DRM]regs:0x%p, node:%d\n", priv->ethdr_comp[i].regs, i);
}
for (i = 0; i < ETHDR_CLK_NUM; i++)
priv->ethdr_clk[i].id = ethdr_clk_str[i];
ret = devm_clk_bulk_get_optional(dev, ETHDR_CLK_NUM, priv->ethdr_clk);
if (ret)
return ret;
priv->irq = platform_get_irq(pdev, 0);
if (priv->irq < 0)
priv->irq = 0;
if (priv->irq) {
ret = devm_request_irq(dev, priv->irq, mtk_ethdr_irq_handler,
IRQF_TRIGGER_NONE, dev_name(dev), priv);
if (ret < 0) {
dev_err(dev, "Failed to request irq %d: %d\n", priv->irq, ret);
return ret;
}
}
priv->reset_ctl = devm_reset_control_array_get_optional_exclusive(dev);
if (IS_ERR(priv->reset_ctl)) {
dev_err_probe(dev, PTR_ERR(priv->reset_ctl), "cannot get ethdr reset control\n");
return PTR_ERR(priv->reset_ctl);
}
platform_set_drvdata(pdev, priv);
ret = component_add(dev, &mtk_ethdr_component_ops);
if (ret)
dev_notice(dev, "Failed to add component: %d\n", ret);
return ret;
}
static int mtk_ethdr_remove(struct platform_device *pdev)
{
component_del(&pdev->dev, &mtk_ethdr_component_ops);
return 0;
}
static const struct of_device_id mtk_ethdr_driver_dt_match[] = {
{ .compatible = "mediatek,mt8195-disp-ethdr"},
{},
};
MODULE_DEVICE_TABLE(of, mtk_ethdr_driver_dt_match);
struct platform_driver mtk_ethdr_driver = {
.probe = mtk_ethdr_probe,
.remove = mtk_ethdr_remove,
.driver = {
.name = "mediatek-disp-ethdr",
.owner = THIS_MODULE,
.of_match_table = mtk_ethdr_driver_dt_match,
},
};
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2021 MediaTek Inc.
*/
#ifndef __MTK_ETHDR_H__
#define __MTK_ETHDR_H__
void mtk_ethdr_start(struct device *dev);
void mtk_ethdr_stop(struct device *dev);
int mtk_ethdr_clk_enable(struct device *dev);
void mtk_ethdr_clk_disable(struct device *dev);
void mtk_ethdr_config(struct device *dev, unsigned int w,
unsigned int h, unsigned int vrefresh,
unsigned int bpc, struct cmdq_pkt *cmdq_pkt);
void mtk_ethdr_layer_config(struct device *dev, unsigned int idx,
struct mtk_plane_state *state,
struct cmdq_pkt *cmdq_pkt);
void mtk_ethdr_register_vblank_cb(struct device *dev,
void (*vblank_cb)(void *),
void *vblank_cb_data);
void mtk_ethdr_unregister_vblank_cb(struct device *dev);
void mtk_ethdr_enable_vblank(struct device *dev);
void mtk_ethdr_disable_vblank(struct device *dev);
#endif
...@@ -62,6 +62,20 @@ ...@@ -62,6 +62,20 @@
#define RDMA_CSC_FULL709_TO_RGB 5 #define RDMA_CSC_FULL709_TO_RGB 5
#define RDMA_CSC_BT601_TO_RGB 6 #define RDMA_CSC_BT601_TO_RGB 6
static const u32 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,
};
enum rdma_format { enum rdma_format {
RDMA_INPUT_FORMAT_RGB565 = 0, RDMA_INPUT_FORMAT_RGB565 = 0,
RDMA_INPUT_FORMAT_RGB888 = 1, RDMA_INPUT_FORMAT_RGB888 = 1,
...@@ -219,6 +233,16 @@ void mtk_mdp_rdma_config(struct device *dev, struct mtk_mdp_rdma_cfg *cfg, ...@@ -219,6 +233,16 @@ void mtk_mdp_rdma_config(struct device *dev, struct mtk_mdp_rdma_cfg *cfg,
MDP_RDMA_MF_CLIP_SIZE, FLD_MF_CLIP_H); MDP_RDMA_MF_CLIP_SIZE, FLD_MF_CLIP_H);
} }
const u32 *mtk_mdp_rdma_get_formats(struct device *dev)
{
return formats;
}
size_t mtk_mdp_rdma_get_num_formats(struct device *dev)
{
return ARRAY_SIZE(formats);
}
int mtk_mdp_rdma_clk_enable(struct device *dev) int mtk_mdp_rdma_clk_enable(struct device *dev)
{ {
struct mtk_mdp_rdma *rdma = dev_get_drvdata(dev); struct mtk_mdp_rdma *rdma = dev_get_drvdata(dev);
......
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