Re: [Intel-gfx] [PATCH 3/3] drm/i915: Add HDMI vendor info frame support
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
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
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],