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 SENARY_MI2S_RX ... SENARY_MI2S_TX: 413 case QUINARY_MI2S_RX ... QUINARY_MI2S_TX: 414 case PRIMARY_MI2S_RX ... QUATERNARY_MI2S_TX: 415 rc = q6afe_i2s_port_prepare(dai_data->port[dai->id], 416 &dai_data->port_config[dai->id].i2s_cfg); 417 if (rc < 0) { 418 dev_err(dai->dev, "fail to prepare AFE port %x\n", 419 dai->id); 420 return rc; 421 } 422 break; 423 case PRIMARY_TDM_RX_0 ... QUINARY_TDM_TX_7: 424 q6afe_tdm_port_prepare(dai_data->port[dai->id], 425 &dai_data->port_config[dai->id].tdm); 426 break; 427 case WSA_CODEC_DMA_RX_0 ... RX_CODEC_DMA_RX_7: 428 q6afe_cdc_dma_port_prepare(dai_data->port[dai->id], 429 &dai_data->port_config[dai->id].dma_cfg); 430 break; 431 case USB_RX: 432 q6afe_usb_port_prepare(dai_data->port[dai->id], 433 &dai_data->port_config[dai->id].usb_audio); 434 break; 435 default: 436 return -EINVAL; 437 } 438 439 rc = q6afe_port_start(dai_data->port[dai->id]); 440 if (rc < 0) { 441 dev_err(dai->dev, "fail to start AFE port %x\n", dai->id); 442 return rc; 443 } 444 dai_data->is_port_started[dai->id] = true; 445 446 return 0; 447 } 448 449 static int q6slim_set_channel_map(struct snd_soc_dai *dai, 450 unsigned int tx_num, 451 const unsigned int *tx_slot, 452 unsigned int rx_num, 453 const unsigned int *rx_slot) 454 { 455 struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev); 456 struct q6afe_port_config *pcfg = &dai_data->port_config[dai->id]; 457 int i; 458 459 if (dai->id & 0x1) { 460 /* TX */ 461 if (!tx_slot) { 462 pr_err("%s: tx slot not found\n", __func__); 463 return -EINVAL; 464 } 465 466 for (i = 0; i < tx_num; i++) 467 pcfg->slim.ch_mapping[i] = tx_slot[i]; 468 469 pcfg->slim.num_channels = tx_num; 470 471 472 } else { 473 if (!rx_slot) { 474 pr_err("%s: rx slot not found\n", __func__); 475 return -EINVAL; 476 } 477 478 for (i = 0; i < rx_num; i++) 479 pcfg->slim.ch_mapping[i] = rx_slot[i]; 480 481 pcfg->slim.num_channels = rx_num; 482 483 } 484 485 return 0; 486 } 487 488 static int q6afe_mi2s_set_sysclk(struct snd_soc_dai *dai, 489 int clk_id, unsigned int freq, int dir) 490 { 491 struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev); 492 struct q6afe_port *port = dai_data->port[dai->id]; 493 494 switch (clk_id) { 495 case LPAIF_DIG_CLK: 496 return q6afe_port_set_sysclk(port, clk_id, 0, 5, freq, dir); 497 case LPAIF_BIT_CLK: 498 case LPAIF_OSR_CLK: 499 return q6afe_port_set_sysclk(port, clk_id, 500 Q6AFE_LPASS_CLK_SRC_INTERNAL, 501 Q6AFE_LPASS_CLK_ROOT_DEFAULT, 502 freq, dir); 503 case Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT ... Q6AFE_LPASS_CLK_ID_QUI_MI2S_OSR: 504 case Q6AFE_LPASS_CLK_ID_MCLK_1 ... Q6AFE_LPASS_CLK_ID_INT_MCLK_1: 505 case Q6AFE_LPASS_CLK_ID_WSA_CORE_MCLK ... Q6AFE_LPASS_CLK_ID_VA_CORE_2X_MCLK: 506 return q6afe_port_set_sysclk(port, clk_id, 507 Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO, 508 Q6AFE_LPASS_CLK_ROOT_DEFAULT, 509 freq, dir); 510 case Q6AFE_LPASS_CLK_ID_PRI_TDM_IBIT ... Q6AFE_LPASS_CLK_ID_QUIN_TDM_EBIT: 511 return q6afe_port_set_sysclk(port, clk_id, 512 Q6AFE_LPASS_CLK_ATTRIBUTE_INVERT_COUPLE_NO, 513 Q6AFE_LPASS_CLK_ROOT_DEFAULT, 514 freq, dir); 515 } 516 517 return 0; 518 } 519 520 static const struct snd_soc_dapm_route q6afe_dapm_routes[] = { 521 {"HDMI Playback", NULL, "HDMI_RX"}, 522 {"DISPLAY_PORT_RX_0 Playback", NULL, "DISPLAY_PORT_RX"}, 523 {"Slimbus Playback", NULL, "SLIMBUS_0_RX"}, 524 {"Slimbus1 Playback", NULL, "SLIMBUS_1_RX"}, 525 {"Slimbus2 Playback", NULL, "SLIMBUS_2_RX"}, 526 {"Slimbus3 Playback", NULL, "SLIMBUS_3_RX"}, 527 {"Slimbus4 Playback", NULL, "SLIMBUS_4_RX"}, 528 {"Slimbus5 Playback", NULL, "SLIMBUS_5_RX"}, 529 {"Slimbus6 Playback", NULL, "SLIMBUS_6_RX"}, 530 531 {"SLIMBUS_0_TX", NULL, "Slimbus Capture"}, 532 {"SLIMBUS_1_TX", NULL, "Slimbus1 Capture"}, 533 {"SLIMBUS_2_TX", NULL, "Slimbus2 Capture"}, 534 {"SLIMBUS_3_TX", NULL, "Slimbus3 Capture"}, 535 {"SLIMBUS_4_TX", NULL, "Slimbus4 Capture"}, 536 {"SLIMBUS_5_TX", NULL, "Slimbus5 Capture"}, 537 {"SLIMBUS_6_TX", NULL, "Slimbus6 Capture"}, 538 539 {"Primary MI2S Playback", NULL, "PRI_MI2S_RX"}, 540 {"Secondary MI2S Playback", NULL, "SEC_MI2S_RX"}, 541 {"Tertiary MI2S Playback", NULL, "TERT_MI2S_RX"}, 542 {"Quaternary MI2S Playback", NULL, "QUAT_MI2S_RX"}, 543 {"Quinary MI2S Playback", NULL, "QUIN_MI2S_RX"}, 544 {"Senary MI2S Playback", NULL, "SEN_MI2S_RX"}, 545 546 {"Primary TDM0 Playback", NULL, "PRIMARY_TDM_RX_0"}, 547 {"Primary TDM1 Playback", NULL, "PRIMARY_TDM_RX_1"}, 548 {"Primary TDM2 Playback", NULL, "PRIMARY_TDM_RX_2"}, 549 {"Primary TDM3 Playback", NULL, "PRIMARY_TDM_RX_3"}, 550 {"Primary TDM4 Playback", NULL, "PRIMARY_TDM_RX_4"}, 551 {"Primary TDM5 Playback", NULL, "PRIMARY_TDM_RX_5"}, 552 {"Primary TDM6 Playback", NULL, "PRIMARY_TDM_RX_6"}, 553 {"Primary TDM7 Playback", NULL, "PRIMARY_TDM_RX_7"}, 554 555 {"Secondary TDM0 Playback", NULL, "SEC_TDM_RX_0"}, 556 {"Secondary TDM1 Playback", NULL, "SEC_TDM_RX_1"}, 557 {"Secondary TDM2 Playback", NULL, "SEC_TDM_RX_2"}, 558 {"Secondary TDM3 Playback", NULL, "SEC_TDM_RX_3"}, 559 {"Secondary TDM4 Playback", NULL, "SEC_TDM_RX_4"}, 560 {"Secondary TDM5 Playback", NULL, "SEC_TDM_RX_5"}, 561 {"Secondary TDM6 Playback", NULL, "SEC_TDM_RX_6"}, 562 {"Secondary TDM7 Playback", NULL, "SEC_TDM_RX_7"}, 563 564 {"Tertiary TDM0 Playback", NULL, "TERT_TDM_RX_0"}, 565 {"Tertiary TDM1 Playback", NULL, "TERT_TDM_RX_1"}, 566 {"Tertiary TDM2 Playback", NULL, "TERT_TDM_RX_2"}, 567 {"Tertiary TDM3 Playback", NULL, "TERT_TDM_RX_3"}, 568 {"Tertiary TDM4 Playback", NULL, "TERT_TDM_RX_4"}, 569 {"Tertiary TDM5 Playback", NULL, "TERT_TDM_RX_5"}, 570 {"Tertiary TDM6 Playback", NULL, "TERT_TDM_RX_6"}, 571 {"Tertiary TDM7 Playback", NULL, "TERT_TDM_RX_7"}, 572 573 {"Quaternary TDM0 Playback", NULL, "QUAT_TDM_RX_0"}, 574 {"Quaternary TDM1 Playback", NULL, "QUAT_TDM_RX_1"}, 575 {"Quaternary TDM2 Playback", NULL, "QUAT_TDM_RX_2"}, 576 {"Quaternary TDM3 Playback", NULL, "QUAT_TDM_RX_3"}, 577 {"Quaternary TDM4 Playback", NULL, "QUAT_TDM_RX_4"}, 578 {"Quaternary TDM5 Playback", NULL, "QUAT_TDM_RX_5"}, 579 {"Quaternary TDM6 Playback", NULL, "QUAT_TDM_RX_6"}, 580 {"Quaternary TDM7 Playback", NULL, "QUAT_TDM_RX_7"}, 581 582 {"Quinary TDM0 Playback", NULL, "QUIN_TDM_RX_0"}, 583 {"Quinary TDM1 Playback", NULL, "QUIN_TDM_RX_1"}, 584 {"Quinary TDM2 Playback", NULL, "QUIN_TDM_RX_2"}, 585 {"Quinary TDM3 Playback", NULL, "QUIN_TDM_RX_3"}, 586 {"Quinary TDM4 Playback", NULL, "QUIN_TDM_RX_4"}, 587 {"Quinary TDM5 Playback", NULL, "QUIN_TDM_RX_5"}, 588 {"Quinary TDM6 Playback", NULL, "QUIN_TDM_RX_6"}, 589 {"Quinary TDM7 Playback", NULL, "QUIN_TDM_RX_7"}, 590 591 {"PRIMARY_TDM_TX_0", NULL, "Primary TDM0 Capture"}, 592 {"PRIMARY_TDM_TX_1", NULL, "Primary TDM1 Capture"}, 593 {"PRIMARY_TDM_TX_2", NULL, "Primary TDM2 Capture"}, 594 {"PRIMARY_TDM_TX_3", NULL, "Primary TDM3 Capture"}, 595 {"PRIMARY_TDM_TX_4", NULL, "Primary TDM4 Capture"}, 596 {"PRIMARY_TDM_TX_5", NULL, "Primary TDM5 Capture"}, 597 {"PRIMARY_TDM_TX_6", NULL, "Primary TDM6 Capture"}, 598 {"PRIMARY_TDM_TX_7", NULL, "Primary TDM7 Capture"}, 599 600 {"SEC_TDM_TX_0", NULL, "Secondary TDM0 Capture"}, 601 {"SEC_TDM_TX_1", NULL, "Secondary TDM1 Capture"}, 602 {"SEC_TDM_TX_2", NULL, "Secondary TDM2 Capture"}, 603 {"SEC_TDM_TX_3", NULL, "Secondary TDM3 Capture"}, 604 {"SEC_TDM_TX_4", NULL, "Secondary TDM4 Capture"}, 605 {"SEC_TDM_TX_5", NULL, "Secondary TDM5 Capture"}, 606 {"SEC_TDM_TX_6", NULL, "Secondary TDM6 Capture"}, 607 {"SEC_TDM_TX_7", NULL, "Secondary TDM7 Capture"}, 608 609 {"TERT_TDM_TX_0", NULL, "Tertiary TDM0 Capture"}, 610 {"TERT_TDM_TX_1", NULL, "Tertiary TDM1 Capture"}, 611 {"TERT_TDM_TX_2", NULL, "Tertiary TDM2 Capture"}, 612 {"TERT_TDM_TX_3", NULL, "Tertiary TDM3 Capture"}, 613 {"TERT_TDM_TX_4", NULL, "Tertiary TDM4 Capture"}, 614 {"TERT_TDM_TX_5", NULL, "Tertiary TDM5 Capture"}, 615 {"TERT_TDM_TX_6", NULL, "Tertiary TDM6 Capture"}, 616 {"TERT_TDM_TX_7", NULL, "Tertiary TDM7 Capture"}, 617 618 {"QUAT_TDM_TX_0", NULL, "Quaternary TDM0 Capture"}, 619 {"QUAT_TDM_TX_1", NULL, "Quaternary TDM1 Capture"}, 620 {"QUAT_TDM_TX_2", NULL, "Quaternary TDM2 Capture"}, 621 {"QUAT_TDM_TX_3", NULL, "Quaternary TDM3 Capture"}, 622 {"QUAT_TDM_TX_4", NULL, "Quaternary TDM4 Capture"}, 623 {"QUAT_TDM_TX_5", NULL, "Quaternary TDM5 Capture"}, 624 {"QUAT_TDM_TX_6", NULL, "Quaternary TDM6 Capture"}, 625 {"QUAT_TDM_TX_7", NULL, "Quaternary TDM7 Capture"}, 626 627 {"QUIN_TDM_TX_0", NULL, "Quinary TDM0 Capture"}, 628 {"QUIN_TDM_TX_1", NULL, "Quinary TDM1 Capture"}, 629 {"QUIN_TDM_TX_2", NULL, "Quinary TDM2 Capture"}, 630 {"QUIN_TDM_TX_3", NULL, "Quinary TDM3 Capture"}, 631 {"QUIN_TDM_TX_4", NULL, "Quinary TDM4 Capture"}, 632 {"QUIN_TDM_TX_5", NULL, "Quinary TDM5 Capture"}, 633 {"QUIN_TDM_TX_6", NULL, "Quinary TDM6 Capture"}, 634 {"QUIN_TDM_TX_7", NULL, "Quinary TDM7 Capture"}, 635 636 {"TERT_MI2S_TX", NULL, "Tertiary MI2S Capture"}, 637 {"PRI_MI2S_TX", NULL, "Primary MI2S Capture"}, 638 {"SEC_MI2S_TX", NULL, "Secondary MI2S Capture"}, 639 {"QUAT_MI2S_TX", NULL, "Quaternary MI2S Capture"}, 640 {"QUIN_MI2S_TX", NULL, "Quinary MI2S Capture"}, 641 {"SEN_MI2S_TX", NULL, "Senary MI2S Capture"}, 642 643 {"WSA_CODEC_DMA_RX_0 Playback", NULL, "WSA_CODEC_DMA_RX_0"}, 644 {"WSA_CODEC_DMA_TX_0", NULL, "WSA_CODEC_DMA_TX_0 Capture"}, 645 {"WSA_CODEC_DMA_RX_1 Playback", NULL, "WSA_CODEC_DMA_RX_1"}, 646 {"WSA_CODEC_DMA_TX_1", NULL, "WSA_CODEC_DMA_TX_1 Capture"}, 647 {"WSA_CODEC_DMA_TX_2", NULL, "WSA_CODEC_DMA_TX_2 Capture"}, 648 {"VA_CODEC_DMA_TX_0", NULL, "VA_CODEC_DMA_TX_0 Capture"}, 649 {"VA_CODEC_DMA_TX_1", NULL, "VA_CODEC_DMA_TX_1 Capture"}, 650 {"VA_CODEC_DMA_TX_2", NULL, "VA_CODEC_DMA_TX_2 Capture"}, 651 {"RX_CODEC_DMA_RX_0 Playback", NULL, "RX_CODEC_DMA_RX_0"}, 652 {"TX_CODEC_DMA_TX_0", NULL, "TX_CODEC_DMA_TX_0 Capture"}, 653 {"RX_CODEC_DMA_RX_1 Playback", NULL, "RX_CODEC_DMA_RX_1"}, 654 {"TX_CODEC_DMA_TX_1", NULL, "TX_CODEC_DMA_TX_1 Capture"}, 655 {"RX_CODEC_DMA_RX_2 Playback", NULL, "RX_CODEC_DMA_RX_2"}, 656 {"TX_CODEC_DMA_TX_2", NULL, "TX_CODEC_DMA_TX_2 Capture"}, 657 {"RX_CODEC_DMA_RX_3 Playback", NULL, "RX_CODEC_DMA_RX_3"}, 658 {"TX_CODEC_DMA_TX_3", NULL, "TX_CODEC_DMA_TX_3 Capture"}, 659 {"RX_CODEC_DMA_RX_4 Playback", NULL, "RX_CODEC_DMA_RX_4"}, 660 {"TX_CODEC_DMA_TX_4", NULL, "TX_CODEC_DMA_TX_4 Capture"}, 661 {"RX_CODEC_DMA_RX_5 Playback", NULL, "RX_CODEC_DMA_RX_5"}, 662 {"TX_CODEC_DMA_TX_5", NULL, "TX_CODEC_DMA_TX_5 Capture"}, 663 {"RX_CODEC_DMA_RX_6 Playback", NULL, "RX_CODEC_DMA_RX_6"}, 664 {"RX_CODEC_DMA_RX_7 Playback", NULL, "RX_CODEC_DMA_RX_7"}, 665 666 /* USB playback AFE port receives data for playback, hence use the RX port */ 667 {"USB Playback", NULL, "USB_RX"}, 668 }; 669 670 static int msm_dai_q6_dai_probe(struct snd_soc_dai *dai) 671 { 672 struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev); 673 struct q6afe_port *port; 674 675 port = q6afe_port_get_from_id(dai->dev, dai->id); 676 if (IS_ERR(port)) { 677 dev_err(dai->dev, "Unable to get afe port\n"); 678 return -EINVAL; 679 } 680 dai_data->port[dai->id] = port; 681 682 return 0; 683 } 684 685 static int msm_dai_q6_dai_remove(struct snd_soc_dai *dai) 686 { 687 struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev); 688 689 q6afe_port_put(dai_data->port[dai->id]); 690 dai_data->port[dai->id] = NULL; 691 692 return 0; 693 } 694 695 static const struct snd_soc_dai_ops q6afe_usb_ops = { 696 .probe = msm_dai_q6_dai_probe, 697 .prepare = q6afe_dai_prepare, 698 .hw_params = q6afe_usb_hw_params, 699 /* 700 * Shutdown callback required to stop the USB AFE port, which is enabled 701 * by the prepare() stage. This stops the audio traffic on the USB AFE 702 * port on the Q6DSP. 703 */ 704 .shutdown = q6afe_dai_shutdown, 705 /* 706 * Startup callback not needed, as AFE port start command passes the PCM 707 * parameters within the AFE command, which is provided by the PCM core 708 * during the prepare() stage. 709 */ 710 }; 711 712 static const struct snd_soc_dai_ops q6hdmi_ops = { 713 .probe = msm_dai_q6_dai_probe, 714 .remove = msm_dai_q6_dai_remove, 715 .prepare = q6afe_dai_prepare, 716 .hw_params = q6hdmi_hw_params, 717 .shutdown = q6afe_dai_shutdown, 718 }; 719 720 static const struct snd_soc_dai_ops q6i2s_ops = { 721 .probe = msm_dai_q6_dai_probe, 722 .remove = msm_dai_q6_dai_remove, 723 .prepare = q6afe_dai_prepare, 724 .hw_params = q6i2s_hw_params, 725 .set_fmt = q6i2s_set_fmt, 726 .shutdown = q6afe_dai_shutdown, 727 .set_sysclk = q6afe_mi2s_set_sysclk, 728 }; 729 730 static const struct snd_soc_dai_ops q6slim_ops = { 731 .probe = msm_dai_q6_dai_probe, 732 .remove = msm_dai_q6_dai_remove, 733 .prepare = q6afe_dai_prepare, 734 .hw_params = q6slim_hw_params, 735 .shutdown = q6afe_dai_shutdown, 736 .set_channel_map = q6slim_set_channel_map, 737 }; 738 739 static const struct snd_soc_dai_ops q6tdm_ops = { 740 .probe = msm_dai_q6_dai_probe, 741 .remove = msm_dai_q6_dai_remove, 742 .prepare = q6afe_dai_prepare, 743 .shutdown = q6afe_dai_shutdown, 744 .set_sysclk = q6afe_mi2s_set_sysclk, 745 .set_tdm_slot = q6tdm_set_tdm_slot, 746 .set_channel_map = q6tdm_set_channel_map, 747 .hw_params = q6tdm_hw_params, 748 }; 749 750 static const struct snd_soc_dai_ops q6dma_ops = { 751 .probe = msm_dai_q6_dai_probe, 752 .remove = msm_dai_q6_dai_remove, 753 .prepare = q6afe_dai_prepare, 754 .shutdown = q6afe_dai_shutdown, 755 .set_sysclk = q6afe_mi2s_set_sysclk, 756 .set_channel_map = q6dma_set_channel_map, 757 .hw_params = q6dma_hw_params, 758 }; 759 760 static const struct snd_soc_dapm_widget q6afe_dai_widgets[] = { 761 SND_SOC_DAPM_AIF_IN("HDMI_RX", NULL, 0, SND_SOC_NOPM, 0, 0), 762 SND_SOC_DAPM_AIF_IN("SLIMBUS_0_RX", NULL, 0, SND_SOC_NOPM, 0, 0), 763 SND_SOC_DAPM_AIF_IN("SLIMBUS_1_RX", NULL, 0, SND_SOC_NOPM, 0, 0), 764 SND_SOC_DAPM_AIF_IN("SLIMBUS_2_RX", NULL, 0, SND_SOC_NOPM, 0, 0), 765 SND_SOC_DAPM_AIF_IN("SLIMBUS_3_RX", NULL, 0, SND_SOC_NOPM, 0, 0), 766 SND_SOC_DAPM_AIF_IN("SLIMBUS_4_RX", NULL, 0, SND_SOC_NOPM, 0, 0), 767 SND_SOC_DAPM_AIF_IN("SLIMBUS_5_RX", NULL, 0, SND_SOC_NOPM, 0, 0), 768 SND_SOC_DAPM_AIF_IN("SLIMBUS_6_RX", NULL, 0, SND_SOC_NOPM, 0, 0), 769 SND_SOC_DAPM_AIF_OUT("SLIMBUS_0_TX", NULL, 0, SND_SOC_NOPM, 0, 0), 770 SND_SOC_DAPM_AIF_OUT("SLIMBUS_1_TX", NULL, 0, SND_SOC_NOPM, 0, 0), 771 SND_SOC_DAPM_AIF_OUT("SLIMBUS_2_TX", NULL, 0, SND_SOC_NOPM, 0, 0), 772 SND_SOC_DAPM_AIF_OUT("SLIMBUS_3_TX", NULL, 0, SND_SOC_NOPM, 0, 0), 773 SND_SOC_DAPM_AIF_OUT("SLIMBUS_4_TX", NULL, 0, SND_SOC_NOPM, 0, 0), 774 SND_SOC_DAPM_AIF_OUT("SLIMBUS_5_TX", NULL, 0, SND_SOC_NOPM, 0, 0), 775 SND_SOC_DAPM_AIF_OUT("SLIMBUS_6_TX", NULL, 0, SND_SOC_NOPM, 0, 0), 776 SND_SOC_DAPM_AIF_IN("SEN_MI2S_RX", NULL, 0, SND_SOC_NOPM, 0, 0), 777 SND_SOC_DAPM_AIF_OUT("SEN_MI2S_TX", NULL, 0, SND_SOC_NOPM, 0, 0), 778 SND_SOC_DAPM_AIF_IN("QUIN_MI2S_RX", NULL, 779 0, SND_SOC_NOPM, 0, 0), 780 SND_SOC_DAPM_AIF_OUT("QUIN_MI2S_TX", NULL, 781 0, SND_SOC_NOPM, 0, 0), 782 SND_SOC_DAPM_AIF_IN("QUAT_MI2S_RX", NULL, 783 0, SND_SOC_NOPM, 0, 0), 784 SND_SOC_DAPM_AIF_OUT("QUAT_MI2S_TX", NULL, 785 0, SND_SOC_NOPM, 0, 0), 786 SND_SOC_DAPM_AIF_IN("TERT_MI2S_RX", NULL, 787 0, SND_SOC_NOPM, 0, 0), 788 SND_SOC_DAPM_AIF_OUT("TERT_MI2S_TX", NULL, 789 0, SND_SOC_NOPM, 0, 0), 790 SND_SOC_DAPM_AIF_IN("SEC_MI2S_RX", NULL, 791 0, SND_SOC_NOPM, 0, 0), 792 SND_SOC_DAPM_AIF_OUT("SEC_MI2S_TX", NULL, 793 0, SND_SOC_NOPM, 0, 0), 794 SND_SOC_DAPM_AIF_IN("SEC_MI2S_RX_SD1", 795 "Secondary MI2S Playback SD1", 796 0, SND_SOC_NOPM, 0, 0), 797 SND_SOC_DAPM_AIF_IN("PRI_MI2S_RX", NULL, 798 0, SND_SOC_NOPM, 0, 0), 799 SND_SOC_DAPM_AIF_OUT("PRI_MI2S_TX", NULL, 800 0, SND_SOC_NOPM, 0, 0), 801 802 SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_0", NULL, 803 0, SND_SOC_NOPM, 0, 0), 804 SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_1", NULL, 805 0, SND_SOC_NOPM, 0, 0), 806 SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_2", NULL, 807 0, SND_SOC_NOPM, 0, 0), 808 SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_3", NULL, 809 0, SND_SOC_NOPM, 0, 0), 810 SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_4", NULL, 811 0, SND_SOC_NOPM, 0, 0), 812 SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_5", NULL, 813 0, SND_SOC_NOPM, 0, 0), 814 SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_6", NULL, 815 0, SND_SOC_NOPM, 0, 0), 816 SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_7", NULL, 817 0, SND_SOC_NOPM, 0, 0), 818 SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_0", NULL, 819 0, SND_SOC_NOPM, 0, 0), 820 SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_1", NULL, 821 0, SND_SOC_NOPM, 0, 0), 822 SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_2", NULL, 823 0, SND_SOC_NOPM, 0, 0), 824 SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_3", NULL, 825 0, SND_SOC_NOPM, 0, 0), 826 SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_4", NULL, 827 0, SND_SOC_NOPM, 0, 0), 828 SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_5", NULL, 829 0, SND_SOC_NOPM, 0, 0), 830 SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_6", NULL, 831 0, SND_SOC_NOPM, 0, 0), 832 SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_7", NULL, 833 0, SND_SOC_NOPM, 0, 0), 834 835 SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_0", NULL, 836 0, SND_SOC_NOPM, 0, 0), 837 SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_1", NULL, 838 0, SND_SOC_NOPM, 0, 0), 839 SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_2", NULL, 840 0, SND_SOC_NOPM, 0, 0), 841 SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_3", NULL, 842 0, SND_SOC_NOPM, 0, 0), 843 SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_4", NULL, 844 0, SND_SOC_NOPM, 0, 0), 845 SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_5", NULL, 846 0, SND_SOC_NOPM, 0, 0), 847 SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_6", NULL, 848 0, SND_SOC_NOPM, 0, 0), 849 SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_7", NULL, 850 0, SND_SOC_NOPM, 0, 0), 851 SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_0", NULL, 852 0, SND_SOC_NOPM, 0, 0), 853 SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_1", NULL, 854 0, SND_SOC_NOPM, 0, 0), 855 SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_2", NULL, 856 0, SND_SOC_NOPM, 0, 0), 857 SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_3", NULL, 858 0, SND_SOC_NOPM, 0, 0), 859 SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_4", NULL, 860 0, SND_SOC_NOPM, 0, 0), 861 SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_5", NULL, 862 0, SND_SOC_NOPM, 0, 0), 863 SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_6", NULL, 864 0, SND_SOC_NOPM, 0, 0), 865 SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_7", NULL, 866 0, SND_SOC_NOPM, 0, 0), 867 868 SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_0", NULL, 869 0, SND_SOC_NOPM, 0, 0), 870 SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_1", NULL, 871 0, SND_SOC_NOPM, 0, 0), 872 SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_2", NULL, 873 0, SND_SOC_NOPM, 0, 0), 874 SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_3", NULL, 875 0, SND_SOC_NOPM, 0, 0), 876 SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_4", NULL, 877 0, SND_SOC_NOPM, 0, 0), 878 SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_5", NULL, 879 0, SND_SOC_NOPM, 0, 0), 880 SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_6", NULL, 881 0, SND_SOC_NOPM, 0, 0), 882 SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_7", NULL, 883 0, SND_SOC_NOPM, 0, 0), 884 SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_0", NULL, 885 0, SND_SOC_NOPM, 0, 0), 886 SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_1", NULL, 887 0, SND_SOC_NOPM, 0, 0), 888 SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_2", NULL, 889 0, SND_SOC_NOPM, 0, 0), 890 SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_3", NULL, 891 0, SND_SOC_NOPM, 0, 0), 892 SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_4", NULL, 893 0, SND_SOC_NOPM, 0, 0), 894 SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_5", NULL, 895 0, SND_SOC_NOPM, 0, 0), 896 SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_6", NULL, 897 0, SND_SOC_NOPM, 0, 0), 898 SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_7", NULL, 899 0, SND_SOC_NOPM, 0, 0), 900 901 SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_0", NULL, 902 0, SND_SOC_NOPM, 0, 0), 903 SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_1", NULL, 904 0, SND_SOC_NOPM, 0, 0), 905 SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_2", NULL, 906 0, SND_SOC_NOPM, 0, 0), 907 SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_3", NULL, 908 0, SND_SOC_NOPM, 0, 0), 909 SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_4", NULL, 910 0, SND_SOC_NOPM, 0, 0), 911 SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_5", NULL, 912 0, SND_SOC_NOPM, 0, 0), 913 SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_6", NULL, 914 0, SND_SOC_NOPM, 0, 0), 915 SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_7", NULL, 916 0, SND_SOC_NOPM, 0, 0), 917 SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_0", NULL, 918 0, SND_SOC_NOPM, 0, 0), 919 SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_1", NULL, 920 0, SND_SOC_NOPM, 0, 0), 921 SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_2", NULL, 922 0, SND_SOC_NOPM, 0, 0), 923 SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_3", NULL, 924 0, SND_SOC_NOPM, 0, 0), 925 SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_4", NULL, 926 0, SND_SOC_NOPM, 0, 0), 927 SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_5", NULL, 928 0, SND_SOC_NOPM, 0, 0), 929 SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_6", NULL, 930 0, SND_SOC_NOPM, 0, 0), 931 SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_7", NULL, 932 0, SND_SOC_NOPM, 0, 0), 933 934 SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_0", NULL, 935 0, SND_SOC_NOPM, 0, 0), 936 SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_1", NULL, 937 0, SND_SOC_NOPM, 0, 0), 938 SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_2", NULL, 939 0, SND_SOC_NOPM, 0, 0), 940 SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_3", NULL, 941 0, SND_SOC_NOPM, 0, 0), 942 SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_4", NULL, 943 0, SND_SOC_NOPM, 0, 0), 944 SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_5", NULL, 945 0, SND_SOC_NOPM, 0, 0), 946 SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_6", NULL, 947 0, SND_SOC_NOPM, 0, 0), 948 SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_7", NULL, 949 0, SND_SOC_NOPM, 0, 0), 950 SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_0", NULL, 951 0, SND_SOC_NOPM, 0, 0), 952 SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_1", NULL, 953 0, SND_SOC_NOPM, 0, 0), 954 SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_2", NULL, 955 0, SND_SOC_NOPM, 0, 0), 956 SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_3", NULL, 957 0, SND_SOC_NOPM, 0, 0), 958 SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_4", NULL, 959 0, SND_SOC_NOPM, 0, 0), 960 SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_5", NULL, 961 0, SND_SOC_NOPM, 0, 0), 962 SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_6", NULL, 963 0, SND_SOC_NOPM, 0, 0), 964 SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_7", NULL, 965 0, SND_SOC_NOPM, 0, 0), 966 SND_SOC_DAPM_AIF_OUT("DISPLAY_PORT_RX", "NULL", 0, SND_SOC_NOPM, 0, 0), 967 968 SND_SOC_DAPM_AIF_IN("WSA_CODEC_DMA_RX_0", "NULL", 969 0, SND_SOC_NOPM, 0, 0), 970 SND_SOC_DAPM_AIF_OUT("WSA_CODEC_DMA_TX_0", "NULL", 971 0, SND_SOC_NOPM, 0, 0), 972 SND_SOC_DAPM_AIF_IN("WSA_CODEC_DMA_RX_1", "NULL", 973 0, SND_SOC_NOPM, 0, 0), 974 SND_SOC_DAPM_AIF_OUT("WSA_CODEC_DMA_TX_1", "NULL", 975 0, SND_SOC_NOPM, 0, 0), 976 SND_SOC_DAPM_AIF_OUT("WSA_CODEC_DMA_TX_2", "NULL", 977 0, SND_SOC_NOPM, 0, 0), 978 SND_SOC_DAPM_AIF_OUT("VA_CODEC_DMA_TX_0", "NULL", 979 0, SND_SOC_NOPM, 0, 0), 980 SND_SOC_DAPM_AIF_OUT("VA_CODEC_DMA_TX_1", "NULL", 981 0, SND_SOC_NOPM, 0, 0), 982 SND_SOC_DAPM_AIF_OUT("VA_CODEC_DMA_TX_2", "NULL", 983 0, SND_SOC_NOPM, 0, 0), 984 SND_SOC_DAPM_AIF_IN("RX_CODEC_DMA_RX_0", "NULL", 985 0, SND_SOC_NOPM, 0, 0), 986 SND_SOC_DAPM_AIF_OUT("TX_CODEC_DMA_TX_0", "NULL", 987 0, SND_SOC_NOPM, 0, 0), 988 SND_SOC_DAPM_AIF_IN("RX_CODEC_DMA_RX_1", "NULL", 989 0, SND_SOC_NOPM, 0, 0), 990 SND_SOC_DAPM_AIF_OUT("TX_CODEC_DMA_TX_1", "NULL", 991 0, SND_SOC_NOPM, 0, 0), 992 SND_SOC_DAPM_AIF_IN("RX_CODEC_DMA_RX_2", "NULL", 993 0, SND_SOC_NOPM, 0, 0), 994 SND_SOC_DAPM_AIF_OUT("TX_CODEC_DMA_TX_2", "NULL", 995 0, SND_SOC_NOPM, 0, 0), 996 SND_SOC_DAPM_AIF_IN("RX_CODEC_DMA_RX_3", "NULL", 997 0, SND_SOC_NOPM, 0, 0), 998 SND_SOC_DAPM_AIF_OUT("TX_CODEC_DMA_TX_3", "NULL", 999 0, SND_SOC_NOPM, 0, 0), 1000 SND_SOC_DAPM_AIF_IN("RX_CODEC_DMA_RX_4", "NULL", 1001 0, SND_SOC_NOPM, 0, 0), 1002 SND_SOC_DAPM_AIF_OUT("TX_CODEC_DMA_TX_4", "NULL", 1003 0, SND_SOC_NOPM, 0, 0), 1004 SND_SOC_DAPM_AIF_IN("RX_CODEC_DMA_RX_5", "NULL", 1005 0, SND_SOC_NOPM, 0, 0), 1006 SND_SOC_DAPM_AIF_OUT("TX_CODEC_DMA_TX_5", "NULL", 1007 0, SND_SOC_NOPM, 0, 0), 1008 SND_SOC_DAPM_AIF_IN("RX_CODEC_DMA_RX_6", "NULL", 1009 0, SND_SOC_NOPM, 0, 0), 1010 SND_SOC_DAPM_AIF_IN("RX_CODEC_DMA_RX_7", "NULL", 1011 0, SND_SOC_NOPM, 0, 0), 1012 1013 SND_SOC_DAPM_AIF_IN("USB_RX", NULL, 0, SND_SOC_NOPM, 0, 0), 1014 }; 1015 1016 static const struct snd_soc_component_driver q6afe_dai_component = { 1017 .name = "q6afe-dai-component", 1018 .dapm_widgets = q6afe_dai_widgets, 1019 .num_dapm_widgets = ARRAY_SIZE(q6afe_dai_widgets), 1020 .dapm_routes = q6afe_dapm_routes, 1021 .num_dapm_routes = ARRAY_SIZE(q6afe_dapm_routes), 1022 .of_xlate_dai_name = q6dsp_audio_ports_of_xlate_dai_name, 1023 1024 }; 1025 1026 static void of_q6afe_parse_dai_data(struct device *dev, 1027 struct q6afe_dai_data *data) 1028 { 1029 struct device_node *node; 1030 int ret; 1031 1032 for_each_child_of_node(dev->of_node, node) { 1033 unsigned int lines[Q6AFE_MAX_MI2S_LINES]; 1034 struct q6afe_dai_priv_data *priv; 1035 int id, i, num_lines; 1036 1037 ret = of_property_read_u32(node, "reg", &id); 1038 if (ret || id < 0 || id >= AFE_PORT_MAX) { 1039 dev_err(dev, "valid dai id not found:%d\n", ret); 1040 continue; 1041 } 1042 1043 switch (id) { 1044 /* MI2S specific properties */ 1045 case SENARY_MI2S_RX ... SENARY_MI2S_TX: 1046 case QUINARY_MI2S_RX ... QUINARY_MI2S_TX: 1047 case PRIMARY_MI2S_RX ... QUATERNARY_MI2S_TX: 1048 priv = &data->priv[id]; 1049 ret = of_property_read_variable_u32_array(node, 1050 "qcom,sd-lines", 1051 lines, 0, 1052 Q6AFE_MAX_MI2S_LINES); 1053 if (ret < 0) 1054 num_lines = 0; 1055 else 1056 num_lines = ret; 1057 1058 priv->sd_line_mask = 0; 1059 1060 for (i = 0; i < num_lines; i++) 1061 priv->sd_line_mask |= BIT(lines[i]); 1062 1063 break; 1064 case PRIMARY_TDM_RX_0 ... QUINARY_TDM_TX_7: 1065 priv = &data->priv[id]; 1066 ret = of_property_read_u32(node, "qcom,tdm-sync-mode", 1067 &priv->sync_mode); 1068 if (ret) { 1069 dev_err(dev, "No Sync mode from DT\n"); 1070 break; 1071 } 1072 ret = of_property_read_u32(node, "qcom,tdm-sync-src", 1073 &priv->sync_src); 1074 if (ret) { 1075 dev_err(dev, "No Sync Src from DT\n"); 1076 break; 1077 } 1078 ret = of_property_read_u32(node, "qcom,tdm-data-out", 1079 &priv->data_out_enable); 1080 if (ret) { 1081 dev_err(dev, "No Data out enable from DT\n"); 1082 break; 1083 } 1084 ret = of_property_read_u32(node, "qcom,tdm-invert-sync", 1085 &priv->invert_sync); 1086 if (ret) { 1087 dev_err(dev, "No Invert sync from DT\n"); 1088 break; 1089 } 1090 ret = of_property_read_u32(node, "qcom,tdm-data-delay", 1091 &priv->data_delay); 1092 if (ret) { 1093 dev_err(dev, "No Data Delay from DT\n"); 1094 break; 1095 } 1096 ret = of_property_read_u32(node, "qcom,tdm-data-align", 1097 &priv->data_align); 1098 if (ret) { 1099 dev_err(dev, "No Data align from DT\n"); 1100 break; 1101 } 1102 break; 1103 default: 1104 break; 1105 } 1106 } 1107 } 1108 1109 static int q6afe_dai_dev_probe(struct platform_device *pdev) 1110 { 1111 struct q6dsp_audio_port_dai_driver_config cfg; 1112 struct snd_soc_dai_driver *dais; 1113 struct q6afe_dai_data *dai_data; 1114 struct device *dev = &pdev->dev; 1115 int num_dais; 1116 1117 dai_data = devm_kzalloc(dev, sizeof(*dai_data), GFP_KERNEL); 1118 if (!dai_data) 1119 return -ENOMEM; 1120 1121 dev_set_drvdata(dev, dai_data); 1122 of_q6afe_parse_dai_data(dev, dai_data); 1123 1124 cfg.q6hdmi_ops = &q6hdmi_ops; 1125 cfg.q6slim_ops = &q6slim_ops; 1126 cfg.q6i2s_ops = &q6i2s_ops; 1127 cfg.q6tdm_ops = &q6tdm_ops; 1128 cfg.q6dma_ops = &q6dma_ops; 1129 cfg.q6usb_ops = &q6afe_usb_ops; 1130 dais = q6dsp_audio_ports_set_config(dev, &cfg, &num_dais); 1131 1132 return devm_snd_soc_register_component(dev, &q6afe_dai_component, dais, num_dais); 1133 } 1134 1135 #ifdef CONFIG_OF 1136 static const struct of_device_id q6afe_dai_device_id[] = { 1137 { .compatible = "qcom,q6afe-dais" }, 1138 {}, 1139 }; 1140 MODULE_DEVICE_TABLE(of, q6afe_dai_device_id); 1141 #endif 1142 1143 static struct platform_driver q6afe_dai_platform_driver = { 1144 .driver = { 1145 .name = "q6afe-dai", 1146 .of_match_table = of_match_ptr(q6afe_dai_device_id), 1147 }, 1148 .probe = q6afe_dai_dev_probe, 1149 }; 1150 module_platform_driver(q6afe_dai_platform_driver); 1151 1152 MODULE_DESCRIPTION("Q6 Audio Frontend dai driver"); 1153 MODULE_LICENSE("GPL v2"); 1154