Skip to contentSkip to conversation

drm/msm/hdmi: Some HDMI fixes for 8x96

PATCH New Archit Taneja 1 participant 4 messages Jun 16, 2017

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

cover drm/msm/hdmi: Some HDMI fixes for 8x96

Some fixes that makes HDMI more stable on 8x96:

- Make PLL switch to different freqs successfully (when switching between modes).
- Add AVI infoframes to reemove the pink strips seen on some monitors.
- Update some of the HDMI timing bitfields so that they can take in values > 4K.

The display bindings for 8x96 aren't in yet, so it's okay to have these for 4.13.

Archit Taneja (3):
drm/msm/hdmi: 8996 PLL: Populate unprepare drm/msm/hdmi: Updated generated headers drm/msm/hdmi: Fix HDMI pink strip issue seen on 8x96

 drivers/gpu/drm/msm/hdmi/hdmi.xml.h      | 59 +++++++++++++++++----------
 drivers/gpu/drm/msm/hdmi/hdmi_bridge.c   | 70 ++++++++++++++++++++++++++++++--
 drivers/gpu/drm/msm/hdmi/hdmi_phy_8996.c |  5 +++
 3 files changed, 110 insertions(+), 24 deletions(-)
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
#1 lore raw

PATCH 1/3 drm/msm/hdmi: 8996 PLL: Populate unprepare

Without doing anything in unprepare, the HDMI driver isn't able to switch modes successfully. Calling set_rate with a new rate results in an un-locked PLL.

If we reset the PLL in unprepare, the PLL is able to lock with the new rate.

---
 drivers/gpu/drm/msm/hdmi/hdmi_phy_8996.c | 5 +++++
 1 file changed, 5 insertions(+)
drivers/gpu/drm/msm/hdmi/hdmi_phy_8996.c +5 -0
index 143eab46ba68..1fb7645cc721 100644
@@ -670,6 +670,11 @@ static unsigned long hdmi_8996_pll_recalc_rate(struct clk_hw *hw,
 
 static void hdmi_8996_pll_unprepare(struct clk_hw *hw)
 {
+	struct hdmi_pll_8996 *pll = hw_clk_to_pll(hw);
+	struct hdmi_phy *phy = pll_get_phy(pll);
+
+	hdmi_phy_write(phy, REG_HDMI_8996_PHY_CFG, 0x6);
+	usleep_range(100, 150);
 }
 
 static int hdmi_8996_pll_is_enabled(struct clk_hw *hw)
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
#2 lore raw

PATCH 2/3 drm/msm/hdmi: Updated generated headers

In reply to Archit Taneja

- Add HDMI_INFOFRAME_CONTROL1 register and its bitfields.

- Fix up the HDMI timing registers bitfield widths to 13 bits so that values greater than 4095 can be written to them. The older chips (APQ8064 etc) only have 12 bit width for these fields, but KMS won't let them try to write widths > 4095 anyway.

---
 drivers/gpu/drm/msm/hdmi/hdmi.xml.h | 59 ++++++++++++++++++++++++-------------
 1 file changed, 38 insertions(+), 21 deletions(-)
drivers/gpu/drm/msm/hdmi/hdmi.xml.h +38 -21
index 0a97ff75ed6f..e4b9753b9d57 100644
@@ -8,19 +8,10 @@ This file was generated by the rules-ng-ng headergen tool in this git repository
 git clone https://github.com/freedreno/envytools.git
 
 The rules-ng-ng source files this header was generated from are:
-- /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    676 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1572 bytes, from 2016-02-10 17:07:21)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20915 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2849 bytes, from 2015-09-18 12:07:28)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  36965 bytes, from 2016-11-26 23:01:08)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  27887 bytes, from 2015-10-22 16:34:52)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    602 bytes, from 2015-10-22 16:35:02)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1686 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2015-05-20 20:03:07)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  41472 bytes, from 2016-01-22 18:18:18)
-- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml             (  10416 bytes, from 2015-05-20 20:03:14)
-
-Copyright (C) 2013-2016 by the following authors:
+- /local/mnt/workspace/source_trees/envytools/rnndb/../rnndb/hdmi/hdmi.xml  (  41799 bytes, from 2017-06-16 04:34:09)
+- /local/mnt/workspace/source_trees/envytools/rnndb/freedreno_copyright.xml (   1572 bytes, from 2016-05-09 06:32:54)
+
+Copyright (C) 2013-2017 by the following authors:
 - Rob Clark <[email protected]> (robclark)
 - Ilia Mirkin <[email protected]> (imirkin)
 
