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: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
This commit is contained in:
parent
3dbf11e421
commit
906eff7fca
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue