ssi.c 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  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. struct snd_soc_dai *dai)
  87. {
  88. struct ssi_priv *ssi = &ssi_cpu_data[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. struct snd_soc_dai *dai)
  98. {
  99. struct ssi_priv *ssi = &ssi_cpu_data[dai->id];
  100. ssi->inuse = 0;
  101. }
  102. static int ssi_trigger(struct snd_pcm_substream *substream, int cmd,
  103. struct snd_soc_dai *dai)
  104. {
  105. struct ssi_priv *ssi = &ssi_cpu_data[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. struct snd_soc_dai *dai)
  121. {
  122. struct ssi_priv *ssi = &ssi_cpu_data[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: %u channels: %u\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. static const struct snd_soc_dai_ops ssi_dai_ops = {
  296. .startup = ssi_startup,
  297. .shutdown = ssi_shutdown,
  298. .trigger = ssi_trigger,
  299. .hw_params = ssi_hw_params,
  300. .set_sysclk = ssi_set_sysclk,
  301. .set_clkdiv = ssi_set_clkdiv,
  302. .set_fmt = ssi_set_fmt,
  303. };
  304. static struct snd_soc_dai_driver sh4_ssi_dai[] = {
  305. {
  306. .name = "ssi-dai.0",
  307. .playback = {
  308. .rates = SSI_RATES,
  309. .formats = SSI_FMTS,
  310. .channels_min = 2,
  311. .channels_max = 8,
  312. },
  313. .capture = {
  314. .rates = SSI_RATES,
  315. .formats = SSI_FMTS,
  316. .channels_min = 2,
  317. .channels_max = 8,
  318. },
  319. .ops = &ssi_dai_ops,
  320. },
  321. #ifdef CONFIG_CPU_SUBTYPE_SH7760
  322. {
  323. .name = "ssi-dai.1",
  324. .playback = {
  325. .rates = SSI_RATES,
  326. .formats = SSI_FMTS,
  327. .channels_min = 2,
  328. .channels_max = 8,
  329. },
  330. .capture = {
  331. .rates = SSI_RATES,
  332. .formats = SSI_FMTS,
  333. .channels_min = 2,
  334. .channels_max = 8,
  335. },
  336. .ops = &ssi_dai_ops,
  337. },
  338. #endif
  339. };
  340. static const struct snd_soc_component_driver sh4_ssi_component = {
  341. .name = "sh4-ssi",
  342. };
  343. static int sh4_soc_dai_probe(struct platform_device *pdev)
  344. {
  345. return devm_snd_soc_register_component(&pdev->dev, &sh4_ssi_component,
  346. sh4_ssi_dai,
  347. ARRAY_SIZE(sh4_ssi_dai));
  348. }
  349. static struct platform_driver sh4_ssi_driver = {
  350. .driver = {
  351. .name = "sh4-ssi-dai",
  352. },
  353. .probe = sh4_soc_dai_probe,
  354. };
  355. module_platform_driver(sh4_ssi_driver);
  356. MODULE_LICENSE("GPL");
  357. MODULE_DESCRIPTION("SuperH onchip SSI (I2S) audio driver");
  358. MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>");