layerscape: add patches-5.4
[openwrt/staging/stintel.git] / target / linux / layerscape / patches-5.4 / 805-display-0007-drm-bridge-cadence-Add-mhdp-audio-driver.patch
1 From 3cd4b3cfc651c4d54897c72fbbaa9cd583ee6208 Mon Sep 17 00:00:00 2001
2 From: Sandor Yu <Sandor.yu@nxp.com>
3 Date: Fri, 30 Aug 2019 17:51:43 +0800
4 Subject: [PATCH] drm: bridge: cadence: Add mhdp audio driver
5
6 Move mhdp audio driver to cadence folder.
7 Add audio info-frame set function for hdmi tx audio.
8 The driver suppoer both HDMI and DP audio.
9
10 Signed-off-by: Sandor Yu <Sandor.yu@nxp.com>
11 ---
12 drivers/gpu/drm/bridge/cadence/Kconfig | 3 +
13 drivers/gpu/drm/bridge/cadence/Makefile | 3 +-
14 drivers/gpu/drm/bridge/cadence/cdns-dp-core.c | 4 +
15 drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c | 5 +-
16 drivers/gpu/drm/bridge/cadence/cdns-mhdp-audio.c | 395 ++++++++++++++++++++++
17 drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c | 183 ----------
18 drivers/gpu/drm/imx/Kconfig | 1 +
19 include/drm/bridge/cdns-mhdp-common.h | 6 +
20 8 files changed, 414 insertions(+), 186 deletions(-)
21 create mode 100644 drivers/gpu/drm/bridge/cadence/cdns-mhdp-audio.c
22
23 --- a/drivers/gpu/drm/bridge/cadence/Kconfig
24 +++ b/drivers/gpu/drm/bridge/cadence/Kconfig
25 @@ -11,3 +11,6 @@ config DRM_CDNS_HDMI
26
27 config DRM_CDNS_DP
28 tristate "Cadence DP DRM driver"
29 +
30 +config DRM_CDNS_AUDIO
31 + tristate "Cadence MHDP Audio driver"
32 --- a/drivers/gpu/drm/bridge/cadence/Makefile
33 +++ b/drivers/gpu/drm/bridge/cadence/Makefile
34 @@ -1,5 +1,4 @@
35 -#ccflags-y := -Iinclude/drm
36 -
37 obj-$(CONFIG_DRM_CDNS_MHDP) += cdns-mhdp-common.o cdns-mhdp-hdmi.o
38 obj-$(CONFIG_DRM_CDNS_HDMI) += cdns-hdmi-core.o
39 obj-$(CONFIG_DRM_CDNS_DP) += cdns-dp-core.o
40 +obj-$(CONFIG_DRM_CDNS_AUDIO) += cdns-mhdp-audio.o
41 --- a/drivers/gpu/drm/bridge/cadence/cdns-dp-core.c
42 +++ b/drivers/gpu/drm/bridge/cadence/cdns-dp-core.c
43 @@ -526,6 +526,9 @@ __cdns_dp_probe(struct platform_device *
44
45 dev_set_drvdata(dev, &dp->mhdp);
46
47 + /* register audio driver */
48 + cdns_mhdp_register_audio_driver(dev);
49 +
50 dp_aux_init(&dp->mhdp, dev);
51
52 return dp;
53 @@ -537,6 +540,7 @@ err_out:
54 static void __cdns_dp_remove(struct cdns_mhdp_device *mhdp)
55 {
56 dp_aux_destroy(mhdp);
57 + cdns_mhdp_unregister_audio_driver(mhdp->dev);
58 }
59
60 /* -----------------------------------------------------------------------------
61 --- a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c
62 +++ b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c
63 @@ -9,7 +9,6 @@
64 * (at your option) any later version.
65 *
66 */
67 -
68 #include <drm/bridge/cdns-mhdp-imx.h>
69 #include <drm/drm_atomic_helper.h>
70 #include <drm/drm_crtc_helper.h>
71 @@ -513,6 +512,9 @@ __cdns_hdmi_probe(struct platform_device
72
73 dev_set_drvdata(dev, &hdmi->mhdp);
74
75 + /* register audio driver */
76 + cdns_mhdp_register_audio_driver(dev);
77 +
78 return hdmi;
79
80 err_out:
81 @@ -522,6 +524,7 @@ err_out:
82
83 static void __cdns_hdmi_remove(struct cdns_mhdp_device *mhdp)
84 {
85 + cdns_mhdp_unregister_audio_driver(mhdp->dev);
86 }
87
88 /* -----------------------------------------------------------------------------
89 --- /dev/null
90 +++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-audio.c
91 @@ -0,0 +1,395 @@
92 +// SPDX-License-Identifier: GPL-2.0
93 +/*
94 + * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
95 + * Author: Chris Zhong <zyw@rock-chips.com>
96 + *
97 + * This software is licensed under the terms of the GNU General Public
98 + * License version 2, as published by the Free Software Foundation, and
99 + * may be copied, distributed, and modified under those terms.
100 + *
101 + * This program is distributed in the hope that it will be useful,
102 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
103 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
104 + * GNU General Public License for more details.
105 + */
106 +#include <linux/clk.h>
107 +#include <linux/reset.h>
108 +#include <drm/bridge/cdns-mhdp-common.h>
109 +#include <sound/hdmi-codec.h>
110 +#include <drm/bridge/cdns-mhdp-imx.h>
111 +#include <drm/drm_of.h>
112 +#include <drm/drmP.h>
113 +
114 +#define CDNS_DP_SPDIF_CLK 200000000
115 +
116 +static u32 TMDS_rate_table[7] = {
117 + 25200, 27000, 54000, 74250, 148500, 297000, 594000,
118 +};
119 +
120 +static u32 N_table_32k[7] = {
121 +/* 25200/27000/54000/74250/148500/297000/594000 */
122 + 4096, 4096, 4096, 4096, 4096, 3072, 3072,
123 +};
124 +
125 +static u32 N_table_44k[7] = {
126 + 6272, 6272, 6272, 6272, 6272, 4704, 9408,
127 +};
128 +
129 +static u32 N_table_48k[7] = {
130 + 6144, 6144, 6144, 6144, 6144, 5120, 6144,
131 +};
132 +
133 +static int select_N_index(u32 pclk)
134 +{
135 + int num = sizeof(TMDS_rate_table)/sizeof(int);
136 + int i = 0;
137 +
138 + for (i = 0; i < num ; i++)
139 + if (pclk == TMDS_rate_table[i])
140 + break;
141 +
142 + if (i == num) {
143 + DRM_WARN("pclkc %d is not supported!\n", pclk);
144 + return num-1;
145 + }
146 +
147 + return i;
148 +}
149 +
150 +static void hdmi_audio_avi_set(struct cdns_mhdp_device *mhdp,
151 + u32 channels)
152 +{
153 + struct hdmi_audio_infoframe frame;
154 + u8 buf[32];
155 + int ret;
156 +
157 + hdmi_audio_infoframe_init(&frame);
158 +
159 + frame.channels = channels;
160 + frame.coding_type = HDMI_AUDIO_CODING_TYPE_STREAM;
161 +
162 + if (channels == 2)
163 + frame.channel_allocation = 0;
164 + else if (channels == 4)
165 + frame.channel_allocation = 0x3;
166 + else if (channels == 8)
167 + frame.channel_allocation = 0x13;
168 +
169 + ret = hdmi_audio_infoframe_pack(&frame, buf + 1, sizeof(buf) - 1);
170 + if (ret < 0) {
171 + DRM_ERROR("failed to pack audio infoframe: %d\n", ret);
172 + return;
173 + }
174 +
175 + buf[0] = 0;
176 +
177 + cdns_mhdp_infoframe_set(mhdp, 1, sizeof(buf), buf, HDMI_INFOFRAME_TYPE_AUDIO);
178 +}
179 +
180 +int cdns_mhdp_audio_stop(struct cdns_mhdp_device *mhdp,
181 + struct audio_info *audio)
182 +{
183 + int ret;
184 +
185 + if (audio->connector_type == DRM_MODE_CONNECTOR_DisplayPort) {
186 + ret = cdns_mhdp_reg_write(mhdp, AUDIO_PACK_CONTROL, 0);
187 + if (ret) {
188 + DRM_DEV_ERROR(mhdp->dev, "audio stop failed: %d\n", ret);
189 + return ret;
190 + }
191 + }
192 +
193 + cdns_mhdp_bus_write(0, mhdp, SPDIF_CTRL_ADDR);
194 +
195 + /* clearn the audio config and reset */
196 + cdns_mhdp_bus_write(0, mhdp, AUDIO_SRC_CNTL);
197 + cdns_mhdp_bus_write(0, mhdp, AUDIO_SRC_CNFG);
198 + cdns_mhdp_bus_write(AUDIO_SW_RST, mhdp, AUDIO_SRC_CNTL);
199 + cdns_mhdp_bus_write(0, mhdp, AUDIO_SRC_CNTL);
200 +
201 + /* reset smpl2pckt component */
202 + cdns_mhdp_bus_write(0, mhdp, SMPL2PKT_CNTL);
203 + cdns_mhdp_bus_write(AUDIO_SW_RST, mhdp, SMPL2PKT_CNTL);
204 + cdns_mhdp_bus_write(0, mhdp, SMPL2PKT_CNTL);
205 +
206 + /* reset FIFO */
207 + cdns_mhdp_bus_write(AUDIO_SW_RST, mhdp, FIFO_CNTL);
208 + cdns_mhdp_bus_write(0, mhdp, FIFO_CNTL);
209 +
210 + if (audio->format == AFMT_SPDIF_INT)
211 + clk_disable_unprepare(mhdp->spdif_clk);
212 +
213 + return 0;
214 +}
215 +EXPORT_SYMBOL(cdns_mhdp_audio_stop);
216 +
217 +int cdns_mhdp_audio_mute(struct cdns_mhdp_device *mhdp, bool enable)
218 +{
219 + struct audio_info *audio = &mhdp->audio_info;
220 + int ret = true;
221 +
222 + if (audio->connector_type == DRM_MODE_CONNECTOR_DisplayPort) {
223 + ret = cdns_mhdp_reg_write_bit(mhdp, DP_VB_ID, 4, 1, enable);
224 + if (ret)
225 + DRM_DEV_ERROR(mhdp->dev, "audio mute failed: %d\n", ret);
226 + }
227 +
228 + return ret;
229 +}
230 +EXPORT_SYMBOL(cdns_mhdp_audio_mute);
231 +
232 +static void cdns_mhdp_audio_config_i2s(struct cdns_mhdp_device *mhdp,
233 + struct audio_info *audio)
234 +{
235 + int sub_pckt_num = 1, i2s_port_en_val = 0xf, i;
236 + int idx = select_N_index(mhdp->mode.clock);
237 + u32 val, ncts;
238 +
239 + if (audio->channels == 2) {
240 + if (mhdp->dp.link.num_lanes == 1)
241 + sub_pckt_num = 2;
242 + else
243 + sub_pckt_num = 4;
244 +
245 + i2s_port_en_val = 1;
246 + } else if (audio->channels == 4) {
247 + i2s_port_en_val = 3;
248 + }
249 +
250 + cdns_mhdp_bus_write(0x0, mhdp, SPDIF_CTRL_ADDR);
251 +
252 + cdns_mhdp_bus_write(SYNC_WR_TO_CH_ZERO, mhdp, FIFO_CNTL);
253 +
254 + val = MAX_NUM_CH(audio->channels);
255 + val |= NUM_OF_I2S_PORTS(audio->channels);
256 + val |= AUDIO_TYPE_LPCM;
257 + val |= CFG_SUB_PCKT_NUM(sub_pckt_num);
258 + cdns_mhdp_bus_write(val, mhdp, SMPL2PKT_CNFG);
259 +
260 + if (audio->sample_width == 16)
261 + val = 0;
262 + else if (audio->sample_width == 24)
263 + val = 1 << 9;
264 + else
265 + val = 2 << 9;
266 +
267 + val |= AUDIO_CH_NUM(audio->channels);
268 + val |= I2S_DEC_PORT_EN(i2s_port_en_val);
269 + val |= TRANS_SMPL_WIDTH_32;
270 + cdns_mhdp_bus_write(val, mhdp, AUDIO_SRC_CNFG);
271 +
272 + for (i = 0; i < (audio->channels + 1) / 2; i++) {
273 + if (audio->sample_width == 16)
274 + val = (0x02 << 8) | (0x02 << 20);
275 + else if (audio->sample_width == 24)
276 + val = (0x0b << 8) | (0x0b << 20);
277 +
278 + val |= ((2 * i) << 4) | ((2 * i + 1) << 16);
279 + cdns_mhdp_bus_write(val, mhdp, STTS_BIT_CH(i));
280 + }
281 +
282 + switch (audio->sample_rate) {
283 + case 32000:
284 + val = SAMPLING_FREQ(3) |
285 + ORIGINAL_SAMP_FREQ(0xc);
286 + ncts = N_table_32k[idx];
287 + break;
288 + case 44100:
289 + val = SAMPLING_FREQ(0) |
290 + ORIGINAL_SAMP_FREQ(0xf);
291 + ncts = N_table_44k[idx];
292 + break;
293 + case 48000:
294 + val = SAMPLING_FREQ(2) |
295 + ORIGINAL_SAMP_FREQ(0xd);
296 + ncts = N_table_48k[idx];
297 + break;
298 + case 88200:
299 + val = SAMPLING_FREQ(8) |
300 + ORIGINAL_SAMP_FREQ(0x7);
301 + ncts = N_table_44k[idx] * 2;
302 + break;
303 + case 96000:
304 + val = SAMPLING_FREQ(0xa) |
305 + ORIGINAL_SAMP_FREQ(5);
306 + ncts = N_table_48k[idx] * 2;
307 + break;
308 + case 176400:
309 + val = SAMPLING_FREQ(0xc) |
310 + ORIGINAL_SAMP_FREQ(3);
311 + ncts = N_table_44k[idx] * 4;
312 + break;
313 + case 192000:
314 + default:
315 + val = SAMPLING_FREQ(0xe) |
316 + ORIGINAL_SAMP_FREQ(1);
317 + ncts = N_table_48k[idx] * 4;
318 + break;
319 + }
320 + val |= 4;
321 + cdns_mhdp_bus_write(val, mhdp, COM_CH_STTS_BITS);
322 +
323 + if (audio->connector_type == DRM_MODE_CONNECTOR_HDMIA)
324 + cdns_mhdp_reg_write(mhdp, CM_I2S_CTRL, ncts | 0x4000000);
325 +
326 + cdns_mhdp_bus_write(SMPL2PKT_EN, mhdp, SMPL2PKT_CNTL);
327 + cdns_mhdp_bus_write(I2S_DEC_START, mhdp, AUDIO_SRC_CNTL);
328 +}
329 +
330 +static void cdns_mhdp_audio_config_spdif(struct cdns_mhdp_device *mhdp)
331 +{
332 + u32 val;
333 +
334 + cdns_mhdp_bus_write(SYNC_WR_TO_CH_ZERO, mhdp, FIFO_CNTL);
335 +
336 + val = MAX_NUM_CH(2) | AUDIO_TYPE_LPCM | CFG_SUB_PCKT_NUM(4);
337 + cdns_mhdp_bus_write(val, mhdp, SMPL2PKT_CNFG);
338 + cdns_mhdp_bus_write(SMPL2PKT_EN, mhdp, SMPL2PKT_CNTL);
339 +
340 + val = SPDIF_ENABLE | SPDIF_AVG_SEL | SPDIF_JITTER_BYPASS;
341 + cdns_mhdp_bus_write(val, mhdp, SPDIF_CTRL_ADDR);
342 +
343 + clk_prepare_enable(mhdp->spdif_clk);
344 + clk_set_rate(mhdp->spdif_clk, CDNS_DP_SPDIF_CLK);
345 +}
346 +
347 +int cdns_mhdp_audio_config(struct cdns_mhdp_device *mhdp,
348 + struct audio_info *audio)
349 +{
350 + int ret;
351 +
352 + /* reset the spdif clk before config */
353 + if (audio->format == AFMT_SPDIF_INT) {
354 + reset_control_assert(mhdp->spdif_rst);
355 + reset_control_deassert(mhdp->spdif_rst);
356 + }
357 +
358 + if (audio->connector_type == DRM_MODE_CONNECTOR_DisplayPort) {
359 + ret = cdns_mhdp_reg_write(mhdp, CM_LANE_CTRL, LANE_REF_CYC);
360 + if (ret)
361 + goto err_audio_config;
362 +
363 + ret = cdns_mhdp_reg_write(mhdp, CM_CTRL, 0);
364 + if (ret)
365 + goto err_audio_config;
366 + } else {
367 + /* HDMI Mode */
368 + ret = cdns_mhdp_reg_write(mhdp, CM_CTRL, 8);
369 + if (ret)
370 + goto err_audio_config;
371 + }
372 +
373 + if (audio->format == AFMT_I2S)
374 + cdns_mhdp_audio_config_i2s(mhdp, audio);
375 + else if (audio->format == AFMT_SPDIF_INT)
376 + cdns_mhdp_audio_config_spdif(mhdp);
377 +
378 + if (audio->connector_type == DRM_MODE_CONNECTOR_DisplayPort)
379 + ret = cdns_mhdp_reg_write(mhdp, AUDIO_PACK_CONTROL, AUDIO_PACK_EN);
380 +
381 + if (audio->connector_type == DRM_MODE_CONNECTOR_HDMIA)
382 + hdmi_audio_avi_set(mhdp, audio->channels);
383 +
384 +err_audio_config:
385 + if (ret)
386 + DRM_DEV_ERROR(mhdp->dev, "audio config failed: %d\n", ret);
387 + return ret;
388 +}
389 +EXPORT_SYMBOL(cdns_mhdp_audio_config);
390 +
391 +static int audio_hw_params(struct device *dev, void *data,
392 + struct hdmi_codec_daifmt *daifmt,
393 + struct hdmi_codec_params *params)
394 +{
395 + struct cdns_mhdp_device *mhdp = dev_get_drvdata(dev);
396 + struct audio_info audio = {
397 + .sample_width = params->sample_width,
398 + .sample_rate = params->sample_rate,
399 + .channels = params->channels,
400 + .connector_type = mhdp->connector.base.connector_type,
401 + };
402 + int ret;
403 +
404 + switch (daifmt->fmt) {
405 + case HDMI_I2S:
406 + audio.format = AFMT_I2S;
407 + break;
408 + case HDMI_SPDIF:
409 + audio.format = AFMT_SPDIF_EXT;
410 + break;
411 + default:
412 + DRM_DEV_ERROR(dev, "Invalid format %d\n", daifmt->fmt);
413 + ret = -EINVAL;
414 + goto out;
415 + }
416 +
417 + ret = cdns_mhdp_audio_config(mhdp, &audio);
418 + if (!ret)
419 + mhdp->audio_info = audio;
420 +
421 +out:
422 + return ret;
423 +}
424 +
425 +static void audio_shutdown(struct device *dev, void *data)
426 +{
427 + struct cdns_mhdp_device *mhdp = dev_get_drvdata(dev);
428 + int ret;
429 +
430 + ret = cdns_mhdp_audio_stop(mhdp, &mhdp->audio_info);
431 + if (!ret)
432 + mhdp->audio_info.format = AFMT_UNUSED;
433 +}
434 +
435 +static int audio_digital_mute(struct device *dev, void *data,
436 + bool enable)
437 +{
438 + struct cdns_mhdp_device *mhdp = dev_get_drvdata(dev);
439 + int ret;
440 +
441 + ret = cdns_mhdp_audio_mute(mhdp, enable);
442 +
443 + return ret;
444 +}
445 +
446 +static int audio_get_eld(struct device *dev, void *data,
447 + u8 *buf, size_t len)
448 +{
449 + struct cdns_mhdp_device *mhdp = dev_get_drvdata(dev);
450 +
451 + memcpy(buf, mhdp->connector.base.eld,
452 + min(sizeof(mhdp->connector.base.eld), len));
453 +
454 + return 0;
455 +}
456 +
457 +static const struct hdmi_codec_ops audio_codec_ops = {
458 + .hw_params = audio_hw_params,
459 + .audio_shutdown = audio_shutdown,
460 + .digital_mute = audio_digital_mute,
461 + .get_eld = audio_get_eld,
462 +};
463 +
464 +int cdns_mhdp_register_audio_driver(struct device *dev)
465 +{
466 + struct cdns_mhdp_device *mhdp = dev_get_drvdata(dev);
467 + struct hdmi_codec_pdata codec_data = {
468 + .i2s = 1,
469 + .spdif = 1,
470 + .ops = &audio_codec_ops,
471 + .max_i2s_channels = 8,
472 + };
473 +
474 + mhdp->audio_pdev = platform_device_register_data(
475 + dev, HDMI_CODEC_DRV_NAME, 1,
476 + &codec_data, sizeof(codec_data));
477 +
478 + return PTR_ERR_OR_ZERO(mhdp->audio_pdev);
479 +}
480 +
481 +void cdns_mhdp_unregister_audio_driver(struct device *dev)
482 +{
483 + struct cdns_mhdp_device *mhdp = dev_get_drvdata(dev);
484 +
485 + platform_device_unregister(mhdp->audio_pdev);
486 +}
487 --- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c
488 +++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c
489 @@ -937,189 +937,6 @@ err_config_video:
490 }
491 EXPORT_SYMBOL(cdns_mhdp_config_video);
492
493 -int cdns_mhdp_audio_stop(struct cdns_mhdp_device *mhdp,
494 - struct audio_info *audio)
495 -{
496 - int ret;
497 -
498 - ret = cdns_mhdp_reg_write(mhdp, AUDIO_PACK_CONTROL, 0);
499 - if (ret) {
500 - DRM_DEV_ERROR(mhdp->dev, "audio stop failed: %d\n", ret);
501 - return ret;
502 - }
503 -
504 - cdns_mhdp_bus_write(0, mhdp, SPDIF_CTRL_ADDR);
505 -
506 - /* clearn the audio config and reset */
507 - cdns_mhdp_bus_write(0, mhdp, AUDIO_SRC_CNTL);
508 - cdns_mhdp_bus_write(0, mhdp, AUDIO_SRC_CNFG);
509 - cdns_mhdp_bus_write(AUDIO_SW_RST, mhdp, AUDIO_SRC_CNTL);
510 - cdns_mhdp_bus_write(0, mhdp, AUDIO_SRC_CNTL);
511 -
512 - /* reset smpl2pckt component */
513 - cdns_mhdp_bus_write(0, mhdp, SMPL2PKT_CNTL);
514 - cdns_mhdp_bus_write(AUDIO_SW_RST, mhdp, SMPL2PKT_CNTL);
515 - cdns_mhdp_bus_write(0, mhdp, SMPL2PKT_CNTL);
516 -
517 - /* reset FIFO */
518 - cdns_mhdp_bus_write(AUDIO_SW_RST, mhdp, FIFO_CNTL);
519 - cdns_mhdp_bus_write(0, mhdp, FIFO_CNTL);
520 -
521 - if (audio->format == AFMT_SPDIF_INT)
522 - clk_disable_unprepare(mhdp->spdif_clk);
523 -
524 - return 0;
525 -}
526 -EXPORT_SYMBOL(cdns_mhdp_audio_stop);
527 -
528 -int cdns_mhdp_audio_mute(struct cdns_mhdp_device *mhdp, bool enable)
529 -{
530 - int ret;
531 -
532 - ret = cdns_mhdp_reg_write_bit(mhdp, DP_VB_ID, 4, 1, enable);
533 - if (ret)
534 - DRM_DEV_ERROR(mhdp->dev, "audio mute failed: %d\n", ret);
535 -
536 - return ret;
537 -}
538 -EXPORT_SYMBOL(cdns_mhdp_audio_mute);
539 -
540 -static void cdns_mhdp_audio_config_i2s(struct cdns_mhdp_device *mhdp,
541 - struct audio_info *audio)
542 -{
543 - int sub_pckt_num = 1, i2s_port_en_val = 0xf, i;
544 - u32 val;
545 -
546 - if (audio->channels == 2) {
547 - if (mhdp->dp.link.num_lanes == 1)
548 - sub_pckt_num = 2;
549 - else
550 - sub_pckt_num = 4;
551 -
552 - i2s_port_en_val = 1;
553 - } else if (audio->channels == 4) {
554 - i2s_port_en_val = 3;
555 - }
556 -
557 - cdns_mhdp_bus_write(0x0, mhdp, SPDIF_CTRL_ADDR);
558 -
559 - cdns_mhdp_bus_write(SYNC_WR_TO_CH_ZERO, mhdp, FIFO_CNTL);
560 -
561 - val = MAX_NUM_CH(audio->channels);
562 - val |= NUM_OF_I2S_PORTS(audio->channels);
563 - val |= AUDIO_TYPE_LPCM;
564 - val |= CFG_SUB_PCKT_NUM(sub_pckt_num);
565 - cdns_mhdp_bus_write(val, mhdp, SMPL2PKT_CNFG);
566 -
567 - if (audio->sample_width == 16)
568 - val = 0;
569 - else if (audio->sample_width == 24)
570 - val = 1 << 9;
571 - else
572 - val = 2 << 9;
573 -
574 - val |= AUDIO_CH_NUM(audio->channels);
575 - val |= I2S_DEC_PORT_EN(i2s_port_en_val);
576 - val |= TRANS_SMPL_WIDTH_32;
577 - cdns_mhdp_bus_write(val, mhdp, AUDIO_SRC_CNFG);
578 -
579 - for (i = 0; i < (audio->channels + 1) / 2; i++) {
580 - if (audio->sample_width == 16)
581 - val = (0x02 << 8) | (0x02 << 20);
582 - else if (audio->sample_width == 24)
583 - val = (0x0b << 8) | (0x0b << 20);
584 -
585 - val |= ((2 * i) << 4) | ((2 * i + 1) << 16);
586 - cdns_mhdp_bus_write(val, mhdp, STTS_BIT_CH(i));
587 - }
588 -
589 - switch (audio->sample_rate) {
590 - case 32000:
591 - val = SAMPLING_FREQ(3) |
592 - ORIGINAL_SAMP_FREQ(0xc);
593 - break;
594 - case 44100:
595 - val = SAMPLING_FREQ(0) |
596 - ORIGINAL_SAMP_FREQ(0xf);
597 - break;
598 - case 48000:
599 - val = SAMPLING_FREQ(2) |
600 - ORIGINAL_SAMP_FREQ(0xd);
601 - break;
602 - case 88200:
603 - val = SAMPLING_FREQ(8) |
604 - ORIGINAL_SAMP_FREQ(0x7);
605 - break;
606 - case 96000:
607 - val = SAMPLING_FREQ(0xa) |
608 - ORIGINAL_SAMP_FREQ(5);
609 - break;
610 - case 176400:
611 - val = SAMPLING_FREQ(0xc) |
612 - ORIGINAL_SAMP_FREQ(3);
613 - break;
614 - case 192000:
615 - val = SAMPLING_FREQ(0xe) |
616 - ORIGINAL_SAMP_FREQ(1);
617 - break;
618 - }
619 - val |= 4;
620 - cdns_mhdp_bus_write(val, mhdp, COM_CH_STTS_BITS);
621 -
622 - cdns_mhdp_bus_write(SMPL2PKT_EN, mhdp, SMPL2PKT_CNTL);
623 - cdns_mhdp_bus_write(I2S_DEC_START, mhdp, AUDIO_SRC_CNTL);
624 -}
625 -
626 -static void cdns_mhdp_audio_config_spdif(struct cdns_mhdp_device *mhdp)
627 -{
628 - u32 val;
629 -
630 - cdns_mhdp_bus_write(SYNC_WR_TO_CH_ZERO, mhdp, FIFO_CNTL);
631 -
632 - val = MAX_NUM_CH(2) | AUDIO_TYPE_LPCM | CFG_SUB_PCKT_NUM(4);
633 - cdns_mhdp_bus_write(val, mhdp, SMPL2PKT_CNFG);
634 - cdns_mhdp_bus_write(SMPL2PKT_EN, mhdp, SMPL2PKT_CNTL);
635 -
636 - val = SPDIF_ENABLE | SPDIF_AVG_SEL | SPDIF_JITTER_BYPASS;
637 - cdns_mhdp_bus_write(val, mhdp, SPDIF_CTRL_ADDR);
638 -
639 - clk_prepare_enable(mhdp->spdif_clk);
640 - clk_set_rate(mhdp->spdif_clk, CDNS_DP_SPDIF_CLK);
641 -}
642 -
643 -int cdns_mhdp_audio_config(struct cdns_mhdp_device *mhdp,
644 - struct audio_info *audio)
645 -{
646 - int ret;
647 -
648 - /* reset the spdif clk before config */
649 - if (audio->format == AFMT_SPDIF_INT) {
650 - reset_control_assert(mhdp->spdif_rst);
651 - reset_control_deassert(mhdp->spdif_rst);
652 - }
653 -
654 - ret = cdns_mhdp_reg_write(mhdp, CM_LANE_CTRL, LANE_REF_CYC);
655 - if (ret)
656 - goto err_audio_config;
657 -
658 - ret = cdns_mhdp_reg_write(mhdp, CM_CTRL, 0);
659 - if (ret)
660 - goto err_audio_config;
661 -
662 - if (audio->format == AFMT_I2S)
663 - cdns_mhdp_audio_config_i2s(mhdp, audio);
664 - else if (audio->format == AFMT_SPDIF_INT)
665 - cdns_mhdp_audio_config_spdif(mhdp);
666 -
667 - ret = cdns_mhdp_reg_write(mhdp, AUDIO_PACK_CONTROL, AUDIO_PACK_EN);
668 -
669 -err_audio_config:
670 - if (ret)
671 - DRM_DEV_ERROR(mhdp->dev, "audio config failed: %d\n", ret);
672 - return ret;
673 -}
674 -EXPORT_SYMBOL(cdns_mhdp_audio_config);
675 -
676 int cdns_mhdp_adjust_lt(struct cdns_mhdp_device *mhdp,
677 u8 nlanes, u16 udelay, u8 *lanes_data, u8 *dpcd)
678 {
679 --- a/drivers/gpu/drm/imx/Kconfig
680 +++ b/drivers/gpu/drm/imx/Kconfig
681 @@ -45,6 +45,7 @@ config DRM_IMX_CDNS_MHDP
682 select DRM_CDNS_MHDP
683 select DRM_CDNS_DP
684 select DRM_CDNS_HDMI
685 + select DRM_CDNS_AUDIO
686 depends on DRM_IMX
687 help
688 Choose this if you want to use HDMI on i.MX8.
689 --- a/include/drm/bridge/cdns-mhdp-common.h
690 +++ b/include/drm/bridge/cdns-mhdp-common.h
691 @@ -548,6 +548,7 @@ struct audio_info {
692 int sample_rate;
693 int channels;
694 int sample_width;
695 + int connector_type;
696 };
697
698 enum vic_pxl_encoding_format {
699 @@ -670,11 +671,16 @@ int cdns_mhdp_get_edid_block(void *mhdp,
700 int cdns_mhdp_train_link(struct cdns_mhdp_device *mhdp);
701 int cdns_mhdp_set_video_status(struct cdns_mhdp_device *mhdp, int active);
702 int cdns_mhdp_config_video(struct cdns_mhdp_device *mhdp);
703 +
704 +/* Audio */
705 int cdns_mhdp_audio_stop(struct cdns_mhdp_device *mhdp,
706 struct audio_info *audio);
707 int cdns_mhdp_audio_mute(struct cdns_mhdp_device *mhdp, bool enable);
708 int cdns_mhdp_audio_config(struct cdns_mhdp_device *mhdp,
709 struct audio_info *audio);
710 +int cdns_mhdp_register_audio_driver(struct device *dev);
711 +void cdns_mhdp_unregister_audio_driver(struct device *dev);
712 +
713 int cdns_mhdp_reg_read(struct cdns_mhdp_device *mhdp, u32 addr);
714 int cdns_mhdp_reg_write(struct cdns_mhdp_device *mhdp, u32 addr, u32 val);
715 int cdns_mhdp_reg_write_bit(struct cdns_mhdp_device *mhdp, u16 addr,