ux500_msp_dai.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843
  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/board-mop500-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. 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. /* Enable clock */
  321. dev_dbg(dai->dev, "%s: Enabling MSP-clock.\n", __func__);
  322. clk_enable(drvdata->clk);
  323. return 0;
  324. }
  325. static void ux500_msp_dai_shutdown(struct snd_pcm_substream *substream,
  326. struct snd_soc_dai *dai)
  327. {
  328. int ret;
  329. struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
  330. bool is_playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
  331. dev_dbg(dai->dev, "%s: MSP %d (%s): Enter.\n", __func__, dai->id,
  332. snd_pcm_stream_str(substream));
  333. if (drvdata->vape_opp_constraint == 1) {
  334. prcmu_qos_update_requirement(PRCMU_QOS_APE_OPP,
  335. "ux500_msp_i2s", 50);
  336. drvdata->vape_opp_constraint = 0;
  337. }
  338. if (ux500_msp_i2s_close(drvdata->msp,
  339. is_playback ? MSP_DIR_TX : MSP_DIR_RX)) {
  340. dev_err(dai->dev,
  341. "%s: Error: MSP %d (%s): Unable to close i2s.\n",
  342. __func__, dai->id, snd_pcm_stream_str(substream));
  343. }
  344. /* Disable clock */
  345. clk_disable(drvdata->clk);
  346. /* Disable regulator */
  347. ret = regulator_disable(drvdata->reg_vape);
  348. if (ret < 0)
  349. dev_err(dai->dev,
  350. "%s: ERROR: Failed to disable regulator (%d)!\n",
  351. __func__, ret);
  352. }
  353. static int ux500_msp_dai_prepare(struct snd_pcm_substream *substream,
  354. struct snd_soc_dai *dai)
  355. {
  356. int ret = 0;
  357. struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
  358. struct snd_pcm_runtime *runtime = substream->runtime;
  359. struct ux500_msp_config msp_config;
  360. dev_dbg(dai->dev, "%s: MSP %d (%s): Enter (rate = %d).\n", __func__,
  361. dai->id, snd_pcm_stream_str(substream), runtime->rate);
  362. setup_msp_config(substream, dai, &msp_config);
  363. ret = ux500_msp_i2s_open(drvdata->msp, &msp_config);
  364. if (ret < 0) {
  365. dev_err(dai->dev, "%s: Error: msp_setup failed (ret = %d)!\n",
  366. __func__, ret);
  367. return ret;
  368. }
  369. /* Set OPP-level */
  370. if ((drvdata->fmt & SND_SOC_DAIFMT_MASTER_MASK) &&
  371. (drvdata->msp->f_bitclk > 19200000)) {
  372. /* If the bit-clock is higher than 19.2MHz, Vape should be
  373. * run in 100% OPP. Only when bit-clock is used (MSP master) */
  374. prcmu_qos_update_requirement(PRCMU_QOS_APE_OPP,
  375. "ux500-msp-i2s", 100);
  376. drvdata->vape_opp_constraint = 1;
  377. } else {
  378. prcmu_qos_update_requirement(PRCMU_QOS_APE_OPP,
  379. "ux500-msp-i2s", 50);
  380. drvdata->vape_opp_constraint = 0;
  381. }
  382. return ret;
  383. }
  384. static int ux500_msp_dai_hw_params(struct snd_pcm_substream *substream,
  385. struct snd_pcm_hw_params *params,
  386. struct snd_soc_dai *dai)
  387. {
  388. unsigned int mask, slots_active;
  389. struct snd_pcm_runtime *runtime = substream->runtime;
  390. struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
  391. dev_dbg(dai->dev, "%s: MSP %d (%s): Enter.\n",
  392. __func__, dai->id, snd_pcm_stream_str(substream));
  393. switch (drvdata->fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
  394. case SND_SOC_DAIFMT_I2S:
  395. snd_pcm_hw_constraint_minmax(runtime,
  396. SNDRV_PCM_HW_PARAM_CHANNELS,
  397. 1, 2);
  398. break;
  399. case SND_SOC_DAIFMT_DSP_B:
  400. case SND_SOC_DAIFMT_DSP_A:
  401. mask = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
  402. drvdata->tx_mask :
  403. drvdata->rx_mask;
  404. slots_active = hweight32(mask);
  405. dev_dbg(dai->dev, "TDM-slots active: %d", slots_active);
  406. snd_pcm_hw_constraint_minmax(runtime,
  407. SNDRV_PCM_HW_PARAM_CHANNELS,
  408. slots_active, slots_active);
  409. break;
  410. default:
  411. dev_err(dai->dev,
  412. "%s: Error: Unsupported protocol (fmt = 0x%x)!\n",
  413. __func__, drvdata->fmt);
  414. return -EINVAL;
  415. }
  416. return 0;
  417. }
  418. static int ux500_msp_dai_set_dai_fmt(struct snd_soc_dai *dai,
  419. unsigned int fmt)
  420. {
  421. struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
  422. dev_dbg(dai->dev, "%s: MSP %d: Enter.\n", __func__, dai->id);
  423. switch (fmt & (SND_SOC_DAIFMT_FORMAT_MASK |
  424. SND_SOC_DAIFMT_MASTER_MASK)) {
  425. case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS:
  426. case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM:
  427. case SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBS_CFS:
  428. case SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM:
  429. case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS:
  430. case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM:
  431. break;
  432. default:
  433. dev_err(dai->dev,
  434. "%s: Error: Unsupported protocol/master (fmt = 0x%x)!\n",
  435. __func__, drvdata->fmt);
  436. return -EINVAL;
  437. }
  438. switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
  439. case SND_SOC_DAIFMT_NB_NF:
  440. case SND_SOC_DAIFMT_NB_IF:
  441. case SND_SOC_DAIFMT_IB_IF:
  442. break;
  443. default:
  444. dev_err(dai->dev,
  445. "%s: Error: Unsupported inversion (fmt = 0x%x)!\n",
  446. __func__, drvdata->fmt);
  447. return -EINVAL;
  448. }
  449. drvdata->fmt = fmt;
  450. return 0;
  451. }
  452. static int ux500_msp_dai_set_tdm_slot(struct snd_soc_dai *dai,
  453. unsigned int tx_mask,
  454. unsigned int rx_mask,
  455. int slots, int slot_width)
  456. {
  457. struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
  458. unsigned int cap;
  459. switch (slots) {
  460. case 1:
  461. cap = 0x01;
  462. break;
  463. case 2:
  464. cap = 0x03;
  465. break;
  466. case 8:
  467. cap = 0xFF;
  468. break;
  469. case 16:
  470. cap = 0xFFFF;
  471. break;
  472. default:
  473. dev_err(dai->dev, "%s: Error: Unsupported slot-count (%d)!\n",
  474. __func__, slots);
  475. return -EINVAL;
  476. }
  477. drvdata->slots = slots;
  478. if (!(slot_width == 16)) {
  479. dev_err(dai->dev, "%s: Error: Unsupported slot-width (%d)!\n",
  480. __func__, slot_width);
  481. return -EINVAL;
  482. }
  483. drvdata->slot_width = slot_width;
  484. drvdata->tx_mask = tx_mask & cap;
  485. drvdata->rx_mask = rx_mask & cap;
  486. return 0;
  487. }
  488. static int ux500_msp_dai_set_dai_sysclk(struct snd_soc_dai *dai,
  489. int clk_id, unsigned int freq, int dir)
  490. {
  491. struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
  492. dev_dbg(dai->dev, "%s: MSP %d: Enter. clk-id: %d, freq: %u.\n",
  493. __func__, dai->id, clk_id, freq);
  494. switch (clk_id) {
  495. case UX500_MSP_MASTER_CLOCK:
  496. drvdata->master_clk = freq;
  497. break;
  498. default:
  499. dev_err(dai->dev, "%s: MSP %d: Invalid clk-id (%d)!\n",
  500. __func__, dai->id, clk_id);
  501. return -EINVAL;
  502. }
  503. return 0;
  504. }
  505. static int ux500_msp_dai_trigger(struct snd_pcm_substream *substream,
  506. int cmd, struct snd_soc_dai *dai)
  507. {
  508. int ret = 0;
  509. struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
  510. dev_dbg(dai->dev, "%s: MSP %d (%s): Enter (msp->id = %d, cmd = %d).\n",
  511. __func__, dai->id, snd_pcm_stream_str(substream),
  512. (int)drvdata->msp->id, cmd);
  513. ret = ux500_msp_i2s_trigger(drvdata->msp, cmd, substream->stream);
  514. return ret;
  515. }
  516. static int ux500_msp_dai_probe(struct snd_soc_dai *dai)
  517. {
  518. struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
  519. drvdata->playback_dma_data.dma_cfg = drvdata->msp->dma_cfg_tx;
  520. drvdata->capture_dma_data.dma_cfg = drvdata->msp->dma_cfg_rx;
  521. dai->playback_dma_data = &drvdata->playback_dma_data;
  522. dai->capture_dma_data = &drvdata->capture_dma_data;
  523. drvdata->playback_dma_data.data_size = drvdata->slot_width;
  524. drvdata->capture_dma_data.data_size = drvdata->slot_width;
  525. return 0;
  526. }
  527. static struct snd_soc_dai_ops ux500_msp_dai_ops[] = {
  528. {
  529. .set_sysclk = ux500_msp_dai_set_dai_sysclk,
  530. .set_fmt = ux500_msp_dai_set_dai_fmt,
  531. .set_tdm_slot = ux500_msp_dai_set_tdm_slot,
  532. .startup = ux500_msp_dai_startup,
  533. .shutdown = ux500_msp_dai_shutdown,
  534. .prepare = ux500_msp_dai_prepare,
  535. .trigger = ux500_msp_dai_trigger,
  536. .hw_params = ux500_msp_dai_hw_params,
  537. }
  538. };
  539. static struct snd_soc_dai_driver ux500_msp_dai_drv[UX500_NBR_OF_DAI] = {
  540. {
  541. .name = "ux500-msp-i2s.0",
  542. .probe = ux500_msp_dai_probe,
  543. .id = 0,
  544. .suspend = NULL,
  545. .resume = NULL,
  546. .playback = {
  547. .channels_min = UX500_MSP_MIN_CHANNELS,
  548. .channels_max = UX500_MSP_MAX_CHANNELS,
  549. .rates = UX500_I2S_RATES,
  550. .formats = UX500_I2S_FORMATS,
  551. },
  552. .capture = {
  553. .channels_min = UX500_MSP_MIN_CHANNELS,
  554. .channels_max = UX500_MSP_MAX_CHANNELS,
  555. .rates = UX500_I2S_RATES,
  556. .formats = UX500_I2S_FORMATS,
  557. },
  558. .ops = ux500_msp_dai_ops,
  559. },
  560. {
  561. .name = "ux500-msp-i2s.1",
  562. .probe = ux500_msp_dai_probe,
  563. .id = 1,
  564. .suspend = NULL,
  565. .resume = NULL,
  566. .playback = {
  567. .channels_min = UX500_MSP_MIN_CHANNELS,
  568. .channels_max = UX500_MSP_MAX_CHANNELS,
  569. .rates = UX500_I2S_RATES,
  570. .formats = UX500_I2S_FORMATS,
  571. },
  572. .capture = {
  573. .channels_min = UX500_MSP_MIN_CHANNELS,
  574. .channels_max = UX500_MSP_MAX_CHANNELS,
  575. .rates = UX500_I2S_RATES,
  576. .formats = UX500_I2S_FORMATS,
  577. },
  578. .ops = ux500_msp_dai_ops,
  579. },
  580. {
  581. .name = "ux500-msp-i2s.2",
  582. .id = 2,
  583. .probe = ux500_msp_dai_probe,
  584. .suspend = NULL,
  585. .resume = NULL,
  586. .playback = {
  587. .channels_min = UX500_MSP_MIN_CHANNELS,
  588. .channels_max = UX500_MSP_MAX_CHANNELS,
  589. .rates = UX500_I2S_RATES,
  590. .formats = UX500_I2S_FORMATS,
  591. },
  592. .capture = {
  593. .channels_min = UX500_MSP_MIN_CHANNELS,
  594. .channels_max = UX500_MSP_MAX_CHANNELS,
  595. .rates = UX500_I2S_RATES,
  596. .formats = UX500_I2S_FORMATS,
  597. },
  598. .ops = ux500_msp_dai_ops,
  599. },
  600. {
  601. .name = "ux500-msp-i2s.3",
  602. .probe = ux500_msp_dai_probe,
  603. .id = 3,
  604. .suspend = NULL,
  605. .resume = NULL,
  606. .playback = {
  607. .channels_min = UX500_MSP_MIN_CHANNELS,
  608. .channels_max = UX500_MSP_MAX_CHANNELS,
  609. .rates = UX500_I2S_RATES,
  610. .formats = UX500_I2S_FORMATS,
  611. },
  612. .capture = {
  613. .channels_min = UX500_MSP_MIN_CHANNELS,
  614. .channels_max = UX500_MSP_MAX_CHANNELS,
  615. .rates = UX500_I2S_RATES,
  616. .formats = UX500_I2S_FORMATS,
  617. },
  618. .ops = ux500_msp_dai_ops,
  619. },
  620. };
  621. static int __devinit ux500_msp_drv_probe(struct platform_device *pdev)
  622. {
  623. struct ux500_msp_i2s_drvdata *drvdata;
  624. int ret = 0;
  625. dev_dbg(&pdev->dev, "%s: Enter (pdev->name = %s).\n", __func__,
  626. pdev->name);
  627. drvdata = devm_kzalloc(&pdev->dev,
  628. sizeof(struct ux500_msp_i2s_drvdata),
  629. GFP_KERNEL);
  630. drvdata->fmt = 0;
  631. drvdata->slots = 1;
  632. drvdata->tx_mask = 0x01;
  633. drvdata->rx_mask = 0x01;
  634. drvdata->slot_width = 16;
  635. drvdata->master_clk = MSP_INPUT_FREQ_APB;
  636. drvdata->reg_vape = devm_regulator_get(&pdev->dev, "v-ape");
  637. if (IS_ERR(drvdata->reg_vape)) {
  638. ret = (int)PTR_ERR(drvdata->reg_vape);
  639. dev_err(&pdev->dev,
  640. "%s: ERROR: Failed to get Vape supply (%d)!\n",
  641. __func__, ret);
  642. return ret;
  643. }
  644. prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP, (char *)pdev->name, 50);
  645. drvdata->clk = clk_get(&pdev->dev, NULL);
  646. if (IS_ERR(drvdata->clk)) {
  647. ret = (int)PTR_ERR(drvdata->clk);
  648. dev_err(&pdev->dev, "%s: ERROR: clk_get failed (%d)!\n",
  649. __func__, ret);
  650. goto err_clk;
  651. }
  652. ret = ux500_msp_i2s_init_msp(pdev, &drvdata->msp,
  653. pdev->dev.platform_data);
  654. if (!drvdata->msp) {
  655. dev_err(&pdev->dev,
  656. "%s: ERROR: Failed to init MSP-struct (%d)!",
  657. __func__, ret);
  658. goto err_init_msp;
  659. }
  660. dev_set_drvdata(&pdev->dev, drvdata);
  661. ret = snd_soc_register_dai(&pdev->dev,
  662. &ux500_msp_dai_drv[drvdata->msp->id]);
  663. if (ret < 0) {
  664. dev_err(&pdev->dev, "Error: %s: Failed to register MSP%d!\n",
  665. __func__, drvdata->msp->id);
  666. goto err_init_msp;
  667. }
  668. return 0;
  669. err_init_msp:
  670. clk_put(drvdata->clk);
  671. err_clk:
  672. devm_regulator_put(drvdata->reg_vape);
  673. return ret;
  674. }
  675. static int __devexit ux500_msp_drv_remove(struct platform_device *pdev)
  676. {
  677. struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(&pdev->dev);
  678. snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(ux500_msp_dai_drv));
  679. devm_regulator_put(drvdata->reg_vape);
  680. prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP, "ux500_msp_i2s");
  681. clk_put(drvdata->clk);
  682. ux500_msp_i2s_cleanup_msp(pdev, drvdata->msp);
  683. return 0;
  684. }
  685. static struct platform_driver msp_i2s_driver = {
  686. .driver = {
  687. .name = "ux500-msp-i2s",
  688. .owner = THIS_MODULE,
  689. },
  690. .probe = ux500_msp_drv_probe,
  691. .remove = ux500_msp_drv_remove,
  692. };
  693. module_platform_driver(msp_i2s_driver);
  694. MODULE_LICENSE("GPLv2");