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