Message ID | 20241205114518.53527-7-angelogioacchino.delregno@collabora.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | Add support for MT8195/88 DPI, HDMIv2 and DDCv2 | expand |
Hi, Angelo: On Thu, 2024-12-05 at 12:45 +0100, AngeloGioacchino Del Regno wrote: > External email : Please do not click links or open attachments until you have verified the sender or the content. > > > Add support for the DPI block found in the MT8195 and MT8188 SoCs. > Inside of the SoC, this block is directly connected to the HDMI IP. Note: there is discussion in [1]. [1] https://patchwork.kernel.org/project/linux-mediatek/patch/20241120124420.133914-7-angelogioacchino.delregno@collabora.com/ Regards, CK > > Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> > --- > drivers/gpu/drm/mediatek/mtk_dpi.c | 55 ++++++++++++++++++++++--- > drivers/gpu/drm/mediatek/mtk_dpi_regs.h | 6 +++ > drivers/gpu/drm/mediatek/mtk_drm_drv.c | 2 + > 3 files changed, 58 insertions(+), 5 deletions(-) > > diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c > index 79923d1bfbc9..f76d1c5b68bd 100644 > --- a/drivers/gpu/drm/mediatek/mtk_dpi.c > +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c > @@ -144,6 +144,7 @@ struct mtk_dpi_factor { > * @csc_enable_bit: Enable bit of CSC. > * @pixels_per_iter: Quantity of transferred pixels per iteration. > * @edge_cfg_in_mmsys: If the edge configuration for DPI's output needs to be set in MMSYS. > + * @is_internal_hdmi: Specifies whether the DPI is internally connected to the HDMI block > */ > struct mtk_dpi_conf { > const struct mtk_dpi_factor *dpi_factor; > @@ -164,6 +165,7 @@ struct mtk_dpi_conf { > u32 csc_enable_bit; > u32 pixels_per_iter; > bool edge_cfg_in_mmsys; > + bool is_internal_hdmi; > }; > > static void mtk_dpi_mask(struct mtk_dpi *dpi, u32 offset, u32 val, u32 mask) > @@ -492,6 +494,7 @@ static void mtk_dpi_power_off(struct mtk_dpi *dpi) > > mtk_dpi_disable(dpi); > clk_disable_unprepare(dpi->pixel_clk); > + clk_disable_unprepare(dpi->tvd_clk); > clk_disable_unprepare(dpi->engine_clk); > } > > @@ -508,6 +511,12 @@ static int mtk_dpi_power_on(struct mtk_dpi *dpi) > goto err_refcount; > } > > + ret = clk_prepare_enable(dpi->tvd_clk); > + if (ret) { > + dev_err(dpi->dev, "Failed to enable tvd pll: %d\n", ret); > + goto err_engine; > + } > + > ret = clk_prepare_enable(dpi->pixel_clk); > if (ret) { > dev_err(dpi->dev, "Failed to enable pixel clock: %d\n", ret); > @@ -517,6 +526,8 @@ static int mtk_dpi_power_on(struct mtk_dpi *dpi) > return 0; > > err_pixel: > + clk_disable_unprepare(dpi->tvd_clk); > +err_engine: > clk_disable_unprepare(dpi->engine_clk); > err_refcount: > dpi->refcount--; > @@ -584,7 +595,9 @@ static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi, > struct videomode vm = { 0 }; > > drm_display_mode_to_videomode(mode, &vm); > - mtk_dpi_set_pixel_clk(dpi, &vm, mode->clock); > + > + if (!dpi->conf->is_internal_hdmi) > + mtk_dpi_set_pixel_clk(dpi, &vm, mode->clock); > > dpi_pol.ck_pol = MTK_DPI_POLARITY_FALLING; > dpi_pol.de_pol = MTK_DPI_POLARITY_RISING; > @@ -647,10 +660,18 @@ static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi, > if (dpi->conf->support_direct_pin) { > mtk_dpi_config_yc_map(dpi, dpi->yc_map); > mtk_dpi_config_2n_h_fre(dpi); > - mtk_dpi_dual_edge(dpi); > + /* DPI can connect to either an external bridge or the internal HDMI encoder */ > + if (dpi->conf->is_internal_hdmi) { > + mtk_dpi_mask(dpi, DPI_CON, DPI_OUTPUT_1T1P_EN, DPI_OUTPUT_1T1P_EN); > + mtk_dpi_mask(dpi, DPI_CON, > + dpi->conf->input_2pixel ? DPI_INPUT_2P_EN : 0, > + DPI_INPUT_2P_EN); > + } else { > + mtk_dpi_dual_edge(dpi); > + } > mtk_dpi_config_disable_edge(dpi); > } > - if (dpi->conf->input_2pixel) { > + if (dpi->conf->input_2pixel && !dpi->conf->is_internal_hdmi) { > mtk_dpi_mask(dpi, DPI_CON, DPINTF_INPUT_2P_EN, > DPINTF_INPUT_2P_EN); > } > @@ -919,14 +940,16 @@ void mtk_dpi_start(struct device *dev) > { > struct mtk_dpi *dpi = dev_get_drvdata(dev); > > - mtk_dpi_power_on(dpi); > + if (!dpi->conf->is_internal_hdmi) > + mtk_dpi_power_on(dpi); > } > > void mtk_dpi_stop(struct device *dev) > { > struct mtk_dpi *dpi = dev_get_drvdata(dev); > > - mtk_dpi_power_off(dpi); > + if (!dpi->conf->is_internal_hdmi) > + mtk_dpi_power_off(dpi); > } > > unsigned int mtk_dpi_encoder_index(struct device *dev) > @@ -1021,6 +1044,8 @@ static const struct mtk_dpi_factor dpi_factor_mt8195_dp_intf[] = { > { 70000 - 1, 4 }, { 200000 - 1, 2 }, { U32_MAX, 1 } > }; > > +static const struct mtk_dpi_factor dpi_factor_mt8195_dpi = { U32_MAX, 1 }; > + > static const struct mtk_dpi_conf mt8173_conf = { > .dpi_factor = dpi_factor_mt8173, > .num_dpi_factor = ARRAY_SIZE(dpi_factor_mt8173), > @@ -1113,6 +1138,25 @@ static const struct mtk_dpi_conf mt8192_conf = { > .csc_enable_bit = CSC_ENABLE, > }; > > +static const struct mtk_dpi_conf mt8195_conf = { > + .dpi_factor = &dpi_factor_mt8195_dpi, > + .num_dpi_factor = 1, > + .max_clock_khz = 594000, > + .output_fmts = mt8183_output_fmts, > + .num_output_fmts = ARRAY_SIZE(mt8183_output_fmts), > + .pixels_per_iter = 1, > + .is_ck_de_pol = true, > + .swap_input_support = true, > + .support_direct_pin = true, > + .dimension_mask = HPW_MASK, > + .hvsize_mask = HSIZE_MASK, > + .channel_swap_shift = CH_SWAP, > + .yuv422_en_bit = YUV422_EN, > + .csc_enable_bit = CSC_ENABLE, > + .is_internal_hdmi = true, > + .input_2pixel = true, > +}; > + > static const struct mtk_dpi_conf mt8195_dpintf_conf = { > .dpi_factor = dpi_factor_mt8195_dp_intf, > .num_dpi_factor = ARRAY_SIZE(dpi_factor_mt8195_dp_intf), > @@ -1216,6 +1260,7 @@ static const struct of_device_id mtk_dpi_of_ids[] = { > { .compatible = "mediatek,mt8188-dp-intf", .data = &mt8195_dpintf_conf }, > { .compatible = "mediatek,mt8192-dpi", .data = &mt8192_conf }, > { .compatible = "mediatek,mt8195-dp-intf", .data = &mt8195_dpintf_conf }, > + { .compatible = "mediatek,mt8195-dpi", .data = &mt8195_conf }, > { /* sentinel */ }, > }; > MODULE_DEVICE_TABLE(of, mtk_dpi_of_ids); > diff --git a/drivers/gpu/drm/mediatek/mtk_dpi_regs.h b/drivers/gpu/drm/mediatek/mtk_dpi_regs.h > index a0b1d18bbbf7..3c24d9e9f241 100644 > --- a/drivers/gpu/drm/mediatek/mtk_dpi_regs.h > +++ b/drivers/gpu/drm/mediatek/mtk_dpi_regs.h > @@ -40,6 +40,12 @@ > #define FAKE_DE_LEVEN BIT(21) > #define FAKE_DE_RODD BIT(22) > #define FAKE_DE_REVEN BIT(23) > + > +/* DPI_CON: DPI instances */ > +#define DPI_OUTPUT_1T1P_EN BIT(24) > +#define DPI_INPUT_2P_EN BIT(25) > + > +/* DPI_CON: DPINTF instances */ > #define DPINTF_YUV422_EN BIT(24) > #define DPINTF_CSC_ENABLE BIT(26) > #define DPINTF_INPUT_2P_EN BIT(29) > diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c > index 9a8ef8558da9..ba4539150f52 100644 > --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c > +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c > @@ -807,6 +807,8 @@ static const struct of_device_id mtk_ddp_comp_dt_ids[] = { > .data = (void *)MTK_DPI }, > { .compatible = "mediatek,mt8195-dp-intf", > .data = (void *)MTK_DP_INTF }, > + { .compatible = "mediatek,mt8195-dpi", > + .data = (void *)MTK_DPI }, > { .compatible = "mediatek,mt2701-dsi", > .data = (void *)MTK_DSI }, > { .compatible = "mediatek,mt8173-dsi", > -- > 2.47.0 >
diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c index 79923d1bfbc9..f76d1c5b68bd 100644 --- a/drivers/gpu/drm/mediatek/mtk_dpi.c +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c @@ -144,6 +144,7 @@ struct mtk_dpi_factor { * @csc_enable_bit: Enable bit of CSC. * @pixels_per_iter: Quantity of transferred pixels per iteration. * @edge_cfg_in_mmsys: If the edge configuration for DPI's output needs to be set in MMSYS. + * @is_internal_hdmi: Specifies whether the DPI is internally connected to the HDMI block */ struct mtk_dpi_conf { const struct mtk_dpi_factor *dpi_factor; @@ -164,6 +165,7 @@ struct mtk_dpi_conf { u32 csc_enable_bit; u32 pixels_per_iter; bool edge_cfg_in_mmsys; + bool is_internal_hdmi; }; static void mtk_dpi_mask(struct mtk_dpi *dpi, u32 offset, u32 val, u32 mask) @@ -492,6 +494,7 @@ static void mtk_dpi_power_off(struct mtk_dpi *dpi) mtk_dpi_disable(dpi); clk_disable_unprepare(dpi->pixel_clk); + clk_disable_unprepare(dpi->tvd_clk); clk_disable_unprepare(dpi->engine_clk); } @@ -508,6 +511,12 @@ static int mtk_dpi_power_on(struct mtk_dpi *dpi) goto err_refcount; } + ret = clk_prepare_enable(dpi->tvd_clk); + if (ret) { + dev_err(dpi->dev, "Failed to enable tvd pll: %d\n", ret); + goto err_engine; + } + ret = clk_prepare_enable(dpi->pixel_clk); if (ret) { dev_err(dpi->dev, "Failed to enable pixel clock: %d\n", ret); @@ -517,6 +526,8 @@ static int mtk_dpi_power_on(struct mtk_dpi *dpi) return 0; err_pixel: + clk_disable_unprepare(dpi->tvd_clk); +err_engine: clk_disable_unprepare(dpi->engine_clk); err_refcount: dpi->refcount--; @@ -584,7 +595,9 @@ static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi, struct videomode vm = { 0 }; drm_display_mode_to_videomode(mode, &vm); - mtk_dpi_set_pixel_clk(dpi, &vm, mode->clock); + + if (!dpi->conf->is_internal_hdmi) + mtk_dpi_set_pixel_clk(dpi, &vm, mode->clock); dpi_pol.ck_pol = MTK_DPI_POLARITY_FALLING; dpi_pol.de_pol = MTK_DPI_POLARITY_RISING; @@ -647,10 +660,18 @@ static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi, if (dpi->conf->support_direct_pin) { mtk_dpi_config_yc_map(dpi, dpi->yc_map); mtk_dpi_config_2n_h_fre(dpi); - mtk_dpi_dual_edge(dpi); + /* DPI can connect to either an external bridge or the internal HDMI encoder */ + if (dpi->conf->is_internal_hdmi) { + mtk_dpi_mask(dpi, DPI_CON, DPI_OUTPUT_1T1P_EN, DPI_OUTPUT_1T1P_EN); + mtk_dpi_mask(dpi, DPI_CON, + dpi->conf->input_2pixel ? DPI_INPUT_2P_EN : 0, + DPI_INPUT_2P_EN); + } else { + mtk_dpi_dual_edge(dpi); + } mtk_dpi_config_disable_edge(dpi); } - if (dpi->conf->input_2pixel) { + if (dpi->conf->input_2pixel && !dpi->conf->is_internal_hdmi) { mtk_dpi_mask(dpi, DPI_CON, DPINTF_INPUT_2P_EN, DPINTF_INPUT_2P_EN); } @@ -919,14 +940,16 @@ void mtk_dpi_start(struct device *dev) { struct mtk_dpi *dpi = dev_get_drvdata(dev); - mtk_dpi_power_on(dpi); + if (!dpi->conf->is_internal_hdmi) + mtk_dpi_power_on(dpi); } void mtk_dpi_stop(struct device *dev) { struct mtk_dpi *dpi = dev_get_drvdata(dev); - mtk_dpi_power_off(dpi); + if (!dpi->conf->is_internal_hdmi) + mtk_dpi_power_off(dpi); } unsigned int mtk_dpi_encoder_index(struct device *dev) @@ -1021,6 +1044,8 @@ static const struct mtk_dpi_factor dpi_factor_mt8195_dp_intf[] = { { 70000 - 1, 4 }, { 200000 - 1, 2 }, { U32_MAX, 1 } }; +static const struct mtk_dpi_factor dpi_factor_mt8195_dpi = { U32_MAX, 1 }; + static const struct mtk_dpi_conf mt8173_conf = { .dpi_factor = dpi_factor_mt8173, .num_dpi_factor = ARRAY_SIZE(dpi_factor_mt8173), @@ -1113,6 +1138,25 @@ static const struct mtk_dpi_conf mt8192_conf = { .csc_enable_bit = CSC_ENABLE, }; +static const struct mtk_dpi_conf mt8195_conf = { + .dpi_factor = &dpi_factor_mt8195_dpi, + .num_dpi_factor = 1, + .max_clock_khz = 594000, + .output_fmts = mt8183_output_fmts, + .num_output_fmts = ARRAY_SIZE(mt8183_output_fmts), + .pixels_per_iter = 1, + .is_ck_de_pol = true, + .swap_input_support = true, + .support_direct_pin = true, + .dimension_mask = HPW_MASK, + .hvsize_mask = HSIZE_MASK, + .channel_swap_shift = CH_SWAP, + .yuv422_en_bit = YUV422_EN, + .csc_enable_bit = CSC_ENABLE, + .is_internal_hdmi = true, + .input_2pixel = true, +}; + static const struct mtk_dpi_conf mt8195_dpintf_conf = { .dpi_factor = dpi_factor_mt8195_dp_intf, .num_dpi_factor = ARRAY_SIZE(dpi_factor_mt8195_dp_intf), @@ -1216,6 +1260,7 @@ static const struct of_device_id mtk_dpi_of_ids[] = { { .compatible = "mediatek,mt8188-dp-intf", .data = &mt8195_dpintf_conf }, { .compatible = "mediatek,mt8192-dpi", .data = &mt8192_conf }, { .compatible = "mediatek,mt8195-dp-intf", .data = &mt8195_dpintf_conf }, + { .compatible = "mediatek,mt8195-dpi", .data = &mt8195_conf }, { /* sentinel */ }, }; MODULE_DEVICE_TABLE(of, mtk_dpi_of_ids); diff --git a/drivers/gpu/drm/mediatek/mtk_dpi_regs.h b/drivers/gpu/drm/mediatek/mtk_dpi_regs.h index a0b1d18bbbf7..3c24d9e9f241 100644 --- a/drivers/gpu/drm/mediatek/mtk_dpi_regs.h +++ b/drivers/gpu/drm/mediatek/mtk_dpi_regs.h @@ -40,6 +40,12 @@ #define FAKE_DE_LEVEN BIT(21) #define FAKE_DE_RODD BIT(22) #define FAKE_DE_REVEN BIT(23) + +/* DPI_CON: DPI instances */ +#define DPI_OUTPUT_1T1P_EN BIT(24) +#define DPI_INPUT_2P_EN BIT(25) + +/* DPI_CON: DPINTF instances */ #define DPINTF_YUV422_EN BIT(24) #define DPINTF_CSC_ENABLE BIT(26) #define DPINTF_INPUT_2P_EN BIT(29) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c index 9a8ef8558da9..ba4539150f52 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c @@ -807,6 +807,8 @@ static const struct of_device_id mtk_ddp_comp_dt_ids[] = { .data = (void *)MTK_DPI }, { .compatible = "mediatek,mt8195-dp-intf", .data = (void *)MTK_DP_INTF }, + { .compatible = "mediatek,mt8195-dpi", + .data = (void *)MTK_DPI }, { .compatible = "mediatek,mt2701-dsi", .data = (void *)MTK_DSI }, { .compatible = "mediatek,mt8173-dsi",
Add support for the DPI block found in the MT8195 and MT8188 SoCs. Inside of the SoC, this block is directly connected to the HDMI IP. Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> --- drivers/gpu/drm/mediatek/mtk_dpi.c | 55 ++++++++++++++++++++++--- drivers/gpu/drm/mediatek/mtk_dpi_regs.h | 6 +++ drivers/gpu/drm/mediatek/mtk_drm_drv.c | 2 + 3 files changed, 58 insertions(+), 5 deletions(-)