[Intel-gfx] [PATCH v3] drm: add support for additional stereo 3D modes

2013-10-16 Thread Thomas Wood
Parse the 3D_Structure_ALL and 3D_MASK fields of the HDMI Vendor
Specific Data Block to expose more stereo 3D modes.

v2: Use (1  0) for consistency. (Ville Syrjälä)
Skip adding any modes if 3D_MASK is indicated as being present but
the length only includes 3D_Structure_ALL. (Ville Syrjälä)
Check that the value of HDMI_3D_LEN is large enough to include
3D_Structure_ALL and 3D_MASK, if they are present. (Ville Syrjälä)
v3: Increment offset before the length checks. (Ville Syrjälä)

Signed-off-by: Thomas Wood thomas.w...@intel.com
---
 drivers/gpu/drm/drm_edid.c | 103 +
 1 file changed, 94 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 9e81609..f1764ec 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -2652,6 +2652,50 @@ static int add_hdmi_mode(struct drm_connector 
*connector, u8 vic)
return 1;
 }
 
+static int add_3d_struct_modes(struct drm_connector *connector, u16 structure,
+  const u8 *video_db, u8 video_len, u8 video_index)
+{
+   struct drm_device *dev = connector-dev;
+   struct drm_display_mode *newmode;
+   int modes = 0;
+   u8 cea_mode;
+
+   if (video_db == NULL || video_index  video_len)
+   return 0;
+
+   /* CEA modes are numbered 1..127 */
+   cea_mode = (video_db[video_index]  127) - 1;
+   if (cea_mode = ARRAY_SIZE(edid_cea_modes))
+   return 0;
+
+   if (structure  (1  0)) {
+   newmode = drm_mode_duplicate(dev, edid_cea_modes[cea_mode]);
+   if (newmode) {
+   newmode-flags |= DRM_MODE_FLAG_3D_FRAME_PACKING;
+   drm_mode_probed_add(connector, newmode);
+   modes++;
+   }
+   }
+   if (structure  (1  6)) {
+   newmode = drm_mode_duplicate(dev, edid_cea_modes[cea_mode]);
+   if (newmode) {
+   newmode-flags |= DRM_MODE_FLAG_3D_TOP_AND_BOTTOM;
+   drm_mode_probed_add(connector, newmode);
+   modes++;
+   }
+   }
+   if (structure  (1  8)) {
+   newmode = drm_mode_duplicate(dev, edid_cea_modes[cea_mode]);
+   if (newmode) {
+   newmode-flags = DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF;
+   drm_mode_probed_add(connector, newmode);
+   modes++;
+   }
+   }
+
+   return modes;
+}
+
 /*
  * do_hdmi_vsdb_modes - Parse the HDMI Vendor Specific data block
  * @connector: connector corresponding to the HDMI sink
@@ -2662,10 +2706,13 @@ static int add_hdmi_mode(struct drm_connector 
*connector, u8 vic)
  * also adds the stereo 3d modes when applicable.
  */
 static int
