Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2edd513e authored by Aravind Kumar's avatar Aravind Kumar
Browse files

ASoC: msm: spdif rx driver changes



New hardware for spdif rx has been added in mpq8092.
The changes register the platform driver and dai driver
for spdif rx. Add support in afe for the dai driver
to send clock configuration, channel status configuration
and spdif port configuration information and start the
spdif rx port. The changes enable PCM Audio playback
over spdif rx.

Change-Id: I70a30c8485a0abb1d248fe509d5b66a926997f88
Signed-off-by: default avatarAravind Kumar <akumark@codeaurora.org>
parent af83c6c7
Loading
Loading
Loading
Loading
+120 −1
Original line number Diff line number Diff line
/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -787,6 +787,7 @@ struct adm_cmd_connect_afe_port_v5 {
#define AFE_PORT_ID_SECONDARY_PCM_RX        0x100C
#define AFE_PORT_ID_SECONDARY_PCM_TX        0x100D
#define AFE_PORT_ID_MULTICHAN_HDMI_RX       0x100E
#define AFE_PORT_ID_SPDIF_RX                0x5000
#define  AFE_PORT_ID_RT_PROXY_PORT_001_RX   0x2000
#define  AFE_PORT_ID_RT_PROXY_PORT_001_TX   0x2001
#define AFE_PORT_ID_INTERNAL_BT_SCO_RX      0x3000
@@ -1409,6 +1410,123 @@ struct afe_param_id_i2s_cfg {
/*
 * This param id is used to configure PCM interface
 */

#define AFE_API_VERSION_SPDIF_CONFIG 0x1
#define AFE_API_VERSION_SPDIF_CH_STATUS_CONFIG 0x1
#define AFE_API_VERSION_SPDIF_CLK_CONFIG 0x1
#define AFE_CH_STATUS_A 1
#define AFE_CH_STATUS_B 2

#define AFE_PARAM_ID_SPDIF_CONFIG 0x00010244
#define AFE_PARAM_ID_CH_STATUS_CONFIG 0x00010245
#define AFE_PARAM_ID_SPDIF_CLK_CONFIG 0x00010246

#define AFE_PORT_CLK_ROOT_LPAPLL 0x3
#define AFE_PORT_CLK_ROOT_LPAQ6PLL   0x4

struct afe_param_id_spdif_cfg {
/* Minor version used for tracking the version of the SPDIF
 * configuration interface.
 * Supported values: #AFE_API_VERSION_SPDIF_CONFIG
 */
	u32	spdif_cfg_minor_version;

/* Sampling rate of the port.
 * Supported values:
 * - #AFE_PORT_SAMPLE_RATE_22_05K
 * - #AFE_PORT_SAMPLE_RATE_32K
 * - #AFE_PORT_SAMPLE_RATE_44_1K
 * - #AFE_PORT_SAMPLE_RATE_48K
 * - #AFE_PORT_SAMPLE_RATE_96K
 * - #AFE_PORT_SAMPLE_RATE_176_4K
 * - #AFE_PORT_SAMPLE_RATE_192K
 */
	u32	sample_rate;

/* data format
 * Supported values:
 * - #AFE_LINEAR_PCM_DATA
 * - #AFE_NON_LINEAR_DATA
 */
	u16	data_format;
/* Number of channels supported by the port
 * - PCM - 1, Compressed Case - 2
 */
	u16	num_channels;
/* Bit width of the sample.
 * Supported values: 16, 24
 */
	u16	bit_width;
/* This field must be set to zero. */
	u16	reserved;
} __packed;

struct afe_param_id_spdif_ch_status_cfg {
	u32 ch_status_cfg_minor_version;
/* Minor version used for tracking the version of channel
 * status configuration. Current supported version is 1
 */

	u32 status_type;
/* Indicate if the channel status is for channel A or B
 * Supported values:
 * - #AFE_CH_STATUS_A
 * - #AFE_CH_STATUS_B
 */

	u8 status_bits[24];
/* Channel status - 192 bits for channel
 * Byte ordering as defined by IEC60958-3
 */

	u8 status_mask[24];
/* Channel status with mask bits 1 will be applied.
 * Byte ordering as defined by IEC60958-3
 */
} __packed;

struct afe_param_id_spdif_clk_cfg {
	u32 clk_cfg_minor_version;
/* Minor version used for tracking the version of SPDIF
 * interface clock configuration. Current supported version
 * is 1
 */

	u32 clk_value;
/* Specifies the clock frequency in Hz to set
 * Supported values:
 * 0 - Disable the clock
 * 2 (byphase) * 32 (60958 subframe size) * sampling rate * 2
 * (channels A and B)
 */

	u32 clk_root;
/* Specifies SPDIF root clk source
 * Supported Values:
 * - #AFE_PORT_CLK_ROOT_LPAPLL
 * - #AFE_PORT_CLK_ROOT_LPAQ6PLL
 */
} __packed;

struct afe_spdif_clk_config_command {
	struct apr_hdr                    hdr;
	struct afe_port_cmd_set_param_v2  param;
	struct afe_port_param_data_v2     pdata;
	struct afe_param_id_spdif_clk_cfg clk_cfg;
} __packed;

struct afe_spdif_chstatus_config_command {
	struct apr_hdr                    hdr;
	struct afe_port_cmd_set_param_v2  param;
	struct afe_port_param_data_v2     pdata;
	struct afe_param_id_spdif_ch_status_cfg ch_status;
} __packed;

struct afe_spdif_port_config {
	struct afe_param_id_spdif_cfg            cfg;
	struct afe_param_id_spdif_ch_status_cfg  ch_status;
} __packed;

#define AFE_PARAM_ID_PCM_CONFIG        0x0001020E
#define AFE_API_VERSION_PCM_CONFIG	0x1
/* Enumeration for the auxiliary PCM synchronization signal
@@ -2015,6 +2133,7 @@ union afe_port_config {
	struct afe_param_id_internal_bt_fm_cfg    int_bt_fm;
	struct afe_param_id_pseudo_port_cfg       pseudo_port;
	struct afe_param_id_device_hw_delay_cfg   hw_delay;
	struct afe_param_id_spdif_cfg             spdif;
} __packed;

struct afe_audioif_config_command_no_payload {
+10 −1
Original line number Diff line number Diff line
/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -86,6 +86,7 @@ enum {
	IDX_VOICE2_PLAYBACK_TX = 44,
	IDX_SLIMBUS_6_RX = 45,
	IDX_SLIMBUS_6_TX = 46,
	IDX_SPDIF_RX = 47,
	IDX_GLOBAL_CFG,
	IDX_AUDIO_PORT_ID_I2S_RX,
	AFE_MAX_PORTS
@@ -197,6 +198,14 @@ int afe_set_lpass_internal_digital_codec_clock(u16 port_id,
				struct afe_digital_clk_cfg *cfg);
int q6afe_check_osr_clk_freq(u32 freq);

int afe_send_spdif_clk_cfg(struct afe_param_id_spdif_clk_cfg *cfg,
		u16 port_id);
int afe_send_spdif_ch_status_cfg(struct afe_param_id_spdif_ch_status_cfg
		*ch_status_cfg,	u16 port_id);

int afe_spdif_port_start(u16 port_id, struct afe_spdif_port_config *spdif_port,
		u32 rate);

int afe_turn_onoff_hw_mad(u16 mad_type, u16 mad_enable);
int afe_port_set_mad_type(u16 port_id, enum afe_mad_type mad_type);
enum afe_mad_type afe_port_get_mad_type(u16 port_id);
+331 −1
Original line number Diff line number Diff line
/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -31,6 +31,11 @@
#define MSM_DAI_PRI_AUXPCM_DT_DEV_ID 1
#define MSM_DAI_SEC_AUXPCM_DT_DEV_ID 2

#define spdif_clock_value(rate) (2*rate*32*2)
#define CHANNEL_STATUS_SIZE 24
#define CHANNEL_STATUS_MASK_INIT 0x0
#define CHANNEL_STATUS_MASK 0x4

static const struct afe_clk_cfg lpass_clk_cfg_default = {
	AFE_API_VERSION_I2S_CONFIG,
	Q6AFE_LPASS_OSR_CLK_2_P048_MHZ,
@@ -63,6 +68,14 @@ struct msm_dai_q6_dai_data {
	union afe_port_config port_config;
};

struct msm_dai_q6_spdif_dai_data {
	DECLARE_BITMAP(status_mask, STATUS_MAX);
	u32 rate;
	u32 channels;
	u32 bitwidth;
	struct afe_spdif_port_config spdif_port;
};

struct msm_dai_q6_mi2s_dai_config {
	u16 pdata_mi2s_lines;
	struct msm_dai_q6_dai_data mi2s_dai_data;
@@ -527,6 +540,274 @@ static struct snd_soc_dai_driver msm_dai_q6_aux_pcm_dai[] = {
	}
};

static int msm_dai_q6_spdif_format_put(struct snd_kcontrol *kcontrol,
		struct snd_ctl_elem_value *ucontrol)
{

	struct msm_dai_q6_spdif_dai_data *dai_data = kcontrol->private_data;
	int value = ucontrol->value.integer.value[0];
	dai_data->spdif_port.cfg.data_format = value;
	pr_debug("%s: value = %d\n", __func__, value);
	return 0;
}

static int msm_dai_q6_spdif_format_get(struct snd_kcontrol *kcontrol,
		struct snd_ctl_elem_value *ucontrol)
{

	struct msm_dai_q6_spdif_dai_data *dai_data = kcontrol->private_data;
	ucontrol->value.integer.value[0] =
		dai_data->spdif_port.cfg.data_format;
	return 0;
}

static const char * const spdif_format[] = {
	"LPCM",
	"Compr"
};

static const struct soc_enum spdif_config_enum[] = {
	SOC_ENUM_SINGLE_EXT(2, spdif_format),
};

static int msm_dai_q6_spdif_chstatus_put(struct snd_kcontrol *kcontrol,
		struct snd_ctl_elem_value *ucontrol)
{
	struct msm_dai_q6_spdif_dai_data *dai_data = kcontrol->private_data;
	int ret = 0;

	dai_data->spdif_port.ch_status.status_type =
		AFE_API_VERSION_SPDIF_CH_STATUS_CONFIG;
	memset(dai_data->spdif_port.ch_status.status_mask,
			CHANNEL_STATUS_MASK_INIT, CHANNEL_STATUS_SIZE);
	dai_data->spdif_port.ch_status.status_mask[0] =
		CHANNEL_STATUS_MASK;

	memcpy(dai_data->spdif_port.ch_status.status_bits,
			ucontrol->value.iec958.status, CHANNEL_STATUS_SIZE);

	if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
		pr_debug("%s: Port already started. Dynamic update\n",
				__func__);
		ret = afe_send_spdif_ch_status_cfg(
				&dai_data->spdif_port.ch_status,
				AFE_PORT_ID_SPDIF_RX);
	}
	return ret;
}

static int msm_dai_q6_spdif_chstatus_get(struct snd_kcontrol *kcontrol,
		struct snd_ctl_elem_value *ucontrol)
{

	struct msm_dai_q6_spdif_dai_data *dai_data = kcontrol->private_data;
	memcpy(ucontrol->value.iec958.status,
			dai_data->spdif_port.ch_status.status_bits,
			CHANNEL_STATUS_SIZE);
	return 0;
}

static int msm_dai_q6_spdif_chstatus_info(struct snd_kcontrol *kcontrol,
		struct snd_ctl_elem_info *uinfo)
{
	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
	uinfo->count = 1;
	return 0;
}

static const struct snd_kcontrol_new spdif_config_controls[] = {
	{
		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
				SNDRV_CTL_ELEM_ACCESS_INACTIVE),
		.iface  =   SNDRV_CTL_ELEM_IFACE_PCM,
		.name   =   SNDRV_CTL_NAME_IEC958("", PLAYBACK, PCM_STREAM),
		.info   =   msm_dai_q6_spdif_chstatus_info,
		.get    =   msm_dai_q6_spdif_chstatus_get,
		.put    =   msm_dai_q6_spdif_chstatus_put,
	},
	SOC_ENUM_EXT("SPDIF RX Format", spdif_config_enum[0],
			msm_dai_q6_spdif_format_get,
			msm_dai_q6_spdif_format_put)
};


static int msm_dai_q6_spdif_hw_params(struct snd_pcm_substream *substream,
		struct snd_pcm_hw_params *params,
		struct snd_soc_dai *dai)
{
	struct msm_dai_q6_spdif_dai_data *dai_data = dev_get_drvdata(dai->dev);

	dai->id = AFE_PORT_ID_SPDIF_RX;
	dai_data->channels = params_channels(params);
	dai_data->spdif_port.cfg.num_channels = dai_data->channels;
	switch (params_format(params)) {
	case SNDRV_PCM_FORMAT_S16_LE:
		dai_data->spdif_port.cfg.bit_width = 16;
		break;
	case SNDRV_PCM_FORMAT_S24_LE:
		dai_data->spdif_port.cfg.bit_width = 24;
		break;
	default:
		return -EINVAL;
	}

	dai_data->rate = params_rate(params);
	dai_data->bitwidth = dai_data->spdif_port.cfg.bit_width;
	dai_data->spdif_port.cfg.sample_rate = dai_data->rate;
	dai_data->spdif_port.cfg.spdif_cfg_minor_version =
		AFE_API_VERSION_SPDIF_CONFIG;
	dev_dbg(dai->dev, " channel %d sample rate %d bit width %d\n",
			dai_data->channels, dai_data->rate,
			dai_data->spdif_port.cfg.bit_width);
	dai_data->spdif_port.cfg.reserved = 0;
	return 0;
}

static void msm_dai_q6_spdif_shutdown(struct snd_pcm_substream *substream,
		struct snd_soc_dai *dai)
{
	struct msm_dai_q6_spdif_dai_data *dai_data = dev_get_drvdata(dai->dev);
	int rc = 0;

	if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
		pr_info("%s:  afe port not started. dai_data->status_mask = %ld\n",
				__func__, *dai_data->status_mask);
		return;
	}

	rc = afe_close(dai->id);

	if (IS_ERR_VALUE(rc))
		dev_err(dai->dev, "fail to close AFE port\n");

	pr_debug("%s: dai_data->status_mask = %ld\n", __func__,
			*dai_data->status_mask);

	clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
}


static int msm_dai_q6_spdif_prepare(struct snd_pcm_substream *substream,
		struct snd_soc_dai *dai)
{
	struct msm_dai_q6_spdif_dai_data *dai_data = dev_get_drvdata(dai->dev);
	int rc = 0;

	if (IS_ERR_VALUE(rc)) {
		dev_err(dai->dev, "%s clk_config failed", __func__);
		return rc;
	}
	if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
		rc = afe_spdif_port_start(dai->id, &dai_data->spdif_port,
				dai_data->rate);
		if (IS_ERR_VALUE(rc))
			dev_err(dai->dev, "fail to open AFE port %x\n",
					dai->id);
		else
			set_bit(STATUS_PORT_STARTED,
					dai_data->status_mask);
	}

	return rc;
}

static int msm_dai_q6_spdif_dai_probe(struct snd_soc_dai *dai)
{
	struct msm_dai_q6_spdif_dai_data *dai_data;
	const struct snd_kcontrol_new *kcontrol;
	int rc = 0;
	struct snd_soc_dapm_route intercon;
	dai_data = kzalloc(sizeof(struct msm_dai_q6_spdif_dai_data),
			GFP_KERNEL);

	if (!dai_data) {
		dev_err(dai->dev, "DAI-%d: fail to allocate dai data\n",
				AFE_PORT_ID_SPDIF_RX);
		rc = -ENOMEM;
	} else
		rc = dev_set_drvdata(dai->dev, dai_data);

	kcontrol = &spdif_config_controls[1];

	rc = snd_ctl_add(dai->card->snd_card,
			snd_ctl_new1(kcontrol, dai_data));

	memset(&intercon, 0 , sizeof(intercon));
	if (!rc && dai && dai->driver) {
		if (dai->driver->playback.stream_name &&
				dai->driver->playback.aif_name) {
			dev_dbg(dai->dev, "%s add route for widget %s",
				__func__, dai->driver->playback.stream_name);
			intercon.source = dai->driver->playback.aif_name;
			intercon.sink = dai->driver->playback.stream_name;
			dev_dbg(dai->dev, "%s src %s sink %s\n",
				__func__, intercon.source, intercon.sink);
			snd_soc_dapm_add_routes(&dai->dapm, &intercon, 1);
		}
		if (dai->driver->capture.stream_name &&
				dai->driver->capture.aif_name) {
			dev_dbg(dai->dev, "%s add route for widget %s",
				__func__, dai->driver->capture.stream_name);
			intercon.sink = dai->driver->capture.aif_name;
			intercon.source = dai->driver->capture.stream_name;
			dev_dbg(dai->dev, "%s src %s sink %s\n",
				__func__, intercon.source, intercon.sink);
			snd_soc_dapm_add_routes(&dai->dapm, &intercon, 1);
		}
	}
	return rc;
}

static int msm_dai_q6_spdif_dai_remove(struct snd_soc_dai *dai)
{
	struct msm_dai_q6_spdif_dai_data *dai_data;
	int rc;

	dai_data = dev_get_drvdata(dai->dev);

	/* If AFE port is still up, close it */
	if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
		rc = afe_close(dai->id); /* can block */

		if (IS_ERR_VALUE(rc))
			dev_err(dai->dev, "fail to close AFE port\n");

		clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
	}
	kfree(dai_data);
	snd_soc_unregister_component(dai->dev);

	return 0;
}


