]> git.proxmox.com Git - mirror_ubuntu-disco-kernel.git/commitdiff
drm/msm/dsi: implement auto PHY timing calculator for 10nm PHY
authorAbhinav Kumar <abhinavk@codeaurora.org>
Tue, 17 Apr 2018 20:50:19 +0000 (13:50 -0700)
committerRob Clark <robdclark@gmail.com>
Sun, 3 Jun 2018 20:48:59 +0000 (16:48 -0400)
Currently the DSI PHY timings are hard-coded for a specific panel
for the 10nm PHY.

Replace this with the auto PHY timing calculator which can calculate
the PHY timings for any panel.

Changes in v4:
- None

Changes in v3:
- None

Changes in v2:
- None

Reviewed-by: Sean Paul <seanpaul@chromium.org>
Reviewed-by: Archit Taneja <architt@codeaurora.org>
Signed-off-by: Abhinav Kumar <abhinavk@codeaurora.org>
Signed-off-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c

index 8e9d5c255820272ebe0a759ed51e4aa0ee6047b9..9a9fa0c75a131083f32c57f5cd89a0e02c7b87d1 100644 (file)
@@ -265,6 +265,115 @@ int msm_dsi_dphy_timing_calc_v2(struct msm_dsi_dphy_timing *timing,
        return 0;
 }
 
