Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 906eff7f authored by Laurent Pinchart's avatar Laurent Pinchart
Browse files

drm: rcar-du: Implement support for interlaced modes



Accept interlaced modes on the VGA and HDMI connectors and configure the
hardware accordingly.

Signed-off-by: default avatarLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
parent 3dbf11e4
Loading
Loading
Loading
Loading
+15 −8
Original line number Diff line number Diff line
@@ -155,12 +155,15 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
					mode->hsync_start - 1);
	rcar_du_crtc_write(rcrtc, HCR,  mode->htotal - 1);

	rcar_du_crtc_write(rcrtc, VDSR, mode->vtotal - mode->vsync_end - 2);
	rcar_du_crtc_write(rcrtc, VDER, mode->vtotal - mode->vsync_end +
					mode->vdisplay - 2);
	rcar_du_crtc_write(rcrtc, VSPR, mode->vtotal - mode->vsync_end +
					mode->vsync_start - 1);
	rcar_du_crtc_write(rcrtc, VCR,  mode->vtotal - 1);
	rcar_du_crtc_write(rcrtc, VDSR, mode->crtc_vtotal -
					mode->crtc_vsync_end - 2);
	rcar_du_crtc_write(rcrtc, VDER, mode->crtc_vtotal -
					mode->crtc_vsync_end +
					mode->crtc_vdisplay - 2);
	rcar_du_crtc_write(rcrtc, VSPR, mode->crtc_vtotal -
					mode->crtc_vsync_end +
					mode->crtc_vsync_start - 1);
	rcar_du_crtc_write(rcrtc, VCR,  mode->crtc_vtotal - 1);

	rcar_du_crtc_write(rcrtc, DESR,  mode->htotal - mode->hsync_start);
	rcar_du_crtc_write(rcrtc, DEWR,  mode->hdisplay);
@@ -256,6 +259,7 @@ void rcar_du_crtc_update_planes(struct drm_crtc *crtc)
static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc)
{
	struct drm_crtc *crtc = &rcrtc->crtc;
	bool interlaced;
	unsigned int i;

	if (rcrtc->started)
@@ -291,7 +295,10 @@ static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc)
	 * sync mode (with the HSYNC and VSYNC signals configured as outputs and
	 * actively driven).
	 */
	rcar_du_crtc_clr_set(rcrtc, DSYSR, DSYSR_TVM_MASK, DSYSR_TVM_MASTER);
	interlaced = rcrtc->crtc.mode.flags & DRM_MODE_FLAG_INTERLACE;
	rcar_du_crtc_clr_set(rcrtc, DSYSR, DSYSR_TVM_MASK | DSYSR_SCM_MASK,
			     (interlaced ? DSYSR_SCM_INT_VIDEO : 0) |
			     DSYSR_TVM_MASTER);

	rcar_du_group_start_stop(rcrtc->group, true);

@@ -528,7 +535,7 @@ static irqreturn_t rcar_du_crtc_irq(int irq, void *arg)
	status = rcar_du_crtc_read(rcrtc, DSSR);
	rcar_du_crtc_write(rcrtc, DSRCR, status & DSRCR_MASK);

	if (status & DSSR_VBK) {
	if (status & DSSR_FRM) {
		drm_handle_vblank(rcrtc->crtc.dev, rcrtc->index);
		rcar_du_crtc_finish_page_flip(rcrtc);
		ret = IRQ_HANDLED;
+1 −0
Original line number Diff line number Diff line
@@ -95,6 +95,7 @@ int rcar_du_hdmi_connector_init(struct rcar_du_device *rcdu,
	connector = &rcon->connector;
	connector->display_info.width_mm = 0;
	connector->display_info.height_mm = 0;
	connector->interlace_allowed = true;
	connector->polled = DRM_CONNECTOR_POLL_HPD;

	ret = drm_connector_init(rcdu->ddev, connector, &connector_funcs,
+15 −3
Original line number Diff line number Diff line
@@ -104,14 +104,22 @@ void rcar_du_plane_update_base(struct rcar_du_plane *plane)
{
	struct rcar_du_group *rgrp = plane->group;
	unsigned int index = plane->hwindex;
	bool interlaced;
	u32 mwr;

	/* Memory pitch (expressed in pixels) */
	interlaced = plane->crtc->mode.flags & DRM_MODE_FLAG_INTERLACE;

	/* Memory pitch (expressed in pixels). Must be doubled for interlaced
	 * operation with 32bpp formats.
	 */
	if (plane->format->planes == 2)
		mwr = plane->pitch;
	else
		mwr = plane->pitch * 8 / plane->format->bpp;

	if (interlaced && plane->format->bpp == 32)
		mwr *= 2;

	rcar_du_plane_write(rgrp, index, PnMWR, mwr);

	/* The Y position is expressed in raster line units and must be doubled
@@ -119,12 +127,16 @@ void rcar_du_plane_update_base(struct rcar_du_plane *plane)
	 * doubling the Y position is found in the R8A7779 datasheet, but the
	 * rule seems to apply there as well.
	 *
	 * Despite not being documented, doubling seem not to be needed when
	 * operating in interlaced mode.
	 *
	 * Similarly, for the second plane, NV12 and NV21 formats seem to
	 * require a halved Y position value.
	 * require a halved Y position value, in both progressive and interlaced
	 * modes.
	 */
	rcar_du_plane_write(rgrp, index, PnSPXR, plane->src_x);
	rcar_du_plane_write(rgrp, index, PnSPYR, plane->src_y *
			    (plane->format->bpp == 32 ? 2 : 1));
			    (!interlaced && plane->format->bpp == 32 ? 2 : 1));
	rcar_du_plane_write(rgrp, index, PnDSA0R, plane->dma[0]);

	if (plane->format->planes == 2) {
+1 −0
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@
#define DSYSR_SCM_INT_NONE	(0 << 4)
#define DSYSR_SCM_INT_SYNC	(2 << 4)
#define DSYSR_SCM_INT_VIDEO	(3 << 4)
#define DSYSR_SCM_MASK		(3 << 4)

#define DSMR			0x00004
#define DSMR_VSPM		(1 << 28)
+1 −0
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ int rcar_du_vga_connector_init(struct rcar_du_device *rcdu,
	connector = &rcon->connector;
	connector->display_info.width_mm = 0;
	connector->display_info.height_mm = 0;
	connector->interlace_allowed = true;

	ret = drm_connector_init(rcdu->ddev, connector, &connector_funcs,
				 DRM_MODE_CONNECTOR_VGA);