These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / gpu / drm / tilcdc / tilcdc_crtc.c
index c735884..7d07733 100644 (file)
@@ -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);