idma.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. // SPDX-License-Identifier: GPL-2.0+
  2. //
  3. // idma.c - I2S0 internal DMA driver
  4. //
  5. // Copyright (c) 2011 Samsung Electronics Co., Ltd.
  6. // http://www.samsung.com
  7. #include <linux/interrupt.h>
  8. #include <linux/platform_device.h>
  9. #include <linux/dma-mapping.h>
  10. #include <linux/slab.h>
  11. #include <linux/module.h>
  12. #include <sound/pcm.h>
  13. #include <sound/pcm_params.h>
  14. #include <sound/soc.h>
  15. #include "i2s.h"
  16. #include "idma.h"
  17. #include "i2s-regs.h"
  18. #define ST_RUNNING (1<<0)
  19. #define ST_OPENED (1<<1)
  20. static const struct snd_pcm_hardware idma_hardware = {
  21. .info = SNDRV_PCM_INFO_INTERLEAVED |
  22. SNDRV_PCM_INFO_BLOCK_TRANSFER |
  23. SNDRV_PCM_INFO_MMAP |
  24. SNDRV_PCM_INFO_MMAP_VALID |
  25. SNDRV_PCM_INFO_PAUSE |
  26. SNDRV_PCM_INFO_RESUME,
  27. .buffer_bytes_max = MAX_IDMA_BUFFER,
  28. .period_bytes_min = 128,
  29. .period_bytes_max = MAX_IDMA_PERIOD,
  30. .periods_min = 1,
  31. .periods_max = 2,
  32. };
  33. struct idma_ctrl {
  34. spinlock_t lock;
  35. int state;
  36. dma_addr_t start;
  37. dma_addr_t pos;
  38. dma_addr_t end;
  39. dma_addr_t period;
  40. dma_addr_t periodsz;
  41. void *token;
  42. void (*cb)(void *dt, int bytes_xfer);
  43. };
  44. static struct idma_info {
  45. spinlock_t lock;
  46. void __iomem *regs;
  47. dma_addr_t lp_tx_addr;
  48. } idma;
  49. static int idma_irq;
  50. static void idma_getpos(dma_addr_t *src)
  51. {
  52. *src = idma.lp_tx_addr +
  53. (readl(idma.regs + I2STRNCNT) & 0xffffff) * 4;
  54. }
  55. static int idma_enqueue(struct snd_pcm_substream *substream)
  56. {
  57. struct snd_pcm_runtime *runtime = substream->runtime;
  58. struct idma_ctrl *prtd = substream->runtime->private_data;
  59. u32 val;
  60. spin_lock(&prtd->lock);
  61. prtd->token = (void *) substream;
  62. spin_unlock(&prtd->lock);
  63. /* Internal DMA Level0 Interrupt Address */
  64. val = idma.lp_tx_addr + prtd->periodsz;
  65. writel(val, idma.regs + I2SLVL0ADDR);
  66. /* Start address0 of I2S internal DMA operation. */
  67. val = idma.lp_tx_addr;
  68. writel(val, idma.regs + I2SSTR0);
  69. /*
  70. * Transfer block size for I2S internal DMA.
  71. * Should decide transfer size before start dma operation
  72. */
  73. val = readl(idma.regs + I2SSIZE);
  74. val &= ~(I2SSIZE_TRNMSK << I2SSIZE_SHIFT);
  75. val |= (((runtime->dma_bytes >> 2) &
  76. I2SSIZE_TRNMSK) << I2SSIZE_SHIFT);
  77. writel(val, idma.regs + I2SSIZE);
  78. val = readl(idma.regs + I2SAHB);
  79. val |= AHB_INTENLVL0;
  80. writel(val, idma.regs + I2SAHB);
  81. return 0;
  82. }
  83. static void idma_setcallbk(struct snd_pcm_substream *substream,
  84. void (*cb)(void *, int))
  85. {
  86. struct idma_ctrl *prtd = substream->runtime->private_data;
  87. spin_lock(&prtd->lock);
  88. prtd->cb = cb;
  89. spin_unlock(&prtd->lock);
  90. }
  91. static void idma_control(int op)
  92. {
  93. u32 val = readl(idma.regs + I2SAHB);
  94. spin_lock(&idma.lock);
  95. switch (op) {
  96. case LPAM_DMA_START:
  97. val |= (AHB_INTENLVL0 | AHB_DMAEN);
  98. break;
  99. case LPAM_DMA_STOP:
  100. val &= ~(AHB_INTENLVL0 | AHB_DMAEN);
  101. break;
  102. default:
  103. spin_unlock(&idma.lock);
  104. return;
  105. }
  106. writel(val, idma.regs + I2SAHB);
  107. spin_unlock(&idma.lock);
  108. }
  109. static void idma_done(void *id, int bytes_xfer)
  110. {
  111. struct snd_pcm_substream *substream = id;
  112. struct idma_ctrl *prtd = substream->runtime->private_data;
  113. if (prtd && (prtd->state & ST_RUNNING))
  114. snd_pcm_period_elapsed(substream);
  115. }
  116. static int idma_hw_params(struct snd_soc_component *component,
  117. struct snd_pcm_substream *substream,
  118. struct snd_pcm_hw_params *params)
  119. {
  120. struct snd_pcm_runtime *runtime = substream->runtime;
  121. struct idma_ctrl *prtd = substream->runtime->private_data;
  122. u32 mod = readl(idma.regs + I2SMOD);
  123. u32 ahb = readl(idma.regs + I2SAHB);
  124. ahb |= (AHB_DMARLD | AHB_INTMASK);
  125. mod |= MOD_TXS_IDMA;
  126. writel(ahb, idma.regs + I2SAHB);
  127. writel(mod, idma.regs + I2SMOD);
  128. snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
  129. runtime->dma_bytes = params_buffer_bytes(params);
  130. prtd->start = prtd->pos = runtime->dma_addr;
  131. prtd->period = params_periods(params);
  132. prtd->periodsz = params_period_bytes(params);
  133. prtd->end = runtime->dma_addr + runtime->dma_bytes;
  134. idma_setcallbk(substream, idma_done);
  135. return 0;
  136. }
  137. static int idma_hw_free(struct snd_soc_component *component,
  138. struct snd_pcm_substream *substream)
  139. {
  140. snd_pcm_set_runtime_buffer(substream, NULL);
  141. return 0;
  142. }
  143. static int idma_prepare(struct snd_soc_component *component,
  144. struct snd_pcm_substream *substream)
  145. {
  146. struct idma_ctrl *prtd = substream->runtime->private_data;
  147. prtd->pos = prtd->start;
  148. /* flush the DMA channel */
  149. idma_control(LPAM_DMA_STOP);
  150. idma_enqueue(substream);
  151. return 0;
  152. }
  153. static int idma_trigger(struct snd_soc_component *component,
  154. struct snd_pcm_substream *substream, int cmd)
  155. {
  156. struct idma_ctrl *prtd = substream->runtime->private_data;
  157. int ret = 0;
  158. spin_lock(&prtd->lock);
  159. switch (cmd) {
  160. case SNDRV_PCM_TRIGGER_RESUME:
  161. case SNDRV_PCM_TRIGGER_START:
  162. case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  163. prtd->state |= ST_RUNNING;
  164. idma_control(LPAM_DMA_START);
  165. break;
  166. case SNDRV_PCM_TRIGGER_SUSPEND:
  167. case SNDRV_PCM_TRIGGER_STOP:
  168. case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  169. prtd->state &= ~ST_RUNNING;
  170. idma_control(LPAM_DMA_STOP);
  171. break;
  172. default:
  173. ret = -EINVAL;
  174. break;
  175. }
  176. spin_unlock(&prtd->lock);
  177. return ret;
  178. }
  179. static snd_pcm_uframes_t
  180. idma_pointer(struct snd_soc_component *component,
  181. struct snd_pcm_substream *substream)
  182. {
  183. struct snd_pcm_runtime *runtime = substream->runtime;
  184. struct idma_ctrl *prtd = runtime->private_data;
  185. dma_addr_t src;
  186. unsigned long res;
  187. spin_lock(&prtd->lock);
  188. idma_getpos(&src);
  189. res = src - prtd->start;
  190. spin_unlock(&prtd->lock);
  191. return bytes_to_frames(substream->runtime, res);
  192. }
  193. static int idma_mmap(struct snd_soc_component *component,
  194. struct snd_pcm_substream *substream,
  195. struct vm_area_struct *vma)
  196. {
  197. struct snd_pcm_runtime *runtime = substream->runtime;
  198. unsigned long size, offset;
  199. /* From snd_pcm_lib_mmap_iomem */
  200. vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
  201. size = vma->vm_end - vma->vm_start;
  202. offset = vma->vm_pgoff << PAGE_SHIFT;
  203. return io_remap_pfn_range(vma, vma->vm_start,
  204. (runtime->dma_addr + offset) >> PAGE_SHIFT,
  205. size, vma->vm_page_prot);
  206. }
  207. static irqreturn_t iis_irq(int irqno, void *dev_id)
  208. {
  209. struct idma_ctrl *prtd = (struct idma_ctrl *)dev_id;
  210. u32 iisahb, val, addr;
  211. iisahb = readl(idma.regs + I2SAHB);
  212. val = (iisahb & AHB_LVL0INT) ? AHB_CLRLVL0INT : 0;
  213. if (val) {
  214. iisahb |= val;
  215. writel(iisahb, idma.regs + I2SAHB);
  216. addr = readl(idma.regs + I2SLVL0ADDR) - idma.lp_tx_addr;
  217. addr += prtd->periodsz;
  218. addr %= (u32)(prtd->end - prtd->start);
  219. addr += idma.lp_tx_addr;
  220. writel(addr, idma.regs + I2SLVL0ADDR);
  221. if (prtd->cb)
  222. prtd->cb(prtd->token, prtd->period);
  223. }
  224. return IRQ_HANDLED;
  225. }
  226. static int idma_open(struct snd_soc_component *component,
  227. struct snd_pcm_substream *substream)
  228. {
  229. struct snd_pcm_runtime *runtime = substream->runtime;
  230. struct idma_ctrl *prtd;
  231. int ret;
  232. snd_soc_set_runtime_hwparams(substream, &idma_hardware);
  233. prtd = kzalloc(sizeof(struct idma_ctrl), GFP_KERNEL);
  234. if (prtd == NULL)
  235. return -ENOMEM;
  236. ret = request_irq(idma_irq, iis_irq, 0, "i2s", prtd);
  237. if (ret < 0) {
  238. pr_err("fail to claim i2s irq , ret = %d\n", ret);
  239. kfree(prtd);
  240. return ret;
  241. }
  242. spin_lock_init(&prtd->lock);
  243. runtime->private_data = prtd;
  244. return 0;
  245. }
  246. static int idma_close(struct snd_soc_component *component,
  247. struct snd_pcm_substream *substream)
  248. {
  249. struct snd_pcm_runtime *runtime = substream->runtime;
  250. struct idma_ctrl *prtd = runtime->private_data;
  251. free_irq(idma_irq, prtd);
  252. if (!prtd)
  253. pr_err("idma_close called with prtd == NULL\n");
  254. kfree(prtd);
  255. return 0;
  256. }
  257. static void idma_free(struct snd_soc_component *component,
  258. struct snd_pcm *pcm)
  259. {
  260. struct snd_pcm_substream *substream;
  261. struct snd_dma_buffer *buf;
  262. substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
  263. if (!substream)
  264. return;
  265. buf = &substream->dma_buffer;
  266. if (!buf->area)
  267. return;
  268. iounmap((void __iomem *)buf->area);
  269. buf->area = NULL;
  270. buf->addr = 0;
  271. }
  272. static int preallocate_idma_buffer(struct snd_pcm *pcm, int stream)
  273. {
  274. struct snd_pcm_substream *substream = pcm->streams[stream].substream;
  275. struct snd_dma_buffer *buf = &substream->dma_buffer;
  276. buf->dev.dev = pcm->card->dev;
  277. buf->private_data = NULL;
  278. /* Assign PCM buffer pointers */
  279. buf->dev.type = SNDRV_DMA_TYPE_CONTINUOUS;
  280. buf->addr = idma.lp_tx_addr;
  281. buf->bytes = idma_hardware.buffer_bytes_max;
  282. buf->area = (unsigned char * __force)ioremap(buf->addr, buf->bytes);
  283. if (!buf->area)
  284. return -ENOMEM;
  285. return 0;
  286. }
  287. static int idma_new(struct snd_soc_component *component,
  288. struct snd_soc_pcm_runtime *rtd)
  289. {
  290. struct snd_card *card = rtd->card->snd_card;
  291. struct snd_pcm *pcm = rtd->pcm;
  292. int ret;
  293. ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
  294. if (ret)
  295. return ret;
  296. if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
  297. ret = preallocate_idma_buffer(pcm,
  298. SNDRV_PCM_STREAM_PLAYBACK);
  299. }
  300. return ret;
  301. }
  302. void idma_reg_addr_init(void __iomem *regs, dma_addr_t addr)
  303. {
  304. spin_lock_init(&idma.lock);
  305. idma.regs = regs;
  306. idma.lp_tx_addr = addr;
  307. }
  308. EXPORT_SYMBOL_GPL(idma_reg_addr_init);
  309. static const struct snd_soc_component_driver asoc_idma_platform = {
  310. .open = idma_open,
  311. .close = idma_close,
  312. .trigger = idma_trigger,
  313. .pointer = idma_pointer,
  314. .mmap = idma_mmap,
  315. .hw_params = idma_hw_params,
  316. .hw_free = idma_hw_free,
  317. .prepare = idma_prepare,
  318. .pcm_construct = idma_new,
  319. .pcm_destruct = idma_free,
  320. };
  321. static int asoc_idma_platform_probe(struct platform_device *pdev)
  322. {
  323. idma_irq = platform_get_irq(pdev, 0);
  324. if (idma_irq < 0)
  325. return idma_irq;
  326. return devm_snd_soc_register_component(&pdev->dev, &asoc_idma_platform,
  327. NULL, 0);
  328. }
  329. static struct platform_driver asoc_idma_driver = {
  330. .driver = {
  331. .name = "samsung-idma",
  332. },
  333. .probe = asoc_idma_platform_probe,
  334. };
  335. module_platform_driver(asoc_idma_driver);
  336. MODULE_AUTHOR("Jaswinder Singh, <[email protected]>");
  337. MODULE_DESCRIPTION("Samsung ASoC IDMA Driver");
  338. MODULE_LICENSE("GPL");