acp-legacy-common.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  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) 2023 Advanced Micro Devices, Inc.
  7. //
  8. // Authors: Syed Saba Kareem <Syed.SabaKareem@amd.com>
  9. //
  10. /*
  11. * Common file to be used by amd platforms
  12. */
  13. #include "amd.h"
  14. #include <linux/pci.h>
  15. #include <linux/export.h>
  16. #define ACP_RENOIR_PDM_ADDR 0x02
  17. #define ACP_REMBRANDT_PDM_ADDR 0x03
  18. #define ACP63_PDM_ADDR 0x02
  19. #define ACP70_PDM_ADDR 0x02
  20. void acp_enable_interrupts(struct acp_dev_data *adata)
  21. {
  22. struct acp_resource *rsrc = adata->rsrc;
  23. u32 ext_intr_ctrl;
  24. writel(0x01, ACP_EXTERNAL_INTR_ENB(adata));
  25. ext_intr_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
  26. ext_intr_ctrl |= ACP_ERROR_MASK;
  27. writel(ext_intr_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
  28. }
  29. EXPORT_SYMBOL_NS_GPL(acp_enable_interrupts, SND_SOC_ACP_COMMON);
  30. void acp_disable_interrupts(struct acp_dev_data *adata)
  31. {
  32. struct acp_resource *rsrc = adata->rsrc;
  33. writel(ACP_EXT_INTR_STAT_CLEAR_MASK, ACP_EXTERNAL_INTR_STAT(adata, rsrc->irqp_used));
  34. writel(0x00, ACP_EXTERNAL_INTR_ENB(adata));
  35. }
  36. EXPORT_SYMBOL_NS_GPL(acp_disable_interrupts, SND_SOC_ACP_COMMON);
  37. static void set_acp_pdm_ring_buffer(struct snd_pcm_substream *substream,
  38. struct snd_soc_dai *dai)
  39. {
  40. struct snd_pcm_runtime *runtime = substream->runtime;
  41. struct acp_stream *stream = runtime->private_data;
  42. struct device *dev = dai->component->dev;
  43. struct acp_dev_data *adata = dev_get_drvdata(dev);
  44. u32 physical_addr, pdm_size, period_bytes;
  45. period_bytes = frames_to_bytes(runtime, runtime->period_size);
  46. pdm_size = frames_to_bytes(runtime, runtime->buffer_size);
  47. physical_addr = stream->reg_offset + MEM_WINDOW_START;
  48. /* Init ACP PDM Ring buffer */
  49. writel(physical_addr, adata->acp_base + ACP_WOV_RX_RINGBUFADDR);
  50. writel(pdm_size, adata->acp_base + ACP_WOV_RX_RINGBUFSIZE);
  51. writel(period_bytes, adata->acp_base + ACP_WOV_RX_INTR_WATERMARK_SIZE);
  52. writel(0x01, adata->acp_base + ACPAXI2AXI_ATU_CTRL);
  53. }
  54. static void set_acp_pdm_clk(struct snd_pcm_substream *substream,
  55. struct snd_soc_dai *dai)
  56. {
  57. struct device *dev = dai->component->dev;
  58. struct acp_dev_data *adata = dev_get_drvdata(dev);
  59. unsigned int pdm_ctrl;
  60. /* Enable default ACP PDM clk */
  61. writel(PDM_CLK_FREQ_MASK, adata->acp_base + ACP_WOV_CLK_CTRL);
  62. pdm_ctrl = readl(adata->acp_base + ACP_WOV_MISC_CTRL);
  63. pdm_ctrl |= PDM_MISC_CTRL_MASK;
  64. writel(pdm_ctrl, adata->acp_base + ACP_WOV_MISC_CTRL);
  65. set_acp_pdm_ring_buffer(substream, dai);
  66. }
  67. void restore_acp_pdm_params(struct snd_pcm_substream *substream,
  68. struct acp_dev_data *adata)
  69. {
  70. struct snd_soc_dai *dai;
  71. struct snd_soc_pcm_runtime *soc_runtime;
  72. u32 ext_int_ctrl;
  73. soc_runtime = snd_soc_substream_to_rtd(substream);
  74. dai = snd_soc_rtd_to_cpu(soc_runtime, 0);
  75. /* Programming channel mask and sampling rate */
  76. writel(adata->ch_mask, adata->acp_base + ACP_WOV_PDM_NO_OF_CHANNELS);
  77. writel(PDM_DEC_64, adata->acp_base + ACP_WOV_PDM_DECIMATION_FACTOR);
  78. /* Enabling ACP Pdm interuppts */
  79. ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, 0));
  80. ext_int_ctrl |= PDM_DMA_INTR_MASK;
  81. writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, 0));
  82. set_acp_pdm_clk(substream, dai);
  83. }
  84. EXPORT_SYMBOL_NS_GPL(restore_acp_pdm_params, SND_SOC_ACP_COMMON);
  85. static int set_acp_i2s_dma_fifo(struct snd_pcm_substream *substream,
  86. struct snd_soc_dai *dai)
  87. {
  88. struct device *dev = dai->component->dev;
  89. struct acp_dev_data *adata = dev_get_drvdata(dev);
  90. struct acp_resource *rsrc = adata->rsrc;
  91. struct acp_stream *stream = substream->runtime->private_data;
  92. u32 reg_dma_size, reg_fifo_size, reg_fifo_addr;
  93. u32 phy_addr, acp_fifo_addr, ext_int_ctrl;
  94. unsigned int dir = substream->stream;
  95. switch (dai->driver->id) {
  96. case I2S_SP_INSTANCE:
  97. if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
  98. reg_dma_size = ACP_I2S_TX_DMA_SIZE(adata);
  99. acp_fifo_addr = rsrc->sram_pte_offset +
  100. SP_PB_FIFO_ADDR_OFFSET;
  101. reg_fifo_addr = ACP_I2S_TX_FIFOADDR(adata);
  102. reg_fifo_size = ACP_I2S_TX_FIFOSIZE(adata);
  103. phy_addr = I2S_SP_TX_MEM_WINDOW_START + stream->reg_offset;
  104. writel(phy_addr, adata->acp_base + ACP_I2S_TX_RINGBUFADDR(adata));
  105. } else {
  106. reg_dma_size = ACP_I2S_RX_DMA_SIZE(adata);
  107. acp_fifo_addr = rsrc->sram_pte_offset +
  108. SP_CAPT_FIFO_ADDR_OFFSET;
  109. reg_fifo_addr = ACP_I2S_RX_FIFOADDR(adata);
  110. reg_fifo_size = ACP_I2S_RX_FIFOSIZE(adata);
  111. phy_addr = I2S_SP_RX_MEM_WINDOW_START + stream->reg_offset;
  112. writel(phy_addr, adata->acp_base + ACP_I2S_RX_RINGBUFADDR(adata));
  113. }
  114. break;
  115. case I2S_BT_INSTANCE:
  116. if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
  117. reg_dma_size = ACP_BT_TX_DMA_SIZE(adata);
  118. acp_fifo_addr = rsrc->sram_pte_offset +
  119. BT_PB_FIFO_ADDR_OFFSET;
  120. reg_fifo_addr = ACP_BT_TX_FIFOADDR(adata);
  121. reg_fifo_size = ACP_BT_TX_FIFOSIZE(adata);
  122. phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset;
  123. writel(phy_addr, adata->acp_base + ACP_BT_TX_RINGBUFADDR(adata));
  124. } else {
  125. reg_dma_size = ACP_BT_RX_DMA_SIZE(adata);
  126. acp_fifo_addr = rsrc->sram_pte_offset +
  127. BT_CAPT_FIFO_ADDR_OFFSET;
  128. reg_fifo_addr = ACP_BT_RX_FIFOADDR(adata);
  129. reg_fifo_size = ACP_BT_RX_FIFOSIZE(adata);
  130. phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset;
  131. writel(phy_addr, adata->acp_base + ACP_BT_RX_RINGBUFADDR(adata));
  132. }
  133. break;
  134. case I2S_HS_INSTANCE:
  135. if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
  136. reg_dma_size = ACP_HS_TX_DMA_SIZE;
  137. acp_fifo_addr = rsrc->sram_pte_offset +
  138. HS_PB_FIFO_ADDR_OFFSET;
  139. reg_fifo_addr = ACP_HS_TX_FIFOADDR;
  140. reg_fifo_size = ACP_HS_TX_FIFOSIZE;
  141. phy_addr = I2S_HS_TX_MEM_WINDOW_START + stream->reg_offset;
  142. writel(phy_addr, adata->acp_base + ACP_HS_TX_RINGBUFADDR);
  143. } else {
  144. reg_dma_size = ACP_HS_RX_DMA_SIZE;
  145. acp_fifo_addr = rsrc->sram_pte_offset +
  146. HS_CAPT_FIFO_ADDR_OFFSET;
  147. reg_fifo_addr = ACP_HS_RX_FIFOADDR;
  148. reg_fifo_size = ACP_HS_RX_FIFOSIZE;
  149. phy_addr = I2S_HS_RX_MEM_WINDOW_START + stream->reg_offset;
  150. writel(phy_addr, adata->acp_base + ACP_HS_RX_RINGBUFADDR);
  151. }
  152. break;
  153. default:
  154. dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
  155. return -EINVAL;
  156. }
  157. writel(DMA_SIZE, adata->acp_base + reg_dma_size);
  158. writel(acp_fifo_addr, adata->acp_base + reg_fifo_addr);
  159. writel(FIFO_SIZE, adata->acp_base + reg_fifo_size);
  160. ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
  161. ext_int_ctrl |= BIT(I2S_RX_THRESHOLD(rsrc->offset)) |
  162. BIT(BT_RX_THRESHOLD(rsrc->offset)) |
  163. BIT(I2S_TX_THRESHOLD(rsrc->offset)) |
  164. BIT(BT_TX_THRESHOLD(rsrc->offset)) |
  165. BIT(HS_RX_THRESHOLD(rsrc->offset)) |
  166. BIT(HS_TX_THRESHOLD(rsrc->offset));
  167. writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
  168. return 0;
  169. }
  170. int restore_acp_i2s_params(struct snd_pcm_substream *substream,
  171. struct acp_dev_data *adata,
  172. struct acp_stream *stream)
  173. {
  174. struct snd_soc_dai *dai;
  175. struct snd_soc_pcm_runtime *soc_runtime;
  176. u32 tdm_fmt, reg_val, fmt_reg, val;
  177. soc_runtime = snd_soc_substream_to_rtd(substream);
  178. dai = snd_soc_rtd_to_cpu(soc_runtime, 0);
  179. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  180. tdm_fmt = adata->tdm_tx_fmt[stream->dai_id - 1];
  181. switch (stream->dai_id) {
  182. case I2S_BT_INSTANCE:
  183. reg_val = ACP_BTTDM_ITER;
  184. fmt_reg = ACP_BTTDM_TXFRMT;
  185. break;
  186. case I2S_SP_INSTANCE:
  187. reg_val = ACP_I2STDM_ITER;
  188. fmt_reg = ACP_I2STDM_TXFRMT;
  189. break;
  190. case I2S_HS_INSTANCE:
  191. reg_val = ACP_HSTDM_ITER;
  192. fmt_reg = ACP_HSTDM_TXFRMT;
  193. break;
  194. default:
  195. pr_err("Invalid dai id %x\n", stream->dai_id);
  196. return -EINVAL;
  197. }
  198. val = adata->xfer_tx_resolution[stream->dai_id - 1] << 3;
  199. } else {
  200. tdm_fmt = adata->tdm_rx_fmt[stream->dai_id - 1];
  201. switch (stream->dai_id) {
  202. case I2S_BT_INSTANCE:
  203. reg_val = ACP_BTTDM_IRER;
  204. fmt_reg = ACP_BTTDM_RXFRMT;
  205. break;
  206. case I2S_SP_INSTANCE:
  207. reg_val = ACP_I2STDM_IRER;
  208. fmt_reg = ACP_I2STDM_RXFRMT;
  209. break;
  210. case I2S_HS_INSTANCE:
  211. reg_val = ACP_HSTDM_IRER;
  212. fmt_reg = ACP_HSTDM_RXFRMT;
  213. break;
  214. default:
  215. pr_err("Invalid dai id %x\n", stream->dai_id);
  216. return -EINVAL;
  217. }
  218. val = adata->xfer_rx_resolution[stream->dai_id - 1] << 3;
  219. }
  220. writel(val, adata->acp_base + reg_val);
  221. if (adata->tdm_mode == TDM_ENABLE) {
  222. writel(tdm_fmt, adata->acp_base + fmt_reg);
  223. val = readl(adata->acp_base + reg_val);
  224. writel(val | 0x2, adata->acp_base + reg_val);
  225. }
  226. return set_acp_i2s_dma_fifo(substream, dai);
  227. }
  228. EXPORT_SYMBOL_NS_GPL(restore_acp_i2s_params, SND_SOC_ACP_COMMON);
  229. static int acp_power_on(struct acp_chip_info *chip)
  230. {
  231. u32 val, acp_pgfsm_stat_reg, acp_pgfsm_ctrl_reg;
  232. void __iomem *base;
  233. base = chip->base;
  234. switch (chip->acp_rev) {
  235. case ACP3X_DEV:
  236. acp_pgfsm_stat_reg = ACP_PGFSM_STATUS;
  237. acp_pgfsm_ctrl_reg = ACP_PGFSM_CONTROL;
  238. break;
  239. case ACP6X_DEV:
  240. acp_pgfsm_stat_reg = ACP6X_PGFSM_STATUS;
  241. acp_pgfsm_ctrl_reg = ACP6X_PGFSM_CONTROL;
  242. break;
  243. case ACP63_DEV:
  244. acp_pgfsm_stat_reg = ACP63_PGFSM_STATUS;
  245. acp_pgfsm_ctrl_reg = ACP63_PGFSM_CONTROL;
  246. break;
  247. case ACP70_DEV:
  248. case ACP71_DEV:
  249. acp_pgfsm_stat_reg = ACP70_PGFSM_STATUS;
  250. acp_pgfsm_ctrl_reg = ACP70_PGFSM_CONTROL;
  251. break;
  252. default:
  253. return -EINVAL;
  254. }
  255. val = readl(base + acp_pgfsm_stat_reg);
  256. if (val == ACP_POWERED_ON)
  257. return 0;
  258. if ((val & ACP_PGFSM_STATUS_MASK) != ACP_POWER_ON_IN_PROGRESS)
  259. writel(ACP_PGFSM_CNTL_POWER_ON_MASK, base + acp_pgfsm_ctrl_reg);
  260. return readl_poll_timeout(base + acp_pgfsm_stat_reg, val,
  261. !val, DELAY_US, ACP_TIMEOUT);
  262. }
  263. static int acp_reset(void __iomem *base)
  264. {
  265. u32 val;
  266. int ret;
  267. writel(1, base + ACP_SOFT_RESET);
  268. ret = readl_poll_timeout(base + ACP_SOFT_RESET, val, val & ACP_SOFT_RST_DONE_MASK,
  269. DELAY_US, ACP_TIMEOUT);
  270. if (ret)
  271. return ret;
  272. writel(0, base + ACP_SOFT_RESET);
  273. return readl_poll_timeout(base + ACP_SOFT_RESET, val, !val, DELAY_US, ACP_TIMEOUT);
  274. }
  275. int acp_init(struct acp_chip_info *chip)
  276. {
  277. int ret;
  278. /* power on */
  279. ret = acp_power_on(chip);
  280. if (ret) {
  281. pr_err("ACP power on failed\n");
  282. return ret;
  283. }
  284. writel(0x01, chip->base + ACP_CONTROL);
  285. /* Reset */
  286. ret = acp_reset(chip->base);
  287. if (ret) {
  288. pr_err("ACP reset failed\n");
  289. return ret;
  290. }
  291. if (chip->acp_rev >= ACP70_DEV)
  292. writel(0, chip->base + ACP_ZSC_DSP_CTRL);
  293. return 0;
  294. }
  295. EXPORT_SYMBOL_NS_GPL(acp_init, SND_SOC_ACP_COMMON);
  296. int acp_deinit(struct acp_chip_info *chip)
  297. {
  298. int ret;
  299. /* Reset */
  300. ret = acp_reset(chip->base);
  301. if (ret)
  302. return ret;
  303. if (chip->acp_rev < ACP70_DEV)
  304. writel(0, chip->base + ACP_CONTROL);
  305. else
  306. writel(0x01, chip->base + ACP_ZSC_DSP_CTRL);
  307. return 0;
  308. }
  309. EXPORT_SYMBOL_NS_GPL(acp_deinit, SND_SOC_ACP_COMMON);
  310. int smn_write(struct pci_dev *dev, u32 smn_addr, u32 data)
  311. {
  312. pci_write_config_dword(dev, 0x60, smn_addr);
  313. pci_write_config_dword(dev, 0x64, data);
  314. return 0;
  315. }
  316. EXPORT_SYMBOL_NS_GPL(smn_write, SND_SOC_ACP_COMMON);
  317. int smn_read(struct pci_dev *dev, u32 smn_addr)
  318. {
  319. u32 data;
  320. pci_write_config_dword(dev, 0x60, smn_addr);
  321. pci_read_config_dword(dev, 0x64, &data);
  322. return data;
  323. }
  324. EXPORT_SYMBOL_NS_GPL(smn_read, SND_SOC_ACP_COMMON);
  325. static void check_acp3x_config(struct acp_chip_info *chip)
  326. {
  327. u32 val;
  328. val = readl(chip->base + ACP3X_PIN_CONFIG);
  329. switch (val) {
  330. case ACP_CONFIG_4:
  331. chip->is_i2s_config = true;
  332. chip->is_pdm_config = true;
  333. break;
  334. default:
  335. chip->is_pdm_config = true;
  336. break;
  337. }
  338. }
  339. static void check_acp6x_config(struct acp_chip_info *chip)
  340. {
  341. u32 val;
  342. val = readl(chip->base + ACP_PIN_CONFIG);
  343. switch (val) {
  344. case ACP_CONFIG_4:
  345. case ACP_CONFIG_5:
  346. case ACP_CONFIG_6:
  347. case ACP_CONFIG_7:
  348. case ACP_CONFIG_8:
  349. case ACP_CONFIG_11:
  350. case ACP_CONFIG_14:
  351. chip->is_pdm_config = true;
  352. break;
  353. case ACP_CONFIG_9:
  354. chip->is_i2s_config = true;
  355. break;
  356. case ACP_CONFIG_10:
  357. case ACP_CONFIG_12:
  358. case ACP_CONFIG_13:
  359. chip->is_i2s_config = true;
  360. chip->is_pdm_config = true;
  361. break;
  362. default:
  363. break;
  364. }
  365. }
  366. static void check_acp70_config(struct acp_chip_info *chip)
  367. {
  368. u32 val;
  369. val = readl(chip->base + ACP_PIN_CONFIG);
  370. switch (val) {
  371. case ACP_CONFIG_4:
  372. case ACP_CONFIG_5:
  373. case ACP_CONFIG_6:
  374. case ACP_CONFIG_7:
  375. case ACP_CONFIG_8:
  376. case ACP_CONFIG_11:
  377. case ACP_CONFIG_14:
  378. case ACP_CONFIG_17:
  379. case ACP_CONFIG_18:
  380. chip->is_pdm_config = true;
  381. break;
  382. case ACP_CONFIG_9:
  383. chip->is_i2s_config = true;
  384. break;
  385. case ACP_CONFIG_10:
  386. case ACP_CONFIG_12:
  387. case ACP_CONFIG_13:
  388. case ACP_CONFIG_19:
  389. case ACP_CONFIG_20:
  390. chip->is_i2s_config = true;
  391. chip->is_pdm_config = true;
  392. break;
  393. default:
  394. break;
  395. }
  396. }
  397. void check_acp_config(struct pci_dev *pci, struct acp_chip_info *chip)
  398. {
  399. struct acpi_device *pdm_dev;
  400. const union acpi_object *obj;
  401. u32 pdm_addr;
  402. switch (chip->acp_rev) {
  403. case ACP3X_DEV:
  404. pdm_addr = ACP_RENOIR_PDM_ADDR;
  405. check_acp3x_config(chip);
  406. break;
  407. case ACP6X_DEV:
  408. pdm_addr = ACP_REMBRANDT_PDM_ADDR;
  409. check_acp6x_config(chip);
  410. break;
  411. case ACP63_DEV:
  412. pdm_addr = ACP63_PDM_ADDR;
  413. check_acp6x_config(chip);
  414. break;
  415. case ACP70_DEV:
  416. case ACP71_DEV:
  417. pdm_addr = ACP70_PDM_ADDR;
  418. check_acp70_config(chip);
  419. break;
  420. default:
  421. break;
  422. }
  423. if (chip->is_pdm_config) {
  424. pdm_dev = acpi_find_child_device(ACPI_COMPANION(&pci->dev), pdm_addr, 0);
  425. if (pdm_dev) {
  426. if (!acpi_dev_get_property(pdm_dev, "acp-audio-device-type",
  427. ACPI_TYPE_INTEGER, &obj) &&
  428. obj->integer.value == pdm_addr)
  429. chip->is_pdm_dev = true;
  430. }
  431. }
  432. }
  433. EXPORT_SYMBOL_NS_GPL(check_acp_config, SND_SOC_ACP_COMMON);
  434. MODULE_DESCRIPTION("AMD ACP legacy common features");
  435. MODULE_LICENSE("Dual BSD/GPL");