All of lore.kernel.org
 help / color / mirror / Atom feed
From: Damien Lespiau <damien.lespiau@gmail.com>
To: intel-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org
Subject: [PATCH 3/3] drm/i915: Add HDMI vendor info frame support
Date: Wed, 12 Sep 2012 18:47:15 +0100	[thread overview]
Message-ID: <1347472035-2816-4-git-send-email-damien.lespiau@gmail.com> (raw)
In-Reply-To: <1347472035-2816-1-git-send-email-damien.lespiau@gmail.com>

From: Damien Lespiau <damien.lespiau@intel.com>

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 <damien.lespiau@intel.com>
---
 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_SCD	0xb
 
+#define DIP_TYPE_VENDOR		0x81
+#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],
+			hdmi_if.body.payload[5]);
+
+	intel_set_infoframe(encoder, &hdmi_if);
+}
+
 static void g4x_set_infoframes(struct drm_encoder *encoder,
 			       struct drm_display_mode *adjusted_mode)
 {
@@ -398,6 +447,7 @@ static void g4x_set_infoframes(struct drm_encoder *encoder,
 
 	intel_hdmi_set_avi_infoframe(encoder, adjusted_mode);
 	intel_hdmi_set_spd_infoframe(encoder);
+	intel_hdmi_set_hdmi_infoframe(encoder);
 }
 
 static void ibx_set_infoframes(struct drm_encoder *encoder,
@@ -457,6 +507,7 @@ static void ibx_set_infoframes(struct drm_encoder *encoder,
 
 	intel_hdmi_set_avi_infoframe(encoder, adjusted_mode);
 	intel_hdmi_set_spd_infoframe(encoder);
+	intel_hdmi_set_hdmi_infoframe(encoder);
 }
 
 static void cpt_set_infoframes(struct drm_encoder *encoder,
@@ -492,6 +543,7 @@ static void cpt_set_infoframes(struct drm_encoder *encoder,
 
 	intel_hdmi_set_avi_infoframe(encoder, adjusted_mode);
 	intel_hdmi_set_spd_infoframe(encoder);
+	intel_hdmi_set_hdmi_infoframe(encoder);
 }
 
 static void vlv_set_infoframes(struct drm_encoder *encoder,
@@ -526,6 +578,7 @@ static void vlv_set_infoframes(struct drm_encoder *encoder,
 
 	intel_hdmi_set_avi_infoframe(encoder, adjusted_mode);
 	intel_hdmi_set_spd_infoframe(encoder);
+	intel_hdmi_set_hdmi_infoframe(encoder);
 }
 
 static void hsw_set_infoframes(struct drm_encoder *encoder,
@@ -792,7 +845,8 @@ intel_hdmi_set_property(struct drm_connector *connector,
 			uint64_t val)
 {
 	struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
-	struct drm_i915_private *dev_priv = connector->dev->dev_private;
+	struct drm_device *dev = connector->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	int ret;
 
 	ret = drm_connector_property_set_value(connector, property, val);
@@ -828,6 +882,15 @@ intel_hdmi_set_property(struct drm_connector *connector,
 		goto done;
 	}
 
+
+	if (property == dev->mode_config.s3d_select_mode_property) {
+		if (val == intel_hdmi->s3d_mode)
+			return 0;
+
+		intel_hdmi->s3d_mode = val;
+		goto done;
+	}
+
 	return -EINVAL;
 
 done:
@@ -885,8 +948,14 @@ static const struct drm_encoder_funcs intel_hdmi_enc_funcs = {
 static void
 intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *connector)
 {
+	struct drm_device *dev = connector->dev;
+
 	intel_attach_force_audio_property(connector);
 	intel_attach_broadcast_rgb_property(connector);
+	drm_mode_create_3d_property(dev);
+	drm_object_attach_property(&connector->base,
+				   dev->mode_config.s3d_select_mode_property,
+				   0);
 }
 
 void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
-- 
1.7.11.4

  parent reply	other threads:[~2012-09-12 17:47 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-09-12 17:47 [RFC] Stereo 3D modes support Damien Lespiau
2012-09-12 17:47 ` [PATCH 1/3] drm: Parse the HDMI cea vendor block for 3D present Damien Lespiau
2012-09-12 17:47 ` [PATCH 2/3] drm: Add Stereo 3D properties Damien Lespiau
2012-09-12 17:47 ` Damien Lespiau [this message]
2012-09-13 11:37 ` [RFC] Stereo 3D modes support Chris Wilson
2012-09-13 13:02   ` [Intel-gfx] " Lespiau, Damien
2012-09-27 18:41 Stereo 3D modes support v2 Damien Lespiau
2012-09-27 18:41 ` [PATCH 3/3] drm/i915: Add HDMI vendor info frame support Damien Lespiau

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1347472035-2816-4-git-send-email-damien.lespiau@gmail.com \
    --to=damien.lespiau@gmail.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=intel-gfx@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.