ux500_msp_dai.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893
  1. /*
  2. * Copyright (C) ST-Ericsson SA 2012
  3. *
  4. * Author: Ola Lilja <ola.o.lilja@stericsson.com>,
  5. * Roger Nilsson <roger.xr.nilsson@stericsson.com>
  6. * for ST-Ericsson.
  7. *
  8. * License terms:
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License version 2 as published
  12. * by the Free Software Foundation.
  13. */
  14. #include <linux/module.h>
  15. #include <linux/slab.h>
  16. #include <linux/bitops.h>
  17. #include <linux/platform_device.h>
  18. #include <linux/clk.h>
  19. #include <linux/regulator/consumer.h>
  20. #include <linux/mfd/dbx500-prcmu.h>
  21. #include <linux/platform_data/asoc-ux500-msp.h>
  22. #include <sound/soc.h>
  23. #include <sound/soc-dai.h>
  24. #include "ux500_msp_i2s.h"
  25. #include "ux500_msp_dai.h"
  26. #include "ux500_pcm.h"
  27. static int setup_pcm_multichan(struct snd_soc_dai *dai,
  28. struct ux500_msp_config *msp_config)
  29. {
  30. struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
  31. struct msp_multichannel_config *multi =
  32. &msp_config->multichannel_config;
  33. if (drvdata->slots > 1) {
  34. msp_config->multichannel_configured = 1;
  35. multi->tx_multichannel_enable = true;
  36. multi->rx_multichannel_enable = true;
  37. multi->rx_comparison_enable_mode = MSP_COMPARISON_DISABLED;
  38. multi->tx_channel_0_enable = drvdata->tx_mask;
  39. multi->tx_channel_1_enable = 0;
  40. multi->tx_channel_2_enable = 0;
  41. multi->tx_channel_3_enable = 0;
  42. multi->rx_channel_0_enable = drvdata->rx_mask;
  43. multi->rx_channel_1_enable = 0;
  44. multi->rx_channel_2_enable = 0;
  45. multi->rx_channel_3_enable = 0;
  46. dev_dbg(dai->dev,
  47. "%s: Multichannel enabled. Slots: %d, TX: %u, RX: %u\n",
  48. __func__, drvdata->slots, multi->tx_channel_0_enable,
  49. multi->rx_channel_0_enable);
  50. }
  51. return 0;
  52. }
  53. static int setup_frameper(struct snd_soc_dai *dai, unsigned int rate,
  54. struct msp_protdesc *prot_desc)
  55. {
  56. struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
  57. switch (drvdata->slots) {
  58. case 1:
  59. switch (rate) {
  60. case 8000:
  61. prot_desc->frame_period =
  62. FRAME_PER_SINGLE_SLOT_8_KHZ;
  63. break;
  64. case 16000:
  65. prot_desc->frame_period =
  66. FRAME_PER_SINGLE_SLOT_16_KHZ;
  67. break;
  68. case 44100:
  69. prot_desc->frame_period =
  70. FRAME_PER_SINGLE_SLOT_44_1_KHZ;
  71. break;
  72. case 48000:
  73. prot_desc->frame_period =
  74. FRAME_PER_SINGLE_SLOT_48_KHZ;
  75. break;
  76. default:
  77. dev_err(dai->dev,
  78. "%s: Error: Unsupported sample-rate (freq = %d)!\n",
  79. __func__, rate);
  80. return -EINVAL;
  81. }
  82. break;
  83. case 2:
  84. prot_desc->frame_period = FRAME_PER_2_SLOTS;
  85. break;
  86. case 8:
  87. prot_desc->frame_period = FRAME_PER_8_SLOTS;
  88. break;
  89. case 16:
  90. prot_desc->frame_period = FRAME_PER_16_SLOTS;
  91. break;
  92. default:
  93. dev_err(dai->dev,
  94. "%s: Error: Unsupported slot-count (slots = %d)!\n",
  95. __func__, drvdata->slots);
  96. return -EINVAL;
  97. }
  98. prot_desc->clocks_per_frame =
  99. prot_desc->frame_period+1;
  100. dev_dbg(dai->dev, "%s: Clocks per frame: %u\n",
  101. __func__,
  102. prot_desc->clocks_per_frame);
  103. return 0;
  104. }
  105. static int setup_pcm_framing(struct snd_soc_dai *dai, unsigned int rate,
  106. struct msp_protdesc *prot_desc)
  107. {
  108. struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
  109. u32 frame_length = MSP_FRAME_LEN_1;
  110. prot_desc->frame_width = 0;
  111. switch (drvdata->slots) {
  112. case 1:
  113. frame_length = MSP_FRAME_LEN_1;
  114. break;
  115. case 2:
  116. frame_length = MSP_FRAME_LEN_2;
  117. break;
  118. case 8:
  119. frame_length = MSP_FRAME_LEN_8;
  120. break;
  121. case 16:
  122. frame_length = MSP_FRAME_LEN_16;
  123. break;
  124. default:
  125. dev_err(dai->dev,
  126. "%s: Error: Unsupported slot-count (slots = %d)!\n",
  127. __func__, drvdata->slots);
  128. return -EINVAL;
  129. }
  130. prot_desc->tx_frame_len_1 = frame_length;
  131. prot_desc->rx_frame_len_1 = frame_length;
  132. prot_desc->tx_frame_len_2 = frame_length;
  133. prot_desc->rx_frame_len_2 = frame_length;
  134. prot_desc->tx_elem_len_1 = MSP_ELEM_LEN_16;
  135. prot_desc->rx_elem_len_1 = MSP_ELEM_LEN_16;
  136. prot_desc->tx_elem_len_2 = MSP_ELEM_LEN_16;
  137. prot_desc->rx_elem_len_2 = MSP_ELEM_LEN_16;
  138. return setup_frameper(dai, rate, prot_desc);
  139. }
  140. static int setup_clocking(struct snd_soc_dai *dai,
  141. unsigned int fmt,
  142. struct ux500_msp_config *msp_config)
  143. {
  144. switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
  145. case SND_SOC_DAIFMT_NB_NF:
  146. break;
  147. case SND_SOC_DAIFMT_NB_IF:
  148. msp_config->tx_fsync_pol ^= 1 << TFSPOL_SHIFT;
  149. msp_config->rx_fsync_pol ^= 1 << RFSPOL_SHIFT;
  150. break;
  151. default:
  152. dev_err(dai->dev,
  153. "%s: Error: Unsopported inversion (fmt = 0x%x)!\n",
  154. __func__, fmt);
  155. return -EINVAL;
  156. }
  157. switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
  158. case SND_SOC_DAIFMT_CBM_CFM:
  159. dev_dbg(dai->dev, "%s: Codec is master.\n", __func__);
  160. msp_config->iodelay = 0x20;
  161. msp_config->rx_fsync_sel = 0;
  162. msp_config->tx_fsync_sel = 1 << TFSSEL_SHIFT;
  163. msp_config->tx_clk_sel = 0;
  164. msp_config->rx_clk_sel = 0;
  165. msp_config->srg_clk_sel = 0x2 << SCKSEL_SHIFT;
  166. break;
  167. case SND_SOC_DAIFMT_CBS_CFS:
  168. dev_dbg(dai->dev, "%s: Codec is slave.\n", __func__);
  169. msp_config->tx_clk_sel = TX_CLK_SEL_SRG;
  170. msp_config->tx_fsync_sel = TX_SYNC_SRG_PROG;
  171. msp_config->rx_clk_sel = RX_CLK_SEL_SRG;
  172. msp_config->rx_fsync_sel = RX_SYNC_SRG;
  173. msp_config->srg_clk_sel = 1 << SCKSEL_SHIFT;
  174. break;
  175. default:
  176. dev_err(dai->dev, "%s: Error: Unsopported master (fmt = 0x%x)!\n",
  177. __func__, fmt);
  178. return -EINVAL;
  179. }
  180. return 0;
  181. }
  182. static int setup_pcm_protdesc(struct snd_soc_dai *dai,
  183. unsigned int fmt,
  184. struct msp_protdesc *prot_desc)
  185. {
  186. prot_desc->rx_phase_mode = MSP_SINGLE_PHASE;
  187. prot_desc->tx_phase_mode = MSP_SINGLE_PHASE;
  188. prot_desc->rx_phase2_start_mode = MSP_PHASE2_START_MODE_IMEDIATE;
  189. prot_desc->tx_phase2_start_mode = MSP_PHASE2_START_MODE_IMEDIATE;
  190. prot_desc->rx_byte_order = MSP_BTF_MS_BIT_FIRST;
  191. prot_desc->tx_byte_order = MSP_BTF_MS_BIT_FIRST;
  192. prot_desc->tx_fsync_pol = MSP_FSYNC_POL(MSP_FSYNC_POL_ACT_HI);
  193. prot_desc->rx_fsync_pol = MSP_FSYNC_POL_ACT_HI << RFSPOL_SHIFT;
  194. if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_DSP_A) {
  195. dev_dbg(dai->dev, "%s: DSP_A.\n", __func__);
  196. prot_desc->rx_clk_pol = MSP_RISING_EDGE;
  197. prot_desc->tx_clk_pol = MSP_FALLING_EDGE;
  198. prot_desc->rx_data_delay = MSP_DELAY_1;
  199. prot_desc->tx_data_delay = MSP_DELAY_1;
  200. } else {
  201. dev_dbg(dai->dev, "%s: DSP_B.\n", __func__);
  202. prot_desc->rx_clk_pol = MSP_FALLING_EDGE;
  203. prot_desc->tx_clk_pol = MSP_RISING_EDGE;
  204. prot_desc->rx_data_delay = MSP_DELAY_0;
  205. prot_desc->tx_data_delay = MSP_DELAY_0;
  206. }
  207. prot_desc->rx_half_word_swap = MSP_SWAP_NONE;
  208. prot_desc->tx_half_word_swap = MSP_SWAP_NONE;
  209. prot_desc->compression_mode = MSP_COMPRESS_MODE_LINEAR;
  210. prot_desc->expansion_mode = MSP_EXPAND_MODE_LINEAR;
  211. prot_desc->frame_sync_ignore = MSP_FSYNC_IGNORE;
  212. return 0;
  213. }
  214. static int setup_i2s_protdesc(struct msp_protdesc *prot_desc)
  215. {
  216. prot_desc->rx_phase_mode = MSP_DUAL_PHASE;
  217. prot_desc->tx_phase_mode = MSP_DUAL_PHASE;
  218. prot_desc->rx_phase2_start_mode = MSP_PHASE2_START_MODE_FSYNC;
  219. prot_desc->tx_phase2_start_mode = MSP_PHASE2_START_MODE_FSYNC;
  220. prot_desc->rx_byte_order = MSP_BTF_MS_BIT_FIRST;
  221. prot_desc->tx_byte_order = MSP_BTF_MS_BIT_FIRST;
  222. prot_desc->tx_fsync_pol = MSP_FSYNC_POL(MSP_FSYNC_POL_ACT_LO);
  223. prot_desc->rx_fsync_pol = MSP_FSYNC_POL_ACT_LO << RFSPOL_SHIFT;
  224. prot_desc->rx_frame_len_1 = MSP_FRAME_LEN_1;
  225. prot_desc->rx_frame_len_2 = MSP_FRAME_LEN_1;
  226. prot_desc->tx_frame_len_1 = MSP_FRAME_LEN_1;
  227. prot_desc->tx_frame_len_2 = MSP_FRAME_LEN_1;
  228. prot_desc->rx_elem_len_1 = MSP_ELEM_LEN_16;
  229. prot_desc->rx_elem_len_2 = MSP_ELEM_LEN_16;
  230. prot_desc->tx_elem_len_1 = MSP_ELEM_LEN_16;
  231. prot_desc->tx_elem_len_2 = MSP_ELEM_LEN_16;
  232. prot_desc->rx_clk_pol = MSP_RISING_EDGE;
  233. prot_desc->tx_clk_pol = MSP_FALLING_EDGE;
  234. prot_desc->rx_data_delay = MSP_DELAY_0;
  235. prot_desc->tx_data_delay = MSP_DELAY_0;
  236. prot_desc->tx_half_word_swap = MSP_SWAP_NONE;
  237. prot_desc->rx_half_word_swap = MSP_SWAP_NONE;
  238. prot_desc->compression_mode = MSP_COMPRESS_MODE_LINEAR;
  239. prot_desc->expansion_mode = MSP_EXPAND_MODE_LINEAR;
  240. prot_desc->frame_sync_ignore = MSP_FSYNC_IGNORE;
  241. return 0;
  242. }
  243. static int setup_msp_config(struct snd_pcm_substream *substream,
  244. struct snd_soc_dai *dai,
  245. struct ux500_msp_config *msp_config)
  246. {
  247. struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
  248. struct msp_protdesc *prot_desc = &msp_config->protdesc;
  249. struct snd_pcm_runtime *runtime = substream->runtime;
  250. unsigned int fmt = drvdata->fmt;
  251. int ret;
  252. memset(msp_config, 0, sizeof(*msp_config));
  253. msp_config->f_inputclk = drvdata->master_clk;
  254. msp_config->tx_fifo_config = TX_FIFO_ENABLE;
  255. msp_config->rx_fifo_config = RX_FIFO_ENABLE;
  256. msp_config->def_elem_len = 1;
  257. msp_config->direction = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
  258. MSP_DIR_TX : MSP_DIR_RX;
  259. msp_config->data_size = MSP_DATA_BITS_32;
  260. msp_config->frame_freq = runtime->rate;
  261. dev_dbg(dai->dev, "%s: f_inputclk = %u, frame_freq = %u.\n",
  262. __func__, msp_config->f_inputclk, msp_config->frame_freq);
  263. /* To avoid division by zero */
  264. prot_desc->clocks_per_frame = 1;
  265. dev_dbg(dai->dev, "%s: rate: %u, channels: %d.\n", __func__,
  266. runtime->rate, runtime->channels);
  267. switch (fmt &
  268. (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_MASTER_MASK)) {
  269. case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS:
  270. dev_dbg(dai->dev, "%s: SND_SOC_DAIFMT_I2S.\n", __func__);
  271. msp_config->default_protdesc = 1;
  272. msp_config->protocol = MSP_I2S_PROTOCOL;
  273. break;
  274. case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM:
  275. dev_dbg(dai->dev, "%s: SND_SOC_DAIFMT_I2S.\n", __func__);
  276. msp_config->data_size = MSP_DATA_BITS_16;
  277. msp_config->protocol = MSP_I2S_PROTOCOL;
  278. ret = setup_i2s_protdesc(prot_desc);
  279. if (ret < 0)
  280. return ret;
  281. break;
  282. case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS:
  283. case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM:
  284. case SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBS_CFS:
  285. case SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM:
  286. dev_dbg(dai->dev, "%s: PCM format.\n", __func__);
  287. msp_config->data_size = MSP_DATA_BITS_16;
  288. msp_config->protocol = MSP_PCM_PROTOCOL;
  289. ret = setup_pcm_protdesc(dai, fmt, prot_desc);
  290. if (ret < 0)
  291. return ret;
  292. ret = setup_pcm_multichan(dai, msp_config);
  293. if (ret < 0)
  294. return ret;
  295. ret = setup_pcm_framing(dai, runtime->rate, prot_desc);
  296. if (ret < 0)
  297. return ret;
  298. break;
  299. default:
  300. dev_err(dai->dev, "%s: Error: Unsopported format (%d)!\n",
  301. __func__, fmt);
  302. return -EINVAL;
  303. }
  304. return setup_clocking(dai, fmt, msp_config);
  305. }
  306. static int ux500_msp_dai_startup(struct snd_pcm_substream *substream,
  307. struct snd_soc_dai *dai)
  308. {
  309. int ret = 0;
  310. struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
  311. dev_dbg(dai->dev, "%s: MSP %d (%s): Enter.\n", __func__, dai->id,
  312. snd_pcm_stream_str(substream));
  313. /* Enable regulator */
  314. ret = regulator_enable(drvdata->reg_vape);
  315. if (ret != 0) {
  316. dev_err(drvdata->msp->dev,
  317. "%s: Failed to enable regulator!\n", __func__);
  318. return ret;
  319. }
  320. /* Prepare and enable clocks */
  321. dev_dbg(dai->dev, "%s: Enabling MSP-clocks.\n", __func__);
  322. ret = clk_prepare_enable(drvdata->pclk);
  323. if (ret) {
  324. dev_err(drvdata->msp->dev,
  325. "%s: Failed to prepare/enable pclk!\n", __func__);
  326. goto err_pclk;
  327. }
  328. ret = clk_prepare_enable(drvdata->clk);
  329. if (ret) {
  330. dev_err(drvdata->msp->dev,
  331. "%s: Failed to prepare/enable clk!\n", __func__);
  332. goto err_clk;
  333. }
  334. return ret;
  335. err_clk:
  336. clk_disable_unprepare(drvdata->pclk);
  337. err_pclk:
  338. regulator_disable(drvdata->reg_vape);
  339. return ret;
  340. }
  341. static void ux500_msp_dai_shutdown(struct snd_pcm_substream *substream,
  342. struct snd_soc_dai *dai)
  343. {
  344. int ret;
  345. struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
  346. bool is_playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
  347. dev_dbg(dai->dev, "%s: MSP %d (%s): Enter.\n", __func__, dai->id,
  348. snd_pcm_stream_str(substream));
  349. if (drvdata->vape_opp_constraint == 1) {
  350. prcmu_qos_update_requirement(PRCMU_QOS_APE_OPP,
  351. "ux500_msp_i2s", 50);
  352. drvdata->vape_opp_constraint = 0;
  353. }
  354. if (ux500_msp_i2s_close(drvdata->msp,
  355. is_playback ? MSP_DIR_TX : MSP_DIR_RX)) {
  356. dev_err(dai->dev,
  357. "%s: Error: MSP %d (%s): Unable to close i2s.\n",
  358. __func__, dai->id, snd_pcm_stream_str(substream));
  359. }
  360. /* Disable and unprepare clocks */
  361. clk_disable_unprepare(drvdata->clk);
  362. clk_disable_unprepare(drvdata->pclk);
  363. /* Disable regulator */
  364. ret = regulator_disable(drvdata->reg_vape);
  365. if (ret < 0)
  366. dev_err(dai->dev,
  367. "%s: ERROR: Failed to disable regulator (%d)!\n",
  368. __func__, ret);
  369. }
  370. static int ux500_msp_dai_prepare(struct snd_pcm_substream *substream,
  371. struct snd_soc_dai *dai)
  372. {
  373. int ret = 0;
  374. struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
  375. struct snd_pcm_runtime *runtime = substream->runtime;
  376. struct ux500_msp_config msp_config;
  377. dev_dbg(dai->dev, "%s: MSP %d (%s): Enter (rate = %d).\n", __func__,
  378. dai->id, snd_pcm_stream_str(substream), runtime->rate);
  379. setup_msp_config(substream, dai, &msp_config);
  380. ret = ux500_msp_i2s_open(drvdata->msp, &msp_config);
  381. if (ret < 0) {
  382. dev_err(dai->dev, "%s: Error: msp_setup failed (ret = %d)!\n",
  383. __func__, ret);
  384. return ret;
  385. }
  386. /* Set OPP-level */
  387. if ((drvdata->fmt & SND_SOC_DAIFMT_MASTER_MASK) &&
  388. (drvdata->msp->f_bitclk > 19200000)) {
  389. /* If the bit-clock is higher than 19.2MHz, Vape should be
  390. * run in 100% OPP. Only when bit-clock is used (MSP master) */
  391. prcmu_qos_update_requirement(PRCMU_QOS_APE_OPP,
  392. "ux500-msp-i2s", 100);
  393. drvdata->vape_opp_constraint = 1;
  394. } else {
  395. prcmu_qos_update_requirement(PRCMU_QOS_APE_OPP,
  396. "ux500-msp-i2s", 50);
  397. drvdata->vape_opp_constraint = 0;
  398. }
  399. return ret;
  400. }
  401. static int ux500_msp_dai_hw_params(struct snd_pcm_substream *substream,
  402. struct snd_pcm_hw_params *params,
  403. struct snd_soc_dai *dai)
  404. {
  405. unsigned int mask, slots_active;
  406. struct snd_pcm_runtime *runtime = substream->runtime;
  407. struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
  408. dev_dbg(dai->dev, "%s: MSP %d (%s): Enter.\n",
  409. __func__, dai->id, snd_pcm_stream_str(substream));
  410. switch (drvdata->fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
  411. case SND_SOC_DAIFMT_I2S:
  412. snd_pcm_hw_constraint_minmax(runtime,
  413. SNDRV_PCM_HW_PARAM_CHANNELS,
  414. 1, 2);
  415. break;
  416. case SND_SOC_DAIFMT_DSP_B:
  417. case SND_SOC_DAIFMT_DSP_A:
  418. mask = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
  419. drvdata->tx_mask :
  420. drvdata->rx_mask;
  421. slots_active = hweight32(mask);
  422. dev_dbg(dai->dev, "TDM-slots active: %d", slots_active);
  423. snd_pcm_hw_constraint_minmax(runtime,
  424. SNDRV_PCM_HW_PARAM_CHANNELS,
  425. slots_active, slots_active);
  426. break;
  427. default:
  428. dev_err(dai->dev,
  429. "%s: Error: Unsupported protocol (fmt = 0x%x)!\n",
  430. __func__, drvdata->fmt);
  431. return -EINVAL;
  432. }
  433. return 0;
  434. }
  435. static int ux500_msp_dai_set_dai_fmt(struct snd_soc_dai *dai,
  436. unsigned int fmt)
  437. {
  438. struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
  439. dev_dbg(dai->dev, "%s: MSP %d: Enter.\n", __func__, dai->id);
  440. switch (fmt & (SND_SOC_DAIFMT_FORMAT_MASK |
  441. SND_SOC_DAIFMT_MASTER_MASK)) {
  442. case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS:
  443. case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM:
  444. case SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBS_CFS:
  445. case SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM:
  446. case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS:
  447. case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM:
  448. break;
  449. default:
  450. dev_err(dai->dev,
  451. "%s: Error: Unsupported protocol/master (fmt = 0x%x)!\n",
  452. __func__, drvdata->fmt);
  453. return -EINVAL;
  454. }
  455. switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
  456. case SND_SOC_DAIFMT_NB_NF:
  457. case SND_SOC_DAIFMT_NB_IF:
  458. case SND_SOC_DAIFMT_IB_IF:
  459. break;
  460. default:
  461. dev_err(dai->dev,
  462. "%s: Error: Unsupported inversion (fmt = 0x%x)!\n",
  463. __func__, drvdata->fmt);
  464. return -EINVAL;
  465. }
  466. drvdata->fmt = fmt;
  467. return 0;
  468. }
  469. static int ux500_msp_dai_set_tdm_slot(struct snd_soc_dai *dai,
  470. unsigned int tx_mask,
  471. unsigned int rx_mask,
  472. int slots, int slot_width)
  473. {
  474. struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
  475. unsigned int cap;
  476. switch (slots) {
  477. case 1:
  478. cap = 0x01;
  479. break;
  480. case 2:
  481. cap = 0x03;
  482. break;
  483. case 8:
  484. cap = 0xFF;
  485. break;
  486. case 16:
  487. cap = 0xFFFF;
  488. break;
  489. default:
  490. dev_err(dai->dev, "%s: Error: Unsupported slot-count (%d)!\n",
  491. __func__, slots);
  492. return -EINVAL;
  493. }
  494. drvdata->slots = slots;
  495. if (!(slot_width == 16)) {
  496. dev_err(dai->dev, "%s: Error: Unsupported slot-width (%d)!\n",
  497. __func__, slot_width);
  498. return -EINVAL;
  499. }
  500. drvdata->slot_width = slot_width;
  501. drvdata->tx_mask = tx_mask & cap;
  502. drvdata->rx_mask = rx_mask & cap;
  503. return 0;
  504. }
  505. static int ux500_msp_dai_set_dai_sysclk(struct snd_soc_dai *dai,
  506. int clk_id, unsigned int freq, int dir)
  507. {
  508. struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
  509. dev_dbg(dai->dev, "%s: MSP %d: Enter. clk-id: %d, freq: %u.\n",
  510. __func__, dai->id, clk_id, freq);
  511. switch (clk_id) {
  512. case UX500_MSP_MASTER_CLOCK:
  513. drvdata->master_clk = freq;
  514. break;
  515. default:
  516. dev_err(dai->dev, "%s: MSP %d: Invalid clk-id (%d)!\n",
  517. __func__, dai->id, clk_id);
  518. return -EINVAL;
  519. }
  520. return 0;
  521. }
  522. static int ux500_msp_dai_trigger(struct snd_pcm_substream *substream,
  523. int cmd, struct snd_soc_dai *dai)
  524. {
  525. int ret = 0;
  526. struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
  527. dev_dbg(dai->dev, "%s: MSP %d (%s): Enter (msp->id = %d, cmd = %d).\n",
  528. __func__, dai->id, snd_pcm_stream_str(substream),
  529. (int)drvdata->msp->id, cmd);
  530. ret = ux500_msp_i2s_trigger(drvdata->msp, cmd, substream->stream);
  531. return ret;
  532. }
  533. static int ux500_msp_dai_probe(struct snd_soc_dai *dai)
  534. {
  535. struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
  536. dai->playback_dma_data = &drvdata->msp->playback_dma_data;
  537. dai->capture_dma_data = &drvdata->msp->capture_dma_data;
  538. drvdata->msp->playback_dma_data.data_size = drvdata->slot_width;
  539. drvdata->msp->capture_dma_data.data_size = drvdata->slot_width;
  540. return 0;
  541. }
  542. static struct snd_soc_dai_ops ux500_msp_dai_ops[] = {
  543. {
  544. .set_sysclk = ux500_msp_dai_set_dai_sysclk,
  545. .set_fmt = ux500_msp_dai_set_dai_fmt,
  546. .set_tdm_slot = ux500_msp_dai_set_tdm_slot,
  547. .startup = ux500_msp_dai_startup,
  548. .shutdown = ux500_msp_dai_shutdown,
  549. .prepare = ux500_msp_dai_prepare,
  550. .trigger = ux500_msp_dai_trigger,
  551. .hw_params = ux500_msp_dai_hw_params,
  552. }
  553. };
  554. static struct snd_soc_dai_driver ux500_msp_dai_drv[UX500_NBR_OF_DAI] = {
  555. {
  556. .name = "ux500-msp-i2s.0",
  557. .probe = ux500_msp_dai_probe,
  558. .id = 0,
  559. .suspend = NULL,
  560. .resume = NULL,
  561. .playback = {
  562. .channels_min = UX500_MSP_MIN_CHANNELS,
  563. .channels_max = UX500_MSP_MAX_CHANNELS,
  564. .rates = UX500_I2S_RATES,
  565. .formats = UX500_I2S_FORMATS,
  566. },
  567. .capture = {
  568. .channels_min = UX500_MSP_MIN_CHANNELS,
  569. .channels_max = UX500_MSP_MAX_CHANNELS,
  570. .rates = UX500_I2S_RATES,
  571. .formats = UX500_I2S_FORMATS,
  572. },
  573. .ops = ux500_msp_dai_ops,
  574. },
  575. {
  576. .name = "ux500-msp-i2s.1",
  577. .probe = ux500_msp_dai_probe,
  578. .id = 1,
  579. .suspend = NULL,
  580. .resume = NULL,
  581. .playback = {
  582. .channels_min = UX500_MSP_MIN_CHANNELS,
  583. .channels_max = UX500_MSP_MAX_CHANNELS,
  584. .rates = UX500_I2S_RATES,
  585. .formats = UX500_I2S_FORMATS,
  586. },
  587. .capture = {
  588. .channels_min = UX500_MSP_MIN_CHANNELS,
  589. .channels_max = UX500_MSP_MAX_CHANNELS,
  590. .rates = UX500_I2S_RATES,
  591. .formats = UX500_I2S_FORMATS,
  592. },
  593. .ops = ux500_msp_dai_ops,
  594. },
  595. {
  596. .name = "ux500-msp-i2s.2",
  597. .id = 2,
  598. .probe = ux500_msp_dai_probe,
  599. .suspend = NULL,
  600. .resume = NULL,
  601. .playback = {
  602. .channels_min = UX500_MSP_MIN_CHANNELS,
  603. .channels_max = UX500_MSP_MAX_CHANNELS,
  604. .rates = UX500_I2S_RATES,
  605. .formats = UX500_I2S_FORMATS,
  606. },
  607. .capture = {
  608. .channels_min = UX500_MSP_MIN_CHANNELS,
  609. .channels_max = UX500_MSP_MAX_CHANNELS,
  610. .rates = UX500_I2S_RATES,
  611. .formats = UX500_I2S_FORMATS,
  612. },
  613. .ops = ux500_msp_dai_ops,
  614. },
  615. {
  616. .name = "ux500-msp-i2s.3",
  617. .probe = ux500_msp_dai_probe,
  618. .id = 3,
  619. .suspend = NULL,
  620. .resume = NULL,
  621. .playback = {
  622. .channels_min = UX500_MSP_MIN_CHANNELS,
  623. .channels_max = UX500_MSP_MAX_CHANNELS,
  624. .rates = UX500_I2S_RATES,
  625. .formats = UX500_I2S_FORMATS,
  626. },
  627. .capture = {
  628. .channels_min = UX500_MSP_MIN_CHANNELS,
  629. .channels_max = UX500_MSP_MAX_CHANNELS,
  630. .rates = UX500_I2S_RATES,
  631. .formats = UX500_I2S_FORMATS,
  632. },
  633. .ops = ux500_msp_dai_ops,
  634. },
  635. };
  636. static const struct snd_soc_component_driver ux500_msp_component = {
  637. .name = "ux500-msp",
  638. };
  639. static int ux500_msp_drv_probe(struct platform_device *pdev)
  640. {
  641. struct ux500_msp_i2s_drvdata *drvdata;
  642. int ret = 0;
  643. dev_dbg(&pdev->dev, "%s: Enter (pdev->name = %s).\n", __func__,
  644. pdev->name);
  645. drvdata = devm_kzalloc(&pdev->dev,
  646. sizeof(struct ux500_msp_i2s_drvdata),
  647. GFP_KERNEL);
  648. if (!drvdata)
  649. return -ENOMEM;
  650. drvdata->fmt = 0;
  651. drvdata->slots = 1;
  652. drvdata->tx_mask = 0x01;
  653. drvdata->rx_mask = 0x01;
  654. drvdata->slot_width = 16;
  655. drvdata->master_clk = MSP_INPUT_FREQ_APB;
  656. drvdata->reg_vape = devm_regulator_get(&pdev->dev, "v-ape");
  657. if (IS_ERR(drvdata->reg_vape)) {
  658. ret = (int)PTR_ERR(drvdata->reg_vape);
  659. dev_err(&pdev->dev,
  660. "%s: ERROR: Failed to get Vape supply (%d)!\n",
  661. __func__, ret);
  662. return ret;
  663. }
  664. prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP, (char *)pdev->name, 50);
  665. drvdata->pclk = clk_get(&pdev->dev, "apb_pclk");
  666. if (IS_ERR(drvdata->pclk)) {
  667. ret = (int)PTR_ERR(drvdata->pclk);
  668. dev_err(&pdev->dev, "%s: ERROR: clk_get of pclk failed (%d)!\n",
  669. __func__, ret);
  670. goto err_pclk;
  671. }
  672. drvdata->clk = clk_get(&pdev->dev, NULL);
  673. if (IS_ERR(drvdata->clk)) {
  674. ret = (int)PTR_ERR(drvdata->clk);
  675. dev_err(&pdev->dev, "%s: ERROR: clk_get failed (%d)!\n",
  676. __func__, ret);
  677. goto err_clk;
  678. }
  679. ret = ux500_msp_i2s_init_msp(pdev, &drvdata->msp,
  680. pdev->dev.platform_data);
  681. if (!drvdata->msp) {
  682. dev_err(&pdev->dev,
  683. "%s: ERROR: Failed to init MSP-struct (%d)!",
  684. __func__, ret);
  685. goto err_init_msp;
  686. }
  687. dev_set_drvdata(&pdev->dev, drvdata);
  688. ret = snd_soc_register_component(&pdev->dev, &ux500_msp_component,
  689. &ux500_msp_dai_drv[drvdata->msp->id], 1);
  690. if (ret < 0) {
  691. dev_err(&pdev->dev, "Error: %s: Failed to register MSP%d!\n",
  692. __func__, drvdata->msp->id);
  693. goto err_init_msp;
  694. }
  695. ret = ux500_pcm_register_platform(pdev);
  696. if (ret < 0) {
  697. dev_err(&pdev->dev,
  698. "Error: %s: Failed to register PCM platform device!\n",
  699. __func__);
  700. goto err_reg_plat;
  701. }
  702. return 0;
  703. err_reg_plat:
  704. snd_soc_unregister_component(&pdev->dev);
  705. err_init_msp:
  706. clk_put(drvdata->clk);
  707. err_clk:
  708. clk_put(drvdata->pclk);
  709. err_pclk:
  710. devm_regulator_put(drvdata->reg_vape);
  711. return ret;
  712. }
  713. static int ux500_msp_drv_remove(struct platform_device *pdev)
  714. {
  715. struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(&pdev->dev);
  716. ux500_pcm_unregister_platform(pdev);
  717. snd_soc_unregister_component(&pdev->dev);
  718. devm_regulator_put(drvdata->reg_vape);
  719. prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP, "ux500_msp_i2s");
  720. clk_put(drvdata->clk);
  721. clk_put(drvdata->pclk);
  722. ux500_msp_i2s_cleanup_msp(pdev, drvdata->msp);
  723. return 0;
  724. }
  725. static const struct of_device_id ux500_msp_i2s_match[] = {
  726. { .compatible = "stericsson,ux500-msp-i2s", },
  727. {},
  728. };
  729. static struct platform_driver msp_i2s_driver = {
  730. .driver = {
  731. .name = "ux500-msp-i2s",
  732. .owner = THIS_MODULE,
  733. .of_match_table = ux500_msp_i2s_match,
  734. },
  735. .probe = ux500_msp_drv_probe,
  736. .remove = ux500_msp_drv_remove,
  737. };
  738. module_platform_driver(msp_i2s_driver);
  739. MODULE_LICENSE("GPL v2");