<html><body><p>
<pre>
On Mon, 2025-04-07 at 21:31 +0800, Bincai Liu wrote:
> Add dsi and mipi phy driver for mt8196.
>
> Signed-off-by: Bincai Liu <bincai.liu@mediatek.com>
> ---
> drivers/gpu/drm/mediatek/mtk_drm_drv.c | 2 +
> drivers/gpu/drm/mediatek/mtk_dsi.c | 248 +++++++++++-------
> drivers/phy/mediatek/Makefile | 1 +
> .../phy/mediatek/phy-mtk-mipi-dsi-mt8196.c | 201 ++++++++++++++
> drivers/phy/mediatek/phy-mtk-mipi-dsi.c | 1 +
> drivers/phy/mediatek/phy-mtk-mipi-dsi.h | 1 +
Separate drm driver and phy driver to different patch.
> 6 files changed, 356 insertions(+), 98 deletions(-)
> create mode 100644 drivers/phy/mediatek/phy-mtk-mipi-dsi-mt8196.c
>
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> index 74158b9d6503..ae859f20fab3 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> @@ -830,6 +830,8 @@ static const struct of_device_id mtk_ddp_comp_dt_ids[] = {
> .data = (void *)MTK_DSI },
> { .compatible = "mediatek,mt8188-dsi",
> .data = (void *)MTK_DSI },
> +{ .compatible = "mediatek,mt8196-dsi",
> + .data = (void *)MTK_DSI },
> { }
> };
>
> diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
> index d1f407fb7eb1..b1467d6bed06 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dsi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
> @@ -44,12 +44,12 @@
> #define EXT_TE_RDY_INT_FLAGBIT(4)
> #define DSI_BUSYBIT(31)
>
> -#define DSI_CON_CTRL0x10
> +#define DSI_CON_CTRL(data)(0x10 + (data)->reg_20_ofs)
I do not like the term reg_20_ofs.
It limit that the offset should be zero or 20.
If a new SoC its offset is 30 for DSI_CON_CTRL, this code would be modified again.
May be reg_ctrl_off for all the register name has 'CTRL'.
> #define DSI_RESETBIT(0)
> #define DSI_ENBIT(1)
> #define DPHY_RESETBIT(2)
>
> -#define DSI_MODE_CTRL0x14
> +#define DSI_MODE_CTRL(data)(0x14 + (data)->reg_20_ofs)
> #define MODE(3)
> #define CMD_MODE0
> #define SYNC_PULSE_MODE1
> @@ -58,7 +58,7 @@
> #define FRM_MODEBIT(16)
> #define MIX_MODEBIT(17)
>
> -#define DSI_TXRX_CTRL0x18
> +#define DSI_TXRX_CTRL(data)(0x18 + (data)->reg_20_ofs)
> #define VC_NUMBIT(1)
> #define LANE_NUMGENMASK(5, 2)
> #define DIS_EOTBIT(6)
> @@ -69,81 +69,87 @@
> #define MAX_RTN_SIZEGENMASK(15, 12)
> #define HSTX_CKLP_ENBIT(16)
>
> -#define DSI_PSCTRL0x1c
> +#define DSI_PSCTRL(data)(0x1c + (data)->reg_20_ofs)
> #define DSI_PS_WCGENMASK(13, 0)
> -#define DSI_PS_SELGENMASK(17, 16)
> +#define DSI_PS_SELGENMASK(19, 16)
> #define PACKED_PS_16BIT_RGB5650
> #define PACKED_PS_18BIT_RGB6661
> #define LOOSELY_PS_24BIT_RGB6662
> #define PACKED_PS_24BIT_RGB8883
>
> -#define DSI_VSA_NL0x20
> -#define DSI_VBP_NL0x24
> -#define DSI_VFP_NL0x28
> -#define DSI_VACT_NL0x2C
> +#define DSI_VSA_NL(data)(0x20 + (data)->reg_40_ofs)
reg_nl_off.
> +#define DSI_VBP_NL(data)(0x24 + (data)->reg_40_ofs)
> +#define DSI_VFP_NL(data)(0x28 + (data)->reg_40_ofs)
> +#define DSI_VACT_NL(data)(0x2c + (data)->reg_40_ofs)
> #define VACT_NLGENMASK(14, 0)
> -#define DSI_SIZE_CON0x38
> +#define DSI_SIZE_CON(data)((data)->dsi_size_con ? \
> +(data)->dsi_size_con : 0x38)
> #define DSI_HEIGHTGENMASK(30, 16)
> #define DSI_WIDTHGENMASK(14, 0)
> -#define DSI_HSA_WC0x50
> -#define DSI_HBP_WC0x54
> -#define DSI_HFP_WC0x58
> +#define DSI_HSA_WC(data)(0x50 + (data)->reg_30_ofs)
reg_wc_off.
> +#define DSI_HBP_WC(data)(0x54 + (data)->reg_30_ofs)
> +#define DSI_HFP_WC(data)(0x58 + (data)->reg_30_ofs)
> #define HFP_HS_VB_PS_WCGENMASK(30, 16)
> #define HFP_HS_ENBIT(31)
>
> -#define DSI_CMDQ_SIZE0x60
> +#define DSI_CMDQ_SIZE(data)((data)->dsi_cmdq_con ? \
> +(data)->dsi_cmdq_con : 0x60)
> #define CMDQ_SIZE0x3f
> #define CMDQ_SIZE_SELBIT(15)
>
> -#define DSI_HSTX_CKL_WC0x64
> +#define DSI_HSTX_CKL_WC(data)((data)->dsi_hstx_ckl_wc ? \
> +(data)->dsi_hstx_ckl_wc : 0x64)
> #define HSTX_CKL_WCGENMASK(15, 2)
>
> -#define DSI_RX_DATA00x74
> -#define DSI_RX_DATA10x78
> -#define DSI_RX_DATA20x7c
> -#define DSI_RX_DATA30x80
> +#define DSI_RX_DATA0(data)(0x74 + (data)->reg_30_ofs)
reg_rx_off
> +#define DSI_RX_DATA1(data)(0x78 + (data)->reg_30_ofs)
> +#define DSI_RX_DATA2(data)(0x7c + (data)->reg_30_ofs)
> +#define DSI_RX_DATA3(data)(0x80 + (data)->reg_30_ofs)
>
> -#define DSI_RACK0x84
> +#define DSI_RACK(data)(0x84 + (data)->reg_30_ofs)
> #define RACKBIT(0)
>
> -#define DSI_PHY_LCCON0x104
> +#define DSI_PHY_LCCON(data)((data)->reg_phy_base ? 0x1d0 : 0x104)
> #define LC_HS_TX_ENBIT(0)
> #define LC_ULPM_ENBIT(1)
> #define LC_WAKEUP_ENBIT(2)
>
> -#define DSI_PHY_LD0CON0x108
> +#define DSI_PHY_LD0CON(data)((data)->reg_phy_base ? 0x1d4 : 0x108)
> #define LD0_HS_TX_ENBIT(0)
> #define LD0_ULPM_ENBIT(1)
> #define LD0_WAKEUP_ENBIT(2)
>
> -#define DSI_PHY_TIMECON00x110
> -#define LPXGENMASK(7, 0)
> -#define HS_PREPGENMASK(15, 8)
> -#define HS_ZEROGENMASK(23, 16)
> -#define HS_TRAILGENMASK(31, 24)
> -
> -#define DSI_PHY_TIMECON10x114
> -#define TA_GOGENMASK(7, 0)
> -#define TA_SUREGENMASK(15, 8)
> -#define TA_GETGENMASK(23, 16)
> -#define DA_HS_EXITGENMASK(31, 24)
> -
> -#define DSI_PHY_TIMECON20x118
> -#define CONT_DETGENMASK(7, 0)
> -#define DA_HS_SYNCGENMASK(15, 8)
> -#define CLK_ZEROGENMASK(23, 16)
> -#define CLK_TRAILGENMASK(31, 24)
> -
> -#define DSI_PHY_TIMECON30x11c
> -#define CLK_HS_PREPGENMASK(7, 0)
> -#define CLK_HS_POSTGENMASK(15, 8)
> -#define CLK_HS_EXITGENMASK(23, 16)
> +#define DSI_PHY_TIMECON0(data)((data)->reg_phy_base ? \
> +(data)->reg_phy_base : 0x110)
> +#define LPX(0xff << 0)
Keep GENMASK, do not modify this.
> +#define HS_PREP(0xff << 8)
> +#define HS_ZERO(0xff << 16)
> +#define HS_TRAIL(0xff << 24)
> +
> +#define DSI_PHY_TIMECON1(data)(DSI_PHY_TIMECON0(data) + 0x4)
Let all SoC has (data)->reg_phy_base value (0x110 for old SoC).
And this would be
#define DSI_PHY_TIMECON0(data)(data)->reg_phy_base
#define DSI_PHY_TIMECON1(data)((data)->reg_phy_base + 0x4)
> +#define TA_GO(0xff << 0)
> +#define TA_SURE(0xff << 8)
> +#define TA_GET(0xff << 16)
> +#define DA_HS_EXIT(0xff << 24)
> +
> +#define DSI_PHY_TIMECON2(data)(DSI_PHY_TIMECON0(data) + 0x8)
> +#define CONT_DET(0xff << 0)
> +#define DA_HS_SYNC(0xff << 8)
> +#define CLK_ZERO(0xff << 16)
> +#define CLK_TRAIL(0xff << 24)
> +
> +#define DSI_PHY_TIMECON3(data)(DSI_PHY_TIMECON0(data) + 0xc)
> +#define CLK_HS_PREP(0xff << 0)
> +#define CLK_HS_POST(0xff << 8)
> +#define CLK_HS_EXIT(0xff << 16)
>
> /* DSI_VM_CMD_CON */
> #define VM_CMD_ENBIT(0)
> #define TS_VFP_ENBIT(5)
>
> /* DSI_SHADOW_DEBUG */
> +#define DSI_SHADOW_DEBUG(data)((data)->dsi_shadow_dbg ? \
> +(data)->dsi_shadow_dbg : 0x190)
> #define FORCE_COMMITBIT(0)
> #define BYPASS_SHADOWBIT(1)
>
> @@ -193,6 +199,24 @@ struct mtk_dsi_driver_data {
> bool has_size_ctl;
> bool cmdq_long_packet_ctl;
> bool support_per_frame_lp;
> +const u32 reg_phy_base;
> +const u32 reg_20_ofs;
> +const u32 reg_30_ofs;
> +const u32 reg_40_ofs;
> +const u32 reg_100_ofs;
> +const u32 dsi_size_con;
> +const u32 dsi_vfp_early_stop;
Useless, so drop it.
> +const u32 dsi_lfr_con;
Ditto.
> +const u32 dsi_cmdq_con;
> +const u32 dsi_type1_hs;
Ditto.
> +const u32 dsi_hstx_ckl_wc;
> +const u32 dsi_mem_conti;
Ditto.
> +const u32 dsi_time_con;
Ditto.
> +const u32 dsi_reserved;
Ditto.
> +const u32 dsi_state_dbg6;
Ditto.
> +const u32 dsi_dbg_sel;
Ditto.
> +const u32 dsi_shadow_dbg;
There is already reg_shadow_dbg_off.
Use reg_shadow_dbg_off for mt8196.
So drop this.
> +const u32 dsi_vm_cmd_con;
There is already reg_vm_cmd_off.
Use reg_vm_cmd_off for mt8196.
So drop this.
> };
>
> struct mtk_dsi {
> @@ -283,71 +307,71 @@ static void mtk_dsi_phy_timconfig(struct mtk_dsi *dsi)
> FIELD_PREP(CLK_HS_POST, timing->clk_hs_post) |
> FIELD_PREP(CLK_HS_EXIT, timing->clk_hs_exit);
>
> -writel(timcon0, dsi->regs + DSI_PHY_TIMECON0);
> -writel(timcon1, dsi->regs + DSI_PHY_TIMECON1);
> -writel(timcon2, dsi->regs + DSI_PHY_TIMECON2);
> -writel(timcon3, dsi->regs + DSI_PHY_TIMECON3);
> +writel(timcon0, dsi->regs + DSI_PHY_TIMECON0(dsi->driver_data));
> +writel(timcon1, dsi->regs + DSI_PHY_TIMECON1(dsi->driver_data));
> +writel(timcon2, dsi->regs + DSI_PHY_TIMECON2(dsi->driver_data));
> +writel(timcon3, dsi->regs + DSI_PHY_TIMECON3(dsi->driver_data));
> }
>
[snip]
> +
> +static const struct mtk_dsi_driver_data mt8196_dsi_driver_data = {
> +.reg_cmdq_off = 0x400,
> +.has_shadow_ctl = true,
> +.has_size_ctl = true,
> +.cmdq_long_packet_ctl = true,
> +.support_per_frame_lp = true,
> +.reg_phy_base = 0x600,
> +.reg_20_ofs = 0x020,
> +.reg_30_ofs = 0x030,
> +.reg_40_ofs = 0x040,
> +.reg_100_ofs = 0x100,
> +.dsi_size_con = 0x02c,
> +.dsi_vfp_early_stop = 0x170,
> +.dsi_lfr_con = 0x1a0,
> +.dsi_cmdq_con = 0x44,
> +.dsi_type1_hs = 0x50,
> +.dsi_hstx_ckl_wc = 0x100,
> +.dsi_mem_conti = 0x048,
> +.dsi_time_con = 0x200,
> +.dsi_reserved = 0x3f8,
> +.dsi_state_dbg6 = 0x274,
> +.dsi_dbg_sel = 0x274,
> +.dsi_shadow_dbg = 0x0d0,
> +.dsi_vm_cmd_con = 0x110,
> };
Separate mt8196_dsi_driver_data to an independent patch which is adding mt8196 dsi support.
And the rest is a preparing patch which support variant register offset.
>
> static const struct of_device_id mtk_dsi_of_match[] = {
> @@ -1304,6 +1355,7 @@ static const struct of_device_id mtk_dsi_of_match[] = {
> { .compatible = "mediatek,mt8183-dsi", .data = &mt8183_dsi_driver_data },
> { .compatible = "mediatek,mt8186-dsi", .data = &mt8186_dsi_driver_data },
> { .compatible = "mediatek,mt8188-dsi", .data = &mt8188_dsi_driver_data },
> +{ .compatible = "mediatek,mt8196-dsi", .data = &mt8196_dsi_driver_data },
> { /* sentinel */ }
> };
> MODULE_DEVICE_TABLE(of, mtk_dsi_of_match);
> diff --git a/drivers/phy/mediatek/Makefile b/drivers/phy/mediatek/Makefile
> index 1b8088df71e8..ed0da708759b 100644
> --- a/drivers/phy/mediatek/Makefile
> +++ b/drivers/phy/mediatek/Makefile
> @@ -21,4 +21,5 @@ obj-$(CONFIG_PHY_MTK_MIPI_CSI_0_5)+= phy-mtk-mipi-csi-0-5.o
> phy-mtk-mipi-dsi-drv-y:= phy-mtk-mipi-dsi.o
> phy-mtk-mipi-dsi-drv-y+= phy-mtk-mipi-dsi-mt8173.o
> phy-mtk-mipi-dsi-drv-y+= phy-mtk-mipi-dsi-mt8183.o
> +phy-mtk-mipi-dsi-drv-y+= phy-mtk-mipi-dsi-mt8196.o
> obj-$(CONFIG_PHY_MTK_MIPI_DSI)+= phy-mtk-mipi-dsi-drv.o
> diff --git a/drivers/phy/mediatek/phy-mtk-mipi-dsi-mt8196.c b/drivers/phy/mediatek/phy-mtk-mipi-dsi-mt8196.c
> new file mode 100644
> index 000000000000..09c7159748d7
> --- /dev/null
> +++ b/drivers/phy/mediatek/phy-mtk-mipi-dsi-mt8196.c
> @@ -0,0 +1,201 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2019 MediaTek Inc.
> + * Author: jitao.shi <jitao.shi@mediatek.com>
> + */
> +
[snip]
> +
> +static void mtk_mipi_tx_power_off_signal(struct phy *phy)
> +{
> +struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy);
> +void __iomem *base = mipi_tx->regs;
> +
> +/* Switch ON each Lane */
> +mtk_phy_set_bits(base + MIPITX_D0_SW_CTL_EN, DSI_SW_CTL_EN);
> +mtk_phy_set_bits(base + MIPITX_D1_SW_CTL_EN, DSI_SW_CTL_EN);
> +mtk_phy_set_bits(base + MIPITX_D2_SW_CTL_EN, DSI_SW_CTL_EN);
> +mtk_phy_set_bits(base + MIPITX_D3_SW_CTL_EN, DSI_SW_CTL_EN);
> +mtk_phy_set_bits(base + MIPITX_CK_SW_CTL_EN, DSI_SW_CTL_EN);
> +
> +writel(RG_DSI_PAD_TIEL_SEL | RG_DSI_BG_CORE_EN, base + MIPITX_LANE_CON);
> +writel(RG_DSI_PAD_TIEL_SEL, base + MIPITX_LANE_CON);
> +}
> +
> +const struct mtk_mipitx_data mt8196_mipitx_data = {
> +.mipi_tx_clk_ops = &mtk_mipi_tx_pll_ops,
> +.mipi_tx_enable_signal = mtk_mipi_tx_power_on_signal,
> +.mipi_tx_disable_signal = mtk_mipi_tx_power_off_signal,
> +};
phy-mtk-mipi-dsi-mt8196.c is almost the same as phy-mtk-mipi-dsi-mt8183.c
so merge these two files into one files.
You could reference phy-mtk-mipi-dsi-mt8173.c
Regards,
CK
> diff --git a/drivers/phy/mediatek/phy-mtk-mipi-dsi.c b/drivers/phy/mediatek/phy-mtk-mipi-dsi.c
> index 065ea626093a..46f0cb3ac096 100644
> --- a/drivers/phy/mediatek/phy-mtk-mipi-dsi.c
> +++ b/drivers/phy/mediatek/phy-mtk-mipi-dsi.c
> @@ -183,6 +183,7 @@ static const struct of_device_id mtk_mipi_tx_match[] = {
> { .compatible = "mediatek,mt2701-mipi-tx", .data = &mt2701_mipitx_data },
> { .compatible = "mediatek,mt8173-mipi-tx", .data = &mt8173_mipitx_data },
> { .compatible = "mediatek,mt8183-mipi-tx", .data = &mt8183_mipitx_data },
> +{ .compatible = "mediatek,mt8196-mipi-tx", .data = &mt8196_mipitx_data },
> { /* sentinel */ }
> };
> MODULE_DEVICE_TABLE(of, mtk_mipi_tx_match);
> diff --git a/drivers/phy/mediatek/phy-mtk-mipi-dsi.h b/drivers/phy/mediatek/phy-mtk-mipi-dsi.h
> index 5d4876f1dc95..38f64e1c75aa 100644
> --- a/drivers/phy/mediatek/phy-mtk-mipi-dsi.h
> +++ b/drivers/phy/mediatek/phy-mtk-mipi-dsi.h
> @@ -42,5 +42,6 @@ unsigned long mtk_mipi_tx_pll_recalc_rate(struct clk_hw *hw,
> extern const struct mtk_mipitx_data mt2701_mipitx_data;
> extern const struct mtk_mipitx_data mt8173_mipitx_data;
> extern const struct mtk_mipitx_data mt8183_mipitx_data;
> +extern const struct mtk_mipitx_data mt8196_mipitx_data;
>
> #endif
</pre>
</p></body></html><!--type:text--><!--{--><pre>************* MEDIATEK Confidentiality Notice
********************
The information contained in this e-mail message (including any
attachments) may be confidential, proprietary, privileged, or otherwise
exempt from disclosure under applicable laws. It is intended to be
conveyed only to the designated recipient(s). Any use, dissemination,
distribution, printing, retaining or copying of this e-mail (including its
attachments) by unintended recipient(s) is strictly prohibited and may
be unlawful. If you are not an intended recipient of this e-mail, or believe
that you have received this e-mail in error, please notify the sender
immediately (by replying to this e-mail), delete any and all copies of
this e-mail (including any attachments) from your system, and do not
disclose the content of this e-mail to any other person. Thank you!
</pre><!--}-->