static struct snd_soc_dai_ops msm_dai_q6_spdif_ops = {
	.prepare	= msm_dai_q6_spdif_prepare,
	.hw_params	= msm_dai_q6_spdif_hw_params,
	.shutdown	= msm_dai_q6_spdif_shutdown,
};

static struct snd_soc_dai_driver msm_dai_q6_spdif_spdif_rx_dai = {
	.playback = {
		.stream_name = "SPDIF Playback",
		.aif_name = "SPDIF_RX",
		.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
			SNDRV_PCM_RATE_16000,
		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
		.channels_min = 1,
		.channels_max = 4,
		.rate_min = 8000,
		.rate_max = 48000,
	},
	.ops = &msm_dai_q6_spdif_ops,
	.probe = msm_dai_q6_spdif_dai_probe,
	.remove = msm_dai_q6_spdif_dai_remove,
};

static const struct snd_soc_component_driver msm_dai_spdif_q6_component = {
	.name		= "msm-dai-q6-spdif",
};

static int msm_dai_q6_prepare(struct snd_pcm_substream *substream,
		struct snd_soc_dai *dai)
{
@@ -2668,6 +2949,46 @@ static struct platform_driver msm_dai_q6_mi2s_driver = {
	},
};

static int msm_dai_q6_spdif_dev_probe(struct platform_device *pdev)
{
	int rc;

	pdev->id = AFE_PORT_ID_SPDIF_RX;
	dev_set_name(&pdev->dev, "%s", "msm-dai-q6-spdif");

	pr_debug("%s: dev name %s, id:%d\n", __func__,
			dev_name(&pdev->dev), pdev->id);

	rc = snd_soc_register_component(&pdev->dev,
			&msm_dai_spdif_q6_component,
			&msm_dai_q6_spdif_spdif_rx_dai, 1);
	return rc;
}

