Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ASoC: amd: ps: add SoundWire support

Merge series from Vijendar Mukunda <Vijendar.Mukunda@amd.com>:

This patch series add support for
- Platform device creation for SoundWire Manager instances and
PDM controller.
- SoundWire DMA driver.
- Interrupt handling for SoundWire manager related interrupts,
SoundWire DMA interrupts and ACP error interrupts.
- ACP PCI driver PM ops modification with respect to SoundWire
Power modes.

+1118 -39
+2 -1
sound/soc/amd/Kconfig
··· 138 138 help 139 139 This option enables Audio Coprocessor i.e ACP v6.3 support on 140 140 AMD Pink sardine platform. By enabling this flag build will be 141 - triggered for ACP PCI driver, ACP PDM DMA driver. 141 + triggered for ACP PCI driver, ACP PDM DMA driver, ACP SoundWire 142 + DMA driver. 142 143 Say m if you have such a device. 143 144 If unsure select "N". 144 145
+2
sound/soc/amd/ps/Makefile
··· 3 3 snd-pci-ps-objs := pci-ps.o 4 4 snd-ps-pdm-dma-objs := ps-pdm-dma.o 5 5 snd-soc-ps-mach-objs := ps-mach.o 6 + snd-ps-sdw-dma-objs := ps-sdw-dma.o 6 7 7 8 obj-$(CONFIG_SND_SOC_AMD_PS) += snd-pci-ps.o 8 9 obj-$(CONFIG_SND_SOC_AMD_PS) += snd-ps-pdm-dma.o 10 + obj-$(CONFIG_SND_SOC_AMD_PS) += snd-ps-sdw-dma.o 9 11 obj-$(CONFIG_SND_SOC_AMD_PS_MACH) += snd-soc-ps-mach.o
+167 -5
sound/soc/amd/ps/acp63.h
··· 10 10 #define ACP_DEVICE_ID 0x15E2 11 11 #define ACP63_REG_START 0x1240000 12 12 #define ACP63_REG_END 0x1250200 13 - #define ACP63_DEVS 3 13 + #define ACP63_DEVS 5 14 14 15 15 #define ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK 0x00010001 16 16 #define ACP_PGFSM_CNTL_POWER_ON_MASK 1 ··· 53 53 /* time in ms for runtime suspend delay */ 54 54 #define ACP_SUSPEND_DELAY_MS 2000 55 55 56 - #define ACP63_DMIC_ADDR 2 57 - #define ACP63_PDM_MODE_DEVS 3 58 - #define ACP63_PDM_DEV_MASK 1 59 56 #define ACP_DMIC_DEV 2 57 + 58 + /* ACP63_PDM_MODE_DEVS corresponds to platform devices count for ACP PDM configuration */ 59 + #define ACP63_PDM_MODE_DEVS 3 60 + 61 + /* 62 + * ACP63_SDW0_MODE_DEVS corresponds to platform devices count for 63 + * SW0 SoundWire manager instance configuration 64 + */ 65 + #define ACP63_SDW0_MODE_DEVS 2 66 + 67 + /* 68 + * ACP63_SDW0_SDW1_MODE_DEVS corresponds to platform devices count for SW0 + SW1 SoundWire manager 69 + * instances configuration 70 + */ 71 + #define ACP63_SDW0_SDW1_MODE_DEVS 3 72 + 73 + /* 74 + * ACP63_SDW0_PDM_MODE_DEVS corresponds to platform devices count for SW0 manager 75 + * instance + ACP PDM controller configuration 76 + */ 77 + #define ACP63_SDW0_PDM_MODE_DEVS 4 78 + 79 + /* 80 + * ACP63_SDW0_SDW1_PDM_MODE_DEVS corresponds to platform devices count for 81 + * SW0 + SW1 SoundWire manager instances + ACP PDM controller configuration 82 + */ 83 + #define ACP63_SDW0_SDW1_PDM_MODE_DEVS 5 84 + #define ACP63_DMIC_ADDR 2 85 + #define ACP63_SDW_ADDR 5 86 + #define AMD_SDW_MAX_MANAGERS 2 60 87 61 88 /* time in ms for acp timeout */ 62 89 #define ACP_TIMEOUT 500 90 + 91 + /* ACP63_PDM_DEV_CONFIG corresponds to platform device configuration for ACP PDM controller */ 92 + #define ACP63_PDM_DEV_CONFIG BIT(0) 93 + 94 + /* ACP63_SDW_DEV_CONFIG corresponds to platform device configuration for SDW manager instances */ 95 + #define ACP63_SDW_DEV_CONFIG BIT(1) 96 + 97 + /* 98 + * ACP63_SDW_PDM_DEV_CONFIG corresponds to platform device configuration for ACP PDM + SoundWire 99 + * manager instance combination. 100 + */ 101 + #define ACP63_SDW_PDM_DEV_CONFIG GENMASK(1, 0) 102 + #define ACP_SDW0_STAT BIT(21) 103 + #define ACP_SDW1_STAT BIT(2) 104 + #define ACP_ERROR_IRQ BIT(29) 105 + 106 + #define ACP_AUDIO0_TX_THRESHOLD 0x1c 107 + #define ACP_AUDIO1_TX_THRESHOLD 0x1a 108 + #define ACP_AUDIO2_TX_THRESHOLD 0x18 109 + #define ACP_AUDIO0_RX_THRESHOLD 0x1b 110 + #define ACP_AUDIO1_RX_THRESHOLD 0x19 111 + #define ACP_AUDIO2_RX_THRESHOLD 0x17 112 + #define ACP_P1_AUDIO1_TX_THRESHOLD BIT(6) 113 + #define ACP_P1_AUDIO1_RX_THRESHOLD BIT(5) 114 + #define ACP_SDW_DMA_IRQ_MASK 0x1F800000 115 + #define ACP_P1_SDW_DMA_IRQ_MASK 0x60 116 + #define ACP63_SDW0_DMA_MAX_STREAMS 6 117 + #define ACP63_SDW1_DMA_MAX_STREAMS 2 118 + #define ACP_P1_AUDIO_TX_THRESHOLD 6 119 + #define SDW0_DMA_TX_IRQ_MASK(i) (ACP_AUDIO0_TX_THRESHOLD - (2 * (i))) 120 + #define SDW0_DMA_RX_IRQ_MASK(i) (ACP_AUDIO0_RX_THRESHOLD - (2 * (i))) 121 + #define SDW1_DMA_IRQ_MASK(i) (ACP_P1_AUDIO_TX_THRESHOLD - (i)) 122 + 123 + #define ACP_DELAY_US 5 124 + #define ACP_SDW_RING_BUFF_ADDR_OFFSET (128 * 1024) 125 + #define SDW0_MEM_WINDOW_START 0x4800000 126 + #define ACP_SDW_SRAM_PTE_OFFSET 0x03800400 127 + #define SDW0_PTE_OFFSET 0x400 128 + #define SDW_FIFO_SIZE 0x100 129 + #define SDW_DMA_SIZE 0x40 130 + #define ACP_SDW0_FIFO_OFFSET 0x100 131 + #define ACP_SDW_PTE_OFFSET 0x100 132 + #define SDW_FIFO_OFFSET 0x100 133 + #define SDW_PTE_OFFSET(i) (SDW0_PTE_OFFSET + ((i) * 0x600)) 134 + #define ACP_SDW_FIFO_OFFSET(i) (ACP_SDW0_FIFO_OFFSET + ((i) * 0x500)) 135 + #define SDW_MEM_WINDOW_START(i) (SDW0_MEM_WINDOW_START + ((i) * 0xC0000)) 136 + 137 + #define SDW_PLAYBACK_MIN_NUM_PERIODS 2 138 + #define SDW_PLAYBACK_MAX_NUM_PERIODS 8 139 + #define SDW_PLAYBACK_MAX_PERIOD_SIZE 8192 140 + #define SDW_PLAYBACK_MIN_PERIOD_SIZE 1024 141 + #define SDW_CAPTURE_MIN_NUM_PERIODS 2 142 + #define SDW_CAPTURE_MAX_NUM_PERIODS 8 143 + #define SDW_CAPTURE_MAX_PERIOD_SIZE 8192 144 + #define SDW_CAPTURE_MIN_PERIOD_SIZE 1024 145 + 146 + #define SDW_MAX_BUFFER (SDW_PLAYBACK_MAX_PERIOD_SIZE * SDW_PLAYBACK_MAX_NUM_PERIODS) 147 + #define SDW_MIN_BUFFER SDW_MAX_BUFFER 63 148 64 149 enum acp_config { 65 150 ACP_CONFIG_0 = 0, ··· 165 80 ACP_CONFIG_15, 166 81 }; 167 82 83 + enum amd_sdw0_channel { 84 + ACP_SDW0_AUDIO0_TX = 0, 85 + ACP_SDW0_AUDIO1_TX, 86 + ACP_SDW0_AUDIO2_TX, 87 + ACP_SDW0_AUDIO0_RX, 88 + ACP_SDW0_AUDIO1_RX, 89 + ACP_SDW0_AUDIO2_RX, 90 + }; 91 + 92 + enum amd_sdw1_channel { 93 + ACP_SDW1_AUDIO1_TX, 94 + ACP_SDW1_AUDIO1_RX, 95 + }; 96 + 168 97 struct pdm_stream_instance { 169 98 u16 num_pages; 170 99 u16 channels; ··· 194 95 struct snd_pcm_substream *capture_stream; 195 96 }; 196 97 98 + struct sdw_dma_dev_data { 99 + void __iomem *acp_base; 100 + struct mutex *acp_lock; /* used to protect acp common register access */ 101 + struct snd_pcm_substream *sdw0_dma_stream[ACP63_SDW0_DMA_MAX_STREAMS]; 102 + struct snd_pcm_substream *sdw1_dma_stream[ACP63_SDW1_DMA_MAX_STREAMS]; 103 + }; 104 + 105 + struct acp_sdw_dma_stream { 106 + u16 num_pages; 107 + u16 channels; 108 + u32 stream_id; 109 + u32 instance; 110 + dma_addr_t dma_addr; 111 + u64 bytescount; 112 + }; 113 + 114 + union acp_sdw_dma_count { 115 + struct { 116 + u32 low; 117 + u32 high; 118 + } bcount; 119 + u64 bytescount; 120 + }; 121 + 122 + struct sdw_dma_ring_buf_reg { 123 + u32 reg_dma_size; 124 + u32 reg_fifo_addr; 125 + u32 reg_fifo_size; 126 + u32 reg_ring_buf_size; 127 + u32 reg_ring_buf_addr; 128 + u32 water_mark_size_reg; 129 + u32 pos_low_reg; 130 + u32 pos_high_reg; 131 + }; 132 + 133 + /** 134 + * struct acp63_dev_data - acp pci driver context 135 + * @acp63_base: acp mmio base 136 + * @res: resource 137 + * @pdev: array of child platform device node structures 138 + * @acp_lock: used to protect acp common registers 139 + * @sdw_fw_node: SoundWire controller fw node handle 140 + * @pdev_config: platform device configuration 141 + * @pdev_count: platform devices count 142 + * @pdm_dev_index: pdm platform device index 143 + * @sdw_manager_count: SoundWire manager instance count 144 + * @sdw0_dev_index: SoundWire Manager-0 platform device index 145 + * @sdw1_dev_index: SoundWire Manager-1 platform device index 146 + * @sdw_dma_dev_index: SoundWire DMA controller platform device index 147 + * @sdw0-dma_intr_stat: DMA interrupt status array for SoundWire manager-SW0 instance 148 + * @sdw_dma_intr_stat: DMA interrupt status array for SoundWire manager-SW1 instance 149 + * @acp_reset: flag set to true when bus reset is applied across all 150 + * the active SoundWire manager instances 151 + */ 152 + 197 153 struct acp63_dev_data { 198 154 void __iomem *acp63_base; 199 155 struct resource *res; 200 156 struct platform_device *pdev[ACP63_DEVS]; 201 157 struct mutex acp_lock; /* protect shared registers */ 202 - u16 pdev_mask; 158 + struct fwnode_handle *sdw_fw_node; 159 + u16 pdev_config; 203 160 u16 pdev_count; 204 161 u16 pdm_dev_index; 162 + u8 sdw_manager_count; 163 + u16 sdw0_dev_index; 164 + u16 sdw1_dev_index; 165 + u16 sdw_dma_dev_index; 166 + u16 sdw0_dma_intr_stat[ACP63_SDW0_DMA_MAX_STREAMS]; 167 + u16 sdw1_dma_intr_stat[ACP63_SDW1_DMA_MAX_STREAMS]; 168 + bool acp_reset; 205 169 }; 206 170 207 171 int snd_amd_acp_find_config(struct pci_dev *pci);
+392 -33
sound/soc/amd/ps/pci-ps.c
··· 6 6 */ 7 7 8 8 #include <linux/pci.h> 9 + #include <linux/bitops.h> 9 10 #include <linux/module.h> 10 11 #include <linux/io.h> 11 12 #include <linux/delay.h> ··· 16 15 #include <sound/pcm_params.h> 17 16 #include <linux/pm_runtime.h> 18 17 #include <linux/iopoll.h> 18 + #include <linux/soundwire/sdw_amd.h> 19 19 20 20 #include "acp63.h" 21 21 ··· 56 54 static void acp63_enable_interrupts(void __iomem *acp_base) 57 55 { 58 56 writel(1, acp_base + ACP_EXTERNAL_INTR_ENB); 57 + writel(ACP_ERROR_IRQ, acp_base + ACP_EXTERNAL_INTR_CNTL); 59 58 } 60 59 61 60 static void acp63_disable_interrupts(void __iomem *acp_base) ··· 99 96 return 0; 100 97 } 101 98 99 + static irqreturn_t acp63_irq_thread(int irq, void *context) 100 + { 101 + struct sdw_dma_dev_data *sdw_dma_data; 102 + struct acp63_dev_data *adata = context; 103 + u32 stream_index; 104 + u16 pdev_index; 105 + 106 + pdev_index = adata->sdw_dma_dev_index; 107 + sdw_dma_data = dev_get_drvdata(&adata->pdev[pdev_index]->dev); 108 + 109 + for (stream_index = 0; stream_index < ACP63_SDW0_DMA_MAX_STREAMS; stream_index++) { 110 + if (adata->sdw0_dma_intr_stat[stream_index]) { 111 + if (sdw_dma_data->sdw0_dma_stream[stream_index]) 112 + snd_pcm_period_elapsed(sdw_dma_data->sdw0_dma_stream[stream_index]); 113 + adata->sdw0_dma_intr_stat[stream_index] = 0; 114 + } 115 + } 116 + for (stream_index = 0; stream_index < ACP63_SDW1_DMA_MAX_STREAMS; stream_index++) { 117 + if (adata->sdw1_dma_intr_stat[stream_index]) { 118 + if (sdw_dma_data->sdw1_dma_stream[stream_index]) 119 + snd_pcm_period_elapsed(sdw_dma_data->sdw1_dma_stream[stream_index]); 120 + adata->sdw1_dma_intr_stat[stream_index] = 0; 121 + } 122 + } 123 + return IRQ_HANDLED; 124 + } 125 + 102 126 static irqreturn_t acp63_irq_handler(int irq, void *dev_id) 103 127 { 104 128 struct acp63_dev_data *adata; 105 129 struct pdm_dev_data *ps_pdm_data; 106 - u32 val; 130 + struct amd_sdw_manager *amd_manager; 131 + u32 ext_intr_stat, ext_intr_stat1; 132 + u32 stream_id = 0; 133 + u16 irq_flag = 0; 134 + u16 sdw_dma_irq_flag = 0; 107 135 u16 pdev_index; 136 + u16 index; 108 137 109 138 adata = dev_id; 110 139 if (!adata) 111 140 return IRQ_NONE; 141 + /* ACP interrupts will be cleared by reading particular bit and writing 142 + * same value to the status register. writing zero's doesn't have any 143 + * effect. 144 + * Bit by bit checking of IRQ field is implemented. 145 + */ 146 + ext_intr_stat = readl(adata->acp63_base + ACP_EXTERNAL_INTR_STAT); 147 + if (ext_intr_stat & ACP_SDW0_STAT) { 148 + writel(ACP_SDW0_STAT, adata->acp63_base + ACP_EXTERNAL_INTR_STAT); 149 + pdev_index = adata->sdw0_dev_index; 150 + amd_manager = dev_get_drvdata(&adata->pdev[pdev_index]->dev); 151 + if (amd_manager) 152 + schedule_work(&amd_manager->amd_sdw_irq_thread); 153 + irq_flag = 1; 154 + } 112 155 113 - val = readl(adata->acp63_base + ACP_EXTERNAL_INTR_STAT); 114 - if (val & BIT(PDM_DMA_STAT)) { 156 + ext_intr_stat1 = readl(adata->acp63_base + ACP_EXTERNAL_INTR_STAT1); 157 + if (ext_intr_stat1 & ACP_SDW1_STAT) { 158 + writel(ACP_SDW1_STAT, adata->acp63_base + ACP_EXTERNAL_INTR_STAT1); 159 + pdev_index = adata->sdw1_dev_index; 160 + amd_manager = dev_get_drvdata(&adata->pdev[pdev_index]->dev); 161 + if (amd_manager) 162 + schedule_work(&amd_manager->amd_sdw_irq_thread); 163 + irq_flag = 1; 164 + } 165 + 166 + if (ext_intr_stat & ACP_ERROR_IRQ) { 167 + writel(ACP_ERROR_IRQ, adata->acp63_base + ACP_EXTERNAL_INTR_STAT); 168 + /* TODO: Report SoundWire Manager instance errors */ 169 + writel(0, adata->acp63_base + ACP_SW0_I2S_ERROR_REASON); 170 + writel(0, adata->acp63_base + ACP_SW1_I2S_ERROR_REASON); 171 + writel(0, adata->acp63_base + ACP_ERROR_STATUS); 172 + irq_flag = 1; 173 + } 174 + 175 + if (ext_intr_stat & BIT(PDM_DMA_STAT)) { 115 176 pdev_index = adata->pdm_dev_index; 116 177 ps_pdm_data = dev_get_drvdata(&adata->pdev[pdev_index]->dev); 117 178 writel(BIT(PDM_DMA_STAT), adata->acp63_base + ACP_EXTERNAL_INTR_STAT); 118 179 if (ps_pdm_data->capture_stream) 119 180 snd_pcm_period_elapsed(ps_pdm_data->capture_stream); 120 - return IRQ_HANDLED; 181 + irq_flag = 1; 121 182 } 122 - return IRQ_NONE; 183 + if (ext_intr_stat & ACP_SDW_DMA_IRQ_MASK) { 184 + for (index = ACP_AUDIO2_RX_THRESHOLD; index <= ACP_AUDIO0_TX_THRESHOLD; index++) { 185 + if (ext_intr_stat & BIT(index)) { 186 + writel(BIT(index), adata->acp63_base + ACP_EXTERNAL_INTR_STAT); 187 + switch (index) { 188 + case ACP_AUDIO0_TX_THRESHOLD: 189 + stream_id = ACP_SDW0_AUDIO0_TX; 190 + break; 191 + case ACP_AUDIO1_TX_THRESHOLD: 192 + stream_id = ACP_SDW0_AUDIO1_TX; 193 + break; 194 + case ACP_AUDIO2_TX_THRESHOLD: 195 + stream_id = ACP_SDW0_AUDIO2_TX; 196 + break; 197 + case ACP_AUDIO0_RX_THRESHOLD: 198 + stream_id = ACP_SDW0_AUDIO0_RX; 199 + break; 200 + case ACP_AUDIO1_RX_THRESHOLD: 201 + stream_id = ACP_SDW0_AUDIO1_RX; 202 + break; 203 + case ACP_AUDIO2_RX_THRESHOLD: 204 + stream_id = ACP_SDW0_AUDIO2_RX; 205 + break; 206 + } 207 + 208 + adata->sdw0_dma_intr_stat[stream_id] = 1; 209 + sdw_dma_irq_flag = 1; 210 + } 211 + } 212 + } 213 + 214 + if (ext_intr_stat1 & ACP_P1_AUDIO1_RX_THRESHOLD) { 215 + writel(ACP_P1_AUDIO1_RX_THRESHOLD, 216 + adata->acp63_base + ACP_EXTERNAL_INTR_STAT1); 217 + adata->sdw1_dma_intr_stat[ACP_SDW1_AUDIO1_RX] = 1; 218 + sdw_dma_irq_flag = 1; 219 + } 220 + 221 + if (ext_intr_stat1 & ACP_P1_AUDIO1_TX_THRESHOLD) { 222 + writel(ACP_P1_AUDIO1_TX_THRESHOLD, 223 + adata->acp63_base + ACP_EXTERNAL_INTR_STAT1); 224 + adata->sdw1_dma_intr_stat[ACP_SDW1_AUDIO1_TX] = 1; 225 + sdw_dma_irq_flag = 1; 226 + } 227 + 228 + if (sdw_dma_irq_flag) 229 + return IRQ_WAKE_THREAD; 230 + 231 + if (irq_flag) 232 + return IRQ_HANDLED; 233 + else 234 + return IRQ_NONE; 123 235 } 124 236 125 - static void get_acp63_device_config(u32 config, struct pci_dev *pci, 126 - struct acp63_dev_data *acp_data) 237 + static int sdw_amd_scan_controller(struct device *dev) 238 + { 239 + struct acp63_dev_data *acp_data; 240 + struct fwnode_handle *link; 241 + char name[32]; 242 + u32 sdw_manager_bitmap; 243 + u8 count = 0; 244 + u32 acp_sdw_power_mode = 0; 245 + int index; 246 + int ret; 247 + 248 + acp_data = dev_get_drvdata(dev); 249 + /* 250 + * Current implementation is based on MIPI DisCo 2.0 spec. 251 + * Found controller, find links supported. 252 + */ 253 + ret = fwnode_property_read_u32_array((acp_data->sdw_fw_node), "mipi-sdw-manager-list", 254 + &sdw_manager_bitmap, 1); 255 + 256 + if (ret) { 257 + dev_err(dev, "Failed to read mipi-sdw-manager-list: %d\n", ret); 258 + return -EINVAL; 259 + } 260 + count = hweight32(sdw_manager_bitmap); 261 + /* Check count is within bounds */ 262 + if (count > AMD_SDW_MAX_MANAGERS) { 263 + dev_err(dev, "Manager count %d exceeds max %d\n", count, AMD_SDW_MAX_MANAGERS); 264 + return -EINVAL; 265 + } 266 + 267 + if (!count) { 268 + dev_dbg(dev, "No SoundWire Managers detected\n"); 269 + return -EINVAL; 270 + } 271 + dev_dbg(dev, "ACPI reports %d SoundWire Manager devices\n", count); 272 + acp_data->sdw_manager_count = count; 273 + for (index = 0; index < count; index++) { 274 + snprintf(name, sizeof(name), "mipi-sdw-link-%d-subproperties", index); 275 + link = fwnode_get_named_child_node(acp_data->sdw_fw_node, name); 276 + if (!link) { 277 + dev_err(dev, "Manager node %s not found\n", name); 278 + return -EIO; 279 + } 280 + 281 + ret = fwnode_property_read_u32(link, "amd-sdw-power-mode", &acp_sdw_power_mode); 282 + if (ret) 283 + return ret; 284 + /* 285 + * when SoundWire configuration is selected from acp pin config, 286 + * based on manager instances count, acp init/de-init sequence should be 287 + * executed as part of PM ops only when Bus reset is applied for the active 288 + * SoundWire manager instances. 289 + */ 290 + if (acp_sdw_power_mode != AMD_SDW_POWER_OFF_MODE) { 291 + acp_data->acp_reset = false; 292 + return 0; 293 + } 294 + } 295 + return 0; 296 + } 297 + 298 + static int get_acp63_device_config(u32 config, struct pci_dev *pci, struct acp63_dev_data *acp_data) 127 299 { 128 300 struct acpi_device *dmic_dev; 301 + struct acpi_device *sdw_dev; 129 302 const union acpi_object *obj; 130 303 bool is_dmic_dev = false; 304 + bool is_sdw_dev = false; 305 + int ret; 131 306 132 307 dmic_dev = acpi_find_child_device(ACPI_COMPANION(&pci->dev), ACP63_DMIC_ADDR, 0); 133 308 if (dmic_dev) { 309 + /* is_dmic_dev flag will be set when ACP PDM controller device exists */ 134 310 if (!acpi_dev_get_property(dmic_dev, "acp-audio-device-type", 135 311 ACPI_TYPE_INTEGER, &obj) && 136 312 obj->integer.value == ACP_DMIC_DEV) 137 313 is_dmic_dev = true; 138 314 } 139 315 316 + sdw_dev = acpi_find_child_device(ACPI_COMPANION(&pci->dev), ACP63_SDW_ADDR, 0); 317 + if (sdw_dev) { 318 + acp_data->sdw_fw_node = acpi_fwnode_handle(sdw_dev); 319 + ret = sdw_amd_scan_controller(&pci->dev); 320 + /* is_sdw_dev flag will be set when SoundWire Manager device exists */ 321 + if (!ret) 322 + is_sdw_dev = true; 323 + } 324 + if (!is_dmic_dev && !is_sdw_dev) 325 + return -ENODEV; 326 + dev_dbg(&pci->dev, "Audio Mode %d\n", config); 140 327 switch (config) { 141 - case ACP_CONFIG_0: 142 - case ACP_CONFIG_1: 143 - case ACP_CONFIG_2: 144 - case ACP_CONFIG_3: 145 - case ACP_CONFIG_9: 146 - case ACP_CONFIG_15: 147 - dev_dbg(&pci->dev, "Audio Mode %d\n", config); 148 - break; 149 - default: 328 + case ACP_CONFIG_4: 329 + case ACP_CONFIG_5: 330 + case ACP_CONFIG_10: 331 + case ACP_CONFIG_11: 150 332 if (is_dmic_dev) { 151 - acp_data->pdev_mask = ACP63_PDM_DEV_MASK; 333 + acp_data->pdev_config = ACP63_PDM_DEV_CONFIG; 152 334 acp_data->pdev_count = ACP63_PDM_MODE_DEVS; 153 335 } 154 336 break; 337 + case ACP_CONFIG_2: 338 + case ACP_CONFIG_3: 339 + if (is_sdw_dev) { 340 + switch (acp_data->sdw_manager_count) { 341 + case 1: 342 + acp_data->pdev_config = ACP63_SDW_DEV_CONFIG; 343 + acp_data->pdev_count = ACP63_SDW0_MODE_DEVS; 344 + break; 345 + case 2: 346 + acp_data->pdev_config = ACP63_SDW_DEV_CONFIG; 347 + acp_data->pdev_count = ACP63_SDW0_SDW1_MODE_DEVS; 348 + break; 349 + default: 350 + return -EINVAL; 351 + } 352 + } 353 + break; 354 + case ACP_CONFIG_6: 355 + case ACP_CONFIG_7: 356 + case ACP_CONFIG_12: 357 + case ACP_CONFIG_8: 358 + case ACP_CONFIG_13: 359 + case ACP_CONFIG_14: 360 + if (is_dmic_dev && is_sdw_dev) { 361 + switch (acp_data->sdw_manager_count) { 362 + case 1: 363 + acp_data->pdev_config = ACP63_SDW_PDM_DEV_CONFIG; 364 + acp_data->pdev_count = ACP63_SDW0_PDM_MODE_DEVS; 365 + break; 366 + case 2: 367 + acp_data->pdev_config = ACP63_SDW_PDM_DEV_CONFIG; 368 + acp_data->pdev_count = ACP63_SDW0_SDW1_PDM_MODE_DEVS; 369 + break; 370 + default: 371 + return -EINVAL; 372 + } 373 + } else if (is_dmic_dev) { 374 + acp_data->pdev_config = ACP63_PDM_DEV_CONFIG; 375 + acp_data->pdev_count = ACP63_PDM_MODE_DEVS; 376 + } else if (is_sdw_dev) { 377 + switch (acp_data->sdw_manager_count) { 378 + case 1: 379 + acp_data->pdev_config = ACP63_SDW_DEV_CONFIG; 380 + acp_data->pdev_count = ACP63_SDW0_MODE_DEVS; 381 + break; 382 + case 2: 383 + acp_data->pdev_config = ACP63_SDW_DEV_CONFIG; 384 + acp_data->pdev_count = ACP63_SDW0_SDW1_MODE_DEVS; 385 + break; 386 + default: 387 + return -EINVAL; 388 + } 389 + } 390 + break; 391 + default: 392 + break; 155 393 } 394 + return 0; 156 395 } 157 396 158 397 static void acp63_fill_platform_dev_info(struct platform_device_info *pdevinfo, ··· 418 173 419 174 static int create_acp63_platform_devs(struct pci_dev *pci, struct acp63_dev_data *adata, u32 addr) 420 175 { 176 + struct acp_sdw_pdata *sdw_pdata; 421 177 struct platform_device_info pdevinfo[ACP63_DEVS]; 422 178 struct device *parent; 423 179 int index; ··· 426 180 427 181 parent = &pci->dev; 428 182 dev_dbg(&pci->dev, 429 - "%s pdev_mask:0x%x pdev_count:0x%x\n", __func__, adata->pdev_mask, 183 + "%s pdev_config:0x%x pdev_count:0x%x\n", __func__, adata->pdev_config, 430 184 adata->pdev_count); 431 - if (adata->pdev_mask) { 185 + if (adata->pdev_config) { 432 186 adata->res = devm_kzalloc(&pci->dev, sizeof(struct resource), GFP_KERNEL); 433 187 if (!adata->res) { 434 188 ret = -ENOMEM; ··· 440 194 memset(&pdevinfo, 0, sizeof(pdevinfo)); 441 195 } 442 196 443 - switch (adata->pdev_mask) { 444 - case ACP63_PDM_DEV_MASK: 197 + switch (adata->pdev_config) { 198 + case ACP63_PDM_DEV_CONFIG: 445 199 adata->pdm_dev_index = 0; 446 200 acp63_fill_platform_dev_info(&pdevinfo[0], parent, NULL, "acp_ps_pdm_dma", 447 201 0, adata->res, 1, NULL, 0); ··· 450 204 acp63_fill_platform_dev_info(&pdevinfo[2], parent, NULL, "acp_ps_mach", 451 205 0, NULL, 0, NULL, 0); 452 206 break; 207 + case ACP63_SDW_DEV_CONFIG: 208 + if (adata->pdev_count == ACP63_SDW0_MODE_DEVS) { 209 + sdw_pdata = devm_kzalloc(&pci->dev, sizeof(struct acp_sdw_pdata), 210 + GFP_KERNEL); 211 + if (!sdw_pdata) { 212 + ret = -ENOMEM; 213 + goto de_init; 214 + } 215 + 216 + sdw_pdata->instance = 0; 217 + sdw_pdata->acp_sdw_lock = &adata->acp_lock; 218 + adata->sdw0_dev_index = 0; 219 + adata->sdw_dma_dev_index = 1; 220 + acp63_fill_platform_dev_info(&pdevinfo[0], parent, adata->sdw_fw_node, 221 + "amd_sdw_manager", 0, adata->res, 1, 222 + sdw_pdata, sizeof(struct acp_sdw_pdata)); 223 + acp63_fill_platform_dev_info(&pdevinfo[1], parent, NULL, "amd_ps_sdw_dma", 224 + 0, adata->res, 1, NULL, 0); 225 + } else if (adata->pdev_count == ACP63_SDW0_SDW1_MODE_DEVS) { 226 + sdw_pdata = devm_kzalloc(&pci->dev, sizeof(struct acp_sdw_pdata) * 2, 227 + GFP_KERNEL); 228 + if (!sdw_pdata) { 229 + ret = -ENOMEM; 230 + goto de_init; 231 + } 232 + 233 + sdw_pdata[0].instance = 0; 234 + sdw_pdata[1].instance = 1; 235 + sdw_pdata[0].acp_sdw_lock = &adata->acp_lock; 236 + sdw_pdata[1].acp_sdw_lock = &adata->acp_lock; 237 + sdw_pdata->acp_sdw_lock = &adata->acp_lock; 238 + adata->sdw0_dev_index = 0; 239 + adata->sdw1_dev_index = 1; 240 + adata->sdw_dma_dev_index = 2; 241 + acp63_fill_platform_dev_info(&pdevinfo[0], parent, adata->sdw_fw_node, 242 + "amd_sdw_manager", 0, adata->res, 1, 243 + &sdw_pdata[0], sizeof(struct acp_sdw_pdata)); 244 + acp63_fill_platform_dev_info(&pdevinfo[1], parent, adata->sdw_fw_node, 245 + "amd_sdw_manager", 1, adata->res, 1, 246 + &sdw_pdata[1], sizeof(struct acp_sdw_pdata)); 247 + acp63_fill_platform_dev_info(&pdevinfo[2], parent, NULL, "amd_ps_sdw_dma", 248 + 0, adata->res, 1, NULL, 0); 249 + } 250 + break; 251 + case ACP63_SDW_PDM_DEV_CONFIG: 252 + if (adata->pdev_count == ACP63_SDW0_PDM_MODE_DEVS) { 253 + sdw_pdata = devm_kzalloc(&pci->dev, sizeof(struct acp_sdw_pdata), 254 + GFP_KERNEL); 255 + if (!sdw_pdata) { 256 + ret = -ENOMEM; 257 + goto de_init; 258 + } 259 + 260 + sdw_pdata->instance = 0; 261 + sdw_pdata->acp_sdw_lock = &adata->acp_lock; 262 + adata->pdm_dev_index = 0; 263 + adata->sdw0_dev_index = 1; 264 + adata->sdw_dma_dev_index = 2; 265 + acp63_fill_platform_dev_info(&pdevinfo[0], parent, NULL, "acp_ps_pdm_dma", 266 + 0, adata->res, 1, NULL, 0); 267 + acp63_fill_platform_dev_info(&pdevinfo[1], parent, adata->sdw_fw_node, 268 + "amd_sdw_manager", 0, adata->res, 1, 269 + sdw_pdata, sizeof(struct acp_sdw_pdata)); 270 + acp63_fill_platform_dev_info(&pdevinfo[2], parent, NULL, "amd_ps_sdw_dma", 271 + 0, adata->res, 1, NULL, 0); 272 + acp63_fill_platform_dev_info(&pdevinfo[3], parent, NULL, "dmic-codec", 273 + 0, NULL, 0, NULL, 0); 274 + } else if (adata->pdev_count == ACP63_SDW0_SDW1_PDM_MODE_DEVS) { 275 + sdw_pdata = devm_kzalloc(&pci->dev, sizeof(struct acp_sdw_pdata) * 2, 276 + GFP_KERNEL); 277 + if (!sdw_pdata) { 278 + ret = -ENOMEM; 279 + goto de_init; 280 + } 281 + sdw_pdata[0].instance = 0; 282 + sdw_pdata[1].instance = 1; 283 + sdw_pdata[0].acp_sdw_lock = &adata->acp_lock; 284 + sdw_pdata[1].acp_sdw_lock = &adata->acp_lock; 285 + adata->pdm_dev_index = 0; 286 + adata->sdw0_dev_index = 1; 287 + adata->sdw1_dev_index = 2; 288 + adata->sdw_dma_dev_index = 3; 289 + acp63_fill_platform_dev_info(&pdevinfo[0], parent, NULL, "acp_ps_pdm_dma", 290 + 0, adata->res, 1, NULL, 0); 291 + acp63_fill_platform_dev_info(&pdevinfo[1], parent, adata->sdw_fw_node, 292 + "amd_sdw_manager", 0, adata->res, 1, 293 + &sdw_pdata[0], sizeof(struct acp_sdw_pdata)); 294 + acp63_fill_platform_dev_info(&pdevinfo[2], parent, adata->sdw_fw_node, 295 + "amd_sdw_manager", 1, adata->res, 1, 296 + &sdw_pdata[1], sizeof(struct acp_sdw_pdata)); 297 + acp63_fill_platform_dev_info(&pdevinfo[3], parent, NULL, "amd_ps_sdw_dma", 298 + 0, adata->res, 1, NULL, 0); 299 + acp63_fill_platform_dev_info(&pdevinfo[4], parent, NULL, "dmic-codec", 300 + 0, NULL, 0, NULL, 0); 301 + } 302 + break; 453 303 default: 454 - dev_dbg(&pci->dev, "No PDM devices found\n"); 304 + dev_dbg(&pci->dev, "No PDM or SoundWire manager devices found\n"); 455 305 return 0; 456 306 } 457 307 ··· 618 276 ret = -ENOMEM; 619 277 goto release_regions; 620 278 } 279 + /* 280 + * By default acp_reset flag is set to true. i.e acp_deinit() and acp_init() 281 + * will be invoked for all ACP configurations during suspend/resume callbacks. 282 + * This flag should be set to false only when SoundWire manager power mode 283 + * set to ClockStopMode. 284 + */ 285 + adata->acp_reset = true; 621 286 pci_set_master(pci); 622 287 pci_set_drvdata(pci, adata); 623 288 mutex_init(&adata->acp_lock); 624 289 ret = acp63_init(adata->acp63_base, &pci->dev); 625 290 if (ret) 626 291 goto release_regions; 627 - ret = devm_request_irq(&pci->dev, pci->irq, acp63_irq_handler, 628 - irqflags, "ACP_PCI_IRQ", adata); 292 + ret = devm_request_threaded_irq(&pci->dev, pci->irq, acp63_irq_handler, 293 + acp63_irq_thread, irqflags, "ACP_PCI_IRQ", adata); 629 294 if (ret) { 630 295 dev_err(&pci->dev, "ACP PCI IRQ request failed\n"); 631 296 goto de_init; 632 297 } 633 298 val = readl(adata->acp63_base + ACP_PIN_CONFIG); 634 - get_acp63_device_config(val, pci, adata); 299 + ret = get_acp63_device_config(val, pci, adata); 300 + /* ACP PCI driver probe should be continued even PDM or SoundWire Devices are not found */ 301 + if (ret) { 302 + dev_err(&pci->dev, "get acp device config failed:%d\n", ret); 303 + goto skip_pdev_creation; 304 + } 635 305 ret = create_acp63_platform_devs(pci, adata, addr); 636 306 if (ret < 0) { 637 307 dev_err(&pci->dev, "ACP platform devices creation failed\n"); 638 308 goto de_init; 639 309 } 310 + skip_pdev_creation: 640 311 pm_runtime_set_autosuspend_delay(&pci->dev, ACP_SUSPEND_DELAY_MS); 641 312 pm_runtime_use_autosuspend(&pci->dev); 642 313 pm_runtime_put_noidle(&pci->dev); ··· 669 314 static int __maybe_unused snd_acp63_suspend(struct device *dev) 670 315 { 671 316 struct acp63_dev_data *adata; 672 - int ret; 317 + int ret = 0; 673 318 674 319 adata = dev_get_drvdata(dev); 675 - ret = acp63_deinit(adata->acp63_base, dev); 676 - if (ret) 677 - dev_err(dev, "ACP de-init failed\n"); 320 + if (adata->acp_reset) { 321 + ret = acp63_deinit(adata->acp63_base, dev); 322 + if (ret) 323 + dev_err(dev, "ACP de-init failed\n"); 324 + } 678 325 return ret; 679 326 } 680 327 681 328 static int __maybe_unused snd_acp63_resume(struct device *dev) 682 329 { 683 330 struct acp63_dev_data *adata; 684 - int ret; 331 + int ret = 0; 685 332 686 333 adata = dev_get_drvdata(dev); 687 - ret = acp63_init(adata->acp63_base, dev); 688 - if (ret) 689 - dev_err(dev, "ACP init failed\n"); 334 + if (adata->acp_reset) { 335 + ret = acp63_init(adata->acp63_base, dev); 336 + if (ret) 337 + dev_err(dev, "ACP init failed\n"); 338 + } 690 339 return ret; 691 340 } 692 341
+555
sound/soc/amd/ps/ps-sdw-dma.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* 3 + * AMD ALSA SoC Pink Sardine SoundWire DMA Driver 4 + * 5 + * Copyright 2023 Advanced Micro Devices, Inc. 6 + */ 7 + 8 + #include <linux/err.h> 9 + #include <linux/io.h> 10 + #include <linux/module.h> 11 + #include <linux/platform_device.h> 12 + #include <sound/pcm_params.h> 13 + #include <sound/soc.h> 14 + #include <sound/soc-dai.h> 15 + #include <linux/pm_runtime.h> 16 + #include <linux/soundwire/sdw_amd.h> 17 + #include "acp63.h" 18 + 19 + #define DRV_NAME "amd_ps_sdw_dma" 20 + 21 + static struct sdw_dma_ring_buf_reg sdw0_dma_ring_buf_reg[ACP63_SDW0_DMA_MAX_STREAMS] = { 22 + {ACP_AUDIO0_TX_DMA_SIZE, ACP_AUDIO0_TX_FIFOADDR, ACP_AUDIO0_TX_FIFOSIZE, 23 + ACP_AUDIO0_TX_RINGBUFSIZE, ACP_AUDIO0_TX_RINGBUFADDR, ACP_AUDIO0_TX_INTR_WATERMARK_SIZE, 24 + ACP_AUDIO0_TX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO0_TX_LINEARPOSITIONCNTR_HIGH}, 25 + {ACP_AUDIO1_TX_DMA_SIZE, ACP_AUDIO1_TX_FIFOADDR, ACP_AUDIO1_TX_FIFOSIZE, 26 + ACP_AUDIO1_TX_RINGBUFSIZE, ACP_AUDIO1_TX_RINGBUFADDR, ACP_AUDIO1_TX_INTR_WATERMARK_SIZE, 27 + ACP_AUDIO1_TX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO1_TX_LINEARPOSITIONCNTR_HIGH}, 28 + {ACP_AUDIO2_TX_DMA_SIZE, ACP_AUDIO2_TX_FIFOADDR, ACP_AUDIO2_TX_FIFOSIZE, 29 + ACP_AUDIO2_TX_RINGBUFSIZE, ACP_AUDIO2_TX_RINGBUFADDR, ACP_AUDIO2_TX_INTR_WATERMARK_SIZE, 30 + ACP_AUDIO2_TX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO2_TX_LINEARPOSITIONCNTR_HIGH}, 31 + {ACP_AUDIO0_RX_DMA_SIZE, ACP_AUDIO0_RX_FIFOADDR, ACP_AUDIO0_RX_FIFOSIZE, 32 + ACP_AUDIO0_RX_RINGBUFSIZE, ACP_AUDIO0_RX_RINGBUFADDR, ACP_AUDIO0_RX_INTR_WATERMARK_SIZE, 33 + ACP_AUDIO0_TX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO0_TX_LINEARPOSITIONCNTR_HIGH}, 34 + {ACP_AUDIO1_RX_DMA_SIZE, ACP_AUDIO1_RX_FIFOADDR, ACP_AUDIO1_RX_FIFOSIZE, 35 + ACP_AUDIO1_RX_RINGBUFSIZE, ACP_AUDIO1_RX_RINGBUFADDR, ACP_AUDIO1_RX_INTR_WATERMARK_SIZE, 36 + ACP_AUDIO1_RX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO1_RX_LINEARPOSITIONCNTR_HIGH}, 37 + {ACP_AUDIO2_RX_DMA_SIZE, ACP_AUDIO2_RX_FIFOADDR, ACP_AUDIO2_RX_FIFOSIZE, 38 + ACP_AUDIO2_RX_RINGBUFSIZE, ACP_AUDIO2_RX_RINGBUFADDR, ACP_AUDIO2_RX_INTR_WATERMARK_SIZE, 39 + ACP_AUDIO2_RX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO2_RX_LINEARPOSITIONCNTR_HIGH} 40 + }; 41 + 42 + static struct sdw_dma_ring_buf_reg sdw1_dma_ring_buf_reg[ACP63_SDW1_DMA_MAX_STREAMS] = { 43 + {ACP_P1_AUDIO1_TX_DMA_SIZE, ACP_P1_AUDIO1_TX_FIFOADDR, ACP_P1_AUDIO1_TX_FIFOSIZE, 44 + ACP_P1_AUDIO1_TX_RINGBUFSIZE, ACP_P1_AUDIO1_TX_RINGBUFADDR, 45 + ACP_P1_AUDIO1_TX_INTR_WATERMARK_SIZE, 46 + ACP_P1_AUDIO1_TX_LINEARPOSITIONCNTR_LOW, ACP_P1_AUDIO1_TX_LINEARPOSITIONCNTR_HIGH}, 47 + {ACP_P1_AUDIO1_RX_DMA_SIZE, ACP_P1_AUDIO1_RX_FIFOADDR, ACP_P1_AUDIO1_RX_FIFOSIZE, 48 + ACP_P1_AUDIO1_RX_RINGBUFSIZE, ACP_P1_AUDIO1_RX_RINGBUFADDR, 49 + ACP_P1_AUDIO1_RX_INTR_WATERMARK_SIZE, 50 + ACP_P1_AUDIO1_RX_LINEARPOSITIONCNTR_LOW, ACP_P1_AUDIO1_RX_LINEARPOSITIONCNTR_HIGH}, 51 + }; 52 + 53 + static u32 sdw0_dma_enable_reg[ACP63_SDW0_DMA_MAX_STREAMS] = { 54 + ACP_SW0_AUDIO0_TX_EN, 55 + ACP_SW0_AUDIO1_TX_EN, 56 + ACP_SW0_AUDIO2_TX_EN, 57 + ACP_SW0_AUDIO0_RX_EN, 58 + ACP_SW0_AUDIO1_RX_EN, 59 + ACP_SW0_AUDIO2_RX_EN, 60 + }; 61 + 62 + static u32 sdw1_dma_enable_reg[ACP63_SDW1_DMA_MAX_STREAMS] = { 63 + ACP_SW1_AUDIO1_TX_EN, 64 + ACP_SW1_AUDIO1_RX_EN, 65 + }; 66 + 67 + static const struct snd_pcm_hardware acp63_sdw_hardware_playback = { 68 + .info = SNDRV_PCM_INFO_INTERLEAVED | 69 + SNDRV_PCM_INFO_BLOCK_TRANSFER | 70 + SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | 71 + SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME, 72 + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | 73 + SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, 74 + .channels_min = 2, 75 + .channels_max = 2, 76 + .rates = SNDRV_PCM_RATE_48000, 77 + .rate_min = 48000, 78 + .rate_max = 48000, 79 + .buffer_bytes_max = SDW_PLAYBACK_MAX_NUM_PERIODS * SDW_PLAYBACK_MAX_PERIOD_SIZE, 80 + .period_bytes_min = SDW_PLAYBACK_MIN_PERIOD_SIZE, 81 + .period_bytes_max = SDW_PLAYBACK_MAX_PERIOD_SIZE, 82 + .periods_min = SDW_PLAYBACK_MIN_NUM_PERIODS, 83 + .periods_max = SDW_PLAYBACK_MAX_NUM_PERIODS, 84 + }; 85 + 86 + static const struct snd_pcm_hardware acp63_sdw_hardware_capture = { 87 + .info = SNDRV_PCM_INFO_INTERLEAVED | 88 + SNDRV_PCM_INFO_BLOCK_TRANSFER | 89 + SNDRV_PCM_INFO_MMAP | 90 + SNDRV_PCM_INFO_MMAP_VALID | 91 + SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME, 92 + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | 93 + SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, 94 + .channels_min = 2, 95 + .channels_max = 2, 96 + .rates = SNDRV_PCM_RATE_48000, 97 + .rate_min = 48000, 98 + .rate_max = 48000, 99 + .buffer_bytes_max = SDW_CAPTURE_MAX_NUM_PERIODS * SDW_CAPTURE_MAX_PERIOD_SIZE, 100 + .period_bytes_min = SDW_CAPTURE_MIN_PERIOD_SIZE, 101 + .period_bytes_max = SDW_CAPTURE_MAX_PERIOD_SIZE, 102 + .periods_min = SDW_CAPTURE_MIN_NUM_PERIODS, 103 + .periods_max = SDW_CAPTURE_MAX_NUM_PERIODS, 104 + }; 105 + 106 + static void acp63_enable_disable_sdw_dma_interrupts(void __iomem *acp_base, bool enable) 107 + { 108 + u32 ext_intr_cntl, ext_intr_cntl1; 109 + u32 irq_mask = ACP_SDW_DMA_IRQ_MASK; 110 + u32 irq_mask1 = ACP_P1_SDW_DMA_IRQ_MASK; 111 + 112 + if (enable) { 113 + ext_intr_cntl = readl(acp_base + ACP_EXTERNAL_INTR_CNTL); 114 + ext_intr_cntl |= irq_mask; 115 + writel(ext_intr_cntl, acp_base + ACP_EXTERNAL_INTR_CNTL); 116 + ext_intr_cntl1 = readl(acp_base + ACP_EXTERNAL_INTR_CNTL1); 117 + ext_intr_cntl1 |= irq_mask1; 118 + writel(ext_intr_cntl1, acp_base + ACP_EXTERNAL_INTR_CNTL1); 119 + } else { 120 + ext_intr_cntl = readl(acp_base + ACP_EXTERNAL_INTR_CNTL); 121 + ext_intr_cntl &= ~irq_mask; 122 + writel(ext_intr_cntl, acp_base + ACP_EXTERNAL_INTR_CNTL); 123 + ext_intr_cntl1 = readl(acp_base + ACP_EXTERNAL_INTR_CNTL1); 124 + ext_intr_cntl1 &= ~irq_mask1; 125 + writel(ext_intr_cntl1, acp_base + ACP_EXTERNAL_INTR_CNTL1); 126 + } 127 + } 128 + 129 + static void acp63_config_dma(struct acp_sdw_dma_stream *stream, void __iomem *acp_base, 130 + u32 stream_id) 131 + { 132 + u16 page_idx; 133 + u32 low, high, val; 134 + u32 sdw_dma_pte_offset; 135 + dma_addr_t addr; 136 + 137 + addr = stream->dma_addr; 138 + sdw_dma_pte_offset = SDW_PTE_OFFSET(stream->instance); 139 + val = sdw_dma_pte_offset + (stream_id * ACP_SDW_PTE_OFFSET); 140 + 141 + /* Group Enable */ 142 + writel(ACP_SDW_SRAM_PTE_OFFSET | BIT(31), acp_base + ACPAXI2AXI_ATU_BASE_ADDR_GRP_2); 143 + writel(PAGE_SIZE_4K_ENABLE, acp_base + ACPAXI2AXI_ATU_PAGE_SIZE_GRP_2); 144 + for (page_idx = 0; page_idx < stream->num_pages; page_idx++) { 145 + /* Load the low address of page int ACP SRAM through SRBM */ 146 + low = lower_32_bits(addr); 147 + high = upper_32_bits(addr); 148 + 149 + writel(low, acp_base + ACP_SCRATCH_REG_0 + val); 150 + high |= BIT(31); 151 + writel(high, acp_base + ACP_SCRATCH_REG_0 + val + 4); 152 + val += 8; 153 + addr += PAGE_SIZE; 154 + } 155 + writel(0x1, acp_base + ACPAXI2AXI_ATU_CTRL); 156 + } 157 + 158 + static int acp63_configure_sdw_ringbuffer(void __iomem *acp_base, u32 stream_id, u32 size, 159 + u32 manager_instance) 160 + { 161 + u32 reg_dma_size; 162 + u32 reg_fifo_addr; 163 + u32 reg_fifo_size; 164 + u32 reg_ring_buf_size; 165 + u32 reg_ring_buf_addr; 166 + u32 sdw_fifo_addr; 167 + u32 sdw_fifo_offset; 168 + u32 sdw_ring_buf_addr; 169 + u32 sdw_ring_buf_size; 170 + u32 sdw_mem_window_offset; 171 + 172 + switch (manager_instance) { 173 + case ACP_SDW0: 174 + reg_dma_size = sdw0_dma_ring_buf_reg[stream_id].reg_dma_size; 175 + reg_fifo_addr = sdw0_dma_ring_buf_reg[stream_id].reg_fifo_addr; 176 + reg_fifo_size = sdw0_dma_ring_buf_reg[stream_id].reg_fifo_size; 177 + reg_ring_buf_size = sdw0_dma_ring_buf_reg[stream_id].reg_ring_buf_size; 178 + reg_ring_buf_addr = sdw0_dma_ring_buf_reg[stream_id].reg_ring_buf_addr; 179 + break; 180 + case ACP_SDW1: 181 + reg_dma_size = sdw1_dma_ring_buf_reg[stream_id].reg_dma_size; 182 + reg_fifo_addr = sdw1_dma_ring_buf_reg[stream_id].reg_fifo_addr; 183 + reg_fifo_size = sdw1_dma_ring_buf_reg[stream_id].reg_fifo_size; 184 + reg_ring_buf_size = sdw1_dma_ring_buf_reg[stream_id].reg_ring_buf_size; 185 + reg_ring_buf_addr = sdw1_dma_ring_buf_reg[stream_id].reg_ring_buf_addr; 186 + break; 187 + default: 188 + return -EINVAL; 189 + } 190 + sdw_fifo_offset = ACP_SDW_FIFO_OFFSET(manager_instance); 191 + sdw_mem_window_offset = SDW_MEM_WINDOW_START(manager_instance); 192 + sdw_fifo_addr = sdw_fifo_offset + (stream_id * SDW_FIFO_OFFSET); 193 + sdw_ring_buf_addr = sdw_mem_window_offset + (stream_id * ACP_SDW_RING_BUFF_ADDR_OFFSET); 194 + sdw_ring_buf_size = size; 195 + writel(sdw_ring_buf_size, acp_base + reg_ring_buf_size); 196 + writel(sdw_ring_buf_addr, acp_base + reg_ring_buf_addr); 197 + writel(sdw_fifo_addr, acp_base + reg_fifo_addr); 198 + writel(SDW_DMA_SIZE, acp_base + reg_dma_size); 199 + writel(SDW_FIFO_SIZE, acp_base + reg_fifo_size); 200 + return 0; 201 + } 202 + 203 + static int acp63_sdw_dma_open(struct snd_soc_component *component, 204 + struct snd_pcm_substream *substream) 205 + { 206 + struct snd_pcm_runtime *runtime; 207 + struct acp_sdw_dma_stream *stream; 208 + struct snd_soc_dai *cpu_dai; 209 + struct amd_sdw_manager *amd_manager; 210 + struct snd_soc_pcm_runtime *prtd = substream->private_data; 211 + int ret; 212 + 213 + runtime = substream->runtime; 214 + cpu_dai = asoc_rtd_to_cpu(prtd, 0); 215 + amd_manager = snd_soc_dai_get_drvdata(cpu_dai); 216 + stream = kzalloc(sizeof(*stream), GFP_KERNEL); 217 + if (!stream) 218 + return -ENOMEM; 219 + 220 + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 221 + runtime->hw = acp63_sdw_hardware_playback; 222 + else 223 + runtime->hw = acp63_sdw_hardware_capture; 224 + ret = snd_pcm_hw_constraint_integer(runtime, 225 + SNDRV_PCM_HW_PARAM_PERIODS); 226 + if (ret < 0) { 227 + dev_err(component->dev, "set integer constraint failed\n"); 228 + kfree(stream); 229 + return ret; 230 + } 231 + 232 + stream->stream_id = cpu_dai->id; 233 + stream->instance = amd_manager->instance; 234 + runtime->private_data = stream; 235 + return ret; 236 + } 237 + 238 + static int acp63_sdw_dma_hw_params(struct snd_soc_component *component, 239 + struct snd_pcm_substream *substream, 240 + struct snd_pcm_hw_params *params) 241 + { 242 + struct acp_sdw_dma_stream *stream; 243 + struct sdw_dma_dev_data *sdw_data; 244 + u32 period_bytes; 245 + u32 water_mark_size_reg; 246 + u32 irq_mask, ext_intr_ctrl; 247 + u64 size; 248 + u32 stream_id; 249 + u32 acp_ext_intr_cntl_reg; 250 + int ret; 251 + 252 + sdw_data = dev_get_drvdata(component->dev); 253 + stream = substream->runtime->private_data; 254 + if (!stream) 255 + return -EINVAL; 256 + stream_id = stream->stream_id; 257 + switch (stream->instance) { 258 + case ACP_SDW0: 259 + sdw_data->sdw0_dma_stream[stream_id] = substream; 260 + water_mark_size_reg = sdw0_dma_ring_buf_reg[stream_id].water_mark_size_reg; 261 + acp_ext_intr_cntl_reg = ACP_EXTERNAL_INTR_CNTL; 262 + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 263 + irq_mask = BIT(SDW0_DMA_TX_IRQ_MASK(stream_id)); 264 + else 265 + irq_mask = BIT(SDW0_DMA_RX_IRQ_MASK(stream_id)); 266 + break; 267 + case ACP_SDW1: 268 + sdw_data->sdw1_dma_stream[stream_id] = substream; 269 + acp_ext_intr_cntl_reg = ACP_EXTERNAL_INTR_CNTL1; 270 + water_mark_size_reg = sdw1_dma_ring_buf_reg[stream_id].water_mark_size_reg; 271 + irq_mask = BIT(SDW1_DMA_IRQ_MASK(stream_id)); 272 + break; 273 + default: 274 + return -EINVAL; 275 + } 276 + size = params_buffer_bytes(params); 277 + period_bytes = params_period_bytes(params); 278 + stream->dma_addr = substream->runtime->dma_addr; 279 + stream->num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT); 280 + acp63_config_dma(stream, sdw_data->acp_base, stream_id); 281 + ret = acp63_configure_sdw_ringbuffer(sdw_data->acp_base, stream_id, size, 282 + stream->instance); 283 + if (ret) { 284 + dev_err(component->dev, "Invalid DMA channel\n"); 285 + return -EINVAL; 286 + } 287 + ext_intr_ctrl = readl(sdw_data->acp_base + acp_ext_intr_cntl_reg); 288 + ext_intr_ctrl |= irq_mask; 289 + writel(ext_intr_ctrl, sdw_data->acp_base + acp_ext_intr_cntl_reg); 290 + writel(period_bytes, sdw_data->acp_base + water_mark_size_reg); 291 + return 0; 292 + } 293 + 294 + static u64 acp63_sdw_get_byte_count(struct acp_sdw_dma_stream *stream, void __iomem *acp_base) 295 + { 296 + union acp_sdw_dma_count byte_count; 297 + u32 pos_low_reg, pos_high_reg; 298 + 299 + byte_count.bytescount = 0; 300 + switch (stream->instance) { 301 + case ACP_SDW0: 302 + pos_low_reg = sdw0_dma_ring_buf_reg[stream->stream_id].pos_low_reg; 303 + pos_high_reg = sdw0_dma_ring_buf_reg[stream->stream_id].pos_high_reg; 304 + break; 305 + case ACP_SDW1: 306 + pos_low_reg = sdw1_dma_ring_buf_reg[stream->stream_id].pos_low_reg; 307 + pos_high_reg = sdw1_dma_ring_buf_reg[stream->stream_id].pos_high_reg; 308 + break; 309 + default: 310 + return -EINVAL; 311 + } 312 + if (pos_low_reg) { 313 + byte_count.bcount.high = readl(acp_base + pos_high_reg); 314 + byte_count.bcount.low = readl(acp_base + pos_low_reg); 315 + } 316 + return byte_count.bytescount; 317 + } 318 + 319 + static snd_pcm_uframes_t acp63_sdw_dma_pointer(struct snd_soc_component *comp, 320 + struct snd_pcm_substream *substream) 321 + { 322 + struct sdw_dma_dev_data *sdw_data; 323 + struct acp_sdw_dma_stream *stream; 324 + u32 pos, buffersize; 325 + u64 bytescount; 326 + 327 + sdw_data = dev_get_drvdata(comp->dev); 328 + stream = substream->runtime->private_data; 329 + buffersize = frames_to_bytes(substream->runtime, 330 + substream->runtime->buffer_size); 331 + bytescount = acp63_sdw_get_byte_count(stream, sdw_data->acp_base); 332 + if (bytescount > stream->bytescount) 333 + bytescount -= stream->bytescount; 334 + pos = do_div(bytescount, buffersize); 335 + return bytes_to_frames(substream->runtime, pos); 336 + } 337 + 338 + static int acp63_sdw_dma_new(struct snd_soc_component *component, 339 + struct snd_soc_pcm_runtime *rtd) 340 + { 341 + struct device *parent = component->dev->parent; 342 + 343 + snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, 344 + parent, SDW_MIN_BUFFER, SDW_MAX_BUFFER); 345 + return 0; 346 + } 347 + 348 + static int acp63_sdw_dma_close(struct snd_soc_component *component, 349 + struct snd_pcm_substream *substream) 350 + { 351 + struct sdw_dma_dev_data *sdw_data; 352 + struct acp_sdw_dma_stream *stream; 353 + 354 + sdw_data = dev_get_drvdata(component->dev); 355 + stream = substream->runtime->private_data; 356 + if (!stream) 357 + return -EINVAL; 358 + switch (stream->instance) { 359 + case ACP_SDW0: 360 + sdw_data->sdw0_dma_stream[stream->stream_id] = NULL; 361 + break; 362 + case ACP_SDW1: 363 + sdw_data->sdw1_dma_stream[stream->stream_id] = NULL; 364 + break; 365 + default: 366 + return -EINVAL; 367 + } 368 + kfree(stream); 369 + return 0; 370 + } 371 + 372 + static int acp63_sdw_dma_enable(struct snd_pcm_substream *substream, 373 + void __iomem *acp_base, bool sdw_dma_enable) 374 + { 375 + struct acp_sdw_dma_stream *stream; 376 + u32 stream_id; 377 + u32 sdw_dma_en_reg; 378 + u32 sdw_dma_en_stat_reg; 379 + u32 sdw_dma_stat; 380 + u32 dma_enable; 381 + 382 + stream = substream->runtime->private_data; 383 + stream_id = stream->stream_id; 384 + switch (stream->instance) { 385 + case ACP_SDW0: 386 + sdw_dma_en_reg = sdw0_dma_enable_reg[stream_id]; 387 + break; 388 + case ACP_SDW1: 389 + sdw_dma_en_reg = sdw1_dma_enable_reg[stream_id]; 390 + break; 391 + default: 392 + return -EINVAL; 393 + } 394 + sdw_dma_en_stat_reg = sdw_dma_en_reg + 4; 395 + dma_enable = sdw_dma_enable; 396 + writel(dma_enable, acp_base + sdw_dma_en_reg); 397 + return readl_poll_timeout(acp_base + sdw_dma_en_stat_reg, sdw_dma_stat, 398 + (sdw_dma_stat == dma_enable), ACP_DELAY_US, ACP_COUNTER); 399 + } 400 + 401 + static int acp63_sdw_dma_trigger(struct snd_soc_component *comp, 402 + struct snd_pcm_substream *substream, 403 + int cmd) 404 + { 405 + struct sdw_dma_dev_data *sdw_data; 406 + int ret; 407 + 408 + sdw_data = dev_get_drvdata(comp->dev); 409 + switch (cmd) { 410 + case SNDRV_PCM_TRIGGER_START: 411 + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 412 + case SNDRV_PCM_TRIGGER_RESUME: 413 + ret = acp63_sdw_dma_enable(substream, sdw_data->acp_base, true); 414 + break; 415 + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 416 + case SNDRV_PCM_TRIGGER_SUSPEND: 417 + case SNDRV_PCM_TRIGGER_STOP: 418 + ret = acp63_sdw_dma_enable(substream, sdw_data->acp_base, false); 419 + break; 420 + default: 421 + ret = -EINVAL; 422 + } 423 + if (ret) 424 + dev_err(comp->dev, "trigger %d failed: %d", cmd, ret); 425 + return ret; 426 + } 427 + 428 + static const struct snd_soc_component_driver acp63_sdw_component = { 429 + .name = DRV_NAME, 430 + .open = acp63_sdw_dma_open, 431 + .close = acp63_sdw_dma_close, 432 + .hw_params = acp63_sdw_dma_hw_params, 433 + .trigger = acp63_sdw_dma_trigger, 434 + .pointer = acp63_sdw_dma_pointer, 435 + .pcm_construct = acp63_sdw_dma_new, 436 + }; 437 + 438 + static int acp63_sdw_platform_probe(struct platform_device *pdev) 439 + { 440 + struct resource *res; 441 + struct sdw_dma_dev_data *sdw_data; 442 + struct acp63_dev_data *acp_data; 443 + struct device *parent; 444 + int status; 445 + 446 + parent = pdev->dev.parent; 447 + acp_data = dev_get_drvdata(parent); 448 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 449 + if (!res) { 450 + dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n"); 451 + return -ENODEV; 452 + } 453 + 454 + sdw_data = devm_kzalloc(&pdev->dev, sizeof(*sdw_data), GFP_KERNEL); 455 + if (!sdw_data) 456 + return -ENOMEM; 457 + 458 + sdw_data->acp_base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); 459 + if (!sdw_data->acp_base) 460 + return -ENOMEM; 461 + 462 + sdw_data->acp_lock = &acp_data->acp_lock; 463 + dev_set_drvdata(&pdev->dev, sdw_data); 464 + status = devm_snd_soc_register_component(&pdev->dev, 465 + &acp63_sdw_component, 466 + NULL, 0); 467 + if (status) { 468 + dev_err(&pdev->dev, "Fail to register sdw dma component\n"); 469 + return status; 470 + } 471 + pm_runtime_set_autosuspend_delay(&pdev->dev, ACP_SUSPEND_DELAY_MS); 472 + pm_runtime_use_autosuspend(&pdev->dev); 473 + pm_runtime_mark_last_busy(&pdev->dev); 474 + pm_runtime_set_active(&pdev->dev); 475 + pm_runtime_enable(&pdev->dev); 476 + return 0; 477 + } 478 + 479 + static int acp63_sdw_platform_remove(struct platform_device *pdev) 480 + { 481 + pm_runtime_disable(&pdev->dev); 482 + return 0; 483 + } 484 + 485 + static int acp_restore_sdw_dma_config(struct sdw_dma_dev_data *sdw_data) 486 + { 487 + struct acp_sdw_dma_stream *stream; 488 + struct snd_pcm_substream *substream; 489 + struct snd_pcm_runtime *runtime; 490 + u32 period_bytes, buf_size, water_mark_size_reg; 491 + u32 stream_count; 492 + int index, instance, ret; 493 + 494 + for (instance = 0; instance < AMD_SDW_MAX_MANAGERS; instance++) { 495 + if (instance == ACP_SDW0) 496 + stream_count = ACP63_SDW0_DMA_MAX_STREAMS; 497 + else 498 + stream_count = ACP63_SDW1_DMA_MAX_STREAMS; 499 + 500 + for (index = 0; index < stream_count; index++) { 501 + if (instance == ACP_SDW0) { 502 + substream = sdw_data->sdw0_dma_stream[index]; 503 + water_mark_size_reg = 504 + sdw0_dma_ring_buf_reg[index].water_mark_size_reg; 505 + } else { 506 + substream = sdw_data->sdw1_dma_stream[index]; 507 + water_mark_size_reg = 508 + sdw1_dma_ring_buf_reg[index].water_mark_size_reg; 509 + } 510 + 511 + if (substream && substream->runtime) { 512 + runtime = substream->runtime; 513 + stream = runtime->private_data; 514 + period_bytes = frames_to_bytes(runtime, runtime->period_size); 515 + buf_size = frames_to_bytes(runtime, runtime->buffer_size); 516 + acp63_config_dma(stream, sdw_data->acp_base, index); 517 + ret = acp63_configure_sdw_ringbuffer(sdw_data->acp_base, index, 518 + buf_size, instance); 519 + if (ret) 520 + return ret; 521 + writel(period_bytes, sdw_data->acp_base + water_mark_size_reg); 522 + } 523 + } 524 + } 525 + acp63_enable_disable_sdw_dma_interrupts(sdw_data->acp_base, true); 526 + return 0; 527 + } 528 + 529 + static int __maybe_unused acp63_sdw_pcm_resume(struct device *dev) 530 + { 531 + struct sdw_dma_dev_data *sdw_data; 532 + 533 + sdw_data = dev_get_drvdata(dev); 534 + return acp_restore_sdw_dma_config(sdw_data); 535 + } 536 + 537 + static const struct dev_pm_ops acp63_pm_ops = { 538 + SET_SYSTEM_SLEEP_PM_OPS(NULL, acp63_sdw_pcm_resume) 539 + }; 540 + 541 + static struct platform_driver acp63_sdw_dma_driver = { 542 + .probe = acp63_sdw_platform_probe, 543 + .remove = acp63_sdw_platform_remove, 544 + .driver = { 545 + .name = "amd_ps_sdw_dma", 546 + .pm = &acp63_pm_ops, 547 + }, 548 + }; 549 + 550 + module_platform_driver(acp63_sdw_dma_driver); 551 + 552 + MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); 553 + MODULE_DESCRIPTION("AMD ACP6.3 PS SDW DMA Driver"); 554 + MODULE_LICENSE("GPL"); 555 + MODULE_ALIAS("platform:" DRV_NAME);