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