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