mirror of
https://github.com/torvalds/linux.git
synced 2024-12-26 21:02:19 +00:00
drm: bridge/dw_hdmi: add support for interlaced video modes
Add support for interlaced video modes to the dw_hdmi bridge. This mainly involves halving the vertical parameters to be programmed into the bridge registers, and setting the interlace_allowed connector flag. This brings working 1080i support. However, 480i and 576i fail to work due to the lack of proper pixel repetition support, which is not trivial to add due to the tabular PLL parameterisation. Hence, we filter out these modes in our mode_valid() method. Tested-by: Philipp Zabel <p.zabel@pengutronix.de> Reviewed-by: Fabio Estevam <fabio.estevam@freescale.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
This commit is contained in:
parent
aefa627fa3
commit
e80b9f4eea
@ -1063,6 +1063,7 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
|
||||
u8 inv_val;
|
||||
struct hdmi_vmode *vmode = &hdmi->hdmi_data.video_mode;
|
||||
int hblank, vblank, h_de_hs, v_de_vs, hsync_len, vsync_len;
|
||||
unsigned int vdisplay;
|
||||
|
||||
vmode->mpixelclock = mode->clock * 1000;
|
||||
|
||||
@ -1102,13 +1103,29 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
|
||||
|
||||
hdmi_writeb(hdmi, inv_val, HDMI_FC_INVIDCONF);
|
||||
|
||||
vdisplay = mode->vdisplay;
|
||||
vblank = mode->vtotal - mode->vdisplay;
|
||||
v_de_vs = mode->vsync_start - mode->vdisplay;
|
||||
vsync_len = mode->vsync_end - mode->vsync_start;
|
||||
|
||||
/*
|
||||
* When we're setting an interlaced mode, we need
|
||||
* to adjust the vertical timing to suit.
|
||||
*/
|
||||
if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
|
||||
vdisplay /= 2;
|
||||
vblank /= 2;
|
||||
v_de_vs /= 2;
|
||||
vsync_len /= 2;
|
||||
}
|
||||
|
||||
/* Set up horizontal active pixel width */
|
||||
hdmi_writeb(hdmi, mode->hdisplay >> 8, HDMI_FC_INHACTV1);
|
||||
hdmi_writeb(hdmi, mode->hdisplay, HDMI_FC_INHACTV0);
|
||||
|
||||
/* Set up vertical active lines */
|
||||
hdmi_writeb(hdmi, mode->vdisplay >> 8, HDMI_FC_INVACTV1);
|
||||
hdmi_writeb(hdmi, mode->vdisplay, HDMI_FC_INVACTV0);
|
||||
hdmi_writeb(hdmi, vdisplay >> 8, HDMI_FC_INVACTV1);
|
||||
hdmi_writeb(hdmi, vdisplay, HDMI_FC_INVACTV0);
|
||||
|
||||
/* Set up horizontal blanking pixel region width */
|
||||
hblank = mode->htotal - mode->hdisplay;
|
||||
@ -1116,7 +1133,6 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
|
||||
hdmi_writeb(hdmi, hblank, HDMI_FC_INHBLANK0);
|
||||
|
||||
/* Set up vertical blanking pixel region width */
|
||||
vblank = mode->vtotal - mode->vdisplay;
|
||||
hdmi_writeb(hdmi, vblank, HDMI_FC_INVBLANK);
|
||||
|
||||
/* Set up HSYNC active edge delay width (in pixel clks) */
|
||||
@ -1125,7 +1141,6 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
|
||||
hdmi_writeb(hdmi, h_de_hs, HDMI_FC_HSYNCINDELAY0);
|
||||
|
||||
/* Set up VSYNC active edge delay (in lines) */
|
||||
v_de_vs = mode->vsync_start - mode->vdisplay;
|
||||
hdmi_writeb(hdmi, v_de_vs, HDMI_FC_VSYNCINDELAY);
|
||||
|
||||
/* Set up HSYNC active pulse width (in pixel clks) */
|
||||
@ -1134,7 +1149,6 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
|
||||
hdmi_writeb(hdmi, hsync_len, HDMI_FC_HSYNCINWIDTH0);
|
||||
|
||||
/* Set up VSYNC active edge delay (in lines) */
|
||||
vsync_len = mode->vsync_end - mode->vsync_start;
|
||||
hdmi_writeb(hdmi, vsync_len, HDMI_FC_VSYNCINWIDTH);
|
||||
}
|
||||
|
||||
@ -1608,6 +1622,8 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
|
||||
if (!hdmi)
|
||||
return -ENOMEM;
|
||||
|
||||
hdmi->connector.interlace_allowed = 1;
|
||||
|
||||
hdmi->plat_data = plat_data;
|
||||
hdmi->dev = dev;
|
||||
hdmi->dev_type = plat_data->dev_type;
|
||||
|
Loading…
Reference in New Issue
Block a user