ath79/mikrotik: use routerbootpart partitions
[oweals/openwrt.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,