ssi.c 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. /*
  2. * Serial Sound Interface (I2S) support for SH7760/SH7780
  3. *
  4. * Copyright (c) 2007 Manuel Lauss <mano@roarinelk.homelinux.net>
  5. *
  6. * licensed under the terms outlined in the file COPYING at the root
  7. * of the linux kernel sources.
  8. *
  9. * dont forget to set IPSEL/OMSEL register bits (in your board code) to
  10. * enable SSI output pins!
  11. */
  12. /*
  13. * LIMITATIONS:
  14. * The SSI unit has only one physical data line, so full duplex is
  15. * impossible. This can be remedied on the SH7760 by using the
  16. * other SSI unit for recording; however the SH7780 has only 1 SSI
  17. * unit, and its pins are shared with the AC97 unit, among others.
  18. *
  19. * FEATURES:
  20. * The SSI features "compressed mode": in this mode it continuously
  21. * streams PCM data over the I2S lines and uses LRCK as a handshake
  22. * signal. Can be used to send compressed data (AC3/DTS) to a DSP.
  23. * The number of bits sent over the wire in a frame can be adjusted
  24. * and can be independent from the actual sample bit depth. This is
  25. * useful to support TDM mode codecs like the AD1939 which have a
  26. * fixed TDM slot size, regardless of sample resolution.
  27. */
  28. #include <linux/init.h>
  29. #include <linux/module.h>
  30. #include <linux/platform_device.h>
  31. #include <sound/core.h>
  32. #include <sound/pcm.h>
  33. #include <sound/initval.h>
  34. #include <sound/soc.h>
  35. #include <asm/io.h>
  36. #define SSICR 0x00
  37. #define SSISR 0x04
  38. #define CR_DMAEN (1 << 28)
  39. #define CR_CHNL_SHIFT 22
  40. #define CR_CHNL_MASK (3 << CR_CHNL_SHIFT)
  41. #define CR_DWL_SHIFT 19
  42. #define CR_DWL_MASK (7 << CR_DWL_SHIFT)
  43. #define CR_SWL_SHIFT 16
  44. #define CR_SWL_MASK (7 << CR_SWL_SHIFT)
  45. #define CR_SCK_MASTER (1 << 15) /* bitclock master bit */
  46. #define CR_SWS_MASTER (1 << 14) /* wordselect master bit */
  47. #define CR_SCKP (1 << 13) /* I2Sclock polarity */
  48. #define CR_SWSP (1 << 12) /* LRCK polarity */
  49. #define CR_SPDP (1 << 11)
  50. #define CR_SDTA (1 << 10) /* i2s alignment (msb/lsb) */
  51. #define CR_PDTA (1 << 9) /* fifo data alignment */
  52. #define CR_DEL (1 << 8) /* delay data by 1 i2sclk */
  53. #define CR_BREN (1 << 7) /* clock gating in burst mode */
  54. #define CR_CKDIV_SHIFT 4
  55. #define CR_CKDIV_MASK (7 << CR_CKDIV_SHIFT) /* bitclock divider */
  56. #define CR_MUTE (1 << 3) /* SSI mute */
  57. #define CR_CPEN (1 << 2) /* compressed mode */
  58. #define CR_TRMD (1 << 1) /* transmit/receive select */
  59. #define CR_EN (1 << 0) /* enable SSI */
  60. #define SSIREG(reg) (*(unsigned long *)(ssi->mmio + (reg)))
  61. struct ssi_priv {
  62. unsigned long mmio;
  63. unsigned long sysclk;
  64. int inuse;
  65. } ssi_cpu_data[] = {
  66. #if defined(CONFIG_CPU_SUBTYPE_SH7760)
  67. {
  68. .mmio = 0xFE680000,
  69. },
  70. {
  71. .mmio = 0xFE690000,
  72. },
  73. #elif defined(CONFIG_CPU_SUBTYPE_SH7780)
  74. {
  75. .mmio = 0xFFE70000,
  76. },
  77. #else
  78. #error "Unsupported SuperH SoC"
  79. #endif
  80. };
  81. /*
  82. * track usage of the SSI; it is simplex-only so prevent attempts of
  83. * concurrent playback + capture. FIXME: any locking required?
  84. */
  85. static int ssi_startup(struct snd_pcm_substream *substream)
  86. {
  87. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  88. struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id];
  89. if (ssi->inuse) {
  90. pr_debug("ssi: already in use!\n");
  91. return -EBUSY;
  92. } else
  93. ssi->inuse = 1;
  94. return 0;
  95. }
  96. static void ssi_shutdown(struct snd_pcm_substream *substream)
  97. {
  98. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  99. struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id];
  100. ssi->inuse = 0;
  101. }
  102. static int ssi_trigger(struct snd_pcm_substream *substream, int cmd)
  103. {
  104. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  105. struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id];
  106. switch (cmd) {
  107. case SNDRV_PCM_TRIGGER_START:
  108. SSIREG(SSICR) |= CR_DMAEN | CR_EN;
  109. break;
  110. case SNDRV_PCM_TRIGGER_STOP:
  111. SSIREG(SSICR) &= ~(CR_DMAEN | CR_EN);
  112. break;
  113. default:
  114. return -EINVAL;
  115. }
  116. return 0;
  117. }
  118. static int ssi_hw_params(struct snd_pcm_substream *substream,
  119. struct snd_pcm_hw_params *params)
  120. {
  121. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  122. struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id];
  123. unsigned long ssicr = SSIREG(SSICR);
  124. unsigned int bits, channels, swl, recv, i;
  125. channels = params_channels(params);
  126. bits = params->msbits;
  127. recv = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? 0 : 1;
  128. pr_debug("ssi_hw_params() enter\nssicr was %08lx\n", ssicr);
  129. pr_debug("bits: %d channels: %d\n", bits, channels);
  130. ssicr &= ~(CR_TRMD | CR_CHNL_MASK | CR_DWL_MASK | CR_PDTA |
  131. CR_SWL_MASK);
  132. /* direction (send/receive) */
  133. if (!recv)
  134. ssicr |= CR_TRMD; /* transmit */
  135. /* channels */
  136. if ((channels < 2) || (channels > 8) || (channels & 1)) {
  137. pr_debug("ssi: invalid number of channels\n");
  138. return -EINVAL;
  139. }
  140. ssicr |= ((channels >> 1) - 1) << CR_CHNL_SHIFT;
  141. /* DATA WORD LENGTH (DWL): databits in audio sample */
  142. i = 0;
  143. switch (bits) {
  144. case 32: ++i;
  145. case 24: ++i;
  146. case 22: ++i;
  147. case 20: ++i;
  148. case 18: ++i;
  149. case 16: ++i;
  150. ssicr |= i << CR_DWL_SHIFT;
  151. case 8: break;
  152. default:
  153. pr_debug("ssi: invalid sample width\n");
  154. return -EINVAL;
  155. }
  156. /*
  157. * SYSTEM WORD LENGTH: size in bits of half a frame over the I2S
  158. * wires. This is usually bits_per_sample x channels/2; i.e. in
  159. * Stereo mode the SWL equals DWL. SWL can be bigger than the
  160. * product of (channels_per_slot x samplebits), e.g. for codecs
  161. * like the AD1939 which only accept 32bit wide TDM slots. For
  162. * "standard" I2S operation we set SWL = chans / 2 * DWL here.
  163. * Waiting for ASoC to get TDM support ;-)
  164. */
  165. if ((bits > 16) && (bits <= 24)) {
  166. bits = 24; /* these are padded by the SSI */
  167. /*ssicr |= CR_PDTA;*/ /* cpu/data endianness ? */
  168. }
  169. i = 0;
  170. swl = (bits * channels) / 2;
  171. switch (swl) {
  172. case 256: ++i;
  173. case 128: ++i;
  174. case 64: ++i;
  175. case 48: ++i;
  176. case 32: ++i;
  177. case 16: ++i;
  178. ssicr |= i << CR_SWL_SHIFT;
  179. case 8: break;
  180. default:
  181. pr_debug("ssi: invalid system word length computed\n");
  182. return -EINVAL;
  183. }
  184. SSIREG(SSICR) = ssicr;
  185. pr_debug("ssi_hw_params() leave\nssicr is now %08lx\n", ssicr);
  186. return 0;
  187. }
  188. static int ssi_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id,
  189. unsigned int freq, int dir)
  190. {
  191. struct ssi_priv *ssi = &ssi_cpu_data[cpu_dai->id];
  192. ssi->sysclk = freq;
  193. return 0;
  194. }
  195. /*
  196. * This divider is used to generate the SSI_SCK (I2S bitclock) from the
  197. * clock at the HAC_BIT_CLK ("oversampling clock") pin.
  198. */
  199. static int ssi_set_clkdiv(struct snd_soc_dai *dai, int did, int div)
  200. {
  201. struct ssi_priv *ssi = &ssi_cpu_data[dai->id];
  202. unsigned long ssicr;
  203. int i;
  204. i = 0;
  205. ssicr = SSIREG(SSICR) & ~CR_CKDIV_MASK;
  206. switch (div) {
  207. case 16: ++i;
  208. case 8: ++i;
  209. case 4: ++i;
  210. case 2: ++i;
  211. SSIREG(SSICR) = ssicr | (i << CR_CKDIV_SHIFT);
  212. case 1: break;
  213. default:
  214. pr_debug("ssi: invalid sck divider %d\n", div);
  215. return -EINVAL;
  216. }
  217. return 0;
  218. }
  219. static int ssi_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
  220. {
  221. struct ssi_priv *ssi = &ssi_cpu_data[dai->id];
  222. unsigned long ssicr = SSIREG(SSICR);
  223. pr_debug("ssi_set_fmt()\nssicr was 0x%08lx\n", ssicr);
  224. ssicr &= ~(CR_DEL | CR_PDTA | CR_BREN | CR_SWSP | CR_SCKP |
  225. CR_SWS_MASTER | CR_SCK_MASTER);
  226. switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
  227. case SND_SOC_DAIFMT_I2S:
  228. break;
  229. case SND_SOC_DAIFMT_RIGHT_J:
  230. ssicr |= CR_DEL | CR_PDTA;
  231. break;
  232. case SND_SOC_DAIFMT_LEFT_J:
  233. ssicr |= CR_DEL;
  234. break;
  235. default:
  236. pr_debug("ssi: unsupported format\n");
  237. return -EINVAL;
  238. }
  239. switch (fmt & SND_SOC_DAIFMT_CLOCK_MASK) {
  240. case SND_SOC_DAIFMT_CONT:
  241. break;
  242. case SND_SOC_DAIFMT_GATED:
  243. ssicr |= CR_BREN;
  244. break;
  245. }
  246. switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
  247. case SND_SOC_DAIFMT_NB_NF:
  248. ssicr |= CR_SCKP; /* sample data at low clkedge */
  249. break;
  250. case SND_SOC_DAIFMT_NB_IF:
  251. ssicr |= CR_SCKP | CR_SWSP;
  252. break;
  253. case SND_SOC_DAIFMT_IB_NF:
  254. break;
  255. case SND_SOC_DAIFMT_IB_IF:
  256. ssicr |= CR_SWSP; /* word select starts low */
  257. break;
  258. default:
  259. pr_debug("ssi: invalid inversion\n");
  260. return -EINVAL;
  261. }
  262. switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
  263. case SND_SOC_DAIFMT_CBM_CFM:
  264. break;
  265. case SND_SOC_DAIFMT_CBS_CFM:
  266. ssicr |= CR_SCK_MASTER;
  267. break;
  268. case SND_SOC_DAIFMT_CBM_CFS:
  269. ssicr |= CR_SWS_MASTER;
  270. break;
  271. case SND_SOC_DAIFMT_CBS_CFS:
  272. ssicr |= CR_SWS_MASTER | CR_SCK_MASTER;
  273. break;
  274. default:
  275. pr_debug("ssi: invalid master/slave configuration\n");
  276. return -EINVAL;
  277. }
  278. SSIREG(SSICR) = ssicr;
  279. pr_debug("ssi_set_fmt() leave\nssicr is now 0x%08lx\n", ssicr);
  280. return 0;
  281. }
  282. /* the SSI depends on an external clocksource (at HAC_BIT_CLK) even in
  283. * Master mode, so really this is board specific; the SSI can do any
  284. * rate with the right bitclk and divider settings.
  285. */
  286. #define SSI_RATES \
  287. SNDRV_PCM_RATE_8000_192000
  288. /* the SSI can do 8-32 bit samples, with 8 possible channels */
  289. #define SSI_FMTS \
  290. (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 | \
  291. SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE | \
  292. SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_U20_3LE | \
  293. SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_U24_3LE | \
  294. SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_U32_LE)
  295. struct snd_soc_dai sh4_ssi_dai[] = {
  296. {
  297. .name = "SSI0",
  298. .id = 0,
  299. .type = SND_SOC_DAI_I2S,
  300. .playback = {
  301. .rates = SSI_RATES,
  302. .formats = SSI_FMTS,
  303. .channels_min = 2,
  304. .channels_max = 8,
  305. },
  306. .capture = {
  307. .rates = SSI_RATES,
  308. .formats = SSI_FMTS,
  309. .channels_min = 2,
  310. .channels_max = 8,
  311. },
  312. .ops = {
  313. .startup = ssi_startup,
  314. .shutdown = ssi_shutdown,
  315. .trigger = ssi_trigger,
  316. .hw_params = ssi_hw_params,
  317. },
  318. .dai_ops = {
  319. .set_sysclk = ssi_set_sysclk,
  320. .set_clkdiv = ssi_set_clkdiv,
  321. .set_fmt = ssi_set_fmt,
  322. },
  323. },
  324. #ifdef CONFIG_CPU_SUBTYPE_SH7760
  325. {
  326. .name = "SSI1",
  327. .id = 1,
  328. .type = SND_SOC_DAI_I2S,
  329. .playback = {
  330. .rates = SSI_RATES,
  331. .formats = SSI_FMTS,
  332. .channels_min = 2,
  333. .channels_max = 8,
  334. },
  335. .capture = {
  336. .rates = SSI_RATES,
  337. .formats = SSI_FMTS,
  338. .channels_min = 2,
  339. .channels_max = 8,
  340. },
  341. .ops = {
  342. .startup = ssi_startup,
  343. .shutdown = ssi_shutdown,
  344. .trigger = ssi_trigger,
  345. .hw_params = ssi_hw_params,
  346. },
  347. .dai_ops = {
  348. .set_sysclk = ssi_set_sysclk,
  349. .set_clkdiv = ssi_set_clkdiv,
  350. .set_fmt = ssi_set_fmt,
  351. },
  352. },
  353. #endif
  354. };
  355. EXPORT_SYMBOL_GPL(sh4_ssi_dai);
  356. MODULE_LICENSE("GPL");
  357. MODULE_DESCRIPTION("SuperH onchip SSI (I2S) audio driver");
  358. MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>");