blob: f0a1414b036603f6c3cf4f7c41a414125fb927d7 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001From 3cd4b3cfc651c4d54897c72fbbaa9cd583ee6208 Mon Sep 17 00:00:00 2001
2From: Sandor Yu <Sandor.yu@nxp.com>
3Date: Fri, 30 Aug 2019 17:51:43 +0800
4Subject: [PATCH] drm: bridge: cadence: Add mhdp audio driver
5
6Move mhdp audio driver to cadence folder.
7Add audio info-frame set function for hdmi tx audio.
8The driver suppoer both HDMI and DP audio.
9
10Signed-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,