Re: [PATCH v2 9/9] drm/mediatek: add MERGE support for mt8195
From: Jason-JH Lin <hidden>
Date: 2021-07-16 08:48:38
Also in:
linux-arm-kernel
Hi CK, On Sun, 2021-07-11 at 07:42 +0800, Chun-Kuang Hu wrote:
Hi, Jason: jason-jh.lin [off-list ref] 於 2021年7月10日 週六 下午7:38寫道:quoted
1. Add MERGE module file. 2. Add REG_FLD macro in mtk_dem_crtc header to support bitwise register settings. Signed-off-by: jason-jh.lin <redacted> --- drivers/gpu/drm/mediatek/Makefile | 1 + drivers/gpu/drm/mediatek/mtk_disp_drv.h | 8 + drivers/gpu/drm/mediatek/mtk_disp_merge.c | 525 ++++++++++++++++++++ drivers/gpu/drm/mediatek/mtk_drm_crtc.h | 14 + drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 16 + drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h | 1 + drivers/gpu/drm/mediatek/mtk_drm_drv.c | 4 + drivers/gpu/drm/mediatek/mtk_drm_drv.h | 1 + 8 files changed, 570 insertions(+) create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_merge.cdiff --git a/drivers/gpu/drm/mediatek/Makefileb/drivers/gpu/drm/mediatek/Makefile index a1b239135c8f..9044c5aabae1 100644--- a/drivers/gpu/drm/mediatek/Makefile +++ b/drivers/gpu/drm/mediatek/Makefile@@ -6,6 +6,7 @@ mediatek-drm-y := mtk_disp_ccorr.o \ mtk_disp_ovl.o \ mtk_disp_rdma.o \ mtk_disp_dsc.o \ + mtk_disp_merge.o \ mtk_drm_crtc.o \ mtk_drm_ddp_comp.o \ mtk_drm_drv.o \diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.hb/drivers/gpu/drm/mediatek/mtk_disp_drv.h index 128d9fdbaf9e..dfb078541430 100644--- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h +++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h@@ -97,4 +97,12 @@ void mtk_dsc_config(struct device *dev, unsignedint width, void mtk_dsc_start(struct device *dev); void mtk_dsc_stop(struct device *dev); +int mtk_merge_clk_enable(struct device *dev); +void mtk_merge_clk_disable(struct device *dev); +void mtk_merge_config(struct device *dev, unsigned int width, + unsigned int height, unsigned int vrefresh, + unsigned int bpc, struct cmdq_pkt *cmdq_pkt); +void mtk_merge_start(struct device *dev); +void mtk_merge_stop(struct device *dev); + #endifdiff --git a/drivers/gpu/drm/mediatek/mtk_disp_merge.cb/drivers/gpu/drm/mediatek/mtk_disp_merge.c new file mode 100644 index 000000000000..b7d633ca2f71--- /dev/null +++ b/drivers/gpu/drm/mediatek/mtk_disp_merge.c@@ -0,0 +1,525 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2021 MediaTek Inc. + */ + +#include <linux/clk.h> +#include <linux/component.h> +#include <linux/of_device.h> +#include <linux/of_irq.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/soc/mediatek/mtk-cmdq.h> + +#include "mtk_drm_crtc.h" +#include "mtk_drm_ddp_comp.h" +#include "mtk_drm_drv.h" +#include "mtk_disp_drv.h" + +#define DISP_REG_MERGE_CTRL (0x000) +#define FLD_MERGE_EN BIT(0) +#define FLD_MERGE_RST BIT(4) +#define FLD_MERGE_LR_SWAP BIT(8) +#define FLD_MERGE_DCM_DIS BIT(12) + +#define DISP_REG_MERGE_WIDTH (0x004) +#define FLD_IN_WIDHT_L GENMASK(15, 0) +#define FLD_IN_WIDHT_R GENMASK(31, 16) + +#define DISP_REG_MERGE_HEIGHT (0x008) +#define FLD_IN_HEIGHT GENMASK(15, 0) + +#define DISP_REG_MERGE_SHADOW_CRTL (0x00c) + +#define DISP_REG_MERGE_DGB0 (0x010) +#define FLD_PIXEL_CNT GENMASK(15, 0) +#define FLD_MERGE_STATE GENMASK(17, 16) + +#define DISP_REG_MERGE_DGB1 (0x014) +#define FLD_LINE_CNT GENMASK(15, 0) + +#define DISP_REG_MERGE_CFG2_0 (0x160) + +#define DISP_REG_MERGE_CFG2_2 (0x168) + +#define DISP_MERGE_CFG_0 0x010 +#define DISP_MERGE_CFG_1 0x014 +#define DISP_MERGE_CFG_4 0x020 +#define DISP_MERGE_CFG_5 0x024 +#define DISP_MERGE_CFG_8 0x030 +#define DISP_MERGE_CFG_9 0x034 +#define DISP_MERGE_CFG_10 0x038 +#define DISP_MERGE_CFG_11 0x03c +#define DISP_MERGE_CFG_12 0x040 +#define CFG_11_11_1PI_1PO_BYPASS 1 +#define CFG_11_11_2PI_2PO_BYPASS 2 +#define CFG_10_10_2PI_1PO_BYPASS 3 +#define CFG_10_10_2PI_2PO_BYPASS 4 +#define CFG_10_10_1PI_1PO_BUF_MODE 5 +#define CFG_10_10_1PI_2PO_BUF_MODE 6 +#define CFG_10_10_2PI_1PO_BUF_MODE 7 +#define CFG_10_10_2PI_2PO_BUF_MODE 8 +#define CFG_10_01_1PI_1PO_BUF_MODE 9 +#define CFG_10_01_2PI_1PO_BUF_MODE 10 +#define CFG_01_10_1PI_1PO_BUF_MODE 11 +#define CFG_01_10_1PI_2PO_BUF_MODE 12 +#define CFG_01_01_1PI_1PO_BUF_MODE 13 +#define CFG_10_11_1PI_1PO_SPLIT 14 +#define CFG_10_11_2PI_1PO_SPLIT 15 +#define CFG_01_11_1PI_1PO_SPLIT 16 +#define CFG_11_10_1PI_1PO_MERGE 17 +#define CFG_11_10_1PI_2PO_MERGE 18 +#define CFG_10_10_1PI_1PO_TO422 19 +#define CFG_10_10_1PI_2PO_TO444 20 +#define CFG_10_10_2PI_2PO_TO444 21 +#define DISP_MERGE_CFG_13 0x044Useless, so remove.
OK, I'll remove it.
quoted
+#define DISP_MERGE_CFG_14 0x048 +#define DISP_MERGE_CFG_15 0x04c +#define DISP_MERGE_CFG_17 0x054 +#define DISP_MERGE_CFG_18 0x058 +#define DISP_MERGE_CFG_19 0x05c +#define DISP_MERGE_CFG_20 0x060 +#define DISP_MERGE_CFG_21 0x064 +#define DISP_MERGE_CFG_22 0x068 +#define DISP_MERGE_CFG_23 0x06c +#define DISP_MERGE_CFG_24 0x070 +#define DISP_MERGE_CFG_25 0x074 +#define DISP_MERGE_CFG_26 0x078 +#define DISP_MERGE_CFG_27 0x07c +#define DISP_MERGE_CFG_28 0x080 +#define DISP_MERGE_CFG_29 0x084 +#define DISP_MERGE_CFG_36 0x0a0 +#define DISP_MERGE_CFG_36_FLD_ULTRA_EN \ + REG_FLD(1, 0) +#define DISP_MERGE_CFG_36_FLD_PREULTRA_EN \ + REG_FLD(1, 4) +#define DISP_MERGE_CFG_36_FLD_HALT_FOR_DVFS_EN \ + REG_FLD(1, 8) +#define DISP_MERGE_CFG_36_VAL_ULTRA_EN(val) \ + REG_FLD_VAL(DISP_MERGE_CFG_36_FLD_ULTRA_EN, val) +#define DISP_MERGE_CFG_36_VAL_PREULTRA_EN(val) \ + REG_FLD_VAL(DISP_MERGE_CFG_36_FLD_PREULTRA_EN, val) +#define DISP_MERGE_CFG_36_VAL_HALT_FOR_DVFS_EN(val) \ + REG_FLD_VAL(DISP_MERGE_CFG_36_FLD_HALT_FOR_DVFS_EN, val) +#define DISP_MERGE_CFG_37 0x0a4 +#define DISP_MERGE_CFG_37_FLD_BUFFER_MODE \ + REG_FLD(2, 0) +#define DISP_MERGE_CFG_37_VAL_BUFFER_MODE(val) \ + REG_FLD_VAL(DISP_MERGE_CFG_37_FLD_BUFFER_MODE, val) +#define DISP_MERGE_CFG_38 0x0a8 +#define DISP_MERGE_CFG_38_FLD_VDE_BLOCK_ULTRA \ + REG_FLD(1, 0) +#define DISP_MERGE_CFG_38_FLD_VALID_TH_BLOCK_ULTRA \ + REG_FLD(1, 4) +#define DISP_MERGE_CFG_38_FLD_ULTRA_FIFO_VALID_TH \ + REG_FLD(16, 16) +#define DISP_MERGE_CFG_38_VAL_VDE_BLOCK_ULTRA(val) \ + REG_FLD_VAL(DISP_MERGE_CFG_38_FLD_VDE_BLOCK_ULTRA, val) +#define DISP_MERGE_CFG_38_VAL_VALID_TH_BLOCK_ULTRA(val) \ + REG_FLD_VAL(DISP_MERGE_CFG_38_FLD_VALID_TH_BLOCK_ULTRA, val) +#define DISP_MERGE_CFG_38_VAL_ULTRA_FIFO_VALID_TH(val) \ + REG_FLD_VAL(DISP_MERGE_CFG_38_FLD_ULTRA_FIFO_VALID_TH, val) +#define DISP_MERGE_CFG_39 0x0ac +#define DISP_MERGE_CFG_39_FLD_NVDE_FORCE_PREULTRA \ + REG_FLD(1, 8) +#define DISP_MERGE_CFG_39_FLD_NVALID_TH_FORCE_PREULTRA \ + REG_FLD(1, 12) +#define DISP_MERGE_CFG_39_FLD_PREULTRA_FIFO_VALID_TH \ + REG_FLD(16, 16) +#define DISP_MERGE_CFG_39_VAL_NVDE_FORCE_PREULTRA(val) \ + REG_FLD_VAL(DISP_MERGE_CFG_39_FLD_NVDE_FORCE_PREULTRA, val) +#define DISP_MERGE_CFG_39_VAL_NVALID_TH_FORCE_PREULTRA(val) \ + REG_FLD_VAL(DISP_MERGE_CFG_39_FLD_NVALID_TH_FORCE_PREULTRA, val) +#define DISP_MERGE_CFG_39_VAL_PREULTRA_FIFO_VALID_TH(val) \ + REG_FLD_VAL(DISP_MERGE_CFG_39_FLD_PREULTRA_FIFO_VALID_TH, val) +#define DISP_MERGE_CFG_40 0x0b0 +#define DISP_MERGE_CFG_40_FLD_ULTRA_TH_LOW \ + REG_FLD(16, 0) +#define DISP_MERGE_CFG_40_FLD_ULTRA_TH_HIGH \ + REG_FLD(16, 16) +#define DISP_MERGE_CFG_40_VAL_ULTRA_TH_LOW(val) \ + REG_FLD_VAL(DISP_MERGE_CFG_40_FLD_ULTRA_TH_LOW, (val)) +#define DISP_MERGE_CFG_40_VAL_ULTRA_TH_HIGH(val) \ + REG_FLD_VAL(DISP_MERGE_CFG_40_FLD_ULTRA_TH_HIGH, val) +#define DISP_MERGE_CFG_41 0x0b4 +#define DISP_MERGE_CFG_41_FLD_PREULTRA_TH_LOW \ + REG_FLD(16, 0) +#define DISP_MERGE_CFG_41_FLD_PREULTRA_TH_HIGH \ + REG_FLD(16, 16) +#define DISP_MERGE_CFG_41_VAL_PREULTRA_TH_LOW(val) \ + REG_FLD_VAL(DISP_MERGE_CFG_41_FLD_PREULTRA_TH_LOW, val) +#define DISP_MERGE_CFG_41_VAL_PREULTRA_TH_HIGH(val) \ + REG_FLD_VAL(DISP_MERGE_CFG_41_FLD_PREULTRA_TH_HIGH, val) + +struct mtk_merge_config_struct { + unsigned short width_right; + unsigned short width_left; + unsigned int height; + unsigned int fmt; + unsigned int mode; + unsigned int swap; +}; + +struct mtk_disp_merge { + enum mtk_ddp_comp_id comp_id; + struct drm_crtc *crtc; + struct clk *clk; + struct clk *async_clk; + void __iomem *regs; + struct cmdq_client_reg cmdq_reg; + int irq; + bool need_golden_setting;need_golden_setting is always true, so remove this.
OK, I'll remove it.
quoted
+ enum mtk_ddp_comp_id gs_comp_id; +}; + +void mtk_merge_start(struct device *dev) +{ + struct mtk_disp_merge *priv = dev_get_drvdata(dev); + + mtk_ddp_write(NULL, 0x1, &priv->cmdq_reg, priv->regs, + DISP_REG_MERGE_CTRL);One line.
OK, I'll fix it.
quoted
+} + +void mtk_merge_stop(struct device *dev) +{ + struct mtk_disp_merge *priv = dev_get_drvdata(dev); + + mtk_ddp_write(NULL, 0x0, &priv->cmdq_reg, priv->regs, + DISP_REG_MERGE_CTRL); +} + +static int mtk_merge_check_params(struct mtk_merge_config_struct *merge_config) +{ + if (!merge_config->height || + !merge_config->width_left || !merge_config-quoted
width_right) {+ pr_err("%s:merge input width l(%u) w(%u) h(%u)\n", + __func__, merge_config->width_left, + merge_config->width_right, merge_config-quoted
height);+ return -EINVAL; + } + pr_debug("%s:merge input width l(%u) r(%u) height(%u)\n", + __func__, merge_config->width_left, + merge_config->width_right, merge_config->height); + return 0; +} + +static int mtk_merge_golden_setting(struct mtk_disp_merge *priv, + struct cmdq_pkt *handle) +{ + int ultra_en = 1; + int preultra_en = 1; + int halt_for_dvfs_en = 0; + int buffer_mode = 3; + int vde_block_ultra = 0; + int valid_th_block_ultra = 0; + int ultra_fifo_valid_th = 0; + int nvde_force_preultra = 0; + int nvalid_th_force_preultra = 0; + int preultra_fifo_valid_th = 0; + int ultra_th_low = 0xe10; + int ultra_th_high = 0x12c0; + int preultra_th_low = 0x12c0; + int preultra_th_high = 0x1518;I do not like a 'golden setting' which means we have no knowledge to control these value for some special case. Could you explain the logic why we set these value?
I'll change it to fifo setting and add the MERGE fifo description in Documentation/devicetree/bindings/display/mediatek/mediatek,disp.yaml at the next version.
quoted
+ + mtk_ddp_write_mask(handle, + DISP_MERGE_CFG_36_VAL_ULTRA_EN + (ultra_en) | + DISP_MERGE_CFG_36_VAL_PREULTRA_EN + (preultra_en) | + DISP_MERGE_CFG_36_VAL_HALT_FOR_DVFS_EN + (halt_for_dvfs_en), + &priv->cmdq_reg, priv->regs, + DISP_MERGE_CFG_36, + REG_FLD_MASK + (DISP_MERGE_CFG_36_FLD_ULTRA_EN) | + REG_FLD_MASK + (DISP_MERGE_CFG_36_FLD_PREULTRA_EN) | + REG_FLD_MASK + (DISP_MERGE_CFG_36_FLD_HALT_FOR_DVF S_EN)); + + mtk_ddp_write_mask(handle, + DISP_MERGE_CFG_37_VAL_BUFFER_MODE + (buffer_mode), + &priv->cmdq_reg, priv->regs, + DISP_MERGE_CFG_37, + REG_FLD_MASK + (DISP_MERGE_CFG_37_FLD_BUFFER_MODE) ); + + mtk_ddp_write_mask(handle, + DISP_MERGE_CFG_38_VAL_VDE_BLOCK_ULTRA + (vde_block_ultra) | + DISP_MERGE_CFG_38_VAL_VALID_TH_BLOCK_ULT RA + (valid_th_block_ultra) | + DISP_MERGE_CFG_38_VAL_ULTRA_FIFO_VALID_T H + (ultra_fifo_valid_th), + &priv->cmdq_reg, priv->regs, + DISP_MERGE_CFG_38, + REG_FLD_MASK + (DISP_MERGE_CFG_38_FLD_VDE_BLOCK_UL TRA) | + REG_FLD_MASK + (DISP_MERGE_CFG_38_FLD_VALID_TH_BLO CK_ULTRA) | + REG_FLD_MASK + (DISP_MERGE_CFG_38_FLD_ULTRA_FIFO_V ALID_TH)); + + mtk_ddp_write_mask(handle, + DISP_MERGE_CFG_39_VAL_NVDE_FORCE_PREULTR A + (nvde_force_preultra) | + DISP_MERGE_CFG_39_VAL_NVALID_TH_FORCE_PR EULTRA + (nvalid_th_force_preultra) | + DISP_MERGE_CFG_39_VAL_PREULTRA_FIFO_VALI D_TH + (preultra_fifo_valid_th), + &priv->cmdq_reg, priv->regs, + DISP_MERGE_CFG_39, + REG_FLD_MASK + (DISP_MERGE_CFG_39_FLD_NVDE_FORCE_P REULTRA) | + REG_FLD_MASK + (DISP_MERGE_CFG_39_FLD_NVALID_TH_FO RCE_PREULTRA) | + REG_FLD_MASK + (DISP_MERGE_CFG_39_FLD_PREULTRA_FIF O_VALID_TH)); + + mtk_ddp_write_mask(handle, + DISP_MERGE_CFG_40_VAL_ULTRA_TH_LOW + (ultra_th_low) | + DISP_MERGE_CFG_40_VAL_ULTRA_TH_HIGH + (ultra_th_high), + &priv->cmdq_reg, priv->regs, + DISP_MERGE_CFG_40, + REG_FLD_MASK + (DISP_MERGE_CFG_40_FLD_ULTRA_TH_LOW ) | + REG_FLD_MASK + (DISP_MERGE_CFG_40_FLD_ULTRA_TH_HIG H)); + + mtk_ddp_write_mask(handle, + DISP_MERGE_CFG_41_VAL_PREULTRA_TH_LOW + (preultra_th_low) | + DISP_MERGE_CFG_41_VAL_PREULTRA_TH_HIGH + (preultra_th_high), + &priv->cmdq_reg, priv->regs, + DISP_MERGE_CFG_41, + REG_FLD_MASK + (DISP_MERGE_CFG_41_FLD_PREULTRA_TH_ LOW) | + REG_FLD_MASK + (DISP_MERGE_CFG_41_FLD_PREULTRA_TH_ HIGH)); + + return 0; +} + +void mtk_merge_config(struct device *dev, unsigned int w, + unsigned int h, unsigned int vrefresh, + unsigned int bpc, struct cmdq_pkt *handle) +{ + struct mtk_merge_config_struct merge_config; + struct mtk_disp_merge *priv = dev_get_drvdata(dev); + + /*golden setting*/ + if (priv->need_golden_setting && + priv->gs_comp_id == priv->comp_id) + mtk_merge_golden_setting(priv, handle);Why only MERGE_5 set the fifo setting? I think all merge should set fifo setting.
Only MERGE5 need to set the fifo setting and MERGE0~4 can't config the fifo settings. I'll add the new property in binding document and describe it.
quoted
+ + switch (priv->comp_id) { + case DDP_COMPONENT_MERGE0: + merge_config.mode = CFG_10_10_1PI_2PO_BUF_MODE;Please explain what the mode means.
The mode setting here is to set the input and output pixel number per times in buffer mode or bypass mode. E.g. CFG_10_10_1PI_2PO_BUF_MODE: 1 pixel in, 2pixel out per times in buffer mode. CFG_10_10_2PI_2PO_BUF_MODE: 2 pixel in, 2pixel out per times in buffer mode.
quoted
+ merge_config.width_left = w; + merge_config.width_right = w; + merge_config.height = h; + merge_config.swap = 0; + break; + case DDP_COMPONENT_MERGE5: + merge_config.mode = CFG_10_10_2PI_2PO_BUF_MODE; + merge_config.width_left = w; + merge_config.width_right = w; + merge_config.height = h; + merge_config.swap = 0; + break; + default: + pr_err("No find component merge %d\n", priv-quoted
comp_id);+ return; + } + + mtk_merge_check_params(&merge_config); + + switch (merge_config.mode) { + case CFG_10_10_1PI_2PO_BUF_MODE: + case CFG_10_10_2PI_2PO_BUF_MODE:Remove 'switch' because these two cases are always true.
OK, I'll remove it.
quoted
+ mtk_ddp_write_mask(handle, + (merge_config.height << 16 | + merge_config.width_left), + &priv->cmdq_reg, priv->regs, + DISP_MERGE_CFG_0, ~0);mtk_ddp_write(handle, h << 16 | w, &priv->comdq_reg, priv->regs, DISP_MERGE_CFG_0);
I'll fix it.
quoted
+ + mtk_ddp_write_mask(handle, + (merge_config.height << 16 | + merge_config.width_left), + &priv->cmdq_reg, priv->regs, + DISP_MERGE_CFG_4, ~0);mtk_ddp_write(handle, h << 16 | w, &priv->cmdq_reg, priv->regs, DISP_MERGE_CFG_4);
I'll fix it.
quoted
+ + mtk_ddp_write_mask(handle, + (merge_config.height << 16 | + merge_config.width_left), + &priv->cmdq_reg, priv->regs, + DISP_MERGE_CFG_24, ~0);mtk_ddp_write(handle, h << 16 | w, &priv->cmdq_reg, priv->regs, DISP_MERGE_CFG_24);
I'll fix it.
quoted
+ + mtk_ddp_write_mask(handle, + (merge_config.height << 16 | + merge_config.width_left), + &priv->cmdq_reg, priv->regs, + DISP_MERGE_CFG_25, ~0); +mtk_ddp_write(handle, h << 16 | w, &priv->cmdq_reg, priv->regs, DISP_MERGE_CFG_25);
I'll fix it.
quoted
+ mtk_ddp_write_mask(handle, + merge_config.swap, + &priv->cmdq_reg, priv->regs, + DISP_MERGE_CFG_10, 0x1f);/* no swap */ mtk_ddp_write_mask(handle, 0, &priv->cmdq_reg, priv->regs, DISP_MERGE_CFG_10, 0x1f);
I'll fix it.
quoted
+ break; + default: + break; + } + mtk_ddp_write_mask(handle, merge_config.mode, + &priv->cmdq_reg, priv->regs, + DISP_MERGE_CFG_12, 0x1f); + mtk_ddp_write_mask(handle, 0x1, + &priv->cmdq_reg, priv->regs, + DISP_REG_MERGE_CTRL, 0x1);Why do you enable merge in config? Regards, Chun-Kuang.
I'll remove it. Regards, Jason-JH.Lin
quoted
+} + +int mtk_merge_clk_enable(struct device *dev) +{ + int ret = 0; + struct mtk_disp_merge *priv = dev_get_drvdata(dev); + + ret = pm_runtime_get_sync(dev); + + if (priv->clk) { + ret = clk_prepare_enable(priv->clk); + if (ret) + pr_err("merge clk prepare enable failed\n"); + } + + if (priv->async_clk) { + ret = clk_prepare_enable(priv->async_clk); + if (ret) + pr_err("async clk prepare enable failed\n"); + } + + return ret; +} + +void mtk_merge_clk_disable(struct device *dev) +{ + struct mtk_disp_merge *priv = dev_get_drvdata(dev); + + if (priv->async_clk) + clk_disable_unprepare(priv->async_clk); + + if (priv->clk) + clk_disable_unprepare(priv->clk); + + pm_runtime_put_sync(dev); +} + +static int mtk_disp_merge_bind(struct device *dev, struct device *master, + void *data) +{ + return 0; +} + +static void mtk_disp_merge_unbind(struct device *dev, struct device *master, + void *data) +{ +} + +static const struct component_ops mtk_disp_merge_component_ops = { + .bind = mtk_disp_merge_bind, + .unbind = mtk_disp_merge_unbind, +}; + +static int mtk_disp_merge_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct resource *res; + struct mtk_disp_merge *priv; + enum mtk_ddp_comp_id comp_id; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + comp_id = mtk_ddp_comp_get_id(dev->of_node, MTK_DISP_MERGE); + if ((int)comp_id < 0) { + dev_err(dev, "Failed to identify by alias: %d\n", comp_id); + return comp_id; + } + + priv->comp_id = comp_id; + priv->need_golden_setting = true; + priv->gs_comp_id = DDP_COMPONENT_MERGE5; + + priv->clk = devm_clk_get(dev, NULL); + if (IS_ERR(priv->clk)) { + dev_err(dev, "failed to get merge clk\n"); + return PTR_ERR(priv->clk); + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + priv->regs = devm_ioremap_resource(dev, res); + if (IS_ERR(priv->regs)) { + dev_err(dev, "failed to ioremap merge\n"); + return PTR_ERR(priv->regs); + } + +#if IS_REACHABLE(CONFIG_MTK_CMDQ) + ret = cmdq_dev_get_client_reg(dev, &priv->cmdq_reg, 0); + if (ret) + dev_dbg(dev, "get mediatek,gce-client-reg fail!\n"); +#endif + + priv->irq = platform_get_irq(pdev, 0); + if (priv->irq < 0) + priv->irq = 0; + + priv->async_clk = of_clk_get(dev->of_node, 1); + if (IS_ERR(priv->async_clk)) { + ret = PTR_ERR(priv->async_clk); + dev_dbg(dev, "No merge async clock: %d\n", ret); + priv->async_clk = NULL; + } + + platform_set_drvdata(pdev, priv); + + pm_runtime_enable(dev); + + ret = component_add(dev, &mtk_disp_merge_component_ops); + if (ret != 0) { + dev_err(dev, "Failed to add component: %d\n", ret); + pm_runtime_disable(dev); + } + + return ret; +} + +static int mtk_disp_merge_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &mtk_disp_merge_component_ops); + + pm_runtime_disable(&pdev->dev); + + return 0; +} + +static const struct of_device_id mtk_disp_merge_driver_dt_match[] = { + { .compatible = "mediatek,mt8195-disp-merge", }, + {}, +}; + +MODULE_DEVICE_TABLE(of, mtk_disp_merge_driver_dt_match); + +struct platform_driver mtk_disp_merge_driver = { + .probe = mtk_disp_merge_probe, + .remove = mtk_disp_merge_remove, + .driver = { + .name = "mediatek-disp-merge", + .owner = THIS_MODULE, + .of_match_table = mtk_disp_merge_driver_dt_match, + }, +}; +diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.hb/drivers/gpu/drm/mediatek/mtk_drm_crtc.h index cb9a36c48d4f..66d1cf03dfe8 100644--- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.h +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.h@@ -14,6 +14,20 @@ #define MTK_MAX_BPC 10 #define MTK_MIN_BPC 3 +#define REG_FLD(width, shift) \ + ((unsigned int)((((width) & 0xff) << 16) | ((shift) &0xff))) + +#define REG_FLD_WIDTH(field) ((unsigned int)(((field) >> 16) & 0xff)) + +#define REG_FLD_SHIFT(field) ((unsigned int)((field) & 0xff)) + +#define REG_FLD_MASK(field) \ + ((unsigned int)((1ULL << REG_FLD_WIDTH(field)) - 1) \ + << REG_FLD_SHIFT(field)) + +#define REG_FLD_VAL(field, val) \ + (((val) << REG_FLD_SHIFT(field)) & REG_FLD_MASK(field)) + void mtk_drm_crtc_commit(struct drm_crtc *crtc); int mtk_drm_crtc_create(struct drm_device *drm_dev, const enum mtk_ddp_comp_id *path,diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.cb/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c index d0b0f41dfe5a..fb5f260f5ae0 100644--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c@@ -341,6 +341,14 @@ static const struct mtk_ddp_comp_funcs ddp_dsc= { .clk_disable = mtk_dsc_clk_disable, }; +static const struct mtk_ddp_comp_funcs ddp_merge = { + .clk_enable = mtk_merge_clk_enable, + .clk_disable = mtk_merge_clk_disable, + .start = mtk_merge_start, + .stop = mtk_merge_stop, + .config = mtk_merge_config, +}; + static const struct mtk_ddp_comp_funcs ddp_ufoe = { .clk_enable = mtk_ddp_clk_enable, .clk_disable = mtk_ddp_clk_disable,@@ -365,6 +373,7 @@ static const char * constmtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = { [MTK_DISP_OD] = "od", [MTK_DISP_BLS] = "bls", [MTK_DISP_DSC] = "dsc", + [MTK_DISP_MERGE] = "merge", }; struct mtk_ddp_comp_match {@@ -403,6 +412,12 @@ static const struct mtk_ddp_comp_matchmtk_ddp_matches[DDP_COMPONENT_ID_MAX] = { [DDP_COMPONENT_DSC0] = { MTK_DISP_DSC, 0, &ddp_dsc }, [DDP_COMPONENT_DSC1] = { MTK_DISP_DSC, 1, &ddp_dsc }, [DDP_COMPONENT_DSC1_VIRTUAL0] = { MTK_DISP_DSC, -1, &ddp_dsc }, + [DDP_COMPONENT_MERGE0] = { MTK_DISP_MERGE, 0, &ddp_merge }, + [DDP_COMPONENT_MERGE1] = { MTK_DISP_MERGE, 1, &ddp_merge }, + [DDP_COMPONENT_MERGE2] = { MTK_DISP_MERGE, 2, &ddp_merge }, + [DDP_COMPONENT_MERGE3] = { MTK_DISP_MERGE, 3, &ddp_merge }, + [DDP_COMPONENT_MERGE4] = { MTK_DISP_MERGE, 4, &ddp_merge }, + [DDP_COMPONENT_MERGE5] = { MTK_DISP_MERGE, 5, &ddp_merge }, [DDP_COMPONENT_UFOE] = { MTK_DISP_UFOE, 0, &ddp_ufoe }, [DDP_COMPONENT_WDMA0] = { MTK_DISP_WDMA, 0, NULL }, [DDP_COMPONENT_WDMA1] = { MTK_DISP_WDMA, 1, NULL },@@ -522,6 +537,7 @@ int mtk_ddp_comp_init(struct device_node *node,struct mtk_ddp_comp *comp, type == MTK_DISP_COLOR || type == MTK_DISP_GAMMA || type == MTK_DISP_DSC || + type == MTK_DISP_MERGE || type == MTK_DPI || type == MTK_DSI || type == MTK_DISP_OVL ||diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.hb/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h index 661fb620e266..0afd78c0bc92 100644--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h@@ -35,6 +35,7 @@ enum mtk_ddp_comp_type { MTK_DISP_OD, MTK_DISP_BLS, MTK_DISP_DSC, + MTK_DISP_MERGE, MTK_DDP_COMP_TYPE_MAX, };diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.cb/drivers/gpu/drm/mediatek/mtk_drm_drv.c index 7dfca63c1042..24599fc0a597 100644--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c@@ -448,6 +448,8 @@ static const struct of_device_idmtk_ddp_comp_dt_ids[] = { .data = (void *)MTK_DISP_DITHER }, { .compatible = "mediatek,mt8195-disp-dsc", .data = (void *)MTK_DISP_DSC }, + { .compatible = "mediatek,mt8195-disp-merge", + .data = (void *)MTK_DISP_MERGE }, { .compatible = "mediatek,mt8173-disp-ufoe", .data = (void *)MTK_DISP_UFOE }, { .compatible = "mediatek,mt2701-dsi",@@ -566,6 +568,7 @@ static int mtk_drm_probe(struct platform_device*pdev) comp_type == MTK_DISP_COLOR || comp_type == MTK_DISP_GAMMA || comp_type == MTK_DISP_DSC || + comp_type == MTK_DISP_MERGE || comp_type == MTK_DISP_OVL || comp_type == MTK_DISP_OVL_2L || comp_type == MTK_DISP_RDMA ||@@ -671,6 +674,7 @@ static struct platform_driver * constmtk_drm_drivers[] = { &mtk_dpi_driver, &mtk_drm_platform_driver, &mtk_disp_dsc_driver, + &mtk_disp_merge_driver, &mtk_dsi_driver, };diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.hb/drivers/gpu/drm/mediatek/mtk_drm_drv.h index 8b722330ef7d..c4d802a43531 100644--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h@@ -52,6 +52,7 @@ extern struct platform_drivermtk_disp_gamma_driver; extern struct platform_driver mtk_disp_ovl_driver; extern struct platform_driver mtk_disp_rdma_driver; extern struct platform_driver mtk_disp_dsc_driver; +extern struct platform_driver mtk_disp_merge_driver; extern struct platform_driver mtk_dpi_driver; extern struct platform_driver mtk_dsi_driver; -- 2.18.0
-- Jason-JH Lin [off-list ref] _______________________________________________ Linux-mediatek mailing list Linux-mediatek@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-mediatek