mt8192-dai-tdm.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780
  1. // SPDX-License-Identifier: GPL-2.0
  2. //
  3. // MediaTek ALSA SoC Audio DAI TDM Control
  4. //
  5. // Copyright (c) 2020 MediaTek Inc.
  6. // Author: Shane Chien <[email protected]>
  7. #include <linux/regmap.h>
  8. #include <sound/pcm_params.h>
  9. #include "mt8192-afe-clk.h"
  10. #include "mt8192-afe-common.h"
  11. #include "mt8192-afe-gpio.h"
  12. #include "mt8192-interconnection.h"
  13. struct mtk_afe_tdm_priv {
  14. int id;
  15. int bck_id;
  16. int bck_rate;
  17. int tdm_out_mode;
  18. int bck_invert;
  19. int lck_invert;
  20. int mclk_id;
  21. int mclk_multiple; /* according to sample rate */
  22. int mclk_rate;
  23. int mclk_apll;
  24. };
  25. enum {
  26. TDM_OUT_I2S = 0,
  27. TDM_OUT_DSP_A = 1,
  28. TDM_OUT_DSP_B = 2,
  29. };
  30. enum {
  31. TDM_BCK_NON_INV = 0,
  32. TDM_BCK_INV = 1,
  33. };
  34. enum {
  35. TDM_LCK_NON_INV = 0,
  36. TDM_LCK_INV = 1,
  37. };
  38. enum {
  39. TDM_WLEN_16_BIT = 1,
  40. TDM_WLEN_32_BIT = 2,
  41. };
  42. enum {
  43. TDM_CHANNEL_BCK_16 = 0,
  44. TDM_CHANNEL_BCK_24 = 1,
  45. TDM_CHANNEL_BCK_32 = 2,
  46. };
  47. enum {
  48. TDM_CHANNEL_NUM_2 = 0,
  49. TDM_CHANNEL_NUM_4 = 1,
  50. TDM_CHANNEL_NUM_8 = 2,
  51. };
  52. enum {
  53. TDM_CH_START_O30_O31 = 0,
  54. TDM_CH_START_O32_O33,
  55. TDM_CH_START_O34_O35,
  56. TDM_CH_START_O36_O37,
  57. TDM_CH_ZERO,
  58. };
  59. static unsigned int get_tdm_wlen(snd_pcm_format_t format)
  60. {
  61. return snd_pcm_format_physical_width(format) <= 16 ?
  62. TDM_WLEN_16_BIT : TDM_WLEN_32_BIT;
  63. }
  64. static unsigned int get_tdm_channel_bck(snd_pcm_format_t format)
  65. {
  66. return snd_pcm_format_physical_width(format) <= 16 ?
  67. TDM_CHANNEL_BCK_16 : TDM_CHANNEL_BCK_32;
  68. }
  69. static unsigned int get_tdm_lrck_width(snd_pcm_format_t format)
  70. {
  71. return snd_pcm_format_physical_width(format) - 1;
  72. }
  73. static unsigned int get_tdm_ch(unsigned int ch)
  74. {
  75. switch (ch) {
  76. case 1:
  77. case 2:
  78. return TDM_CHANNEL_NUM_2;
  79. case 3:
  80. case 4:
  81. return TDM_CHANNEL_NUM_4;
  82. case 5:
  83. case 6:
  84. case 7:
  85. case 8:
  86. default:
  87. return TDM_CHANNEL_NUM_8;
  88. }
  89. }
  90. static unsigned int get_tdm_ch_fixup(unsigned int channels)
  91. {
  92. if (channels > 4)
  93. return 8;
  94. else if (channels > 2)
  95. return 4;
  96. else
  97. return 2;
  98. }
  99. static unsigned int get_tdm_ch_per_sdata(unsigned int mode,
  100. unsigned int channels)
  101. {
  102. if (mode == TDM_OUT_DSP_A || mode == TDM_OUT_DSP_B)
  103. return get_tdm_ch_fixup(channels);
  104. else
  105. return 2;
  106. }
  107. /* interconnection */
  108. enum {
  109. HDMI_CONN_CH0 = 0,
  110. HDMI_CONN_CH1,
  111. HDMI_CONN_CH2,
  112. HDMI_CONN_CH3,
  113. HDMI_CONN_CH4,
  114. HDMI_CONN_CH5,
  115. HDMI_CONN_CH6,
  116. HDMI_CONN_CH7,
  117. };
  118. static const char *const hdmi_conn_mux_map[] = {
  119. "CH0", "CH1", "CH2", "CH3",
  120. "CH4", "CH5", "CH6", "CH7",
  121. };
  122. static int hdmi_conn_mux_map_value[] = {
  123. HDMI_CONN_CH0,
  124. HDMI_CONN_CH1,
  125. HDMI_CONN_CH2,
  126. HDMI_CONN_CH3,
  127. HDMI_CONN_CH4,
  128. HDMI_CONN_CH5,
  129. HDMI_CONN_CH6,
  130. HDMI_CONN_CH7,
  131. };
  132. static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch0_mux_map_enum,
  133. AFE_HDMI_CONN0,
  134. HDMI_O_0_SFT,
  135. HDMI_O_0_MASK,
  136. hdmi_conn_mux_map,
  137. hdmi_conn_mux_map_value);
  138. static const struct snd_kcontrol_new hdmi_ch0_mux_control =
  139. SOC_DAPM_ENUM("HDMI_CH0_MUX", hdmi_ch0_mux_map_enum);
  140. static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch1_mux_map_enum,
  141. AFE_HDMI_CONN0,
  142. HDMI_O_1_SFT,
  143. HDMI_O_1_MASK,
  144. hdmi_conn_mux_map,
  145. hdmi_conn_mux_map_value);
  146. static const struct snd_kcontrol_new hdmi_ch1_mux_control =
  147. SOC_DAPM_ENUM("HDMI_CH1_MUX", hdmi_ch1_mux_map_enum);
  148. static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch2_mux_map_enum,
  149. AFE_HDMI_CONN0,
  150. HDMI_O_2_SFT,
  151. HDMI_O_2_MASK,
  152. hdmi_conn_mux_map,
  153. hdmi_conn_mux_map_value);
  154. static const struct snd_kcontrol_new hdmi_ch2_mux_control =
  155. SOC_DAPM_ENUM("HDMI_CH2_MUX", hdmi_ch2_mux_map_enum);
  156. static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch3_mux_map_enum,
  157. AFE_HDMI_CONN0,
  158. HDMI_O_3_SFT,
  159. HDMI_O_3_MASK,
  160. hdmi_conn_mux_map,
  161. hdmi_conn_mux_map_value);
  162. static const struct snd_kcontrol_new hdmi_ch3_mux_control =
  163. SOC_DAPM_ENUM("HDMI_CH3_MUX", hdmi_ch3_mux_map_enum);
  164. static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch4_mux_map_enum,
  165. AFE_HDMI_CONN0,
  166. HDMI_O_4_SFT,
  167. HDMI_O_4_MASK,
  168. hdmi_conn_mux_map,
  169. hdmi_conn_mux_map_value);
  170. static const struct snd_kcontrol_new hdmi_ch4_mux_control =
  171. SOC_DAPM_ENUM("HDMI_CH4_MUX", hdmi_ch4_mux_map_enum);
  172. static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch5_mux_map_enum,
  173. AFE_HDMI_CONN0,
  174. HDMI_O_5_SFT,
  175. HDMI_O_5_MASK,
  176. hdmi_conn_mux_map,
  177. hdmi_conn_mux_map_value);
  178. static const struct snd_kcontrol_new hdmi_ch5_mux_control =
  179. SOC_DAPM_ENUM("HDMI_CH5_MUX", hdmi_ch5_mux_map_enum);
  180. static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch6_mux_map_enum,
  181. AFE_HDMI_CONN0,
  182. HDMI_O_6_SFT,
  183. HDMI_O_6_MASK,
  184. hdmi_conn_mux_map,
  185. hdmi_conn_mux_map_value);
  186. static const struct snd_kcontrol_new hdmi_ch6_mux_control =
  187. SOC_DAPM_ENUM("HDMI_CH6_MUX", hdmi_ch6_mux_map_enum);
  188. static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch7_mux_map_enum,
  189. AFE_HDMI_CONN0,
  190. HDMI_O_7_SFT,
  191. HDMI_O_7_MASK,
  192. hdmi_conn_mux_map,
  193. hdmi_conn_mux_map_value);
  194. static const struct snd_kcontrol_new hdmi_ch7_mux_control =
  195. SOC_DAPM_ENUM("HDMI_CH7_MUX", hdmi_ch7_mux_map_enum);
  196. enum {
  197. SUPPLY_SEQ_APLL,
  198. SUPPLY_SEQ_TDM_MCK_EN,
  199. SUPPLY_SEQ_TDM_BCK_EN,
  200. SUPPLY_SEQ_TDM_EN,
  201. };
  202. static int get_tdm_id_by_name(const char *name)
  203. {
  204. return MT8192_DAI_TDM;
  205. }
  206. static int mtk_tdm_en_event(struct snd_soc_dapm_widget *w,
  207. struct snd_kcontrol *kcontrol,
  208. int event)
  209. {
  210. struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
  211. struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
  212. struct mt8192_afe_private *afe_priv = afe->platform_priv;
  213. int dai_id = get_tdm_id_by_name(w->name);
  214. struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
  215. if (!tdm_priv) {
  216. dev_warn(afe->dev, "%s(), tdm_priv == NULL", __func__);
  217. return -EINVAL;
  218. }
  219. dev_info(cmpnt->dev, "%s(), name %s, event 0x%x\n",
  220. __func__, w->name, event);
  221. switch (event) {
  222. case SND_SOC_DAPM_PRE_PMU:
  223. mt8192_afe_gpio_request(afe->dev, true, tdm_priv->id, 0);
  224. break;
  225. case SND_SOC_DAPM_POST_PMD:
  226. mt8192_afe_gpio_request(afe->dev, false, tdm_priv->id, 0);
  227. break;
  228. default:
  229. break;
  230. }
  231. return 0;
  232. }
  233. static int mtk_tdm_bck_en_event(struct snd_soc_dapm_widget *w,
  234. struct snd_kcontrol *kcontrol,
  235. int event)
  236. {
  237. struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
  238. struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
  239. struct mt8192_afe_private *afe_priv = afe->platform_priv;
  240. int dai_id = get_tdm_id_by_name(w->name);
  241. struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
  242. if (!tdm_priv) {
  243. dev_warn(afe->dev, "%s(), tdm_priv == NULL", __func__);
  244. return -EINVAL;
  245. }
  246. dev_info(cmpnt->dev, "%s(), name %s, event 0x%x, dai_id %d\n",
  247. __func__, w->name, event, dai_id);
  248. switch (event) {
  249. case SND_SOC_DAPM_PRE_PMU:
  250. mt8192_mck_enable(afe, tdm_priv->bck_id, tdm_priv->bck_rate);
  251. break;
  252. case SND_SOC_DAPM_POST_PMD:
  253. mt8192_mck_disable(afe, tdm_priv->bck_id);
  254. break;
  255. default:
  256. break;
  257. }
  258. return 0;
  259. }
  260. static int mtk_tdm_mck_en_event(struct snd_soc_dapm_widget *w,
  261. struct snd_kcontrol *kcontrol,
  262. int event)
  263. {
  264. struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
  265. struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
  266. struct mt8192_afe_private *afe_priv = afe->platform_priv;
  267. int dai_id = get_tdm_id_by_name(w->name);
  268. struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
  269. if (!tdm_priv) {
  270. dev_warn(afe->dev, "%s(), tdm_priv == NULL", __func__);
  271. return -EINVAL;
  272. }
  273. dev_info(cmpnt->dev, "%s(), name %s, event 0x%x, dai_id %d\n",
  274. __func__, w->name, event, dai_id);
  275. switch (event) {
  276. case SND_SOC_DAPM_PRE_PMU:
  277. mt8192_mck_enable(afe, tdm_priv->mclk_id, tdm_priv->mclk_rate);
  278. break;
  279. case SND_SOC_DAPM_POST_PMD:
  280. tdm_priv->mclk_rate = 0;
  281. mt8192_mck_disable(afe, tdm_priv->mclk_id);
  282. break;
  283. default:
  284. break;
  285. }
  286. return 0;
  287. }
  288. static const struct snd_soc_dapm_widget mtk_dai_tdm_widgets[] = {
  289. SND_SOC_DAPM_MUX("HDMI_CH0_MUX", SND_SOC_NOPM, 0, 0,
  290. &hdmi_ch0_mux_control),
  291. SND_SOC_DAPM_MUX("HDMI_CH1_MUX", SND_SOC_NOPM, 0, 0,
  292. &hdmi_ch1_mux_control),
  293. SND_SOC_DAPM_MUX("HDMI_CH2_MUX", SND_SOC_NOPM, 0, 0,
  294. &hdmi_ch2_mux_control),
  295. SND_SOC_DAPM_MUX("HDMI_CH3_MUX", SND_SOC_NOPM, 0, 0,
  296. &hdmi_ch3_mux_control),
  297. SND_SOC_DAPM_MUX("HDMI_CH4_MUX", SND_SOC_NOPM, 0, 0,
  298. &hdmi_ch4_mux_control),
  299. SND_SOC_DAPM_MUX("HDMI_CH5_MUX", SND_SOC_NOPM, 0, 0,
  300. &hdmi_ch5_mux_control),
  301. SND_SOC_DAPM_MUX("HDMI_CH6_MUX", SND_SOC_NOPM, 0, 0,
  302. &hdmi_ch6_mux_control),
  303. SND_SOC_DAPM_MUX("HDMI_CH7_MUX", SND_SOC_NOPM, 0, 0,
  304. &hdmi_ch7_mux_control),
  305. SND_SOC_DAPM_CLOCK_SUPPLY("aud_tdm_clk"),
  306. SND_SOC_DAPM_SUPPLY_S("TDM_EN", SUPPLY_SEQ_TDM_EN,
  307. AFE_TDM_CON1, TDM_EN_SFT, 0,
  308. mtk_tdm_en_event,
  309. SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
  310. SND_SOC_DAPM_SUPPLY_S("TDM_BCK", SUPPLY_SEQ_TDM_BCK_EN,
  311. SND_SOC_NOPM, 0, 0,
  312. mtk_tdm_bck_en_event,
  313. SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
  314. SND_SOC_DAPM_SUPPLY_S("TDM_MCK", SUPPLY_SEQ_TDM_MCK_EN,
  315. SND_SOC_NOPM, 0, 0,
  316. mtk_tdm_mck_en_event,
  317. SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
  318. };
  319. static int mtk_afe_tdm_apll_connect(struct snd_soc_dapm_widget *source,
  320. struct snd_soc_dapm_widget *sink)
  321. {
  322. struct snd_soc_dapm_widget *w = sink;
  323. struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
  324. struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
  325. struct mt8192_afe_private *afe_priv = afe->platform_priv;
  326. int dai_id = get_tdm_id_by_name(w->name);
  327. struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
  328. int cur_apll;
  329. /* which apll */
  330. cur_apll = mt8192_get_apll_by_name(afe, source->name);
  331. return (tdm_priv->mclk_apll == cur_apll) ? 1 : 0;
  332. }
  333. static const struct snd_soc_dapm_route mtk_dai_tdm_routes[] = {
  334. {"HDMI_CH0_MUX", "CH0", "HDMI"},
  335. {"HDMI_CH0_MUX", "CH1", "HDMI"},
  336. {"HDMI_CH0_MUX", "CH2", "HDMI"},
  337. {"HDMI_CH0_MUX", "CH3", "HDMI"},
  338. {"HDMI_CH0_MUX", "CH4", "HDMI"},
  339. {"HDMI_CH0_MUX", "CH5", "HDMI"},
  340. {"HDMI_CH0_MUX", "CH6", "HDMI"},
  341. {"HDMI_CH0_MUX", "CH7", "HDMI"},
  342. {"HDMI_CH1_MUX", "CH0", "HDMI"},
  343. {"HDMI_CH1_MUX", "CH1", "HDMI"},
  344. {"HDMI_CH1_MUX", "CH2", "HDMI"},
  345. {"HDMI_CH1_MUX", "CH3", "HDMI"},
  346. {"HDMI_CH1_MUX", "CH4", "HDMI"},
  347. {"HDMI_CH1_MUX", "CH5", "HDMI"},
  348. {"HDMI_CH1_MUX", "CH6", "HDMI"},
  349. {"HDMI_CH1_MUX", "CH7", "HDMI"},
  350. {"HDMI_CH2_MUX", "CH0", "HDMI"},
  351. {"HDMI_CH2_MUX", "CH1", "HDMI"},
  352. {"HDMI_CH2_MUX", "CH2", "HDMI"},
  353. {"HDMI_CH2_MUX", "CH3", "HDMI"},
  354. {"HDMI_CH2_MUX", "CH4", "HDMI"},
  355. {"HDMI_CH2_MUX", "CH5", "HDMI"},
  356. {"HDMI_CH2_MUX", "CH6", "HDMI"},
  357. {"HDMI_CH2_MUX", "CH7", "HDMI"},
  358. {"HDMI_CH3_MUX", "CH0", "HDMI"},
  359. {"HDMI_CH3_MUX", "CH1", "HDMI"},
  360. {"HDMI_CH3_MUX", "CH2", "HDMI"},
  361. {"HDMI_CH3_MUX", "CH3", "HDMI"},
  362. {"HDMI_CH3_MUX", "CH4", "HDMI"},
  363. {"HDMI_CH3_MUX", "CH5", "HDMI"},
  364. {"HDMI_CH3_MUX", "CH6", "HDMI"},
  365. {"HDMI_CH3_MUX", "CH7", "HDMI"},
  366. {"HDMI_CH4_MUX", "CH0", "HDMI"},
  367. {"HDMI_CH4_MUX", "CH1", "HDMI"},
  368. {"HDMI_CH4_MUX", "CH2", "HDMI"},
  369. {"HDMI_CH4_MUX", "CH3", "HDMI"},
  370. {"HDMI_CH4_MUX", "CH4", "HDMI"},
  371. {"HDMI_CH4_MUX", "CH5", "HDMI"},
  372. {"HDMI_CH4_MUX", "CH6", "HDMI"},
  373. {"HDMI_CH4_MUX", "CH7", "HDMI"},
  374. {"HDMI_CH5_MUX", "CH0", "HDMI"},
  375. {"HDMI_CH5_MUX", "CH1", "HDMI"},
  376. {"HDMI_CH5_MUX", "CH2", "HDMI"},
  377. {"HDMI_CH5_MUX", "CH3", "HDMI"},
  378. {"HDMI_CH5_MUX", "CH4", "HDMI"},
  379. {"HDMI_CH5_MUX", "CH5", "HDMI"},
  380. {"HDMI_CH5_MUX", "CH6", "HDMI"},
  381. {"HDMI_CH5_MUX", "CH7", "HDMI"},
  382. {"HDMI_CH6_MUX", "CH0", "HDMI"},
  383. {"HDMI_CH6_MUX", "CH1", "HDMI"},
  384. {"HDMI_CH6_MUX", "CH2", "HDMI"},
  385. {"HDMI_CH6_MUX", "CH3", "HDMI"},
  386. {"HDMI_CH6_MUX", "CH4", "HDMI"},
  387. {"HDMI_CH6_MUX", "CH5", "HDMI"},
  388. {"HDMI_CH6_MUX", "CH6", "HDMI"},
  389. {"HDMI_CH6_MUX", "CH7", "HDMI"},
  390. {"HDMI_CH7_MUX", "CH0", "HDMI"},
  391. {"HDMI_CH7_MUX", "CH1", "HDMI"},
  392. {"HDMI_CH7_MUX", "CH2", "HDMI"},
  393. {"HDMI_CH7_MUX", "CH3", "HDMI"},
  394. {"HDMI_CH7_MUX", "CH4", "HDMI"},
  395. {"HDMI_CH7_MUX", "CH5", "HDMI"},
  396. {"HDMI_CH7_MUX", "CH6", "HDMI"},
  397. {"HDMI_CH7_MUX", "CH7", "HDMI"},
  398. {"TDM", NULL, "HDMI_CH0_MUX"},
  399. {"TDM", NULL, "HDMI_CH1_MUX"},
  400. {"TDM", NULL, "HDMI_CH2_MUX"},
  401. {"TDM", NULL, "HDMI_CH3_MUX"},
  402. {"TDM", NULL, "HDMI_CH4_MUX"},
  403. {"TDM", NULL, "HDMI_CH5_MUX"},
  404. {"TDM", NULL, "HDMI_CH6_MUX"},
  405. {"TDM", NULL, "HDMI_CH7_MUX"},
  406. {"TDM", NULL, "aud_tdm_clk"},
  407. {"TDM", NULL, "TDM_BCK"},
  408. {"TDM", NULL, "TDM_EN"},
  409. {"TDM_BCK", NULL, "TDM_MCK"},
  410. {"TDM_MCK", NULL, APLL1_W_NAME, mtk_afe_tdm_apll_connect},
  411. {"TDM_MCK", NULL, APLL2_W_NAME, mtk_afe_tdm_apll_connect},
  412. };
  413. /* dai ops */
  414. static int mtk_dai_tdm_cal_mclk(struct mtk_base_afe *afe,
  415. struct mtk_afe_tdm_priv *tdm_priv,
  416. int freq)
  417. {
  418. int apll;
  419. int apll_rate;
  420. apll = mt8192_get_apll_by_rate(afe, freq);
  421. apll_rate = mt8192_get_apll_rate(afe, apll);
  422. if (!freq || freq > apll_rate) {
  423. dev_warn(afe->dev,
  424. "%s(), freq(%d Hz) invalid\n", __func__, freq);
  425. return -EINVAL;
  426. }
  427. if (apll_rate % freq != 0) {
  428. dev_warn(afe->dev,
  429. "%s(), APLL cannot generate %d Hz", __func__, freq);
  430. return -EINVAL;
  431. }
  432. tdm_priv->mclk_rate = freq;
  433. tdm_priv->mclk_apll = apll;
  434. return 0;
  435. }
  436. static int mtk_dai_tdm_hw_params(struct snd_pcm_substream *substream,
  437. struct snd_pcm_hw_params *params,
  438. struct snd_soc_dai *dai)
  439. {
  440. struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
  441. struct mt8192_afe_private *afe_priv = afe->platform_priv;
  442. int tdm_id = dai->id;
  443. struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[tdm_id];
  444. unsigned int tdm_out_mode = tdm_priv->tdm_out_mode;
  445. unsigned int rate = params_rate(params);
  446. unsigned int channels = params_channels(params);
  447. unsigned int out_channels_per_sdata =
  448. get_tdm_ch_per_sdata(tdm_out_mode, channels);
  449. snd_pcm_format_t format = params_format(params);
  450. unsigned int tdm_con = 0;
  451. /* calculate mclk_rate, if not set explicitly */
  452. if (!tdm_priv->mclk_rate) {
  453. tdm_priv->mclk_rate = rate * tdm_priv->mclk_multiple;
  454. mtk_dai_tdm_cal_mclk(afe,
  455. tdm_priv,
  456. tdm_priv->mclk_rate);
  457. }
  458. /* calculate bck */
  459. tdm_priv->bck_rate = rate *
  460. out_channels_per_sdata *
  461. snd_pcm_format_physical_width(format);
  462. if (tdm_priv->bck_rate > tdm_priv->mclk_rate)
  463. dev_warn(afe->dev, "%s(), bck_rate > mclk_rate rate", __func__);
  464. if (tdm_priv->mclk_rate % tdm_priv->bck_rate != 0)
  465. dev_warn(afe->dev, "%s(), bck cannot generate", __func__);
  466. dev_info(afe->dev, "%s(), id %d, rate %d, channels %d, format %d, mclk_rate %d, bck_rate %d\n",
  467. __func__,
  468. tdm_id, rate, channels, format,
  469. tdm_priv->mclk_rate, tdm_priv->bck_rate);
  470. dev_info(afe->dev, "%s(), out_channels_per_sdata = %d\n",
  471. __func__, out_channels_per_sdata);
  472. /* set tdm */
  473. if (tdm_priv->bck_invert)
  474. regmap_update_bits(afe->regmap, AUDIO_TOP_CON3,
  475. BCK_INVERSE_MASK_SFT,
  476. 0x1 << BCK_INVERSE_SFT);
  477. if (tdm_priv->lck_invert)
  478. tdm_con |= 1 << LRCK_INVERSE_SFT;
  479. if (tdm_priv->tdm_out_mode == TDM_OUT_I2S) {
  480. tdm_con |= 1 << DELAY_DATA_SFT;
  481. tdm_con |= get_tdm_lrck_width(format) << LRCK_TDM_WIDTH_SFT;
  482. } else if (tdm_priv->tdm_out_mode == TDM_OUT_DSP_A) {
  483. tdm_con |= 0 << DELAY_DATA_SFT;
  484. tdm_con |= 0 << LRCK_TDM_WIDTH_SFT;
  485. } else if (tdm_priv->tdm_out_mode == TDM_OUT_DSP_B) {
  486. tdm_con |= 1 << DELAY_DATA_SFT;
  487. tdm_con |= 0 << LRCK_TDM_WIDTH_SFT;
  488. }
  489. tdm_con |= 1 << LEFT_ALIGN_SFT;
  490. tdm_con |= get_tdm_wlen(format) << WLEN_SFT;
  491. tdm_con |= get_tdm_ch(out_channels_per_sdata) << CHANNEL_NUM_SFT;
  492. tdm_con |= get_tdm_channel_bck(format) << CHANNEL_BCK_CYCLES_SFT;
  493. regmap_write(afe->regmap, AFE_TDM_CON1, tdm_con);
  494. if (out_channels_per_sdata == 2) {
  495. switch (channels) {
  496. case 1:
  497. case 2:
  498. tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
  499. tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT1_SFT;
  500. tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT2_SFT;
  501. tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT;
  502. break;
  503. case 3:
  504. case 4:
  505. tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
  506. tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT;
  507. tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT2_SFT;
  508. tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT;
  509. break;
  510. case 5:
  511. case 6:
  512. tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
  513. tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT;
  514. tdm_con |= TDM_CH_START_O34_O35 << ST_CH_PAIR_SOUT2_SFT;
  515. tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT;
  516. break;
  517. case 7:
  518. case 8:
  519. tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
  520. tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT;
  521. tdm_con |= TDM_CH_START_O34_O35 << ST_CH_PAIR_SOUT2_SFT;
  522. tdm_con |= TDM_CH_START_O36_O37 << ST_CH_PAIR_SOUT3_SFT;
  523. break;
  524. default:
  525. tdm_con = 0;
  526. }
  527. } else {
  528. tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
  529. tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT1_SFT;
  530. tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT2_SFT;
  531. tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT;
  532. }
  533. regmap_write(afe->regmap, AFE_TDM_CON2, tdm_con);
  534. regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0,
  535. HDMI_CH_NUM_MASK_SFT,
  536. channels << HDMI_CH_NUM_SFT);
  537. return 0;
  538. }
  539. static int mtk_dai_tdm_set_sysclk(struct snd_soc_dai *dai,
  540. int clk_id, unsigned int freq, int dir)
  541. {
  542. struct mtk_base_afe *afe = dev_get_drvdata(dai->dev);
  543. struct mt8192_afe_private *afe_priv = afe->platform_priv;
  544. struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai->id];
  545. if (!tdm_priv) {
  546. dev_warn(afe->dev, "%s(), tdm_priv == NULL", __func__);
  547. return -EINVAL;
  548. }
  549. if (dir != SND_SOC_CLOCK_OUT) {
  550. dev_warn(afe->dev, "%s(), dir != SND_SOC_CLOCK_OUT", __func__);
  551. return -EINVAL;
  552. }
  553. dev_info(afe->dev, "%s(), freq %d\n", __func__, freq);
  554. return mtk_dai_tdm_cal_mclk(afe, tdm_priv, freq);
  555. }
  556. static int mtk_dai_tdm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
  557. {
  558. struct mtk_base_afe *afe = dev_get_drvdata(dai->dev);
  559. struct mt8192_afe_private *afe_priv = afe->platform_priv;
  560. struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai->id];
  561. if (!tdm_priv) {
  562. dev_warn(afe->dev, "%s(), tdm_priv == NULL", __func__);
  563. return -EINVAL;
  564. }
  565. /* DAI mode*/
  566. switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
  567. case SND_SOC_DAIFMT_I2S:
  568. tdm_priv->tdm_out_mode = TDM_OUT_I2S;
  569. break;
  570. case SND_SOC_DAIFMT_DSP_A:
  571. tdm_priv->tdm_out_mode = TDM_OUT_DSP_A;
  572. break;
  573. case SND_SOC_DAIFMT_DSP_B:
  574. tdm_priv->tdm_out_mode = TDM_OUT_DSP_B;
  575. break;
  576. default:
  577. tdm_priv->tdm_out_mode = TDM_OUT_I2S;
  578. }
  579. /* DAI clock inversion*/
  580. switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
  581. case SND_SOC_DAIFMT_NB_NF:
  582. tdm_priv->bck_invert = TDM_BCK_NON_INV;
  583. tdm_priv->lck_invert = TDM_LCK_NON_INV;
  584. break;
  585. case SND_SOC_DAIFMT_NB_IF:
  586. tdm_priv->bck_invert = TDM_BCK_NON_INV;
  587. tdm_priv->lck_invert = TDM_LCK_INV;
  588. break;
  589. case SND_SOC_DAIFMT_IB_NF:
  590. tdm_priv->bck_invert = TDM_BCK_INV;
  591. tdm_priv->lck_invert = TDM_LCK_NON_INV;
  592. break;
  593. case SND_SOC_DAIFMT_IB_IF:
  594. default:
  595. tdm_priv->bck_invert = TDM_BCK_INV;
  596. tdm_priv->lck_invert = TDM_LCK_INV;
  597. break;
  598. }
  599. return 0;
  600. }
  601. static const struct snd_soc_dai_ops mtk_dai_tdm_ops = {
  602. .hw_params = mtk_dai_tdm_hw_params,
  603. .set_sysclk = mtk_dai_tdm_set_sysclk,
  604. .set_fmt = mtk_dai_tdm_set_fmt,
  605. };
  606. /* dai driver */
  607. #define MTK_TDM_RATES (SNDRV_PCM_RATE_8000_48000 |\
  608. SNDRV_PCM_RATE_88200 |\
  609. SNDRV_PCM_RATE_96000 |\
  610. SNDRV_PCM_RATE_176400 |\
  611. SNDRV_PCM_RATE_192000)
  612. #define MTK_TDM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
  613. SNDRV_PCM_FMTBIT_S24_LE |\
  614. SNDRV_PCM_FMTBIT_S32_LE)
  615. static struct snd_soc_dai_driver mtk_dai_tdm_driver[] = {
  616. {
  617. .name = "TDM",
  618. .id = MT8192_DAI_TDM,
  619. .playback = {
  620. .stream_name = "TDM",
  621. .channels_min = 2,
  622. .channels_max = 8,
  623. .rates = MTK_TDM_RATES,
  624. .formats = MTK_TDM_FORMATS,
  625. },
  626. .ops = &mtk_dai_tdm_ops,
  627. },
  628. };
  629. static struct mtk_afe_tdm_priv *init_tdm_priv_data(struct mtk_base_afe *afe)
  630. {
  631. struct mtk_afe_tdm_priv *tdm_priv;
  632. tdm_priv = devm_kzalloc(afe->dev, sizeof(struct mtk_afe_tdm_priv),
  633. GFP_KERNEL);
  634. if (!tdm_priv)
  635. return NULL;
  636. tdm_priv->mclk_multiple = 512;
  637. tdm_priv->bck_id = MT8192_I2S4_BCK;
  638. tdm_priv->mclk_id = MT8192_I2S4_MCK;
  639. tdm_priv->id = MT8192_DAI_TDM;
  640. return tdm_priv;
  641. }
  642. int mt8192_dai_tdm_register(struct mtk_base_afe *afe)
  643. {
  644. struct mt8192_afe_private *afe_priv = afe->platform_priv;
  645. struct mtk_afe_tdm_priv *tdm_priv;
  646. struct mtk_base_afe_dai *dai;
  647. dev_info(afe->dev, "%s()\n", __func__);
  648. dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
  649. if (!dai)
  650. return -ENOMEM;
  651. list_add(&dai->list, &afe->sub_dais);
  652. dai->dai_drivers = mtk_dai_tdm_driver;
  653. dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_tdm_driver);
  654. dai->dapm_widgets = mtk_dai_tdm_widgets;
  655. dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_tdm_widgets);
  656. dai->dapm_routes = mtk_dai_tdm_routes;
  657. dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_tdm_routes);
  658. tdm_priv = init_tdm_priv_data(afe);
  659. if (!tdm_priv)
  660. return -ENOMEM;
  661. afe_priv->dai_priv[MT8192_DAI_TDM] = tdm_priv;
  662. return 0;
  663. }