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