@@ -215,6 +215,7 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
215215 const struct drm_display_mode * mode = & rcrtc -> crtc .state -> adjusted_mode ;
216216 struct rcar_du_device * rcdu = rcrtc -> dev ;
217217 unsigned long mode_clock = mode -> clock * 1000 ;
218+ unsigned int hdse_offset ;
218219 u32 dsmr ;
219220 u32 escr ;
220221
@@ -261,12 +262,13 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
261262 rcar_du_group_write (rcrtc -> group , DPLLCR , dpllcr );
262263
263264 escr = ESCR_DCLKSEL_DCLKIN | div ;
264- } else if (rcdu -> info -> lvds_clk_mask & BIT (rcrtc -> index )) {
265+ } else if (rcdu -> info -> lvds_clk_mask & BIT (rcrtc -> index ) ||
266+ rcdu -> info -> dsi_clk_mask & BIT (rcrtc -> index )) {
265267 /*
266- * Use the LVDS PLL output as the dot clock when outputting to
267- * the LVDS encoder on an SoC that supports this clock routing
268- * option. We use the clock directly in that case, without any
269- * additional divider.
268+ * Use the external LVDS or DSI PLL output as the dot clock when
269+ * outputting to the LVDS or DSI encoder on an SoC that supports
270+ * this clock routing option. We use the clock directly in that
271+ * case, without any additional divider.
270272 */
271273 escr = ESCR_DCLKSEL_DCLKIN ;
272274 } else {
@@ -298,10 +300,15 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
298300 | DSMR_DIPM_DISP | DSMR_CSPM ;
299301 rcar_du_crtc_write (rcrtc , DSMR , dsmr );
300302
303+ hdse_offset = 19 ;
304+ if (rcrtc -> group -> cmms_mask & BIT (rcrtc -> index % 2 ))
305+ hdse_offset += 25 ;
306+
301307 /* Display timings */
302- rcar_du_crtc_write (rcrtc , HDSR , mode -> htotal - mode -> hsync_start - 19 );
308+ rcar_du_crtc_write (rcrtc , HDSR , mode -> htotal - mode -> hsync_start -
309+ hdse_offset );
303310 rcar_du_crtc_write (rcrtc , HDER , mode -> htotal - mode -> hsync_start +
304- mode -> hdisplay - 19 );
311+ mode -> hdisplay - hdse_offset );
305312 rcar_du_crtc_write (rcrtc , HSWR , mode -> hsync_end -
306313 mode -> hsync_start - 1 );
307314 rcar_du_crtc_write (rcrtc , HCR , mode -> htotal - 1 );
@@ -836,16 +843,22 @@ rcar_du_crtc_mode_valid(struct drm_crtc *crtc,
836843 struct rcar_du_crtc * rcrtc = to_rcar_crtc (crtc );
837844 struct rcar_du_device * rcdu = rcrtc -> dev ;
838845 bool interlaced = mode -> flags & DRM_MODE_FLAG_INTERLACE ;
846+ unsigned int min_sync_porch ;
839847 unsigned int vbp ;
840848
841849 if (interlaced && !rcar_du_has (rcdu , RCAR_DU_FEATURE_INTERLACED ))
842850 return MODE_NO_INTERLACE ;
843851
844852 /*
845853 * The hardware requires a minimum combined horizontal sync and back
846- * porch of 20 pixels and a minimum vertical back porch of 3 lines.
854+ * porch of 20 pixels (when CMM isn't used) or 45 pixels (when CMM is
855+ * used), and a minimum vertical back porch of 3 lines.
847856 */
848- if (mode -> htotal - mode -> hsync_start < 20 )
857+ min_sync_porch = 20 ;
858+ if (rcrtc -> group -> cmms_mask & BIT (rcrtc -> index % 2 ))
859+ min_sync_porch += 25 ;
860+
861+ if (mode -> htotal - mode -> hsync_start < min_sync_porch )
849862 return MODE_HBLANK_NARROW ;
850863
851864 vbp = (mode -> vtotal - mode -> vsync_end ) / (interlaced ? 2 : 1 );
0 commit comments