1 | /* SPDX-License-Identifier: GPL-2.0+ */ |
2 | /* |
3 | * AMD ALSA SoC PDM Driver |
4 | * |
5 | * Copyright (C) 2022, 2023 Advanced Micro Devices, Inc. All rights reserved. |
6 | */ |
7 | |
8 | #include <linux/soundwire/sdw_amd.h> |
9 | #include <sound/acp63_chip_offset_byte.h> |
10 | |
11 | #define ACP_DEVICE_ID 0x15E2 |
12 | #define ACP63_REG_START 0x1240000 |
13 | #define ACP63_REG_END 0x125C000 |
14 | |
15 | #define ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK 0x00010001 |
16 | #define ACP_PGFSM_CNTL_POWER_ON_MASK 1 |
17 | #define ACP_PGFSM_CNTL_POWER_OFF_MASK 0 |
18 | #define ACP_PGFSM_STATUS_MASK 3 |
19 | #define ACP_POWERED_ON 0 |
20 | #define ACP_POWER_ON_IN_PROGRESS 1 |
21 | #define ACP_POWERED_OFF 2 |
22 | #define ACP_POWER_OFF_IN_PROGRESS 3 |
23 | |
24 | #define ACP_ERROR_MASK 0x20000000 |
25 | #define ACP_EXT_INTR_STAT_CLEAR_MASK 0xFFFFFFFF |
26 | #define PDM_DMA_STAT 0x10 |
27 | |
28 | #define PDM_DMA_INTR_MASK 0x10000 |
29 | #define ACP_ERROR_STAT 29 |
30 | #define PDM_DECIMATION_FACTOR 2 |
31 | #define ACP_PDM_CLK_FREQ_MASK 7 |
32 | #define ACP_WOV_GAIN_CONTROL GENMASK(4, 3) |
33 | #define ACP_PDM_ENABLE 1 |
34 | #define ACP_PDM_DISABLE 0 |
35 | #define ACP_PDM_DMA_EN_STATUS 2 |
36 | #define TWO_CH 2 |
37 | #define DELAY_US 5 |
38 | #define ACP_COUNTER 20000 |
39 | |
40 | #define ACP_SRAM_PTE_OFFSET 0x03800000 |
41 | #define PAGE_SIZE_4K_ENABLE 2 |
42 | #define PDM_PTE_OFFSET 0 |
43 | #define PDM_MEM_WINDOW_START 0x4000000 |
44 | |
45 | #define CAPTURE_MIN_NUM_PERIODS 4 |
46 | #define CAPTURE_MAX_NUM_PERIODS 4 |
47 | #define CAPTURE_MAX_PERIOD_SIZE 8192 |
48 | #define CAPTURE_MIN_PERIOD_SIZE 4096 |
49 | |
50 | #define MAX_BUFFER (CAPTURE_MAX_PERIOD_SIZE * CAPTURE_MAX_NUM_PERIODS) |
51 | #define MIN_BUFFER MAX_BUFFER |
52 | |
53 | /* time in ms for runtime suspend delay */ |
54 | #define ACP_SUSPEND_DELAY_MS 2000 |
55 | |
56 | #define ACP_DMIC_DEV 2 |
57 | |
58 | #define ACP63_DMIC_ADDR 2 |
59 | #define ACP63_SDW_ADDR 5 |
60 | #define AMD_SDW_MAX_MANAGERS 2 |
61 | |
62 | /* time in ms for acp timeout */ |
63 | #define ACP_TIMEOUT 500 |
64 | |
65 | #define ACP_SDW0_STAT BIT(21) |
66 | #define ACP_SDW1_STAT BIT(2) |
67 | #define ACP_ERROR_IRQ BIT(29) |
68 | |
69 | #define ACP_AUDIO0_TX_THRESHOLD 0x1c |
70 | #define ACP_AUDIO1_TX_THRESHOLD 0x1a |
71 | #define ACP_AUDIO2_TX_THRESHOLD 0x18 |
72 | #define ACP_AUDIO0_RX_THRESHOLD 0x1b |
73 | #define ACP_AUDIO1_RX_THRESHOLD 0x19 |
74 | #define ACP_AUDIO2_RX_THRESHOLD 0x17 |
75 | #define ACP_P1_AUDIO1_TX_THRESHOLD BIT(6) |
76 | #define ACP_P1_AUDIO1_RX_THRESHOLD BIT(5) |
77 | #define ACP_SDW_DMA_IRQ_MASK 0x1F800000 |
78 | #define ACP_P1_SDW_DMA_IRQ_MASK 0x60 |
79 | #define ACP63_SDW0_DMA_MAX_STREAMS 6 |
80 | #define ACP63_SDW1_DMA_MAX_STREAMS 2 |
81 | #define ACP_P1_AUDIO_TX_THRESHOLD 6 |
82 | |
83 | /* |
84 | * Below entries describes SDW0 instance DMA stream id and DMA irq bit mapping |
85 | * in ACP_EXTENAL_INTR_CNTL register. |
86 | * Stream id IRQ Bit |
87 | * 0 (SDW0_AUDIO0_TX) 28 |
88 | * 1 (SDW0_AUDIO1_TX) 26 |
89 | * 2 (SDW0_AUDIO2_TX) 24 |
90 | * 3 (SDW0_AUDIO0_RX) 27 |
91 | * 4 (SDW0_AUDIO1_RX) 25 |
92 | * 5 (SDW0_AUDIO2_RX) 23 |
93 | */ |
94 | #define SDW0_DMA_TX_IRQ_MASK(i) (ACP_AUDIO0_TX_THRESHOLD - (2 * (i))) |
95 | #define SDW0_DMA_RX_IRQ_MASK(i) (ACP_AUDIO0_RX_THRESHOLD - (2 * ((i) - 3))) |
96 | |
97 | /* |
98 | * Below entries describes SDW1 instance DMA stream id and DMA irq bit mapping |
99 | * in ACP_EXTENAL_INTR_CNTL1 register. |
100 | * Stream id IRQ Bit |
101 | * 0 (SDW1_AUDIO1_TX) 6 |
102 | * 1 (SDW1_AUDIO1_RX) 5 |
103 | */ |
104 | #define SDW1_DMA_IRQ_MASK(i) (ACP_P1_AUDIO_TX_THRESHOLD - (i)) |
105 | |
106 | #define ACP_DELAY_US 5 |
107 | #define ACP_SDW_RING_BUFF_ADDR_OFFSET (128 * 1024) |
108 | #define SDW0_MEM_WINDOW_START 0x4800000 |
109 | #define ACP_SDW_SRAM_PTE_OFFSET 0x03800400 |
110 | #define SDW0_PTE_OFFSET 0x400 |
111 | #define SDW_FIFO_SIZE 0x100 |
112 | #define SDW_DMA_SIZE 0x40 |
113 | #define ACP_SDW0_FIFO_OFFSET 0x100 |
114 | #define ACP_SDW_PTE_OFFSET 0x100 |
115 | #define SDW_FIFO_OFFSET 0x100 |
116 | #define SDW_PTE_OFFSET(i) (SDW0_PTE_OFFSET + ((i) * 0x600)) |
117 | #define ACP_SDW_FIFO_OFFSET(i) (ACP_SDW0_FIFO_OFFSET + ((i) * 0x500)) |
118 | #define SDW_MEM_WINDOW_START(i) (SDW0_MEM_WINDOW_START + ((i) * 0xC0000)) |
119 | |
120 | #define SDW_PLAYBACK_MIN_NUM_PERIODS 2 |
121 | #define SDW_PLAYBACK_MAX_NUM_PERIODS 8 |
122 | #define SDW_PLAYBACK_MAX_PERIOD_SIZE 8192 |
123 | #define SDW_PLAYBACK_MIN_PERIOD_SIZE 1024 |
124 | #define SDW_CAPTURE_MIN_NUM_PERIODS 2 |
125 | #define SDW_CAPTURE_MAX_NUM_PERIODS 8 |
126 | #define SDW_CAPTURE_MAX_PERIOD_SIZE 8192 |
127 | #define SDW_CAPTURE_MIN_PERIOD_SIZE 1024 |
128 | |
129 | #define SDW_MAX_BUFFER (SDW_PLAYBACK_MAX_PERIOD_SIZE * SDW_PLAYBACK_MAX_NUM_PERIODS) |
130 | #define SDW_MIN_BUFFER SDW_MAX_BUFFER |
131 | |
132 | enum acp_config { |
133 | ACP_CONFIG_0 = 0, |
134 | ACP_CONFIG_1, |
135 | ACP_CONFIG_2, |
136 | ACP_CONFIG_3, |
137 | ACP_CONFIG_4, |
138 | ACP_CONFIG_5, |
139 | ACP_CONFIG_6, |
140 | ACP_CONFIG_7, |
141 | ACP_CONFIG_8, |
142 | ACP_CONFIG_9, |
143 | ACP_CONFIG_10, |
144 | ACP_CONFIG_11, |
145 | ACP_CONFIG_12, |
146 | ACP_CONFIG_13, |
147 | ACP_CONFIG_14, |
148 | ACP_CONFIG_15, |
149 | }; |
150 | |
151 | enum amd_sdw0_channel { |
152 | ACP_SDW0_AUDIO0_TX = 0, |
153 | ACP_SDW0_AUDIO1_TX, |
154 | ACP_SDW0_AUDIO2_TX, |
155 | ACP_SDW0_AUDIO0_RX, |
156 | ACP_SDW0_AUDIO1_RX, |
157 | ACP_SDW0_AUDIO2_RX, |
158 | }; |
159 | |
160 | enum amd_sdw1_channel { |
161 | ACP_SDW1_AUDIO1_TX, |
162 | ACP_SDW1_AUDIO1_RX, |
163 | }; |
164 | |
165 | struct pdm_stream_instance { |
166 | u16 num_pages; |
167 | u16 channels; |
168 | dma_addr_t dma_addr; |
169 | u64 bytescount; |
170 | void __iomem *acp63_base; |
171 | }; |
172 | |
173 | struct pdm_dev_data { |
174 | u32 pdm_irq; |
175 | void __iomem *acp63_base; |
176 | struct mutex *acp_lock; |
177 | struct snd_pcm_substream *capture_stream; |
178 | }; |
179 | |
180 | struct sdw_dma_dev_data { |
181 | void __iomem *acp_base; |
182 | struct mutex *acp_lock; /* used to protect acp common register access */ |
183 | struct snd_pcm_substream *sdw0_dma_stream[ACP63_SDW0_DMA_MAX_STREAMS]; |
184 | struct snd_pcm_substream *sdw1_dma_stream[ACP63_SDW1_DMA_MAX_STREAMS]; |
185 | }; |
186 | |
187 | struct acp_sdw_dma_stream { |
188 | u16 num_pages; |
189 | u16 channels; |
190 | u32 stream_id; |
191 | u32 instance; |
192 | dma_addr_t dma_addr; |
193 | u64 bytescount; |
194 | }; |
195 | |
196 | union acp_sdw_dma_count { |
197 | struct { |
198 | u32 low; |
199 | u32 high; |
200 | } bcount; |
201 | u64 bytescount; |
202 | }; |
203 | |
204 | struct sdw_dma_ring_buf_reg { |
205 | u32 reg_dma_size; |
206 | u32 reg_fifo_addr; |
207 | u32 reg_fifo_size; |
208 | u32 reg_ring_buf_size; |
209 | u32 reg_ring_buf_addr; |
210 | u32 water_mark_size_reg; |
211 | u32 pos_low_reg; |
212 | u32 pos_high_reg; |
213 | }; |
214 | |
215 | /** |
216 | * struct acp63_dev_data - acp pci driver context |
217 | * @acp63_base: acp mmio base |
218 | * @res: resource |
219 | * @pdm_dev: ACP PDM controller platform device |
220 | * @dmic_codec: platform device for DMIC Codec |
221 | * sdw_dma_dev: platform device for SoundWire DMA controller |
222 | * @mach_dev: platform device for machine driver to support ACP PDM/SoundWire configuration |
223 | * @acp_lock: used to protect acp common registers |
224 | * @info: SoundWire AMD information found in ACPI tables |
225 | * @sdw: SoundWire context for all SoundWire manager instances |
226 | * @machine: ACPI machines for SoundWire interface |
227 | * @is_sdw_dev: flag set to true when any SoundWire manager instances are available |
228 | * @is_pdm_dev: flag set to true when ACP PDM controller exists |
229 | * @is_pdm_config: flat set to true when PDM configuration is selected from BIOS |
230 | * @is_sdw_config: flag set to true when SDW configuration is selected from BIOS |
231 | * @sdw_en_stat: flag set to true when any one of the SoundWire manager instance is enabled |
232 | * @addr: pci ioremap address |
233 | * @reg_range: ACP reigister range |
234 | * @sdw0-dma_intr_stat: DMA interrupt status array for SoundWire manager-SW0 instance |
235 | * @sdw_dma_intr_stat: DMA interrupt status array for SoundWire manager-SW1 instance |
236 | */ |
237 | |
238 | struct acp63_dev_data { |
239 | void __iomem *acp63_base; |
240 | struct resource *res; |
241 | struct platform_device *pdm_dev; |
242 | struct platform_device *dmic_codec_dev; |
243 | struct platform_device *sdw_dma_dev; |
244 | struct platform_device *mach_dev; |
245 | struct mutex acp_lock; /* protect shared registers */ |
246 | struct sdw_amd_acpi_info info; |
247 | /* sdw context allocated by SoundWire driver */ |
248 | struct sdw_amd_ctx *sdw; |
249 | struct snd_soc_acpi_mach *machines; |
250 | bool is_sdw_dev; |
251 | bool is_pdm_dev; |
252 | bool is_pdm_config; |
253 | bool is_sdw_config; |
254 | bool sdw_en_stat; |
255 | u32 addr; |
256 | u32 reg_range; |
257 | u16 sdw0_dma_intr_stat[ACP63_SDW0_DMA_MAX_STREAMS]; |
258 | u16 sdw1_dma_intr_stat[ACP63_SDW1_DMA_MAX_STREAMS]; |
259 | }; |
260 | |
261 | int snd_amd_acp_find_config(struct pci_dev *pci); |
262 | |