+int msm_dsi_dphy_timing_calc_v3(struct msm_dsi_dphy_timing *timing,
+       struct msm_dsi_phy_clk_request *clk_req)
+{
+       const unsigned long bit_rate = clk_req->bitclk_rate;
+       const unsigned long esc_rate = clk_req->escclk_rate;
+       s32 ui, ui_x8, lpx;
+       s32 tmax, tmin;
+       s32 pcnt0 = 50;
+       s32 pcnt1 = 50;
+       s32 pcnt2 = 10;
+       s32 pcnt3 = 30;
+       s32 pcnt4 = 10;
+       s32 pcnt5 = 2;
+       s32 coeff = 1000; /* Precision, should avoid overflow */
+       s32 hb_en, hb_en_ckln;
+       s32 temp;
+
+       if (!bit_rate || !esc_rate)
+               return -EINVAL;
+
+       timing->hs_halfbyte_en = 0;
+       hb_en = 0;
+       timing->hs_halfbyte_en_ckln = 0;
+       hb_en_ckln = 0;
+
+       ui = mult_frac(NSEC_PER_MSEC, coeff, bit_rate / 1000);
+       ui_x8 = ui << 3;
+       lpx = mult_frac(NSEC_PER_MSEC, coeff, esc_rate / 1000);
+
+       temp = S_DIV_ROUND_UP(38 * coeff, ui_x8);
+       tmin = max_t(s32, temp, 0);
+       temp = (95 * coeff) / ui_x8;
+       tmax = max_t(s32, temp, 0);
+       timing->clk_prepare = linear_inter(tmax, tmin, pcnt0, 0, false);
+
+       temp = 300 * coeff - (timing->clk_prepare << 3) * ui;
+       tmin = S_DIV_ROUND_UP(temp, ui_x8) - 1;
+       tmax = (tmin > 255) ? 511 : 255;
+       timing->clk_zero = linear_inter(tmax, tmin, pcnt5, 0, false);
+
+       tmin = DIV_ROUND_UP(60 * coeff + 3 * ui, ui_x8);
+       temp = 105 * coeff + 12 * ui - 20 * coeff;
+       tmax = (temp + 3 * ui) / ui_x8;
+       timing->clk_trail = linear_inter(tmax, tmin, pcnt3, 0, false);
+
+       temp = S_DIV_ROUND_UP(40 * coeff + 4 * ui, ui_x8);
+       tmin = max_t(s32, temp, 0);
+       temp = (85 * coeff + 6 * ui) / ui_x8;
+       tmax = max_t(s32, temp, 0);
+       timing->hs_prepare = linear_inter(tmax, tmin, pcnt1, 0, false);
+
+       temp = 145 * coeff + 10 * ui - (timing->hs_prepare << 3) * ui;
+       tmin = S_DIV_ROUND_UP(temp, ui_x8) - 1;
+       tmax = 255;
+       timing->hs_zero = linear_inter(tmax, tmin, pcnt4, 0, false);
+
+       tmin = DIV_ROUND_UP(60 * coeff + 4 * ui, ui_x8) - 1;
+       temp = 105 * coeff + 12 * ui - 20 * coeff;
+       tmax = (temp / ui_x8) - 1;
+       timing->hs_trail = linear_inter(tmax, tmin, pcnt3, 0, false);
+
+       temp = 50 * coeff + ((hb_en << 2) - 8) * ui;
+       timing->hs_rqst = S_DIV_ROUND_UP(temp, ui_x8);
+
+       tmin = DIV_ROUND_UP(100 * coeff, ui_x8) - 1;
+       tmax = 255;
+       timing->hs_exit = linear_inter(tmax, tmin, pcnt2, 0, false);
+
+       temp = 50 * coeff + ((hb_en_ckln << 2) - 8) * ui;
+       timing->hs_rqst_ckln = S_DIV_ROUND_UP(temp, ui_x8);
+
+       temp = 60 * coeff + 52 * ui - 43 * ui;
+       tmin = DIV_ROUND_UP(temp, ui_x8) - 1;
+       tmax = 63;
+       timing->shared_timings.clk_post =
+               linear_inter(tmax, tmin, pcnt2, 0, false);
+
+       temp = 8 * ui + (timing->clk_prepare << 3) * ui;
+       temp += (((timing->clk_zero + 3) << 3) + 11) * ui;
+       temp += hb_en_ckln ? (((timing->hs_rqst_ckln << 3) + 4) * ui) :
+               (((timing->hs_rqst_ckln << 3) + 8) * ui);
+       tmin = S_DIV_ROUND_UP(temp, ui_x8) - 1;
+       tmax = 63;
+       if (tmin > tmax) {
+               temp = linear_inter(tmax << 1, tmin, pcnt2, 0, false);
+               timing->shared_timings.clk_pre = temp >> 1;
+               timing->shared_timings.clk_pre_inc_by_2 = 1;
+       } else {
+               timing->shared_timings.clk_pre =
+                       linear_inter(tmax, tmin, pcnt2, 0, false);
+                       timing->shared_timings.clk_pre_inc_by_2 = 0;
+       }
+
+       timing->ta_go = 3;
+       timing->ta_sure = 0;
+       timing->ta_get = 4;
+
+       DBG("%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d",
+               timing->shared_timings.clk_pre, timing->shared_timings.clk_post,
+               timing->shared_timings.clk_pre_inc_by_2, timing->clk_zero,
+               timing->clk_trail, timing->clk_prepare, timing->hs_exit,
+               timing->hs_zero, timing->hs_prepare, timing->hs_trail,
+               timing->hs_rqst, timing->hs_rqst_ckln, timing->hs_halfbyte_en,
+               timing->hs_halfbyte_en_ckln, timing->hs_prep_dly,
+               timing->hs_prep_dly_ckln);
+
+       return 0;
+}
+
 void msm_dsi_phy_set_src_pll(struct msm_dsi_phy *phy, int pll_id, u32 reg,
                                u32 bit_mask)
 {
index c56268cbdb3d81925410be764515d0f6be8a9864..a24ab80994a3c08710723f6a0325512785196a84 100644 (file)
@@ -101,6 +101,8 @@ int msm_dsi_dphy_timing_calc(struct msm_dsi_dphy_timing *timing,
                             struct msm_dsi_phy_clk_request *clk_req);
 int msm_dsi_dphy_timing_calc_v2(struct msm_dsi_dphy_timing *timing,
                                struct msm_dsi_phy_clk_request *clk_req);
+int msm_dsi_dphy_timing_calc_v3(struct msm_dsi_dphy_timing *timing,
+                               struct msm_dsi_phy_clk_request *clk_req);
 void msm_dsi_phy_set_src_pll(struct msm_dsi_phy *phy, int pll_id, u32 reg,
                                u32 bit_mask);
 int msm_dsi_phy_init_common(struct msm_dsi_phy *phy);
index 0af951aaeea1e2d563d4bd2238241e87791a65f7..b3fffc8dbb2ab572aa688aabe8ef4546728e3fb8 100644 (file)
@@ -79,34 +79,6 @@ static void dsi_phy_hw_v3_0_lane_settings(struct msm_dsi_phy *phy)
        dsi_phy_write(lane_base + REG_DSI_10nm_PHY_LN_TX_DCTRL(3), 0x04);
 }
 
-static int msm_dsi_dphy_timing_calc_v3(struct msm_dsi_dphy_timing *timing,
-                                      struct msm_dsi_phy_clk_request *clk_req)
-{
-       /*
-        * TODO: These params need to be computed, they're currently hardcoded
-        * for a 1440x2560@60Hz panel with a byteclk of 100.618 Mhz, and a
-        * default escape clock of 19.2 Mhz.
-        */
-
-       timing->hs_halfbyte_en = 0;
-       timing->clk_zero = 0x1c;
-       timing->clk_prepare = 0x07;
-       timing->clk_trail = 0x07;
-       timing->hs_exit = 0x23;
-       timing->hs_zero = 0x21;
-       timing->hs_prepare = 0x07;
-       timing->hs_trail = 0x07;
-       timing->hs_rqst = 0x05;
-       timing->ta_sure = 0x00;
-       timing->ta_go = 0x03;
-       timing->ta_get = 0x04;
-
-       timing->shared_timings.clk_pre = 0x2d;
-       timing->shared_timings.clk_post = 0x0d;
-
-       return 0;
-}
-
 static int dsi_10nm_phy_enable(struct msm_dsi_phy *phy, int src_pll_id,
                               struct msm_dsi_phy_clk_request *clk_req)
 {