aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHai Li <hali@codeaurora.org>2017-01-03 09:01:16 -0500
committerRob Clark <robdclark@gmail.com>2017-02-06 11:28:45 -0500
commita4df68fa232e979fb74b2efe6997d0f38cbfc626 (patch)
tree63a78511b4570fe87898e1e5646c5102f3c0472e
parentb62aa70a98c5401ada63657eee7c88da70bdbb27 (diff)
drm/msm/dsi: Add new method to calculate 14nm PHY timings
The 14nm DSI PHY on 8x96 (called PHY v2 downstream) requires a different set of calculations for computing D-PHY timing params. Create a timing_calc_v2 func for the newer v2 PHYs. Signed-off-by: Hai Li <hali@codeaurora.org> Signed-off-by: Archit Taneja <architt@codeaurora.org> Signed-off-by: Rob Clark <robdclark@gmail.com>
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy.c117
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy.h11
2 files changed, 127 insertions, 1 deletions
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
index a761531ec04c..541d7dfa13c0 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
@@ -148,6 +148,123 @@ int msm_dsi_dphy_timing_calc(struct msm_dsi_dphy_timing *timing,
148 return 0; 148 return 0;
149} 149}
150 150
151int msm_dsi_dphy_timing_calc_v2(struct msm_dsi_dphy_timing *timing,
152 struct msm_dsi_phy_clk_request *clk_req)
153{
154 const unsigned long bit_rate = clk_req->bitclk_rate;
155 const unsigned long esc_rate = clk_req->escclk_rate;
156 s32 ui, ui_x8, lpx;
157 s32 tmax, tmin;
158 s32 pcnt0 = 50;
159 s32 pcnt1 = 50;
160 s32 pcnt2 = 10;
161 s32 pcnt3 = 30;
162 s32 pcnt4 = 10;
163 s32 pcnt5 = 2;
164 s32 coeff = 1000; /* Precision, should avoid overflow */
165 s32 hb_en, hb_en_ckln, pd_ckln, pd;
166 s32 val, val_ckln;
167 s32 temp;
168
169 if (!bit_rate || !esc_rate)
170 return -EINVAL;
171
172 timing->hs_halfbyte_en = 0;
173 hb_en = 0;
174 timing->hs_halfbyte_en_ckln = 0;
175 hb_en_ckln = 0;
176 timing->hs_prep_dly_ckln = (bit_rate > 100000000) ? 0 : 3;
177 pd_ckln = timing->hs_prep_dly_ckln;
178 timing->hs_prep_dly = (bit_rate > 120000000) ? 0 : 1;
179 pd = timing->hs_prep_dly;
180
181 val = (hb_en << 2) + (pd << 1);
182 val_ckln = (hb_en_ckln << 2) + (pd_ckln << 1);
183
184 ui = mult_frac(NSEC_PER_MSEC, coeff, bit_rate / 1000);
185 ui_x8 = ui << 3;
186 lpx = mult_frac(NSEC_PER_MSEC, coeff, esc_rate / 1000);
187
188 temp = S_DIV_ROUND_UP(38 * coeff - val_ckln * ui, ui_x8);
189 tmin = max_t(s32, temp, 0);
190 temp = (95 * coeff - val_ckln * ui) / ui_x8;
191 tmax = max_t(s32, temp, 0);
192 timing->clk_prepare = linear_inter(tmax, tmin, pcnt0, 0, false);
193
194 temp = 300 * coeff - ((timing->clk_prepare << 3) + val_ckln) * ui;
195 tmin = S_DIV_ROUND_UP(temp - 11 * ui, ui_x8) - 3;
196 tmax = (tmin > 255) ? 511 : 255;
197 timing->clk_zero = linear_inter(tmax, tmin, pcnt5, 0, false);
198
199 tmin = DIV_ROUND_UP(60 * coeff + 3 * ui, ui_x8);
200 temp = 105 * coeff + 12 * ui - 20 * coeff;
201 tmax = (temp + 3 * ui) / ui_x8;
202 timing->clk_trail = linear_inter(tmax, tmin, pcnt3, 0, false);
203
204 temp = S_DIV_ROUND_UP(40 * coeff + 4 * ui - val * ui, ui_x8);
205 tmin = max_t(s32, temp, 0);
206 temp = (85 * coeff + 6 * ui - val * ui) / ui_x8;
207 tmax = max_t(s32, temp, 0);
208 timing->hs_prepare = linear_inter(tmax, tmin, pcnt1, 0, false);
209
210 temp = 145 * coeff + 10 * ui - ((timing->hs_prepare << 3) + val) * ui;
211 tmin = S_DIV_ROUND_UP(temp - 11 * ui, ui_x8) - 3;
212 tmax = 255;
213 timing->hs_zero = linear_inter(tmax, tmin, pcnt4, 0, false);
214
215 tmin = DIV_ROUND_UP(60 * coeff + 4 * ui + 3 * ui, ui_x8);
216 temp = 105 * coeff + 12 * ui - 20 * coeff;
217 tmax = (temp + 3 * ui) / ui_x8;
218 timing->hs_trail = linear_inter(tmax, tmin, pcnt3, 0, false);
219
220 temp = 50 * coeff + ((hb_en << 2) - 8) * ui;
221 timing->hs_rqst = S_DIV_ROUND_UP(temp, ui_x8);
222
223 tmin = DIV_ROUND_UP(100 * coeff, ui_x8) - 1;
224 tmax = 255;
225 timing->hs_exit = linear_inter(tmax, tmin, pcnt2, 0, false);
226
227 temp = 50 * coeff + ((hb_en_ckln << 2) - 8) * ui;
228 timing->hs_rqst_ckln = S_DIV_ROUND_UP(temp, ui_x8);
229
230 temp = 60 * coeff + 52 * ui - 43 * ui;
231 tmin = DIV_ROUND_UP(temp, ui_x8) - 1;
232 tmax = 63;
233 timing->shared_timings.clk_post =
234 linear_inter(tmax, tmin, pcnt2, 0, false);
235
236 temp = 8 * ui + ((timing->clk_prepare << 3) + val_ckln) * ui;
237 temp += (((timing->clk_zero + 3) << 3) + 11 - (pd_ckln << 1)) * ui;
238 temp += hb_en_ckln ? (((timing->hs_rqst_ckln << 3) + 4) * ui) :
239 (((timing->hs_rqst_ckln << 3) + 8) * ui);
240 tmin = S_DIV_ROUND_UP(temp, ui_x8) - 1;
241 tmax = 63;
242 if (tmin > tmax) {
243 temp = linear_inter(tmax << 1, tmin, pcnt2, 0, false);
244 timing->shared_timings.clk_pre = temp >> 1;
245 timing->shared_timings.clk_pre_inc_by_2 = 1;
246 } else {
247 timing->shared_timings.clk_pre =
248 linear_inter(tmax, tmin, pcnt2, 0, false);
249 timing->shared_timings.clk_pre_inc_by_2 = 0;
250 }
251
252 timing->ta_go = 3;
253 timing->ta_sure = 0;
254 timing->ta_get = 4;
255
256 DBG("%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d",
257 timing->shared_timings.clk_pre, timing->shared_timings.clk_post,
258 timing->shared_timings.clk_pre_inc_by_2, timing->clk_zero,
259 timing->clk_trail, timing->clk_prepare, timing->hs_exit,
260 timing->hs_zero, timing->hs_prepare, timing->hs_trail,
261 timing->hs_rqst, timing->hs_rqst_ckln, timing->hs_halfbyte_en,
262 timing->hs_halfbyte_en_ckln, timing->hs_prep_dly,
263 timing->hs_prep_dly_ckln);
264
265 return 0;
266}
267
151void msm_dsi_phy_set_src_pll(struct msm_dsi_phy *phy, int pll_id, u32 reg, 268void msm_dsi_phy_set_src_pll(struct msm_dsi_phy *phy, int pll_id, u32 reg,
152 u32 bit_mask) 269 u32 bit_mask)
153{ 270{
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
index 6472b600ac41..feee87094ef5 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
@@ -64,6 +64,13 @@ struct msm_dsi_dphy_timing {
64 u32 ta_get; 64 u32 ta_get;
65 65
66 struct msm_dsi_phy_shared_timings shared_timings; 66 struct msm_dsi_phy_shared_timings shared_timings;
67
68 /* For PHY v2 only */
69 u32 hs_rqst_ckln;
70 u32 hs_prep_dly;
71 u32 hs_prep_dly_ckln;
72 u8 hs_halfbyte_en;
73 u8 hs_halfbyte_en_ckln;
67}; 74};
68 75
69struct msm_dsi_phy { 76struct msm_dsi_phy {
@@ -88,7 +95,9 @@ struct msm_dsi_phy {
88 * PHY internal functions 95 * PHY internal functions
89 */ 96 */
90int msm_dsi_dphy_timing_calc(struct msm_dsi_dphy_timing *timing, 97int msm_dsi_dphy_timing_calc(struct msm_dsi_dphy_timing *timing,
91 struct msm_dsi_phy_clk_request *clk_req); 98 struct msm_dsi_phy_clk_request *clk_req);
99int msm_dsi_dphy_timing_calc_v2(struct msm_dsi_dphy_timing *timing,
100 struct msm_dsi_phy_clk_request *clk_req);
92void msm_dsi_phy_set_src_pll(struct msm_dsi_phy *phy, int pll_id, u32 reg, 101void msm_dsi_phy_set_src_pll(struct msm_dsi_phy *phy, int pll_id, u32 reg,
93 u32 bit_mask); 102 u32 bit_mask);
94int msm_dsi_phy_init_common(struct msm_dsi_phy *phy); 103int msm_dsi_phy_init_common(struct msm_dsi_phy *phy);