static int msm_dai_q6_spdif_dev_remove(struct platform_device *pdev)
{
	snd_soc_unregister_component(&pdev->dev);
	return 0;
}

static const struct of_device_id msm_dai_q6_spdif_dt_match[] = {
	{.compatible = "qcom,msm-dai-q6-spdif"},
	{}
};
MODULE_DEVICE_TABLE(of, msm_dai_q6_spdif_dt_match);

static struct platform_driver msm_dai_q6_spdif_driver = {
	.probe  = msm_dai_q6_spdif_dev_probe,
	.remove = msm_dai_q6_spdif_dev_remove,
	.driver = {
		.name = "msm-dai-q6-spdif",
		.owner = THIS_MODULE,
		.of_match_table = msm_dai_q6_spdif_dt_match,
	},
};



static int __init msm_dai_q6_init(void)
{
	int rc;
@@ -2701,8 +3022,16 @@ static int __init msm_dai_q6_init(void)
		pr_err("%s: fail to register dai MI2S\n", __func__);
		goto dai_mi2s_q6_fail;
	}

	rc = platform_driver_register(&msm_dai_q6_spdif_driver);
	if (rc) {
		pr_err("%s: fail to register dai SPDIF\n", __func__);
		goto dai_spdif_q6_fail;
	}
	return rc;