@@ -111,6 +102,32 @@ static inline uint32_t HDMI_ACR_PKT_CTRL_N_MULTIPLIER(uint32_t val)
 #define HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SOURCE			0x00000040
 #define HDMI_INFOFRAME_CTRL0_AUDIO_INFO_UPDATE			0x00000080
 
+#define REG_HDMI_INFOFRAME_CTRL1				0x00000030
+#define HDMI_INFOFRAME_CTRL1_AVI_INFO_LINE__MASK		0x0000003f
+#define HDMI_INFOFRAME_CTRL1_AVI_INFO_LINE__SHIFT		0
+static inline uint32_t HDMI_INFOFRAME_CTRL1_AVI_INFO_LINE(uint32_t val)
+{
+	return ((val) << HDMI_INFOFRAME_CTRL1_AVI_INFO_LINE__SHIFT) & HDMI_INFOFRAME_CTRL1_AVI_INFO_LINE__MASK;
+}
+#define HDMI_INFOFRAME_CTRL1_AUDIO_INFO_LINE__MASK		0x00003f00
+#define HDMI_INFOFRAME_CTRL1_AUDIO_INFO_LINE__SHIFT		8
+static inline uint32_t HDMI_INFOFRAME_CTRL1_AUDIO_INFO_LINE(uint32_t val)
+{
+	return ((val) << HDMI_INFOFRAME_CTRL1_AUDIO_INFO_LINE__SHIFT) & HDMI_INFOFRAME_CTRL1_AUDIO_INFO_LINE__MASK;
+}
+#define HDMI_INFOFRAME_CTRL1_MPEG_INFO_LINE__MASK		0x003f0000
+#define HDMI_INFOFRAME_CTRL1_MPEG_INFO_LINE__SHIFT		16
+static inline uint32_t HDMI_INFOFRAME_CTRL1_MPEG_INFO_LINE(uint32_t val)
+{
+	return ((val) << HDMI_INFOFRAME_CTRL1_MPEG_INFO_LINE__SHIFT) & HDMI_INFOFRAME_CTRL1_MPEG_INFO_LINE__MASK;
+}
+#define HDMI_INFOFRAME_CTRL1_VENSPEC_INFO_LINE__MASK		0x3f000000
+#define HDMI_INFOFRAME_CTRL1_VENSPEC_INFO_LINE__SHIFT		24
+static inline uint32_t HDMI_INFOFRAME_CTRL1_VENSPEC_INFO_LINE(uint32_t val)
+{
+	return ((val) << HDMI_INFOFRAME_CTRL1_VENSPEC_INFO_LINE__SHIFT) & HDMI_INFOFRAME_CTRL1_VENSPEC_INFO_LINE__MASK;
+}
+
 #define REG_HDMI_GEN_PKT_CTRL					0x00000034
 #define HDMI_GEN_PKT_CTRL_GENERIC0_SEND				0x00000001
 #define HDMI_GEN_PKT_CTRL_GENERIC0_CONT				0x00000002
@@ -463,7 +480,7 @@ static inline uint32_t HDMI_DDC_REF_REFTIMER(uint32_t val)
 #define REG_HDMI_CEC_RD_FILTER					0x000002b0
 
 #define REG_HDMI_ACTIVE_HSYNC					0x000002b4
-#define HDMI_ACTIVE_HSYNC_START__MASK				0x00000fff
+#define HDMI_ACTIVE_HSYNC_START__MASK				0x00001fff
 #define HDMI_ACTIVE_HSYNC_START__SHIFT				0
 static inline uint32_t HDMI_ACTIVE_HSYNC_START(uint32_t val)
 {
@@ -477,13 +494,13 @@ static inline uint32_t HDMI_ACTIVE_HSYNC_END(uint32_t val)
 }
 
 #define REG_HDMI_ACTIVE_VSYNC					0x000002b8
-#define HDMI_ACTIVE_VSYNC_START__MASK				0x00000fff
+#define HDMI_ACTIVE_VSYNC_START__MASK				0x00001fff
 #define HDMI_ACTIVE_VSYNC_START__SHIFT				0
 static inline uint32_t HDMI_ACTIVE_VSYNC_START(uint32_t val)
 {
 	return ((val) << HDMI_ACTIVE_VSYNC_START__SHIFT) & HDMI_ACTIVE_VSYNC_START__MASK;
 }
-#define HDMI_ACTIVE_VSYNC_END__MASK				0x0fff0000
+#define HDMI_ACTIVE_VSYNC_END__MASK				0x1fff0000
 #define HDMI_ACTIVE_VSYNC_END__SHIFT				16
 static inline uint32_t HDMI_ACTIVE_VSYNC_END(uint32_t val)
 {
@@ -491,13 +508,13 @@ static inline uint32_t HDMI_ACTIVE_VSYNC_END(uint32_t val)
 }
 
 #define REG_HDMI_VSYNC_ACTIVE_F2				0x000002bc
-#define HDMI_VSYNC_ACTIVE_F2_START__MASK			0x00000fff
+#define HDMI_VSYNC_ACTIVE_F2_START__MASK			0x00001fff
 #define HDMI_VSYNC_ACTIVE_F2_START__SHIFT			0
 static inline uint32_t HDMI_VSYNC_ACTIVE_F2_START(uint32_t val)
 {
 	return ((val) << HDMI_VSYNC_ACTIVE_F2_START__SHIFT) & HDMI_VSYNC_ACTIVE_F2_START__MASK;
 }
-#define HDMI_VSYNC_ACTIVE_F2_END__MASK				0x0fff0000
+#define HDMI_VSYNC_ACTIVE_F2_END__MASK				0x1fff0000
 #define HDMI_VSYNC_ACTIVE_F2_END__SHIFT				16
 static inline uint32_t HDMI_VSYNC_ACTIVE_F2_END(uint32_t val)
 {
@@ -505,13 +522,13 @@ static inline uint32_t HDMI_VSYNC_ACTIVE_F2_END(uint32_t val)
 }
 
 #define REG_HDMI_TOTAL						0x000002c0
-#define HDMI_TOTAL_H_TOTAL__MASK				0x00000fff
+#define HDMI_TOTAL_H_TOTAL__MASK				0x00001fff
 #define HDMI_TOTAL_H_TOTAL__SHIFT				0
 static inline uint32_t HDMI_TOTAL_H_TOTAL(uint32_t val)
 {
 	return ((val) << HDMI_TOTAL_H_TOTAL__SHIFT) & HDMI_TOTAL_H_TOTAL__MASK;
 }
-#define HDMI_TOTAL_V_TOTAL__MASK				0x0fff0000
+#define HDMI_TOTAL_V_TOTAL__MASK				0x1fff0000
 #define HDMI_TOTAL_V_TOTAL__SHIFT				16
 static inline uint32_t HDMI_TOTAL_V_TOTAL(uint32_t val)
 {
@@ -519,7 +536,7 @@ static inline uint32_t HDMI_TOTAL_V_TOTAL(uint32_t val)
 }
 
 #define REG_HDMI_VSYNC_TOTAL_F2					0x000002c4
-#define HDMI_VSYNC_TOTAL_F2_V_TOTAL__MASK			0x00000fff
+#define HDMI_VSYNC_TOTAL_F2_V_TOTAL__MASK			0x00001fff
 #define HDMI_VSYNC_TOTAL_F2_V_TOTAL__SHIFT			0
 static inline uint32_t HDMI_VSYNC_TOTAL_F2_V_TOTAL(uint32_t val)
 {
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
#3 lore raw

PATCH 3/3 drm/msm/hdmi: Fix HDMI pink strip issue seen on 8x96

In reply to Archit Taneja

A 2 pixel wide pink strip was observed on the left end of some HDMI monitors configured in a HDMI mode.

It turned out that we were missing out on configuring AVI infoframes, and unlike APQ8064, the 8x96 HDMI H/W seems to be sensitive to that.

Add configuration of AVI infoframes. While at it, make sure that hdmi_audio_update is only called when we've detected that the monitor supports HDMI.

---
 drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 70 ++++++++++++++++++++++++++++++++--
 1 file changed, 67 insertions(+), 3 deletions(-)
drivers/gpu/drm/msm/hdmi/hdmi_bridge.c +67 -3
index 4e6d1bf27474..ae40e7179d4f 100644
@@ -86,6 +86,65 @@ static void power_off(struct drm_bridge *bridge)
 	}
 }
 
+#define AVI_IFRAME_LINE_NUMBER 1
+
+static void msm_hdmi_config_avi_infoframe(struct hdmi *hdmi)
+{
+	struct drm_crtc *crtc = hdmi->encoder->crtc;
+	const struct drm_display_mode *mode = &crtc->state->adjusted_mode;
+	union hdmi_infoframe frame;
+	u8 buffer[HDMI_INFOFRAME_SIZE(AVI)];
+	u32 val;
+	int len;
+
+	drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode);
+
+	len = hdmi_infoframe_pack(&frame, buffer, sizeof(buffer));
+	if (len < 0) {
+		dev_err(&hdmi->pdev->dev,
+			"failed to configure avi infoframe\n");
+		return;
+	}
+
+	/*
+	 * the AVI_INFOx registers don't map exactly to how the AVI infoframes
+	 * are packed according to the spec. The checksum from the header is
+	 * written to the LSB byte of AVI_INFO0 and the version is written to
+	 * the third byte from the LSB of AVI_INFO3
+	 */
+	hdmi_write(hdmi, REG_HDMI_AVI_INFO(0),
+		   buffer[3] |
+		   buffer[4] << 8 |
+		   buffer[5] << 16 |
+		   buffer[6] << 24);
+
+	hdmi_write(hdmi, REG_HDMI_AVI_INFO(1),
+		   buffer[7] |
+		   buffer[8] << 8 |
+		   buffer[9] << 16 |
+		   buffer[10] << 24);
+
+	hdmi_write(hdmi, REG_HDMI_AVI_INFO(2),
+		   buffer[11] |
+		   buffer[12] << 8 |
+		   buffer[13] << 16 |
+		   buffer[14] << 24);
+
+	hdmi_write(hdmi, REG_HDMI_AVI_INFO(3),
+		   buffer[15] |
+		   buffer[16] << 8 |
+		   buffer[1] << 24);
+
+	hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL0,
+		   HDMI_INFOFRAME_CTRL0_AVI_SEND |
+		   HDMI_INFOFRAME_CTRL0_AVI_CONT);
+
+	val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL1);
+	val &= ~HDMI_INFOFRAME_CTRL1_AVI_INFO_LINE__MASK;
+	val |= HDMI_INFOFRAME_CTRL1_AVI_INFO_LINE(AVI_IFRAME_LINE_NUMBER);
+	hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL1, val);
+}
+
 static void msm_hdmi_bridge_pre_enable(struct drm_bridge *bridge)
 {
 	struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
@@ -98,7 +157,10 @@ static void msm_hdmi_bridge_pre_enable(struct drm_bridge *bridge)
 		msm_hdmi_phy_resource_enable(phy);
 		msm_hdmi_power_on(bridge);
 		hdmi->power_on = true;
-		msm_hdmi_audio_update(hdmi);
+		if (hdmi->hdmi_mode) {
+			msm_hdmi_config_avi_infoframe(hdmi);
+			msm_hdmi_audio_update(hdmi);
+		}
 	}
 
 	msm_hdmi_phy_powerup(phy, hdmi->pixclock);
@@ -134,7 +196,8 @@ static void msm_hdmi_bridge_post_disable(struct drm_bridge *bridge)
 	if (hdmi->power_on) {
 		power_off(bridge);
 		hdmi->power_on = false;
-		msm_hdmi_audio_update(hdmi);
+		if (hdmi->hdmi_mode)
+			msm_hdmi_audio_update(hdmi);
 		msm_hdmi_phy_resource_disable(phy);
 	}
 }
@@ -196,7 +259,8 @@ static void msm_hdmi_bridge_mode_set(struct drm_bridge *bridge,
 	DBG("frame_ctrl=%08x", frame_ctrl);
 	hdmi_write(hdmi, REG_HDMI_FRAME_CTRL, frame_ctrl);
 
-	msm_hdmi_audio_update(hdmi);
+	if (hdmi->hdmi_mode)
+		msm_hdmi_audio_update(hdmi);
 }
 
 static const struct drm_bridge_funcs msm_hdmi_bridge_funcs = {
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation