aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/tilcdc/tilcdc_crtc.c')
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_crtc.c36
1 files changed, 35 insertions, 1 deletions
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
index c73588483be0..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 {
37 37
38 /* for deferred fb unref's: */ 38 /* for deferred fb unref's: */
39 struct drm_flip_work unref_work; 39 struct drm_flip_work unref_work;
40
41 /* Only set if an external encoder is connected */
42 bool simulate_vesa_sync;
40}; 43};
41#define to_tilcdc_crtc(x) container_of(x, struct tilcdc_crtc, base) 44#define to_tilcdc_crtc(x) container_of(x, struct tilcdc_crtc, base)
42 45
@@ -135,11 +138,12 @@ static void stop(struct drm_crtc *crtc)
135 tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ENABLE); 138 tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ENABLE);
136} 139}
137 140
141static void tilcdc_crtc_dpms(struct drm_crtc *crtc, int mode);
138static void tilcdc_crtc_destroy(struct drm_crtc *crtc) 142static void tilcdc_crtc_destroy(struct drm_crtc *crtc)
139{ 143{
140 struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); 144 struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
141 145
142 WARN_ON(tilcdc_crtc->dpms == DRM_MODE_DPMS_ON); 146 tilcdc_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
143 147
144 drm_crtc_cleanup(crtc); 148 drm_crtc_cleanup(crtc);
145 drm_flip_work_cleanup(&tilcdc_crtc->unref_work); 149 drm_flip_work_cleanup(&tilcdc_crtc->unref_work);
@@ -213,6 +217,28 @@ static bool tilcdc_crtc_mode_fixup(struct drm_crtc *crtc,
213 const struct drm_display_mode *mode, 217 const struct drm_display_mode *mode,
214 struct drm_display_mode *adjusted_mode) 218 struct drm_display_mode *adjusted_mode)
215{ 219{
220 struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
221
222 if (!tilcdc_crtc->simulate_vesa_sync)
223 return true;
224
225 /*
226 * tilcdc does not generate VESA-compliant sync but aligns
227 * VS on the second edge of HS instead of first edge.
228 * We use adjusted_mode, to fixup sync by aligning both rising
229 * edges and add HSKEW offset to fix the sync.
230 */
231 adjusted_mode->hskew = mode->hsync_end - mode->hsync_start;
232 adjusted_mode->flags |= DRM_MODE_FLAG_HSKEW;
233
234 if (mode->flags & DRM_MODE_FLAG_NHSYNC) {
235 adjusted_mode->flags |= DRM_MODE_FLAG_PHSYNC;
236 adjusted_mode->flags &= ~DRM_MODE_FLAG_NHSYNC;
237 } else {
238 adjusted_mode->flags |= DRM_MODE_FLAG_NHSYNC;
239 adjusted_mode->flags &= ~DRM_MODE_FLAG_PHSYNC;
240 }
241
216 return true; 242 return true;
217} 243}
218 244
@@ -533,6 +559,14 @@ void tilcdc_crtc_set_panel_info(struct drm_crtc *crtc,
533 tilcdc_crtc->info = info; 559 tilcdc_crtc->info = info;
534} 560}
535 561
562void tilcdc_crtc_set_simulate_vesa_sync(struct drm_crtc *crtc,
563 bool simulate_vesa_sync)
564{
565 struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
566
567 tilcdc_crtc->simulate_vesa_sync = simulate_vesa_sync;
568}
569
536void tilcdc_crtc_update_clk(struct drm_crtc *crtc) 570void tilcdc_crtc_update_clk(struct drm_crtc *crtc)
537{ 571{
538 struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); 572 struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);