Newer MediaTek DSI IPs, found in newer SoCs like MT8189 and others
can support a higher link rate up to 2.5Gbps, while older ones are
limited to 1.5Gbps.

In preparation for adding support for those, move the maximum link
rate parameter from being a magic number in mtk_dsi's .mode_valid()
callback to platform data, declared for each SoC.

Note that said number was previously expressed in Kbps but, in the
platform data member, it is now expressed in Mbps instead in order
to keep the mtk_dsi_driver_data structure footprint smaller: for
this, the calculation in mtk_dsi_bridge_mode_valid() was changed
to multiply the max_link_rate_mbps parameter by KILO (1000), which
brings the value back to Kbps.

Also, since now higher maximum pixel clock rates are achievable,
make sure that calculations are not overflowing by casting to u64
where needed.

In terms of wasted cycles, this is fine, because this callback is
executed only once during display IF enablement (at boot, after a
resume from suspend, or during runtime display resolution changes).

Signed-off-by: AngeloGioacchino Del Regno 
<[email protected]>
---
 drivers/gpu/drm/mediatek/mtk_dsi.c | 29 +++++++++++++++++++++++++++--
 1 file changed, 27 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c 
b/drivers/gpu/drm/mediatek/mtk_dsi.c
index fa0f404bc7ad..6e92e4e1586f 100644
--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
@@ -234,6 +234,8 @@ struct mtk_dsi_driver_data {
        const u16 *reg_main;
        const u16 *reg_adv;
 
+       const u16 max_link_rate_mbps;
+
        bool has_size_ctl;
        bool cmdq_long_packet_ctl;
        bool support_per_frame_lp;
@@ -921,7 +923,7 @@ static int mtk_dsi_poweron(struct mtk_dsi *dsi)
        }
        bit_per_pixel = ret;
 
-       dsi->data_rate = DIV_ROUND_UP_ULL(dsi->vm.pixelclock * bit_per_pixel,
+       dsi->data_rate = DIV_ROUND_UP_ULL((u64)dsi->vm.pixelclock * 
bit_per_pixel,
                                          dsi->lanes);
 
        ret = clk_set_rate(dsi->hs_clk, dsi->data_rate);
@@ -1097,13 +1099,21 @@ mtk_dsi_bridge_mode_valid(struct drm_bridge *bridge,
                          const struct drm_display_mode *mode)
 {
        struct mtk_dsi *dsi = bridge_to_dsi(bridge);
+       const struct mtk_dsi_driver_data *data = dsi->driver_data;
+       u64 wanted_link_rate, max_link_rate;
        int bpp;
 
        bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
        if (bpp < 0)
                return MODE_ERROR;
 
-       if (mode->clock * bpp / dsi->lanes > 1500000)
+       wanted_link_rate = mode->clock;
+       wanted_link_rate *= bpp;
+       max_link_rate = data->max_link_rate_mbps;
+       max_link_rate *= dsi->lanes;
+       max_link_rate *= KILO;
+
+       if (wanted_link_rate > max_link_rate)
                return MODE_CLOCK_HIGH;
 
        if (dsi->dsc) {
@@ -1547,28 +1557,42 @@ static void mtk_dsi_remove(struct platform_device *pdev)
 static const struct mtk_dsi_driver_data mt8173_dsi_driver_data = {
        .reg_main = mtk_dsi_regs_main_v1,
        .reg_adv = mtk_dsi_regs_mt8173,
+       .max_link_rate_mbps = 1500,
 };
 
 static const struct mtk_dsi_driver_data mt2701_dsi_driver_data = {
        .reg_main = mtk_dsi_regs_main_v1,
        .reg_adv = mtk_dsi_regs_mt2701,
+       .max_link_rate_mbps = 1500,
 };
 
 static const struct mtk_dsi_driver_data mt8183_dsi_driver_data = {
        .reg_main = mtk_dsi_regs_main_v1,
        .reg_adv = mtk_dsi_regs_mt8183,
+       .max_link_rate_mbps = 1500,
        .has_size_ctl = true,
 };
 
 static const struct mtk_dsi_driver_data mt8186_dsi_driver_data = {
        .reg_main = mtk_dsi_regs_main_v1,
        .reg_adv = mtk_dsi_regs_mt8186,
+       .max_link_rate_mbps = 1500,
        .has_size_ctl = true,
 };
 
 static const struct mtk_dsi_driver_data mt8188_dsi_driver_data = {
        .reg_main = mtk_dsi_regs_main_v1,
        .reg_adv = mtk_dsi_regs_mt8186,
+       .max_link_rate_mbps = 1500,
+       .has_size_ctl = true,
+       .cmdq_long_packet_ctl = true,
+       .support_per_frame_lp = true,
+};
+
+static const struct mtk_dsi_driver_data mt8189_dsi_driver_data = {
+       .reg_main = mtk_dsi_regs_main_v1,
+       .reg_adv = mtk_dsi_regs_mt8186,
+       .max_link_rate_mbps = 2500,
        .has_size_ctl = true,
        .cmdq_long_packet_ctl = true,
        .support_per_frame_lp = true,
@@ -1581,6 +1605,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,mt8189-dsi", .data = &mt8189_dsi_driver_data 
},
        { /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, mtk_dsi_of_match);
-- 
2.55.0

Reply via email to