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