Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/soc/amd/ps/ps-sdw-dma.c
26481 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
* AMD ALSA SoC common SoundWire DMA Driver for ACP6.3, ACP7.0 and ACP7.1
4
* platforms.
5
*
6
* Copyright 2023, 2025 Advanced Micro Devices, Inc.
7
*/
8
9
#include <linux/err.h>
10
#include <linux/io.h>
11
#include <linux/module.h>
12
#include <linux/platform_device.h>
13
#include <sound/pcm_params.h>
14
#include <sound/soc.h>
15
#include <sound/soc-dai.h>
16
#include <linux/pm_runtime.h>
17
#include <linux/soundwire/sdw_amd.h>
18
#include "acp63.h"
19
20
#define DRV_NAME "amd_ps_sdw_dma"
21
22
static struct sdw_dma_ring_buf_reg acp63_sdw0_dma_reg[ACP63_SDW0_DMA_MAX_STREAMS] = {
23
{ACP_AUDIO0_TX_DMA_SIZE, ACP_AUDIO0_TX_FIFOADDR, ACP_AUDIO0_TX_FIFOSIZE,
24
ACP_AUDIO0_TX_RINGBUFSIZE, ACP_AUDIO0_TX_RINGBUFADDR, ACP_AUDIO0_TX_INTR_WATERMARK_SIZE,
25
ACP_AUDIO0_TX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO0_TX_LINEARPOSITIONCNTR_HIGH},
26
{ACP_AUDIO1_TX_DMA_SIZE, ACP_AUDIO1_TX_FIFOADDR, ACP_AUDIO1_TX_FIFOSIZE,
27
ACP_AUDIO1_TX_RINGBUFSIZE, ACP_AUDIO1_TX_RINGBUFADDR, ACP_AUDIO1_TX_INTR_WATERMARK_SIZE,
28
ACP_AUDIO1_TX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO1_TX_LINEARPOSITIONCNTR_HIGH},
29
{ACP_AUDIO2_TX_DMA_SIZE, ACP_AUDIO2_TX_FIFOADDR, ACP_AUDIO2_TX_FIFOSIZE,
30
ACP_AUDIO2_TX_RINGBUFSIZE, ACP_AUDIO2_TX_RINGBUFADDR, ACP_AUDIO2_TX_INTR_WATERMARK_SIZE,
31
ACP_AUDIO2_TX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO2_TX_LINEARPOSITIONCNTR_HIGH},
32
{ACP_AUDIO0_RX_DMA_SIZE, ACP_AUDIO0_RX_FIFOADDR, ACP_AUDIO0_RX_FIFOSIZE,
33
ACP_AUDIO0_RX_RINGBUFSIZE, ACP_AUDIO0_RX_RINGBUFADDR, ACP_AUDIO0_RX_INTR_WATERMARK_SIZE,
34
ACP_AUDIO0_RX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO0_RX_LINEARPOSITIONCNTR_HIGH},
35
{ACP_AUDIO1_RX_DMA_SIZE, ACP_AUDIO1_RX_FIFOADDR, ACP_AUDIO1_RX_FIFOSIZE,
36
ACP_AUDIO1_RX_RINGBUFSIZE, ACP_AUDIO1_RX_RINGBUFADDR, ACP_AUDIO1_RX_INTR_WATERMARK_SIZE,
37
ACP_AUDIO1_RX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO1_RX_LINEARPOSITIONCNTR_HIGH},
38
{ACP_AUDIO2_RX_DMA_SIZE, ACP_AUDIO2_RX_FIFOADDR, ACP_AUDIO2_RX_FIFOSIZE,
39
ACP_AUDIO2_RX_RINGBUFSIZE, ACP_AUDIO2_RX_RINGBUFADDR, ACP_AUDIO2_RX_INTR_WATERMARK_SIZE,
40
ACP_AUDIO2_RX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO2_RX_LINEARPOSITIONCNTR_HIGH}
41
};
42
43
/*
44
* SDW1 instance supports one TX stream and one RX stream.
45
* For TX/RX streams DMA registers programming for SDW1 instance, it uses ACP_P1_AUDIO1 register
46
* set as per hardware register documentation
47
*/
48
static struct sdw_dma_ring_buf_reg acp63_sdw1_dma_reg[ACP63_SDW1_DMA_MAX_STREAMS] = {
49
{ACP_P1_AUDIO1_TX_DMA_SIZE, ACP_P1_AUDIO1_TX_FIFOADDR, ACP_P1_AUDIO1_TX_FIFOSIZE,
50
ACP_P1_AUDIO1_TX_RINGBUFSIZE, ACP_P1_AUDIO1_TX_RINGBUFADDR,
51
ACP_P1_AUDIO1_TX_INTR_WATERMARK_SIZE,
52
ACP_P1_AUDIO1_TX_LINEARPOSITIONCNTR_LOW, ACP_P1_AUDIO1_TX_LINEARPOSITIONCNTR_HIGH},
53
{ACP_P1_AUDIO1_RX_DMA_SIZE, ACP_P1_AUDIO1_RX_FIFOADDR, ACP_P1_AUDIO1_RX_FIFOSIZE,
54
ACP_P1_AUDIO1_RX_RINGBUFSIZE, ACP_P1_AUDIO1_RX_RINGBUFADDR,
55
ACP_P1_AUDIO1_RX_INTR_WATERMARK_SIZE,
56
ACP_P1_AUDIO1_RX_LINEARPOSITIONCNTR_LOW, ACP_P1_AUDIO1_RX_LINEARPOSITIONCNTR_HIGH},
57
};
58
59
static u32 acp63_sdw0_dma_enable_reg[ACP63_SDW0_DMA_MAX_STREAMS] = {
60
ACP_SW0_AUDIO0_TX_EN,
61
ACP_SW0_AUDIO1_TX_EN,
62
ACP_SW0_AUDIO2_TX_EN,
63
ACP_SW0_AUDIO0_RX_EN,
64
ACP_SW0_AUDIO1_RX_EN,
65
ACP_SW0_AUDIO2_RX_EN,
66
};
67
68
/*
69
* SDW1 instance supports one TX stream and one RX stream.
70
* For TX/RX streams DMA enable register programming for SDW1 instance,
71
* it uses ACP_SW1_AUDIO1_TX_EN and ACP_SW1_AUDIO1_RX_EN registers
72
* as per hardware register documentation.
73
*/
74
static u32 acp63_sdw1_dma_enable_reg[ACP63_SDW1_DMA_MAX_STREAMS] = {
75
ACP_SW1_AUDIO1_TX_EN,
76
ACP_SW1_AUDIO1_RX_EN,
77
};
78
79
static struct sdw_dma_ring_buf_reg acp70_sdw0_dma_reg[ACP70_SDW0_DMA_MAX_STREAMS] = {
80
{ACP_AUDIO0_TX_DMA_SIZE, ACP_AUDIO0_TX_FIFOADDR, ACP_AUDIO0_TX_FIFOSIZE,
81
ACP_AUDIO0_TX_RINGBUFSIZE, ACP_AUDIO0_TX_RINGBUFADDR, ACP_AUDIO0_TX_INTR_WATERMARK_SIZE,
82
ACP_AUDIO0_TX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO0_TX_LINEARPOSITIONCNTR_HIGH},
83
{ACP_AUDIO1_TX_DMA_SIZE, ACP_AUDIO1_TX_FIFOADDR, ACP_AUDIO1_TX_FIFOSIZE,
84
ACP_AUDIO1_TX_RINGBUFSIZE, ACP_AUDIO1_TX_RINGBUFADDR, ACP_AUDIO1_TX_INTR_WATERMARK_SIZE,
85
ACP_AUDIO1_TX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO1_TX_LINEARPOSITIONCNTR_HIGH},
86
{ACP_AUDIO2_TX_DMA_SIZE, ACP_AUDIO2_TX_FIFOADDR, ACP_AUDIO2_TX_FIFOSIZE,
87
ACP_AUDIO2_TX_RINGBUFSIZE, ACP_AUDIO2_TX_RINGBUFADDR, ACP_AUDIO2_TX_INTR_WATERMARK_SIZE,
88
ACP_AUDIO2_TX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO2_TX_LINEARPOSITIONCNTR_HIGH},
89
{ACP_AUDIO0_RX_DMA_SIZE, ACP_AUDIO0_RX_FIFOADDR, ACP_AUDIO0_RX_FIFOSIZE,
90
ACP_AUDIO0_RX_RINGBUFSIZE, ACP_AUDIO0_RX_RINGBUFADDR, ACP_AUDIO0_RX_INTR_WATERMARK_SIZE,
91
ACP_AUDIO0_RX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO0_RX_LINEARPOSITIONCNTR_HIGH},
92
{ACP_AUDIO1_RX_DMA_SIZE, ACP_AUDIO1_RX_FIFOADDR, ACP_AUDIO1_RX_FIFOSIZE,
93
ACP_AUDIO1_RX_RINGBUFSIZE, ACP_AUDIO1_RX_RINGBUFADDR, ACP_AUDIO1_RX_INTR_WATERMARK_SIZE,
94
ACP_AUDIO1_RX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO1_RX_LINEARPOSITIONCNTR_HIGH},
95
{ACP_AUDIO2_RX_DMA_SIZE, ACP_AUDIO2_RX_FIFOADDR, ACP_AUDIO2_RX_FIFOSIZE,
96
ACP_AUDIO2_RX_RINGBUFSIZE, ACP_AUDIO2_RX_RINGBUFADDR, ACP_AUDIO2_RX_INTR_WATERMARK_SIZE,
97
ACP_AUDIO2_RX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO2_RX_LINEARPOSITIONCNTR_HIGH}
98
};
99
100
static struct sdw_dma_ring_buf_reg acp70_sdw1_dma_reg[ACP70_SDW1_DMA_MAX_STREAMS] = {
101
{ACP_P1_AUDIO0_TX_DMA_SIZE, ACP_P1_AUDIO0_TX_FIFOADDR, ACP_P1_AUDIO0_TX_FIFOSIZE,
102
ACP_P1_AUDIO0_TX_RINGBUFSIZE, ACP_P1_AUDIO0_TX_RINGBUFADDR,
103
ACP_P1_AUDIO0_TX_INTR_WATERMARK_SIZE,
104
ACP_P1_AUDIO0_TX_LINEARPOSITIONCNTR_LOW, ACP_P1_AUDIO0_TX_LINEARPOSITIONCNTR_HIGH},
105
{ACP_P1_AUDIO1_TX_DMA_SIZE, ACP_P1_AUDIO1_TX_FIFOADDR, ACP_P1_AUDIO1_TX_FIFOSIZE,
106
ACP_P1_AUDIO1_TX_RINGBUFSIZE, ACP_P1_AUDIO1_TX_RINGBUFADDR,
107
ACP_P1_AUDIO1_TX_INTR_WATERMARK_SIZE,
108
ACP_P1_AUDIO1_TX_LINEARPOSITIONCNTR_LOW, ACP_P1_AUDIO1_TX_LINEARPOSITIONCNTR_HIGH},
109
{ACP_P1_AUDIO2_TX_DMA_SIZE, ACP_P1_AUDIO2_TX_FIFOADDR, ACP_P1_AUDIO2_TX_FIFOSIZE,
110
ACP_P1_AUDIO2_TX_RINGBUFSIZE, ACP_P1_AUDIO2_TX_RINGBUFADDR,
111
ACP_P1_AUDIO2_TX_INTR_WATERMARK_SIZE,
112
ACP_P1_AUDIO2_TX_LINEARPOSITIONCNTR_LOW, ACP_P1_AUDIO2_TX_LINEARPOSITIONCNTR_HIGH},
113
{ACP_P1_AUDIO0_RX_DMA_SIZE, ACP_P1_AUDIO0_RX_FIFOADDR, ACP_P1_AUDIO0_RX_FIFOSIZE,
114
ACP_P1_AUDIO0_RX_RINGBUFSIZE, ACP_P1_AUDIO0_RX_RINGBUFADDR,
115
ACP_P1_AUDIO0_RX_INTR_WATERMARK_SIZE,
116
ACP_P1_AUDIO0_RX_LINEARPOSITIONCNTR_LOW, ACP_P1_AUDIO0_RX_LINEARPOSITIONCNTR_HIGH},
117
{ACP_P1_AUDIO1_RX_DMA_SIZE, ACP_P1_AUDIO1_RX_FIFOADDR, ACP_P1_AUDIO1_RX_FIFOSIZE,
118
ACP_P1_AUDIO1_RX_RINGBUFSIZE, ACP_P1_AUDIO1_RX_RINGBUFADDR,
119
ACP_P1_AUDIO1_RX_INTR_WATERMARK_SIZE,
120
ACP_P1_AUDIO1_RX_LINEARPOSITIONCNTR_LOW, ACP_P1_AUDIO1_RX_LINEARPOSITIONCNTR_HIGH},
121
{ACP_P1_AUDIO2_RX_DMA_SIZE, ACP_P1_AUDIO2_RX_FIFOADDR, ACP_P1_AUDIO2_RX_FIFOSIZE,
122
ACP_P1_AUDIO2_RX_RINGBUFSIZE, ACP_P1_AUDIO2_RX_RINGBUFADDR,
123
ACP_P1_AUDIO2_RX_INTR_WATERMARK_SIZE,
124
ACP_P1_AUDIO2_RX_LINEARPOSITIONCNTR_LOW, ACP_P1_AUDIO2_RX_LINEARPOSITIONCNTR_HIGH}
125
};
126
127
static u32 acp70_sdw0_dma_enable_reg[ACP70_SDW0_DMA_MAX_STREAMS] = {
128
ACP70_SW0_AUDIO0_TX_EN,
129
ACP70_SW0_AUDIO1_TX_EN,
130
ACP70_SW0_AUDIO2_TX_EN,
131
ACP70_SW0_AUDIO0_RX_EN,
132
ACP70_SW0_AUDIO1_RX_EN,
133
ACP70_SW0_AUDIO2_RX_EN,
134
};
135
136
static u32 acp70_sdw1_dma_enable_reg[ACP70_SDW1_DMA_MAX_STREAMS] = {
137
ACP70_SW1_AUDIO0_TX_EN,
138
ACP70_SW1_AUDIO1_TX_EN,
139
ACP70_SW1_AUDIO2_TX_EN,
140
ACP70_SW1_AUDIO0_RX_EN,
141
ACP70_SW1_AUDIO1_RX_EN,
142
ACP70_SW1_AUDIO2_RX_EN,
143
};
144
145
static const struct snd_pcm_hardware acp63_sdw_hardware_playback = {
146
.info = SNDRV_PCM_INFO_INTERLEAVED |
147
SNDRV_PCM_INFO_BLOCK_TRANSFER |
148
SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
149
SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
150
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
151
SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE,
152
.channels_min = 2,
153
.channels_max = 2,
154
.rates = SNDRV_PCM_RATE_48000,
155
.rate_min = 48000,
156
.rate_max = 48000,
157
.buffer_bytes_max = SDW_PLAYBACK_MAX_NUM_PERIODS * SDW_PLAYBACK_MAX_PERIOD_SIZE,
158
.period_bytes_min = SDW_PLAYBACK_MIN_PERIOD_SIZE,
159
.period_bytes_max = SDW_PLAYBACK_MAX_PERIOD_SIZE,
160
.periods_min = SDW_PLAYBACK_MIN_NUM_PERIODS,
161
.periods_max = SDW_PLAYBACK_MAX_NUM_PERIODS,
162
};
163
164
static const struct snd_pcm_hardware acp63_sdw_hardware_capture = {
165
.info = SNDRV_PCM_INFO_INTERLEAVED |
166
SNDRV_PCM_INFO_BLOCK_TRANSFER |
167
SNDRV_PCM_INFO_MMAP |
168
SNDRV_PCM_INFO_MMAP_VALID |
169
SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
170
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
171
SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE,
172
.channels_min = 2,
173
.channels_max = 2,
174
.rates = SNDRV_PCM_RATE_48000,
175
.rate_min = 48000,
176
.rate_max = 48000,
177
.buffer_bytes_max = SDW_CAPTURE_MAX_NUM_PERIODS * SDW_CAPTURE_MAX_PERIOD_SIZE,
178
.period_bytes_min = SDW_CAPTURE_MIN_PERIOD_SIZE,
179
.period_bytes_max = SDW_CAPTURE_MAX_PERIOD_SIZE,
180
.periods_min = SDW_CAPTURE_MIN_NUM_PERIODS,
181
.periods_max = SDW_CAPTURE_MAX_NUM_PERIODS,
182
};
183
184
static void acp63_enable_disable_sdw_dma_interrupts(void __iomem *acp_base, u32 irq_mask,
185
u32 irq_mask1, bool enable)
186
{
187
u32 ext_intr_cntl, ext_intr_cntl1;
188
189
if (enable) {
190
ext_intr_cntl = readl(acp_base + ACP_EXTERNAL_INTR_CNTL);
191
ext_intr_cntl |= irq_mask;
192
writel(ext_intr_cntl, acp_base + ACP_EXTERNAL_INTR_CNTL);
193
ext_intr_cntl1 = readl(acp_base + ACP_EXTERNAL_INTR_CNTL1);
194
ext_intr_cntl1 |= irq_mask1;
195
writel(ext_intr_cntl1, acp_base + ACP_EXTERNAL_INTR_CNTL1);
196
} else {
197
ext_intr_cntl = readl(acp_base + ACP_EXTERNAL_INTR_CNTL);
198
ext_intr_cntl &= ~irq_mask;
199
writel(ext_intr_cntl, acp_base + ACP_EXTERNAL_INTR_CNTL);
200
ext_intr_cntl1 = readl(acp_base + ACP_EXTERNAL_INTR_CNTL1);
201
ext_intr_cntl1 &= ~irq_mask1;
202
writel(ext_intr_cntl1, acp_base + ACP_EXTERNAL_INTR_CNTL1);
203
}
204
}
205
206
static void acp63_config_dma(struct acp_sdw_dma_stream *stream, void __iomem *acp_base,
207
u32 stream_id)
208
{
209
u16 page_idx;
210
u32 low, high, val;
211
u32 sdw_dma_pte_offset;
212
dma_addr_t addr;
213
214
addr = stream->dma_addr;
215
sdw_dma_pte_offset = SDW_PTE_OFFSET(stream->instance);
216
val = sdw_dma_pte_offset + (stream_id * ACP_SDW_PTE_OFFSET);
217
218
/* Group Enable */
219
writel(ACP_SDW_SRAM_PTE_OFFSET | BIT(31), acp_base + ACPAXI2AXI_ATU_BASE_ADDR_GRP_2);
220
writel(PAGE_SIZE_4K_ENABLE, acp_base + ACPAXI2AXI_ATU_PAGE_SIZE_GRP_2);
221
for (page_idx = 0; page_idx < stream->num_pages; page_idx++) {
222
/* Load the low address of page int ACP SRAM through SRBM */
223
low = lower_32_bits(addr);
224
high = upper_32_bits(addr);
225
226
writel(low, acp_base + ACP_SCRATCH_REG_0 + val);
227
high |= BIT(31);
228
writel(high, acp_base + ACP_SCRATCH_REG_0 + val + 4);
229
val += 8;
230
addr += PAGE_SIZE;
231
}
232
writel(0x1, acp_base + ACPAXI2AXI_ATU_CTRL);
233
}
234
235
static int acp63_configure_sdw_ringbuffer(void __iomem *acp_base, u32 stream_id, u32 size,
236
u32 manager_instance, u32 acp_rev)
237
{
238
u32 reg_dma_size;
239
u32 reg_fifo_addr;
240
u32 reg_fifo_size;
241
u32 reg_ring_buf_size;
242
u32 reg_ring_buf_addr;
243
u32 sdw_fifo_addr;
244
u32 sdw_fifo_offset;
245
u32 sdw_ring_buf_addr;
246
u32 sdw_ring_buf_size;
247
u32 sdw_mem_window_offset;
248
249
switch (acp_rev) {
250
case ACP63_PCI_REV:
251
switch (manager_instance) {
252
case ACP_SDW0:
253
reg_dma_size = acp63_sdw0_dma_reg[stream_id].reg_dma_size;
254
reg_fifo_addr = acp63_sdw0_dma_reg[stream_id].reg_fifo_addr;
255
reg_fifo_size = acp63_sdw0_dma_reg[stream_id].reg_fifo_size;
256
reg_ring_buf_size = acp63_sdw0_dma_reg[stream_id].reg_ring_buf_size;
257
reg_ring_buf_addr = acp63_sdw0_dma_reg[stream_id].reg_ring_buf_addr;
258
break;
259
case ACP_SDW1:
260
reg_dma_size = acp63_sdw1_dma_reg[stream_id].reg_dma_size;
261
reg_fifo_addr = acp63_sdw1_dma_reg[stream_id].reg_fifo_addr;
262
reg_fifo_size = acp63_sdw1_dma_reg[stream_id].reg_fifo_size;
263
reg_ring_buf_size = acp63_sdw1_dma_reg[stream_id].reg_ring_buf_size;
264
reg_ring_buf_addr = acp63_sdw1_dma_reg[stream_id].reg_ring_buf_addr;
265
break;
266
default:
267
return -EINVAL;
268
}
269
break;
270
case ACP70_PCI_REV:
271
case ACP71_PCI_REV:
272
case ACP72_PCI_REV:
273
switch (manager_instance) {
274
case ACP_SDW0:
275
reg_dma_size = acp70_sdw0_dma_reg[stream_id].reg_dma_size;
276
reg_fifo_addr = acp70_sdw0_dma_reg[stream_id].reg_fifo_addr;
277
reg_fifo_size = acp70_sdw0_dma_reg[stream_id].reg_fifo_size;
278
reg_ring_buf_size = acp70_sdw0_dma_reg[stream_id].reg_ring_buf_size;
279
reg_ring_buf_addr = acp70_sdw0_dma_reg[stream_id].reg_ring_buf_addr;
280
break;
281
case ACP_SDW1:
282
reg_dma_size = acp70_sdw1_dma_reg[stream_id].reg_dma_size;
283
reg_fifo_addr = acp70_sdw1_dma_reg[stream_id].reg_fifo_addr;
284
reg_fifo_size = acp70_sdw1_dma_reg[stream_id].reg_fifo_size;
285
reg_ring_buf_size = acp70_sdw1_dma_reg[stream_id].reg_ring_buf_size;
286
reg_ring_buf_addr = acp70_sdw1_dma_reg[stream_id].reg_ring_buf_addr;
287
break;
288
default:
289
return -EINVAL;
290
}
291
break;
292
default:
293
return -EINVAL;
294
}
295
sdw_fifo_offset = ACP_SDW_FIFO_OFFSET(manager_instance);
296
sdw_mem_window_offset = SDW_MEM_WINDOW_START(manager_instance);
297
sdw_fifo_addr = sdw_fifo_offset + (stream_id * SDW_FIFO_OFFSET);
298
sdw_ring_buf_addr = sdw_mem_window_offset + (stream_id * ACP_SDW_RING_BUFF_ADDR_OFFSET);
299
sdw_ring_buf_size = size;
300
writel(sdw_ring_buf_size, acp_base + reg_ring_buf_size);
301
writel(sdw_ring_buf_addr, acp_base + reg_ring_buf_addr);
302
writel(sdw_fifo_addr, acp_base + reg_fifo_addr);
303
writel(SDW_DMA_SIZE, acp_base + reg_dma_size);
304
writel(SDW_FIFO_SIZE, acp_base + reg_fifo_size);
305
return 0;
306
}
307
308
static int acp63_sdw_dma_open(struct snd_soc_component *component,
309
struct snd_pcm_substream *substream)
310
{
311
struct snd_pcm_runtime *runtime;
312
struct acp_sdw_dma_stream *stream;
313
struct snd_soc_dai *cpu_dai;
314
struct amd_sdw_manager *amd_manager;
315
struct snd_soc_pcm_runtime *prtd = snd_soc_substream_to_rtd(substream);
316
int ret;
317
318
runtime = substream->runtime;
319
cpu_dai = snd_soc_rtd_to_cpu(prtd, 0);
320
amd_manager = snd_soc_dai_get_drvdata(cpu_dai);
321
stream = kzalloc(sizeof(*stream), GFP_KERNEL);
322
if (!stream)
323
return -ENOMEM;
324
325
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
326
runtime->hw = acp63_sdw_hardware_playback;
327
else
328
runtime->hw = acp63_sdw_hardware_capture;
329
ret = snd_pcm_hw_constraint_integer(runtime,
330
SNDRV_PCM_HW_PARAM_PERIODS);
331
if (ret < 0) {
332
dev_err(component->dev, "set integer constraint failed\n");
333
kfree(stream);
334
return ret;
335
}
336
337
stream->stream_id = cpu_dai->id;
338
stream->instance = amd_manager->instance;
339
runtime->private_data = stream;
340
return ret;
341
}
342
343
static int acp63_sdw_dma_hw_params(struct snd_soc_component *component,
344
struct snd_pcm_substream *substream,
345
struct snd_pcm_hw_params *params)
346
{
347
struct acp_sdw_dma_stream *stream;
348
struct sdw_dma_dev_data *sdw_data;
349
u32 period_bytes;
350
u32 water_mark_size_reg;
351
u32 irq_mask, ext_intr_ctrl;
352
u64 size;
353
u32 stream_id;
354
u32 acp_ext_intr_cntl_reg;
355
int ret;
356
357
sdw_data = dev_get_drvdata(component->dev);
358
stream = substream->runtime->private_data;
359
if (!stream)
360
return -EINVAL;
361
stream_id = stream->stream_id;
362
switch (sdw_data->acp_rev) {
363
case ACP63_PCI_REV:
364
switch (stream->instance) {
365
case ACP_SDW0:
366
sdw_data->acp63_sdw0_dma_stream[stream_id] = substream;
367
water_mark_size_reg = acp63_sdw0_dma_reg[stream_id].water_mark_size_reg;
368
acp_ext_intr_cntl_reg = ACP_EXTERNAL_INTR_CNTL;
369
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
370
irq_mask = BIT(ACP63_SDW0_DMA_TX_IRQ_MASK(stream_id));
371
else
372
irq_mask = BIT(ACP63_SDW0_DMA_RX_IRQ_MASK(stream_id));
373
break;
374
case ACP_SDW1:
375
sdw_data->acp63_sdw1_dma_stream[stream_id] = substream;
376
acp_ext_intr_cntl_reg = ACP_EXTERNAL_INTR_CNTL1;
377
water_mark_size_reg = acp63_sdw1_dma_reg[stream_id].water_mark_size_reg;
378
irq_mask = BIT(ACP63_SDW1_DMA_IRQ_MASK(stream_id));
379
break;
380
default:
381
return -EINVAL;
382
}
383
break;
384
case ACP70_PCI_REV:
385
case ACP71_PCI_REV:
386
case ACP72_PCI_REV:
387
switch (stream->instance) {
388
case ACP_SDW0:
389
sdw_data->acp70_sdw0_dma_stream[stream_id] = substream;
390
water_mark_size_reg = acp70_sdw0_dma_reg[stream_id].water_mark_size_reg;
391
acp_ext_intr_cntl_reg = ACP_EXTERNAL_INTR_CNTL;
392
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
393
irq_mask = BIT(ACP70_SDW0_DMA_TX_IRQ_MASK(stream_id));
394
else
395
irq_mask = BIT(ACP70_SDW0_DMA_RX_IRQ_MASK(stream_id));
396
break;
397
case ACP_SDW1:
398
sdw_data->acp70_sdw1_dma_stream[stream_id] = substream;
399
acp_ext_intr_cntl_reg = ACP_EXTERNAL_INTR_CNTL1;
400
water_mark_size_reg = acp70_sdw1_dma_reg[stream_id].water_mark_size_reg;
401
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
402
irq_mask = BIT(ACP70_SDW1_DMA_TX_IRQ_MASK(stream_id));
403
else
404
irq_mask = BIT(ACP70_SDW1_DMA_RX_IRQ_MASK(stream_id));
405
406
break;
407
default:
408
return -EINVAL;
409
}
410
break;
411
default:
412
return -EINVAL;
413
}
414
size = params_buffer_bytes(params);
415
period_bytes = params_period_bytes(params);
416
stream->dma_addr = substream->runtime->dma_addr;
417
stream->num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT);
418
acp63_config_dma(stream, sdw_data->acp_base, stream_id);
419
ret = acp63_configure_sdw_ringbuffer(sdw_data->acp_base, stream_id, size,
420
stream->instance, sdw_data->acp_rev);
421
if (ret) {
422
dev_err(component->dev, "Invalid DMA channel\n");
423
return -EINVAL;
424
}
425
ext_intr_ctrl = readl(sdw_data->acp_base + acp_ext_intr_cntl_reg);
426
ext_intr_ctrl |= irq_mask;
427
writel(ext_intr_ctrl, sdw_data->acp_base + acp_ext_intr_cntl_reg);
428
writel(period_bytes, sdw_data->acp_base + water_mark_size_reg);
429
return 0;
430
}
431
432
static u64 acp63_sdw_get_byte_count(struct acp_sdw_dma_stream *stream, void __iomem *acp_base,
433
u32 acp_rev)
434
{
435
union acp_sdw_dma_count byte_count;
436
u32 pos_low_reg, pos_high_reg;
437
438
byte_count.bytescount = 0;
439
switch (acp_rev) {
440
case ACP63_PCI_REV:
441
switch (stream->instance) {
442
case ACP_SDW0:
443
pos_low_reg = acp63_sdw0_dma_reg[stream->stream_id].pos_low_reg;
444
pos_high_reg = acp63_sdw0_dma_reg[stream->stream_id].pos_high_reg;
445
break;
446
case ACP_SDW1:
447
pos_low_reg = acp63_sdw1_dma_reg[stream->stream_id].pos_low_reg;
448
pos_high_reg = acp63_sdw1_dma_reg[stream->stream_id].pos_high_reg;
449
break;
450
default:
451
goto POINTER_RETURN_BYTES;
452
}
453
break;
454
case ACP70_PCI_REV:
455
case ACP71_PCI_REV:
456
case ACP72_PCI_REV:
457
switch (stream->instance) {
458
case ACP_SDW0:
459
pos_low_reg = acp70_sdw0_dma_reg[stream->stream_id].pos_low_reg;
460
pos_high_reg = acp70_sdw0_dma_reg[stream->stream_id].pos_high_reg;
461
break;
462
case ACP_SDW1:
463
pos_low_reg = acp70_sdw1_dma_reg[stream->stream_id].pos_low_reg;
464
pos_high_reg = acp70_sdw1_dma_reg[stream->stream_id].pos_high_reg;
465
break;
466
default:
467
goto POINTER_RETURN_BYTES;
468
}
469
break;
470
default:
471
goto POINTER_RETURN_BYTES;
472
}
473
if (pos_low_reg) {
474
byte_count.bcount.high = readl(acp_base + pos_high_reg);
475
byte_count.bcount.low = readl(acp_base + pos_low_reg);
476
}
477
POINTER_RETURN_BYTES:
478
return byte_count.bytescount;
479
}
480
481
static snd_pcm_uframes_t acp63_sdw_dma_pointer(struct snd_soc_component *comp,
482
struct snd_pcm_substream *substream)
483
{
484
struct sdw_dma_dev_data *sdw_data;
485
struct acp_sdw_dma_stream *stream;
486
u32 pos, buffersize;
487
u64 bytescount;
488
489
sdw_data = dev_get_drvdata(comp->dev);
490
stream = substream->runtime->private_data;
491
buffersize = frames_to_bytes(substream->runtime,
492
substream->runtime->buffer_size);
493
bytescount = acp63_sdw_get_byte_count(stream, sdw_data->acp_base, sdw_data->acp_rev);
494
if (bytescount > stream->bytescount)
495
bytescount -= stream->bytescount;
496
pos = do_div(bytescount, buffersize);
497
return bytes_to_frames(substream->runtime, pos);
498
}
499
500
static int acp63_sdw_dma_new(struct snd_soc_component *component,
501
struct snd_soc_pcm_runtime *rtd)
502
{
503
struct device *parent = component->dev->parent;
504
505
snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV,
506
parent, SDW_MIN_BUFFER, SDW_MAX_BUFFER);
507
return 0;
508
}
509
510
static int acp63_sdw_dma_close(struct snd_soc_component *component,
511
struct snd_pcm_substream *substream)
512
{
513
struct sdw_dma_dev_data *sdw_data;
514
struct acp_sdw_dma_stream *stream;
515
516
sdw_data = dev_get_drvdata(component->dev);
517
stream = substream->runtime->private_data;
518
if (!stream)
519
return -EINVAL;
520
switch (sdw_data->acp_rev) {
521
case ACP63_PCI_REV:
522
switch (stream->instance) {
523
case ACP_SDW0:
524
sdw_data->acp63_sdw0_dma_stream[stream->stream_id] = NULL;
525
break;
526
case ACP_SDW1:
527
sdw_data->acp63_sdw1_dma_stream[stream->stream_id] = NULL;
528
break;
529
default:
530
return -EINVAL;
531
}
532
break;
533
case ACP70_PCI_REV:
534
case ACP71_PCI_REV:
535
case ACP72_PCI_REV:
536
switch (stream->instance) {
537
case ACP_SDW0:
538
sdw_data->acp70_sdw0_dma_stream[stream->stream_id] = NULL;
539
break;
540
case ACP_SDW1:
541
sdw_data->acp70_sdw1_dma_stream[stream->stream_id] = NULL;
542
break;
543
default:
544
return -EINVAL;
545
}
546
break;
547
default:
548
return -EINVAL;
549
}
550
kfree(stream);
551
return 0;
552
}
553
554
static int acp63_sdw_dma_enable(struct snd_pcm_substream *substream,
555
void __iomem *acp_base, u32 acp_rev, bool sdw_dma_enable)
556
{
557
struct acp_sdw_dma_stream *stream;
558
u32 stream_id;
559
u32 sdw_dma_en_reg;
560
u32 sdw_dma_en_stat_reg;
561
u32 sdw_dma_stat;
562
u32 dma_enable;
563
564
stream = substream->runtime->private_data;
565
stream_id = stream->stream_id;
566
switch (acp_rev) {
567
case ACP63_PCI_REV:
568
switch (stream->instance) {
569
case ACP_SDW0:
570
sdw_dma_en_reg = acp63_sdw0_dma_enable_reg[stream_id];
571
break;
572
case ACP_SDW1:
573
sdw_dma_en_reg = acp63_sdw1_dma_enable_reg[stream_id];
574
break;
575
default:
576
return -EINVAL;
577
}
578
break;
579
case ACP70_PCI_REV:
580
case ACP71_PCI_REV:
581
case ACP72_PCI_REV:
582
switch (stream->instance) {
583
case ACP_SDW0:
584
sdw_dma_en_reg = acp70_sdw0_dma_enable_reg[stream_id];
585
break;
586
case ACP_SDW1:
587
sdw_dma_en_reg = acp70_sdw1_dma_enable_reg[stream_id];
588
break;
589
default:
590
return -EINVAL;
591
}
592
break;
593
default:
594
return -EINVAL;
595
}
596
sdw_dma_en_stat_reg = sdw_dma_en_reg + 4;
597
dma_enable = sdw_dma_enable;
598
writel(dma_enable, acp_base + sdw_dma_en_reg);
599
return readl_poll_timeout(acp_base + sdw_dma_en_stat_reg, sdw_dma_stat,
600
(sdw_dma_stat == dma_enable), ACP_DELAY_US, ACP_COUNTER);
601
}
602
603
static int acp63_sdw_dma_trigger(struct snd_soc_component *comp,
604
struct snd_pcm_substream *substream,
605
int cmd)
606
{
607
struct sdw_dma_dev_data *sdw_data;
608
int ret;
609
610
sdw_data = dev_get_drvdata(comp->dev);
611
switch (cmd) {
612
case SNDRV_PCM_TRIGGER_START:
613
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
614
case SNDRV_PCM_TRIGGER_RESUME:
615
ret = acp63_sdw_dma_enable(substream, sdw_data->acp_base, sdw_data->acp_rev, true);
616
break;
617
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
618
case SNDRV_PCM_TRIGGER_SUSPEND:
619
case SNDRV_PCM_TRIGGER_STOP:
620
ret = acp63_sdw_dma_enable(substream, sdw_data->acp_base, sdw_data->acp_rev, false);
621
break;
622
default:
623
ret = -EINVAL;
624
}
625
if (ret)
626
dev_err(comp->dev, "trigger %d failed: %d", cmd, ret);
627
return ret;
628
}
629
630
static const struct snd_soc_component_driver acp63_sdw_component = {
631
.name = DRV_NAME,
632
.open = acp63_sdw_dma_open,
633
.close = acp63_sdw_dma_close,
634
.hw_params = acp63_sdw_dma_hw_params,
635
.trigger = acp63_sdw_dma_trigger,
636
.pointer = acp63_sdw_dma_pointer,
637
.pcm_construct = acp63_sdw_dma_new,
638
.use_dai_pcm_id = true,
639
640
};
641
642
static int acp63_sdw_platform_probe(struct platform_device *pdev)
643
{
644
struct resource *res;
645
struct sdw_dma_dev_data *sdw_data;
646
struct acp63_dev_data *acp_data;
647
struct device *parent;
648
int status;
649
650
parent = pdev->dev.parent;
651
acp_data = dev_get_drvdata(parent);
652
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
653
if (!res) {
654
dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n");
655
return -ENODEV;
656
}
657
658
sdw_data = devm_kzalloc(&pdev->dev, sizeof(*sdw_data), GFP_KERNEL);
659
if (!sdw_data)
660
return -ENOMEM;
661
662
sdw_data->acp_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
663
if (!sdw_data->acp_base)
664
return -ENOMEM;
665
666
sdw_data->acp_lock = &acp_data->acp_lock;
667
sdw_data->acp_rev = acp_data->acp_rev;
668
dev_set_drvdata(&pdev->dev, sdw_data);
669
status = devm_snd_soc_register_component(&pdev->dev,
670
&acp63_sdw_component,
671
NULL, 0);
672
if (status) {
673
dev_err(&pdev->dev, "Fail to register sdw dma component\n");
674
return status;
675
}
676
pm_runtime_set_autosuspend_delay(&pdev->dev, ACP_SUSPEND_DELAY_MS);
677
pm_runtime_use_autosuspend(&pdev->dev);
678
pm_runtime_mark_last_busy(&pdev->dev);
679
pm_runtime_set_active(&pdev->dev);
680
pm_runtime_enable(&pdev->dev);
681
return 0;
682
}
683
684
static void acp63_sdw_platform_remove(struct platform_device *pdev)
685
{
686
pm_runtime_disable(&pdev->dev);
687
}
688
689
static int acp63_restore_sdw_dma_config(struct sdw_dma_dev_data *sdw_data)
690
{
691
struct acp_sdw_dma_stream *stream;
692
struct snd_pcm_substream *substream;
693
struct snd_pcm_runtime *runtime;
694
u32 period_bytes, buf_size, water_mark_size_reg;
695
u32 stream_count, irq_mask, irq_mask1;
696
int index, instance, ret;
697
698
irq_mask = ACP63_SDW_DMA_IRQ_MASK;
699
irq_mask1 = ACP63_P1_SDW_DMA_IRQ_MASK;
700
for (instance = 0; instance < AMD_SDW_MAX_MANAGERS; instance++) {
701
if (instance == ACP_SDW0)
702
stream_count = ACP63_SDW0_DMA_MAX_STREAMS;
703
else
704
stream_count = ACP63_SDW1_DMA_MAX_STREAMS;
705
706
for (index = 0; index < stream_count; index++) {
707
if (instance == ACP_SDW0) {
708
substream = sdw_data->acp63_sdw0_dma_stream[index];
709
water_mark_size_reg = acp63_sdw0_dma_reg[index].water_mark_size_reg;
710
} else {
711
substream = sdw_data->acp63_sdw1_dma_stream[index];
712
water_mark_size_reg = acp63_sdw1_dma_reg[index].water_mark_size_reg;
713
}
714
715
if (substream && substream->runtime) {
716
runtime = substream->runtime;
717
stream = runtime->private_data;
718
period_bytes = frames_to_bytes(runtime, runtime->period_size);
719
buf_size = frames_to_bytes(runtime, runtime->buffer_size);
720
acp63_config_dma(stream, sdw_data->acp_base, index);
721
ret = acp63_configure_sdw_ringbuffer(sdw_data->acp_base, index,
722
buf_size, instance,
723
ACP63_PCI_REV);
724
if (ret)
725
return ret;
726
writel(period_bytes, sdw_data->acp_base + water_mark_size_reg);
727
}
728
}
729
}
730
acp63_enable_disable_sdw_dma_interrupts(sdw_data->acp_base, irq_mask, irq_mask1, true);
731
return 0;
732
}
733
734
static int acp70_restore_sdw_dma_config(struct sdw_dma_dev_data *sdw_data)
735
{
736
struct acp_sdw_dma_stream *stream;
737
struct snd_pcm_substream *substream;
738
struct snd_pcm_runtime *runtime;
739
u32 period_bytes, buf_size, water_mark_size_reg;
740
u32 stream_count, irq_mask, irq_mask1;
741
int index, instance, ret;
742
743
irq_mask = ACP70_SDW_DMA_IRQ_MASK;
744
irq_mask1 = ACP70_P1_SDW_DMA_IRQ_MASK;
745
stream_count = ACP70_SDW0_DMA_MAX_STREAMS;
746
for (instance = 0; instance < AMD_SDW_MAX_MANAGERS; instance++) {
747
for (index = 0; index < stream_count; index++) {
748
if (instance == ACP_SDW0) {
749
substream = sdw_data->acp70_sdw0_dma_stream[index];
750
water_mark_size_reg = acp70_sdw0_dma_reg[index].water_mark_size_reg;
751
} else {
752
substream = sdw_data->acp70_sdw1_dma_stream[index];
753
water_mark_size_reg = acp70_sdw1_dma_reg[index].water_mark_size_reg;
754
}
755
756
if (substream && substream->runtime) {
757
runtime = substream->runtime;
758
stream = runtime->private_data;
759
period_bytes = frames_to_bytes(runtime, runtime->period_size);
760
buf_size = frames_to_bytes(runtime, runtime->buffer_size);
761
acp63_config_dma(stream, sdw_data->acp_base, index);
762
ret = acp63_configure_sdw_ringbuffer(sdw_data->acp_base, index,
763
buf_size, instance,
764
sdw_data->acp_rev);
765
if (ret)
766
return ret;
767
writel(period_bytes, sdw_data->acp_base + water_mark_size_reg);
768
}
769
}
770
}
771
acp63_enable_disable_sdw_dma_interrupts(sdw_data->acp_base, irq_mask, irq_mask1, true);
772
return 0;
773
}
774
775
static int acp63_sdw_pcm_resume(struct device *dev)
776
{
777
struct sdw_dma_dev_data *sdw_data;
778
779
sdw_data = dev_get_drvdata(dev);
780
if (sdw_data->acp_rev == ACP63_PCI_REV)
781
return acp63_restore_sdw_dma_config(sdw_data);
782
else
783
return acp70_restore_sdw_dma_config(sdw_data);
784
}
785
786
static const struct dev_pm_ops acp63_pm_ops = {
787
SYSTEM_SLEEP_PM_OPS(NULL, acp63_sdw_pcm_resume)
788
};
789
790
static struct platform_driver acp63_sdw_dma_driver = {
791
.probe = acp63_sdw_platform_probe,
792
.remove = acp63_sdw_platform_remove,
793
.driver = {
794
.name = "amd_ps_sdw_dma",
795
.pm = pm_ptr(&acp63_pm_ops),
796
},
797
};
798
799
module_platform_driver(acp63_sdw_dma_driver);
800
801
MODULE_AUTHOR("[email protected]");
802
MODULE_DESCRIPTION("AMD common SDW DMA Driver for ACP6.3, ACP7.0 & ACP7.1 platforms");
803
MODULE_LICENSE("GPL");
804
MODULE_ALIAS("platform:" DRV_NAME);
805
806