diff options
Diffstat (limited to 'drivers/gpu/drm/drm_edid.c')
| -rw-r--r-- | drivers/gpu/drm/drm_edid.c | 47 | 
1 files changed, 45 insertions, 2 deletions
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index f665b05592f..ab6c9733041 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -598,6 +598,50 @@ struct drm_display_mode *drm_mode_std(struct drm_device *dev,  	return mode;  } +/* + * EDID is delightfully ambiguous about how interlaced modes are to be + * encoded.  Our internal representation is of frame height, but some + * HDTV detailed timings are encoded as field height. + * + * The format list here is from CEA, in frame size.  Technically we + * should be checking refresh rate too.  Whatever. + */ +static void +drm_mode_do_interlace_quirk(struct drm_display_mode *mode, +			    struct detailed_pixel_timing *pt) +{ +	int i; +	static const struct { +		int w, h; +	} cea_interlaced[] = { +		{ 1920, 1080 }, +		{  720,  480 }, +		{ 1440,  480 }, +		{ 2880,  480 }, +		{  720,  576 }, +		{ 1440,  576 }, +		{ 2880,  576 }, +	}; +	static const int n_sizes = +		sizeof(cea_interlaced)/sizeof(cea_interlaced[0]); + +	if (!(pt->misc & DRM_EDID_PT_INTERLACED)) +		return; + +	for (i = 0; i < n_sizes; i++) { +		if ((mode->hdisplay == cea_interlaced[i].w) && +		    (mode->vdisplay == cea_interlaced[i].h / 2)) { +			mode->vdisplay *= 2; +			mode->vsync_start *= 2; +			mode->vsync_end *= 2; +			mode->vtotal *= 2; +			mode->vtotal |= 1; +		} +	} + +	mode->flags |= DRM_MODE_FLAG_INTERLACE; +} +  /**   * drm_mode_detailed - create a new mode from an EDID detailed timing section   * @dev: DRM device (needed to create new mode) @@ -680,8 +724,7 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,  	drm_mode_set_name(mode); -	if (pt->misc & DRM_EDID_PT_INTERLACED) -		mode->flags |= DRM_MODE_FLAG_INTERLACE; +	drm_mode_do_interlace_quirk(mode, pt);  	if (quirks & EDID_QUIRK_DETAILED_SYNC_PP) {  		pt->misc |= DRM_EDID_PT_HSYNC_POSITIVE | DRM_EDID_PT_VSYNC_POSITIVE;  |