xref: /linux/drivers/gpu/drm/msm/dp/dp_audio.c (revision e814f3fd16acfb7f9966773953de8f740a1e3202)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
4  */
5 
6 
7 #define pr_fmt(fmt)	"[drm-dp] %s: " fmt, __func__
8 
9 #include <linux/platform_device.h>
10 
11 #include <drm/display/drm_dp_helper.h>
12 #include <drm/drm_edid.h>
13 
14 #include "dp_catalog.h"
15 #include "dp_audio.h"
16 #include "dp_panel.h"
17 #include "dp_reg.h"
18 #include "dp_display.h"
19 #include "dp_utils.h"
20 
21 struct msm_dp_audio_private {
22 	struct platform_device *audio_pdev;
23 	struct platform_device *pdev;
24 	struct drm_device *drm_dev;
25 	struct msm_dp_catalog *catalog;
26 
27 	u32 channels;
28 
29 	struct msm_dp_audio msm_dp_audio;
30 };
31 
32 static void msm_dp_audio_stream_sdp(struct msm_dp_audio_private *audio)
33 {
34 	struct dp_sdp_header sdp_hdr = {
35 		.HB0 = 0x00,
36 		.HB1 = 0x02,
37 		.HB2 = 0x00,
38 		.HB3 = audio->channels - 1,
39 	};
40 
41 	msm_dp_catalog_write_audio_stream(audio->catalog, &sdp_hdr);
42 }
43 
44 static void msm_dp_audio_timestamp_sdp(struct msm_dp_audio_private *audio)
45 {
46 	struct dp_sdp_header sdp_hdr = {
47 		.HB0 = 0x00,
48 		.HB1 = 0x01,
49 		.HB2 = 0x17,
50 		.HB3 = 0x0 | (0x11 << 2),
51 	};
52 
53 	msm_dp_catalog_write_audio_timestamp(audio->catalog, &sdp_hdr);
54 }
55 
56 static void msm_dp_audio_infoframe_sdp(struct msm_dp_audio_private *audio)
57 {
58 	struct dp_sdp_header sdp_hdr = {
59 		.HB0 = 0x00,
60 		.HB1 = 0x84,
61 		.HB2 = 0x1b,
62 		.HB3 = 0x0 | (0x11 << 2),
63 	};
64 
65 	msm_dp_catalog_write_audio_infoframe(audio->catalog, &sdp_hdr);
66 }
67 
68 static void msm_dp_audio_copy_management_sdp(struct msm_dp_audio_private *audio)
69 {
70 	struct dp_sdp_header sdp_hdr = {
71 		.HB0 = 0x00,
72 		.HB1 = 0x05,
73 		.HB2 = 0x0f,
74 		.HB3 = 0x00,
75 	};
76 
77 	msm_dp_catalog_write_audio_copy_mgmt(audio->catalog, &sdp_hdr);
78 }
79 
80 static void msm_dp_audio_isrc_sdp(struct msm_dp_audio_private *audio)
81 {
82 	struct dp_sdp_header sdp_hdr = {
83 		.HB0 = 0x00,
84 		.HB1 = 0x06,
85 		.HB2 = 0x0f,
86 		.HB3 = 0x00,
87 	};
88 
89 	msm_dp_catalog_write_audio_isrc(audio->catalog, &sdp_hdr);
90 }
91 
92 static void msm_dp_audio_setup_sdp(struct msm_dp_audio_private *audio)
93 {
94 	msm_dp_catalog_audio_config_sdp(audio->catalog);
95 
96 	msm_dp_audio_stream_sdp(audio);
97 	msm_dp_audio_timestamp_sdp(audio);
98 	msm_dp_audio_infoframe_sdp(audio);
99 	msm_dp_audio_copy_management_sdp(audio);
100 	msm_dp_audio_isrc_sdp(audio);
101 }
102 
103 static void msm_dp_audio_setup_acr(struct msm_dp_audio_private *audio)
104 {
105 	u32 select = 0;
106 	struct msm_dp_catalog *catalog = audio->catalog;
107 
108 	switch (audio->msm_dp_audio.bw_code) {
109 	case DP_LINK_BW_1_62:
110 		select = 0;
111 		break;
112 	case DP_LINK_BW_2_7:
113 		select = 1;
114 		break;
115 	case DP_LINK_BW_5_4:
116 		select = 2;
117 		break;
118 	case DP_LINK_BW_8_1:
119 		select = 3;
120 		break;
121 	default:
122 		drm_dbg_dp(audio->drm_dev, "Unknown link rate\n");
123 		select = 0;
124 		break;
125 	}
126 
127 	msm_dp_catalog_audio_config_acr(catalog, select);
128 }
129 
130 static void msm_dp_audio_safe_to_exit_level(struct msm_dp_audio_private *audio)
131 {
132 	struct msm_dp_catalog *catalog = audio->catalog;
133 	u32 safe_to_exit_level = 0;
134 
135 	switch (audio->msm_dp_audio.lane_count) {
136 	case 1:
137 		safe_to_exit_level = 14;
138 		break;
139 	case 2:
140 		safe_to_exit_level = 8;
141 		break;
142 	case 4:
143 		safe_to_exit_level = 5;
144 		break;
145 	default:
146 		safe_to_exit_level = 14;
147 		drm_dbg_dp(audio->drm_dev,
148 				"setting the default safe_to_exit_level = %u\n",
149 				safe_to_exit_level);
150 		break;
151 	}
152 
153 	msm_dp_catalog_audio_sfe_level(catalog, safe_to_exit_level);
154 }
155 
156 static void msm_dp_audio_enable(struct msm_dp_audio_private *audio, bool enable)
157 {
158 	struct msm_dp_catalog *catalog = audio->catalog;
159 
160 	msm_dp_catalog_audio_enable(catalog, enable);
161 }
162 
163 static struct msm_dp_audio_private *msm_dp_audio_get_data(struct platform_device *pdev)
164 {
165 	struct msm_dp_audio *msm_dp_audio;
166 	struct msm_dp *msm_dp_display;
167 
168 	if (!pdev) {
169 		DRM_ERROR("invalid input\n");
170 		return ERR_PTR(-ENODEV);
171 	}
172 
173 	msm_dp_display = platform_get_drvdata(pdev);
174 	if (!msm_dp_display) {
175 		DRM_ERROR("invalid input\n");
176 		return ERR_PTR(-ENODEV);
177 	}
178 
179 	msm_dp_audio = msm_dp_display->msm_dp_audio;
180 
181 	if (!msm_dp_audio) {
182 		DRM_ERROR("invalid msm_dp_audio data\n");
183 		return ERR_PTR(-EINVAL);
184 	}
185 
186 	return container_of(msm_dp_audio, struct msm_dp_audio_private, msm_dp_audio);
187 }
188 
189 static int msm_dp_audio_hook_plugged_cb(struct device *dev, void *data,
190 		hdmi_codec_plugged_cb fn,
191 		struct device *codec_dev)
192 {
193 
194 	struct platform_device *pdev;
195 	struct msm_dp *msm_dp_display;
196 
197 	pdev = to_platform_device(dev);
198 	if (!pdev) {
199 		pr_err("invalid input\n");
200 		return -ENODEV;
201 	}
202 
203 	msm_dp_display = platform_get_drvdata(pdev);
204 	if (!msm_dp_display) {
205 		pr_err("invalid input\n");
206 		return -ENODEV;
207 	}
208 
209 	return msm_dp_display_set_plugged_cb(msm_dp_display, fn, codec_dev);
210 }
211 
212 static int msm_dp_audio_get_eld(struct device *dev,
213 	void *data, uint8_t *buf, size_t len)
214 {
215 	struct platform_device *pdev;
216 	struct msm_dp *msm_dp_display;
217 
218 	pdev = to_platform_device(dev);
219 
220 	if (!pdev) {
221 		DRM_ERROR("invalid input\n");
222 		return -ENODEV;
223 	}
224 
225 	msm_dp_display = platform_get_drvdata(pdev);
226 	if (!msm_dp_display) {
227 		DRM_ERROR("invalid input\n");
228 		return -ENODEV;
229 	}
230 
231 	mutex_lock(&msm_dp_display->connector->eld_mutex);
232 	memcpy(buf, msm_dp_display->connector->eld,
233 		min(sizeof(msm_dp_display->connector->eld), len));
234 	mutex_unlock(&msm_dp_display->connector->eld_mutex);
235 
236 	return 0;
237 }
238 
239 int msm_dp_audio_hw_params(struct device *dev,
240 	void *data,
241 	struct hdmi_codec_daifmt *daifmt,
242 	struct hdmi_codec_params *params)
243 {
244 	int rc = 0;
245 	struct msm_dp_audio_private *audio;
246 	struct platform_device *pdev;
247 	struct msm_dp *msm_dp_display;
248 
249 	pdev = to_platform_device(dev);
250 	msm_dp_display = platform_get_drvdata(pdev);
251 
252 	/*
253 	 * there could be cases where sound card can be opened even
254 	 * before OR even when DP is not connected . This can cause
255 	 * unclocked access as the audio subsystem relies on the DP
256 	 * driver to maintain the correct state of clocks. To protect
257 	 * such cases check for connection status and bail out if not
258 	 * connected.
259 	 */
260 	if (!msm_dp_display->power_on) {
261 		rc = -EINVAL;
262 		goto end;
263 	}
264 
265 	audio = msm_dp_audio_get_data(pdev);
266 	if (IS_ERR(audio)) {
267 		rc = PTR_ERR(audio);
268 		goto end;
269 	}
270 
271 	audio->channels = params->channels;
272 
273 	msm_dp_audio_setup_sdp(audio);
274 	msm_dp_audio_setup_acr(audio);
275 	msm_dp_audio_safe_to_exit_level(audio);
276 	msm_dp_audio_enable(audio, true);
277 	msm_dp_display_signal_audio_start(msm_dp_display);
278 	msm_dp_display->audio_enabled = true;
279 
280 end:
281 	return rc;
282 }
283 
284 static void msm_dp_audio_shutdown(struct device *dev, void *data)
285 {
286 	struct msm_dp_audio_private *audio;
287 	struct platform_device *pdev;
288 	struct msm_dp *msm_dp_display;
289 
290 	pdev = to_platform_device(dev);
291 	msm_dp_display = platform_get_drvdata(pdev);
292 	audio = msm_dp_audio_get_data(pdev);
293 	if (IS_ERR(audio)) {
294 		DRM_ERROR("failed to get audio data\n");
295 		return;
296 	}
297 
298 	/*
299 	 * if audio was not enabled there is no need
300 	 * to execute the shutdown and we can bail out early.
301 	 * This also makes sure that we dont cause an unclocked
302 	 * access when audio subsystem calls this without DP being
303 	 * connected. is_connected cannot be used here as its set
304 	 * to false earlier than this call
305 	 */
306 	if (!msm_dp_display->audio_enabled)
307 		return;
308 
309 	msm_dp_audio_enable(audio, false);
310 	/* signal the dp display to safely shutdown clocks */
311 	msm_dp_display_signal_audio_complete(msm_dp_display);
312 }
313 
314 static const struct hdmi_codec_ops msm_dp_audio_codec_ops = {
315 	.hw_params = msm_dp_audio_hw_params,
316 	.audio_shutdown = msm_dp_audio_shutdown,
317 	.get_eld = msm_dp_audio_get_eld,
318 	.hook_plugged_cb = msm_dp_audio_hook_plugged_cb,
319 };
320 
321 static struct hdmi_codec_pdata codec_data = {
322 	.ops = &msm_dp_audio_codec_ops,
323 	.max_i2s_channels = 8,
324 	.i2s = 1,
325 };
326 
327 void msm_dp_unregister_audio_driver(struct device *dev, struct msm_dp_audio *msm_dp_audio)
328 {
329 	struct msm_dp_audio_private *audio_priv;
330 
331 	audio_priv = container_of(msm_dp_audio, struct msm_dp_audio_private, msm_dp_audio);
332 
333 	if (audio_priv->audio_pdev) {
334 		platform_device_unregister(audio_priv->audio_pdev);
335 		audio_priv->audio_pdev = NULL;
336 	}
337 }
338 
339 int msm_dp_register_audio_driver(struct device *dev,
340 		struct msm_dp_audio *msm_dp_audio)
341 {
342 	struct msm_dp_audio_private *audio_priv;
343 
344 	audio_priv = container_of(msm_dp_audio,
345 			struct msm_dp_audio_private, msm_dp_audio);
346 
347 	audio_priv->audio_pdev = platform_device_register_data(dev,
348 						HDMI_CODEC_DRV_NAME,
349 						PLATFORM_DEVID_AUTO,
350 						&codec_data,
351 						sizeof(codec_data));
352 	return PTR_ERR_OR_ZERO(audio_priv->audio_pdev);
353 }
354 
355 struct msm_dp_audio *msm_dp_audio_get(struct platform_device *pdev,
356 			struct msm_dp_catalog *catalog)
357 {
358 	int rc = 0;
359 	struct msm_dp_audio_private *audio;
360 	struct msm_dp_audio *msm_dp_audio;
361 
362 	if (!pdev || !catalog) {
363 		DRM_ERROR("invalid input\n");
364 		rc = -EINVAL;
365 		goto error;
366 	}
367 
368 	audio = devm_kzalloc(&pdev->dev, sizeof(*audio), GFP_KERNEL);
369 	if (!audio) {
370 		rc = -ENOMEM;
371 		goto error;
372 	}
373 
374 	audio->pdev = pdev;
375 	audio->catalog = catalog;
376 
377 	msm_dp_audio = &audio->msm_dp_audio;
378 
379 	return msm_dp_audio;
380 error:
381 	return ERR_PTR(rc);
382 }
383 
384 void msm_dp_audio_put(struct msm_dp_audio *msm_dp_audio)
385 {
386 	struct msm_dp_audio_private *audio;
387 
388 	if (!msm_dp_audio)
389 		return;
390 
391 	audio = container_of(msm_dp_audio, struct msm_dp_audio_private, msm_dp_audio);
392 
393 	devm_kfree(&audio->pdev->dev, audio);
394 }
395