[PATCH 1/2] drm/edid: adjust double-clocked cea modes

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The CEA spec has a bunch of very peculiar modes. For backwards
compatibility it specifies a bunch of modes that are suitable to
display old SD TV content. But these modes have such low pixel clocks
that pixels need to be doubled to reach the minimal clock of the HDMI
interface.

Paulo Zanoni already started to fix this up by properly marking these
modes as double-clocked and sending the correct avi infoframe as
required by CEA.

The problem left is that the CEA spec specifies these modes with
timings as they get transmitted, but because the double-clocking is
just to make the HDMI phy happy, the TV actually drops every 2nd
pixel. So e.g. a 1440x576 mode in our CEA mode list is actually a
720x576 mode.

In a way this is similar to the interlaced stuff, where the frame that
logically gets send out is not the same that actually goes through the
wire. To be consistent with how we handle interlaced modes, we want
only half the horizontal timings of what the CEA tables list (which
then also properly tells userspace how big the scanned-out framebuffer
actually is).

To avoid digressing from the CEA table, fix up the horizontal timings
in the cea parsing code and not in the table. Wrt the pixel clock I've
opted to keep it as-is - in interlaced modes we also specify the
pixelclock on the wire. Furthermore this makes checking for bandwidth
constraints simpler.

Similarly to interlaced modes it could be useful to add a doubleclock
flag to drm_mode_set_crtcinfo to specify whether we want double
clocked mode timings specified in doubled-up pixels or not. But
because only the intel driver bothers atm to correctly implement these
modes I've figured adding dead code for potential future use is not
worth it.

Because the mode names are used in userspace tools, these need to be
adjusted, too. But I've left the comments as-is to make comparing with
the CEA spec easier.

Note also that this completely breaks these modes on intel, but that
will be fixed in the next patch to correctly handle double-clocked
modes.

v2: Fix English fail in the commit message

Signed-Off-by: Daniel Vetter <daniel.vetter at ffwll.ch>
---
 drivers/gpu/drm/drm_edid.c       |   19 +++++++++++++++++++
 drivers/gpu/drm/drm_edid_modes.h |   30 +++++++++++++++---------------
 2 files changed, 34 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 608bddf..9e22b61 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -1467,6 +1467,25 @@ do_cea_modes (struct drm_connector *connector, u8 *db, u8 len)
 			struct drm_display_mode *newmode;
 			newmode = drm_mode_duplicate(dev,
 						     &edid_cea_modes[cea_mode]);
+
+			/*
+			 * CEA specifies horizontal timings for double-clocked
+			 * modes in doubled pixels. In drm, we want actual
+			 * pixels (for consistency with other modes where a
+			 * framebuffer pixel is not equal to a scanned-out
+			 * pixel, e.g. interlaced modes).
+			 *
+			 * To keep the table in-sync with the CEA spec, adjust
+			 * horizontal timings here.
+			 */
+			if (newmode->flags & DRM_MODE_FLAG_DBLCLK) {
+				newmode->hdisplay /= 2;
+				newmode->hsync_start /= 2;
+				newmode->hsync_end /= 2;
+				newmode->htotal /= 2;
+				newmode->hskew /= 2;
+			}
+
 			if (newmode) {
 				drm_mode_probed_add(connector, newmode);
 				modes++;
diff --git a/drivers/gpu/drm/drm_edid_modes.h b/drivers/gpu/drm/drm_edid_modes.h
index ff98a7e..9226cbe 100644
--- a/drivers/gpu/drm/drm_edid_modes.h
+++ b/drivers/gpu/drm/drm_edid_modes.h
@@ -511,22 +511,22 @@ static const struct drm_display_mode edid_cea_modes[] = {
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
 			DRM_MODE_FLAG_INTERLACE) },
 	/* 6 - 1440x480i at 60Hz */
-	{ DRM_MODE("1440x480", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1478,
+	{ DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1478,
 		   1602, 1716, 0, 480, 488, 494, 525, 0,
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
 			DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK) },
 	/* 7 - 1440x480i at 60Hz */
-	{ DRM_MODE("1440x480", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1478,
+	{ DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1478,
 		   1602, 1716, 0, 480, 488, 494, 525, 0,
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
 			DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK) },
 	/* 8 - 1440x240 at 60Hz */
-	{ DRM_MODE("1440x240", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1478,
+	{ DRM_MODE("720x240", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1478,
 		   1602, 1716, 0, 240, 244, 247, 262, 0,
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
 			DRM_MODE_FLAG_DBLCLK) },
 	/* 9 - 1440x240 at 60Hz */
-	{ DRM_MODE("1440x240", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1478,
+	{ DRM_MODE("720x240", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1478,
 		   1602, 1716, 0, 240, 244, 247, 262, 0,
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
 			DRM_MODE_FLAG_DBLCLK) },
@@ -578,17 +578,17 @@ static const struct drm_display_mode edid_cea_modes[] = {
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
 			DRM_MODE_FLAG_INTERLACE) },
 	/* 21 - 1440x576i at 50Hz */
-	{ DRM_MODE("1440x576", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1464,
+	{ DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1464,
 		   1590, 1728, 0, 576, 580, 586, 625, 0,
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
 			DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK) },
 	/* 22 - 1440x576i at 50Hz */
-	{ DRM_MODE("1440x576", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1464,
+	{ DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1464,
 		   1590, 1728, 0, 576, 580, 586, 625, 0,
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
 			DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK) },
 	/* 23 - 1440x288 at 50Hz */
-	{ DRM_MODE("1440x288", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1464,
+	{ DRM_MODE("720x288", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1464,
 		   1590, 1728, 0, 288, 290, 293, 312, 0,
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
 			DRM_MODE_FLAG_DBLCLK) },
@@ -678,12 +678,12 @@ static const struct drm_display_mode edid_cea_modes[] = {
 		   796, 864, 0, 576, 581, 586, 625, 0,
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
 	/* 44 - 1440x576i at 100Hz */
-	{ DRM_MODE("1440x576", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1464,
+	{ DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1464,
 		   1590, 1728, 0, 576, 580, 586, 625, 0,
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
 			DRM_MODE_FLAG_DBLCLK) },
 	/* 45 - 1440x576i at 100Hz */
-	{ DRM_MODE("1440x576", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1464,
+	{ DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1464,
 		   1590, 1728, 0, 576, 580, 586, 625, 0,
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
 			DRM_MODE_FLAG_DBLCLK) },
@@ -705,12 +705,12 @@ static const struct drm_display_mode edid_cea_modes[] = {
 		   798, 858, 0, 480, 489, 495, 525, 0,
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
 	/* 50 - 1440x480i at 120Hz */
-	{ DRM_MODE("1440x480", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1478,
+	{ DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1478,
 		   1602, 1716, 0, 480, 488, 494, 525, 0,
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
 			DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK) },
 	/* 51 - 1440x480i at 120Hz */
-	{ DRM_MODE("1440x480", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1478,
+	{ DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1478,
 		   1602, 1716, 0, 480, 488, 494, 525, 0,
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
 			DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK) },
@@ -723,12 +723,12 @@ static const struct drm_display_mode edid_cea_modes[] = {
 		   796, 864, 0, 576, 581, 586, 625, 0,
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
 	/* 54 - 1440x576i at 200Hz */
-	{ DRM_MODE("1440x576", DRM_MODE_TYPE_DRIVER, 108000, 1440, 1464,
+	{ DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 108000, 1440, 1464,
 		   1590, 1728, 0, 576, 580, 586, 625, 0,
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
 			DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK) },
 	/* 55 - 1440x576i at 200Hz */
-	{ DRM_MODE("1440x576", DRM_MODE_TYPE_DRIVER, 108000, 1440, 1464,
+	{ DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 108000, 1440, 1464,
 		   1590, 1728, 0, 576, 580, 586, 625, 0,
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
 			DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK) },
@@ -741,12 +741,12 @@ static const struct drm_display_mode edid_cea_modes[] = {
 		   798, 858, 0, 480, 489, 495, 525, 0,
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
 	/* 58 - 1440x480i at 240 */
-	{ DRM_MODE("1440x480", DRM_MODE_TYPE_DRIVER, 108000, 1440, 1478,
+	{ DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 108000, 1440, 1478,
 		   1602, 1716, 0, 480, 488, 494, 525, 0,
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
 			DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK) },
 	/* 59 - 1440x480i at 240 */
-	{ DRM_MODE("1440x480", DRM_MODE_TYPE_DRIVER, 108000, 1440, 1478,
+	{ DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 108000, 1440, 1478,
 		   1602, 1716, 0, 480, 488, 494, 525, 0,
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
 			DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK) },
-- 
1.7.9



[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux