[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