mt8186-dai-pcm.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. // SPDX-License-Identifier: GPL-2.0
  2. //
  3. // MediaTek ALSA SoC Audio DAI I2S Control
  4. //
  5. // Copyright (c) 2022 MediaTek Inc.
  6. // Author: Jiaxin Yu <[email protected]>
  7. #include <linux/regmap.h>
  8. #include <sound/pcm_params.h>
  9. #include "mt8186-afe-common.h"
  10. #include "mt8186-afe-gpio.h"
  11. #include "mt8186-interconnection.h"
  12. struct mtk_afe_pcm_priv {
  13. unsigned int id;
  14. unsigned int fmt;
  15. unsigned int bck_invert;
  16. unsigned int lck_invert;
  17. };
  18. enum aud_tx_lch_rpt {
  19. AUD_TX_LCH_RPT_NO_REPEAT = 0,
  20. AUD_TX_LCH_RPT_REPEAT = 1
  21. };
  22. enum aud_vbt_16k_mode {
  23. AUD_VBT_16K_MODE_DISABLE = 0,
  24. AUD_VBT_16K_MODE_ENABLE = 1
  25. };
  26. enum aud_ext_modem {
  27. AUD_EXT_MODEM_SELECT_INTERNAL = 0,
  28. AUD_EXT_MODEM_SELECT_EXTERNAL = 1
  29. };
  30. enum aud_pcm_sync_type {
  31. /* bck sync length = 1 */
  32. AUD_PCM_ONE_BCK_CYCLE_SYNC = 0,
  33. /* bck sync length = PCM_INTF_CON1[9:13] */
  34. AUD_PCM_EXTENDED_BCK_CYCLE_SYNC = 1
  35. };
  36. enum aud_bt_mode {
  37. AUD_BT_MODE_DUAL_MIC_ON_TX = 0,
  38. AUD_BT_MODE_SINGLE_MIC_ON_TX = 1
  39. };
  40. enum aud_pcm_afifo_src {
  41. /* slave mode & external modem uses different crystal */
  42. AUD_PCM_AFIFO_ASRC = 0,
  43. /* slave mode & external modem uses the same crystal */
  44. AUD_PCM_AFIFO_AFIFO = 1
  45. };
  46. enum aud_pcm_clock_source {
  47. AUD_PCM_CLOCK_MASTER_MODE = 0,
  48. AUD_PCM_CLOCK_SLAVE_MODE = 1
  49. };
  50. enum aud_pcm_wlen {
  51. AUD_PCM_WLEN_PCM_32_BCK_CYCLES = 0,
  52. AUD_PCM_WLEN_PCM_64_BCK_CYCLES = 1
  53. };
  54. enum aud_pcm_24bit {
  55. AUD_PCM_24BIT_PCM_16_BITS = 0,
  56. AUD_PCM_24BIT_PCM_24_BITS = 1
  57. };
  58. enum aud_pcm_mode {
  59. AUD_PCM_MODE_PCM_MODE_8K = 0,
  60. AUD_PCM_MODE_PCM_MODE_16K = 1,
  61. AUD_PCM_MODE_PCM_MODE_32K = 2,
  62. AUD_PCM_MODE_PCM_MODE_48K = 3,
  63. };
  64. enum aud_pcm_fmt {
  65. AUD_PCM_FMT_I2S = 0,
  66. AUD_PCM_FMT_EIAJ = 1,
  67. AUD_PCM_FMT_PCM_MODE_A = 2,
  68. AUD_PCM_FMT_PCM_MODE_B = 3
  69. };
  70. enum aud_bclk_out_inv {
  71. AUD_BCLK_OUT_INV_NO_INVERSE = 0,
  72. AUD_BCLK_OUT_INV_INVERSE = 1
  73. };
  74. enum aud_lrclk_out_inv {
  75. AUD_LRCLK_OUT_INV_NO_INVERSE = 0,
  76. AUD_LRCLK_OUT_INV_INVERSE = 1
  77. };
  78. enum aud_pcm_en {
  79. AUD_PCM_EN_DISABLE = 0,
  80. AUD_PCM_EN_ENABLE = 1
  81. };
  82. /* dai component */
  83. static const struct snd_kcontrol_new mtk_pcm_1_playback_ch1_mix[] = {
  84. SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN7,
  85. I_ADDA_UL_CH1, 1, 0),
  86. SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1 Switch", AFE_CONN7,
  87. I_DL2_CH1, 1, 0),
  88. SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1 Switch", AFE_CONN7_1,
  89. I_DL4_CH1, 1, 0),
  90. };
  91. static const struct snd_kcontrol_new mtk_pcm_1_playback_ch2_mix[] = {
  92. SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN8,
  93. I_ADDA_UL_CH2, 1, 0),
  94. SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2 Switch", AFE_CONN8,
  95. I_DL2_CH2, 1, 0),
  96. SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2 Switch", AFE_CONN8_1,
  97. I_DL4_CH2, 1, 0),
  98. };
  99. static int mtk_pcm_en_event(struct snd_soc_dapm_widget *w,
  100. struct snd_kcontrol *kcontrol,
  101. int event)
  102. {
  103. struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
  104. struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
  105. dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n",
  106. __func__, w->name, event);
  107. switch (event) {
  108. case SND_SOC_DAPM_PRE_PMU:
  109. mt8186_afe_gpio_request(afe->dev, true, MT8186_DAI_PCM, 0);
  110. break;
  111. case SND_SOC_DAPM_POST_PMD:
  112. mt8186_afe_gpio_request(afe->dev, false, MT8186_DAI_PCM, 0);
  113. break;
  114. }
  115. return 0;
  116. }
  117. /* pcm in/out lpbk */
  118. static const char * const pcm_lpbk_mux_map[] = {
  119. "Normal", "Lpbk",
  120. };
  121. static int pcm_lpbk_mux_map_value[] = {
  122. 0, 1,
  123. };
  124. static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(pcm_in_lpbk_mux_map_enum,
  125. PCM_INTF_CON1,
  126. PCM_I2S_PCM_LOOPBACK_SFT,
  127. 1,
  128. pcm_lpbk_mux_map,
  129. pcm_lpbk_mux_map_value);
  130. static const struct snd_kcontrol_new pcm_in_lpbk_mux_control =
  131. SOC_DAPM_ENUM("PCM In Lpbk Select", pcm_in_lpbk_mux_map_enum);
  132. static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(pcm_out_lpbk_mux_map_enum,
  133. PCM_INTF_CON1,
  134. PCM_I2S_PCM_LOOPBACK_SFT,
  135. 1,
  136. pcm_lpbk_mux_map,
  137. pcm_lpbk_mux_map_value);
  138. static const struct snd_kcontrol_new pcm_out_lpbk_mux_control =
  139. SOC_DAPM_ENUM("PCM Out Lpbk Select", pcm_out_lpbk_mux_map_enum);
  140. static const struct snd_soc_dapm_widget mtk_dai_pcm_widgets[] = {
  141. /* inter-connections */
  142. SND_SOC_DAPM_MIXER("PCM_1_PB_CH1", SND_SOC_NOPM, 0, 0,
  143. mtk_pcm_1_playback_ch1_mix,
  144. ARRAY_SIZE(mtk_pcm_1_playback_ch1_mix)),
  145. SND_SOC_DAPM_MIXER("PCM_1_PB_CH2", SND_SOC_NOPM, 0, 0,
  146. mtk_pcm_1_playback_ch2_mix,
  147. ARRAY_SIZE(mtk_pcm_1_playback_ch2_mix)),
  148. SND_SOC_DAPM_SUPPLY("PCM_1_EN",
  149. PCM_INTF_CON1, PCM_EN_SFT, 0,
  150. mtk_pcm_en_event,
  151. SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
  152. /* pcm in lpbk */
  153. SND_SOC_DAPM_MUX("PCM_In_Lpbk_Mux",
  154. SND_SOC_NOPM, 0, 0, &pcm_in_lpbk_mux_control),
  155. /* pcm out lpbk */
  156. SND_SOC_DAPM_MUX("PCM_Out_Lpbk_Mux",
  157. SND_SOC_NOPM, 0, 0, &pcm_out_lpbk_mux_control),
  158. };
  159. static const struct snd_soc_dapm_route mtk_dai_pcm_routes[] = {
  160. {"PCM 1 Playback", NULL, "PCM_1_PB_CH1"},
  161. {"PCM 1 Playback", NULL, "PCM_1_PB_CH2"},
  162. {"PCM 1 Playback", NULL, "PCM_1_EN"},
  163. {"PCM 1 Capture", NULL, "PCM_1_EN"},
  164. {"PCM_1_PB_CH1", "DL2_CH1 Switch", "DL2"},
  165. {"PCM_1_PB_CH2", "DL2_CH2 Switch", "DL2"},
  166. {"PCM_1_PB_CH1", "DL4_CH1 Switch", "DL4"},
  167. {"PCM_1_PB_CH2", "DL4_CH2 Switch", "DL4"},
  168. /* pcm out lpbk */
  169. {"PCM_Out_Lpbk_Mux", "Lpbk", "PCM 1 Playback"},
  170. {"I2S0", NULL, "PCM_Out_Lpbk_Mux"},
  171. /* pcm in lpbk */
  172. {"PCM_In_Lpbk_Mux", "Lpbk", "PCM 1 Capture"},
  173. {"I2S3", NULL, "PCM_In_Lpbk_Mux"},
  174. };
  175. /* dai ops */
  176. static int mtk_dai_pcm_hw_params(struct snd_pcm_substream *substream,
  177. struct snd_pcm_hw_params *params,
  178. struct snd_soc_dai *dai)
  179. {
  180. struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
  181. struct mt8186_afe_private *afe_priv = afe->platform_priv;
  182. int pcm_id = dai->id;
  183. struct mtk_afe_pcm_priv *pcm_priv = afe_priv->dai_priv[pcm_id];
  184. unsigned int rate = params_rate(params);
  185. unsigned int rate_reg = mt8186_rate_transform(afe->dev, rate, dai->id);
  186. snd_pcm_format_t format = params_format(params);
  187. unsigned int data_width =
  188. snd_pcm_format_width(format);
  189. unsigned int wlen_width =
  190. snd_pcm_format_physical_width(format);
  191. unsigned int pcm_con = 0;
  192. dev_dbg(afe->dev, "%s(), id %d, stream %d, widget active p %d, c %d\n",
  193. __func__, dai->id, substream->stream, dai->playback_widget->active,
  194. dai->capture_widget->active);
  195. dev_dbg(afe->dev, "%s(), rate %d, rate_reg %d, data_width %d, wlen_width %d\n",
  196. __func__, rate, rate_reg, data_width, wlen_width);
  197. if (dai->playback_widget->active || dai->capture_widget->active)
  198. return 0;
  199. switch (dai->id) {
  200. case MT8186_DAI_PCM:
  201. pcm_con |= AUD_TX_LCH_RPT_NO_REPEAT << PCM_TX_LCH_RPT_SFT;
  202. pcm_con |= AUD_VBT_16K_MODE_DISABLE << PCM_VBT_16K_MODE_SFT;
  203. pcm_con |= AUD_EXT_MODEM_SELECT_EXTERNAL << PCM_EXT_MODEM_SFT;
  204. pcm_con |= AUD_PCM_ONE_BCK_CYCLE_SYNC << PCM_SYNC_TYPE_SFT;
  205. pcm_con |= AUD_BT_MODE_DUAL_MIC_ON_TX << PCM_BT_MODE_SFT;
  206. pcm_con |= AUD_PCM_AFIFO_AFIFO << PCM_BYP_ASRC_SFT;
  207. pcm_con |= AUD_PCM_CLOCK_MASTER_MODE << PCM_SLAVE_SFT;
  208. pcm_con |= 0 << PCM_SYNC_LENGTH_SFT;
  209. /* sampling rate */
  210. pcm_con |= rate_reg << PCM_MODE_SFT;
  211. /* format */
  212. pcm_con |= pcm_priv->fmt << PCM_FMT_SFT;
  213. /* 24bit data width */
  214. if (data_width > 16)
  215. pcm_con |= AUD_PCM_24BIT_PCM_24_BITS << PCM_24BIT_SFT;
  216. else
  217. pcm_con |= AUD_PCM_24BIT_PCM_16_BITS << PCM_24BIT_SFT;
  218. /* wlen width*/
  219. if (wlen_width > 16)
  220. pcm_con |= AUD_PCM_WLEN_PCM_64_BCK_CYCLES << PCM_WLEN_SFT;
  221. else
  222. pcm_con |= AUD_PCM_WLEN_PCM_32_BCK_CYCLES << PCM_WLEN_SFT;
  223. /* clock invert */
  224. pcm_con |= pcm_priv->lck_invert << PCM_SYNC_OUT_INV_SFT;
  225. pcm_con |= pcm_priv->bck_invert << PCM_BCLK_OUT_INV_SFT;
  226. regmap_update_bits(afe->regmap, PCM_INTF_CON1, 0xfffffffe, pcm_con);
  227. break;
  228. default:
  229. dev_err(afe->dev, "%s(), id %d not support\n", __func__, dai->id);
  230. return -EINVAL;
  231. }
  232. return 0;
  233. }
  234. static int mtk_dai_pcm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
  235. {
  236. struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
  237. struct mt8186_afe_private *afe_priv = afe->platform_priv;
  238. struct mtk_afe_pcm_priv *pcm_priv = afe_priv->dai_priv[dai->id];
  239. /* DAI mode*/
  240. switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
  241. case SND_SOC_DAIFMT_I2S:
  242. pcm_priv->fmt = AUD_PCM_FMT_I2S;
  243. break;
  244. case SND_SOC_DAIFMT_LEFT_J:
  245. pcm_priv->fmt = AUD_PCM_FMT_EIAJ;
  246. break;
  247. case SND_SOC_DAIFMT_DSP_A:
  248. pcm_priv->fmt = AUD_PCM_FMT_PCM_MODE_A;
  249. break;
  250. case SND_SOC_DAIFMT_DSP_B:
  251. pcm_priv->fmt = AUD_PCM_FMT_PCM_MODE_B;
  252. break;
  253. default:
  254. pcm_priv->fmt = AUD_PCM_FMT_I2S;
  255. }
  256. /* DAI clock inversion*/
  257. switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
  258. case SND_SOC_DAIFMT_NB_NF:
  259. pcm_priv->bck_invert = AUD_BCLK_OUT_INV_NO_INVERSE;
  260. pcm_priv->lck_invert = AUD_LRCLK_OUT_INV_NO_INVERSE;
  261. break;
  262. case SND_SOC_DAIFMT_NB_IF:
  263. pcm_priv->bck_invert = AUD_BCLK_OUT_INV_NO_INVERSE;
  264. pcm_priv->lck_invert = AUD_BCLK_OUT_INV_INVERSE;
  265. break;
  266. case SND_SOC_DAIFMT_IB_NF:
  267. pcm_priv->bck_invert = AUD_BCLK_OUT_INV_INVERSE;
  268. pcm_priv->lck_invert = AUD_LRCLK_OUT_INV_NO_INVERSE;
  269. break;
  270. case SND_SOC_DAIFMT_IB_IF:
  271. pcm_priv->bck_invert = AUD_BCLK_OUT_INV_INVERSE;
  272. pcm_priv->lck_invert = AUD_BCLK_OUT_INV_INVERSE;
  273. break;
  274. default:
  275. pcm_priv->bck_invert = AUD_BCLK_OUT_INV_NO_INVERSE;
  276. pcm_priv->lck_invert = AUD_LRCLK_OUT_INV_NO_INVERSE;
  277. break;
  278. }
  279. return 0;
  280. }
  281. static const struct snd_soc_dai_ops mtk_dai_pcm_ops = {
  282. .hw_params = mtk_dai_pcm_hw_params,
  283. .set_fmt = mtk_dai_pcm_set_fmt,
  284. };
  285. /* dai driver */
  286. #define MTK_PCM_RATES (SNDRV_PCM_RATE_8000 |\
  287. SNDRV_PCM_RATE_16000 |\
  288. SNDRV_PCM_RATE_32000 |\
  289. SNDRV_PCM_RATE_48000)
  290. #define MTK_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
  291. SNDRV_PCM_FMTBIT_S24_LE |\
  292. SNDRV_PCM_FMTBIT_S32_LE)
  293. static struct snd_soc_dai_driver mtk_dai_pcm_driver[] = {
  294. {
  295. .name = "PCM 1",
  296. .id = MT8186_DAI_PCM,
  297. .playback = {
  298. .stream_name = "PCM 1 Playback",
  299. .channels_min = 1,
  300. .channels_max = 2,
  301. .rates = MTK_PCM_RATES,
  302. .formats = MTK_PCM_FORMATS,
  303. },
  304. .capture = {
  305. .stream_name = "PCM 1 Capture",
  306. .channels_min = 1,
  307. .channels_max = 2,
  308. .rates = MTK_PCM_RATES,
  309. .formats = MTK_PCM_FORMATS,
  310. },
  311. .ops = &mtk_dai_pcm_ops,
  312. .symmetric_rate = 1,
  313. .symmetric_sample_bits = 1,
  314. },
  315. };
  316. static struct mtk_afe_pcm_priv *init_pcm_priv_data(struct mtk_base_afe *afe)
  317. {
  318. struct mtk_afe_pcm_priv *pcm_priv;
  319. pcm_priv = devm_kzalloc(afe->dev, sizeof(struct mtk_afe_pcm_priv),
  320. GFP_KERNEL);
  321. if (!pcm_priv)
  322. return NULL;
  323. pcm_priv->id = MT8186_DAI_PCM;
  324. pcm_priv->fmt = AUD_PCM_FMT_I2S;
  325. pcm_priv->bck_invert = AUD_BCLK_OUT_INV_NO_INVERSE;
  326. pcm_priv->lck_invert = AUD_LRCLK_OUT_INV_NO_INVERSE;
  327. return pcm_priv;
  328. }
  329. int mt8186_dai_pcm_register(struct mtk_base_afe *afe)
  330. {
  331. struct mt8186_afe_private *afe_priv = afe->platform_priv;
  332. struct mtk_afe_pcm_priv *pcm_priv;
  333. struct mtk_base_afe_dai *dai;
  334. dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
  335. if (!dai)
  336. return -ENOMEM;
  337. list_add(&dai->list, &afe->sub_dais);
  338. dai->dai_drivers = mtk_dai_pcm_driver;
  339. dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_pcm_driver);
  340. dai->dapm_widgets = mtk_dai_pcm_widgets;
  341. dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_pcm_widgets);
  342. dai->dapm_routes = mtk_dai_pcm_routes;
  343. dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_pcm_routes);
  344. pcm_priv = init_pcm_priv_data(afe);
  345. if (!pcm_priv)
  346. return -ENOMEM;
  347. afe_priv->dai_priv[MT8186_DAI_PCM] = pcm_priv;
  348. return 0;
  349. }