diff options
Diffstat (limited to 'target/linux/layerscape/patches-5.4/805-display-0007-drm-bridge-cadence-Add-mhdp-audio-driver.patch')
-rw-r--r-- | target/linux/layerscape/patches-5.4/805-display-0007-drm-bridge-cadence-Add-mhdp-audio-driver.patch | 715 |
1 files changed, 0 insertions, 715 deletions
diff --git a/target/linux/layerscape/patches-5.4/805-display-0007-drm-bridge-cadence-Add-mhdp-audio-driver.patch b/target/linux/layerscape/patches-5.4/805-display-0007-drm-bridge-cadence-Add-mhdp-audio-driver.patch deleted file mode 100644 index f0a1414b03..0000000000 --- a/target/linux/layerscape/patches-5.4/805-display-0007-drm-bridge-cadence-Add-mhdp-audio-driver.patch +++ /dev/null @@ -1,715 +0,0 @@ -From 3cd4b3cfc651c4d54897c72fbbaa9cd583ee6208 Mon Sep 17 00:00:00 2001 -From: Sandor Yu <Sandor.yu@nxp.com> -Date: Fri, 30 Aug 2019 17:51:43 +0800 -Subject: [PATCH] drm: bridge: cadence: Add mhdp audio driver - -Move mhdp audio driver to cadence folder. -Add audio info-frame set function for hdmi tx audio. -The driver suppoer both HDMI and DP audio. - -Signed-off-by: Sandor Yu <Sandor.yu@nxp.com> ---- - drivers/gpu/drm/bridge/cadence/Kconfig | 3 + - drivers/gpu/drm/bridge/cadence/Makefile | 3 +- - drivers/gpu/drm/bridge/cadence/cdns-dp-core.c | 4 + - drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c | 5 +- - drivers/gpu/drm/bridge/cadence/cdns-mhdp-audio.c | 395 ++++++++++++++++++++++ - drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c | 183 ---------- - drivers/gpu/drm/imx/Kconfig | 1 + - include/drm/bridge/cdns-mhdp-common.h | 6 + - 8 files changed, 414 insertions(+), 186 deletions(-) - create mode 100644 drivers/gpu/drm/bridge/cadence/cdns-mhdp-audio.c - ---- a/drivers/gpu/drm/bridge/cadence/Kconfig -+++ b/drivers/gpu/drm/bridge/cadence/Kconfig -@@ -11,3 +11,6 @@ config DRM_CDNS_HDMI - - config DRM_CDNS_DP - tristate "Cadence DP DRM driver" -+ -+config DRM_CDNS_AUDIO -+ tristate "Cadence MHDP Audio driver" ---- a/drivers/gpu/drm/bridge/cadence/Makefile -+++ b/drivers/gpu/drm/bridge/cadence/Makefile -@@ -1,5 +1,4 @@ --#ccflags-y := -Iinclude/drm -- - obj-$(CONFIG_DRM_CDNS_MHDP) += cdns-mhdp-common.o cdns-mhdp-hdmi.o - obj-$(CONFIG_DRM_CDNS_HDMI) += cdns-hdmi-core.o - obj-$(CONFIG_DRM_CDNS_DP) += cdns-dp-core.o -+obj-$(CONFIG_DRM_CDNS_AUDIO) += cdns-mhdp-audio.o ---- a/drivers/gpu/drm/bridge/cadence/cdns-dp-core.c -+++ b/drivers/gpu/drm/bridge/cadence/cdns-dp-core.c -@@ -526,6 +526,9 @@ __cdns_dp_probe(struct platform_device * - - dev_set_drvdata(dev, &dp->mhdp); - -+ /* register audio driver */ -+ cdns_mhdp_register_audio_driver(dev); -+ - dp_aux_init(&dp->mhdp, dev); - - return dp; -@@ -537,6 +540,7 @@ err_out: - static void __cdns_dp_remove(struct cdns_mhdp_device *mhdp) - { - dp_aux_destroy(mhdp); -+ cdns_mhdp_unregister_audio_driver(mhdp->dev); - } - - /* ----------------------------------------------------------------------------- ---- a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c -+++ b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c -@@ -9,7 +9,6 @@ - * (at your option) any later version. - * - */ -- - #include <drm/bridge/cdns-mhdp-imx.h> - #include <drm/drm_atomic_helper.h> - #include <drm/drm_crtc_helper.h> -@@ -513,6 +512,9 @@ __cdns_hdmi_probe(struct platform_device - - dev_set_drvdata(dev, &hdmi->mhdp); - -+ /* register audio driver */ -+ cdns_mhdp_register_audio_driver(dev); -+ - return hdmi; - - err_out: -@@ -522,6 +524,7 @@ err_out: - - static void __cdns_hdmi_remove(struct cdns_mhdp_device *mhdp) - { -+ cdns_mhdp_unregister_audio_driver(mhdp->dev); - } - - /* ----------------------------------------------------------------------------- ---- /dev/null -+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-audio.c -@@ -0,0 +1,395 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd -+ * Author: Chris Zhong <zyw@rock-chips.com> -+ * -+ * This software is licensed under the terms of the GNU General Public -+ * License version 2, as published by the Free Software Foundation, and -+ * may be copied, distributed, and modified under those terms. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ */ -+#include <linux/clk.h> -+#include <linux/reset.h> -+#include <drm/bridge/cdns-mhdp-common.h> -+#include <sound/hdmi-codec.h> -+#include <drm/bridge/cdns-mhdp-imx.h> -+#include <drm/drm_of.h> -+#include <drm/drmP.h> -+ -+#define CDNS_DP_SPDIF_CLK 200000000 -+ -+static u32 TMDS_rate_table[7] = { -+ 25200, 27000, 54000, 74250, 148500, 297000, 594000, -+}; -+ -+static u32 N_table_32k[7] = { -+/* 25200/27000/54000/74250/148500/297000/594000 */ -+ 4096, 4096, 4096, 4096, 4096, 3072, 3072, -+}; -+ -+static u32 N_table_44k[7] = { -+ 6272, 6272, 6272, 6272, 6272, 4704, 9408, -+}; -+ -+static u32 N_table_48k[7] = { -+ 6144, 6144, 6144, 6144, 6144, 5120, 6144, -+}; -+ -+static int select_N_index(u32 pclk) -+{ -+ int num = sizeof(TMDS_rate_table)/sizeof(int); -+ int i = 0; -+ -+ for (i = 0; i < num ; i++) -+ if (pclk == TMDS_rate_table[i]) -+ break; -+ -+ if (i == num) { -+ DRM_WARN("pclkc %d is not supported!\n", pclk); -+ return num-1; -+ } -+ -+ return i; -+} -+ -+static void hdmi_audio_avi_set(struct cdns_mhdp_device *mhdp, -+ u32 channels) -+{ -+ struct hdmi_audio_infoframe frame; -+ u8 buf[32]; -+ int ret; -+ -+ hdmi_audio_infoframe_init(&frame); -+ -+ frame.channels = channels; -+ frame.coding_type = HDMI_AUDIO_CODING_TYPE_STREAM; -+ -+ if (channels == 2) -+ frame.channel_allocation = 0; -+ else if (channels == 4) -+ frame.channel_allocation = 0x3; -+ else if (channels == 8) -+ frame.channel_allocation = 0x13; -+ -+ ret = hdmi_audio_infoframe_pack(&frame, buf + 1, sizeof(buf) - 1); -+ if (ret < 0) { -+ DRM_ERROR("failed to pack audio infoframe: %d\n", ret); -+ return; -+ } -+ -+ buf[0] = 0; -+ -+ cdns_mhdp_infoframe_set(mhdp, 1, sizeof(buf), buf, HDMI_INFOFRAME_TYPE_AUDIO); -+} -+ -+int cdns_mhdp_audio_stop(struct cdns_mhdp_device *mhdp, -+ struct audio_info *audio) -+{ -+ int ret; -+ -+ if (audio->connector_type == DRM_MODE_CONNECTOR_DisplayPort) { -+ ret = cdns_mhdp_reg_write(mhdp, AUDIO_PACK_CONTROL, 0); -+ if (ret) { -+ DRM_DEV_ERROR(mhdp->dev, "audio stop failed: %d\n", ret); -+ return ret; -+ } -+ } -+ -+ cdns_mhdp_bus_write(0, mhdp, SPDIF_CTRL_ADDR); -+ -+ /* clearn the audio config and reset */ -+ cdns_mhdp_bus_write(0, mhdp, AUDIO_SRC_CNTL); -+ cdns_mhdp_bus_write(0, mhdp, AUDIO_SRC_CNFG); -+ cdns_mhdp_bus_write(AUDIO_SW_RST, mhdp, AUDIO_SRC_CNTL); -+ cdns_mhdp_bus_write(0, mhdp, AUDIO_SRC_CNTL); -+ -+ /* reset smpl2pckt component */ -+ cdns_mhdp_bus_write(0, mhdp, SMPL2PKT_CNTL); -+ cdns_mhdp_bus_write(AUDIO_SW_RST, mhdp, SMPL2PKT_CNTL); -+ cdns_mhdp_bus_write(0, mhdp, SMPL2PKT_CNTL); -+ -+ /* reset FIFO */ -+ cdns_mhdp_bus_write(AUDIO_SW_RST, mhdp, FIFO_CNTL); -+ cdns_mhdp_bus_write(0, mhdp, FIFO_CNTL); -+ -+ if (audio->format == AFMT_SPDIF_INT) -+ clk_disable_unprepare(mhdp->spdif_clk); -+ -+ return 0; -+} -+EXPORT_SYMBOL(cdns_mhdp_audio_stop); -+ -+int cdns_mhdp_audio_mute(struct cdns_mhdp_device *mhdp, bool enable) -+{ -+ struct audio_info *audio = &mhdp->audio_info; -+ int ret = true; -+ -+ if (audio->connector_type == DRM_MODE_CONNECTOR_DisplayPort) { -+ ret = cdns_mhdp_reg_write_bit(mhdp, DP_VB_ID, 4, 1, enable); -+ if (ret) -+ DRM_DEV_ERROR(mhdp->dev, "audio mute failed: %d\n", ret); -+ } -+ -+ return ret; -+} -+EXPORT_SYMBOL(cdns_mhdp_audio_mute); -+ -+static void cdns_mhdp_audio_config_i2s(struct cdns_mhdp_device *mhdp, -+ struct audio_info *audio) -+{ -+ int sub_pckt_num = 1, i2s_port_en_val = 0xf, i; -+ int idx = select_N_index(mhdp->mode.clock); -+ u32 val, ncts; -+ -+ if (audio->channels == 2) { -+ if (mhdp->dp.link.num_lanes == 1) -+ sub_pckt_num = 2; -+ else -+ sub_pckt_num = 4; -+ -+ i2s_port_en_val = 1; -+ } else if (audio->channels == 4) { -+ i2s_port_en_val = 3; -+ } -+ -+ cdns_mhdp_bus_write(0x0, mhdp, SPDIF_CTRL_ADDR); -+ -+ cdns_mhdp_bus_write(SYNC_WR_TO_CH_ZERO, mhdp, FIFO_CNTL); -+ -+ val = MAX_NUM_CH(audio->channels); -+ val |= NUM_OF_I2S_PORTS(audio->channels); -+ val |= AUDIO_TYPE_LPCM; -+ val |= CFG_SUB_PCKT_NUM(sub_pckt_num); -+ cdns_mhdp_bus_write(val, mhdp, SMPL2PKT_CNFG); -+ -+ if (audio->sample_width == 16) -+ val = 0; -+ else if (audio->sample_width == 24) -+ val = 1 << 9; -+ else -+ val = 2 << 9; -+ -+ val |= AUDIO_CH_NUM(audio->channels); -+ val |= I2S_DEC_PORT_EN(i2s_port_en_val); -+ val |= TRANS_SMPL_WIDTH_32; -+ cdns_mhdp_bus_write(val, mhdp, AUDIO_SRC_CNFG); -+ -+ for (i = 0; i < (audio->channels + 1) / 2; i++) { -+ if (audio->sample_width == 16) -+ val = (0x02 << 8) | (0x02 << 20); -+ else if (audio->sample_width == 24) -+ val = (0x0b << 8) | (0x0b << 20); -+ -+ val |= ((2 * i) << 4) | ((2 * i + 1) << 16); -+ cdns_mhdp_bus_write(val, mhdp, STTS_BIT_CH(i)); -+ } -+ -+ switch (audio->sample_rate) { -+ case 32000: -+ val = SAMPLING_FREQ(3) | -+ ORIGINAL_SAMP_FREQ(0xc); -+ ncts = N_table_32k[idx]; -+ break; -+ case 44100: -+ val = SAMPLING_FREQ(0) | -+ ORIGINAL_SAMP_FREQ(0xf); -+ ncts = N_table_44k[idx]; -+ break; -+ case 48000: -+ val = SAMPLING_FREQ(2) | -+ ORIGINAL_SAMP_FREQ(0xd); -+ ncts = N_table_48k[idx]; -+ break; -+ case 88200: -+ val = SAMPLING_FREQ(8) | -+ ORIGINAL_SAMP_FREQ(0x7); -+ ncts = N_table_44k[idx] * 2; -+ break; -+ case 96000: -+ val = SAMPLING_FREQ(0xa) | -+ ORIGINAL_SAMP_FREQ(5); -+ ncts = N_table_48k[idx] * 2; -+ break; -+ case 176400: -+ val = SAMPLING_FREQ(0xc) | -+ ORIGINAL_SAMP_FREQ(3); -+ ncts = N_table_44k[idx] * 4; -+ break; -+ case 192000: -+ default: -+ val = SAMPLING_FREQ(0xe) | -+ ORIGINAL_SAMP_FREQ(1); -+ ncts = N_table_48k[idx] * 4; -+ break; -+ } -+ val |= 4; -+ cdns_mhdp_bus_write(val, mhdp, COM_CH_STTS_BITS); -+ -+ if (audio->connector_type == DRM_MODE_CONNECTOR_HDMIA) -+ cdns_mhdp_reg_write(mhdp, CM_I2S_CTRL, ncts | 0x4000000); -+ -+ cdns_mhdp_bus_write(SMPL2PKT_EN, mhdp, SMPL2PKT_CNTL); -+ cdns_mhdp_bus_write(I2S_DEC_START, mhdp, AUDIO_SRC_CNTL); -+} -+ -+static void cdns_mhdp_audio_config_spdif(struct cdns_mhdp_device *mhdp) -+{ -+ u32 val; -+ -+ cdns_mhdp_bus_write(SYNC_WR_TO_CH_ZERO, mhdp, FIFO_CNTL); -+ -+ val = MAX_NUM_CH(2) | AUDIO_TYPE_LPCM | CFG_SUB_PCKT_NUM(4); -+ cdns_mhdp_bus_write(val, mhdp, SMPL2PKT_CNFG); -+ cdns_mhdp_bus_write(SMPL2PKT_EN, mhdp, SMPL2PKT_CNTL); -+ -+ val = SPDIF_ENABLE | SPDIF_AVG_SEL | SPDIF_JITTER_BYPASS; -+ cdns_mhdp_bus_write(val, mhdp, SPDIF_CTRL_ADDR); -+ -+ clk_prepare_enable(mhdp->spdif_clk); -+ clk_set_rate(mhdp->spdif_clk, CDNS_DP_SPDIF_CLK); -+} -+ -+int cdns_mhdp_audio_config(struct cdns_mhdp_device *mhdp, -+ struct audio_info *audio) -+{ -+ int ret; -+ -+ /* reset the spdif clk before config */ -+ if (audio->format == AFMT_SPDIF_INT) { -+ reset_control_assert(mhdp->spdif_rst); -+ reset_control_deassert(mhdp->spdif_rst); -+ } -+ -+ if (audio->connector_type == DRM_MODE_CONNECTOR_DisplayPort) { -+ ret = cdns_mhdp_reg_write(mhdp, CM_LANE_CTRL, LANE_REF_CYC); -+ if (ret) -+ goto err_audio_config; -+ -+ ret = cdns_mhdp_reg_write(mhdp, CM_CTRL, 0); -+ if (ret) -+ goto err_audio_config; -+ } else { -+ /* HDMI Mode */ -+ ret = cdns_mhdp_reg_write(mhdp, CM_CTRL, 8); -+ if (ret) -+ goto err_audio_config; -+ } -+ -+ if (audio->format == AFMT_I2S) -+ cdns_mhdp_audio_config_i2s(mhdp, audio); -+ else if (audio->format == AFMT_SPDIF_INT) -+ cdns_mhdp_audio_config_spdif(mhdp); -+ -+ if (audio->connector_type == DRM_MODE_CONNECTOR_DisplayPort) -+ ret = cdns_mhdp_reg_write(mhdp, AUDIO_PACK_CONTROL, AUDIO_PACK_EN); -+ -+ if (audio->connector_type == DRM_MODE_CONNECTOR_HDMIA) -+ hdmi_audio_avi_set(mhdp, audio->channels); -+ -+err_audio_config: -+ if (ret) -+ DRM_DEV_ERROR(mhdp->dev, "audio config failed: %d\n", ret); -+ return ret; -+} -+EXPORT_SYMBOL(cdns_mhdp_audio_config); -+ -+static int audio_hw_params(struct device *dev, void *data, -+ struct hdmi_codec_daifmt *daifmt, -+ struct hdmi_codec_params *params) -+{ -+ struct cdns_mhdp_device *mhdp = dev_get_drvdata(dev); -+ struct audio_info audio = { -+ .sample_width = params->sample_width, -+ .sample_rate = params->sample_rate, -+ .channels = params->channels, -+ .connector_type = mhdp->connector.base.connector_type, -+ }; -+ int ret; -+ -+ switch (daifmt->fmt) { -+ case HDMI_I2S: -+ audio.format = AFMT_I2S; -+ break; -+ case HDMI_SPDIF: -+ audio.format = AFMT_SPDIF_EXT; -+ break; -+ default: -+ DRM_DEV_ERROR(dev, "Invalid format %d\n", daifmt->fmt); -+ ret = -EINVAL; -+ goto out; -+ } -+ -+ ret = cdns_mhdp_audio_config(mhdp, &audio); -+ if (!ret) -+ mhdp->audio_info = audio; -+ -+out: -+ return ret; -+} -+ -+static void audio_shutdown(struct device *dev, void *data) -+{ -+ struct cdns_mhdp_device *mhdp = dev_get_drvdata(dev); -+ int ret; -+ -+ ret = cdns_mhdp_audio_stop(mhdp, &mhdp->audio_info); -+ if (!ret) -+ mhdp->audio_info.format = AFMT_UNUSED; -+} -+ -+static int audio_digital_mute(struct device *dev, void *data, -+ bool enable) -+{ -+ struct cdns_mhdp_device *mhdp = dev_get_drvdata(dev); -+ int ret; -+ -+ ret = cdns_mhdp_audio_mute(mhdp, enable); -+ -+ return ret; -+} -+ -+static int audio_get_eld(struct device *dev, void *data, -+ u8 *buf, size_t len) -+{ -+ struct cdns_mhdp_device *mhdp = dev_get_drvdata(dev); -+ -+ memcpy(buf, mhdp->connector.base.eld, -+ min(sizeof(mhdp->connector.base.eld), len)); -+ -+ return 0; -+} -+ -+static const struct hdmi_codec_ops audio_codec_ops = { -+ .hw_params = audio_hw_params, -+ .audio_shutdown = audio_shutdown, -+ .digital_mute = audio_digital_mute, -+ .get_eld = audio_get_eld, -+}; -+ -+int cdns_mhdp_register_audio_driver(struct device *dev) -+{ -+ struct cdns_mhdp_device *mhdp = dev_get_drvdata(dev); -+ struct hdmi_codec_pdata codec_data = { -+ .i2s = 1, -+ .spdif = 1, -+ .ops = &audio_codec_ops, -+ .max_i2s_channels = 8, -+ }; -+ -+ mhdp->audio_pdev = platform_device_register_data( -+ dev, HDMI_CODEC_DRV_NAME, 1, -+ &codec_data, sizeof(codec_data)); -+ -+ return PTR_ERR_OR_ZERO(mhdp->audio_pdev); -+} -+ -+void cdns_mhdp_unregister_audio_driver(struct device *dev) -+{ -+ struct cdns_mhdp_device *mhdp = dev_get_drvdata(dev); -+ -+ platform_device_unregister(mhdp->audio_pdev); -+} ---- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c -+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp-common.c -@@ -937,189 +937,6 @@ err_config_video: - } - EXPORT_SYMBOL(cdns_mhdp_config_video); - --int cdns_mhdp_audio_stop(struct cdns_mhdp_device *mhdp, -- struct audio_info *audio) --{ -- int ret; -- -- ret = cdns_mhdp_reg_write(mhdp, AUDIO_PACK_CONTROL, 0); -- if (ret) { -- DRM_DEV_ERROR(mhdp->dev, "audio stop failed: %d\n", ret); -- return ret; -- } -- -- cdns_mhdp_bus_write(0, mhdp, SPDIF_CTRL_ADDR); -- -- /* clearn the audio config and reset */ -- cdns_mhdp_bus_write(0, mhdp, AUDIO_SRC_CNTL); -- cdns_mhdp_bus_write(0, mhdp, AUDIO_SRC_CNFG); -- cdns_mhdp_bus_write(AUDIO_SW_RST, mhdp, AUDIO_SRC_CNTL); -- cdns_mhdp_bus_write(0, mhdp, AUDIO_SRC_CNTL); -- -- /* reset smpl2pckt component */ -- cdns_mhdp_bus_write(0, mhdp, SMPL2PKT_CNTL); -- cdns_mhdp_bus_write(AUDIO_SW_RST, mhdp, SMPL2PKT_CNTL); -- cdns_mhdp_bus_write(0, mhdp, SMPL2PKT_CNTL); -- -- /* reset FIFO */ -- cdns_mhdp_bus_write(AUDIO_SW_RST, mhdp, FIFO_CNTL); -- cdns_mhdp_bus_write(0, mhdp, FIFO_CNTL); -- -- if (audio->format == AFMT_SPDIF_INT) -- clk_disable_unprepare(mhdp->spdif_clk); -- -- return 0; --} --EXPORT_SYMBOL(cdns_mhdp_audio_stop); -- --int cdns_mhdp_audio_mute(struct cdns_mhdp_device *mhdp, bool enable) --{ -- int ret; -- -- ret = cdns_mhdp_reg_write_bit(mhdp, DP_VB_ID, 4, 1, enable); -- if (ret) -- DRM_DEV_ERROR(mhdp->dev, "audio mute failed: %d\n", ret); -- -- return ret; --} --EXPORT_SYMBOL(cdns_mhdp_audio_mute); -- --static void cdns_mhdp_audio_config_i2s(struct cdns_mhdp_device *mhdp, -- struct audio_info *audio) --{ -- int sub_pckt_num = 1, i2s_port_en_val = 0xf, i; -- u32 val; -- -- if (audio->channels == 2) { -- if (mhdp->dp.link.num_lanes == 1) -- sub_pckt_num = 2; -- else -- sub_pckt_num = 4; -- -- i2s_port_en_val = 1; -- } else if (audio->channels == 4) { -- i2s_port_en_val = 3; -- } -- -- cdns_mhdp_bus_write(0x0, mhdp, SPDIF_CTRL_ADDR); -- -- cdns_mhdp_bus_write(SYNC_WR_TO_CH_ZERO, mhdp, FIFO_CNTL); -- -- val = MAX_NUM_CH(audio->channels); -- val |= NUM_OF_I2S_PORTS(audio->channels); -- val |= AUDIO_TYPE_LPCM; -- val |= CFG_SUB_PCKT_NUM(sub_pckt_num); -- cdns_mhdp_bus_write(val, mhdp, SMPL2PKT_CNFG); -- -- if (audio->sample_width == 16) -- val = 0; -- else if (audio->sample_width == 24) -- val = 1 << 9; -- else -- val = 2 << 9; -- -- val |= AUDIO_CH_NUM(audio->channels); -- val |= I2S_DEC_PORT_EN(i2s_port_en_val); -- val |= TRANS_SMPL_WIDTH_32; -- cdns_mhdp_bus_write(val, mhdp, AUDIO_SRC_CNFG); -- -- for (i = 0; i < (audio->channels + 1) / 2; i++) { -- if (audio->sample_width == 16) -- val = (0x02 << 8) | (0x02 << 20); -- else if (audio->sample_width == 24) -- val = (0x0b << 8) | (0x0b << 20); -- -- val |= ((2 * i) << 4) | ((2 * i + 1) << 16); -- cdns_mhdp_bus_write(val, mhdp, STTS_BIT_CH(i)); -- } -- -- switch (audio->sample_rate) { -- case 32000: -- val = SAMPLING_FREQ(3) | -- ORIGINAL_SAMP_FREQ(0xc); -- break; -- case 44100: -- val = SAMPLING_FREQ(0) | -- ORIGINAL_SAMP_FREQ(0xf); -- break; -- case 48000: -- val = SAMPLING_FREQ(2) | -- ORIGINAL_SAMP_FREQ(0xd); -- break; -- case 88200: -- val = SAMPLING_FREQ(8) | -- ORIGINAL_SAMP_FREQ(0x7); -- break; -- case 96000: -- val = SAMPLING_FREQ(0xa) | -- ORIGINAL_SAMP_FREQ(5); -- break; -- case 176400: -- val = SAMPLING_FREQ(0xc) | -- ORIGINAL_SAMP_FREQ(3); -- break; -- case 192000: -- val = SAMPLING_FREQ(0xe) | -- ORIGINAL_SAMP_FREQ(1); -- break; -- } -- val |= 4; -- cdns_mhdp_bus_write(val, mhdp, COM_CH_STTS_BITS); -- -- cdns_mhdp_bus_write(SMPL2PKT_EN, mhdp, SMPL2PKT_CNTL); -- cdns_mhdp_bus_write(I2S_DEC_START, mhdp, AUDIO_SRC_CNTL); --} -- --static void cdns_mhdp_audio_config_spdif(struct cdns_mhdp_device *mhdp) --{ -- u32 val; -- -- cdns_mhdp_bus_write(SYNC_WR_TO_CH_ZERO, mhdp, FIFO_CNTL); -- -- val = MAX_NUM_CH(2) | AUDIO_TYPE_LPCM | CFG_SUB_PCKT_NUM(4); -- cdns_mhdp_bus_write(val, mhdp, SMPL2PKT_CNFG); -- cdns_mhdp_bus_write(SMPL2PKT_EN, mhdp, SMPL2PKT_CNTL); -- -- val = SPDIF_ENABLE | SPDIF_AVG_SEL | SPDIF_JITTER_BYPASS; -- cdns_mhdp_bus_write(val, mhdp, SPDIF_CTRL_ADDR); -- -- clk_prepare_enable(mhdp->spdif_clk); -- clk_set_rate(mhdp->spdif_clk, CDNS_DP_SPDIF_CLK); --} -- --int cdns_mhdp_audio_config(struct cdns_mhdp_device *mhdp, -- struct audio_info *audio) --{ -- int ret; -- -- /* reset the spdif clk before config */ -- if (audio->format == AFMT_SPDIF_INT) { -- reset_control_assert(mhdp->spdif_rst); -- reset_control_deassert(mhdp->spdif_rst); -- } -- -- ret = cdns_mhdp_reg_write(mhdp, CM_LANE_CTRL, LANE_REF_CYC); -- if (ret) -- goto err_audio_config; -- -- ret = cdns_mhdp_reg_write(mhdp, CM_CTRL, 0); -- if (ret) -- goto err_audio_config; -- -- if (audio->format == AFMT_I2S) -- cdns_mhdp_audio_config_i2s(mhdp, audio); -- else if (audio->format == AFMT_SPDIF_INT) -- cdns_mhdp_audio_config_spdif(mhdp); -- -- ret = cdns_mhdp_reg_write(mhdp, AUDIO_PACK_CONTROL, AUDIO_PACK_EN); -- --err_audio_config: -- if (ret) -- DRM_DEV_ERROR(mhdp->dev, "audio config failed: %d\n", ret); -- return ret; --} --EXPORT_SYMBOL(cdns_mhdp_audio_config); -- - int cdns_mhdp_adjust_lt(struct cdns_mhdp_device *mhdp, - u8 nlanes, u16 udelay, u8 *lanes_data, u8 *dpcd) - { ---- a/drivers/gpu/drm/imx/Kconfig -+++ b/drivers/gpu/drm/imx/Kconfig -@@ -45,6 +45,7 @@ config DRM_IMX_CDNS_MHDP - select DRM_CDNS_MHDP - select DRM_CDNS_DP - select DRM_CDNS_HDMI -+ select DRM_CDNS_AUDIO - depends on DRM_IMX - help - Choose this if you want to use HDMI on i.MX8. ---- a/include/drm/bridge/cdns-mhdp-common.h -+++ b/include/drm/bridge/cdns-mhdp-common.h -@@ -548,6 +548,7 @@ struct audio_info { - int sample_rate; - int channels; - int sample_width; -+ int connector_type; - }; - - enum vic_pxl_encoding_format { -@@ -670,11 +671,16 @@ int cdns_mhdp_get_edid_block(void *mhdp, - int cdns_mhdp_train_link(struct cdns_mhdp_device *mhdp); - int cdns_mhdp_set_video_status(struct cdns_mhdp_device *mhdp, int active); - int cdns_mhdp_config_video(struct cdns_mhdp_device *mhdp); -+ -+/* Audio */ - int cdns_mhdp_audio_stop(struct cdns_mhdp_device *mhdp, - struct audio_info *audio); - int cdns_mhdp_audio_mute(struct cdns_mhdp_device *mhdp, bool enable); - int cdns_mhdp_audio_config(struct cdns_mhdp_device *mhdp, - struct audio_info *audio); -+int cdns_mhdp_register_audio_driver(struct device *dev); -+void cdns_mhdp_unregister_audio_driver(struct device *dev); -+ - int cdns_mhdp_reg_read(struct cdns_mhdp_device *mhdp, u32 addr); - int cdns_mhdp_reg_write(struct cdns_mhdp_device *mhdp, u32 addr, u32 val); - int cdns_mhdp_reg_write_bit(struct cdns_mhdp_device *mhdp, u16 addr, |