aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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,