Re: [Intel-gfx] [PATCH 3/3] drm/i915: Add HDMI vendor info frame support

2012-09-28 Thread Rodrigo Vivi
On Thu, Sep 27, 2012 at 3:41 PM, Damien Lespiau
 wrote:
> From: Damien Lespiau 
>
> When scanning out a 3D framebuffer, send the corresponding infoframe to
> the HDMI sink.
>
> See http://www.hdmi.org/manufacturer/specification.aspx for details.
>
> Signed-off-by: Damien Lespiau 
> ---
>  drivers/gpu/drm/i915/intel_drv.h   | 14 +++
>  drivers/gpu/drm/i915/intel_hdmi.c  | 49 
> +-
>  drivers/gpu/drm/i915/intel_modes.c | 12 ++
>  3 files changed, 74 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_drv.h 
> b/drivers/gpu/drm/i915/intel_drv.h
> index cd54cf8..c326d30e 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -263,6 +263,13 @@ struct cxsr_latency {
>  #define DIP_SPD_BD 0xa
>  #define DIP_SPD_SCD0xb
>
> +#define DIP_TYPE_VENDOR0x81
> +#define DIP_VERSION_VENDOR 0x1
> +#define DIP_HDMI_3D_PRESENT(0x2<<5)
> +#define DIP_HDMI_3D_STRUCT_FP  (0x0<<4)
> +#define DIP_HDMI_3D_STRUCT_TB  (0x6<<4)
> +#define DIP_HDMI_3D_STRUCT_SBSH(0x8<<4)
> +
>  struct dip_infoframe {
> uint8_t type;   /* HB0 */
> uint8_t ver;/* HB1 */
> @@ -292,6 +299,12 @@ struct dip_infoframe {
> uint8_t pd[16];
> uint8_t sdi;
> } __attribute__ ((packed)) spd;
> +   struct {
> +   uint8_t vendor_id[3];
> +   uint8_t video_format;
> +   uint8_t s3d_struct;
> +   uint8_t s3d_ext_data;
> +   } __attribute__ ((packed)) hdmi;
> uint8_t payload[27];
> } __attribute__ ((packed)) body;
>  } __attribute__((packed));
> @@ -348,6 +361,7 @@ int intel_ddc_get_modes(struct drm_connector *c, struct 
> i2c_adapter *adapter);
>
>  extern void intel_attach_force_audio_property(struct drm_connector 
> *connector);
>  extern void intel_attach_broadcast_rgb_property(struct drm_connector 
> *connector);
> +extern void intel_attach_expose_3d_modes_property(struct drm_connector 
> *connector);
>
>  extern void intel_crt_init(struct drm_device *dev);
>  extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg);
> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c 
> b/drivers/gpu/drm/i915/intel_hdmi.c
> index 98f6024..2d51b7e 100644
> --- a/drivers/gpu/drm/i915/intel_hdmi.c
> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> @@ -83,6 +83,8 @@ static u32 g4x_infoframe_index(struct dip_infoframe *frame)
> return VIDEO_DIP_SELECT_AVI;
> case DIP_TYPE_SPD:
> return VIDEO_DIP_SELECT_SPD;
> +   case DIP_TYPE_VENDOR:
> +   return VIDEO_DIP_SELECT_VENDOR;
> default:
> DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type);
> return 0;
> @@ -96,6 +98,8 @@ static u32 g4x_infoframe_enable(struct dip_infoframe *frame)
> return VIDEO_DIP_ENABLE_AVI;
> case DIP_TYPE_SPD:
> return VIDEO_DIP_ENABLE_SPD;
> +   case DIP_TYPE_VENDOR:
> +   return VIDEO_DIP_ENABLE_VENDOR;
> default:
> DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type);
> return 0;
> @@ -338,6 +342,42 @@ static void intel_hdmi_set_spd_infoframe(struct 
> drm_encoder *encoder)
> intel_set_infoframe(encoder, &spd_if);
>  }
>
> +static void intel_hdmi_set_hdmi_infoframe(struct drm_encoder *encoder,
> + struct drm_display_mode 
> *adjusted_mode)
> +{
> +   struct dip_infoframe hdmi_if;
> +
> +   /* We really only need to send a HDMI vendor info frame when having
> +* a 3D format to describe */
> +   if (!(adjusted_mode->flags & DRM_MODE_FLAG_3D_MASK))
> +   return;
> +
> +   memset(&hdmi_if, 0, sizeof(hdmi_if));
> +   hdmi_if.type = DIP_TYPE_VENDOR;
> +   hdmi_if.ver = DIP_VERSION_VENDOR;
> +   /* HDMI IEEE registration id, least significant bit first */
> +   hdmi_if.body.hdmi.vendor_id[0] = 0x03;
> +   hdmi_if.body.hdmi.vendor_id[1] = 0x0c;
> +   hdmi_if.body.hdmi.vendor_id[2] = 0x00;
> +   hdmi_if.body.hdmi.video_format = DIP_HDMI_3D_PRESENT;
> +   if (adjusted_mode->flags & DRM_MODE_FLAG_3D_FRAME_PACKING)
> +   hdmi_if.body.hdmi.s3d_struct = DIP_HDMI_3D_STRUCT_FP;
> +   else if (adjusted_mode->flags & DRM_MODE_FLAG_3D_TOP_BOTTOM)
> +   hdmi_if.body.hdmi.s3d_struct = DIP_HDMI_3D_STRUCT_TB;
> +   else if (adjusted_mode->flags & DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF)
> +   hdmi_if.body.hdmi.s3d_struct = DIP_HDMI_3D_STRUCT_SBSH;
> +   /* len is the payload len, not including checksum. Side by side (half)
> +* has an extra byte for 3D_Ext_Data */
> +   if (adjusted_mode->flags & DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF) {
> +   hdmi_if.len = 6;
> +   /* 

[Intel-gfx] [PATCH 3/3] drm/i915: Add HDMI vendor info frame support

2012-09-27 Thread Damien Lespiau
From: Damien Lespiau 

When scanning out a 3D framebuffer, send the corresponding infoframe to
the HDMI sink.

See http://www.hdmi.org/manufacturer/specification.aspx for details.

Signed-off-by: Damien Lespiau 
---
 drivers/gpu/drm/i915/intel_drv.h   | 14 +++
 drivers/gpu/drm/i915/intel_hdmi.c  | 49 +-
 drivers/gpu/drm/i915/intel_modes.c | 12 ++
 3 files changed, 74 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index cd54cf8..c326d30e 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -263,6 +263,13 @@ struct cxsr_latency {
 #define DIP_SPD_BD 0xa
 #define DIP_SPD_SCD0xb
 
+#define DIP_TYPE_VENDOR0x81
+#define DIP_VERSION_VENDOR 0x1
+#define DIP_HDMI_3D_PRESENT(0x2<<5)
+#define DIP_HDMI_3D_STRUCT_FP  (0x0<<4)
+#define DIP_HDMI_3D_STRUCT_TB  (0x6<<4)
+#define DIP_HDMI_3D_STRUCT_SBSH(0x8<<4)
+
 struct dip_infoframe {
uint8_t type;   /* HB0 */
uint8_t ver;/* HB1 */
@@ -292,6 +299,12 @@ struct dip_infoframe {
uint8_t pd[16];
uint8_t sdi;
} __attribute__ ((packed)) spd;
+   struct {
+   uint8_t vendor_id[3];
+   uint8_t video_format;
+   uint8_t s3d_struct;
+   uint8_t s3d_ext_data;
+   } __attribute__ ((packed)) hdmi;
uint8_t payload[27];
} __attribute__ ((packed)) body;
 } __attribute__((packed));
