Reviewed-by: Rodrigo Vivi rodrigo.vivi@gmail.com Tested-by: Rodrigo Vivi rodrigo.vivi@gmail.com
On Thu, Sep 27, 2012 at 3:41 PM, Damien Lespiau damien.lespiau@gmail.com wrote:
From: Damien Lespiau damien.lespiau@intel.com
For now, let's just look at the 3D_present flag of the CEA HDMI vendor block to detect if the sink supports a small list of then mandatory 3D formats.
See the HDMI 1.4a 3D extraction for detail: http://www.hdmi.org/manufacturer/specification.aspx
Signed-off-by: Damien Lespiau damien.lespiau@intel.com
drivers/gpu/drm/drm_edid.c | 87 ++++++++++++++++++++++++++++++++++++++++++++-- include/drm/drm_mode.h | 35 +++++++++++-------- 2 files changed, 105 insertions(+), 17 deletions(-)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index b7ee230..7eecfa0 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -1522,21 +1522,102 @@ do_cea_modes (struct drm_connector *connector, u8 *db, u8 len) return modes; }
+static bool cea_hdmi_3d_present(u8 *hdmi) +{
u8 len, skip = 0;
len = hdmi[0] & 0x1f;
if (len < 8)
return false;
/* no HDMI_Video_present */
if (!(hdmi[8] & (1<<5)))
return false;
/* Latency_fields_present */
if (hdmi[8] & (1 << 7))
skip += 2;
/* I_Latency_fields_present */
if (hdmi[8] & (1 << 6))
skip += 2;
/* the declared length is not long enough */
if (len < (9 + skip))
return false;
return (hdmi[9 + skip] & (1 << 7)) != 0;
+}
+static const struct {
int width, height, freq;
unsigned int select, value;
unsigned int formats;
+} s3d_mandatory_modes[] = {
{ 1920, 1080, 24, DRM_MODE_FLAG_INTERLACE, 0,
DRM_MODE_FLAG_3D_TOP_BOTTOM | DRM_MODE_FLAG_3D_FRAME_PACKING },
{ 1920, 1080, 50, DRM_MODE_FLAG_INTERLACE, DRM_MODE_FLAG_INTERLACE,
DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF },
{ 1920, 1080, 60, DRM_MODE_FLAG_INTERLACE, DRM_MODE_FLAG_INTERLACE,
DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF },
{ 1280, 720, 50, DRM_MODE_FLAG_INTERLACE, 0,
DRM_MODE_FLAG_3D_TOP_BOTTOM | DRM_MODE_FLAG_3D_FRAME_PACKING },
{ 1280, 720, 60, DRM_MODE_FLAG_INTERLACE, 0,
DRM_MODE_FLAG_3D_TOP_BOTTOM | DRM_MODE_FLAG_3D_FRAME_PACKING }
+};
+static void cea_hdmi_patch_mandatory_3d_mode(struct drm_display_mode *mode) +{
int i;
for (i = 0; i < ARRAY_SIZE(s3d_mandatory_modes); i++) {
if (mode->hdisplay == s3d_mandatory_modes[i].width &&
mode->vdisplay == s3d_mandatory_modes[i].height &&
(mode->flags & s3d_mandatory_modes[i].select) ==
s3d_mandatory_modes[i].value &&
drm_mode_vrefresh(mode) == s3d_mandatory_modes[i].freq) {
mode->flags |= s3d_mandatory_modes[i].formats;
}
}
+}
+static void cea_hdmi_patch_mandatory_3d_modes(struct drm_connector *connector) +{
struct drm_display_mode *mode;
list_for_each_entry(mode, &connector->probed_modes, head)
cea_hdmi_patch_mandatory_3d_mode(mode);
+}
static int add_cea_modes(struct drm_connector *connector, struct edid *edid) { u8 * cea = drm_find_cea_extension(edid);
u8 * db, dbl;
int modes = 0;
u8 * db, *hdmi = NULL, dbl;
int modes = 0, vendor_id;
/* let's find the cea modes before looking at the hdmi vendor block
* as the 3d_present flag needs to know about the supported modes
* to infer the 3D modes */ if (cea && cea[1] >= 3) { for (db = cea + 4; db < cea + cea[2]; db += dbl + 1) { dbl = db[0] & 0x1f;
if (((db[0] & 0xe0) >> 5) == VIDEO_BLOCK)
switch ((db[0] & 0xe0) >> 5) {
case VIDEO_BLOCK: modes += do_cea_modes (connector, db+1, dbl);
break;
case VENDOR_BLOCK:
vendor_id = db[1] | db[2] << 8 | db[3] << 16;
if (vendor_id == HDMI_IDENTIFIER)
hdmi = db;
} } }
if (connector->expose_3d_modes && hdmi && cea_hdmi_3d_present(hdmi))
cea_hdmi_patch_mandatory_3d_modes(connector);
return modes;
}
diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h index 45b19c6..d5d22de 100644 --- a/include/drm/drm_mode.h +++ b/include/drm/drm_mode.h @@ -44,20 +44,27 @@
/* Video mode flags */ /* bit compatible with the xorg definitions. */ -#define DRM_MODE_FLAG_PHSYNC (1<<0) -#define DRM_MODE_FLAG_NHSYNC (1<<1) -#define DRM_MODE_FLAG_PVSYNC (1<<2) -#define DRM_MODE_FLAG_NVSYNC (1<<3) -#define DRM_MODE_FLAG_INTERLACE (1<<4) -#define DRM_MODE_FLAG_DBLSCAN (1<<5) -#define DRM_MODE_FLAG_CSYNC (1<<6) -#define DRM_MODE_FLAG_PCSYNC (1<<7) -#define DRM_MODE_FLAG_NCSYNC (1<<8) -#define DRM_MODE_FLAG_HSKEW (1<<9) /* hskew provided */ -#define DRM_MODE_FLAG_BCAST (1<<10) -#define DRM_MODE_FLAG_PIXMUX (1<<11) -#define DRM_MODE_FLAG_DBLCLK (1<<12) -#define DRM_MODE_FLAG_CLKDIV2 (1<<13) +#define DRM_MODE_FLAG_PHSYNC (1<<0) +#define DRM_MODE_FLAG_NHSYNC (1<<1) +#define DRM_MODE_FLAG_PVSYNC (1<<2) +#define DRM_MODE_FLAG_NVSYNC (1<<3) +#define DRM_MODE_FLAG_INTERLACE (1<<4) +#define DRM_MODE_FLAG_DBLSCAN (1<<5) +#define DRM_MODE_FLAG_CSYNC (1<<6) +#define DRM_MODE_FLAG_PCSYNC (1<<7) +#define DRM_MODE_FLAG_NCSYNC (1<<8) +#define DRM_MODE_FLAG_HSKEW (1<<9) /* hskew provided */ +#define DRM_MODE_FLAG_BCAST (1<<10) +#define DRM_MODE_FLAG_PIXMUX (1<<11) +#define DRM_MODE_FLAG_DBLCLK (1<<12) +#define DRM_MODE_FLAG_CLKDIV2 (1<<13) +#define DRM_MODE_FLAG_3D_TOP_BOTTOM (1<<14) +#define DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF (1<<15) +#define DRM_MODE_FLAG_3D_FRAME_PACKING (1<<16)
+#define DRM_MODE_FLAG_3D_MASK (DRM_MODE_FLAG_3D_TOP_BOTTOM | \
DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF | \
DRM_MODE_FLAG_3D_FRAME_PACKING)
/* DPMS flags */ /* bit compatible with the xorg definitions. */ -- 1.7.11.4
dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel