acp-platform.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
  2. //
  3. // This file is provided under a dual BSD/GPLv2 license. When using or
  4. // redistributing this file, you may do so under either license.
  5. //
  6. // Copyright(c) 2021 Advanced Micro Devices, Inc.
  7. //
  8. // Authors: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
  9. /*
  10. * Generic interface for ACP audio blck PCM component
  11. */
  12. #include <linux/platform_device.h>
  13. #include <linux/module.h>
  14. #include <linux/err.h>
  15. #include <linux/io.h>
  16. #include <sound/pcm_params.h>
  17. #include <sound/soc.h>
  18. #include <sound/soc-dai.h>
  19. #include <linux/dma-mapping.h>
  20. #include "amd.h"
  21. #include "../mach-config.h"
  22. #include "acp-mach.h"
  23. #define DRV_NAME "acp_i2s_dma"
  24. static const struct snd_pcm_hardware acp_pcm_hardware_playback = {
  25. .info = SNDRV_PCM_INFO_INTERLEAVED |
  26. SNDRV_PCM_INFO_BLOCK_TRANSFER |
  27. SNDRV_PCM_INFO_BATCH |
  28. SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
  29. SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
  30. .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
  31. SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S24_LE |
  32. SNDRV_PCM_FMTBIT_S32_LE,
  33. .channels_min = 2,
  34. .channels_max = 8,
  35. .rates = SNDRV_PCM_RATE_8000_96000,
  36. .rate_min = 8000,
  37. .rate_max = 96000,
  38. .buffer_bytes_max = PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE,
  39. .period_bytes_min = PLAYBACK_MIN_PERIOD_SIZE,
  40. .period_bytes_max = PLAYBACK_MAX_PERIOD_SIZE,
  41. .periods_min = PLAYBACK_MIN_NUM_PERIODS,
  42. .periods_max = PLAYBACK_MAX_NUM_PERIODS,
  43. };
  44. static const struct snd_pcm_hardware acp_pcm_hardware_capture = {
  45. .info = SNDRV_PCM_INFO_INTERLEAVED |
  46. SNDRV_PCM_INFO_BLOCK_TRANSFER |
  47. SNDRV_PCM_INFO_BATCH |
  48. SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
  49. SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
  50. .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
  51. SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S24_LE |
  52. SNDRV_PCM_FMTBIT_S32_LE,
  53. .channels_min = 2,
  54. .channels_max = 2,
  55. .rates = SNDRV_PCM_RATE_8000_48000,
  56. .rate_min = 8000,
  57. .rate_max = 48000,
  58. .buffer_bytes_max = CAPTURE_MAX_NUM_PERIODS * CAPTURE_MAX_PERIOD_SIZE,
  59. .period_bytes_min = CAPTURE_MIN_PERIOD_SIZE,
  60. .period_bytes_max = CAPTURE_MAX_PERIOD_SIZE,
  61. .periods_min = CAPTURE_MIN_NUM_PERIODS,
  62. .periods_max = CAPTURE_MAX_NUM_PERIODS,
  63. };
  64. static const struct snd_pcm_hardware acp6x_pcm_hardware_playback = {
  65. .info = SNDRV_PCM_INFO_INTERLEAVED |
  66. SNDRV_PCM_INFO_BLOCK_TRANSFER |
  67. SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
  68. SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
  69. .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
  70. SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S24_LE |
  71. SNDRV_PCM_FMTBIT_S32_LE,
  72. .channels_min = 2,
  73. .channels_max = 32,
  74. .rates = SNDRV_PCM_RATE_8000_192000,
  75. .rate_min = 8000,
  76. .rate_max = 192000,
  77. .buffer_bytes_max = PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE,
  78. .period_bytes_min = PLAYBACK_MIN_PERIOD_SIZE,
  79. .period_bytes_max = PLAYBACK_MAX_PERIOD_SIZE,
  80. .periods_min = PLAYBACK_MIN_NUM_PERIODS,
  81. .periods_max = PLAYBACK_MAX_NUM_PERIODS,
  82. };
  83. static const struct snd_pcm_hardware acp6x_pcm_hardware_capture = {
  84. .info = SNDRV_PCM_INFO_INTERLEAVED |
  85. SNDRV_PCM_INFO_BLOCK_TRANSFER |
  86. SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
  87. SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
  88. .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
  89. SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S24_LE |
  90. SNDRV_PCM_FMTBIT_S32_LE,
  91. .channels_min = 2,
  92. .channels_max = 32,
  93. .rates = SNDRV_PCM_RATE_8000_192000,
  94. .rate_min = 8000,
  95. .rate_max = 192000,
  96. .buffer_bytes_max = CAPTURE_MAX_NUM_PERIODS * CAPTURE_MAX_PERIOD_SIZE,
  97. .period_bytes_min = CAPTURE_MIN_PERIOD_SIZE,
  98. .period_bytes_max = CAPTURE_MAX_PERIOD_SIZE,
  99. .periods_min = CAPTURE_MIN_NUM_PERIODS,
  100. .periods_max = CAPTURE_MAX_NUM_PERIODS,
  101. };
  102. int acp_machine_select(struct acp_dev_data *adata)
  103. {
  104. struct snd_soc_acpi_mach *mach;
  105. int size, platform;
  106. if (adata->flag == FLAG_AMD_LEGACY_ONLY_DMIC) {
  107. platform = adata->platform;
  108. adata->mach_dev = platform_device_register_data(adata->dev, "acp-pdm-mach",
  109. PLATFORM_DEVID_NONE, &platform,
  110. sizeof(platform));
  111. } else {
  112. size = sizeof(*adata->machines);
  113. mach = snd_soc_acpi_find_machine(adata->machines);
  114. if (!mach) {
  115. dev_err(adata->dev, "warning: No matching ASoC machine driver found\n");
  116. return -EINVAL;
  117. }
  118. adata->mach_dev = platform_device_register_data(adata->dev, mach->drv_name,
  119. PLATFORM_DEVID_NONE, mach, size);
  120. }
  121. if (IS_ERR(adata->mach_dev))
  122. dev_warn(adata->dev, "Unable to register Machine device\n");
  123. return 0;
  124. }
  125. EXPORT_SYMBOL_NS_GPL(acp_machine_select, SND_SOC_ACP_COMMON);
  126. static irqreturn_t i2s_irq_handler(int irq, void *data)
  127. {
  128. struct acp_dev_data *adata = data;
  129. struct acp_resource *rsrc = adata->rsrc;
  130. struct acp_stream *stream;
  131. u16 i2s_flag = 0;
  132. u32 ext_intr_stat, ext_intr_stat1;
  133. if (!adata)
  134. return IRQ_NONE;
  135. if (adata->rsrc->no_of_ctrls == 2)
  136. ext_intr_stat1 = readl(ACP_EXTERNAL_INTR_STAT(adata, (rsrc->irqp_used - 1)));
  137. ext_intr_stat = readl(ACP_EXTERNAL_INTR_STAT(adata, rsrc->irqp_used));
  138. spin_lock(&adata->acp_lock);
  139. list_for_each_entry(stream, &adata->stream_list, list) {
  140. if (ext_intr_stat & stream->irq_bit) {
  141. writel(stream->irq_bit,
  142. ACP_EXTERNAL_INTR_STAT(adata, rsrc->irqp_used));
  143. snd_pcm_period_elapsed(stream->substream);
  144. i2s_flag = 1;
  145. }
  146. if (adata->rsrc->no_of_ctrls == 2) {
  147. if (ext_intr_stat1 & stream->irq_bit) {
  148. writel(stream->irq_bit, ACP_EXTERNAL_INTR_STAT(adata,
  149. (rsrc->irqp_used - 1)));
  150. snd_pcm_period_elapsed(stream->substream);
  151. i2s_flag = 1;
  152. }
  153. }
  154. }
  155. spin_unlock(&adata->acp_lock);
  156. if (i2s_flag)
  157. return IRQ_HANDLED;
  158. return IRQ_NONE;
  159. }
  160. void config_pte_for_stream(struct acp_dev_data *adata, struct acp_stream *stream)
  161. {
  162. struct acp_resource *rsrc = adata->rsrc;
  163. u32 reg_val;
  164. reg_val = rsrc->sram_pte_offset;
  165. stream->reg_offset = 0x02000000;
  166. writel((reg_val + GRP1_OFFSET) | BIT(31), adata->acp_base + ACPAXI2AXI_ATU_BASE_ADDR_GRP_1);
  167. writel(PAGE_SIZE_4K_ENABLE, adata->acp_base + ACPAXI2AXI_ATU_PAGE_SIZE_GRP_1);
  168. writel((reg_val + GRP2_OFFSET) | BIT(31), adata->acp_base + ACPAXI2AXI_ATU_BASE_ADDR_GRP_2);
  169. writel(PAGE_SIZE_4K_ENABLE, adata->acp_base + ACPAXI2AXI_ATU_PAGE_SIZE_GRP_2);
  170. writel(reg_val | BIT(31), adata->acp_base + ACPAXI2AXI_ATU_BASE_ADDR_GRP_5);
  171. writel(PAGE_SIZE_4K_ENABLE, adata->acp_base + ACPAXI2AXI_ATU_PAGE_SIZE_GRP_5);
  172. writel(0x01, adata->acp_base + ACPAXI2AXI_ATU_CTRL);
  173. }
  174. EXPORT_SYMBOL_NS_GPL(config_pte_for_stream, SND_SOC_ACP_COMMON);
  175. void config_acp_dma(struct acp_dev_data *adata, struct acp_stream *stream, int size)
  176. {
  177. struct snd_pcm_substream *substream = stream->substream;
  178. struct acp_resource *rsrc = adata->rsrc;
  179. dma_addr_t addr = substream->dma_buffer.addr;
  180. int num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT);
  181. u32 low, high, val;
  182. u16 page_idx;
  183. switch (adata->platform) {
  184. case ACP70:
  185. case ACP71:
  186. switch (stream->dai_id) {
  187. case I2S_SP_INSTANCE:
  188. if (stream->dir == SNDRV_PCM_STREAM_PLAYBACK)
  189. val = 0x0;
  190. else
  191. val = 0x1000;
  192. break;
  193. case I2S_BT_INSTANCE:
  194. if (stream->dir == SNDRV_PCM_STREAM_PLAYBACK)
  195. val = 0x2000;
  196. else
  197. val = 0x3000;
  198. break;
  199. case I2S_HS_INSTANCE:
  200. if (stream->dir == SNDRV_PCM_STREAM_PLAYBACK)
  201. val = 0x4000;
  202. else
  203. val = 0x5000;
  204. break;
  205. case DMIC_INSTANCE:
  206. val = 0x6000;
  207. break;
  208. default:
  209. dev_err(adata->dev, "Invalid dai id %x\n", stream->dai_id);
  210. return;
  211. }
  212. break;
  213. default:
  214. val = stream->pte_offset;
  215. break;
  216. }
  217. for (page_idx = 0; page_idx < num_pages; page_idx++) {
  218. /* Load the low address of page int ACP SRAM through SRBM */
  219. low = lower_32_bits(addr);
  220. high = upper_32_bits(addr);
  221. writel(low, adata->acp_base + rsrc->scratch_reg_offset + val);
  222. high |= BIT(31);
  223. writel(high, adata->acp_base + rsrc->scratch_reg_offset + val + 4);
  224. /* Move to next physically contiguous page */
  225. val += 8;
  226. addr += PAGE_SIZE;
  227. }
  228. }
  229. EXPORT_SYMBOL_NS_GPL(config_acp_dma, SND_SOC_ACP_COMMON);
  230. static int acp_dma_open(struct snd_soc_component *component, struct snd_pcm_substream *substream)
  231. {
  232. struct snd_pcm_runtime *runtime = substream->runtime;
  233. struct device *dev = component->dev;
  234. struct acp_dev_data *adata = dev_get_drvdata(dev);
  235. struct acp_chip_info *chip;
  236. struct acp_stream *stream;
  237. int ret;
  238. stream = kzalloc(sizeof(*stream), GFP_KERNEL);
  239. if (!stream)
  240. return -ENOMEM;
  241. stream->substream = substream;
  242. chip = dev_get_platdata(dev);
  243. switch (chip->acp_rev) {
  244. case ACP63_DEV:
  245. case ACP70_DEV:
  246. case ACP71_DEV:
  247. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  248. runtime->hw = acp6x_pcm_hardware_playback;
  249. else
  250. runtime->hw = acp6x_pcm_hardware_capture;
  251. break;
  252. default:
  253. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  254. runtime->hw = acp_pcm_hardware_playback;
  255. else
  256. runtime->hw = acp_pcm_hardware_capture;
  257. break;
  258. }
  259. ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, DMA_SIZE);
  260. if (ret) {
  261. dev_err(component->dev, "set hw constraint HW_PARAM_PERIOD_BYTES failed\n");
  262. kfree(stream);
  263. return ret;
  264. }
  265. ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, DMA_SIZE);
  266. if (ret) {
  267. dev_err(component->dev, "set hw constraint HW_PARAM_BUFFER_BYTES failed\n");
  268. kfree(stream);
  269. return ret;
  270. }
  271. ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
  272. if (ret < 0) {
  273. dev_err(component->dev, "set integer constraint failed\n");
  274. kfree(stream);
  275. return ret;
  276. }
  277. runtime->private_data = stream;
  278. writel(1, ACP_EXTERNAL_INTR_ENB(adata));
  279. spin_lock_irq(&adata->acp_lock);
  280. list_add_tail(&stream->list, &adata->stream_list);
  281. spin_unlock_irq(&adata->acp_lock);
  282. return ret;
  283. }
  284. static int acp_dma_hw_params(struct snd_soc_component *component,
  285. struct snd_pcm_substream *substream,
  286. struct snd_pcm_hw_params *params)
  287. {
  288. struct acp_dev_data *adata = snd_soc_component_get_drvdata(component);
  289. struct acp_stream *stream = substream->runtime->private_data;
  290. u64 size = params_buffer_bytes(params);
  291. /* Configure ACP DMA block with params */
  292. config_pte_for_stream(adata, stream);
  293. config_acp_dma(adata, stream, size);
  294. return 0;
  295. }
  296. static snd_pcm_uframes_t acp_dma_pointer(struct snd_soc_component *component,
  297. struct snd_pcm_substream *substream)
  298. {
  299. struct device *dev = component->dev;
  300. struct acp_dev_data *adata = dev_get_drvdata(dev);
  301. struct acp_stream *stream = substream->runtime->private_data;
  302. u32 pos, buffersize;
  303. u64 bytescount;
  304. buffersize = frames_to_bytes(substream->runtime,
  305. substream->runtime->buffer_size);
  306. bytescount = acp_get_byte_count(adata, stream->dai_id, substream->stream);
  307. if (bytescount > stream->bytescount)
  308. bytescount -= stream->bytescount;
  309. pos = do_div(bytescount, buffersize);
  310. return bytes_to_frames(substream->runtime, pos);
  311. }
  312. static int acp_dma_new(struct snd_soc_component *component,
  313. struct snd_soc_pcm_runtime *rtd)
  314. {
  315. struct device *parent = component->dev->parent;
  316. snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV,
  317. parent, MIN_BUFFER, MAX_BUFFER);
  318. return 0;
  319. }
  320. static int acp_dma_close(struct snd_soc_component *component,
  321. struct snd_pcm_substream *substream)
  322. {
  323. struct device *dev = component->dev;
  324. struct acp_dev_data *adata = dev_get_drvdata(dev);
  325. struct acp_stream *stream = substream->runtime->private_data;
  326. /* Remove entry from list */
  327. spin_lock_irq(&adata->acp_lock);
  328. list_del(&stream->list);
  329. spin_unlock_irq(&adata->acp_lock);
  330. kfree(stream);
  331. return 0;
  332. }
  333. static const struct snd_soc_component_driver acp_pcm_component = {
  334. .name = DRV_NAME,
  335. .open = acp_dma_open,
  336. .close = acp_dma_close,
  337. .hw_params = acp_dma_hw_params,
  338. .pointer = acp_dma_pointer,
  339. .pcm_construct = acp_dma_new,
  340. .legacy_dai_naming = 1,
  341. };
  342. int acp_platform_register(struct device *dev)
  343. {
  344. struct acp_dev_data *adata = dev_get_drvdata(dev);
  345. struct snd_soc_dai_driver;
  346. unsigned int status;
  347. status = devm_request_irq(dev, adata->i2s_irq, i2s_irq_handler,
  348. IRQF_SHARED, "ACP_I2S_IRQ", adata);
  349. if (status) {
  350. dev_err(dev, "ACP I2S IRQ request failed\n");
  351. return status;
  352. }
  353. status = devm_snd_soc_register_component(dev, &acp_pcm_component,
  354. adata->dai_driver,
  355. adata->num_dai);
  356. if (status) {
  357. dev_err(dev, "Fail to register acp i2s component\n");
  358. return status;
  359. }
  360. INIT_LIST_HEAD(&adata->stream_list);
  361. spin_lock_init(&adata->acp_lock);
  362. return 0;
  363. }
  364. EXPORT_SYMBOL_NS_GPL(acp_platform_register, SND_SOC_ACP_COMMON);
  365. int acp_platform_unregister(struct device *dev)
  366. {
  367. struct acp_dev_data *adata = dev_get_drvdata(dev);
  368. if (adata->mach_dev)
  369. platform_device_unregister(adata->mach_dev);
  370. return 0;
  371. }
  372. EXPORT_SYMBOL_NS_GPL(acp_platform_unregister, SND_SOC_ACP_COMMON);
  373. MODULE_DESCRIPTION("AMD ACP PCM Driver");
  374. MODULE_LICENSE("Dual BSD/GPL");
  375. MODULE_ALIAS(DRV_NAME);