@@ -348,6 +361,7 @@ int intel_ddc_get_modes(struct drm_connector *c, struct 
i2c_adapter *adapter);
 
 extern void intel_attach_force_audio_property(struct drm_connector *connector);
 extern void intel_attach_broadcast_rgb_property(struct drm_connector 
*connector);
+extern void intel_attach_expose_3d_modes_property(struct drm_connector 
*connector);
 
 extern void intel_crt_init(struct drm_device *dev);
 extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg);
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c 
b/drivers/gpu/drm/i915/intel_hdmi.c
index 98f6024..2d51b7e 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -83,6 +83,8 @@ static u32 g4x_infoframe_index(struct dip_infoframe *frame)
return VIDEO_DIP_SELECT_AVI;
case DIP_TYPE_SPD:
return VIDEO_DIP_SELECT_SPD;
+   case DIP_TYPE_VENDOR:
+   return VIDEO_DIP_SELECT_VENDOR;
default:
DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type);
return 0;
@@ -96,6 +98,8 @@ static u32 g4x_infoframe_enable(struct dip_infoframe *frame)
return VIDEO_DIP_ENABLE_AVI;
case DIP_TYPE_SPD:
return VIDEO_DIP_ENABLE_SPD;
+   case DIP_TYPE_VENDOR:
+   return VIDEO_DIP_ENABLE_VENDOR;
default:
DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type);
return 0;
@@ -338,6 +342,42 @@ static void intel_hdmi_set_spd_infoframe(struct 
drm_encoder *encoder)
intel_set_infoframe(encoder, &spd_if);
 }
 
