From patchwork Thu Sep 27 18:41:08 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Damien Lespiau X-Patchwork-Id: 1515511 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by patchwork1.kernel.org (Postfix) with ESMTP id 1F6D83FC71 for ; Thu, 27 Sep 2012 18:47:30 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 210A9A0278 for ; Thu, 27 Sep 2012 11:47:30 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-wi0-f169.google.com (mail-wi0-f169.google.com [209.85.212.169]) by gabe.freedesktop.org (Postfix) with ESMTP id 9B8DC9F4C9; Thu, 27 Sep 2012 11:41:22 -0700 (PDT) Received: by mail-wi0-f169.google.com with SMTP id c10so876748wiw.0 for ; Thu, 27 Sep 2012 11:41:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:subject:date:message-id:x-mailer:in-reply-to:references; bh=DJeUg50GAVaiGjww+Zwgyut2U87hwf6oLtsOvr+dCu8=; b=Y63GiGnJ5E58MR5nKpZ/jiGZnFvBB/Kj0TXVYFebvcPSkjP46FFbONgEoVPYIElTXA MfzzUycDvH2U5Z6ug4g+ew3Rue5MI7QvzWdXEJu/9u4zTySDAxfabo8qpK3kjDO1H0Ex OaXSZALt4Xv5hPda5T8itkmT5dgryT540NJA4tIPzL3YUV/PZ74K6tg1eFJR330F2vXK /0aTykYxNMWoFhRWy/Atj4Vqll0gXr5OTwq05P3me550tKhBgVkeMr+PIXFVjHKr3Ctw +zIHTt6uR/rkMMLAC2VoKa9DSe5qny9PuBel8E2+GcD7P2OsYQBOIX+sHTlrw3U03j3U J7yw== Received: by 10.180.82.164 with SMTP id j4mr10086649wiy.18.1348771282251; Thu, 27 Sep 2012 11:41:22 -0700 (PDT) Received: from localhost.localdomain ([83.217.123.106]) by mx.google.com with ESMTPS id q7sm14624516wiy.11.2012.09.27.11.41.21 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 27 Sep 2012 11:41:21 -0700 (PDT) From: Damien Lespiau To: intel-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org Subject: [PATCH 3/3] drm/i915: Add HDMI vendor info frame support Date: Thu, 27 Sep 2012 19:41:08 +0100 Message-Id: <1348771268-3436-4-git-send-email-damien.lespiau@gmail.com> X-Mailer: git-send-email 1.7.11.4 In-Reply-To: <1348771268-3436-1-git-send-email-damien.lespiau@gmail.com> References: <1348771268-3436-1-git-send-email-damien.lespiau@gmail.com> X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org Errors-To: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org 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 Reviewed-by: Rodrigo Vivi Tested-by: Rodrigo Vivi --- 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_SCD 0xb +#define DIP_TYPE_VENDOR 0x81 +#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, struct drm_display_mode *adjusted_mode) { @@ -398,6 +438,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, adjusted_mode); } static void ibx_set_infoframes(struct drm_encoder *encoder, @@ -457,6 +498,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, adjusted_mode); } static void cpt_set_infoframes(struct drm_encoder *encoder, @@ -492,6 +534,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, adjusted_mode); } static void vlv_set_infoframes(struct drm_encoder *encoder, @@ -526,6 +569,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, adjusted_mode); } static void hsw_set_infoframes(struct drm_encoder *encoder, @@ -792,7 +836,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 +873,7 @@ intel_hdmi_set_property(struct drm_connector *connector, goto done; } + return -EINVAL; done: @@ -887,6 +933,7 @@ intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *c { intel_attach_force_audio_property(connector); intel_attach_broadcast_rgb_property(connector); + intel_attach_expose_3d_modes_property(connector); } void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) diff --git a/drivers/gpu/drm/i915/intel_modes.c b/drivers/gpu/drm/i915/intel_modes.c index 29b7259..50216af 100644 --- a/drivers/gpu/drm/i915/intel_modes.c +++ b/drivers/gpu/drm/i915/intel_modes.c @@ -124,3 +124,15 @@ intel_attach_broadcast_rgb_property(struct drm_connector *connector) drm_connector_attach_property(connector, prop, 0); } + +void +intel_attach_expose_3d_modes_property(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + struct drm_property *prop; + + drm_mode_create_s3d_properties(dev); + prop = dev->mode_config.s3d_expose_modes_property; + drm_connector_attach_property(connector, prop, + DRM_MODE_EXPOSE_3D_MODES_OFF); +}