aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/stm
diff options
context:
space:
mode:
authorPhilippe CORNU <philippe.cornu@st.com>2018-04-17 07:40:26 -0400
committerPhilippe Cornu <philippe.cornu@st.com>2018-04-27 04:58:06 -0400
commit0cefff963bf2af9ec9b2e2b537c3d3e6a43ceb9b (patch)
tree4814e894220e54da2e3e13a9bab0b5a4d0b0554d /drivers/gpu/drm/stm
parentc2af73645d3a67cc2e4a750179048a4c6d5110a1 (diff)
drm/stm: ltdc: add mode_valid()
Add mode_valid() function to filter modes according to available pll clock values and "preferred" modes. It is particularly useful for hdmi modes that require precise pixel clocks. Note that "preferred" modes are always accepted: - this is important for panels because panel clock tolerances are bigger than hdmi ones and there is no reason to not accept them (the fps may vary a little but it is not a problem). - the hdmi preferred mode will be accepted too, but userland will be able to use others hdmi "valid" modes if necessary. Signed-off-by: Philippe Cornu <philippe.cornu@st.com> Reviewed-by: Yannick Fertré <yannick.fertre@st.com> Link: https://patchwork.freedesktop.org/patch/msgid/20180417114026.8709-1-philippe.cornu@st.com
Diffstat (limited to 'drivers/gpu/drm/stm')
-rw-r--r--drivers/gpu/drm/stm/ltdc.c38
1 files changed, 38 insertions, 0 deletions
diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c
index 014cef8cef37..616191fe98ae 100644
--- a/drivers/gpu/drm/stm/ltdc.c
+++ b/drivers/gpu/drm/stm/ltdc.c
@@ -445,6 +445,43 @@ static void ltdc_crtc_atomic_disable(struct drm_crtc *crtc,
445 reg_set(ldev->regs, LTDC_SRCR, SRCR_IMR); 445 reg_set(ldev->regs, LTDC_SRCR, SRCR_IMR);
446} 446}
447 447
448#define CLK_TOLERANCE_HZ 50
449
450static enum drm_mode_status
451ltdc_crtc_mode_valid(struct drm_crtc *crtc,
452 const struct drm_display_mode *mode)
453{
454 struct ltdc_device *ldev = crtc_to_ltdc(crtc);
455 int target = mode->clock * 1000;
456 int target_min = target - CLK_TOLERANCE_HZ;
457 int target_max = target + CLK_TOLERANCE_HZ;
458 int result;
459
460 /*
461 * Accept all "preferred" modes:
462 * - this is important for panels because panel clock tolerances are
463 * bigger than hdmi ones and there is no reason to not accept them
464 * (the fps may vary a little but it is not a problem).
465 * - the hdmi preferred mode will be accepted too, but userland will
466 * be able to use others hdmi "valid" modes if necessary.
467 */
468 if (mode->type & DRM_MODE_TYPE_PREFERRED)
469 return MODE_OK;
470
471 result = clk_round_rate(ldev->pixel_clk, target);
472
473 DRM_DEBUG_DRIVER("clk rate target %d, available %d\n", target, result);
474
475 /*
476 * Filter modes according to the clock value, particularly useful for
477 * hdmi modes that require precise pixel clocks.
478 */
479 if (result < target_min || result > target_max)
480 return MODE_CLOCK_RANGE;
481
482 return MODE_OK;
483}
484
448static bool ltdc_crtc_mode_fixup(struct drm_crtc *crtc, 485static bool ltdc_crtc_mode_fixup(struct drm_crtc *crtc,
449 const struct drm_display_mode *mode, 486 const struct drm_display_mode *mode,
450 struct drm_display_mode *adjusted_mode) 487 struct drm_display_mode *adjusted_mode)
@@ -559,6 +596,7 @@ static void ltdc_crtc_atomic_flush(struct drm_crtc *crtc,
559} 596}
560 597
561static const struct drm_crtc_helper_funcs ltdc_crtc_helper_funcs = { 598static const struct drm_crtc_helper_funcs ltdc_crtc_helper_funcs = {
599 .mode_valid = ltdc_crtc_mode_valid,
562 .mode_fixup = ltdc_crtc_mode_fixup, 600 .mode_fixup = ltdc_crtc_mode_fixup,
563 .mode_set_nofb = ltdc_crtc_mode_set_nofb, 601 .mode_set_nofb = ltdc_crtc_mode_set_nofb,
564 .atomic_flush = ltdc_crtc_atomic_flush, 602 .atomic_flush = ltdc_crtc_atomic_flush,