Skip to content

Commit

Permalink
drm: rcar-du: Fix CRTC timings when CMM is used
Browse files Browse the repository at this point in the history
When the CMM is enabled, an offset of 25 pixels must be subtracted from
the HDS (horizontal display start) and HDE (horizontal display end)
registers. Fix the timings calculation, and take this into account in
the mode validation.

This fixes a visible horizontal offset in the image with VGA monitors.
HDMI monitors seem to be generally more tolerant to incorrect timings,
but may be affected too.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
  • Loading branch information
Laurent Pinchart committed Dec 6, 2021
1 parent 42d95d1 commit f0ce591
Showing 1 changed file with 16 additions and 4 deletions.
20 changes: 16 additions & 4 deletions drivers/gpu/drm/rcar-du/rcar_du_crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
const struct drm_display_mode *mode = &rcrtc->crtc.state->adjusted_mode;
struct rcar_du_device *rcdu = rcrtc->dev;
unsigned long mode_clock = mode->clock * 1000;
unsigned int hdse_offset;
u32 dsmr;
u32 escr;

Expand Down Expand Up @@ -298,10 +299,15 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
| DSMR_DIPM_DISP | DSMR_CSPM;
rcar_du_crtc_write(rcrtc, DSMR, dsmr);

hdse_offset = 19;
if (rcrtc->group->cmms_mask & BIT(rcrtc->index % 2))
hdse_offset += 25;

/* Display timings */
rcar_du_crtc_write(rcrtc, HDSR, mode->htotal - mode->hsync_start - 19);
rcar_du_crtc_write(rcrtc, HDSR, mode->htotal - mode->hsync_start -
hdse_offset);
rcar_du_crtc_write(rcrtc, HDER, mode->htotal - mode->hsync_start +
mode->hdisplay - 19);
mode->hdisplay - hdse_offset);
rcar_du_crtc_write(rcrtc, HSWR, mode->hsync_end -
mode->hsync_start - 1);
rcar_du_crtc_write(rcrtc, HCR, mode->htotal - 1);
Expand Down Expand Up @@ -836,16 +842,22 @@ rcar_du_crtc_mode_valid(struct drm_crtc *crtc,
struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
struct rcar_du_device *rcdu = rcrtc->dev;
bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE;
unsigned int min_sync_porch;
unsigned int vbp;

if (interlaced && !rcar_du_has(rcdu, RCAR_DU_FEATURE_INTERLACED))
return MODE_NO_INTERLACE;

/*
* The hardware requires a minimum combined horizontal sync and back
* porch of 20 pixels and a minimum vertical back porch of 3 lines.
* porch of 20 pixels (when CMM isn't used) or 45 pixels (when CMM is
* used), and a minimum vertical back porch of 3 lines.
*/
if (mode->htotal - mode->hsync_start < 20)
min_sync_porch = 20;
if (rcrtc->group->cmms_mask & BIT(rcrtc->index % 2))
min_sync_porch += 25;

if (mode->htotal - mode->hsync_start < min_sync_porch)
return MODE_HBLANK_NARROW;

vbp = (mode->vtotal - mode->vsync_end) / (interlaced ? 2 : 1);
Expand Down

0 comments on commit f0ce591

Please sign in to comment.