diff options
Diffstat (limited to 'drivers/gpu/drm/tilcdc/tilcdc_crtc.c')
-rw-r--r-- | drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index c2d5980b9965..7d07733bdc86 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -37,6 +37,9 @@ struct tilcdc_crtc { /* for deferred fb unref's: */ struct drm_flip_work unref_work; + + /* Only set if an external encoder is connected */ + bool simulate_vesa_sync; }; #define to_tilcdc_crtc(x) container_of(x, struct tilcdc_crtc, base) @@ -214,6 +217,28 @@ static bool tilcdc_crtc_mode_fixup(struct drm_crtc *crtc, const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { + struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); + + if (!tilcdc_crtc->simulate_vesa_sync) + return true; + + /* + * tilcdc does not generate VESA-compliant sync but aligns + * VS on the second edge of HS instead of first edge. + * We use adjusted_mode, to fixup sync by aligning both rising + * edges and add HSKEW offset to fix the sync. + */ + adjusted_mode->hskew = mode->hsync_end - mode->hsync_start; + adjusted_mode->flags |= DRM_MODE_FLAG_HSKEW; + + if (mode->flags & DRM_MODE_FLAG_NHSYNC) { + adjusted_mode->flags |= DRM_MODE_FLAG_PHSYNC; + adjusted_mode->flags &= ~DRM_MODE_FLAG_NHSYNC; + } else { + adjusted_mode->flags |= DRM_MODE_FLAG_NHSYNC; + adjusted_mode->flags &= ~DRM_MODE_FLAG_PHSYNC; + } + return true; } @@ -534,6 +559,14 @@ void tilcdc_crtc_set_panel_info(struct drm_crtc *crtc, tilcdc_crtc->info = info; } +void tilcdc_crtc_set_simulate_vesa_sync(struct drm_crtc *crtc, + bool simulate_vesa_sync) +{ + struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); + + tilcdc_crtc->simulate_vesa_sync = simulate_vesa_sync; +} + void tilcdc_crtc_update_clk(struct drm_crtc *crtc) { struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); |