[PATCH 2/3] drm: Parse the HDMI cea vendor block for 3D present
Rodrigo Vivi
rodrigo.vivi at gmail.com
Fri Sep 28 17:46:19 PDT 2012
Reviewed-by: Rodrigo Vivi <rodrigo.vivi at gmail.com>
Tested-by: Rodrigo Vivi <rodrigo.vivi at gmail.com>
On Thu, Sep 27, 2012 at 3:41 PM, Damien Lespiau
<damien.lespiau at gmail.com> wrote:
> From: Damien Lespiau <damien.lespiau at 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 at 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 at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
--
Rodrigo Vivi
Blog: http://blog.vivi.eng.br
More information about the dri-devel
mailing list