Message ID | 1348771268-3436-3-git-send-email-damien.lespiau@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
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
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. */