acp3x-pdm-dma.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  1. // SPDX-License-Identifier: GPL-2.0+
  2. //
  3. // AMD ALSA SoC PDM Driver
  4. //
  5. //Copyright 2020 Advanced Micro Devices, Inc.
  6. #include <linux/platform_device.h>
  7. #include <linux/module.h>
  8. #include <linux/err.h>
  9. #include <linux/io.h>
  10. #include <linux/pm_runtime.h>
  11. #include <sound/pcm_params.h>
  12. #include <sound/soc.h>
  13. #include <sound/soc-dai.h>
  14. #include "rn_acp3x.h"
  15. #define DRV_NAME "acp_rn_pdm_dma"
  16. static const struct snd_pcm_hardware acp_pdm_hardware_capture = {
  17. .info = SNDRV_PCM_INFO_INTERLEAVED |
  18. SNDRV_PCM_INFO_BLOCK_TRANSFER |
  19. SNDRV_PCM_INFO_MMAP |
  20. SNDRV_PCM_INFO_MMAP_VALID |
  21. SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
  22. .formats = SNDRV_PCM_FMTBIT_S32_LE,
  23. .channels_min = 2,
  24. .channels_max = 2,
  25. .rates = SNDRV_PCM_RATE_48000,
  26. .rate_min = 48000,
  27. .rate_max = 48000,
  28. .buffer_bytes_max = CAPTURE_MAX_NUM_PERIODS * CAPTURE_MAX_PERIOD_SIZE,
  29. .period_bytes_min = CAPTURE_MIN_PERIOD_SIZE,
  30. .period_bytes_max = CAPTURE_MAX_PERIOD_SIZE,
  31. .periods_min = CAPTURE_MIN_NUM_PERIODS,
  32. .periods_max = CAPTURE_MAX_NUM_PERIODS,
  33. };
  34. static irqreturn_t pdm_irq_handler(int irq, void *dev_id)
  35. {
  36. struct pdm_dev_data *rn_pdm_data;
  37. u16 cap_flag;
  38. u32 val;
  39. rn_pdm_data = dev_id;
  40. if (!rn_pdm_data)
  41. return IRQ_NONE;
  42. cap_flag = 0;
  43. val = rn_readl(rn_pdm_data->acp_base + ACP_EXTERNAL_INTR_STAT);
  44. if ((val & BIT(PDM_DMA_STAT)) && rn_pdm_data->capture_stream) {
  45. rn_writel(BIT(PDM_DMA_STAT), rn_pdm_data->acp_base +
  46. ACP_EXTERNAL_INTR_STAT);
  47. snd_pcm_period_elapsed(rn_pdm_data->capture_stream);
  48. cap_flag = 1;
  49. }
  50. if (cap_flag)
  51. return IRQ_HANDLED;
  52. else
  53. return IRQ_NONE;
  54. }
  55. static void init_pdm_ring_buffer(u32 physical_addr,
  56. u32 buffer_size,
  57. u32 watermark_size,
  58. void __iomem *acp_base)
  59. {
  60. rn_writel(physical_addr, acp_base + ACP_WOV_RX_RINGBUFADDR);
  61. rn_writel(buffer_size, acp_base + ACP_WOV_RX_RINGBUFSIZE);
  62. rn_writel(watermark_size, acp_base + ACP_WOV_RX_INTR_WATERMARK_SIZE);
  63. rn_writel(0x01, acp_base + ACPAXI2AXI_ATU_CTRL);
  64. }
  65. static void enable_pdm_clock(void __iomem *acp_base)
  66. {
  67. u32 pdm_clk_enable, pdm_ctrl;
  68. pdm_clk_enable = ACP_PDM_CLK_FREQ_MASK;
  69. rn_writel(pdm_clk_enable, acp_base + ACP_WOV_CLK_CTRL);
  70. pdm_ctrl = rn_readl(acp_base + ACP_WOV_MISC_CTRL);
  71. pdm_ctrl |= ACP_WOV_MISC_CTRL_MASK;
  72. rn_writel(pdm_ctrl, acp_base + ACP_WOV_MISC_CTRL);
  73. }
  74. static void enable_pdm_interrupts(void __iomem *acp_base)
  75. {
  76. u32 ext_int_ctrl;
  77. ext_int_ctrl = rn_readl(acp_base + ACP_EXTERNAL_INTR_CNTL);
  78. ext_int_ctrl |= PDM_DMA_INTR_MASK;
  79. rn_writel(ext_int_ctrl, acp_base + ACP_EXTERNAL_INTR_CNTL);
  80. }
  81. static void disable_pdm_interrupts(void __iomem *acp_base)
  82. {
  83. u32 ext_int_ctrl;
  84. ext_int_ctrl = rn_readl(acp_base + ACP_EXTERNAL_INTR_CNTL);
  85. ext_int_ctrl |= ~PDM_DMA_INTR_MASK;
  86. rn_writel(ext_int_ctrl, acp_base + ACP_EXTERNAL_INTR_CNTL);
  87. }
  88. static bool check_pdm_dma_status(void __iomem *acp_base)
  89. {
  90. bool pdm_dma_status;
  91. u32 pdm_enable, pdm_dma_enable;
  92. pdm_dma_status = false;
  93. pdm_enable = rn_readl(acp_base + ACP_WOV_PDM_ENABLE);
  94. pdm_dma_enable = rn_readl(acp_base + ACP_WOV_PDM_DMA_ENABLE);
  95. if ((pdm_enable & ACP_PDM_ENABLE) && (pdm_dma_enable &
  96. ACP_PDM_DMA_EN_STATUS))
  97. pdm_dma_status = true;
  98. return pdm_dma_status;
  99. }
  100. static int start_pdm_dma(void __iomem *acp_base)
  101. {
  102. u32 pdm_enable;
  103. u32 pdm_dma_enable;
  104. int timeout;
  105. pdm_enable = 0x01;
  106. pdm_dma_enable = 0x01;
  107. enable_pdm_clock(acp_base);
  108. rn_writel(pdm_enable, acp_base + ACP_WOV_PDM_ENABLE);
  109. rn_writel(pdm_dma_enable, acp_base + ACP_WOV_PDM_DMA_ENABLE);
  110. timeout = 0;
  111. while (++timeout < ACP_COUNTER) {
  112. pdm_dma_enable = rn_readl(acp_base + ACP_WOV_PDM_DMA_ENABLE);
  113. if ((pdm_dma_enable & 0x02) == ACP_PDM_DMA_EN_STATUS)
  114. return 0;
  115. udelay(DELAY_US);
  116. }
  117. return -ETIMEDOUT;
  118. }
  119. static int stop_pdm_dma(void __iomem *acp_base)
  120. {
  121. u32 pdm_enable, pdm_dma_enable;
  122. int timeout;
  123. pdm_enable = rn_readl(acp_base + ACP_WOV_PDM_ENABLE);
  124. pdm_dma_enable = rn_readl(acp_base + ACP_WOV_PDM_DMA_ENABLE);
  125. if (pdm_dma_enable & 0x01) {
  126. pdm_dma_enable = 0x02;
  127. rn_writel(pdm_dma_enable, acp_base + ACP_WOV_PDM_DMA_ENABLE);
  128. timeout = 0;
  129. while (++timeout < ACP_COUNTER) {
  130. pdm_dma_enable = rn_readl(acp_base +
  131. ACP_WOV_PDM_DMA_ENABLE);
  132. if ((pdm_dma_enable & 0x02) == 0x00)
  133. break;
  134. udelay(DELAY_US);
  135. }
  136. if (timeout == ACP_COUNTER)
  137. return -ETIMEDOUT;
  138. }
  139. if (pdm_enable == ACP_PDM_ENABLE) {
  140. pdm_enable = ACP_PDM_DISABLE;
  141. rn_writel(pdm_enable, acp_base + ACP_WOV_PDM_ENABLE);
  142. }
  143. rn_writel(0x01, acp_base + ACP_WOV_PDM_FIFO_FLUSH);
  144. return 0;
  145. }
  146. static void config_acp_dma(struct pdm_stream_instance *rtd, int direction)
  147. {
  148. u16 page_idx;
  149. u32 low, high, val;
  150. dma_addr_t addr;
  151. addr = rtd->dma_addr;
  152. val = 0;
  153. /* Group Enable */
  154. rn_writel(ACP_SRAM_PTE_OFFSET | BIT(31), rtd->acp_base +
  155. ACPAXI2AXI_ATU_BASE_ADDR_GRP_1);
  156. rn_writel(PAGE_SIZE_4K_ENABLE, rtd->acp_base +
  157. ACPAXI2AXI_ATU_PAGE_SIZE_GRP_1);
  158. for (page_idx = 0; page_idx < rtd->num_pages; page_idx++) {
  159. /* Load the low address of page int ACP SRAM through SRBM */
  160. low = lower_32_bits(addr);
  161. high = upper_32_bits(addr);
  162. rn_writel(low, rtd->acp_base + ACP_SCRATCH_REG_0 + val);
  163. high |= BIT(31);
  164. rn_writel(high, rtd->acp_base + ACP_SCRATCH_REG_0 + val + 4);
  165. val += 8;
  166. addr += PAGE_SIZE;
  167. }
  168. }
  169. static int acp_pdm_dma_open(struct snd_soc_component *component,
  170. struct snd_pcm_substream *substream)
  171. {
  172. struct snd_pcm_runtime *runtime;
  173. struct pdm_dev_data *adata;
  174. struct pdm_stream_instance *pdm_data;
  175. int ret;
  176. runtime = substream->runtime;
  177. adata = dev_get_drvdata(component->dev);
  178. pdm_data = kzalloc(sizeof(*pdm_data), GFP_KERNEL);
  179. if (!pdm_data)
  180. return -EINVAL;
  181. if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
  182. runtime->hw = acp_pdm_hardware_capture;
  183. ret = snd_pcm_hw_constraint_integer(runtime,
  184. SNDRV_PCM_HW_PARAM_PERIODS);
  185. if (ret < 0) {
  186. dev_err(component->dev, "set integer constraint failed\n");
  187. kfree(pdm_data);
  188. return ret;
  189. }
  190. enable_pdm_interrupts(adata->acp_base);
  191. if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
  192. adata->capture_stream = substream;
  193. pdm_data->acp_base = adata->acp_base;
  194. runtime->private_data = pdm_data;
  195. return ret;
  196. }
  197. static int acp_pdm_dma_hw_params(struct snd_soc_component *component,
  198. struct snd_pcm_substream *substream,
  199. struct snd_pcm_hw_params *params)
  200. {
  201. struct pdm_stream_instance *rtd;
  202. size_t size, period_bytes;
  203. rtd = substream->runtime->private_data;
  204. if (!rtd)
  205. return -EINVAL;
  206. size = params_buffer_bytes(params);
  207. period_bytes = params_period_bytes(params);
  208. rtd->dma_addr = substream->runtime->dma_addr;
  209. rtd->num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT);
  210. config_acp_dma(rtd, substream->stream);
  211. init_pdm_ring_buffer(MEM_WINDOW_START, size, period_bytes,
  212. rtd->acp_base);
  213. return 0;
  214. }
  215. static u64 acp_pdm_get_byte_count(struct pdm_stream_instance *rtd,
  216. int direction)
  217. {
  218. union acp_pdm_dma_count byte_count;
  219. byte_count.bcount.high =
  220. rn_readl(rtd->acp_base +
  221. ACP_WOV_RX_LINEARPOSITIONCNTR_HIGH);
  222. byte_count.bcount.low =
  223. rn_readl(rtd->acp_base +
  224. ACP_WOV_RX_LINEARPOSITIONCNTR_LOW);
  225. return byte_count.bytescount;
  226. }
  227. static snd_pcm_uframes_t acp_pdm_dma_pointer(struct snd_soc_component *comp,
  228. struct snd_pcm_substream *stream)
  229. {
  230. struct pdm_stream_instance *rtd;
  231. u32 pos, buffersize;
  232. u64 bytescount;
  233. rtd = stream->runtime->private_data;
  234. buffersize = frames_to_bytes(stream->runtime,
  235. stream->runtime->buffer_size);
  236. bytescount = acp_pdm_get_byte_count(rtd, stream->stream);
  237. if (bytescount > rtd->bytescount)
  238. bytescount -= rtd->bytescount;
  239. pos = do_div(bytescount, buffersize);
  240. return bytes_to_frames(stream->runtime, pos);
  241. }
  242. static int acp_pdm_dma_new(struct snd_soc_component *component,
  243. struct snd_soc_pcm_runtime *rtd)
  244. {
  245. struct device *parent = component->dev->parent;
  246. snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV,
  247. parent, MIN_BUFFER, MAX_BUFFER);
  248. return 0;
  249. }
  250. static int acp_pdm_dma_close(struct snd_soc_component *component,
  251. struct snd_pcm_substream *substream)
  252. {
  253. struct pdm_dev_data *adata = dev_get_drvdata(component->dev);
  254. disable_pdm_interrupts(adata->acp_base);
  255. adata->capture_stream = NULL;
  256. return 0;
  257. }
  258. static int acp_pdm_dai_trigger(struct snd_pcm_substream *substream,
  259. int cmd, struct snd_soc_dai *dai)
  260. {
  261. struct pdm_stream_instance *rtd;
  262. int ret;
  263. bool pdm_status;
  264. unsigned int ch_mask;
  265. rtd = substream->runtime->private_data;
  266. ret = 0;
  267. switch (substream->runtime->channels) {
  268. case TWO_CH:
  269. ch_mask = 0x00;
  270. break;
  271. default:
  272. return -EINVAL;
  273. }
  274. switch (cmd) {
  275. case SNDRV_PCM_TRIGGER_START:
  276. case SNDRV_PCM_TRIGGER_RESUME:
  277. case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  278. rn_writel(ch_mask, rtd->acp_base + ACP_WOV_PDM_NO_OF_CHANNELS);
  279. rn_writel(PDM_DECIMATION_FACTOR, rtd->acp_base +
  280. ACP_WOV_PDM_DECIMATION_FACTOR);
  281. rtd->bytescount = acp_pdm_get_byte_count(rtd,
  282. substream->stream);
  283. pdm_status = check_pdm_dma_status(rtd->acp_base);
  284. if (!pdm_status)
  285. ret = start_pdm_dma(rtd->acp_base);
  286. break;
  287. case SNDRV_PCM_TRIGGER_STOP:
  288. case SNDRV_PCM_TRIGGER_SUSPEND:
  289. case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  290. pdm_status = check_pdm_dma_status(rtd->acp_base);
  291. if (pdm_status)
  292. ret = stop_pdm_dma(rtd->acp_base);
  293. break;
  294. default:
  295. ret = -EINVAL;
  296. break;
  297. }
  298. return ret;
  299. }
  300. static const struct snd_soc_dai_ops acp_pdm_dai_ops = {
  301. .trigger = acp_pdm_dai_trigger,
  302. };
  303. static struct snd_soc_dai_driver acp_pdm_dai_driver = {
  304. .capture = {
  305. .rates = SNDRV_PCM_RATE_48000,
  306. .formats = SNDRV_PCM_FMTBIT_S24_LE |
  307. SNDRV_PCM_FMTBIT_S32_LE,
  308. .channels_min = 2,
  309. .channels_max = 2,
  310. .rate_min = 48000,
  311. .rate_max = 48000,
  312. },
  313. .ops = &acp_pdm_dai_ops,
  314. };
  315. static const struct snd_soc_component_driver acp_pdm_component = {
  316. .name = DRV_NAME,
  317. .open = acp_pdm_dma_open,
  318. .close = acp_pdm_dma_close,
  319. .hw_params = acp_pdm_dma_hw_params,
  320. .pointer = acp_pdm_dma_pointer,
  321. .pcm_construct = acp_pdm_dma_new,
  322. .legacy_dai_naming = 1,
  323. };
  324. static int acp_pdm_audio_probe(struct platform_device *pdev)
  325. {
  326. struct resource *res;
  327. struct pdm_dev_data *adata;
  328. unsigned int irqflags;
  329. int status;
  330. if (!pdev->dev.platform_data) {
  331. dev_err(&pdev->dev, "platform_data not retrieved\n");
  332. return -ENODEV;
  333. }
  334. irqflags = *((unsigned int *)(pdev->dev.platform_data));
  335. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  336. if (!res) {
  337. dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n");
  338. return -ENODEV;
  339. }
  340. adata = devm_kzalloc(&pdev->dev, sizeof(*adata), GFP_KERNEL);
  341. if (!adata)
  342. return -ENOMEM;
  343. adata->acp_base = devm_ioremap(&pdev->dev, res->start,
  344. resource_size(res));
  345. if (!adata->acp_base)
  346. return -ENOMEM;
  347. status = platform_get_irq(pdev, 0);
  348. if (status < 0)
  349. return status;
  350. adata->pdm_irq = status;
  351. adata->capture_stream = NULL;
  352. dev_set_drvdata(&pdev->dev, adata);
  353. status = devm_snd_soc_register_component(&pdev->dev,
  354. &acp_pdm_component,
  355. &acp_pdm_dai_driver, 1);
  356. if (status) {
  357. dev_err(&pdev->dev, "Fail to register acp pdm dai\n");
  358. return -ENODEV;
  359. }
  360. status = devm_request_irq(&pdev->dev, adata->pdm_irq, pdm_irq_handler,
  361. irqflags, "ACP_PDM_IRQ", adata);
  362. if (status) {
  363. dev_err(&pdev->dev, "ACP PDM IRQ request failed\n");
  364. return -ENODEV;
  365. }
  366. pm_runtime_set_autosuspend_delay(&pdev->dev, ACP_SUSPEND_DELAY_MS);
  367. pm_runtime_use_autosuspend(&pdev->dev);
  368. pm_runtime_enable(&pdev->dev);
  369. pm_runtime_allow(&pdev->dev);
  370. return 0;
  371. }
  372. static int acp_pdm_audio_remove(struct platform_device *pdev)
  373. {
  374. pm_runtime_disable(&pdev->dev);
  375. return 0;
  376. }
  377. static int acp_pdm_resume(struct device *dev)
  378. {
  379. struct pdm_dev_data *adata;
  380. struct snd_pcm_runtime *runtime;
  381. struct pdm_stream_instance *rtd;
  382. u32 period_bytes, buffer_len;
  383. adata = dev_get_drvdata(dev);
  384. if (adata->capture_stream && adata->capture_stream->runtime) {
  385. runtime = adata->capture_stream->runtime;
  386. rtd = runtime->private_data;
  387. period_bytes = frames_to_bytes(runtime, runtime->period_size);
  388. buffer_len = frames_to_bytes(runtime, runtime->buffer_size);
  389. config_acp_dma(rtd, SNDRV_PCM_STREAM_CAPTURE);
  390. init_pdm_ring_buffer(MEM_WINDOW_START, buffer_len, period_bytes,
  391. adata->acp_base);
  392. }
  393. enable_pdm_interrupts(adata->acp_base);
  394. return 0;
  395. }
  396. static int acp_pdm_runtime_suspend(struct device *dev)
  397. {
  398. struct pdm_dev_data *adata;
  399. adata = dev_get_drvdata(dev);
  400. disable_pdm_interrupts(adata->acp_base);
  401. return 0;
  402. }
  403. static int acp_pdm_runtime_resume(struct device *dev)
  404. {
  405. struct pdm_dev_data *adata;
  406. adata = dev_get_drvdata(dev);
  407. enable_pdm_interrupts(adata->acp_base);
  408. return 0;
  409. }
  410. static const struct dev_pm_ops acp_pdm_pm_ops = {
  411. .runtime_suspend = acp_pdm_runtime_suspend,
  412. .runtime_resume = acp_pdm_runtime_resume,
  413. .resume = acp_pdm_resume,
  414. };
  415. static struct platform_driver acp_pdm_dma_driver = {
  416. .probe = acp_pdm_audio_probe,
  417. .remove = acp_pdm_audio_remove,
  418. .driver = {
  419. .name = "acp_rn_pdm_dma",
  420. .pm = &acp_pdm_pm_ops,
  421. },
  422. };
  423. module_platform_driver(acp_pdm_dma_driver);
  424. MODULE_AUTHOR("[email protected]");
  425. MODULE_DESCRIPTION("AMD ACP3x Renior PDM Driver");
  426. MODULE_LICENSE("GPL v2");
  427. MODULE_ALIAS("platform:" DRV_NAME);