q6afe-dai.c 43 KB

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