pxa2xx-i2s.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. /*
  2. * pxa2xx-i2s.c -- ALSA Soc Audio Layer
  3. *
  4. * Copyright 2005 Wolfson Microelectronics PLC.
  5. * Author: Liam Girdwood
  6. * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
  7. *
  8. * This program is free software; you can redistribute it and/or modify it
  9. * under the terms of the GNU General Public License as published by the
  10. * Free Software Foundation; either version 2 of the License, or (at your
  11. * option) any later version.
  12. *
  13. * Revision history
  14. * 12th Aug 2005 Initial version.
  15. */
  16. #include <linux/init.h>
  17. #include <linux/module.h>
  18. #include <linux/device.h>
  19. #include <linux/delay.h>
  20. #include <sound/driver.h>
  21. #include <sound/core.h>
  22. #include <sound/pcm.h>
  23. #include <sound/initval.h>
  24. #include <sound/soc.h>
  25. #include <asm/hardware.h>
  26. #include <asm/arch/pxa-regs.h>
  27. #include <asm/arch/audio.h>
  28. #include "pxa2xx-pcm.h"
  29. /* used to disable sysclk if external crystal is used */
  30. static int extclk;
  31. module_param(extclk, int, 0);
  32. MODULE_PARM_DESC(extclk, "set to 1 to disable pxa2xx i2s sysclk");
  33. struct pxa_i2s_port {
  34. u32 sadiv;
  35. u32 sacr0;
  36. u32 sacr1;
  37. u32 saimr;
  38. int master;
  39. };
  40. static struct pxa_i2s_port pxa_i2s;
  41. #define PXA_I2S_DAIFMT \
  42. (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF)
  43. #define PXA_I2S_DIR \
  44. (SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
  45. #define PXA_I2S_RATES \
  46. (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \
  47. SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
  48. SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
  49. /* priv is divider */
  50. static struct snd_soc_dai_mode pxa2xx_i2s_modes[] = {
  51. /* pxa2xx I2S frame and clock master modes */
  52. {PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBS_CFS, SND_SOC_DAITDM_LRDW(0,0),
  53. SNDRV_PCM_FMTBIT_S16_LE, SNDRV_PCM_RATE_8000, PXA_I2S_DIR,
  54. SND_SOC_DAI_BFS_DIV, 256, SND_SOC_FSBD(4), 0x48},
  55. {PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBS_CFS, SND_SOC_DAITDM_LRDW(0,0),
  56. SNDRV_PCM_FMTBIT_S16_LE, SNDRV_PCM_RATE_11025, PXA_I2S_DIR,
  57. SND_SOC_DAI_BFS_DIV, 256, SND_SOC_FSBD(4), 0x34},
  58. {PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBS_CFS, SND_SOC_DAITDM_LRDW(0,0),
  59. SNDRV_PCM_FMTBIT_S16_LE, SNDRV_PCM_RATE_16000, PXA_I2S_DIR,
  60. SND_SOC_DAI_BFS_DIV, 256, SND_SOC_FSBD(4), 0x24},
  61. {PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBS_CFS, SND_SOC_DAITDM_LRDW(0,0),
  62. SNDRV_PCM_FMTBIT_S16_LE, SNDRV_PCM_RATE_22050, PXA_I2S_DIR,
  63. SND_SOC_DAI_BFS_DIV, 256, SND_SOC_FSBD(4), 0x1a},
  64. {PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBS_CFS, SND_SOC_DAITDM_LRDW(0,0),
  65. SNDRV_PCM_FMTBIT_S16_LE, SNDRV_PCM_RATE_44100, PXA_I2S_DIR,
  66. SND_SOC_DAI_BFS_DIV, 256, SND_SOC_FSBD(4), 0xd},
  67. {PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBS_CFS, SND_SOC_DAITDM_LRDW(0,0),
  68. SNDRV_PCM_FMTBIT_S16_LE, SNDRV_PCM_RATE_48000, PXA_I2S_DIR,
  69. SND_SOC_DAI_BFS_DIV, 256, SND_SOC_FSBD(4), 0xc},
  70. /* pxa2xx I2S frame master and clock slave mode */
  71. {PXA_I2S_DAIFMT | SND_SOC_DAIFMT_CBM_CFS, SND_SOC_DAITDM_LRDW(0,0),
  72. SNDRV_PCM_FMTBIT_S16_LE, PXA_I2S_RATES, PXA_I2S_DIR, 0,
  73. SND_SOC_FS_ALL, SND_SOC_FSB(64), 0x48},
  74. };
  75. static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_out = {
  76. .name = "I2S PCM Stereo out",
  77. .dev_addr = __PREG(SADR),
  78. .drcmr = &DRCMRTXSADR,
  79. .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
  80. DCMD_BURST32 | DCMD_WIDTH4,
  81. };
  82. static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_in = {
  83. .name = "I2S PCM Stereo in",
  84. .dev_addr = __PREG(SADR),
  85. .drcmr = &DRCMRRXSADR,
  86. .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
  87. DCMD_BURST32 | DCMD_WIDTH4,
  88. };
  89. static struct pxa2xx_gpio gpio_bus[] = {
  90. { /* I2S SoC Slave */
  91. .rx = GPIO29_SDATA_IN_I2S_MD,
  92. .tx = GPIO30_SDATA_OUT_I2S_MD,
  93. .clk = GPIO28_BITCLK_IN_I2S_MD,
  94. .frm = GPIO31_SYNC_I2S_MD,
  95. },
  96. { /* I2S SoC Master */
  97. #ifdef CONFIG_PXA27x
  98. .sys = GPIO113_I2S_SYSCLK_MD,
  99. #else
  100. .sys = GPIO32_SYSCLK_I2S_MD,
  101. #endif
  102. .rx = GPIO29_SDATA_IN_I2S_MD,
  103. .tx = GPIO30_SDATA_OUT_I2S_MD,
  104. .clk = GPIO28_BITCLK_OUT_I2S_MD,
  105. .frm = GPIO31_SYNC_I2S_MD,
  106. },
  107. };
  108. static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream)
  109. {
  110. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  111. if (!rtd->cpu_dai->active) {
  112. SACR0 |= SACR0_RST;
  113. SACR0 = 0;
  114. }
  115. return 0;
  116. }
  117. /* wait for I2S controller to be ready */
  118. static int pxa_i2s_wait(void)
  119. {
  120. int i;
  121. /* flush the Rx FIFO */
  122. for(i = 0; i < 16; i++)
  123. SADR;
  124. return 0;
  125. }
  126. static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,
  127. struct snd_pcm_hw_params *params)
  128. {
  129. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  130. pxa_i2s.master = 0;
  131. if (rtd->cpu_dai->dai_runtime.fmt & SND_SOC_DAIFMT_CBS_CFS)
  132. pxa_i2s.master = 1;
  133. if (pxa_i2s.master && !extclk)
  134. pxa_gpio_mode(gpio_bus[pxa_i2s.master].sys);
  135. pxa_gpio_mode(gpio_bus[pxa_i2s.master].rx);
  136. pxa_gpio_mode(gpio_bus[pxa_i2s.master].tx);
  137. pxa_gpio_mode(gpio_bus[pxa_i2s.master].frm);
  138. pxa_gpio_mode(gpio_bus[pxa_i2s.master].clk);
  139. pxa_set_cken(CKEN8_I2S, 1);
  140. pxa_i2s_wait();
  141. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  142. rtd->cpu_dai->dma_data = &pxa2xx_i2s_pcm_stereo_out;
  143. else
  144. rtd->cpu_dai->dma_data = &pxa2xx_i2s_pcm_stereo_in;
  145. /* is port used by another stream */
  146. if (!(SACR0 & SACR0_ENB)) {
  147. SACR0 = 0;
  148. SACR1 = 0;
  149. if (pxa_i2s.master)
  150. SACR0 |= SACR0_BCKD;
  151. SACR0 |= SACR0_RFTH(14) | SACR0_TFTH(1);
  152. if (rtd->cpu_dai->dai_runtime.fmt & SND_SOC_DAIFMT_LEFT_J)
  153. SACR1 |= SACR1_AMSL;
  154. }
  155. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  156. SAIMR |= SAIMR_TFS;
  157. else
  158. SAIMR |= SAIMR_RFS;
  159. SADIV = rtd->cpu_dai->dai_runtime.priv;
  160. return 0;
  161. }
  162. static int pxa2xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
  163. {
  164. int ret = 0;
  165. switch (cmd) {
  166. case SNDRV_PCM_TRIGGER_START:
  167. SACR0 |= SACR0_ENB;
  168. break;
  169. case SNDRV_PCM_TRIGGER_RESUME:
  170. case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  171. case SNDRV_PCM_TRIGGER_STOP:
  172. case SNDRV_PCM_TRIGGER_SUSPEND:
  173. case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  174. break;
  175. default:
  176. ret = -EINVAL;
  177. }
  178. return ret;
  179. }
  180. static void pxa2xx_i2s_shutdown(struct snd_pcm_substream *substream)
  181. {
  182. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  183. SACR1 |= SACR1_DRPL;
  184. SAIMR &= ~SAIMR_TFS;
  185. } else {
  186. SACR1 |= SACR1_DREC;
  187. SAIMR &= ~SAIMR_RFS;
  188. }
  189. if (SACR1 & (SACR1_DREC | SACR1_DRPL)) {
  190. SACR0 &= ~SACR0_ENB;
  191. pxa_i2s_wait();
  192. pxa_set_cken(CKEN8_I2S, 0);
  193. }
  194. }
  195. #ifdef CONFIG_PM
  196. static int pxa2xx_i2s_suspend(struct platform_device *dev,
  197. struct snd_soc_cpu_dai *dai)
  198. {
  199. if (!dai->active)
  200. return 0;
  201. /* store registers */
  202. pxa_i2s.sacr0 = SACR0;
  203. pxa_i2s.sacr1 = SACR1;
  204. pxa_i2s.saimr = SAIMR;
  205. pxa_i2s.sadiv = SADIV;
  206. /* deactivate link */
  207. SACR0 &= ~SACR0_ENB;
  208. pxa_i2s_wait();
  209. return 0;
  210. }
  211. static int pxa2xx_i2s_resume(struct platform_device *pdev,
  212. struct snd_soc_cpu_dai *dai)
  213. {
  214. if (!dai->active)
  215. return 0;
  216. pxa_i2s_wait();
  217. SACR0 = pxa_i2s.sacr0 &= ~SACR0_ENB;
  218. SACR1 = pxa_i2s.sacr1;
  219. SAIMR = pxa_i2s.saimr;
  220. SADIV = pxa_i2s.sadiv;
  221. SACR0 |= SACR0_ENB;
  222. return 0;
  223. }
  224. #else
  225. #define pxa2xx_i2s_suspend NULL
  226. #define pxa2xx_i2s_resume NULL
  227. #endif
  228. /* pxa2xx I2S sysclock is always 256 FS */
  229. static unsigned int pxa_i2s_config_sysclk(struct snd_soc_cpu_dai *iface,
  230. struct snd_soc_clock_info *info, unsigned int clk)
  231. {
  232. return info->rate << 8;
  233. }
  234. struct snd_soc_cpu_dai pxa_i2s_dai = {
  235. .name = "pxa2xx-i2s",
  236. .id = 0,
  237. .type = SND_SOC_DAI_I2S,
  238. .suspend = pxa2xx_i2s_suspend,
  239. .resume = pxa2xx_i2s_resume,
  240. .config_sysclk = pxa_i2s_config_sysclk,
  241. .playback = {
  242. .channels_min = 2,
  243. .channels_max = 2,},
  244. .capture = {
  245. .channels_min = 2,
  246. .channels_max = 2,},
  247. .ops = {
  248. .startup = pxa2xx_i2s_startup,
  249. .shutdown = pxa2xx_i2s_shutdown,
  250. .trigger = pxa2xx_i2s_trigger,
  251. .hw_params = pxa2xx_i2s_hw_params,},
  252. .caps = {
  253. .num_modes = ARRAY_SIZE(pxa2xx_i2s_modes),
  254. .mode = pxa2xx_i2s_modes,},
  255. };
  256. EXPORT_SYMBOL_GPL(pxa_i2s_dai);
  257. /* Module information */
  258. MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
  259. MODULE_DESCRIPTION("pxa2xx I2S SoC Interface");
  260. MODULE_LICENSE("GPL");