+static void intel_hdmi_set_hdmi_infoframe(struct drm_encoder *encoder,
+ struct drm_display_mode 
*adjusted_mode)
+{
+   struct dip_infoframe hdmi_if;
+
+   /* We really only need to send a HDMI vendor info frame when having
+* a 3D format to describe */
+   if (!(adjusted_mode->flags & DRM_MODE_FLAG_3D_MASK))
+   return;
+
+   memset(&hdmi_if, 0, sizeof(hdmi_if));
+   hdmi_if.type = DIP_TYPE_VENDOR;
+   hdmi_if.ver = DIP_VERSION_VENDOR;
+   /* HDMI IEEE registration id, least significant bit first */
+   hdmi_if.body.hdmi.vendor_id[0] = 0x03;
+   hdmi_if.body.hdmi.vendor_id[1] = 0x0c;
+   hdmi_if.body.hdmi.vendor_id[2] = 0x00;
+   hdmi_if.body.hdmi.video_format = DIP_HDMI_3D_PRESENT;
+   if (adjusted_mode->flags & DRM_MODE_FLAG_3D_FRAME_PACKING)
+   hdmi_if.body.hdmi.s3d_struct = DIP_HDMI_3D_STRUCT_FP;
+   else if (adjusted_mode->flags & DRM_MODE_FLAG_3D_TOP_BOTTOM)
+   hdmi_if.body.hdmi.s3d_struct = DIP_HDMI_3D_STRUCT_TB;
+   else if (adjusted_mode->flags & DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF)
+   hdmi_if.body.hdmi.s3d_struct = DIP_HDMI_3D_STRUCT_SBSH;
+   /* len is the payload len, not including checksum. Side by side (half)
+* has an extra byte for 3D_Ext_Data */
+   if (adjusted_mode->flags & DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF) {
+   hdmi_if.len = 6;
+   /* SBSH is subsampled by a factor of 2 */
+   hdmi_if.body.hdmi.s3d_ext_data = 2 << 4;
+   } else
+   hdmi_if.len = 5;
+
+   intel_set_infoframe(encoder, &hdmi_if);
+}
+
 static void g4x_set_infoframes(struct drm_encoder *encoder,
 

[Intel-gfx] [PATCH 3/3] drm/i915: Add HDMI vendor info frame support

2012-09-12 Thread Damien Lespiau
From: Damien Lespiau 

When scanning out a 3D framebuffer, send the corresponding infoframe to
the HDMI sink.

See http://www.hdmi.org/manufacturer/specification.aspx for details.

Signed-off-by: Damien Lespiau 
---
 drivers/gpu/drm/i915/intel_drv.h  | 14 
 drivers/gpu/drm/i915/intel_hdmi.c | 71 ++-
 2 files changed, 84 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index cd54cf8..76d488e 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -263,6 +263,13 @@ struct cxsr_latency {
 #define DIP_SPD_BD 0xa
 #define DIP_SPD_SCD0xb
 
+#define DIP_TYPE_VENDOR0x81
+#define DIP_VERSION_VENDOR 0x1
+#define DIP_HDMI_3D_PRESENT(0x2<<4)
+#define DIP_HDMI_3D_STRUCT_FP  (0x0<<4)
+#define DIP_HDMI_3D_STRUCT_TB  (0x6<<4)
+#define DIP_HDMI_3D_STRUCT_SBSH(0x8<<4)
+
 struct dip_infoframe {
uint8_t type;   /* HB0 */
uint8_t ver;/* HB1 */
@@ -292,6 +299,12 @@ struct dip_infoframe {
uint8_t pd[16];
uint8_t sdi;
} __attribute__ ((packed)) spd;
+   struct {
+   uint8_t vendor_id[3];
+   uint8_t video_format;
+   uint8_t s3d_struct;
+   uint8_t s3d_ext_data;
+   } __attribute__ ((packed)) hdmi;
uint8_t payload[27];
} __attribute__ ((packed)) body;
 } __attribute__((packed));
@@ -305,6 +318,7 @@ struct intel_hdmi {
bool has_hdmi_sink;
bool has_audio;
enum hdmi_force_audio force_audio;
+   unsigned int s3d_mode;
void (*write_infoframe)(struct drm_encoder *encoder,
struct dip_infoframe *frame);
void (*set_infoframes)(struct drm_encoder *encoder,
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c 
b/drivers/gpu/drm/i915/intel_hdmi.c
index 98f6024..ab0553d 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -83,6 +83,8 @@ static u32 g4x_infoframe_index(struct dip_infoframe *frame)
return VIDEO_DIP_SELECT_AVI;
case DIP_TYPE_SPD:
return VIDEO_DIP_SELECT_SPD;
+   case DIP_TYPE_VENDOR:
+   return VIDEO_DIP_SELECT_VENDOR;
default:
DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type);
return 0;
@@ -96,6 +98,8 @@ static u32 g4x_infoframe_enable(struct dip_infoframe *frame)
return VIDEO_DIP_ENABLE_AVI;
case DIP_TYPE_SPD:
return VIDEO_DIP_ENABLE_SPD;
+   case DIP_TYPE_VENDOR:
+   return VIDEO_DIP_ENABLE_VENDOR;
default:
DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type);
return 0;
@@ -338,6 +342,51 @@ static void intel_hdmi_set_spd_infoframe(struct 
drm_encoder *encoder)
intel_set_infoframe(encoder, &spd_if);
 }
 
+static void intel_hdmi_set_hdmi_infoframe(struct drm_encoder *encoder)
+{
+   struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+   struct dip_infoframe hdmi_if;
+
+   /* We really only need to send a HDMI vendor info frame when having
+* a 3D format to describe */
+   if (!intel_hdmi->s3d_mode)
+   return;
+
+   memset(&hdmi_if, 0, sizeof(hdmi_if));
+   hdmi_if.type = DIP_TYPE_VENDOR;
+   hdmi_if.ver = DIP_VERSION_VENDOR;
+   /* HDMI IEEE registration id, least significant bit first */
+   hdmi_if.body.hdmi.vendor_id[0] = 0x03;
+   hdmi_if.body.hdmi.vendor_id[1] = 0xc0;
+   hdmi_if.body.hdmi.vendor_id[2] = 0x00;
+   hdmi_if.body.hdmi.video_format = DIP_HDMI_3D_PRESENT;
+   if (intel_hdmi->s3d_mode & DRM_MODE_FLAG_3D_FRAME_PACKING)
+   hdmi_if.body.hdmi.s3d_struct = DIP_HDMI_3D_STRUCT_FP;
+   else if (intel_hdmi->s3d_mode & DRM_MODE_FLAG_3D_TOP_BOTTOM)
+   hdmi_if.body.hdmi.s3d_struct = DIP_HDMI_3D_STRUCT_TB;
+   else if (intel_hdmi->s3d_mode & DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF)
+   hdmi_if.body.hdmi.s3d_struct = DIP_HDMI_3D_STRUCT_SBSH;
+   /* len is the payload len, not including checksum. Side by side (half)
+* has an extra byte for 3D_Ext_Data */
+   if (intel_hdmi->s3d_mode & DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF) {
+   hdmi_if.len = 6;
+   /* SBSH is subsampled by a factor of 2 */
+   hdmi_if.body.hdmi.s3d_ext_data = 2 << 4;
+   } else
+   hdmi_if.len = 5;
+
+   DRM_DEBUG_DRIVER("3D payload (len %d) %02x %02x %02x %02x %02x %02x\n",
+   hdmi_if.len,
+   hdmi_if.body.payload[0],
+   hdmi_if.body.payload[1],
+   hdmi_if.body.payload[2],
+   hdmi_if.body.payload[3],
+   hdmi_if.body.payload[4],