cygnus-pcm.c 21 KB

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