dai_spdif_q6_fail:
	platform_driver_unregister(&msm_dai_q6_spdif_driver);
dai_mi2s_q6_fail:
	platform_driver_unregister(&msm_dai_q6_mi2s_driver);
dai_q6_mi2s_drv_fail:
@@ -2721,6 +3050,7 @@ static void __exit msm_dai_q6_exit(void)
	platform_driver_unregister(&msm_dai_q6_dev);
	platform_driver_unregister(&msm_dai_q6);
	platform_driver_unregister(&msm_auxpcm_dev_driver);
	platform_driver_unregister(&msm_dai_q6_spdif_driver);
}
module_exit(msm_dai_q6_exit);

+46 −0
Original line number Diff line number Diff line
@@ -254,6 +254,7 @@ static struct msm_pcm_routing_bdai_data msm_bedais[MSM_BACKEND_DAI_MAX] = {
	{ AFE_PORT_ID_SECONDARY_PCM_TX,   0, 0, 0, 0, 0},
	{ SLIMBUS_6_RX, 0, 0, 0, 0, 0},
	{ SLIMBUS_6_TX, 0, 0, 0, 0, 0},
	{ AFE_PORT_ID_SPDIF_RX, 0, 0, 0, 0, 0},
};


@@ -1644,6 +1645,36 @@ static const struct snd_kcontrol_new sec_i2s_rx_mixer_controls[] = {
	msm_routing_put_audio_mixer),
};

