diff options
author | Dave Airlie <airlied@redhat.com> | 2018-04-25 21:09:04 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2018-04-25 21:09:04 -0400 |
commit | 14cdea89459e71e38027aa4fb1099c29f4c53316 (patch) | |
tree | 6a0606e5f281a802e31fb9f6763c1d87f92ad1fa /drivers/gpu/drm/msm/dsi/phy/dsi_phy.c | |
parent | 8eb8ad52fbc99aa87f1c56db378ee910833ed780 (diff) | |
parent | 789d4c300e10eb2096ee83c3497118e67ccc951e (diff) |
Merge tag 'drm-msm-fixes-2018-04-25' of git://people.freedesktop.org/~robclark/linux into drm-fixes
A few fixes for 4.17.. thanks to Sean for helping pull together some
of the display related fixes while I was off in compute-land.
* tag 'drm-msm-fixes-2018-04-25' of git://people.freedesktop.org/~robclark/linux:
drm/msm: don't deref error pointer in the msm_fbdev_create error path
drm/msm/dsi: use correct enum in dsi_get_cmd_fmt
drm/msm: Fix possible null dereference on failure of get_pages()
drm/msm: Add modifier to mdp_get_format arguments
drm/msm: Mark the crtc->state->event consumed
drm/msm/dsi: implement auto PHY timing calculator for 10nm PHY
drm/msm/dsi: check video mode engine status before waiting
drm/msm/dsi: check return value for video done waits
Diffstat (limited to 'drivers/gpu/drm/msm/dsi/phy/dsi_phy.c')
-rw-r--r-- | drivers/gpu/drm/msm/dsi/phy/dsi_phy.c | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c index 8e9d5c255820..9a9fa0c75a13 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c | |||
@@ -265,6 +265,115 @@ int msm_dsi_dphy_timing_calc_v2(struct msm_dsi_dphy_timing *timing, | |||
265 | return 0; | 265 | return 0; |
266 | } | 266 | } |
267 | 267 | ||
268 | int msm_dsi_dphy_timing_calc_v3(struct msm_dsi_dphy_timing *timing, | ||
269 | struct msm_dsi_phy_clk_request *clk_req) | ||
270 | { | ||
271 | const unsigned long bit_rate = clk_req->bitclk_rate; | ||
272 | const unsigned long esc_rate = clk_req->escclk_rate; | ||
273 | s32 ui, ui_x8, lpx; | ||
274 | s32 tmax, tmin; | ||
275 | s32 pcnt0 = 50; | ||
276 | s32 pcnt1 = 50; | ||
277 | s32 pcnt2 = 10; | ||
278 | s32 pcnt3 = 30; | ||
279 | s32 pcnt4 = 10; | ||
280 | s32 pcnt5 = 2; | ||
281 | s32 coeff = 1000; /* Precision, should avoid overflow */ | ||
282 | s32 hb_en, hb_en_ckln; | ||
283 | s32 temp; | ||
284 | |||
285 | if (!bit_rate || !esc_rate) | ||
286 | return -EINVAL; | ||
287 | |||
288 | timing->hs_halfbyte_en = 0; | ||
289 | hb_en = 0; | ||
290 | timing->hs_halfbyte_en_ckln = 0; | ||
291 | hb_en_ckln = 0; | ||
292 | |||
293 | ui = mult_frac(NSEC_PER_MSEC, coeff, bit_rate / 1000); | ||
294 | ui_x8 = ui << 3; | ||
295 | lpx = mult_frac(NSEC_PER_MSEC, coeff, esc_rate / 1000); | ||
296 | |||
297 | temp = S_DIV_ROUND_UP(38 * coeff, ui_x8); | ||
298 | tmin = max_t(s32, temp, 0); | ||
299 | temp = (95 * coeff) / ui_x8; | ||
300 | tmax = max_t(s32, temp, 0); | ||
301 | timing->clk_prepare = linear_inter(tmax, tmin, pcnt0, 0, false); | ||
302 | |||
303 | temp = 300 * coeff - (timing->clk_prepare << 3) * ui; | ||
304 | tmin = S_DIV_ROUND_UP(temp, ui_x8) - 1; | ||
305 | tmax = (tmin > 255) ? 511 : 255; | ||
306 | timing->clk_zero = linear_inter(tmax, tmin, pcnt5, 0, false); | ||
307 | |||
308 | tmin = DIV_ROUND_UP(60 * coeff + 3 * ui, ui_x8); | ||
309 | temp = 105 * coeff + 12 * ui - 20 * coeff; | ||
310 | tmax = (temp + 3 * ui) / ui_x8; | ||
311 | timing->clk_trail = linear_inter(tmax, tmin, pcnt3, 0, false); | ||
312 | |||
313 | temp = S_DIV_ROUND_UP(40 * coeff + 4 * ui, ui_x8); | ||
314 | tmin = max_t(s32, temp, 0); | ||
315 | temp = (85 * coeff + 6 * ui) / ui_x8; | ||
316 | tmax = max_t(s32, temp, 0); | ||
317 | timing->hs_prepare = linear_inter(tmax, tmin, pcnt1, 0, false); | ||
318 | |||
319 | temp = 145 * coeff + 10 * ui - (timing->hs_prepare << 3) * ui; | ||
320 | tmin = S_DIV_ROUND_UP(temp, ui_x8) - 1; | ||
321 | tmax = 255; | ||
322 | timing->hs_zero = linear_inter(tmax, tmin, pcnt4, 0, false); | ||
323 | |||
324 | tmin = DIV_ROUND_UP(60 * coeff + 4 * ui, ui_x8) - 1; | ||
325 | temp = 105 * coeff + 12 * ui - 20 * coeff; | ||
326 | tmax = (temp / ui_x8) - 1; | ||
327 | timing->hs_trail = linear_inter(tmax, tmin, pcnt3, 0, false); | ||
328 | |||
329 | temp = 50 * coeff + ((hb_en << 2) - 8) * ui; | ||
330 | timing->hs_rqst = S_DIV_ROUND_UP(temp, ui_x8); | ||
331 | |||
332 | tmin = DIV_ROUND_UP(100 * coeff, ui_x8) - 1; | ||
333 | tmax = 255; | ||
334 | timing->hs_exit = linear_inter(tmax, tmin, pcnt2, 0, false); | ||
335 | |||
336 | temp = 50 * coeff + ((hb_en_ckln << 2) - 8) * ui; | ||
337 | timing->hs_rqst_ckln = S_DIV_ROUND_UP(temp, ui_x8); | ||
338 | |||
339 | temp = 60 * coeff + 52 * ui - 43 * ui; | ||
340 | tmin = DIV_ROUND_UP(temp, ui_x8) - 1; | ||
341 | tmax = 63; | ||
342 | timing->shared_timings.clk_post = | ||
343 | linear_inter(tmax, tmin, pcnt2, 0, false); | ||
344 | |||
345 | temp = 8 * ui + (timing->clk_prepare << 3) * ui; | ||
346 | temp += (((timing->clk_zero + 3) << 3) + 11) * ui; | ||
347 | temp += hb_en_ckln ? (((timing->hs_rqst_ckln << 3) + 4) * ui) : | ||
348 | (((timing->hs_rqst_ckln << 3) + 8) * ui); | ||
349 | tmin = S_DIV_ROUND_UP(temp, ui_x8) - 1; | ||
350 | tmax = 63; | ||
351 | if (tmin > tmax) { | ||
352 | temp = linear_inter(tmax << 1, tmin, pcnt2, 0, false); | ||
353 | timing->shared_timings.clk_pre = temp >> 1; | ||
354 | timing->shared_timings.clk_pre_inc_by_2 = 1; | ||
355 | } else { | ||
356 | timing->shared_timings.clk_pre = | ||
357 | linear_inter(tmax, tmin, pcnt2, 0, false); | ||
358 | timing->shared_timings.clk_pre_inc_by_2 = 0; | ||
359 | } | ||
360 | |||
361 | timing->ta_go = 3; | ||
362 | timing->ta_sure = 0; | ||
363 | timing->ta_get = 4; | ||
364 | |||
365 | DBG("%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d", | ||
366 | timing->shared_timings.clk_pre, timing->shared_timings.clk_post, | ||
367 | timing->shared_timings.clk_pre_inc_by_2, timing->clk_zero, | ||
368 | timing->clk_trail, timing->clk_prepare, timing->hs_exit, | ||
369 | timing->hs_zero, timing->hs_prepare, timing->hs_trail, | ||
370 | timing->hs_rqst, timing->hs_rqst_ckln, timing->hs_halfbyte_en, | ||
371 | timing->hs_halfbyte_en_ckln, timing->hs_prep_dly, | ||
372 | timing->hs_prep_dly_ckln); | ||
373 | |||
374 | return 0; | ||
375 | } | ||
376 | |||
268 | void msm_dsi_phy_set_src_pll(struct msm_dsi_phy *phy, int pll_id, u32 reg, | 377 | void msm_dsi_phy_set_src_pll(struct msm_dsi_phy *phy, int pll_id, u32 reg, |
269 | u32 bit_mask) | 378 | u32 bit_mask) |
270 | { | 379 | { |