brintos

brintos / linux-shallow public Read only

0
0
Text · 33.3 KiB · 7d9628c Raw
1088 lines · c
1// SPDX-License-Identifier: GPL-2.02// Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.3// Copyright (c) 2018, Linaro Limited4 5#include <dt-bindings/sound/qcom,q6afe.h>6#include <linux/err.h>7#include <linux/init.h>8#include <linux/module.h>9#include <linux/device.h>10#include <linux/platform_device.h>11#include <linux/slab.h>12#include <sound/pcm.h>13#include <sound/soc.h>14#include <sound/pcm_params.h>15#include "q6dsp-lpass-ports.h"16#include "q6dsp-common.h"17#include "q6afe.h"18 19 20struct q6afe_dai_priv_data {21	uint32_t sd_line_mask;22	uint32_t sync_mode;23	uint32_t sync_src;24	uint32_t data_out_enable;25	uint32_t invert_sync;26	uint32_t data_delay;27	uint32_t data_align;28};29 30struct q6afe_dai_data {31	struct q6afe_port *port[AFE_PORT_MAX];32	struct q6afe_port_config port_config[AFE_PORT_MAX];33	bool is_port_started[AFE_PORT_MAX];34	struct q6afe_dai_priv_data priv[AFE_PORT_MAX];35};36 37static int q6slim_hw_params(struct snd_pcm_substream *substream,38			    struct snd_pcm_hw_params *params,39			    struct snd_soc_dai *dai)40{41 42	struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);43	struct q6afe_slim_cfg *slim = &dai_data->port_config[dai->id].slim;44 45	slim->sample_rate = params_rate(params);46 47	switch (params_format(params)) {48	case SNDRV_PCM_FORMAT_S16_LE:49	case SNDRV_PCM_FORMAT_SPECIAL:50		slim->bit_width = 16;51		break;52	case SNDRV_PCM_FORMAT_S24_LE:53		slim->bit_width = 24;54		break;55	case SNDRV_PCM_FORMAT_S32_LE:56		slim->bit_width = 32;57		break;58	default:59		pr_err("%s: format %d\n",60			__func__, params_format(params));61		return -EINVAL;62	}63 64	return 0;65}66 67static int q6hdmi_hw_params(struct snd_pcm_substream *substream,68				struct snd_pcm_hw_params *params,69				struct snd_soc_dai *dai)70{71	struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);72	int channels = params_channels(params);73	struct q6afe_hdmi_cfg *hdmi = &dai_data->port_config[dai->id].hdmi;74	int ret;75 76	hdmi->sample_rate = params_rate(params);77	switch (params_format(params)) {78	case SNDRV_PCM_FORMAT_S16_LE:79		hdmi->bit_width = 16;80		break;81	case SNDRV_PCM_FORMAT_S24_LE:82		hdmi->bit_width = 24;83		break;84	}85 86	ret = q6dsp_get_channel_allocation(channels);87	if (ret < 0)88		return ret;89 90	hdmi->channel_allocation = (u16) ret;91 92	return 0;93}94 95static int q6i2s_hw_params(struct snd_pcm_substream *substream,96			   struct snd_pcm_hw_params *params,97			   struct snd_soc_dai *dai)98{99	struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);100	struct q6afe_i2s_cfg *i2s = &dai_data->port_config[dai->id].i2s_cfg;101 102	i2s->sample_rate = params_rate(params);103	i2s->bit_width = params_width(params);104	i2s->num_channels = params_channels(params);105	i2s->sd_line_mask = dai_data->priv[dai->id].sd_line_mask;106 107	return 0;108}109 110static int q6i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)111{112	struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);113	struct q6afe_i2s_cfg *i2s = &dai_data->port_config[dai->id].i2s_cfg;114 115	i2s->fmt = fmt;116 117	return 0;118}119 120static int q6tdm_set_tdm_slot(struct snd_soc_dai *dai,121				unsigned int tx_mask,122				unsigned int rx_mask,123				int slots, int slot_width)124{125 126	struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);127	struct q6afe_tdm_cfg *tdm = &dai_data->port_config[dai->id].tdm;128	unsigned int cap_mask;129	int rc = 0;130 131	/* HW only supports 16 and 32 bit slot width configuration */132	if ((slot_width != 16) && (slot_width != 32)) {133		dev_err(dai->dev, "%s: invalid slot_width %d\n",134			__func__, slot_width);135		return -EINVAL;136	}137 138	/* HW supports 1-32 slots configuration. Typical: 1, 2, 4, 8, 16, 32 */139	switch (slots) {140	case 2:141		cap_mask = 0x03;142		break;143	case 4:144		cap_mask = 0x0F;145		break;146	case 8:147		cap_mask = 0xFF;148		break;149	case 16:150		cap_mask = 0xFFFF;151		break;152	default:153		dev_err(dai->dev, "%s: invalid slots %d\n",154			__func__, slots);155		return -EINVAL;156	}157 158	switch (dai->id) {159	case PRIMARY_TDM_RX_0 ... QUINARY_TDM_TX_7:160		tdm->nslots_per_frame = slots;161		tdm->slot_width = slot_width;162		/* TDM RX dais ids are even and tx are odd */163		tdm->slot_mask = ((dai->id & 0x1) ? tx_mask : rx_mask) & cap_mask;164		break;165	default:166		dev_err(dai->dev, "%s: invalid dai id 0x%x\n",167			__func__, dai->id);168		return -EINVAL;169	}170 171	return rc;172}173 174static int q6tdm_set_channel_map(struct snd_soc_dai *dai,175				unsigned int tx_num, const unsigned int *tx_slot,176				unsigned int rx_num, const unsigned int *rx_slot)177{178 179	struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);180	struct q6afe_tdm_cfg *tdm = &dai_data->port_config[dai->id].tdm;181	int rc = 0;182	int i = 0;183 184	switch (dai->id) {185	case PRIMARY_TDM_RX_0 ... QUINARY_TDM_TX_7:186		if (dai->id & 0x1) {187			if (!tx_slot) {188				dev_err(dai->dev, "tx slot not found\n");189				return -EINVAL;190			}191			if (tx_num > AFE_PORT_MAX_AUDIO_CHAN_CNT) {192				dev_err(dai->dev, "invalid tx num %d\n",193					tx_num);194				return -EINVAL;195			}196 197			for (i = 0; i < tx_num; i++)198				tdm->ch_mapping[i] = tx_slot[i];199 200			for (i = tx_num; i < AFE_PORT_MAX_AUDIO_CHAN_CNT; i++)201				tdm->ch_mapping[i] = Q6AFE_CMAP_INVALID;202 203			tdm->num_channels = tx_num;204		} else {205			/* rx */206			if (!rx_slot) {207				dev_err(dai->dev, "rx slot not found\n");208				return -EINVAL;209			}210			if (rx_num > AFE_PORT_MAX_AUDIO_CHAN_CNT) {211				dev_err(dai->dev, "invalid rx num %d\n",212					rx_num);213				return -EINVAL;214			}215 216			for (i = 0; i < rx_num; i++)217				tdm->ch_mapping[i] = rx_slot[i];218 219			for (i = rx_num; i < AFE_PORT_MAX_AUDIO_CHAN_CNT; i++)220				tdm->ch_mapping[i] = Q6AFE_CMAP_INVALID;221 222			tdm->num_channels = rx_num;223		}224 225		break;226	default:227		dev_err(dai->dev, "%s: invalid dai id 0x%x\n",228			__func__, dai->id);229		return -EINVAL;230	}231 232	return rc;233}234 235static int q6tdm_hw_params(struct snd_pcm_substream *substream,236			   struct snd_pcm_hw_params *params,237			   struct snd_soc_dai *dai)238{239	struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);240	struct q6afe_tdm_cfg *tdm = &dai_data->port_config[dai->id].tdm;241 242	tdm->bit_width = params_width(params);243	tdm->sample_rate = params_rate(params);244	tdm->num_channels = params_channels(params);245	tdm->data_align_type = dai_data->priv[dai->id].data_align;246	tdm->sync_src = dai_data->priv[dai->id].sync_src;247	tdm->sync_mode = dai_data->priv[dai->id].sync_mode;248 249	return 0;250}251 252static int q6dma_set_channel_map(struct snd_soc_dai *dai,253				 unsigned int tx_num,254				 const unsigned int *tx_ch_mask,255				 unsigned int rx_num,256				 const unsigned int *rx_ch_mask)257{258 259	struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);260	struct q6afe_cdc_dma_cfg *cfg = &dai_data->port_config[dai->id].dma_cfg;261	int ch_mask;262	int rc = 0;263 264	switch (dai->id) {265	case WSA_CODEC_DMA_TX_0:266	case WSA_CODEC_DMA_TX_1:267	case WSA_CODEC_DMA_TX_2:268	case VA_CODEC_DMA_TX_0:269	case VA_CODEC_DMA_TX_1:270	case VA_CODEC_DMA_TX_2:271	case TX_CODEC_DMA_TX_0:272	case TX_CODEC_DMA_TX_1:273	case TX_CODEC_DMA_TX_2:274	case TX_CODEC_DMA_TX_3:275	case TX_CODEC_DMA_TX_4:276	case TX_CODEC_DMA_TX_5:277		if (!tx_ch_mask) {278			dev_err(dai->dev, "tx slot not found\n");279			return -EINVAL;280		}281 282		if (tx_num > AFE_PORT_MAX_AUDIO_CHAN_CNT) {283			dev_err(dai->dev, "invalid tx num %d\n",284				tx_num);285			return -EINVAL;286		}287		ch_mask = *tx_ch_mask;288 289		break;290	case WSA_CODEC_DMA_RX_0:291	case WSA_CODEC_DMA_RX_1:292	case RX_CODEC_DMA_RX_0:293	case RX_CODEC_DMA_RX_1:294	case RX_CODEC_DMA_RX_2:295	case RX_CODEC_DMA_RX_3:296	case RX_CODEC_DMA_RX_4:297	case RX_CODEC_DMA_RX_5:298	case RX_CODEC_DMA_RX_6:299	case RX_CODEC_DMA_RX_7:300		/* rx */301		if (!rx_ch_mask) {302			dev_err(dai->dev, "rx slot not found\n");303			return -EINVAL;304		}305		if (rx_num > AFE_PORT_MAX_AUDIO_CHAN_CNT) {306			dev_err(dai->dev, "invalid rx num %d\n",307				rx_num);308			return -EINVAL;309		}310		ch_mask = *rx_ch_mask;311 312		break;313	default:314		dev_err(dai->dev, "%s: invalid dai id 0x%x\n",315			__func__, dai->id);316		return -EINVAL;317	}318 319	cfg->active_channels_mask = ch_mask;320 321	return rc;322}323 324static int q6dma_hw_params(struct snd_pcm_substream *substream,325			   struct snd_pcm_hw_params *params,326			   struct snd_soc_dai *dai)327{328	struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);329	struct q6afe_cdc_dma_cfg *cfg = &dai_data->port_config[dai->id].dma_cfg;330 331	cfg->bit_width = params_width(params);332	cfg->sample_rate = params_rate(params);333	cfg->num_channels = params_channels(params);334 335	return 0;336}337static void q6afe_dai_shutdown(struct snd_pcm_substream *substream,338				struct snd_soc_dai *dai)339{340	struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);341	int rc;342 343	if (!dai_data->is_port_started[dai->id])344		return;345 346	rc = q6afe_port_stop(dai_data->port[dai->id]);347	if (rc < 0)348		dev_err(dai->dev, "fail to close AFE port (%d)\n", rc);349 350	dai_data->is_port_started[dai->id] = false;351 352}353 354static int q6afe_dai_prepare(struct snd_pcm_substream *substream,355		struct snd_soc_dai *dai)356{357	struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);358	int rc;359 360	if (dai_data->is_port_started[dai->id]) {361		/* stop the port and restart with new port config */362		rc = q6afe_port_stop(dai_data->port[dai->id]);363		if (rc < 0) {364			dev_err(dai->dev, "fail to close AFE port (%d)\n", rc);365			return rc;366		}367	}368 369	switch (dai->id) {370	case HDMI_RX:371	case DISPLAY_PORT_RX:372		q6afe_hdmi_port_prepare(dai_data->port[dai->id],373					&dai_data->port_config[dai->id].hdmi);374		break;375	case SLIMBUS_0_RX ... SLIMBUS_6_TX:376		q6afe_slim_port_prepare(dai_data->port[dai->id],377					&dai_data->port_config[dai->id].slim);378		break;379	case QUINARY_MI2S_RX ... QUINARY_MI2S_TX:380	case PRIMARY_MI2S_RX ... QUATERNARY_MI2S_TX:381		rc = q6afe_i2s_port_prepare(dai_data->port[dai->id],382			       &dai_data->port_config[dai->id].i2s_cfg);383		if (rc < 0) {384			dev_err(dai->dev, "fail to prepare AFE port %x\n",385				dai->id);386			return rc;387		}388		break;389	case PRIMARY_TDM_RX_0 ... QUINARY_TDM_TX_7:390		q6afe_tdm_port_prepare(dai_data->port[dai->id],391					&dai_data->port_config[dai->id].tdm);392		break;393	case WSA_CODEC_DMA_RX_0 ... RX_CODEC_DMA_RX_7:394		q6afe_cdc_dma_port_prepare(dai_data->port[dai->id],395					   &dai_data->port_config[dai->id].dma_cfg);396		break;397	default:398		return -EINVAL;399	}400 401	rc = q6afe_port_start(dai_data->port[dai->id]);402	if (rc < 0) {403		dev_err(dai->dev, "fail to start AFE port %x\n", dai->id);404		return rc;405	}406	dai_data->is_port_started[dai->id] = true;407 408	return 0;409}410 411static int q6slim_set_channel_map(struct snd_soc_dai *dai,412				  unsigned int tx_num,413				  const unsigned int *tx_slot,414				  unsigned int rx_num,415				  const unsigned int *rx_slot)416{417	struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);418	struct q6afe_port_config *pcfg = &dai_data->port_config[dai->id];419	int i;420 421	if (dai->id & 0x1) {422		/* TX */423		if (!tx_slot) {424			pr_err("%s: tx slot not found\n", __func__);425			return -EINVAL;426		}427 428		for (i = 0; i < tx_num; i++)429			pcfg->slim.ch_mapping[i] = tx_slot[i];430 431		pcfg->slim.num_channels = tx_num;432 433 434	} else {435		if (!rx_slot) {436			pr_err("%s: rx slot not found\n", __func__);437			return -EINVAL;438		}439 440		for (i = 0; i < rx_num; i++)441			pcfg->slim.ch_mapping[i] =   rx_slot[i];442 443		pcfg->slim.num_channels = rx_num;444 445	}446 447	return 0;448}449 450static int q6afe_mi2s_set_sysclk(struct snd_soc_dai *dai,451		int clk_id, unsigned int freq, int dir)452{453	struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);454	struct q6afe_port *port = dai_data->port[dai->id];455 456	switch (clk_id) {457	case LPAIF_DIG_CLK:458		return q6afe_port_set_sysclk(port, clk_id, 0, 5, freq, dir);459	case LPAIF_BIT_CLK:460	case LPAIF_OSR_CLK:461		return q6afe_port_set_sysclk(port, clk_id,462					     Q6AFE_LPASS_CLK_SRC_INTERNAL,463					     Q6AFE_LPASS_CLK_ROOT_DEFAULT,464					     freq, dir);465	case Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT ... Q6AFE_LPASS_CLK_ID_QUI_MI2S_OSR:466	case Q6AFE_LPASS_CLK_ID_MCLK_1 ... Q6AFE_LPASS_CLK_ID_INT_MCLK_1:467	case Q6AFE_LPASS_CLK_ID_WSA_CORE_MCLK ... Q6AFE_LPASS_CLK_ID_VA_CORE_2X_MCLK:468		return q6afe_port_set_sysclk(port, clk_id,469					     Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,470					     Q6AFE_LPASS_CLK_ROOT_DEFAULT,471					     freq, dir);472	case Q6AFE_LPASS_CLK_ID_PRI_TDM_IBIT ... Q6AFE_LPASS_CLK_ID_QUIN_TDM_EBIT:473		return q6afe_port_set_sysclk(port, clk_id,474					     Q6AFE_LPASS_CLK_ATTRIBUTE_INVERT_COUPLE_NO,475					     Q6AFE_LPASS_CLK_ROOT_DEFAULT,476					     freq, dir);477	}478 479	return 0;480}481 482static const struct snd_soc_dapm_route q6afe_dapm_routes[] = {483	{"HDMI Playback", NULL, "HDMI_RX"},484	{"DISPLAY_PORT_RX_0 Playback", NULL, "DISPLAY_PORT_RX"},485	{"Slimbus Playback", NULL, "SLIMBUS_0_RX"},486	{"Slimbus1 Playback", NULL, "SLIMBUS_1_RX"},487	{"Slimbus2 Playback", NULL, "SLIMBUS_2_RX"},488	{"Slimbus3 Playback", NULL, "SLIMBUS_3_RX"},489	{"Slimbus4 Playback", NULL, "SLIMBUS_4_RX"},490	{"Slimbus5 Playback", NULL, "SLIMBUS_5_RX"},491	{"Slimbus6 Playback", NULL, "SLIMBUS_6_RX"},492 493	{"SLIMBUS_0_TX", NULL, "Slimbus Capture"},494	{"SLIMBUS_1_TX", NULL, "Slimbus1 Capture"},495	{"SLIMBUS_2_TX", NULL, "Slimbus2 Capture"},496	{"SLIMBUS_3_TX", NULL, "Slimbus3 Capture"},497	{"SLIMBUS_4_TX", NULL, "Slimbus4 Capture"},498	{"SLIMBUS_5_TX", NULL, "Slimbus5 Capture"},499	{"SLIMBUS_6_TX", NULL, "Slimbus6 Capture"},500 501	{"Primary MI2S Playback", NULL, "PRI_MI2S_RX"},502	{"Secondary MI2S Playback", NULL, "SEC_MI2S_RX"},503	{"Tertiary MI2S Playback", NULL, "TERT_MI2S_RX"},504	{"Quaternary MI2S Playback", NULL, "QUAT_MI2S_RX"},505	{"Quinary MI2S Playback", NULL, "QUIN_MI2S_RX"},506 507	{"Primary TDM0 Playback", NULL, "PRIMARY_TDM_RX_0"},508	{"Primary TDM1 Playback", NULL, "PRIMARY_TDM_RX_1"},509	{"Primary TDM2 Playback", NULL, "PRIMARY_TDM_RX_2"},510	{"Primary TDM3 Playback", NULL, "PRIMARY_TDM_RX_3"},511	{"Primary TDM4 Playback", NULL, "PRIMARY_TDM_RX_4"},512	{"Primary TDM5 Playback", NULL, "PRIMARY_TDM_RX_5"},513	{"Primary TDM6 Playback", NULL, "PRIMARY_TDM_RX_6"},514	{"Primary TDM7 Playback", NULL, "PRIMARY_TDM_RX_7"},515 516	{"Secondary TDM0 Playback", NULL, "SEC_TDM_RX_0"},517	{"Secondary TDM1 Playback", NULL, "SEC_TDM_RX_1"},518	{"Secondary TDM2 Playback", NULL, "SEC_TDM_RX_2"},519	{"Secondary TDM3 Playback", NULL, "SEC_TDM_RX_3"},520	{"Secondary TDM4 Playback", NULL, "SEC_TDM_RX_4"},521	{"Secondary TDM5 Playback", NULL, "SEC_TDM_RX_5"},522	{"Secondary TDM6 Playback", NULL, "SEC_TDM_RX_6"},523	{"Secondary TDM7 Playback", NULL, "SEC_TDM_RX_7"},524 525	{"Tertiary TDM0 Playback", NULL, "TERT_TDM_RX_0"},526	{"Tertiary TDM1 Playback", NULL, "TERT_TDM_RX_1"},527	{"Tertiary TDM2 Playback", NULL, "TERT_TDM_RX_2"},528	{"Tertiary TDM3 Playback", NULL, "TERT_TDM_RX_3"},529	{"Tertiary TDM4 Playback", NULL, "TERT_TDM_RX_4"},530	{"Tertiary TDM5 Playback", NULL, "TERT_TDM_RX_5"},531	{"Tertiary TDM6 Playback", NULL, "TERT_TDM_RX_6"},532	{"Tertiary TDM7 Playback", NULL, "TERT_TDM_RX_7"},533 534	{"Quaternary TDM0 Playback", NULL, "QUAT_TDM_RX_0"},535	{"Quaternary TDM1 Playback", NULL, "QUAT_TDM_RX_1"},536	{"Quaternary TDM2 Playback", NULL, "QUAT_TDM_RX_2"},537	{"Quaternary TDM3 Playback", NULL, "QUAT_TDM_RX_3"},538	{"Quaternary TDM4 Playback", NULL, "QUAT_TDM_RX_4"},539	{"Quaternary TDM5 Playback", NULL, "QUAT_TDM_RX_5"},540	{"Quaternary TDM6 Playback", NULL, "QUAT_TDM_RX_6"},541	{"Quaternary TDM7 Playback", NULL, "QUAT_TDM_RX_7"},542 543	{"Quinary TDM0 Playback", NULL, "QUIN_TDM_RX_0"},544	{"Quinary TDM1 Playback", NULL, "QUIN_TDM_RX_1"},545	{"Quinary TDM2 Playback", NULL, "QUIN_TDM_RX_2"},546	{"Quinary TDM3 Playback", NULL, "QUIN_TDM_RX_3"},547	{"Quinary TDM4 Playback", NULL, "QUIN_TDM_RX_4"},548	{"Quinary TDM5 Playback", NULL, "QUIN_TDM_RX_5"},549	{"Quinary TDM6 Playback", NULL, "QUIN_TDM_RX_6"},550	{"Quinary TDM7 Playback", NULL, "QUIN_TDM_RX_7"},551 552	{"PRIMARY_TDM_TX_0", NULL, "Primary TDM0 Capture"},553	{"PRIMARY_TDM_TX_1", NULL, "Primary TDM1 Capture"},554	{"PRIMARY_TDM_TX_2", NULL, "Primary TDM2 Capture"},555	{"PRIMARY_TDM_TX_3", NULL, "Primary TDM3 Capture"},556	{"PRIMARY_TDM_TX_4", NULL, "Primary TDM4 Capture"},557	{"PRIMARY_TDM_TX_5", NULL, "Primary TDM5 Capture"},558	{"PRIMARY_TDM_TX_6", NULL, "Primary TDM6 Capture"},559	{"PRIMARY_TDM_TX_7", NULL, "Primary TDM7 Capture"},560 561	{"SEC_TDM_TX_0", NULL, "Secondary TDM0 Capture"},562	{"SEC_TDM_TX_1", NULL, "Secondary TDM1 Capture"},563	{"SEC_TDM_TX_2", NULL, "Secondary TDM2 Capture"},564	{"SEC_TDM_TX_3", NULL, "Secondary TDM3 Capture"},565	{"SEC_TDM_TX_4", NULL, "Secondary TDM4 Capture"},566	{"SEC_TDM_TX_5", NULL, "Secondary TDM5 Capture"},567	{"SEC_TDM_TX_6", NULL, "Secondary TDM6 Capture"},568	{"SEC_TDM_TX_7", NULL, "Secondary TDM7 Capture"},569 570	{"TERT_TDM_TX_0", NULL, "Tertiary TDM0 Capture"},571	{"TERT_TDM_TX_1", NULL, "Tertiary TDM1 Capture"},572	{"TERT_TDM_TX_2", NULL, "Tertiary TDM2 Capture"},573	{"TERT_TDM_TX_3", NULL, "Tertiary TDM3 Capture"},574	{"TERT_TDM_TX_4", NULL, "Tertiary TDM4 Capture"},575	{"TERT_TDM_TX_5", NULL, "Tertiary TDM5 Capture"},576	{"TERT_TDM_TX_6", NULL, "Tertiary TDM6 Capture"},577	{"TERT_TDM_TX_7", NULL, "Tertiary TDM7 Capture"},578 579	{"QUAT_TDM_TX_0", NULL, "Quaternary TDM0 Capture"},580	{"QUAT_TDM_TX_1", NULL, "Quaternary TDM1 Capture"},581	{"QUAT_TDM_TX_2", NULL, "Quaternary TDM2 Capture"},582	{"QUAT_TDM_TX_3", NULL, "Quaternary TDM3 Capture"},583	{"QUAT_TDM_TX_4", NULL, "Quaternary TDM4 Capture"},584	{"QUAT_TDM_TX_5", NULL, "Quaternary TDM5 Capture"},585	{"QUAT_TDM_TX_6", NULL, "Quaternary TDM6 Capture"},586	{"QUAT_TDM_TX_7", NULL, "Quaternary TDM7 Capture"},587 588	{"QUIN_TDM_TX_0", NULL, "Quinary TDM0 Capture"},589	{"QUIN_TDM_TX_1", NULL, "Quinary TDM1 Capture"},590	{"QUIN_TDM_TX_2", NULL, "Quinary TDM2 Capture"},591	{"QUIN_TDM_TX_3", NULL, "Quinary TDM3 Capture"},592	{"QUIN_TDM_TX_4", NULL, "Quinary TDM4 Capture"},593	{"QUIN_TDM_TX_5", NULL, "Quinary TDM5 Capture"},594	{"QUIN_TDM_TX_6", NULL, "Quinary TDM6 Capture"},595	{"QUIN_TDM_TX_7", NULL, "Quinary TDM7 Capture"},596 597	{"TERT_MI2S_TX", NULL, "Tertiary MI2S Capture"},598	{"PRI_MI2S_TX", NULL, "Primary MI2S Capture"},599	{"SEC_MI2S_TX", NULL, "Secondary MI2S Capture"},600	{"QUAT_MI2S_TX", NULL, "Quaternary MI2S Capture"},601	{"QUIN_MI2S_TX", NULL, "Quinary MI2S Capture"},602 603	{"WSA_CODEC_DMA_RX_0 Playback", NULL, "WSA_CODEC_DMA_RX_0"},604	{"WSA_CODEC_DMA_TX_0", NULL, "WSA_CODEC_DMA_TX_0 Capture"},605	{"WSA_CODEC_DMA_RX_1 Playback", NULL, "WSA_CODEC_DMA_RX_1"},606	{"WSA_CODEC_DMA_TX_1", NULL, "WSA_CODEC_DMA_TX_1 Capture"},607	{"WSA_CODEC_DMA_TX_2", NULL, "WSA_CODEC_DMA_TX_2 Capture"},608	{"VA_CODEC_DMA_TX_0", NULL, "VA_CODEC_DMA_TX_0 Capture"},609	{"VA_CODEC_DMA_TX_1", NULL, "VA_CODEC_DMA_TX_1 Capture"},610	{"VA_CODEC_DMA_TX_2", NULL, "VA_CODEC_DMA_TX_2 Capture"},611	{"RX_CODEC_DMA_RX_0 Playback", NULL, "RX_CODEC_DMA_RX_0"},612	{"TX_CODEC_DMA_TX_0", NULL, "TX_CODEC_DMA_TX_0 Capture"},613	{"RX_CODEC_DMA_RX_1 Playback", NULL, "RX_CODEC_DMA_RX_1"},614	{"TX_CODEC_DMA_TX_1", NULL, "TX_CODEC_DMA_TX_1 Capture"},615	{"RX_CODEC_DMA_RX_2 Playback", NULL, "RX_CODEC_DMA_RX_2"},616	{"TX_CODEC_DMA_TX_2", NULL, "TX_CODEC_DMA_TX_2 Capture"},617	{"RX_CODEC_DMA_RX_3 Playback", NULL, "RX_CODEC_DMA_RX_3"},618	{"TX_CODEC_DMA_TX_3", NULL, "TX_CODEC_DMA_TX_3 Capture"},619	{"RX_CODEC_DMA_RX_4 Playback", NULL, "RX_CODEC_DMA_RX_4"},620	{"TX_CODEC_DMA_TX_4", NULL, "TX_CODEC_DMA_TX_4 Capture"},621	{"RX_CODEC_DMA_RX_5 Playback", NULL, "RX_CODEC_DMA_RX_5"},622	{"TX_CODEC_DMA_TX_5", NULL, "TX_CODEC_DMA_TX_5 Capture"},623	{"RX_CODEC_DMA_RX_6 Playback", NULL, "RX_CODEC_DMA_RX_6"},624	{"RX_CODEC_DMA_RX_7 Playback", NULL, "RX_CODEC_DMA_RX_7"},625};626 627static int msm_dai_q6_dai_probe(struct snd_soc_dai *dai)628{629	struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);630	struct q6afe_port *port;631 632	port = q6afe_port_get_from_id(dai->dev, dai->id);633	if (IS_ERR(port)) {634		dev_err(dai->dev, "Unable to get afe port\n");635		return -EINVAL;636	}637	dai_data->port[dai->id] = port;638 639	return 0;640}641 642static int msm_dai_q6_dai_remove(struct snd_soc_dai *dai)643{644	struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev);645 646	q6afe_port_put(dai_data->port[dai->id]);647	dai_data->port[dai->id] = NULL;648 649	return 0;650}651 652static const struct snd_soc_dai_ops q6hdmi_ops = {653	.probe			= msm_dai_q6_dai_probe,654	.remove			= msm_dai_q6_dai_remove,655	.prepare		= q6afe_dai_prepare,656	.hw_params		= q6hdmi_hw_params,657	.shutdown		= q6afe_dai_shutdown,658};659 660static const struct snd_soc_dai_ops q6i2s_ops = {661	.probe			= msm_dai_q6_dai_probe,662	.remove			= msm_dai_q6_dai_remove,663	.prepare		= q6afe_dai_prepare,664	.hw_params		= q6i2s_hw_params,665	.set_fmt		= q6i2s_set_fmt,666	.shutdown		= q6afe_dai_shutdown,667	.set_sysclk		= q6afe_mi2s_set_sysclk,668};669 670static const struct snd_soc_dai_ops q6slim_ops = {671	.probe			= msm_dai_q6_dai_probe,672	.remove			= msm_dai_q6_dai_remove,673	.prepare		= q6afe_dai_prepare,674	.hw_params		= q6slim_hw_params,675	.shutdown		= q6afe_dai_shutdown,676	.set_channel_map	= q6slim_set_channel_map,677};678 679static const struct snd_soc_dai_ops q6tdm_ops = {680	.probe			= msm_dai_q6_dai_probe,681	.remove			= msm_dai_q6_dai_remove,682	.prepare		= q6afe_dai_prepare,683	.shutdown		= q6afe_dai_shutdown,684	.set_sysclk		= q6afe_mi2s_set_sysclk,685	.set_tdm_slot		= q6tdm_set_tdm_slot,686	.set_channel_map	= q6tdm_set_channel_map,687	.hw_params		= q6tdm_hw_params,688};689 690static const struct snd_soc_dai_ops q6dma_ops = {691	.probe			= msm_dai_q6_dai_probe,692	.remove			= msm_dai_q6_dai_remove,693	.prepare		= q6afe_dai_prepare,694	.shutdown		= q6afe_dai_shutdown,695	.set_sysclk		= q6afe_mi2s_set_sysclk,696	.set_channel_map	= q6dma_set_channel_map,697	.hw_params		= q6dma_hw_params,698};699 700static const struct snd_soc_dapm_widget q6afe_dai_widgets[] = {701	SND_SOC_DAPM_AIF_IN("HDMI_RX", NULL, 0, SND_SOC_NOPM, 0, 0),702	SND_SOC_DAPM_AIF_IN("SLIMBUS_0_RX", NULL, 0, SND_SOC_NOPM, 0, 0),703	SND_SOC_DAPM_AIF_IN("SLIMBUS_1_RX", NULL, 0, SND_SOC_NOPM, 0, 0),704	SND_SOC_DAPM_AIF_IN("SLIMBUS_2_RX", NULL, 0, SND_SOC_NOPM, 0, 0),705	SND_SOC_DAPM_AIF_IN("SLIMBUS_3_RX", NULL, 0, SND_SOC_NOPM, 0, 0),706	SND_SOC_DAPM_AIF_IN("SLIMBUS_4_RX", NULL, 0, SND_SOC_NOPM, 0, 0),707	SND_SOC_DAPM_AIF_IN("SLIMBUS_5_RX", NULL, 0, SND_SOC_NOPM, 0, 0),708	SND_SOC_DAPM_AIF_IN("SLIMBUS_6_RX", NULL, 0, SND_SOC_NOPM, 0, 0),709	SND_SOC_DAPM_AIF_OUT("SLIMBUS_0_TX", NULL, 0, SND_SOC_NOPM, 0, 0),710	SND_SOC_DAPM_AIF_OUT("SLIMBUS_1_TX", NULL, 0, SND_SOC_NOPM, 0, 0),711	SND_SOC_DAPM_AIF_OUT("SLIMBUS_2_TX", NULL, 0, SND_SOC_NOPM, 0, 0),712	SND_SOC_DAPM_AIF_OUT("SLIMBUS_3_TX", NULL, 0, SND_SOC_NOPM, 0, 0),713	SND_SOC_DAPM_AIF_OUT("SLIMBUS_4_TX", NULL, 0, SND_SOC_NOPM, 0, 0),714	SND_SOC_DAPM_AIF_OUT("SLIMBUS_5_TX", NULL, 0, SND_SOC_NOPM, 0, 0),715	SND_SOC_DAPM_AIF_OUT("SLIMBUS_6_TX", NULL, 0, SND_SOC_NOPM, 0, 0),716	SND_SOC_DAPM_AIF_IN("QUIN_MI2S_RX", NULL,717						0, SND_SOC_NOPM, 0, 0),718	SND_SOC_DAPM_AIF_OUT("QUIN_MI2S_TX", NULL,719						0, SND_SOC_NOPM, 0, 0),720	SND_SOC_DAPM_AIF_IN("QUAT_MI2S_RX", NULL,721						0, SND_SOC_NOPM, 0, 0),722	SND_SOC_DAPM_AIF_OUT("QUAT_MI2S_TX", NULL,723						0, SND_SOC_NOPM, 0, 0),724	SND_SOC_DAPM_AIF_IN("TERT_MI2S_RX", NULL,725						0, SND_SOC_NOPM, 0, 0),726	SND_SOC_DAPM_AIF_OUT("TERT_MI2S_TX", NULL,727						0, SND_SOC_NOPM, 0, 0),728	SND_SOC_DAPM_AIF_IN("SEC_MI2S_RX", NULL,729			     0, SND_SOC_NOPM, 0, 0),730	SND_SOC_DAPM_AIF_OUT("SEC_MI2S_TX", NULL,731						0, SND_SOC_NOPM, 0, 0),732	SND_SOC_DAPM_AIF_IN("SEC_MI2S_RX_SD1",733			"Secondary MI2S Playback SD1",734			0, SND_SOC_NOPM, 0, 0),735	SND_SOC_DAPM_AIF_IN("PRI_MI2S_RX", NULL,736			     0, SND_SOC_NOPM, 0, 0),737	SND_SOC_DAPM_AIF_OUT("PRI_MI2S_TX", NULL,738						0, SND_SOC_NOPM, 0, 0),739 740	SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_0", NULL,741			     0, SND_SOC_NOPM, 0, 0),742	SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_1", NULL,743			     0, SND_SOC_NOPM, 0, 0),744	SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_2", NULL,745			     0, SND_SOC_NOPM, 0, 0),746	SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_3", NULL,747			     0, SND_SOC_NOPM, 0, 0),748	SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_4", NULL,749			     0, SND_SOC_NOPM, 0, 0),750	SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_5", NULL,751			     0, SND_SOC_NOPM, 0, 0),752	SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_6", NULL,753			     0, SND_SOC_NOPM, 0, 0),754	SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_7", NULL,755			     0, SND_SOC_NOPM, 0, 0),756	SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_0", NULL,757						0, SND_SOC_NOPM, 0, 0),758	SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_1", NULL,759						0, SND_SOC_NOPM, 0, 0),760	SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_2", NULL,761						0, SND_SOC_NOPM, 0, 0),762	SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_3", NULL,763						0, SND_SOC_NOPM, 0, 0),764	SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_4", NULL,765						0, SND_SOC_NOPM, 0, 0),766	SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_5", NULL,767						0, SND_SOC_NOPM, 0, 0),768	SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_6", NULL,769						0, SND_SOC_NOPM, 0, 0),770	SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_7", NULL,771						0, SND_SOC_NOPM, 0, 0),772 773	SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_0", NULL,774			     0, SND_SOC_NOPM, 0, 0),775	SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_1", NULL,776			     0, SND_SOC_NOPM, 0, 0),777	SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_2", NULL,778			     0, SND_SOC_NOPM, 0, 0),779	SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_3", NULL,780			     0, SND_SOC_NOPM, 0, 0),781	SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_4", NULL,782			     0, SND_SOC_NOPM, 0, 0),783	SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_5", NULL,784			     0, SND_SOC_NOPM, 0, 0),785	SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_6", NULL,786			     0, SND_SOC_NOPM, 0, 0),787	SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_7", NULL,788			     0, SND_SOC_NOPM, 0, 0),789	SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_0", NULL,790						0, SND_SOC_NOPM, 0, 0),791	SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_1", NULL,792						0, SND_SOC_NOPM, 0, 0),793	SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_2", NULL,794						0, SND_SOC_NOPM, 0, 0),795	SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_3", NULL,796						0, SND_SOC_NOPM, 0, 0),797	SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_4", NULL,798						0, SND_SOC_NOPM, 0, 0),799	SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_5", NULL,800						0, SND_SOC_NOPM, 0, 0),801	SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_6", NULL,802						0, SND_SOC_NOPM, 0, 0),803	SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_7", NULL,804						0, SND_SOC_NOPM, 0, 0),805 806	SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_0", NULL,807			     0, SND_SOC_NOPM, 0, 0),808	SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_1", NULL,809			     0, SND_SOC_NOPM, 0, 0),810	SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_2", NULL,811			     0, SND_SOC_NOPM, 0, 0),812	SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_3", NULL,813			     0, SND_SOC_NOPM, 0, 0),814	SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_4", NULL,815			     0, SND_SOC_NOPM, 0, 0),816	SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_5", NULL,817			     0, SND_SOC_NOPM, 0, 0),818	SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_6", NULL,819			     0, SND_SOC_NOPM, 0, 0),820	SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_7", NULL,821			     0, SND_SOC_NOPM, 0, 0),822	SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_0", NULL,823						0, SND_SOC_NOPM, 0, 0),824	SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_1", NULL,825						0, SND_SOC_NOPM, 0, 0),826	SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_2", NULL,827						0, SND_SOC_NOPM, 0, 0),828	SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_3", NULL,829						0, SND_SOC_NOPM, 0, 0),830	SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_4", NULL,831						0, SND_SOC_NOPM, 0, 0),832	SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_5", NULL,833						0, SND_SOC_NOPM, 0, 0),834	SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_6", NULL,835						0, SND_SOC_NOPM, 0, 0),836	SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_7", NULL,837						0, SND_SOC_NOPM, 0, 0),838 839	SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_0", NULL,840			     0, SND_SOC_NOPM, 0, 0),841	SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_1", NULL,842			     0, SND_SOC_NOPM, 0, 0),843	SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_2", NULL,844			     0, SND_SOC_NOPM, 0, 0),845	SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_3", NULL,846			     0, SND_SOC_NOPM, 0, 0),847	SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_4", NULL,848			     0, SND_SOC_NOPM, 0, 0),849	SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_5", NULL,850			     0, SND_SOC_NOPM, 0, 0),851	SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_6", NULL,852			     0, SND_SOC_NOPM, 0, 0),853	SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_7", NULL,854			     0, SND_SOC_NOPM, 0, 0),855	SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_0", NULL,856						0, SND_SOC_NOPM, 0, 0),857	SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_1", NULL,858						0, SND_SOC_NOPM, 0, 0),859	SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_2", NULL,860						0, SND_SOC_NOPM, 0, 0),861	SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_3", NULL,862						0, SND_SOC_NOPM, 0, 0),863	SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_4", NULL,864						0, SND_SOC_NOPM, 0, 0),865	SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_5", NULL,866						0, SND_SOC_NOPM, 0, 0),867	SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_6", NULL,868						0, SND_SOC_NOPM, 0, 0),869	SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_7", NULL,870						0, SND_SOC_NOPM, 0, 0),871 872	SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_0", NULL,873			     0, SND_SOC_NOPM, 0, 0),874	SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_1", NULL,875			     0, SND_SOC_NOPM, 0, 0),876	SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_2", NULL,877			     0, SND_SOC_NOPM, 0, 0),878	SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_3", NULL,879			     0, SND_SOC_NOPM, 0, 0),880	SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_4", NULL,881			     0, SND_SOC_NOPM, 0, 0),882	SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_5", NULL,883			     0, SND_SOC_NOPM, 0, 0),884	SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_6", NULL,885			     0, SND_SOC_NOPM, 0, 0),886	SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_7", NULL,887			     0, SND_SOC_NOPM, 0, 0),888	SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_0", NULL,889						0, SND_SOC_NOPM, 0, 0),890	SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_1", NULL,891						0, SND_SOC_NOPM, 0, 0),892	SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_2", NULL,893						0, SND_SOC_NOPM, 0, 0),894	SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_3", NULL,895						0, SND_SOC_NOPM, 0, 0),896	SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_4", NULL,897						0, SND_SOC_NOPM, 0, 0),898	SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_5", NULL,899						0, SND_SOC_NOPM, 0, 0),900	SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_6", NULL,901						0, SND_SOC_NOPM, 0, 0),902	SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_7", NULL,903						0, SND_SOC_NOPM, 0, 0),904	SND_SOC_DAPM_AIF_OUT("DISPLAY_PORT_RX", "NULL", 0, SND_SOC_NOPM, 0, 0),905 906	SND_SOC_DAPM_AIF_IN("WSA_CODEC_DMA_RX_0", "NULL",907		0, SND_SOC_NOPM, 0, 0),908	SND_SOC_DAPM_AIF_OUT("WSA_CODEC_DMA_TX_0", "NULL",909		 0, SND_SOC_NOPM, 0, 0),910	SND_SOC_DAPM_AIF_IN("WSA_CODEC_DMA_RX_1", "NULL",911		0, SND_SOC_NOPM, 0, 0),912	SND_SOC_DAPM_AIF_OUT("WSA_CODEC_DMA_TX_1", "NULL",913		 0, SND_SOC_NOPM, 0, 0),914	SND_SOC_DAPM_AIF_OUT("WSA_CODEC_DMA_TX_2", "NULL",915		 0, SND_SOC_NOPM, 0, 0),916	SND_SOC_DAPM_AIF_OUT("VA_CODEC_DMA_TX_0", "NULL",917		 0, SND_SOC_NOPM, 0, 0),918	SND_SOC_DAPM_AIF_OUT("VA_CODEC_DMA_TX_1", "NULL",919		 0, SND_SOC_NOPM, 0, 0),920	SND_SOC_DAPM_AIF_OUT("VA_CODEC_DMA_TX_2", "NULL",921		 0, SND_SOC_NOPM, 0, 0),922	SND_SOC_DAPM_AIF_IN("RX_CODEC_DMA_RX_0", "NULL",923		0, SND_SOC_NOPM, 0, 0),924	SND_SOC_DAPM_AIF_OUT("TX_CODEC_DMA_TX_0", "NULL",925		 0, SND_SOC_NOPM, 0, 0),926	SND_SOC_DAPM_AIF_IN("RX_CODEC_DMA_RX_1", "NULL",927		0, SND_SOC_NOPM, 0, 0),928	SND_SOC_DAPM_AIF_OUT("TX_CODEC_DMA_TX_1", "NULL",929		 0, SND_SOC_NOPM, 0, 0),930	SND_SOC_DAPM_AIF_IN("RX_CODEC_DMA_RX_2", "NULL",931		0, SND_SOC_NOPM, 0, 0),932	SND_SOC_DAPM_AIF_OUT("TX_CODEC_DMA_TX_2", "NULL",933		 0, SND_SOC_NOPM, 0, 0),934	SND_SOC_DAPM_AIF_IN("RX_CODEC_DMA_RX_3", "NULL",935		0, SND_SOC_NOPM, 0, 0),936	SND_SOC_DAPM_AIF_OUT("TX_CODEC_DMA_TX_3", "NULL",937		 0, SND_SOC_NOPM, 0, 0),938	SND_SOC_DAPM_AIF_IN("RX_CODEC_DMA_RX_4", "NULL",939		0, SND_SOC_NOPM, 0, 0),940	SND_SOC_DAPM_AIF_OUT("TX_CODEC_DMA_TX_4", "NULL",941		 0, SND_SOC_NOPM, 0, 0),942	SND_SOC_DAPM_AIF_IN("RX_CODEC_DMA_RX_5", "NULL",943		0, SND_SOC_NOPM, 0, 0),944	SND_SOC_DAPM_AIF_OUT("TX_CODEC_DMA_TX_5", "NULL",945		 0, SND_SOC_NOPM, 0, 0),946	SND_SOC_DAPM_AIF_IN("RX_CODEC_DMA_RX_6", "NULL",947		0, SND_SOC_NOPM, 0, 0),948	SND_SOC_DAPM_AIF_IN("RX_CODEC_DMA_RX_7", "NULL",949		0, SND_SOC_NOPM, 0, 0),950};951 952static const struct snd_soc_component_driver q6afe_dai_component = {953	.name		= "q6afe-dai-component",954	.dapm_widgets = q6afe_dai_widgets,955	.num_dapm_widgets = ARRAY_SIZE(q6afe_dai_widgets),956	.dapm_routes = q6afe_dapm_routes,957	.num_dapm_routes = ARRAY_SIZE(q6afe_dapm_routes),958	.of_xlate_dai_name = q6dsp_audio_ports_of_xlate_dai_name,959 960};961 962static void of_q6afe_parse_dai_data(struct device *dev,963				    struct q6afe_dai_data *data)964{965	struct device_node *node;966	int ret;967 968	for_each_child_of_node(dev->of_node, node) {969		unsigned int lines[Q6AFE_MAX_MI2S_LINES];970		struct q6afe_dai_priv_data *priv;971		int id, i, num_lines;972 973		ret = of_property_read_u32(node, "reg", &id);974		if (ret || id < 0 || id >= AFE_PORT_MAX) {975			dev_err(dev, "valid dai id not found:%d\n", ret);976			continue;977		}978 979		switch (id) {980		/* MI2S specific properties */981		case QUINARY_MI2S_RX ... QUINARY_MI2S_TX:982		case PRIMARY_MI2S_RX ... QUATERNARY_MI2S_TX:983			priv = &data->priv[id];984			ret = of_property_read_variable_u32_array(node,985							"qcom,sd-lines",986							lines, 0,987							Q6AFE_MAX_MI2S_LINES);988			if (ret < 0)989				num_lines = 0;990			else991				num_lines = ret;992 993			priv->sd_line_mask = 0;994 995			for (i = 0; i < num_lines; i++)996				priv->sd_line_mask |= BIT(lines[i]);997 998			break;999		case PRIMARY_TDM_RX_0 ... QUINARY_TDM_TX_7:1000			priv = &data->priv[id];1001			ret = of_property_read_u32(node, "qcom,tdm-sync-mode",1002						   &priv->sync_mode);1003			if (ret) {1004				dev_err(dev, "No Sync mode from DT\n");1005				break;1006			}1007			ret = of_property_read_u32(node, "qcom,tdm-sync-src",1008						   &priv->sync_src);1009			if (ret) {1010				dev_err(dev, "No Sync Src from DT\n");1011				break;1012			}1013			ret = of_property_read_u32(node, "qcom,tdm-data-out",1014						   &priv->data_out_enable);1015			if (ret) {1016				dev_err(dev, "No Data out enable from DT\n");1017				break;1018			}1019			ret = of_property_read_u32(node, "qcom,tdm-invert-sync",1020						   &priv->invert_sync);1021			if (ret) {1022				dev_err(dev, "No Invert sync from DT\n");1023				break;1024			}1025			ret = of_property_read_u32(node, "qcom,tdm-data-delay",1026						   &priv->data_delay);1027			if (ret) {1028				dev_err(dev, "No Data Delay from DT\n");1029				break;1030			}1031			ret = of_property_read_u32(node, "qcom,tdm-data-align",1032						   &priv->data_align);1033			if (ret) {1034				dev_err(dev, "No Data align from DT\n");1035				break;1036			}1037			break;1038		default:1039			break;1040		}1041	}1042}1043 1044static int q6afe_dai_dev_probe(struct platform_device *pdev)1045{1046	struct q6dsp_audio_port_dai_driver_config cfg;1047	struct snd_soc_dai_driver *dais;1048	struct q6afe_dai_data *dai_data;1049	struct device *dev = &pdev->dev;1050	int num_dais;1051 1052	dai_data = devm_kzalloc(dev, sizeof(*dai_data), GFP_KERNEL);1053	if (!dai_data)1054		return -ENOMEM;1055 1056	dev_set_drvdata(dev, dai_data);1057	of_q6afe_parse_dai_data(dev, dai_data);1058 1059	cfg.q6hdmi_ops = &q6hdmi_ops;1060	cfg.q6slim_ops = &q6slim_ops;1061	cfg.q6i2s_ops = &q6i2s_ops;1062	cfg.q6tdm_ops = &q6tdm_ops;1063	cfg.q6dma_ops = &q6dma_ops;1064	dais = q6dsp_audio_ports_set_config(dev, &cfg, &num_dais);1065 1066	return devm_snd_soc_register_component(dev, &q6afe_dai_component, dais, num_dais);1067}1068 1069#ifdef CONFIG_OF1070static const struct of_device_id q6afe_dai_device_id[] = {1071	{ .compatible = "qcom,q6afe-dais" },1072	{},1073};1074MODULE_DEVICE_TABLE(of, q6afe_dai_device_id);1075#endif1076 1077static struct platform_driver q6afe_dai_platform_driver = {1078	.driver = {1079		.name = "q6afe-dai",1080		.of_match_table = of_match_ptr(q6afe_dai_device_id),1081	},1082	.probe = q6afe_dai_dev_probe,1083};1084module_platform_driver(q6afe_dai_platform_driver);1085 1086MODULE_DESCRIPTION("Q6 Audio Frontend dai driver");1087MODULE_LICENSE("GPL v2");1088