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/component.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 "q6afe.h" 16 17 #define Q6AFE_TDM_PB_DAI(pre, num, did) { \ 18 .playback = { \ 19 .stream_name = pre" TDM"#num" Playback", \ 20 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ 21 SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\ 22 SNDRV_PCM_RATE_176400, \ 23 .formats = SNDRV_PCM_FMTBIT_S16_LE | \ 24 SNDRV_PCM_FMTBIT_S24_LE | \ 25 SNDRV_PCM_FMTBIT_S32_LE, \ 26 .channels_min = 1, \ 27 .channels_max = 8, \ 28 .rate_min = 8000, \ 29 .rate_max = 176400, \ 30 }, \ 31 .name = #did, \ 32 .ops = &q6tdm_ops, \ 33 .id = did, \ 34 .probe = msm_dai_q6_dai_probe, \ 35 .remove = msm_dai_q6_dai_remove, \ 36 } 37 38 #define Q6AFE_TDM_CAP_DAI(pre, num, did) { \ 39 .capture = { \ 40 .stream_name = pre" TDM"#num" Capture", \ 41 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ 42 SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\ 43 SNDRV_PCM_RATE_176400, \ 44 .formats = SNDRV_PCM_FMTBIT_S16_LE | \ 45 SNDRV_PCM_FMTBIT_S24_LE | \ 46 SNDRV_PCM_FMTBIT_S32_LE, \ 47 .channels_min = 1, \ 48 .channels_max = 8, \ 49 .rate_min = 8000, \ 50 .rate_max = 176400, \ 51 }, \ 52 .name = #did, \ 53 .ops = &q6tdm_ops, \ 54 .id = did, \ 55 .probe = msm_dai_q6_dai_probe, \ 56 .remove = msm_dai_q6_dai_remove, \ 57 } 58 59 struct q6afe_dai_priv_data { 60 uint32_t sd_line_mask; 61 uint32_t sync_mode; 62 uint32_t sync_src; 63 uint32_t data_out_enable; 64 uint32_t invert_sync; 65 uint32_t data_delay; 66 uint32_t data_align; 67 }; 68 69 struct q6afe_dai_data { 70 struct q6afe_port *port[AFE_PORT_MAX]; 71 struct q6afe_port_config port_config[AFE_PORT_MAX]; 72 bool is_port_started[AFE_PORT_MAX]; 73 struct q6afe_dai_priv_data priv[AFE_PORT_MAX]; 74 }; 75 76 static int q6slim_hw_params(struct snd_pcm_substream *substream, 77 struct snd_pcm_hw_params *params, 78 struct snd_soc_dai *dai) 79 { 80 81 struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev); 82 struct q6afe_slim_cfg *slim = &dai_data->port_config[dai->id].slim; 83 84 slim->num_channels = params_channels(params); 85 slim->sample_rate = params_rate(params); 86 87 switch (params_format(params)) { 88 case SNDRV_PCM_FORMAT_S16_LE: 89 case SNDRV_PCM_FORMAT_SPECIAL: 90 slim->bit_width = 16; 91 break; 92 case SNDRV_PCM_FORMAT_S24_LE: 93 slim->bit_width = 24; 94 break; 95 case SNDRV_PCM_FORMAT_S32_LE: 96 slim->bit_width = 32; 97 break; 98 default: 99 pr_err("%s: format %d\n", 100 __func__, params_format(params)); 101 return -EINVAL; 102 } 103 104 return 0; 105 } 106 107 static int q6hdmi_hw_params(struct snd_pcm_substream *substream, 108 struct snd_pcm_hw_params *params, 109 struct snd_soc_dai *dai) 110 { 111 struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev); 112 int channels = params_channels(params); 113 struct q6afe_hdmi_cfg *hdmi = &dai_data->port_config[dai->id].hdmi; 114 115 hdmi->sample_rate = params_rate(params); 116 switch (params_format(params)) { 117 case SNDRV_PCM_FORMAT_S16_LE: 118 hdmi->bit_width = 16; 119 break; 120 case SNDRV_PCM_FORMAT_S24_LE: 121 hdmi->bit_width = 24; 122 break; 123 } 124 125 /* HDMI spec CEA-861-E: Table 28 Audio InfoFrame Data Byte 4 */ 126 switch (channels) { 127 case 2: 128 hdmi->channel_allocation = 0; 129 break; 130 case 3: 131 hdmi->channel_allocation = 0x02; 132 break; 133 case 4: 134 hdmi->channel_allocation = 0x06; 135 break; 136 case 5: 137 hdmi->channel_allocation = 0x0A; 138 break; 139 case 6: 140 hdmi->channel_allocation = 0x0B; 141 break; 142 case 7: 143 hdmi->channel_allocation = 0x12; 144 break; 145 case 8: 146 hdmi->channel_allocation = 0x13; 147 break; 148 default: 149 dev_err(dai->dev, "invalid Channels = %u\n", channels); 150 return -EINVAL; 151 } 152 153 return 0; 154 } 155 156 static int q6i2s_hw_params(struct snd_pcm_substream *substream, 157 struct snd_pcm_hw_params *params, 158 struct snd_soc_dai *dai) 159 { 160 struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev); 161 struct q6afe_i2s_cfg *i2s = &dai_data->port_config[dai->id].i2s_cfg; 162 163 i2s->sample_rate = params_rate(params); 164 i2s->bit_width = params_width(params); 165 i2s->num_channels = params_channels(params); 166 i2s->sd_line_mask = dai_data->priv[dai->id].sd_line_mask; 167 168 return 0; 169 } 170 171 static int q6i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 172 { 173 struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev); 174 struct q6afe_i2s_cfg *i2s = &dai_data->port_config[dai->id].i2s_cfg; 175 176 i2s->fmt = fmt; 177 178 return 0; 179 } 180 181 static int q6tdm_set_tdm_slot(struct snd_soc_dai *dai, 182 unsigned int tx_mask, 183 unsigned int rx_mask, 184 int slots, int slot_width) 185 { 186 187 struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev); 188 struct q6afe_tdm_cfg *tdm = &dai_data->port_config[dai->id].tdm; 189 unsigned int cap_mask; 190 int rc = 0; 191 192 /* HW only supports 16 and 32 bit slot width configuration */ 193 if ((slot_width != 16) && (slot_width != 32)) { 194 dev_err(dai->dev, "%s: invalid slot_width %d\n", 195 __func__, slot_width); 196 return -EINVAL; 197 } 198 199 /* HW supports 1-32 slots configuration. Typical: 1, 2, 4, 8, 16, 32 */ 200 switch (slots) { 201 case 2: 202 cap_mask = 0x03; 203 break; 204 case 4: 205 cap_mask = 0x0F; 206 break; 207 case 8: 208 cap_mask = 0xFF; 209 break; 210 case 16: 211 cap_mask = 0xFFFF; 212 break; 213 default: 214 dev_err(dai->dev, "%s: invalid slots %d\n", 215 __func__, slots); 216 return -EINVAL; 217 } 218 219 switch (dai->id) { 220 case PRIMARY_TDM_RX_0 ... QUINARY_TDM_TX_7: 221 tdm->nslots_per_frame = slots; 222 tdm->slot_width = slot_width; 223 /* TDM RX dais ids are even and tx are odd */ 224 tdm->slot_mask = (dai->id & 0x1 ? tx_mask : rx_mask) & cap_mask; 225 break; 226 default: 227 dev_err(dai->dev, "%s: invalid dai id 0x%x\n", 228 __func__, dai->id); 229 return -EINVAL; 230 } 231 232 return rc; 233 } 234 235 static int q6tdm_set_channel_map(struct snd_soc_dai *dai, 236 unsigned int tx_num, unsigned int *tx_slot, 237 unsigned int rx_num, unsigned int *rx_slot) 238 { 239 240 struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev); 241 struct q6afe_tdm_cfg *tdm = &dai_data->port_config[dai->id].tdm; 242 int rc = 0; 243 int i = 0; 244 245 switch (dai->id) { 246 case PRIMARY_TDM_RX_0 ... QUINARY_TDM_TX_7: 247 if (dai->id & 0x1) { 248 if (!tx_slot) { 249 dev_err(dai->dev, "tx slot not found\n"); 250 return -EINVAL; 251 } 252 if (tx_num > AFE_PORT_MAX_AUDIO_CHAN_CNT) { 253 dev_err(dai->dev, "invalid tx num %d\n", 254 tx_num); 255 return -EINVAL; 256 } 257 258 for (i = 0; i < tx_num; i++) 259 tdm->ch_mapping[i] = tx_slot[i]; 260 261 for (i = tx_num; i < AFE_PORT_MAX_AUDIO_CHAN_CNT; i++) 262 tdm->ch_mapping[i] = Q6AFE_CMAP_INVALID; 263 264 tdm->num_channels = tx_num; 265 } else { 266 /* rx */ 267 if (!rx_slot) { 268 dev_err(dai->dev, "rx slot not found\n"); 269 return -EINVAL; 270 } 271 if (rx_num > AFE_PORT_MAX_AUDIO_CHAN_CNT) { 272 dev_err(dai->dev, "invalid rx num %d\n", 273 rx_num); 274 return -EINVAL; 275 } 276 277 for (i = 0; i < rx_num; i++) 278 tdm->ch_mapping[i] = rx_slot[i]; 279 280 for (i = rx_num; i < AFE_PORT_MAX_AUDIO_CHAN_CNT; i++) 281 tdm->ch_mapping[i] = Q6AFE_CMAP_INVALID; 282 283 tdm->num_channels = rx_num; 284 } 285 286 break; 287 default: 288 dev_err(dai->dev, "%s: invalid dai id 0x%x\n", 289 __func__, dai->id); 290 return -EINVAL; 291 } 292 293 return rc; 294 } 295 296 static int q6tdm_hw_params(struct snd_pcm_substream *substream, 297 struct snd_pcm_hw_params *params, 298 struct snd_soc_dai *dai) 299 { 300 struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev); 301 struct q6afe_tdm_cfg *tdm = &dai_data->port_config[dai->id].tdm; 302 303 tdm->bit_width = params_width(params); 304 tdm->sample_rate = params_rate(params); 305 tdm->num_channels = params_channels(params); 306 tdm->data_align_type = dai_data->priv[dai->id].data_align; 307 tdm->sync_src = dai_data->priv[dai->id].sync_src; 308 tdm->sync_mode = dai_data->priv[dai->id].sync_mode; 309 310 return 0; 311 } 312 static void q6afe_dai_shutdown(struct snd_pcm_substream *substream, 313 struct snd_soc_dai *dai) 314 { 315 struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev); 316 int rc; 317 318 rc = q6afe_port_stop(dai_data->port[dai->id]); 319 if (rc < 0) 320 dev_err(dai->dev, "fail to close AFE port (%d)\n", rc); 321 322 dai_data->is_port_started[dai->id] = false; 323 324 } 325 326 static int q6afe_dai_prepare(struct snd_pcm_substream *substream, 327 struct snd_soc_dai *dai) 328 { 329 struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev); 330 int rc; 331 332 if (dai_data->is_port_started[dai->id]) { 333 /* stop the port and restart with new port config */ 334 rc = q6afe_port_stop(dai_data->port[dai->id]); 335 if (rc < 0) { 336 dev_err(dai->dev, "fail to close AFE port (%d)\n", rc); 337 return rc; 338 } 339 } 340 341 switch (dai->id) { 342 case HDMI_RX: 343 q6afe_hdmi_port_prepare(dai_data->port[dai->id], 344 &dai_data->port_config[dai->id].hdmi); 345 break; 346 case SLIMBUS_0_RX ... SLIMBUS_6_TX: 347 q6afe_slim_port_prepare(dai_data->port[dai->id], 348 &dai_data->port_config[dai->id].slim); 349 break; 350 case PRIMARY_MI2S_RX ... QUATERNARY_MI2S_TX: 351 rc = q6afe_i2s_port_prepare(dai_data->port[dai->id], 352 &dai_data->port_config[dai->id].i2s_cfg); 353 if (rc < 0) { 354 dev_err(dai->dev, "fail to prepare AFE port %x\n", 355 dai->id); 356 return rc; 357 } 358 break; 359 case PRIMARY_TDM_RX_0 ... QUINARY_TDM_TX_7: 360 q6afe_tdm_port_prepare(dai_data->port[dai->id], 361 &dai_data->port_config[dai->id].tdm); 362 break; 363 default: 364 return -EINVAL; 365 } 366 367 rc = q6afe_port_start(dai_data->port[dai->id]); 368 if (rc < 0) { 369 dev_err(dai->dev, "fail to start AFE port %x\n", dai->id); 370 return rc; 371 } 372 dai_data->is_port_started[dai->id] = true; 373 374 return 0; 375 } 376 377 static int q6slim_set_channel_map(struct snd_soc_dai *dai, 378 unsigned int tx_num, unsigned int *tx_slot, 379 unsigned int rx_num, unsigned int *rx_slot) 380 { 381 struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev); 382 struct q6afe_port_config *pcfg = &dai_data->port_config[dai->id]; 383 int i; 384 385 if (!rx_slot) { 386 pr_err("%s: rx slot not found\n", __func__); 387 return -EINVAL; 388 } 389 390 for (i = 0; i < rx_num; i++) { 391 pcfg->slim.ch_mapping[i] = rx_slot[i]; 392 pr_debug("%s: find number of channels[%d] ch[%d]\n", 393 __func__, i, rx_slot[i]); 394 } 395 396 pcfg->slim.num_channels = rx_num; 397 398 pr_debug("%s: SLIMBUS_%d_RX cnt[%d] ch[%d %d]\n", __func__, 399 (dai->id - SLIMBUS_0_RX) / 2, rx_num, 400 pcfg->slim.ch_mapping[0], 401 pcfg->slim.ch_mapping[1]); 402 403 return 0; 404 } 405 406 static int q6afe_mi2s_set_sysclk(struct snd_soc_dai *dai, 407 int clk_id, unsigned int freq, int dir) 408 { 409 struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev); 410 struct q6afe_port *port = dai_data->port[dai->id]; 411 412 switch (clk_id) { 413 case LPAIF_DIG_CLK: 414 return q6afe_port_set_sysclk(port, clk_id, 0, 5, freq, dir); 415 case LPAIF_BIT_CLK: 416 case LPAIF_OSR_CLK: 417 return q6afe_port_set_sysclk(port, clk_id, 418 Q6AFE_LPASS_CLK_SRC_INTERNAL, 419 Q6AFE_LPASS_CLK_ROOT_DEFAULT, 420 freq, dir); 421 case Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT ... Q6AFE_LPASS_CLK_ID_QUI_MI2S_OSR: 422 case Q6AFE_LPASS_CLK_ID_MCLK_1 ... Q6AFE_LPASS_CLK_ID_INT_MCLK_1: 423 return q6afe_port_set_sysclk(port, clk_id, 424 Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO, 425 Q6AFE_LPASS_CLK_ROOT_DEFAULT, 426 freq, dir); 427 case Q6AFE_LPASS_CLK_ID_PRI_TDM_IBIT ... Q6AFE_LPASS_CLK_ID_QUIN_TDM_EBIT: 428 return q6afe_port_set_sysclk(port, clk_id, 429 Q6AFE_LPASS_CLK_ATTRIBUTE_INVERT_COUPLE_NO, 430 Q6AFE_LPASS_CLK_ROOT_DEFAULT, 431 freq, dir); 432 } 433 434 return 0; 435 } 436 437 static const struct snd_soc_dapm_route q6afe_dapm_routes[] = { 438 {"HDMI Playback", NULL, "HDMI_RX"}, 439 {"Slimbus1 Playback", NULL, "SLIMBUS_1_RX"}, 440 {"Slimbus2 Playback", NULL, "SLIMBUS_2_RX"}, 441 {"Slimbus3 Playback", NULL, "SLIMBUS_3_RX"}, 442 {"Slimbus4 Playback", NULL, "SLIMBUS_4_RX"}, 443 {"Slimbus5 Playback", NULL, "SLIMBUS_5_RX"}, 444 {"Slimbus6 Playback", NULL, "SLIMBUS_6_RX"}, 445 446 {"Primary MI2S Playback", NULL, "PRI_MI2S_RX"}, 447 {"Secondary MI2S Playback", NULL, "SEC_MI2S_RX"}, 448 {"Tertiary MI2S Playback", NULL, "TERT_MI2S_RX"}, 449 {"Quaternary MI2S Playback", NULL, "QUAT_MI2S_RX"}, 450 451 {"Primary TDM0 Playback", NULL, "PRIMARY_TDM_RX_0"}, 452 {"Primary TDM1 Playback", NULL, "PRIMARY_TDM_RX_1"}, 453 {"Primary TDM2 Playback", NULL, "PRIMARY_TDM_RX_2"}, 454 {"Primary TDM3 Playback", NULL, "PRIMARY_TDM_RX_3"}, 455 {"Primary TDM4 Playback", NULL, "PRIMARY_TDM_RX_4"}, 456 {"Primary TDM5 Playback", NULL, "PRIMARY_TDM_RX_5"}, 457 {"Primary TDM6 Playback", NULL, "PRIMARY_TDM_RX_6"}, 458 {"Primary TDM7 Playback", NULL, "PRIMARY_TDM_RX_7"}, 459 460 {"Secondary TDM0 Playback", NULL, "SEC_TDM_RX_0"}, 461 {"Secondary TDM1 Playback", NULL, "SEC_TDM_RX_1"}, 462 {"Secondary TDM2 Playback", NULL, "SEC_TDM_RX_2"}, 463 {"Secondary TDM3 Playback", NULL, "SEC_TDM_RX_3"}, 464 {"Secondary TDM4 Playback", NULL, "SEC_TDM_RX_4"}, 465 {"Secondary TDM5 Playback", NULL, "SEC_TDM_RX_5"}, 466 {"Secondary TDM6 Playback", NULL, "SEC_TDM_RX_6"}, 467 {"Secondary TDM7 Playback", NULL, "SEC_TDM_RX_7"}, 468 469 {"Tertiary TDM0 Playback", NULL, "TERT_TDM_RX_0"}, 470 {"Tertiary TDM1 Playback", NULL, "TERT_TDM_RX_1"}, 471 {"Tertiary TDM2 Playback", NULL, "TERT_TDM_RX_2"}, 472 {"Tertiary TDM3 Playback", NULL, "TERT_TDM_RX_3"}, 473 {"Tertiary TDM4 Playback", NULL, "TERT_TDM_RX_4"}, 474 {"Tertiary TDM5 Playback", NULL, "TERT_TDM_RX_5"}, 475 {"Tertiary TDM6 Playback", NULL, "TERT_TDM_RX_6"}, 476 {"Tertiary TDM7 Playback", NULL, "TERT_TDM_RX_7"}, 477 478 {"Quaternary TDM0 Playback", NULL, "QUAT_TDM_RX_0"}, 479 {"Quaternary TDM1 Playback", NULL, "QUAT_TDM_RX_1"}, 480 {"Quaternary TDM2 Playback", NULL, "QUAT_TDM_RX_2"}, 481 {"Quaternary TDM3 Playback", NULL, "QUAT_TDM_RX_3"}, 482 {"Quaternary TDM4 Playback", NULL, "QUAT_TDM_RX_4"}, 483 {"Quaternary TDM5 Playback", NULL, "QUAT_TDM_RX_5"}, 484 {"Quaternary TDM6 Playback", NULL, "QUAT_TDM_RX_6"}, 485 {"Quaternary TDM7 Playback", NULL, "QUAT_TDM_RX_7"}, 486 487 {"Quinary TDM0 Playback", NULL, "QUIN_TDM_RX_0"}, 488 {"Quinary TDM1 Playback", NULL, "QUIN_TDM_RX_1"}, 489 {"Quinary TDM2 Playback", NULL, "QUIN_TDM_RX_2"}, 490 {"Quinary TDM3 Playback", NULL, "QUIN_TDM_RX_3"}, 491 {"Quinary TDM4 Playback", NULL, "QUIN_TDM_RX_4"}, 492 {"Quinary TDM5 Playback", NULL, "QUIN_TDM_RX_5"}, 493 {"Quinary TDM6 Playback", NULL, "QUIN_TDM_RX_6"}, 494 {"Quinary TDM7 Playback", NULL, "QUIN_TDM_RX_7"}, 495 496 {"PRIMARY_TDM_TX_0", NULL, "Primary TDM0 Capture"}, 497 {"PRIMARY_TDM_TX_1", NULL, "Primary TDM1 Capture"}, 498 {"PRIMARY_TDM_TX_2", NULL, "Primary TDM2 Capture"}, 499 {"PRIMARY_TDM_TX_3", NULL, "Primary TDM3 Capture"}, 500 {"PRIMARY_TDM_TX_4", NULL, "Primary TDM4 Capture"}, 501 {"PRIMARY_TDM_TX_5", NULL, "Primary TDM5 Capture"}, 502 {"PRIMARY_TDM_TX_6", NULL, "Primary TDM6 Capture"}, 503 {"PRIMARY_TDM_TX_7", NULL, "Primary TDM7 Capture"}, 504 505 {"SEC_TDM_TX_0", NULL, "Secondary TDM0 Capture"}, 506 {"SEC_TDM_TX_1", NULL, "Secondary TDM1 Capture"}, 507 {"SEC_TDM_TX_2", NULL, "Secondary TDM2 Capture"}, 508 {"SEC_TDM_TX_3", NULL, "Secondary TDM3 Capture"}, 509 {"SEC_TDM_TX_4", NULL, "Secondary TDM4 Capture"}, 510 {"SEC_TDM_TX_5", NULL, "Secondary TDM5 Capture"}, 511 {"SEC_TDM_TX_6", NULL, "Secondary TDM6 Capture"}, 512 {"SEC_TDM_TX_7", NULL, "Secondary TDM7 Capture"}, 513 514 {"TERT_TDM_TX_0", NULL, "Tertiary TDM0 Capture"}, 515 {"TERT_TDM_TX_1", NULL, "Tertiary TDM1 Capture"}, 516 {"TERT_TDM_TX_2", NULL, "Tertiary TDM2 Capture"}, 517 {"TERT_TDM_TX_3", NULL, "Tertiary TDM3 Capture"}, 518 {"TERT_TDM_TX_4", NULL, "Tertiary TDM4 Capture"}, 519 {"TERT_TDM_TX_5", NULL, "Tertiary TDM5 Capture"}, 520 {"TERT_TDM_TX_6", NULL, "Tertiary TDM6 Capture"}, 521 {"TERT_TDM_TX_7", NULL, "Tertiary TDM7 Capture"}, 522 523 {"QUAT_TDM_TX_0", NULL, "Quaternary TDM0 Capture"}, 524 {"QUAT_TDM_TX_1", NULL, "Quaternary TDM1 Capture"}, 525 {"QUAT_TDM_TX_2", NULL, "Quaternary TDM2 Capture"}, 526 {"QUAT_TDM_TX_3", NULL, "Quaternary TDM3 Capture"}, 527 {"QUAT_TDM_TX_4", NULL, "Quaternary TDM4 Capture"}, 528 {"QUAT_TDM_TX_5", NULL, "Quaternary TDM5 Capture"}, 529 {"QUAT_TDM_TX_6", NULL, "Quaternary TDM6 Capture"}, 530 {"QUAT_TDM_TX_7", NULL, "Quaternary TDM7 Capture"}, 531 532 {"QUIN_TDM_TX_0", NULL, "Quinary TDM0 Capture"}, 533 {"QUIN_TDM_TX_1", NULL, "Quinary TDM1 Capture"}, 534 {"QUIN_TDM_TX_2", NULL, "Quinary TDM2 Capture"}, 535 {"QUIN_TDM_TX_3", NULL, "Quinary TDM3 Capture"}, 536 {"QUIN_TDM_TX_4", NULL, "Quinary TDM4 Capture"}, 537 {"QUIN_TDM_TX_5", NULL, "Quinary TDM5 Capture"}, 538 {"QUIN_TDM_TX_6", NULL, "Quinary TDM6 Capture"}, 539 {"QUIN_TDM_TX_7", NULL, "Quinary TDM7 Capture"}, 540 541 {"TERT_MI2S_TX", NULL, "Tertiary MI2S Capture"}, 542 {"PRI_MI2S_TX", NULL, "Primary MI2S Capture"}, 543 {"SEC_MI2S_TX", NULL, "Secondary MI2S Capture"}, 544 {"QUAT_MI2S_TX", NULL, "Quaternary MI2S Capture"}, 545 }; 546 547 static struct snd_soc_dai_ops q6hdmi_ops = { 548 .prepare = q6afe_dai_prepare, 549 .hw_params = q6hdmi_hw_params, 550 .shutdown = q6afe_dai_shutdown, 551 }; 552 553 static struct snd_soc_dai_ops q6i2s_ops = { 554 .prepare = q6afe_dai_prepare, 555 .hw_params = q6i2s_hw_params, 556 .set_fmt = q6i2s_set_fmt, 557 .shutdown = q6afe_dai_shutdown, 558 .set_sysclk = q6afe_mi2s_set_sysclk, 559 }; 560 561 static struct snd_soc_dai_ops q6slim_ops = { 562 .prepare = q6afe_dai_prepare, 563 .hw_params = q6slim_hw_params, 564 .shutdown = q6afe_dai_shutdown, 565 .set_channel_map = q6slim_set_channel_map, 566 }; 567 568 static struct snd_soc_dai_ops q6tdm_ops = { 569 .prepare = q6afe_dai_prepare, 570 .shutdown = q6afe_dai_shutdown, 571 .set_sysclk = q6afe_mi2s_set_sysclk, 572 .set_tdm_slot = q6tdm_set_tdm_slot, 573 .set_channel_map = q6tdm_set_channel_map, 574 .hw_params = q6tdm_hw_params, 575 }; 576 577 static int msm_dai_q6_dai_probe(struct snd_soc_dai *dai) 578 { 579 struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev); 580 struct q6afe_port *port; 581 582 port = q6afe_port_get_from_id(dai->dev, dai->id); 583 if (IS_ERR(port)) { 584 dev_err(dai->dev, "Unable to get afe port\n"); 585 return -EINVAL; 586 } 587 dai_data->port[dai->id] = port; 588 589 return 0; 590 } 591 592 static int msm_dai_q6_dai_remove(struct snd_soc_dai *dai) 593 { 594 struct q6afe_dai_data *dai_data = dev_get_drvdata(dai->dev); 595 596 q6afe_port_put(dai_data->port[dai->id]); 597 dai_data->port[dai->id] = NULL; 598 599 return 0; 600 } 601 602 static struct snd_soc_dai_driver q6afe_dais[] = { 603 { 604 .playback = { 605 .stream_name = "HDMI Playback", 606 .rates = SNDRV_PCM_RATE_48000 | 607 SNDRV_PCM_RATE_96000 | 608 SNDRV_PCM_RATE_192000, 609 .formats = SNDRV_PCM_FMTBIT_S16_LE | 610 SNDRV_PCM_FMTBIT_S24_LE, 611 .channels_min = 2, 612 .channels_max = 8, 613 .rate_max = 192000, 614 .rate_min = 48000, 615 }, 616 .ops = &q6hdmi_ops, 617 .id = HDMI_RX, 618 .name = "HDMI", 619 .probe = msm_dai_q6_dai_probe, 620 .remove = msm_dai_q6_dai_remove, 621 }, { 622 .name = "SLIMBUS_0_RX", 623 .ops = &q6slim_ops, 624 .id = SLIMBUS_0_RX, 625 .probe = msm_dai_q6_dai_probe, 626 .remove = msm_dai_q6_dai_remove, 627 .playback = { 628 .stream_name = "Slimbus Playback", 629 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | 630 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_96000 | 631 SNDRV_PCM_RATE_192000, 632 .formats = SNDRV_PCM_FMTBIT_S16_LE | 633 SNDRV_PCM_FMTBIT_S24_LE, 634 .channels_min = 1, 635 .channels_max = 8, 636 .rate_min = 8000, 637 .rate_max = 192000, 638 }, 639 }, { 640 .playback = { 641 .stream_name = "Slimbus1 Playback", 642 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | 643 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | 644 SNDRV_PCM_RATE_192000, 645 .formats = SNDRV_PCM_FMTBIT_S16_LE | 646 SNDRV_PCM_FMTBIT_S24_LE, 647 .channels_min = 1, 648 .channels_max = 2, 649 .rate_min = 8000, 650 .rate_max = 192000, 651 }, 652 .name = "SLIMBUS_1_RX", 653 .ops = &q6slim_ops, 654 .id = SLIMBUS_1_RX, 655 .probe = msm_dai_q6_dai_probe, 656 .remove = msm_dai_q6_dai_remove, 657 }, { 658 .playback = { 659 .stream_name = "Slimbus2 Playback", 660 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | 661 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_96000 | 662 SNDRV_PCM_RATE_192000, 663 .formats = SNDRV_PCM_FMTBIT_S16_LE | 664 SNDRV_PCM_FMTBIT_S24_LE, 665 .channels_min = 1, 666 .channels_max = 8, 667 .rate_min = 8000, 668 .rate_max = 192000, 669 }, 670 .name = "SLIMBUS_2_RX", 671 .ops = &q6slim_ops, 672 .id = SLIMBUS_2_RX, 673 .probe = msm_dai_q6_dai_probe, 674 .remove = msm_dai_q6_dai_remove, 675 }, { 676 .playback = { 677 .stream_name = "Slimbus3 Playback", 678 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | 679 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | 680 SNDRV_PCM_RATE_192000, 681 .formats = SNDRV_PCM_FMTBIT_S16_LE | 682 SNDRV_PCM_FMTBIT_S24_LE, 683 .channels_min = 1, 684 .channels_max = 2, 685 .rate_min = 8000, 686 .rate_max = 192000, 687 }, 688 .name = "SLIMBUS_3_RX", 689 .ops = &q6slim_ops, 690 .id = SLIMBUS_3_RX, 691 .probe = msm_dai_q6_dai_probe, 692 .remove = msm_dai_q6_dai_remove, 693 }, { 694 .playback = { 695 .stream_name = "Slimbus4 Playback", 696 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | 697 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | 698 SNDRV_PCM_RATE_192000, 699 .formats = SNDRV_PCM_FMTBIT_S16_LE | 700 SNDRV_PCM_FMTBIT_S24_LE, 701 .channels_min = 1, 702 .channels_max = 2, 703 .rate_min = 8000, 704 .rate_max = 192000, 705 }, 706 .name = "SLIMBUS_4_RX", 707 .ops = &q6slim_ops, 708 .id = SLIMBUS_4_RX, 709 .probe = msm_dai_q6_dai_probe, 710 .remove = msm_dai_q6_dai_remove, 711 }, { 712 .playback = { 713 .stream_name = "Slimbus5 Playback", 714 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | 715 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | 716 SNDRV_PCM_RATE_192000, 717 .formats = SNDRV_PCM_FMTBIT_S16_LE | 718 SNDRV_PCM_FMTBIT_S24_LE, 719 .channels_min = 1, 720 .channels_max = 2, 721 .rate_min = 8000, 722 .rate_max = 192000, 723 }, 724 .name = "SLIMBUS_5_RX", 725 .ops = &q6slim_ops, 726 .id = SLIMBUS_5_RX, 727 .probe = msm_dai_q6_dai_probe, 728 .remove = msm_dai_q6_dai_remove, 729 }, { 730 .playback = { 731 .stream_name = "Slimbus6 Playback", 732 .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | 733 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | 734 SNDRV_PCM_RATE_192000, 735 .formats = SNDRV_PCM_FMTBIT_S16_LE | 736 SNDRV_PCM_FMTBIT_S24_LE, 737 .channels_min = 1, 738 .channels_max = 2, 739 .rate_min = 8000, 740 .rate_max = 192000, 741 }, 742 .ops = &q6slim_ops, 743 .name = "SLIMBUS_6_RX", 744 .id = SLIMBUS_6_RX, 745 .probe = msm_dai_q6_dai_probe, 746 .remove = msm_dai_q6_dai_remove, 747 }, { 748 .playback = { 749 .stream_name = "Primary MI2S Playback", 750 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | 751 SNDRV_PCM_RATE_16000, 752 .formats = SNDRV_PCM_FMTBIT_S16_LE | 753 SNDRV_PCM_FMTBIT_S24_LE, 754 .rate_min = 8000, 755 .rate_max = 48000, 756 }, 757 .id = PRIMARY_MI2S_RX, 758 .name = "PRI_MI2S_RX", 759 .ops = &q6i2s_ops, 760 .probe = msm_dai_q6_dai_probe, 761 .remove = msm_dai_q6_dai_remove, 762 }, { 763 .capture = { 764 .stream_name = "Primary MI2S Capture", 765 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | 766 SNDRV_PCM_RATE_16000, 767 .formats = SNDRV_PCM_FMTBIT_S16_LE | 768 SNDRV_PCM_FMTBIT_S24_LE, 769 .rate_min = 8000, 770 .rate_max = 48000, 771 }, 772 .id = PRIMARY_MI2S_TX, 773 .name = "PRI_MI2S_TX", 774 .ops = &q6i2s_ops, 775 .probe = msm_dai_q6_dai_probe, 776 .remove = msm_dai_q6_dai_remove, 777 }, { 778 .playback = { 779 .stream_name = "Secondary MI2S Playback", 780 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | 781 SNDRV_PCM_RATE_16000, 782 .formats = SNDRV_PCM_FMTBIT_S16_LE, 783 .rate_min = 8000, 784 .rate_max = 48000, 785 }, 786 .name = "SEC_MI2S_RX", 787 .id = SECONDARY_MI2S_RX, 788 .ops = &q6i2s_ops, 789 .probe = msm_dai_q6_dai_probe, 790 .remove = msm_dai_q6_dai_remove, 791 }, { 792 .capture = { 793 .stream_name = "Secondary MI2S Capture", 794 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | 795 SNDRV_PCM_RATE_16000, 796 .formats = SNDRV_PCM_FMTBIT_S16_LE | 797 SNDRV_PCM_FMTBIT_S24_LE, 798 .rate_min = 8000, 799 .rate_max = 48000, 800 }, 801 .id = SECONDARY_MI2S_TX, 802 .name = "SEC_MI2S_TX", 803 .ops = &q6i2s_ops, 804 .probe = msm_dai_q6_dai_probe, 805 .remove = msm_dai_q6_dai_remove, 806 }, { 807 .playback = { 808 .stream_name = "Tertiary MI2S Playback", 809 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | 810 SNDRV_PCM_RATE_16000, 811 .formats = SNDRV_PCM_FMTBIT_S16_LE, 812 .rate_min = 8000, 813 .rate_max = 48000, 814 }, 815 .name = "TERT_MI2S_RX", 816 .id = TERTIARY_MI2S_RX, 817 .ops = &q6i2s_ops, 818 .probe = msm_dai_q6_dai_probe, 819 .remove = msm_dai_q6_dai_remove, 820 }, { 821 .capture = { 822 .stream_name = "Tertiary MI2S Capture", 823 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | 824 SNDRV_PCM_RATE_16000, 825 .formats = SNDRV_PCM_FMTBIT_S16_LE | 826 SNDRV_PCM_FMTBIT_S24_LE, 827 .rate_min = 8000, 828 .rate_max = 48000, 829 }, 830 .id = TERTIARY_MI2S_TX, 831 .name = "TERT_MI2S_TX", 832 .ops = &q6i2s_ops, 833 .probe = msm_dai_q6_dai_probe, 834 .remove = msm_dai_q6_dai_remove, 835 }, { 836 .playback = { 837 .stream_name = "Quaternary MI2S Playback", 838 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | 839 SNDRV_PCM_RATE_16000, 840 .formats = SNDRV_PCM_FMTBIT_S16_LE, 841 .rate_min = 8000, 842 .rate_max = 48000, 843 }, 844 .name = "QUAT_MI2S_RX", 845 .id = QUATERNARY_MI2S_RX, 846 .ops = &q6i2s_ops, 847 .probe = msm_dai_q6_dai_probe, 848 .remove = msm_dai_q6_dai_remove, 849 }, { 850 .capture = { 851 .stream_name = "Quaternary MI2S Capture", 852 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | 853 SNDRV_PCM_RATE_16000, 854 .formats = SNDRV_PCM_FMTBIT_S16_LE | 855 SNDRV_PCM_FMTBIT_S24_LE, 856 .rate_min = 8000, 857 .rate_max = 48000, 858 }, 859 .id = QUATERNARY_MI2S_TX, 860 .name = "QUAT_MI2S_TX", 861 .ops = &q6i2s_ops, 862 .probe = msm_dai_q6_dai_probe, 863 .remove = msm_dai_q6_dai_remove, 864 }, 865 Q6AFE_TDM_PB_DAI("Primary", 0, PRIMARY_TDM_RX_0), 866 Q6AFE_TDM_PB_DAI("Primary", 1, PRIMARY_TDM_RX_1), 867 Q6AFE_TDM_PB_DAI("Primary", 2, PRIMARY_TDM_RX_2), 868 Q6AFE_TDM_PB_DAI("Primary", 3, PRIMARY_TDM_RX_3), 869 Q6AFE_TDM_PB_DAI("Primary", 4, PRIMARY_TDM_RX_4), 870 Q6AFE_TDM_PB_DAI("Primary", 5, PRIMARY_TDM_RX_5), 871 Q6AFE_TDM_PB_DAI("Primary", 6, PRIMARY_TDM_RX_6), 872 Q6AFE_TDM_PB_DAI("Primary", 7, PRIMARY_TDM_RX_7), 873 Q6AFE_TDM_CAP_DAI("Primary", 0, PRIMARY_TDM_TX_0), 874 Q6AFE_TDM_CAP_DAI("Primary", 1, PRIMARY_TDM_TX_1), 875 Q6AFE_TDM_CAP_DAI("Primary", 2, PRIMARY_TDM_TX_2), 876 Q6AFE_TDM_CAP_DAI("Primary", 3, PRIMARY_TDM_TX_3), 877 Q6AFE_TDM_CAP_DAI("Primary", 4, PRIMARY_TDM_TX_4), 878 Q6AFE_TDM_CAP_DAI("Primary", 5, PRIMARY_TDM_TX_5), 879 Q6AFE_TDM_CAP_DAI("Primary", 6, PRIMARY_TDM_TX_6), 880 Q6AFE_TDM_CAP_DAI("Primary", 7, PRIMARY_TDM_TX_7), 881 Q6AFE_TDM_PB_DAI("Secondary", 0, SECONDARY_TDM_RX_0), 882 Q6AFE_TDM_PB_DAI("Secondary", 1, SECONDARY_TDM_RX_1), 883 Q6AFE_TDM_PB_DAI("Secondary", 2, SECONDARY_TDM_RX_2), 884 Q6AFE_TDM_PB_DAI("Secondary", 3, SECONDARY_TDM_RX_3), 885 Q6AFE_TDM_PB_DAI("Secondary", 4, SECONDARY_TDM_RX_4), 886 Q6AFE_TDM_PB_DAI("Secondary", 5, SECONDARY_TDM_RX_5), 887 Q6AFE_TDM_PB_DAI("Secondary", 6, SECONDARY_TDM_RX_6), 888 Q6AFE_TDM_PB_DAI("Secondary", 7, SECONDARY_TDM_RX_7), 889 Q6AFE_TDM_CAP_DAI("Secondary", 0, SECONDARY_TDM_TX_0), 890 Q6AFE_TDM_CAP_DAI("Secondary", 1, SECONDARY_TDM_TX_1), 891 Q6AFE_TDM_CAP_DAI("Secondary", 2, SECONDARY_TDM_TX_2), 892 Q6AFE_TDM_CAP_DAI("Secondary", 3, SECONDARY_TDM_TX_3), 893 Q6AFE_TDM_CAP_DAI("Secondary", 4, SECONDARY_TDM_TX_4), 894 Q6AFE_TDM_CAP_DAI("Secondary", 5, SECONDARY_TDM_TX_5), 895 Q6AFE_TDM_CAP_DAI("Secondary", 6, SECONDARY_TDM_TX_6), 896 Q6AFE_TDM_CAP_DAI("Secondary", 7, SECONDARY_TDM_TX_7), 897 Q6AFE_TDM_PB_DAI("Tertiary", 0, TERTIARY_TDM_RX_0), 898 Q6AFE_TDM_PB_DAI("Tertiary", 1, TERTIARY_TDM_RX_1), 899 Q6AFE_TDM_PB_DAI("Tertiary", 2, TERTIARY_TDM_RX_2), 900 Q6AFE_TDM_PB_DAI("Tertiary", 3, TERTIARY_TDM_RX_3), 901 Q6AFE_TDM_PB_DAI("Tertiary", 4, TERTIARY_TDM_RX_4), 902 Q6AFE_TDM_PB_DAI("Tertiary", 5, TERTIARY_TDM_RX_5), 903 Q6AFE_TDM_PB_DAI("Tertiary", 6, TERTIARY_TDM_RX_6), 904 Q6AFE_TDM_PB_DAI("Tertiary", 7, TERTIARY_TDM_RX_7), 905 Q6AFE_TDM_CAP_DAI("Tertiary", 0, TERTIARY_TDM_TX_0), 906 Q6AFE_TDM_CAP_DAI("Tertiary", 1, TERTIARY_TDM_TX_1), 907 Q6AFE_TDM_CAP_DAI("Tertiary", 2, TERTIARY_TDM_TX_2), 908 Q6AFE_TDM_CAP_DAI("Tertiary", 3, TERTIARY_TDM_TX_3), 909 Q6AFE_TDM_CAP_DAI("Tertiary", 4, TERTIARY_TDM_TX_4), 910 Q6AFE_TDM_CAP_DAI("Tertiary", 5, TERTIARY_TDM_TX_5), 911 Q6AFE_TDM_CAP_DAI("Tertiary", 6, TERTIARY_TDM_TX_6), 912 Q6AFE_TDM_CAP_DAI("Tertiary", 7, TERTIARY_TDM_TX_7), 913 Q6AFE_TDM_PB_DAI("Quaternary", 0, QUATERNARY_TDM_RX_0), 914 Q6AFE_TDM_PB_DAI("Quaternary", 1, QUATERNARY_TDM_RX_1), 915 Q6AFE_TDM_PB_DAI("Quaternary", 2, QUATERNARY_TDM_RX_2), 916 Q6AFE_TDM_PB_DAI("Quaternary", 3, QUATERNARY_TDM_RX_3), 917 Q6AFE_TDM_PB_DAI("Quaternary", 4, QUATERNARY_TDM_RX_4), 918 Q6AFE_TDM_PB_DAI("Quaternary", 5, QUATERNARY_TDM_RX_5), 919 Q6AFE_TDM_PB_DAI("Quaternary", 6, QUATERNARY_TDM_RX_6), 920 Q6AFE_TDM_PB_DAI("Quaternary", 7, QUATERNARY_TDM_RX_7), 921 Q6AFE_TDM_CAP_DAI("Quaternary", 0, QUATERNARY_TDM_TX_0), 922 Q6AFE_TDM_CAP_DAI("Quaternary", 1, QUATERNARY_TDM_TX_1), 923 Q6AFE_TDM_CAP_DAI("Quaternary", 2, QUATERNARY_TDM_TX_2), 924 Q6AFE_TDM_CAP_DAI("Quaternary", 3, QUATERNARY_TDM_TX_3), 925 Q6AFE_TDM_CAP_DAI("Quaternary", 4, QUATERNARY_TDM_TX_4), 926 Q6AFE_TDM_CAP_DAI("Quaternary", 5, QUATERNARY_TDM_TX_5), 927 Q6AFE_TDM_CAP_DAI("Quaternary", 6, QUATERNARY_TDM_TX_6), 928 Q6AFE_TDM_CAP_DAI("Quaternary", 7, QUATERNARY_TDM_TX_7), 929 Q6AFE_TDM_PB_DAI("Quinary", 0, QUINARY_TDM_RX_0), 930 Q6AFE_TDM_PB_DAI("Quinary", 1, QUINARY_TDM_RX_1), 931 Q6AFE_TDM_PB_DAI("Quinary", 2, QUINARY_TDM_RX_2), 932 Q6AFE_TDM_PB_DAI("Quinary", 3, QUINARY_TDM_RX_3), 933 Q6AFE_TDM_PB_DAI("Quinary", 4, QUINARY_TDM_RX_4), 934 Q6AFE_TDM_PB_DAI("Quinary", 5, QUINARY_TDM_RX_5), 935 Q6AFE_TDM_PB_DAI("Quinary", 6, QUINARY_TDM_RX_6), 936 Q6AFE_TDM_PB_DAI("Quinary", 7, QUINARY_TDM_RX_7), 937 Q6AFE_TDM_CAP_DAI("Quinary", 0, QUINARY_TDM_TX_0), 938 Q6AFE_TDM_CAP_DAI("Quinary", 1, QUINARY_TDM_TX_1), 939 Q6AFE_TDM_CAP_DAI("Quinary", 2, QUINARY_TDM_TX_2), 940 Q6AFE_TDM_CAP_DAI("Quinary", 3, QUINARY_TDM_TX_3), 941 Q6AFE_TDM_CAP_DAI("Quinary", 4, QUINARY_TDM_TX_4), 942 Q6AFE_TDM_CAP_DAI("Quinary", 5, QUINARY_TDM_TX_5), 943 Q6AFE_TDM_CAP_DAI("Quinary", 6, QUINARY_TDM_TX_6), 944 Q6AFE_TDM_CAP_DAI("Quinary", 7, QUINARY_TDM_TX_7), 945 }; 946 947 static int q6afe_of_xlate_dai_name(struct snd_soc_component *component, 948 struct of_phandle_args *args, 949 const char **dai_name) 950 { 951 int id = args->args[0]; 952 int ret = -EINVAL; 953 int i; 954 955 for (i = 0; i < ARRAY_SIZE(q6afe_dais); i++) { 956 if (q6afe_dais[i].id == id) { 957 *dai_name = q6afe_dais[i].name; 958 ret = 0; 959 break; 960 } 961 } 962 963 return ret; 964 } 965 966 static const struct snd_soc_dapm_widget q6afe_dai_widgets[] = { 967 SND_SOC_DAPM_AIF_OUT("HDMI_RX", "HDMI Playback", 0, 0, 0, 0), 968 SND_SOC_DAPM_AIF_OUT("SLIMBUS_0_RX", "Slimbus Playback", 0, 0, 0, 0), 969 SND_SOC_DAPM_AIF_OUT("SLIMBUS_1_RX", "Slimbus1 Playback", 0, 0, 0, 0), 970 SND_SOC_DAPM_AIF_OUT("SLIMBUS_2_RX", "Slimbus2 Playback", 0, 0, 0, 0), 971 SND_SOC_DAPM_AIF_OUT("SLIMBUS_3_RX", "Slimbus3 Playback", 0, 0, 0, 0), 972 SND_SOC_DAPM_AIF_OUT("SLIMBUS_4_RX", "Slimbus4 Playback", 0, 0, 0, 0), 973 SND_SOC_DAPM_AIF_OUT("SLIMBUS_5_RX", "Slimbus5 Playback", 0, 0, 0, 0), 974 SND_SOC_DAPM_AIF_OUT("SLIMBUS_6_RX", "Slimbus6 Playback", 0, 0, 0, 0), 975 SND_SOC_DAPM_AIF_OUT("QUAT_MI2S_RX", "Quaternary MI2S Playback", 976 0, 0, 0, 0), 977 SND_SOC_DAPM_AIF_IN("QUAT_MI2S_TX", "Quaternary MI2S Capture", 978 0, 0, 0, 0), 979 SND_SOC_DAPM_AIF_OUT("TERT_MI2S_RX", "Tertiary MI2S Playback", 980 0, 0, 0, 0), 981 SND_SOC_DAPM_AIF_IN("TERT_MI2S_TX", "Tertiary MI2S Capture", 982 0, 0, 0, 0), 983 SND_SOC_DAPM_AIF_OUT("SEC_MI2S_RX", "Secondary MI2S Playback", 984 0, 0, 0, 0), 985 SND_SOC_DAPM_AIF_IN("SEC_MI2S_TX", "Secondary MI2S Capture", 986 0, 0, 0, 0), 987 SND_SOC_DAPM_AIF_OUT("SEC_MI2S_RX_SD1", 988 "Secondary MI2S Playback SD1", 989 0, 0, 0, 0), 990 SND_SOC_DAPM_AIF_OUT("PRI_MI2S_RX", "Primary MI2S Playback", 991 0, 0, 0, 0), 992 SND_SOC_DAPM_AIF_IN("PRI_MI2S_TX", "Primary MI2S Capture", 993 0, 0, 0, 0), 994 995 SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_RX_0", "Primary TDM0 Playback", 996 0, 0, 0, 0), 997 SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_RX_1", "Primary TDM1 Playback", 998 0, 0, 0, 0), 999 SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_RX_2", "Primary TDM2 Playback", 1000 0, 0, 0, 0), 1001 SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_RX_3", "Primary TDM3 Playback", 1002 0, 0, 0, 0), 1003 SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_RX_4", "Primary TDM4 Playback", 1004 0, 0, 0, 0), 1005 SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_RX_5", "Primary TDM5 Playback", 1006 0, 0, 0, 0), 1007 SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_RX_6", "Primary TDM6 Playback", 1008 0, 0, 0, 0), 1009 SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_RX_7", "Primary TDM7 Playback", 1010 0, 0, 0, 0), 1011 SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_TX_0", "Primary TDM0 Capture", 1012 0, 0, 0, 0), 1013 SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_TX_1", "Primary TDM1 Capture", 1014 0, 0, 0, 0), 1015 SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_TX_2", "Primary TDM2 Capture", 1016 0, 0, 0, 0), 1017 SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_TX_3", "Primary TDM3 Capture", 1018 0, 0, 0, 0), 1019 SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_TX_4", "Primary TDM4 Capture", 1020 0, 0, 0, 0), 1021 SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_TX_5", "Primary TDM5 Capture", 1022 0, 0, 0, 0), 1023 SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_TX_6", "Primary TDM6 Capture", 1024 0, 0, 0, 0), 1025 SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_TX_7", "Primary TDM7 Capture", 1026 0, 0, 0, 0), 1027 1028 SND_SOC_DAPM_AIF_OUT("SEC_TDM_RX_0", "Secondary TDM0 Playback", 1029 0, 0, 0, 0), 1030 SND_SOC_DAPM_AIF_OUT("SEC_TDM_RX_1", "Secondary TDM1 Playback", 1031 0, 0, 0, 0), 1032 SND_SOC_DAPM_AIF_OUT("SEC_TDM_RX_2", "Secondary TDM2 Playback", 1033 0, 0, 0, 0), 1034 SND_SOC_DAPM_AIF_OUT("SEC_TDM_RX_3", "Secondary TDM3 Playback", 1035 0, 0, 0, 0), 1036 SND_SOC_DAPM_AIF_OUT("SEC_TDM_RX_4", "Secondary TDM4 Playback", 1037 0, 0, 0, 0), 1038 SND_SOC_DAPM_AIF_OUT("SEC_TDM_RX_5", "Secondary TDM5 Playback", 1039 0, 0, 0, 0), 1040 SND_SOC_DAPM_AIF_OUT("SEC_TDM_RX_6", "Secondary TDM6 Playback", 1041 0, 0, 0, 0), 1042 SND_SOC_DAPM_AIF_OUT("SEC_TDM_RX_7", "Secondary TDM7 Playback", 1043 0, 0, 0, 0), 1044 SND_SOC_DAPM_AIF_IN("SEC_TDM_TX_0", "Secondary TDM0 Capture", 1045 0, 0, 0, 0), 1046 SND_SOC_DAPM_AIF_IN("SEC_TDM_TX_1", "Secondary TDM1 Capture", 1047 0, 0, 0, 0), 1048 SND_SOC_DAPM_AIF_IN("SEC_TDM_TX_2", "Secondary TDM2 Capture", 1049 0, 0, 0, 0), 1050 SND_SOC_DAPM_AIF_IN("SEC_TDM_TX_3", "Secondary TDM3 Capture", 1051 0, 0, 0, 0), 1052 SND_SOC_DAPM_AIF_IN("SEC_TDM_TX_4", "Secondary TDM4 Capture", 1053 0, 0, 0, 0), 1054 SND_SOC_DAPM_AIF_IN("SEC_TDM_TX_5", "Secondary TDM5 Capture", 1055 0, 0, 0, 0), 1056 SND_SOC_DAPM_AIF_IN("SEC_TDM_TX_6", "Secondary TDM6 Capture", 1057 0, 0, 0, 0), 1058 SND_SOC_DAPM_AIF_IN("SEC_TDM_TX_7", "Secondary TDM7 Capture", 1059 0, 0, 0, 0), 1060 1061 SND_SOC_DAPM_AIF_OUT("TERT_TDM_RX_0", "Tertiary TDM0 Playback", 1062 0, 0, 0, 0), 1063 SND_SOC_DAPM_AIF_OUT("TERT_TDM_RX_1", "Tertiary TDM1 Playback", 1064 0, 0, 0, 0), 1065 SND_SOC_DAPM_AIF_OUT("TERT_TDM_RX_2", "Tertiary TDM2 Playback", 1066 0, 0, 0, 0), 1067 SND_SOC_DAPM_AIF_OUT("TERT_TDM_RX_3", "Tertiary TDM3 Playback", 1068 0, 0, 0, 0), 1069 SND_SOC_DAPM_AIF_OUT("TERT_TDM_RX_4", "Tertiary TDM4 Playback", 1070 0, 0, 0, 0), 1071 SND_SOC_DAPM_AIF_OUT("TERT_TDM_RX_5", "Tertiary TDM5 Playback", 1072 0, 0, 0, 0), 1073 SND_SOC_DAPM_AIF_OUT("TERT_TDM_RX_6", "Tertiary TDM6 Playback", 1074 0, 0, 0, 0), 1075 SND_SOC_DAPM_AIF_OUT("TERT_TDM_RX_7", "Tertiary TDM7 Playback", 1076 0, 0, 0, 0), 1077 SND_SOC_DAPM_AIF_IN("TERT_TDM_TX_0", "Tertiary TDM0 Capture", 1078 0, 0, 0, 0), 1079 SND_SOC_DAPM_AIF_IN("TERT_TDM_TX_1", "Tertiary TDM1 Capture", 1080 0, 0, 0, 0), 1081 SND_SOC_DAPM_AIF_IN("TERT_TDM_TX_2", "Tertiary TDM2 Capture", 1082 0, 0, 0, 0), 1083 SND_SOC_DAPM_AIF_IN("TERT_TDM_TX_3", "Tertiary TDM3 Capture", 1084 0, 0, 0, 0), 1085 SND_SOC_DAPM_AIF_IN("TERT_TDM_TX_4", "Tertiary TDM4 Capture", 1086 0, 0, 0, 0), 1087 SND_SOC_DAPM_AIF_IN("TERT_TDM_TX_5", "Tertiary TDM5 Capture", 1088 0, 0, 0, 0), 1089 SND_SOC_DAPM_AIF_IN("TERT_TDM_TX_6", "Tertiary TDM6 Capture", 1090 0, 0, 0, 0), 1091 SND_SOC_DAPM_AIF_IN("TERT_TDM_TX_7", "Tertiary TDM7 Capture", 1092 0, 0, 0, 0), 1093 1094 SND_SOC_DAPM_AIF_OUT("QUAT_TDM_RX_0", "Quaternary TDM0 Playback", 1095 0, 0, 0, 0), 1096 SND_SOC_DAPM_AIF_OUT("QUAT_TDM_RX_1", "Quaternary TDM1 Playback", 1097 0, 0, 0, 0), 1098 SND_SOC_DAPM_AIF_OUT("QUAT_TDM_RX_2", "Quaternary TDM2 Playback", 1099 0, 0, 0, 0), 1100 SND_SOC_DAPM_AIF_OUT("QUAT_TDM_RX_3", "Quaternary TDM3 Playback", 1101 0, 0, 0, 0), 1102 SND_SOC_DAPM_AIF_OUT("QUAT_TDM_RX_4", "Quaternary TDM4 Playback", 1103 0, 0, 0, 0), 1104 SND_SOC_DAPM_AIF_OUT("QUAT_TDM_RX_5", "Quaternary TDM5 Playback", 1105 0, 0, 0, 0), 1106 SND_SOC_DAPM_AIF_OUT("QUAT_TDM_RX_6", "Quaternary TDM6 Playback", 1107 0, 0, 0, 0), 1108 SND_SOC_DAPM_AIF_OUT("QUAT_TDM_RX_7", "Quaternary TDM7 Playback", 1109 0, 0, 0, 0), 1110 SND_SOC_DAPM_AIF_IN("QUAT_TDM_TX_0", "Quaternary TDM0 Capture", 1111 0, 0, 0, 0), 1112 SND_SOC_DAPM_AIF_IN("QUAT_TDM_TX_1", "Quaternary TDM1 Capture", 1113 0, 0, 0, 0), 1114 SND_SOC_DAPM_AIF_IN("QUAT_TDM_TX_2", "Quaternary TDM2 Capture", 1115 0, 0, 0, 0), 1116 SND_SOC_DAPM_AIF_IN("QUAT_TDM_TX_3", "Quaternary TDM3 Capture", 1117 0, 0, 0, 0), 1118 SND_SOC_DAPM_AIF_IN("QUAT_TDM_TX_4", "Quaternary TDM4 Capture", 1119 0, 0, 0, 0), 1120 SND_SOC_DAPM_AIF_IN("QUAT_TDM_TX_5", "Quaternary TDM5 Capture", 1121 0, 0, 0, 0), 1122 SND_SOC_DAPM_AIF_IN("QUAT_TDM_TX_6", "Quaternary TDM6 Capture", 1123 0, 0, 0, 0), 1124 SND_SOC_DAPM_AIF_IN("QUAT_TDM_TX_7", "Quaternary TDM7 Capture", 1125 0, 0, 0, 0), 1126 1127 SND_SOC_DAPM_AIF_OUT("QUIN_TDM_RX_0", "Quinary TDM0 Playback", 1128 0, 0, 0, 0), 1129 SND_SOC_DAPM_AIF_OUT("QUIN_TDM_RX_1", "Quinary TDM1 Playback", 1130 0, 0, 0, 0), 1131 SND_SOC_DAPM_AIF_OUT("QUIN_TDM_RX_2", "Quinary TDM2 Playback", 1132 0, 0, 0, 0), 1133 SND_SOC_DAPM_AIF_OUT("QUIN_TDM_RX_3", "Quinary TDM3 Playback", 1134 0, 0, 0, 0), 1135 SND_SOC_DAPM_AIF_OUT("QUIN_TDM_RX_4", "Quinary TDM4 Playback", 1136 0, 0, 0, 0), 1137 SND_SOC_DAPM_AIF_OUT("QUIN_TDM_RX_5", "Quinary TDM5 Playback", 1138 0, 0, 0, 0), 1139 SND_SOC_DAPM_AIF_OUT("QUIN_TDM_RX_6", "Quinary TDM6 Playback", 1140 0, 0, 0, 0), 1141 SND_SOC_DAPM_AIF_OUT("QUIN_TDM_RX_7", "Quinary TDM7 Playback", 1142 0, 0, 0, 0), 1143 SND_SOC_DAPM_AIF_IN("QUIN_TDM_TX_0", "Quinary TDM0 Capture", 1144 0, 0, 0, 0), 1145 SND_SOC_DAPM_AIF_IN("QUIN_TDM_TX_1", "Quinary TDM1 Capture", 1146 0, 0, 0, 0), 1147 SND_SOC_DAPM_AIF_IN("QUIN_TDM_TX_2", "Quinary TDM2 Capture", 1148 0, 0, 0, 0), 1149 SND_SOC_DAPM_AIF_IN("QUIN_TDM_TX_3", "Quinary TDM3 Capture", 1150 0, 0, 0, 0), 1151 SND_SOC_DAPM_AIF_IN("QUIN_TDM_TX_4", "Quinary TDM4 Capture", 1152 0, 0, 0, 0), 1153 SND_SOC_DAPM_AIF_IN("QUIN_TDM_TX_5", "Quinary TDM5 Capture", 1154 0, 0, 0, 0), 1155 SND_SOC_DAPM_AIF_IN("QUIN_TDM_TX_6", "Quinary TDM6 Capture", 1156 0, 0, 0, 0), 1157 SND_SOC_DAPM_AIF_IN("QUIN_TDM_TX_7", "Quinary TDM7 Capture", 1158 0, 0, 0, 0), 1159 }; 1160 1161 static const struct snd_soc_component_driver q6afe_dai_component = { 1162 .name = "q6afe-dai-component", 1163 .dapm_widgets = q6afe_dai_widgets, 1164 .num_dapm_widgets = ARRAY_SIZE(q6afe_dai_widgets), 1165 .dapm_routes = q6afe_dapm_routes, 1166 .num_dapm_routes = ARRAY_SIZE(q6afe_dapm_routes), 1167 .of_xlate_dai_name = q6afe_of_xlate_dai_name, 1168 1169 }; 1170 1171 static void of_q6afe_parse_dai_data(struct device *dev, 1172 struct q6afe_dai_data *data) 1173 { 1174 struct device_node *node; 1175 int ret; 1176 1177 for_each_child_of_node(dev->of_node, node) { 1178 unsigned int lines[Q6AFE_MAX_MI2S_LINES]; 1179 struct q6afe_dai_priv_data *priv; 1180 int id, i, num_lines; 1181 1182 ret = of_property_read_u32(node, "reg", &id); 1183 if (ret || id > AFE_PORT_MAX) { 1184 dev_err(dev, "valid dai id not found:%d\n", ret); 1185 continue; 1186 } 1187 1188 switch (id) { 1189 /* MI2S specific properties */ 1190 case PRIMARY_MI2S_RX ... QUATERNARY_MI2S_TX: 1191 priv = &data->priv[id]; 1192 ret = of_property_read_variable_u32_array(node, 1193 "qcom,sd-lines", 1194 lines, 0, 1195 Q6AFE_MAX_MI2S_LINES); 1196 if (ret < 0) 1197 num_lines = 0; 1198 else 1199 num_lines = ret; 1200 1201 priv->sd_line_mask = 0; 1202 1203 for (i = 0; i < num_lines; i++) 1204 priv->sd_line_mask |= BIT(lines[i]); 1205 1206 break; 1207 case PRIMARY_TDM_RX_0 ... QUINARY_TDM_TX_7: 1208 priv = &data->priv[id]; 1209 ret = of_property_read_u32(node, "qcom,tdm-sync-mode", 1210 &priv->sync_mode); 1211 if (ret) { 1212 dev_err(dev, "No Sync mode from DT\n"); 1213 break; 1214 } 1215 ret = of_property_read_u32(node, "qcom,tdm-sync-src", 1216 &priv->sync_src); 1217 if (ret) { 1218 dev_err(dev, "No Sync Src from DT\n"); 1219 break; 1220 } 1221 ret = of_property_read_u32(node, "qcom,tdm-data-out", 1222 &priv->data_out_enable); 1223 if (ret) { 1224 dev_err(dev, "No Data out enable from DT\n"); 1225 break; 1226 } 1227 ret = of_property_read_u32(node, "qcom,tdm-invert-sync", 1228 &priv->invert_sync); 1229 if (ret) { 1230 dev_err(dev, "No Invert sync from DT\n"); 1231 break; 1232 } 1233 ret = of_property_read_u32(node, "qcom,tdm-data-delay", 1234 &priv->data_delay); 1235 if (ret) { 1236 dev_err(dev, "No Data Delay from DT\n"); 1237 break; 1238 } 1239 ret = of_property_read_u32(node, "qcom,tdm-data-align", 1240 &priv->data_align); 1241 if (ret) { 1242 dev_err(dev, "No Data align from DT\n"); 1243 break; 1244 } 1245 break; 1246 default: 1247 break; 1248 } 1249 } 1250 } 1251 1252 static int q6afe_dai_bind(struct device *dev, struct device *master, void *data) 1253 { 1254 struct q6afe_dai_data *dai_data; 1255 1256 dai_data = kzalloc(sizeof(*dai_data), GFP_KERNEL); 1257 if (!dai_data) 1258 return -ENOMEM; 1259 1260 dev_set_drvdata(dev, dai_data); 1261 1262 of_q6afe_parse_dai_data(dev, dai_data); 1263 1264 return snd_soc_register_component(dev, &q6afe_dai_component, 1265 q6afe_dais, ARRAY_SIZE(q6afe_dais)); 1266 } 1267 1268 static void q6afe_dai_unbind(struct device *dev, struct device *master, 1269 void *data) 1270 { 1271 struct q6afe_dai_data *dai_data = dev_get_drvdata(dev); 1272 1273 snd_soc_unregister_component(dev); 1274 kfree(dai_data); 1275 } 1276 1277 static const struct component_ops q6afe_dai_comp_ops = { 1278 .bind = q6afe_dai_bind, 1279 .unbind = q6afe_dai_unbind, 1280 }; 1281 1282 static int q6afe_dai_dev_probe(struct platform_device *pdev) 1283 { 1284 return component_add(&pdev->dev, &q6afe_dai_comp_ops); 1285 } 1286 1287 static int q6afe_dai_dev_remove(struct platform_device *pdev) 1288 { 1289 component_del(&pdev->dev, &q6afe_dai_comp_ops); 1290 return 0; 1291 } 1292 1293 static struct platform_driver q6afe_dai_platform_driver = { 1294 .driver = { 1295 .name = "q6afe-dai", 1296 }, 1297 .probe = q6afe_dai_dev_probe, 1298 .remove = q6afe_dai_dev_remove, 1299 }; 1300 module_platform_driver(q6afe_dai_platform_driver); 1301 1302 MODULE_DESCRIPTION("Q6 Audio Fronend dai driver"); 1303 MODULE_LICENSE("GPL v2"); 1304