diff options
Diffstat (limited to 'kernel/drivers/gpu/drm/tilcdc/tilcdc_crtc.c')
-rw-r--r-- | kernel/drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 36 |
1 files changed, 35 insertions, 1 deletions
diff --git a/kernel/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/kernel/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index c73588483..7d07733bd 100644 --- a/kernel/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/kernel/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) @@ -135,11 +138,12 @@ static void stop(struct drm_crtc *crtc) tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ENABLE); } +static void tilcdc_crtc_dpms(struct drm_crtc *crtc, int mode); static void tilcdc_crtc_destroy(struct drm_crtc *crtc) { struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); - WARN_ON(tilcdc_crtc->dpms == DRM_MODE_DPMS_ON); + tilcdc_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); drm_crtc_cleanup(crtc); drm_flip_work_cleanup(&tilcdc_crtc->unref_work); @@ -213,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; } @@ -533,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); |