acp-stream.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  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 <[email protected]>
  9. /*
  10. * Hardware interface for generic AMD audio DSP ACP IP
  11. */
  12. #include "../ops.h"
  13. #include "acp-dsp-offset.h"
  14. #include "acp.h"
  15. #define PTE_GRP1_OFFSET 0x00000000
  16. #define PTE_GRP2_OFFSET 0x00800000
  17. #define PTE_GRP3_OFFSET 0x01000000
  18. #define PTE_GRP4_OFFSET 0x01800000
  19. #define PTE_GRP5_OFFSET 0x02000000
  20. #define PTE_GRP6_OFFSET 0x02800000
  21. #define PTE_GRP7_OFFSET 0x03000000
  22. #define PTE_GRP8_OFFSET 0x03800000
  23. int acp_dsp_stream_config(struct snd_sof_dev *sdev, struct acp_dsp_stream *stream)
  24. {
  25. const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata);
  26. unsigned int pte_reg, pte_size, phy_addr_offset, index;
  27. int stream_tag = stream->stream_tag;
  28. u32 low, high, offset, reg_val;
  29. dma_addr_t addr;
  30. int page_idx;
  31. switch (stream_tag) {
  32. case 1:
  33. pte_reg = ACPAXI2AXI_ATU_BASE_ADDR_GRP_1;
  34. pte_size = ACPAXI2AXI_ATU_PAGE_SIZE_GRP_1;
  35. offset = offsetof(struct scratch_reg_conf, grp1_pte);
  36. stream->reg_offset = PTE_GRP1_OFFSET;
  37. break;
  38. case 2:
  39. pte_reg = ACPAXI2AXI_ATU_BASE_ADDR_GRP_2;
  40. pte_size = ACPAXI2AXI_ATU_PAGE_SIZE_GRP_2;
  41. offset = offsetof(struct scratch_reg_conf, grp2_pte);
  42. stream->reg_offset = PTE_GRP2_OFFSET;
  43. break;
  44. case 3:
  45. pte_reg = ACPAXI2AXI_ATU_BASE_ADDR_GRP_3;
  46. pte_size = ACPAXI2AXI_ATU_PAGE_SIZE_GRP_3;
  47. offset = offsetof(struct scratch_reg_conf, grp3_pte);
  48. stream->reg_offset = PTE_GRP3_OFFSET;
  49. break;
  50. case 4:
  51. pte_reg = ACPAXI2AXI_ATU_BASE_ADDR_GRP_4;
  52. pte_size = ACPAXI2AXI_ATU_PAGE_SIZE_GRP_4;
  53. offset = offsetof(struct scratch_reg_conf, grp4_pte);
  54. stream->reg_offset = PTE_GRP4_OFFSET;
  55. break;
  56. case 5:
  57. pte_reg = ACPAXI2AXI_ATU_BASE_ADDR_GRP_5;
  58. pte_size = ACPAXI2AXI_ATU_PAGE_SIZE_GRP_5;
  59. offset = offsetof(struct scratch_reg_conf, grp5_pte);
  60. stream->reg_offset = PTE_GRP5_OFFSET;
  61. break;
  62. case 6:
  63. pte_reg = ACPAXI2AXI_ATU_BASE_ADDR_GRP_6;
  64. pte_size = ACPAXI2AXI_ATU_PAGE_SIZE_GRP_6;
  65. offset = offsetof(struct scratch_reg_conf, grp6_pte);
  66. stream->reg_offset = PTE_GRP6_OFFSET;
  67. break;
  68. case 7:
  69. pte_reg = ACPAXI2AXI_ATU_BASE_ADDR_GRP_7;
  70. pte_size = ACPAXI2AXI_ATU_PAGE_SIZE_GRP_7;
  71. offset = offsetof(struct scratch_reg_conf, grp7_pte);
  72. stream->reg_offset = PTE_GRP7_OFFSET;
  73. break;
  74. case 8:
  75. pte_reg = ACPAXI2AXI_ATU_BASE_ADDR_GRP_8;
  76. pte_size = ACPAXI2AXI_ATU_PAGE_SIZE_GRP_8;
  77. offset = offsetof(struct scratch_reg_conf, grp8_pte);
  78. stream->reg_offset = PTE_GRP8_OFFSET;
  79. break;
  80. default:
  81. dev_err(sdev->dev, "Invalid stream tag %d\n", stream_tag);
  82. return -EINVAL;
  83. }
  84. /* write phy_addr in scratch memory */
  85. phy_addr_offset = sdev->debug_box.offset +
  86. offsetof(struct scratch_reg_conf, reg_offset);
  87. index = stream_tag - 1;
  88. phy_addr_offset = phy_addr_offset + index * 4;
  89. snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SCRATCH_REG_0 +
  90. phy_addr_offset, stream->reg_offset);
  91. /* Group Enable */
  92. offset = offset + sdev->debug_box.offset;
  93. reg_val = desc->sram_pte_offset + offset;
  94. snd_sof_dsp_write(sdev, ACP_DSP_BAR, pte_reg, reg_val | BIT(31));
  95. snd_sof_dsp_write(sdev, ACP_DSP_BAR, pte_size, PAGE_SIZE_4K_ENABLE);
  96. for (page_idx = 0; page_idx < stream->num_pages; page_idx++) {
  97. addr = snd_sgbuf_get_addr(stream->dmab, page_idx * PAGE_SIZE);
  98. /* Load the low address of page int ACP SRAM through SRBM */
  99. low = lower_32_bits(addr);
  100. high = upper_32_bits(addr);
  101. snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SCRATCH_REG_0 + offset, low);
  102. high |= BIT(31);
  103. snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SCRATCH_REG_0 + offset + 4, high);
  104. /* Move to next physically contiguous page */
  105. offset += 8;
  106. }
  107. /* Flush ATU Cache after PTE Update */
  108. snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACPAXI2AXI_ATU_CTRL, ACP_ATU_CACHE_INVALID);
  109. return 0;
  110. }
  111. struct acp_dsp_stream *acp_dsp_stream_get(struct snd_sof_dev *sdev, int tag)
  112. {
  113. struct acp_dev_data *adata = sdev->pdata->hw_pdata;
  114. struct acp_dsp_stream *stream = adata->stream_buf;
  115. int i;
  116. for (i = 0; i < ACP_MAX_STREAM; i++, stream++) {
  117. if (stream->active)
  118. continue;
  119. /* return stream if tag not specified*/
  120. if (!tag) {
  121. stream->active = 1;
  122. return stream;
  123. }
  124. /* check if this is the requested stream tag */
  125. if (stream->stream_tag == tag) {
  126. stream->active = 1;
  127. return stream;
  128. }
  129. }
  130. dev_err(sdev->dev, "stream %d active or no inactive stream\n", tag);
  131. return NULL;
  132. }
  133. EXPORT_SYMBOL_NS(acp_dsp_stream_get, SND_SOC_SOF_AMD_COMMON);
  134. int acp_dsp_stream_put(struct snd_sof_dev *sdev,
  135. struct acp_dsp_stream *acp_stream)
  136. {
  137. struct acp_dev_data *adata = sdev->pdata->hw_pdata;
  138. struct acp_dsp_stream *stream = adata->stream_buf;
  139. int i;
  140. /* Free an active stream */
  141. for (i = 0; i < ACP_MAX_STREAM; i++, stream++) {
  142. if (stream == acp_stream) {
  143. stream->active = 0;
  144. return 0;
  145. }
  146. }
  147. dev_err(sdev->dev, "Cannot find active stream tag %d\n", acp_stream->stream_tag);
  148. return -EINVAL;
  149. }
  150. EXPORT_SYMBOL_NS(acp_dsp_stream_put, SND_SOC_SOF_AMD_COMMON);
  151. int acp_dsp_stream_init(struct snd_sof_dev *sdev)
  152. {
  153. struct acp_dev_data *adata = sdev->pdata->hw_pdata;
  154. int i;
  155. for (i = 0; i < ACP_MAX_STREAM; i++) {
  156. adata->stream_buf[i].sdev = sdev;
  157. adata->stream_buf[i].active = 0;
  158. adata->stream_buf[i].stream_tag = i + 1;
  159. }
  160. return 0;
  161. }
  162. EXPORT_SYMBOL_NS(acp_dsp_stream_init, SND_SOC_SOF_AMD_COMMON);