| From 638db3396ad9b503b213a372dd640394167c7828 Mon Sep 17 00:00:00 2001 |
| From: Nickey Yang <nickey.yang@rock-chips.com> |
| Date: Tue, 21 Mar 2017 15:36:17 +0800 |
| Subject: [PATCH 236/286] drm: bridge: dw-hdmi: add HDMI vendor specific |
| infoframe config |
| |
| Vendor specific infoframe is mandatory for 4K2K resolution. |
| Without this, the HDMI protocol compliance fails. |
| |
| Signed-off-by: Nickey Yang <nickey.yang@rock-chips.com> |
| Reviewed-by: Jose Abreu <joabreu@synopsys.com> |
| Signed-off-by: Archit Taneja <architt@codeaurora.org> |
| Link: http://patchwork.freedesktop.org/patch/msgid/1490081777-2232-1-git-send-email-nickey.yang@rock-chips.com |
| (cherry picked from commit 9aa1eca095579b8a8ea84d9bbd1fbdeff49cebd4) |
| Signed-off-by: Simon Horman <horms+renesas@verge.net.au> |
| --- |
| drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 53 ++++++++++++++++++++++++++++++ |
| drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | 4 ++ |
| 2 files changed, 57 insertions(+) |
| |
| --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c |
| +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c |
| @@ -1240,6 +1240,58 @@ static void hdmi_config_AVI(struct dw_hd |
| hdmi_writeb(hdmi, (frame.right_bar >> 8) & 0xff, HDMI_FC_AVISRB1); |
| } |
| |
| +static void hdmi_config_vendor_specific_infoframe(struct dw_hdmi *hdmi, |
| + struct drm_display_mode *mode) |
| +{ |
| + struct hdmi_vendor_infoframe frame; |
| + u8 buffer[10]; |
| + ssize_t err; |
| + |
| + err = drm_hdmi_vendor_infoframe_from_display_mode(&frame, mode); |
| + if (err < 0) |
| + /* |
| + * Going into that statement does not means vendor infoframe |
| + * fails. It just informed us that vendor infoframe is not |
| + * needed for the selected mode. Only 4k or stereoscopic 3D |
| + * mode requires vendor infoframe. So just simply return. |
| + */ |
| + return; |
| + |
| + err = hdmi_vendor_infoframe_pack(&frame, buffer, sizeof(buffer)); |
| + if (err < 0) { |
| + dev_err(hdmi->dev, "Failed to pack vendor infoframe: %zd\n", |
| + err); |
| + return; |
| + } |
| + hdmi_mask_writeb(hdmi, 0, HDMI_FC_DATAUTO0, HDMI_FC_DATAUTO0_VSD_OFFSET, |
| + HDMI_FC_DATAUTO0_VSD_MASK); |
| + |
| + /* Set the length of HDMI vendor specific InfoFrame payload */ |
| + hdmi_writeb(hdmi, buffer[2], HDMI_FC_VSDSIZE); |
| + |
| + /* Set 24bit IEEE Registration Identifier */ |
| + hdmi_writeb(hdmi, buffer[4], HDMI_FC_VSDIEEEID0); |
| + hdmi_writeb(hdmi, buffer[5], HDMI_FC_VSDIEEEID1); |
| + hdmi_writeb(hdmi, buffer[6], HDMI_FC_VSDIEEEID2); |
| + |
| + /* Set HDMI_Video_Format and HDMI_VIC/3D_Structure */ |
| + hdmi_writeb(hdmi, buffer[7], HDMI_FC_VSDPAYLOAD0); |
| + hdmi_writeb(hdmi, buffer[8], HDMI_FC_VSDPAYLOAD1); |
| + |
| + if (frame.s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF) |
| + hdmi_writeb(hdmi, buffer[9], HDMI_FC_VSDPAYLOAD2); |
| + |
| + /* Packet frame interpolation */ |
| + hdmi_writeb(hdmi, 1, HDMI_FC_DATAUTO1); |
| + |
| + /* Auto packets per frame and line spacing */ |
| + hdmi_writeb(hdmi, 0x11, HDMI_FC_DATAUTO2); |
| + |
| + /* Configures the Frame Composer On RDRB mode */ |
| + hdmi_mask_writeb(hdmi, 1, HDMI_FC_DATAUTO0, HDMI_FC_DATAUTO0_VSD_OFFSET, |
| + HDMI_FC_DATAUTO0_VSD_MASK); |
| +} |
| + |
| static void hdmi_av_composer(struct dw_hdmi *hdmi, |
| const struct drm_display_mode *mode) |
| { |
| @@ -1489,6 +1541,7 @@ static int dw_hdmi_setup(struct dw_hdmi |
| |
| /* HDMI Initialization Step F - Configure AVI InfoFrame */ |
| hdmi_config_AVI(hdmi, mode); |
| + hdmi_config_vendor_specific_infoframe(hdmi, mode); |
| } else { |
| dev_dbg(hdmi->dev, "%s DVI mode\n", __func__); |
| } |
| --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h |
| +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h |
| @@ -854,6 +854,10 @@ enum { |
| HDMI_FC_DBGFORCE_FORCEAUDIO = 0x10, |
| HDMI_FC_DBGFORCE_FORCEVIDEO = 0x1, |
| |
| +/* FC_DATAUTO0 field values */ |
| + HDMI_FC_DATAUTO0_VSD_MASK = 0x08, |
| + HDMI_FC_DATAUTO0_VSD_OFFSET = 3, |
| + |
| /* PHY_CONF0 field values */ |
| HDMI_PHY_CONF0_PDZ_MASK = 0x80, |
| HDMI_PHY_CONF0_PDZ_OFFSET = 7, |