-do_hdmi_vsdb_modes(struct drm_connector *connector, const u8 *db, u8 len)
+do_hdmi_vsdb_modes(struct drm_connector *connector, const u8 *db, u8 len,
+  const u8 *video_db, u8 video_len)
 {
-   int modes = 0, offset = 0, i;
-   u8 vic_len;
+   int modes = 0, offset = 0, i, multi_present = 0;
+   u8 vic_len, hdmi_3d_len = 0;
+   u16 mask;
+   u16 structure_all;
 
if (len  8)
goto out;
@@ -2689,11 +2736,16 @@ do_hdmi_vsdb_modes(struct drm_connector *connector, 
const u8 *db, u8 len)
 
/* 3D_Present */
offset++;
-   if (db[8 + offset]  (1  7))
+   if (db[8 + offset]  (1  7)) {
modes += add_hdmi_mandatory_stereo_modes(connector);
 
+   /* 3D_Multi_present */
+   multi_present = (db[8 + offset]  0x60)  5;
+   }
+
offset++;
vic_len = db[8 + offset]  5;
+   hdmi_3d_len = db[8 + offset]  0x1f;
 
for (i = 0; i  vic_len  len = (9 + offset + i); i++) {
u8 vic;
@@ -2701,6 +2753,35 @@ do_hdmi_vsdb_modes(struct drm_connector *connector, 
const u8 *db, u8 len)
vic = db[9 + offset + i];
modes += add_hdmi_mode(connector, vic);
}
+   offset += 1 + vic_len;
+
+   if (!(multi_present == 1 || multi_present == 2))
+   goto out;
+
+   if ((multi_present == 1  len  (9 + offset)) ||
+   (multi_present == 2  len  (11 + offset)))
+   goto out;
+
+   if ((multi_present == 1  hdmi_3d_len  2) ||
+   (multi_present == 2  hdmi_3d_len  4))
+   goto out;
+
+   /* 3D_Structure_ALL */
+   structure_all = (db[8 + offset]  8) | db[9 + offset];
+
+   /* check if 3D_MASK is present */
+   if (multi_present == 2)
+   mask = (db[10 + offset]  8) | db[11 + offset];
+   else
+   mask = 0x;
+
+   for (i = 0; i  16; i++) {
+   if (mask  (1  i))
+   modes += add_3d_struct_modes(connector,
+structure_all,
+   

Re: [Intel-gfx] [PATCH v3] drm: add support for additional stereo 3D modes

2013-10-16 Thread Ville Syrjälä
On Wed, Oct 16, 2013 at 03:58:50PM +0100, Thomas Wood wrote:
 Parse the 3D_Structure_ALL and 3D_MASK fields of the HDMI Vendor
 Specific Data Block to expose more stereo 3D modes.
 
 v2: Use (1  0) for consistency. (Ville Syrjälä)
 Skip adding any modes if 3D_MASK is indicated as being present but
 the length only includes 3D_Structure_ALL. (Ville Syrjälä)
 Check that the value of HDMI_3D_LEN is large enough to include
 3D_Structure_ALL and 3D_MASK, if they are present. (Ville Syrjälä)
 v3: Increment offset before the length checks. (Ville Syrjälä)
 
 Signed-off-by: Thomas Wood thomas.w...@intel.com

Reviewed-by: Ville Syrjälä ville.syrj...@linux.intel.com

 ---
  drivers/gpu/drm/drm_edid.c | 103 
 +
  1 file changed, 94 insertions(+), 9 deletions(-)
 
 diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
 index 9e81609..f1764ec 100644
 --- a/drivers/gpu/drm/drm_edid.c
 +++ b/drivers/gpu/drm/drm_edid.c
 @@ -2652,6 +2652,50 @@ static int add_hdmi_mode(struct drm_connector 
 *connector, u8 vic)
   return 1;
  }
  
 +static int add_3d_struct_modes(struct drm_connector *connector, u16 
 structure,
 +const u8 *video_db, u8 video_len, u8 video_index)
 +{
 + struct drm_device *dev = connector-dev;
 + struct drm_display_mode *newmode;
 + int modes = 0;
 + u8 cea_mode;
 +
 + if (video_db == NULL || video_index  video_len)
 + return 0;
 +
 + /* CEA modes are numbered 1..127 */
 + cea_mode = (video_db[video_index]  127) - 1;
 + if (cea_mode = ARRAY_SIZE(edid_cea_modes))
 + return 0;
 +
 + if (structure  (1  0)) {
 + newmode = drm_mode_duplicate(dev, edid_cea_modes[cea_mode]);
 + if (newmode) {
 + newmode-flags |= DRM_MODE_FLAG_3D_FRAME_PACKING;
 + drm_mode_probed_add(connector, newmode);
 + modes++;
 + }
 + }
 + if (structure  (1  6)) {
 + newmode = drm_mode_duplicate(dev, edid_cea_modes[cea_mode]);
 + if (newmode) {
 + newmode-flags |= DRM_MODE_FLAG_3D_TOP_AND_BOTTOM;
 + drm_mode_probed_add(connector, newmode);
 + modes++;
 + }
 + }
 + if (structure  (1  8)) {
 + newmode = drm_mode_duplicate(dev, edid_cea_modes[cea_mode]);
 + if (newmode) {
 + newmode-flags = DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF;
 + drm_mode_probed_add(connector, newmode);
 + modes++;
 + }
 + }
 +
 + return modes;
 +}
 +
  /*
   * do_hdmi_vsdb_modes - Parse the HDMI Vendor Specific data block
   * @connector: connector corresponding to the HDMI sink
 @@ -2662,10 +2706,13 @@ static int add_hdmi_mode(struct drm_connector 
 *connector, u8 vic)
   * also adds the stereo 3d modes when applicable.
   */
  static int
 -do_hdmi_vsdb_modes(struct drm_connector *connector, const u8 *db, u8 len)
 +do_hdmi_vsdb_modes(struct drm_connector *connector, const u8 *db, u8 len,
 +const u8 *video_db, u8 video_len)
  {
 - int modes = 0, offset = 0, i;
 - u8 vic_len;
 + int modes = 0, offset = 0, i, multi_present = 0;
 + u8 vic_len, hdmi_3d_len = 0;
 + u16 mask;
 + u16 structure_all;
  
   if (len  8)
   goto out;
 @@ -2689,11 +2736,16 @@ do_hdmi_vsdb_modes(struct drm_connector *connector, 
 const u8 *db, u8 len)
  
   /* 3D_Present */
   offset++;
 - if (db[8 + offset]  (1  7))
 + if (db[8 + offset]  (1  7)) {
   modes += add_hdmi_mandatory_stereo_modes(connector);
  
 + /* 3D_Multi_present */
 + multi_present = (db[8 + offset]  0x60)  5;
 + }
 +
   offset++;
   vic_len = db[8 + offset]  5;
 + hdmi_3d_len = db[8 + offset]  0x1f;
  
   for (i = 0; i  vic_len  len = (9 + offset + i); i++) {
   u8 vic;
 @@ -2701,6 +2753,35 @@ do_hdmi_vsdb_modes(struct drm_connector *connector, 
 const u8 *db, u8 len)
   vic = db[9 + offset + i];
   modes += add_hdmi_mode(connector, vic);
   }
 + offset += 1 + vic_len;
 +
 + if (!(multi_present == 1 || multi_present == 2))
 + goto out;
 +
 + if ((multi_present == 1  len  (9 + offset)) ||
 + (multi_present == 2  len  (11 + offset)))
 + goto out;
 +
 + if ((multi_present == 1  hdmi_3d_len  2) ||
 + (multi_present == 2  hdmi_3d_len  4))
 + goto out;
 +
 + /* 3D_Structure_ALL */
 + structure_all = (db[8 + offset]  8) | db[9 + offset];
 +
 + /* check if 3D_MASK is present */
 + if (multi_present == 2)
 + mask = (db[10 + offset]  8) | db[11 + offset];
 + else
 + mask = 0x;
 +
 + for (i = 0; i  16; i++) {
 + if (mask  (1  i))
 + modes += 

Re: [Intel-gfx] [PATCH v3] drm: add support for additional stereo 3D modes

2013-10-16 Thread Daniel Vetter
On Wed, Oct 16, 2013 at 06:07:30PM +0300, Ville Syrjälä wrote:
 On Wed, Oct 16, 2013 at 03:58:50PM +0100, Thomas Wood wrote:
  Parse the 3D_Structure_ALL and 3D_MASK fields of the HDMI Vendor
  Specific Data Block to expose more stereo 3D modes.
  
  v2: Use (1  0) for consistency. (Ville Syrjälä)
  Skip adding any modes if 3D_MASK is indicated as being present but
  the length only includes 3D_Structure_ALL. (Ville Syrjälä)
  Check that the value of HDMI_3D_LEN is large enough to include
  3D_Structure_ALL and 3D_MASK, if they are present. (Ville Syrjälä)
  v3: Increment offset before the length checks. (Ville Syrjälä)
  
  Signed-off-by: Thomas Wood thomas.w...@intel.com
 
 Reviewed-by: Ville Syrjälä ville.syrj...@linux.intel.com

Queued for -next, thanks for the patch.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx