]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - pending-4.14/drm-i915-sdvo-implement-proper-hdmi-audio-support-for-sdvo.patch
move existing queues out of the way for the moment...
[thirdparty/kernel/stable-queue.git] / pending-4.14 / drm-i915-sdvo-implement-proper-hdmi-audio-support-for-sdvo.patch
CommitLineData
80ae7e1e
GKH
1From d74408f528261f900dddb9778f61b5c5a7a6249c Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com>
3Date: Tue, 9 Apr 2019 17:40:49 +0300
4Subject: drm/i915/sdvo: Implement proper HDMI audio support for SDVO
5MIME-Version: 1.0
6Content-Type: text/plain; charset=UTF-8
7Content-Transfer-Encoding: 8bit
8
9From: Ville Syrjälä <ville.syrjala@linux.intel.com>
10
11commit d74408f528261f900dddb9778f61b5c5a7a6249c upstream.
12
13Our SDVO audio support is pretty bogus. We can't push audio over the
14SDVO bus, so trying to enable audio in the SDVO control register doesn't
15do anything. In fact it looks like the SDVO encoder will always mix in
16the audio coming over HDA, and there's no (at least documented) way to
17disable that from our side. So HDMI audio does work currently on gen4
18but only by luck really. On gen3 it got broken by the referenced commit.
19And what has always been missing on every platform is the ELD.
20
21To pass the ELD to the audio driver we need to write it to magic buffer
22in the SDVO encoder hardware which then gets pulled out via HDA in the
23other end. Ie. pretty much the same thing we had for native HDMI before
24we started to just pass the ELD between the drivers. This sort of
25explains why we even have that silly hardware buffer with native HDMI.
26
27$ cat /proc/asound/card0/eld#1.0
28-monitor_present 0
29-eld_valid 0
30+monitor_present 1
31+eld_valid 1
32+monitor_name LG TV
33+connection_type HDMI
34+...
35
36This also fixes our state readout since we can now query the SDVO
37encoder about the state of the "ELD valid" and "presence detect"
38bits. As mentioned those don't actually control whether audio
39gets sent over the HDMI cable, but it's the best we can do. And with
40the state checker appeased we can re-enable HDMI audio for gen3.
41
42Cc: stable@vger.kernel.org
43Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
44Cc: zardam@gmail.com
45Tested-by: zardam@gmail.com
46Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=108976
47Fixes: de44e256b92c ("drm/i915/sdvo: Shut up state checker with hdmi cards on gen3")
48Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
49Link: https://patchwork.freedesktop.org/patch/msgid/20190409144054.24561-3-ville.syrjala@linux.intel.com
50Reviewed-by: Imre Deak <imre.deak@intel.com>
51(cherry picked from commit dc49a56bd43bb04982e64b44436831da801d0237)
52Signed-off-by: Jani Nikula <jani.nikula@intel.com>
53Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
54
55---
56 drivers/gpu/drm/i915/intel_sdvo.c | 58 ++++++++++++++++++++++++++-------
57 drivers/gpu/drm/i915/intel_sdvo_regs.h | 3 +
58 2 files changed, 50 insertions(+), 11 deletions(-)
59
60--- a/drivers/gpu/drm/i915/intel_sdvo.c
61+++ b/drivers/gpu/drm/i915/intel_sdvo.c
62@@ -928,6 +928,13 @@ static bool intel_sdvo_set_colorimetry(s
63 return intel_sdvo_set_value(intel_sdvo, SDVO_CMD_SET_COLORIMETRY, &mode, 1);
64 }
65
66+static bool intel_sdvo_set_audio_state(struct intel_sdvo *intel_sdvo,
67+ u8 audio_state)
68+{
69+ return intel_sdvo_set_value(intel_sdvo, SDVO_CMD_SET_AUDIO_STAT,
70+ &audio_state, 1);
71+}
72+
73 #if 0
74 static void intel_sdvo_dump_hdmi_buf(struct intel_sdvo *intel_sdvo)
75 {
76@@ -1359,11 +1366,6 @@ static void intel_sdvo_pre_enable(struct
77 else
78 sdvox |= SDVO_PIPE_SEL(crtc->pipe);
79
80- if (crtc_state->has_audio) {
81- WARN_ON_ONCE(INTEL_GEN(dev_priv) < 4);
82- sdvox |= SDVO_AUDIO_ENABLE;
83- }
84-
85 if (INTEL_GEN(dev_priv) >= 4) {
86 /* done in crtc_mode_set as the dpll_md reg must be written early */
87 } else if (IS_I945G(dev_priv) || IS_I945GM(dev_priv) ||
88@@ -1492,8 +1494,13 @@ static void intel_sdvo_get_config(struct
89 if (sdvox & HDMI_COLOR_RANGE_16_235)
90 pipe_config->limited_color_range = true;
91
92- if (sdvox & SDVO_AUDIO_ENABLE)
93- pipe_config->has_audio = true;
94+ if (intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_AUDIO_STAT,
95+ &val, 1)) {
96+ u8 mask = SDVO_AUDIO_ELD_VALID | SDVO_AUDIO_PRESENCE_DETECT;
97+
98+ if ((val & mask) == mask)
99+ pipe_config->has_audio = true;
100+ }
101
102 if (intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_ENCODE,
103 &val, 1)) {
104@@ -1506,6 +1513,32 @@ static void intel_sdvo_get_config(struct
105 pipe_config->pixel_multiplier, encoder_pixel_multiplier);
106 }
107
108+static void intel_sdvo_disable_audio(struct intel_sdvo *intel_sdvo)
109+{
110+ intel_sdvo_set_audio_state(intel_sdvo, 0);
111+}
112+
113+static void intel_sdvo_enable_audio(struct intel_sdvo *intel_sdvo,
114+ const struct intel_crtc_state *crtc_state,
115+ const struct drm_connector_state *conn_state)
116+{
117+ const struct drm_display_mode *adjusted_mode =
118+ &crtc_state->base.adjusted_mode;
119+ struct drm_connector *connector = conn_state->connector;
120+ u8 *eld = connector->eld;
121+
122+ eld[6] = drm_av_sync_delay(connector, adjusted_mode) / 2;
123+
124+ intel_sdvo_set_audio_state(intel_sdvo, 0);
125+
126+ intel_sdvo_write_infoframe(intel_sdvo, SDVO_HBUF_INDEX_ELD,
127+ SDVO_HBUF_TX_DISABLED,
128+ eld, drm_eld_size(eld));
129+
130+ intel_sdvo_set_audio_state(intel_sdvo, SDVO_AUDIO_ELD_VALID |
131+ SDVO_AUDIO_PRESENCE_DETECT);
132+}
133+
134 static void intel_disable_sdvo(struct intel_encoder *encoder,
135 struct intel_crtc_state *old_crtc_state,
136 struct drm_connector_state *conn_state)
137@@ -1515,6 +1548,9 @@ static void intel_disable_sdvo(struct in
138 struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
139 u32 temp;
140
141+ if (old_crtc_state->has_audio)
142+ intel_sdvo_disable_audio(intel_sdvo);
143+
144 intel_sdvo_set_active_outputs(intel_sdvo, 0);
145 if (0)
146 intel_sdvo_set_encoder_power_state(intel_sdvo,
147@@ -1598,6 +1634,9 @@ static void intel_enable_sdvo(struct int
148 intel_sdvo_set_encoder_power_state(intel_sdvo,
149 DRM_MODE_DPMS_ON);
150 intel_sdvo_set_active_outputs(intel_sdvo, intel_sdvo->attached_output);
151+
152+ if (pipe_config->has_audio)
153+ intel_sdvo_enable_audio(intel_sdvo, pipe_config, conn_state);
154 }
155
156 static enum drm_mode_status
157@@ -2468,7 +2507,6 @@ static bool
158 intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
159 {
160 struct drm_encoder *encoder = &intel_sdvo->base.base;
161- struct drm_i915_private *dev_priv = to_i915(encoder->dev);
162 struct drm_connector *connector;
163 struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
164 struct intel_connector *intel_connector;
165@@ -2504,9 +2542,7 @@ intel_sdvo_dvi_init(struct intel_sdvo *i
166 encoder->encoder_type = DRM_MODE_ENCODER_TMDS;
167 connector->connector_type = DRM_MODE_CONNECTOR_DVID;
168
169- /* gen3 doesn't do the hdmi bits in the SDVO register */
170- if (INTEL_GEN(dev_priv) >= 4 &&
171- intel_sdvo_is_hdmi_connector(intel_sdvo, device)) {
172+ if (intel_sdvo_is_hdmi_connector(intel_sdvo, device)) {
173 connector->connector_type = DRM_MODE_CONNECTOR_HDMIA;
174 intel_sdvo->is_hdmi = true;
175 }
176--- a/drivers/gpu/drm/i915/intel_sdvo_regs.h
177+++ b/drivers/gpu/drm/i915/intel_sdvo_regs.h
178@@ -707,6 +707,9 @@ struct intel_sdvo_enhancements_arg {
179 #define SDVO_CMD_GET_AUDIO_ENCRYPT_PREFER 0x90
180 #define SDVO_CMD_SET_AUDIO_STAT 0x91
181 #define SDVO_CMD_GET_AUDIO_STAT 0x92
182+ #define SDVO_AUDIO_ELD_VALID (1 << 0)
183+ #define SDVO_AUDIO_PRESENCE_DETECT (1 << 1)
184+ #define SDVO_AUDIO_CP_READY (1 << 2)
185 #define SDVO_CMD_SET_HBUF_INDEX 0x93
186 #define SDVO_HBUF_INDEX_ELD 0
187 #define SDVO_HBUF_INDEX_AVI_IF 1