ssi.c 10 KB

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