Thread (25 messages) 25 messages, 4 authors, 2021-07-16

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.c
diff --git a/drivers/gpu/drm/mediatek/Makefile
b/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.h
b/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, unsigned
int 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);
+
 #endif
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_merge.c
b/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      0x044
Useless, 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.h
b/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.c
b/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 * const
mtk_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_match
mtk_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.h
b/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.c
b/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_id
mtk_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 * const
mtk_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.h
b/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_driver
mtk_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
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help