cygnus-pcm.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862
  1. /*
  2. * Copyright (C) 2014-2015 Broadcom Corporation
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License as
  6. * published by the Free Software Foundation version 2.
  7. *
  8. * This program is distributed "as is" WITHOUT ANY WARRANTY of any
  9. * kind, whether express or implied; without even the implied warranty
  10. * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. */
  13. #include <linux/debugfs.h>
  14. #include <linux/dma-mapping.h>
  15. #include <linux/init.h>
  16. #include <linux/io.h>
  17. #include <linux/module.h>
  18. #include <linux/slab.h>
  19. #include <linux/timer.h>
  20. #include <sound/core.h>
  21. #include <sound/pcm.h>
  22. #include <sound/pcm_params.h>
  23. #include <sound/soc.h>
  24. #include <sound/soc-dai.h>
  25. #include "cygnus-ssp.h"
  26. /* Register offset needed for ASoC PCM module */
  27. #define INTH_R5F_STATUS_OFFSET 0x040
  28. #define INTH_R5F_CLEAR_OFFSET 0x048
  29. #define INTH_R5F_MASK_SET_OFFSET 0x050
  30. #define INTH_R5F_MASK_CLEAR_OFFSET 0x054
  31. #define BF_REARM_FREE_MARK_OFFSET 0x344
  32. #define BF_REARM_FULL_MARK_OFFSET 0x348
  33. /* Ring Buffer Ctrl Regs --- Start */
  34. /* AUD_FMM_BF_CTRL_SOURCECH_RINGBUF_X_RDADDR_REG_BASE */
  35. #define SRC_RBUF_0_RDADDR_OFFSET 0x500
  36. #define SRC_RBUF_1_RDADDR_OFFSET 0x518
  37. #define SRC_RBUF_2_RDADDR_OFFSET 0x530
  38. #define SRC_RBUF_3_RDADDR_OFFSET 0x548
  39. #define SRC_RBUF_4_RDADDR_OFFSET 0x560
  40. #define SRC_RBUF_5_RDADDR_OFFSET 0x578
  41. #define SRC_RBUF_6_RDADDR_OFFSET 0x590
  42. /* AUD_FMM_BF_CTRL_SOURCECH_RINGBUF_X_WRADDR_REG_BASE */
  43. #define SRC_RBUF_0_WRADDR_OFFSET 0x504
  44. #define SRC_RBUF_1_WRADDR_OFFSET 0x51c
  45. #define SRC_RBUF_2_WRADDR_OFFSET 0x534
  46. #define SRC_RBUF_3_WRADDR_OFFSET 0x54c
  47. #define SRC_RBUF_4_WRADDR_OFFSET 0x564
  48. #define SRC_RBUF_5_WRADDR_OFFSET 0x57c
  49. #define SRC_RBUF_6_WRADDR_OFFSET 0x594
  50. /* AUD_FMM_BF_CTRL_SOURCECH_RINGBUF_X_BASEADDR_REG_BASE */
  51. #define SRC_RBUF_0_BASEADDR_OFFSET 0x508
  52. #define SRC_RBUF_1_BASEADDR_OFFSET 0x520
  53. #define SRC_RBUF_2_BASEADDR_OFFSET 0x538
  54. #define SRC_RBUF_3_BASEADDR_OFFSET 0x550
  55. #define SRC_RBUF_4_BASEADDR_OFFSET 0x568
  56. #define SRC_RBUF_5_BASEADDR_OFFSET 0x580
  57. #define SRC_RBUF_6_BASEADDR_OFFSET 0x598
  58. /* AUD_FMM_BF_CTRL_SOURCECH_RINGBUF_X_ENDADDR_REG_BASE */
  59. #define SRC_RBUF_0_ENDADDR_OFFSET 0x50c
  60. #define SRC_RBUF_1_ENDADDR_OFFSET 0x524
  61. #define SRC_RBUF_2_ENDADDR_OFFSET 0x53c
  62. #define SRC_RBUF_3_ENDADDR_OFFSET 0x554
  63. #define SRC_RBUF_4_ENDADDR_OFFSET 0x56c
  64. #define SRC_RBUF_5_ENDADDR_OFFSET 0x584
  65. #define SRC_RBUF_6_ENDADDR_OFFSET 0x59c
  66. /* AUD_FMM_BF_CTRL_SOURCECH_RINGBUF_X_FREE_MARK_REG_BASE */
  67. #define SRC_RBUF_0_FREE_MARK_OFFSET 0x510
  68. #define SRC_RBUF_1_FREE_MARK_OFFSET 0x528
  69. #define SRC_RBUF_2_FREE_MARK_OFFSET 0x540
  70. #define SRC_RBUF_3_FREE_MARK_OFFSET 0x558
  71. #define SRC_RBUF_4_FREE_MARK_OFFSET 0x570
  72. #define SRC_RBUF_5_FREE_MARK_OFFSET 0x588
  73. #define SRC_RBUF_6_FREE_MARK_OFFSET 0x5a0
  74. /* AUD_FMM_BF_CTRL_DESTCH_RINGBUF_X_RDADDR_REG_BASE */
  75. #define DST_RBUF_0_RDADDR_OFFSET 0x5c0
  76. #define DST_RBUF_1_RDADDR_OFFSET 0x5d8
  77. #define DST_RBUF_2_RDADDR_OFFSET 0x5f0
  78. #define DST_RBUF_3_RDADDR_OFFSET 0x608
  79. #define DST_RBUF_4_RDADDR_OFFSET 0x620
  80. #define DST_RBUF_5_RDADDR_OFFSET 0x638
  81. /* AUD_FMM_BF_CTRL_DESTCH_RINGBUF_X_WRADDR_REG_BASE */
  82. #define DST_RBUF_0_WRADDR_OFFSET 0x5c4
  83. #define DST_RBUF_1_WRADDR_OFFSET 0x5dc
  84. #define DST_RBUF_2_WRADDR_OFFSET 0x5f4
  85. #define DST_RBUF_3_WRADDR_OFFSET 0x60c
  86. #define DST_RBUF_4_WRADDR_OFFSET 0x624
  87. #define DST_RBUF_5_WRADDR_OFFSET 0x63c
  88. /* AUD_FMM_BF_CTRL_DESTCH_RINGBUF_X_BASEADDR_REG_BASE */
  89. #define DST_RBUF_0_BASEADDR_OFFSET 0x5c8
  90. #define DST_RBUF_1_BASEADDR_OFFSET 0x5e0
  91. #define DST_RBUF_2_BASEADDR_OFFSET 0x5f8
  92. #define DST_RBUF_3_BASEADDR_OFFSET 0x610
  93. #define DST_RBUF_4_BASEADDR_OFFSET 0x628
  94. #define DST_RBUF_5_BASEADDR_OFFSET 0x640
  95. /* AUD_FMM_BF_CTRL_DESTCH_RINGBUF_X_ENDADDR_REG_BASE */
  96. #define DST_RBUF_0_ENDADDR_OFFSET 0x5cc
  97. #define DST_RBUF_1_ENDADDR_OFFSET 0x5e4
  98. #define DST_RBUF_2_ENDADDR_OFFSET 0x5fc
  99. #define DST_RBUF_3_ENDADDR_OFFSET 0x614
  100. #define DST_RBUF_4_ENDADDR_OFFSET 0x62c
  101. #define DST_RBUF_5_ENDADDR_OFFSET 0x644
  102. /* AUD_FMM_BF_CTRL_DESTCH_RINGBUF_X_FULL_MARK_REG_BASE */
  103. #define DST_RBUF_0_FULL_MARK_OFFSET 0x5d0
  104. #define DST_RBUF_1_FULL_MARK_OFFSET 0x5e8
  105. #define DST_RBUF_2_FULL_MARK_OFFSET 0x600
  106. #define DST_RBUF_3_FULL_MARK_OFFSET 0x618
  107. #define DST_RBUF_4_FULL_MARK_OFFSET 0x630
  108. #define DST_RBUF_5_FULL_MARK_OFFSET 0x648
  109. /* Ring Buffer Ctrl Regs --- End */
  110. /* Error Status Regs --- Start */
  111. /* AUD_FMM_BF_ESR_ESRX_STATUS_REG_BASE */
  112. #define ESR0_STATUS_OFFSET 0x900
  113. #define ESR1_STATUS_OFFSET 0x918
  114. #define ESR2_STATUS_OFFSET 0x930
  115. #define ESR3_STATUS_OFFSET 0x948
  116. #define ESR4_STATUS_OFFSET 0x960
  117. /* AUD_FMM_BF_ESR_ESRX_STATUS_CLEAR_REG_BASE */
  118. #define ESR0_STATUS_CLR_OFFSET 0x908
  119. #define ESR1_STATUS_CLR_OFFSET 0x920
  120. #define ESR2_STATUS_CLR_OFFSET 0x938
  121. #define ESR3_STATUS_CLR_OFFSET 0x950
  122. #define ESR4_STATUS_CLR_OFFSET 0x968
  123. /* AUD_FMM_BF_ESR_ESRX_MASK_REG_BASE */
  124. #define ESR0_MASK_STATUS_OFFSET 0x90c
  125. #define ESR1_MASK_STATUS_OFFSET 0x924
  126. #define ESR2_MASK_STATUS_OFFSET 0x93c
  127. #define ESR3_MASK_STATUS_OFFSET 0x954
  128. #define ESR4_MASK_STATUS_OFFSET 0x96c
  129. /* AUD_FMM_BF_ESR_ESRX_MASK_SET_REG_BASE */
  130. #define ESR0_MASK_SET_OFFSET 0x910
  131. #define ESR1_MASK_SET_OFFSET 0x928
  132. #define ESR2_MASK_SET_OFFSET 0x940
  133. #define ESR3_MASK_SET_OFFSET 0x958
  134. #define ESR4_MASK_SET_OFFSET 0x970
  135. /* AUD_FMM_BF_ESR_ESRX_MASK_CLEAR_REG_BASE */
  136. #define ESR0_MASK_CLR_OFFSET 0x914
  137. #define ESR1_MASK_CLR_OFFSET 0x92c
  138. #define ESR2_MASK_CLR_OFFSET 0x944
  139. #define ESR3_MASK_CLR_OFFSET 0x95c
  140. #define ESR4_MASK_CLR_OFFSET 0x974
  141. /* Error Status Regs --- End */
  142. #define R5F_ESR0_SHIFT 0 /* esr0 = fifo underflow */
  143. #define R5F_ESR1_SHIFT 1 /* esr1 = ringbuf underflow */
  144. #define R5F_ESR2_SHIFT 2 /* esr2 = ringbuf overflow */
  145. #define R5F_ESR3_SHIFT 3 /* esr3 = freemark */
  146. #define R5F_ESR4_SHIFT 4 /* esr4 = fullmark */
  147. /* Mask for R5F register. Set all relevant interrupt for playback handler */
  148. #define ANY_PLAYBACK_IRQ (BIT(R5F_ESR0_SHIFT) | \
  149. BIT(R5F_ESR1_SHIFT) | \
  150. BIT(R5F_ESR3_SHIFT))
  151. /* Mask for R5F register. Set all relevant interrupt for capture handler */
  152. #define ANY_CAPTURE_IRQ (BIT(R5F_ESR2_SHIFT) | BIT(R5F_ESR4_SHIFT))
  153. /*
  154. * PERIOD_BYTES_MIN is the number of bytes to at which the interrupt will tick.
  155. * This number should be a multiple of 256. Minimum value is 256
  156. */
  157. #define PERIOD_BYTES_MIN 0x100
  158. static const struct snd_pcm_hardware cygnus_pcm_hw = {
  159. .info = SNDRV_PCM_INFO_MMAP |
  160. SNDRV_PCM_INFO_MMAP_VALID |
  161. SNDRV_PCM_INFO_INTERLEAVED,
  162. .formats = SNDRV_PCM_FMTBIT_S16_LE |
  163. SNDRV_PCM_FMTBIT_S32_LE,
  164. /* A period is basically an interrupt */
  165. .period_bytes_min = PERIOD_BYTES_MIN,
  166. .period_bytes_max = 0x10000,
  167. /* period_min/max gives range of approx interrupts per buffer */
  168. .periods_min = 2,
  169. .periods_max = 8,
  170. /*
  171. * maximum buffer size in bytes = period_bytes_max * periods_max
  172. * We allocate this amount of data for each enabled channel
  173. */
  174. .buffer_bytes_max = 4 * 0x8000,
  175. };
  176. static u64 cygnus_dma_dmamask = DMA_BIT_MASK(32);
  177. static struct cygnus_aio_port *cygnus_dai_get_dma_data(
  178. struct snd_pcm_substream *substream)
  179. {
  180. struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
  181. return snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream);
  182. }
  183. static void ringbuf_set_initial(void __iomem *audio_io,
  184. struct ringbuf_regs *p_rbuf,
  185. bool is_playback,
  186. u32 start,
  187. u32 periodsize,
  188. u32 bufsize)
  189. {
  190. u32 initial_rd;
  191. u32 initial_wr;
  192. u32 end;
  193. u32 fmark_val; /* free or full mark */
  194. p_rbuf->period_bytes = periodsize;
  195. p_rbuf->buf_size = bufsize;
  196. if (is_playback) {
  197. /* Set the pointers to indicate full (flip uppermost bit) */
  198. initial_rd = start;
  199. initial_wr = initial_rd ^ BIT(31);
  200. } else {
  201. /* Set the pointers to indicate empty */
  202. initial_wr = start;
  203. initial_rd = initial_wr;
  204. }
  205. end = start + bufsize - 1;
  206. /*
  207. * The interrupt will fire when free/full mark is *exceeded*
  208. * The fmark value must be multiple of PERIOD_BYTES_MIN so set fmark
  209. * to be PERIOD_BYTES_MIN less than the period size.
  210. */
  211. fmark_val = periodsize - PERIOD_BYTES_MIN;
  212. writel(start, audio_io + p_rbuf->baseaddr);
  213. writel(end, audio_io + p_rbuf->endaddr);
  214. writel(fmark_val, audio_io + p_rbuf->fmark);
  215. writel(initial_rd, audio_io + p_rbuf->rdaddr);
  216. writel(initial_wr, audio_io + p_rbuf->wraddr);
  217. }
  218. static int configure_ringbuf_regs(struct snd_pcm_substream *substream)
  219. {
  220. struct cygnus_aio_port *aio;
  221. struct ringbuf_regs *p_rbuf;
  222. int status = 0;
  223. aio = cygnus_dai_get_dma_data(substream);
  224. /* Map the ssp portnum to a set of ring buffers. */
  225. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  226. p_rbuf = &aio->play_rb_regs;
  227. switch (aio->portnum) {
  228. case 0:
  229. *p_rbuf = RINGBUF_REG_PLAYBACK(0);
  230. break;
  231. case 1:
  232. *p_rbuf = RINGBUF_REG_PLAYBACK(2);
  233. break;
  234. case 2:
  235. *p_rbuf = RINGBUF_REG_PLAYBACK(4);
  236. break;
  237. case 3: /* SPDIF */
  238. *p_rbuf = RINGBUF_REG_PLAYBACK(6);
  239. break;
  240. default:
  241. status = -EINVAL;
  242. }
  243. } else {
  244. p_rbuf = &aio->capture_rb_regs;
  245. switch (aio->portnum) {
  246. case 0:
  247. *p_rbuf = RINGBUF_REG_CAPTURE(0);
  248. break;
  249. case 1:
  250. *p_rbuf = RINGBUF_REG_CAPTURE(2);
  251. break;
  252. case 2:
  253. *p_rbuf = RINGBUF_REG_CAPTURE(4);
  254. break;
  255. default:
  256. status = -EINVAL;
  257. }
  258. }
  259. return status;
  260. }
  261. static struct ringbuf_regs *get_ringbuf(struct snd_pcm_substream *substream)
  262. {
  263. struct cygnus_aio_port *aio;
  264. struct ringbuf_regs *p_rbuf = NULL;
  265. aio = cygnus_dai_get_dma_data(substream);
  266. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  267. p_rbuf = &aio->play_rb_regs;
  268. else
  269. p_rbuf = &aio->capture_rb_regs;
  270. return p_rbuf;
  271. }
  272. static void enable_intr(struct snd_pcm_substream *substream)
  273. {
  274. struct cygnus_aio_port *aio;
  275. u32 clear_mask;
  276. aio = cygnus_dai_get_dma_data(substream);
  277. /* The port number maps to the bit position to be cleared */
  278. clear_mask = BIT(aio->portnum);
  279. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  280. /* Clear interrupt status before enabling them */
  281. writel(clear_mask, aio->cygaud->audio + ESR0_STATUS_CLR_OFFSET);
  282. writel(clear_mask, aio->cygaud->audio + ESR1_STATUS_CLR_OFFSET);
  283. writel(clear_mask, aio->cygaud->audio + ESR3_STATUS_CLR_OFFSET);
  284. /* Unmask the interrupts of the given port*/
  285. writel(clear_mask, aio->cygaud->audio + ESR0_MASK_CLR_OFFSET);
  286. writel(clear_mask, aio->cygaud->audio + ESR1_MASK_CLR_OFFSET);
  287. writel(clear_mask, aio->cygaud->audio + ESR3_MASK_CLR_OFFSET);
  288. writel(ANY_PLAYBACK_IRQ,
  289. aio->cygaud->audio + INTH_R5F_MASK_CLEAR_OFFSET);
  290. } else {
  291. writel(clear_mask, aio->cygaud->audio + ESR2_STATUS_CLR_OFFSET);
  292. writel(clear_mask, aio->cygaud->audio + ESR4_STATUS_CLR_OFFSET);
  293. writel(clear_mask, aio->cygaud->audio + ESR2_MASK_CLR_OFFSET);
  294. writel(clear_mask, aio->cygaud->audio + ESR4_MASK_CLR_OFFSET);
  295. writel(ANY_CAPTURE_IRQ,
  296. aio->cygaud->audio + INTH_R5F_MASK_CLEAR_OFFSET);
  297. }
  298. }
  299. static void disable_intr(struct snd_pcm_substream *substream)
  300. {
  301. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  302. struct cygnus_aio_port *aio;
  303. u32 set_mask;
  304. aio = cygnus_dai_get_dma_data(substream);
  305. dev_dbg(rtd->cpu_dai->dev, "%s on port %d\n", __func__, aio->portnum);
  306. /* The port number maps to the bit position to be set */
  307. set_mask = BIT(aio->portnum);
  308. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  309. /* Mask the interrupts of the given port*/
  310. writel(set_mask, aio->cygaud->audio + ESR0_MASK_SET_OFFSET);
  311. writel(set_mask, aio->cygaud->audio + ESR1_MASK_SET_OFFSET);
  312. writel(set_mask, aio->cygaud->audio + ESR3_MASK_SET_OFFSET);
  313. } else {
  314. writel(set_mask, aio->cygaud->audio + ESR2_MASK_SET_OFFSET);
  315. writel(set_mask, aio->cygaud->audio + ESR4_MASK_SET_OFFSET);
  316. }
  317. }
  318. static int cygnus_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
  319. {
  320. int ret = 0;
  321. switch (cmd) {
  322. case SNDRV_PCM_TRIGGER_START:
  323. case SNDRV_PCM_TRIGGER_RESUME:
  324. enable_intr(substream);
  325. break;
  326. case SNDRV_PCM_TRIGGER_STOP:
  327. case SNDRV_PCM_TRIGGER_SUSPEND:
  328. disable_intr(substream);
  329. break;
  330. default:
  331. ret = -EINVAL;
  332. }
  333. return ret;
  334. }
  335. static void cygnus_pcm_period_elapsed(struct snd_pcm_substream *substream)
  336. {
  337. struct cygnus_aio_port *aio;
  338. struct ringbuf_regs *p_rbuf = NULL;
  339. u32 regval;
  340. aio = cygnus_dai_get_dma_data(substream);
  341. p_rbuf = get_ringbuf(substream);
  342. /*
  343. * If free/full mark interrupt occurs, provide timestamp
  344. * to ALSA and update appropriate idx by period_bytes
  345. */
  346. snd_pcm_period_elapsed(substream);
  347. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  348. /* Set the ring buffer to full */
  349. regval = readl(aio->cygaud->audio + p_rbuf->rdaddr);
  350. regval = regval ^ BIT(31);
  351. writel(regval, aio->cygaud->audio + p_rbuf->wraddr);
  352. } else {
  353. /* Set the ring buffer to empty */
  354. regval = readl(aio->cygaud->audio + p_rbuf->wraddr);
  355. writel(regval, aio->cygaud->audio + p_rbuf->rdaddr);
  356. }
  357. }
  358. /*
  359. * ESR0/1/3 status Description
  360. * 0x1 I2S0_out port caused interrupt
  361. * 0x2 I2S1_out port caused interrupt
  362. * 0x4 I2S2_out port caused interrupt
  363. * 0x8 SPDIF_out port caused interrupt
  364. */
  365. static void handle_playback_irq(struct cygnus_audio *cygaud)
  366. {
  367. void __iomem *audio_io;
  368. u32 port;
  369. u32 esr_status0, esr_status1, esr_status3;
  370. audio_io = cygaud->audio;
  371. /*
  372. * ESR status gets updates with/without interrupts enabled.
  373. * So, check the ESR mask, which provides interrupt enable/
  374. * disable status and use it to determine which ESR status
  375. * should be serviced.
  376. */
  377. esr_status0 = readl(audio_io + ESR0_STATUS_OFFSET);
  378. esr_status0 &= ~readl(audio_io + ESR0_MASK_STATUS_OFFSET);
  379. esr_status1 = readl(audio_io + ESR1_STATUS_OFFSET);
  380. esr_status1 &= ~readl(audio_io + ESR1_MASK_STATUS_OFFSET);
  381. esr_status3 = readl(audio_io + ESR3_STATUS_OFFSET);
  382. esr_status3 &= ~readl(audio_io + ESR3_MASK_STATUS_OFFSET);
  383. for (port = 0; port < CYGNUS_MAX_PLAYBACK_PORTS; port++) {
  384. u32 esrmask = BIT(port);
  385. /*
  386. * Ringbuffer or FIFO underflow
  387. * If we get this interrupt then, it is also true that we have
  388. * not yet responded to the freemark interrupt.
  389. * Log a debug message. The freemark handler below will
  390. * handle getting everything going again.
  391. */
  392. if ((esrmask & esr_status1) || (esrmask & esr_status0)) {
  393. dev_dbg(cygaud->dev,
  394. "Underrun: esr0=0x%x, esr1=0x%x esr3=0x%x\n",
  395. esr_status0, esr_status1, esr_status3);
  396. }
  397. /*
  398. * Freemark is hit. This is the normal interrupt.
  399. * In typical operation the read and write regs will be equal
  400. */
  401. if (esrmask & esr_status3) {
  402. struct snd_pcm_substream *playstr;
  403. playstr = cygaud->portinfo[port].play_stream;
  404. cygnus_pcm_period_elapsed(playstr);
  405. }
  406. }
  407. /* Clear ESR interrupt */
  408. writel(esr_status0, audio_io + ESR0_STATUS_CLR_OFFSET);
  409. writel(esr_status1, audio_io + ESR1_STATUS_CLR_OFFSET);
  410. writel(esr_status3, audio_io + ESR3_STATUS_CLR_OFFSET);
  411. /* Rearm freemark logic by writing 1 to the correct bit */
  412. writel(esr_status3, audio_io + BF_REARM_FREE_MARK_OFFSET);
  413. }
  414. /*
  415. * ESR2/4 status Description
  416. * 0x1 I2S0_in port caused interrupt
  417. * 0x2 I2S1_in port caused interrupt
  418. * 0x4 I2S2_in port caused interrupt
  419. */
  420. static void handle_capture_irq(struct cygnus_audio *cygaud)
  421. {
  422. void __iomem *audio_io;
  423. u32 port;
  424. u32 esr_status2, esr_status4;
  425. audio_io = cygaud->audio;
  426. /*
  427. * ESR status gets updates with/without interrupts enabled.
  428. * So, check the ESR mask, which provides interrupt enable/
  429. * disable status and use it to determine which ESR status
  430. * should be serviced.
  431. */
  432. esr_status2 = readl(audio_io + ESR2_STATUS_OFFSET);
  433. esr_status2 &= ~readl(audio_io + ESR2_MASK_STATUS_OFFSET);
  434. esr_status4 = readl(audio_io + ESR4_STATUS_OFFSET);
  435. esr_status4 &= ~readl(audio_io + ESR4_MASK_STATUS_OFFSET);
  436. for (port = 0; port < CYGNUS_MAX_CAPTURE_PORTS; port++) {
  437. u32 esrmask = BIT(port);
  438. /*
  439. * Ringbuffer or FIFO overflow
  440. * If we get this interrupt then, it is also true that we have
  441. * not yet responded to the fullmark interrupt.
  442. * Log a debug message. The fullmark handler below will
  443. * handle getting everything going again.
  444. */
  445. if (esrmask & esr_status2)
  446. dev_dbg(cygaud->dev,
  447. "Overflow: esr2=0x%x\n", esr_status2);
  448. if (esrmask & esr_status4) {
  449. struct snd_pcm_substream *capstr;
  450. capstr = cygaud->portinfo[port].capture_stream;
  451. cygnus_pcm_period_elapsed(capstr);
  452. }
  453. }
  454. writel(esr_status2, audio_io + ESR2_STATUS_CLR_OFFSET);
  455. writel(esr_status4, audio_io + ESR4_STATUS_CLR_OFFSET);
  456. /* Rearm fullmark logic by writing 1 to the correct bit */
  457. writel(esr_status4, audio_io + BF_REARM_FULL_MARK_OFFSET);
  458. }
  459. static irqreturn_t cygnus_dma_irq(int irq, void *data)
  460. {
  461. u32 r5_status;
  462. struct cygnus_audio *cygaud = data;
  463. /*
  464. * R5 status bits Description
  465. * 0 ESR0 (playback FIFO interrupt)
  466. * 1 ESR1 (playback rbuf interrupt)
  467. * 2 ESR2 (capture rbuf interrupt)
  468. * 3 ESR3 (Freemark play. interrupt)
  469. * 4 ESR4 (Fullmark capt. interrupt)
  470. */
  471. r5_status = readl(cygaud->audio + INTH_R5F_STATUS_OFFSET);
  472. if (!(r5_status & (ANY_PLAYBACK_IRQ | ANY_CAPTURE_IRQ)))
  473. return IRQ_NONE;
  474. /* If playback interrupt happened */
  475. if (ANY_PLAYBACK_IRQ & r5_status) {
  476. handle_playback_irq(cygaud);
  477. writel(ANY_PLAYBACK_IRQ & r5_status,
  478. cygaud->audio + INTH_R5F_CLEAR_OFFSET);
  479. }
  480. /* If capture interrupt happened */
  481. if (ANY_CAPTURE_IRQ & r5_status) {
  482. handle_capture_irq(cygaud);
  483. writel(ANY_CAPTURE_IRQ & r5_status,
  484. cygaud->audio + INTH_R5F_CLEAR_OFFSET);
  485. }
  486. return IRQ_HANDLED;
  487. }
  488. static int cygnus_pcm_open(struct snd_pcm_substream *substream)
  489. {
  490. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  491. struct snd_pcm_runtime *runtime = substream->runtime;
  492. struct cygnus_aio_port *aio;
  493. int ret;
  494. aio = cygnus_dai_get_dma_data(substream);
  495. if (!aio)
  496. return -ENODEV;
  497. dev_dbg(rtd->cpu_dai->dev, "%s port %d\n", __func__, aio->portnum);
  498. snd_soc_set_runtime_hwparams(substream, &cygnus_pcm_hw);
  499. ret = snd_pcm_hw_constraint_step(runtime, 0,
  500. SNDRV_PCM_HW_PARAM_PERIOD_BYTES, PERIOD_BYTES_MIN);
  501. if (ret < 0)
  502. return ret;
  503. ret = snd_pcm_hw_constraint_step(runtime, 0,
  504. SNDRV_PCM_HW_PARAM_BUFFER_BYTES, PERIOD_BYTES_MIN);
  505. if (ret < 0)
  506. return ret;
  507. /*
  508. * Keep track of which substream belongs to which port.
  509. * This info is needed by snd_pcm_period_elapsed() in irq_handler
  510. */
  511. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  512. aio->play_stream = substream;
  513. else
  514. aio->capture_stream = substream;
  515. return 0;
  516. }
  517. static int cygnus_pcm_close(struct snd_pcm_substream *substream)
  518. {
  519. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  520. struct cygnus_aio_port *aio;
  521. aio = cygnus_dai_get_dma_data(substream);
  522. dev_dbg(rtd->cpu_dai->dev, "%s port %d\n", __func__, aio->portnum);
  523. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  524. aio->play_stream = NULL;
  525. else
  526. aio->capture_stream = NULL;
  527. if (!aio->play_stream && !aio->capture_stream)
  528. dev_dbg(rtd->cpu_dai->dev, "freed port %d\n", aio->portnum);
  529. return 0;
  530. }
  531. static int cygnus_pcm_hw_params(struct snd_pcm_substream *substream,
  532. struct snd_pcm_hw_params *params)
  533. {
  534. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  535. struct snd_pcm_runtime *runtime = substream->runtime;
  536. struct cygnus_aio_port *aio;
  537. int ret = 0;
  538. aio = cygnus_dai_get_dma_data(substream);
  539. dev_dbg(rtd->cpu_dai->dev, "%s port %d\n", __func__, aio->portnum);
  540. snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
  541. runtime->dma_bytes = params_buffer_bytes(params);
  542. return ret;
  543. }
  544. static int cygnus_pcm_hw_free(struct snd_pcm_substream *substream)
  545. {
  546. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  547. struct cygnus_aio_port *aio;
  548. aio = cygnus_dai_get_dma_data(substream);
  549. dev_dbg(rtd->cpu_dai->dev, "%s port %d\n", __func__, aio->portnum);
  550. snd_pcm_set_runtime_buffer(substream, NULL);
  551. return 0;
  552. }
  553. static int cygnus_pcm_prepare(struct snd_pcm_substream *substream)
  554. {
  555. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  556. struct snd_pcm_runtime *runtime = substream->runtime;
  557. struct cygnus_aio_port *aio;
  558. unsigned long bufsize, periodsize;
  559. int ret = 0;
  560. bool is_play;
  561. u32 start;
  562. struct ringbuf_regs *p_rbuf = NULL;
  563. aio = cygnus_dai_get_dma_data(substream);
  564. dev_dbg(rtd->cpu_dai->dev, "%s port %d\n", __func__, aio->portnum);
  565. bufsize = snd_pcm_lib_buffer_bytes(substream);
  566. periodsize = snd_pcm_lib_period_bytes(substream);
  567. dev_dbg(rtd->cpu_dai->dev, "%s (buf_size %lu) (period_size %lu)\n",
  568. __func__, bufsize, periodsize);
  569. configure_ringbuf_regs(substream);
  570. p_rbuf = get_ringbuf(substream);
  571. start = runtime->dma_addr;
  572. is_play = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? 1 : 0;
  573. ringbuf_set_initial(aio->cygaud->audio, p_rbuf, is_play, start,
  574. periodsize, bufsize);
  575. return ret;
  576. }
  577. static snd_pcm_uframes_t cygnus_pcm_pointer(struct snd_pcm_substream *substream)
  578. {
  579. struct cygnus_aio_port *aio;
  580. unsigned int res = 0, cur = 0, base = 0;
  581. struct ringbuf_regs *p_rbuf = NULL;
  582. aio = cygnus_dai_get_dma_data(substream);
  583. /*
  584. * Get the offset of the current read (for playack) or write
  585. * index (for capture). Report this value back to the asoc framework.
  586. */
  587. p_rbuf = get_ringbuf(substream);
  588. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  589. cur = readl(aio->cygaud->audio + p_rbuf->rdaddr);
  590. else
  591. cur = readl(aio->cygaud->audio + p_rbuf->wraddr);
  592. base = readl(aio->cygaud->audio + p_rbuf->baseaddr);
  593. /*
  594. * Mask off the MSB of the rdaddr,wraddr and baseaddr
  595. * since MSB is not part of the address
  596. */
  597. res = (cur & 0x7fffffff) - (base & 0x7fffffff);
  598. return bytes_to_frames(substream->runtime, res);
  599. }
  600. static int cygnus_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
  601. {
  602. struct snd_pcm_substream *substream = pcm->streams[stream].substream;
  603. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  604. struct snd_dma_buffer *buf = &substream->dma_buffer;
  605. size_t size;
  606. size = cygnus_pcm_hw.buffer_bytes_max;
  607. buf->dev.type = SNDRV_DMA_TYPE_DEV;
  608. buf->dev.dev = pcm->card->dev;
  609. buf->private_data = NULL;
  610. buf->area = dma_alloc_coherent(pcm->card->dev, size,
  611. &buf->addr, GFP_KERNEL);
  612. dev_dbg(rtd->cpu_dai->dev, "%s: size 0x%zx @ %pK\n",
  613. __func__, size, buf->area);
  614. if (!buf->area) {
  615. dev_err(rtd->cpu_dai->dev, "%s: dma_alloc failed\n", __func__);
  616. return -ENOMEM;
  617. }
  618. buf->bytes = size;
  619. return 0;
  620. }
  621. static const struct snd_pcm_ops cygnus_pcm_ops = {
  622. .open = cygnus_pcm_open,
  623. .close = cygnus_pcm_close,
  624. .ioctl = snd_pcm_lib_ioctl,
  625. .hw_params = cygnus_pcm_hw_params,
  626. .hw_free = cygnus_pcm_hw_free,
  627. .prepare = cygnus_pcm_prepare,
  628. .trigger = cygnus_pcm_trigger,
  629. .pointer = cygnus_pcm_pointer,
  630. };
  631. static void cygnus_dma_free_dma_buffers(struct snd_pcm *pcm)
  632. {
  633. struct snd_pcm_substream *substream;
  634. struct snd_dma_buffer *buf;
  635. substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
  636. if (substream) {
  637. buf = &substream->dma_buffer;
  638. if (buf->area) {
  639. dma_free_coherent(pcm->card->dev, buf->bytes,
  640. buf->area, buf->addr);
  641. buf->area = NULL;
  642. }
  643. }
  644. substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
  645. if (substream) {
  646. buf = &substream->dma_buffer;
  647. if (buf->area) {
  648. dma_free_coherent(pcm->card->dev, buf->bytes,
  649. buf->area, buf->addr);
  650. buf->area = NULL;
  651. }
  652. }
  653. }
  654. static int cygnus_dma_new(struct snd_soc_pcm_runtime *rtd)
  655. {
  656. struct snd_card *card = rtd->card->snd_card;
  657. struct snd_pcm *pcm = rtd->pcm;
  658. int ret;
  659. if (!card->dev->dma_mask)
  660. card->dev->dma_mask = &cygnus_dma_dmamask;
  661. if (!card->dev->coherent_dma_mask)
  662. card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
  663. if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
  664. ret = cygnus_pcm_preallocate_dma_buffer(pcm,
  665. SNDRV_PCM_STREAM_PLAYBACK);
  666. if (ret)
  667. return ret;
  668. }
  669. if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
  670. ret = cygnus_pcm_preallocate_dma_buffer(pcm,
  671. SNDRV_PCM_STREAM_CAPTURE);
  672. if (ret) {
  673. cygnus_dma_free_dma_buffers(pcm);
  674. return ret;
  675. }
  676. }
  677. return 0;
  678. }
  679. static struct snd_soc_platform_driver cygnus_soc_platform = {
  680. .ops = &cygnus_pcm_ops,
  681. .pcm_new = cygnus_dma_new,
  682. .pcm_free = cygnus_dma_free_dma_buffers,
  683. };
  684. int cygnus_soc_platform_register(struct device *dev,
  685. struct cygnus_audio *cygaud)
  686. {
  687. int rc = 0;
  688. dev_dbg(dev, "%s Enter\n", __func__);
  689. rc = devm_request_irq(dev, cygaud->irq_num, cygnus_dma_irq,
  690. IRQF_SHARED, "cygnus-audio", cygaud);
  691. if (rc) {
  692. dev_err(dev, "%s request_irq error %d\n", __func__, rc);
  693. return rc;
  694. }
  695. rc = snd_soc_register_platform(dev, &cygnus_soc_platform);
  696. if (rc) {
  697. dev_err(dev, "%s failed\n", __func__);
  698. return rc;
  699. }
  700. return 0;
  701. }
  702. int cygnus_soc_platform_unregister(struct device *dev)
  703. {
  704. snd_soc_unregister_platform(dev);
  705. return 0;
  706. }
  707. MODULE_LICENSE("GPL v2");
  708. MODULE_AUTHOR("Broadcom");
  709. MODULE_DESCRIPTION("Cygnus ASoC PCM module");