static const struct snd_kcontrol_new spdif_rx_mixer_controls[] = {
	SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_SPDIF_RX ,
	MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
	msm_routing_put_audio_mixer),
	SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_SPDIF_RX,
	MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
	msm_routing_put_audio_mixer),
	SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_SPDIF_RX,
	MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
	msm_routing_put_audio_mixer),
	SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_SPDIF_RX,
	MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
	msm_routing_put_audio_mixer),
	SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_SPDIF_RX,
	MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
	msm_routing_put_audio_mixer),
	SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_SPDIF_RX,
	MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer,
	msm_routing_put_audio_mixer),
	SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_SPDIF_RX,
	MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer,
	msm_routing_put_audio_mixer),
	SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_SPDIF_RX,
	MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
	msm_routing_put_audio_mixer),
	SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_SPDIF_RX,
	MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
	msm_routing_put_audio_mixer),
};

static const struct snd_kcontrol_new slimbus_rx_mixer_controls[] = {
	SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_SLIMBUS_0_RX ,
	MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
@@ -3453,6 +3484,7 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = {
	SND_SOC_DAPM_AIF_OUT("PRI_I2S_RX", "Primary I2S Playback", 0, 0, 0, 0),
	SND_SOC_DAPM_AIF_OUT("SEC_I2S_RX", "Secondary I2S Playback",
				0, 0, 0 , 0),
	SND_SOC_DAPM_AIF_OUT("SPDIF_RX", "SPDIF Playback", 0, 0, 0 , 0),
	SND_SOC_DAPM_AIF_OUT("SLIMBUS_0_RX", "Slimbus Playback", 0, 0, 0, 0),
	SND_SOC_DAPM_AIF_OUT("HDMI", "HDMI Playback", 0, 0, 0 , 0),
	SND_SOC_DAPM_AIF_OUT("MI2S_RX", "MI2S Playback", 0, 0, 0, 0),
@@ -3549,6 +3581,8 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = {
	slimbus_rx_mixer_controls, ARRAY_SIZE(slimbus_rx_mixer_controls)),
	SND_SOC_DAPM_MIXER("HDMI Mixer", SND_SOC_NOPM, 0, 0,
	hdmi_mixer_controls, ARRAY_SIZE(hdmi_mixer_controls)),
	SND_SOC_DAPM_MIXER("SPDIF_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
	spdif_rx_mixer_controls, ARRAY_SIZE(spdif_rx_mixer_controls)),
	SND_SOC_DAPM_MIXER("MI2S_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
	mi2s_rx_mixer_controls, ARRAY_SIZE(mi2s_rx_mixer_controls)),
	SND_SOC_DAPM_MIXER("QUAT_MI2S_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
@@ -3758,6 +3792,17 @@ static const struct snd_soc_dapm_route intercon[] = {
	{"HDMI Mixer", "MultiMedia9", "MM_DL9"},
	{"HDMI", NULL, "HDMI Mixer"},

	{"SPDIF_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
	{"SPDIF_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
	{"SPDIF_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
	{"SPDIF_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
	{"SPDIF_RX Audio Mixer", "MultiMedia5", "MM_DL5"},
	{"SPDIF_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
	{"SPDIF_RX Audio Mixer", "MultiMedia7", "MM_DL7"},
	{"SPDIF_RX Audio Mixer", "MultiMedia8", "MM_DL8"},
	{"SPDIF_RX Audio Mixer", "MultiMedia9", "MM_DL9"},
	{"SPDIF_RX", NULL, "SPDIF_RX Audio Mixer"},

		/* incall */
	{"Incall_Music Audio Mixer", "MultiMedia1", "MM_DL1"},
	{"Incall_Music Audio Mixer", "MultiMedia2", "MM_DL2"},
@@ -4212,6 +4257,7 @@ static const struct snd_soc_dapm_route intercon[] = {
	{"BE_OUT", NULL, "SLIMBUS_4_RX"},
	{"BE_OUT", NULL, "SLIMBUS_6_RX"},
	{"BE_OUT", NULL, "HDMI"},
	{"BE_OUT", NULL, "SPDIF_RX"},
	{"BE_OUT", NULL, "MI2S_RX"},
	{"BE_OUT", NULL, "QUAT_MI2S_RX"},
	{"BE_OUT", NULL, "TERT_MI2S_RX"},
+2 −0
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@
#define LPASS_BE_INCALL_RECORD_RX "INCALL_RECORD_TX"
#define LPASS_BE_INCALL_RECORD_TX "INCALL_RECORD_RX"
#define LPASS_BE_SEC_I2S_RX "SECONDARY_I2S_RX"
#define LPASS_BE_SPDIF_RX "SPDIF_RX"

#define LPASS_BE_MI2S_RX "MI2S_RX"
#define LPASS_BE_MI2S_TX "MI2S_TX"
@@ -135,6 +136,7 @@ enum {
	MSM_BACKEND_DAI_SEC_AUXPCM_TX,
	MSM_BACKEND_DAI_SLIMBUS_6_RX,
	MSM_BACKEND_DAI_SLIMBUS_6_TX,
	MSM_BACKEND_DAI_SPDIF_RX,
	MSM_BACKEND_DAI_MAX,
};

Loading