OSDN Git Service

drm/bridge: lt9611: fix clock calculation
authorDmitry Baryshkov <dmitry.baryshkov@linaro.org>
Wed, 18 Jan 2023 08:16:50 +0000 (10:16 +0200)
committerNeil Armstrong <neil.armstrong@linaro.org>
Wed, 18 Jan 2023 14:27:06 +0000 (15:27 +0100)
Instead of having several fixed values for the pcr register, calculate
it before programming. This allows the bridge to support most of the
display modes.

Fixes: 23278bf54afe ("drm/bridge: Introduce LT9611 DSI to HDMI bridge")
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20230118081658.2198520-6-dmitry.baryshkov@linaro.org
drivers/gpu/drm/bridge/lontium-lt9611.c

index 7605c5b..fb72cf7 100644 (file)
@@ -192,8 +192,9 @@ static void lt9611_mipi_video_setup(struct lt9611 *lt9611,
        regmap_write(lt9611->regmap, 0x831b, (u8)(hsync_porch % 256));
 }
 
-static void lt9611_pcr_setup(struct lt9611 *lt9611, const struct drm_display_mode *mode)
+static void lt9611_pcr_setup(struct lt9611 *lt9611, const struct drm_display_mode *mode, unsigned int postdiv)
 {
+       unsigned int pcr_m = mode->clock * 5 * postdiv / 27000;
        const struct reg_sequence reg_cfg[] = {
                { 0x830b, 0x01 },
                { 0x830c, 0x10 },
@@ -236,24 +237,14 @@ static void lt9611_pcr_setup(struct lt9611 *lt9611, const struct drm_display_mod
        else
                regmap_multi_reg_write(lt9611->regmap, reg_cfg, ARRAY_SIZE(reg_cfg));
 
-       switch (mode->hdisplay) {
-       case 640:
-               regmap_write(lt9611->regmap, 0x8326, 0x14);
-               break;
-       case 1920:
-               regmap_write(lt9611->regmap, 0x8326, 0x37);
-               break;
-       case 3840:
-               regmap_write(lt9611->regmap, 0x8326, 0x37);
-               break;
-       }
+       regmap_write(lt9611->regmap, 0x8326, pcr_m);
 
        /* pcr rst */
        regmap_write(lt9611->regmap, 0x8011, 0x5a);
        regmap_write(lt9611->regmap, 0x8011, 0xfa);
 }
 
-static int lt9611_pll_setup(struct lt9611 *lt9611, const struct drm_display_mode *mode)
+static int lt9611_pll_setup(struct lt9611 *lt9611, const struct drm_display_mode *mode, unsigned int *postdiv)
 {
        unsigned int pclk = mode->clock;
        const struct reg_sequence reg_cfg[] = {
@@ -272,12 +263,16 @@ static int lt9611_pll_setup(struct lt9611 *lt9611, const struct drm_display_mode
 
        regmap_multi_reg_write(lt9611->regmap, reg_cfg, ARRAY_SIZE(reg_cfg));
 
-       if (pclk > 150000)
+       if (pclk > 150000) {
                regmap_write(lt9611->regmap, 0x812d, 0x88);
-       else if (pclk > 70000)
+               *postdiv = 1;
+       } else if (pclk > 70000) {
                regmap_write(lt9611->regmap, 0x812d, 0x99);
-       else
+               *postdiv = 2;
+       } else {
                regmap_write(lt9611->regmap, 0x812d, 0xaa);
+               *postdiv = 4;
+       }
 
        /*
         * first divide pclk by 2 first
@@ -896,14 +891,15 @@ static void lt9611_bridge_mode_set(struct drm_bridge *bridge,
 {
        struct lt9611 *lt9611 = bridge_to_lt9611(bridge);
        struct hdmi_avi_infoframe avi_frame;
+       unsigned int postdiv;
        int ret;
 
        lt9611_bridge_pre_enable(bridge);
 
        lt9611_mipi_input_digital(lt9611, mode);
-       lt9611_pll_setup(lt9611, mode);
+       lt9611_pll_setup(lt9611, mode, &postdiv);
        lt9611_mipi_video_setup(lt9611, mode);
-       lt9611_pcr_setup(lt9611, mode);
+       lt9611_pcr_setup(lt9611, mode, postdiv);
 
        ret = drm_hdmi_avi_infoframe_from_display_mode(&avi_frame,
                                                       &lt9611->connector,