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 * Generic interface for ACP audio blck PCM component 12 */ 13 14 #include <linux/platform_device.h> 15 #include <linux/module.h> 16 #include <linux/err.h> 17 #include <linux/io.h> 18 #include <sound/pcm_params.h> 19 #include <sound/soc.h> 20 #include <sound/soc-dai.h> 21 #include <linux/dma-mapping.h> 22 23 #include "amd.h" 24 #include "acp-mach.h" 25 26 #define DRV_NAME "acp_i2s_dma" 27 28 static const struct snd_pcm_hardware acp_pcm_hardware_playback = { 29 .info = SNDRV_PCM_INFO_INTERLEAVED | 30 SNDRV_PCM_INFO_BLOCK_TRANSFER | 31 SNDRV_PCM_INFO_BATCH | 32 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | 33 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME, 34 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | 35 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S24_LE | 36 SNDRV_PCM_FMTBIT_S32_LE, 37 .channels_min = 2, 38 .channels_max = 8, 39 .rates = SNDRV_PCM_RATE_8000_96000, 40 .rate_min = 8000, 41 .rate_max = 96000, 42 .buffer_bytes_max = PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE, 43 .period_bytes_min = PLAYBACK_MIN_PERIOD_SIZE, 44 .period_bytes_max = PLAYBACK_MAX_PERIOD_SIZE, 45 .periods_min = PLAYBACK_MIN_NUM_PERIODS, 46 .periods_max = PLAYBACK_MAX_NUM_PERIODS, 47 }; 48 49 static const struct snd_pcm_hardware acp_pcm_hardware_capture = { 50 .info = SNDRV_PCM_INFO_INTERLEAVED | 51 SNDRV_PCM_INFO_BLOCK_TRANSFER | 52 SNDRV_PCM_INFO_BATCH | 53 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | 54 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME, 55 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | 56 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S24_LE | 57 SNDRV_PCM_FMTBIT_S32_LE, 58 .channels_min = 2, 59 .channels_max = 2, 60 .rates = SNDRV_PCM_RATE_8000_48000, 61 .rate_min = 8000, 62 .rate_max = 48000, 63 .buffer_bytes_max = CAPTURE_MAX_NUM_PERIODS * CAPTURE_MAX_PERIOD_SIZE, 64 .period_bytes_min = CAPTURE_MIN_PERIOD_SIZE, 65 .period_bytes_max = CAPTURE_MAX_PERIOD_SIZE, 66 .periods_min = CAPTURE_MIN_NUM_PERIODS, 67 .periods_max = CAPTURE_MAX_NUM_PERIODS, 68 }; 69 70 static const struct snd_pcm_hardware acp6x_pcm_hardware_playback = { 71 .info = SNDRV_PCM_INFO_INTERLEAVED | 72 SNDRV_PCM_INFO_BLOCK_TRANSFER | 73 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | 74 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME, 75 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | 76 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S24_LE | 77 SNDRV_PCM_FMTBIT_S32_LE, 78 .channels_min = 2, 79 .channels_max = 32, 80 .rates = SNDRV_PCM_RATE_8000_192000, 81 .rate_min = 8000, 82 .rate_max = 192000, 83 .buffer_bytes_max = PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE, 84 .period_bytes_min = PLAYBACK_MIN_PERIOD_SIZE, 85 .period_bytes_max = PLAYBACK_MAX_PERIOD_SIZE, 86 .periods_min = PLAYBACK_MIN_NUM_PERIODS, 87 .periods_max = PLAYBACK_MAX_NUM_PERIODS, 88 }; 89 90 static const struct snd_pcm_hardware acp6x_pcm_hardware_capture = { 91 .info = SNDRV_PCM_INFO_INTERLEAVED | 92 SNDRV_PCM_INFO_BLOCK_TRANSFER | 93 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | 94 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME, 95 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | 96 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S24_LE | 97 SNDRV_PCM_FMTBIT_S32_LE, 98 .channels_min = 2, 99 .channels_max = 32, 100 .rates = SNDRV_PCM_RATE_8000_192000, 101 .rate_min = 8000, 102 .rate_max = 192000, 103 .buffer_bytes_max = CAPTURE_MAX_NUM_PERIODS * CAPTURE_MAX_PERIOD_SIZE, 104 .period_bytes_min = CAPTURE_MIN_PERIOD_SIZE, 105 .period_bytes_max = CAPTURE_MAX_PERIOD_SIZE, 106 .periods_min = CAPTURE_MIN_NUM_PERIODS, 107 .periods_max = CAPTURE_MAX_NUM_PERIODS, 108 }; 109 110 void config_pte_for_stream(struct acp_chip_info *chip, struct acp_stream *stream) 111 { 112 struct acp_resource *rsrc = chip->rsrc; 113 u32 reg_val; 114 115 reg_val = rsrc->sram_pte_offset; 116 stream->reg_offset = 0x02000000; 117 118 writel((reg_val + GRP1_OFFSET) | BIT(31), chip->base + ACPAXI2AXI_ATU_BASE_ADDR_GRP_1); 119 writel(PAGE_SIZE_4K_ENABLE, chip->base + ACPAXI2AXI_ATU_PAGE_SIZE_GRP_1); 120 121 writel((reg_val + GRP2_OFFSET) | BIT(31), chip->base + ACPAXI2AXI_ATU_BASE_ADDR_GRP_2); 122 writel(PAGE_SIZE_4K_ENABLE, chip->base + ACPAXI2AXI_ATU_PAGE_SIZE_GRP_2); 123 124 writel(reg_val | BIT(31), chip->base + ACPAXI2AXI_ATU_BASE_ADDR_GRP_5); 125 writel(PAGE_SIZE_4K_ENABLE, chip->base + ACPAXI2AXI_ATU_PAGE_SIZE_GRP_5); 126 127 writel(0x01, chip->base + ACPAXI2AXI_ATU_CTRL); 128 } 129 EXPORT_SYMBOL_NS_GPL(config_pte_for_stream, "SND_SOC_ACP_COMMON"); 130 131 void config_acp_dma(struct acp_chip_info *chip, struct acp_stream *stream, int size) 132 { 133 struct snd_pcm_substream *substream = stream->substream; 134 struct acp_resource *rsrc = chip->rsrc; 135 dma_addr_t addr = substream->dma_buffer.addr; 136 int num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT); 137 u32 low, high, val; 138 u16 page_idx; 139 140 switch (chip->acp_rev) { 141 case ACP70_PCI_ID: 142 case ACP71_PCI_ID: 143 switch (stream->dai_id) { 144 case I2S_SP_INSTANCE: 145 if (stream->dir == SNDRV_PCM_STREAM_PLAYBACK) 146 val = 0x0; 147 else 148 val = 0x1000; 149 break; 150 case I2S_BT_INSTANCE: 151 if (stream->dir == SNDRV_PCM_STREAM_PLAYBACK) 152 val = 0x2000; 153 else 154 val = 0x3000; 155 break; 156 case I2S_HS_INSTANCE: 157 if (stream->dir == SNDRV_PCM_STREAM_PLAYBACK) 158 val = 0x4000; 159 else 160 val = 0x5000; 161 break; 162 case DMIC_INSTANCE: 163 val = 0x6000; 164 break; 165 default: 166 dev_err(chip->dev, "Invalid dai id %x\n", stream->dai_id); 167 return; 168 } 169 break; 170 default: 171 val = stream->pte_offset; 172 break; 173 } 174 175 for (page_idx = 0; page_idx < num_pages; page_idx++) { 176 /* Load the low address of page int ACP SRAM through SRBM */ 177 low = lower_32_bits(addr); 178 high = upper_32_bits(addr); 179 writel(low, chip->base + rsrc->scratch_reg_offset + val); 180 high |= BIT(31); 181 writel(high, chip->base + rsrc->scratch_reg_offset + val + 4); 182 183 /* Move to next physically contiguous page */ 184 val += 8; 185 addr += PAGE_SIZE; 186 } 187 } 188 EXPORT_SYMBOL_NS_GPL(config_acp_dma, "SND_SOC_ACP_COMMON"); 189 190 static int acp_dma_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) 191 { 192 struct snd_pcm_runtime *runtime = substream->runtime; 193 struct device *dev = component->dev; 194 struct acp_chip_info *chip; 195 struct acp_stream *stream; 196 int ret; 197 198 stream = kzalloc(sizeof(*stream), GFP_KERNEL); 199 if (!stream) 200 return -ENOMEM; 201 202 stream->substream = substream; 203 chip = dev_get_drvdata(dev->parent); 204 switch (chip->acp_rev) { 205 case ACP63_PCI_ID: 206 case ACP70_PCI_ID: 207 case ACP71_PCI_ID: 208 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 209 runtime->hw = acp6x_pcm_hardware_playback; 210 else 211 runtime->hw = acp6x_pcm_hardware_capture; 212 break; 213 default: 214 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 215 runtime->hw = acp_pcm_hardware_playback; 216 else 217 runtime->hw = acp_pcm_hardware_capture; 218 break; 219 } 220 221 ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, DMA_SIZE); 222 if (ret) { 223 dev_err(component->dev, "set hw constraint HW_PARAM_PERIOD_BYTES failed\n"); 224 kfree(stream); 225 return ret; 226 } 227 228 ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, DMA_SIZE); 229 if (ret) { 230 dev_err(component->dev, "set hw constraint HW_PARAM_BUFFER_BYTES failed\n"); 231 kfree(stream); 232 return ret; 233 } 234 235 ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); 236 if (ret < 0) { 237 dev_err(component->dev, "set integer constraint failed\n"); 238 kfree(stream); 239 return ret; 240 } 241 runtime->private_data = stream; 242 243 writel(1, ACP_EXTERNAL_INTR_ENB(chip)); 244 245 spin_lock_irq(&chip->acp_lock); 246 list_add_tail(&stream->list, &chip->stream_list); 247 spin_unlock_irq(&chip->acp_lock); 248 249 return ret; 250 } 251 252 static int acp_dma_hw_params(struct snd_soc_component *component, 253 struct snd_pcm_substream *substream, 254 struct snd_pcm_hw_params *params) 255 { 256 struct device *dev = component->dev; 257 struct acp_chip_info *chip = dev_get_drvdata(dev->parent); 258 struct acp_stream *stream = substream->runtime->private_data; 259 u64 size = params_buffer_bytes(params); 260 261 /* Configure ACP DMA block with params */ 262 config_pte_for_stream(chip, stream); 263 config_acp_dma(chip, stream, size); 264 265 return 0; 266 } 267 268 static snd_pcm_uframes_t acp_dma_pointer(struct snd_soc_component *component, 269 struct snd_pcm_substream *substream) 270 { 271 struct device *dev = component->dev; 272 struct acp_chip_info *chip = dev_get_drvdata(dev->parent); 273 struct acp_stream *stream = substream->runtime->private_data; 274 u32 pos, buffersize; 275 u64 bytescount; 276 277 buffersize = frames_to_bytes(substream->runtime, 278 substream->runtime->buffer_size); 279 280 bytescount = acp_get_byte_count(chip, stream->dai_id, substream->stream); 281 282 if (bytescount > stream->bytescount) 283 bytescount -= stream->bytescount; 284 285 pos = do_div(bytescount, buffersize); 286 287 return bytes_to_frames(substream->runtime, pos); 288 } 289 290 static int acp_dma_new(struct snd_soc_component *component, 291 struct snd_soc_pcm_runtime *rtd) 292 { 293 struct device *parent = component->dev->parent; 294 295 snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, 296 parent, MIN_BUFFER, MAX_BUFFER); 297 return 0; 298 } 299 300 static int acp_dma_close(struct snd_soc_component *component, 301 struct snd_pcm_substream *substream) 302 { 303 struct device *dev = component->dev; 304 struct acp_chip_info *chip = dev_get_drvdata(dev->parent); 305 struct acp_stream *stream = substream->runtime->private_data; 306 307 /* Remove entry from list */ 308 spin_lock_irq(&chip->acp_lock); 309 list_del(&stream->list); 310 spin_unlock_irq(&chip->acp_lock); 311 kfree(stream); 312 313 return 0; 314 } 315 316 static const struct snd_soc_component_driver acp_pcm_component = { 317 .name = DRV_NAME, 318 .open = acp_dma_open, 319 .close = acp_dma_close, 320 .hw_params = acp_dma_hw_params, 321 .pointer = acp_dma_pointer, 322 .pcm_construct = acp_dma_new, 323 .legacy_dai_naming = 1, 324 }; 325 326 int acp_platform_register(struct device *dev) 327 { 328 struct acp_chip_info *chip; 329 struct snd_soc_dai_driver; 330 unsigned int status; 331 332 chip = dev_get_platdata(dev); 333 if (!chip || !chip->base) { 334 dev_err(dev, "ACP chip data is NULL\n"); 335 return -ENODEV; 336 } 337 338 status = devm_snd_soc_register_component(dev, &acp_pcm_component, 339 chip->dai_driver, 340 chip->num_dai); 341 if (status) { 342 dev_err(dev, "Fail to register acp i2s component\n"); 343 return status; 344 } 345 346 return 0; 347 } 348 EXPORT_SYMBOL_NS_GPL(acp_platform_register, "SND_SOC_ACP_COMMON"); 349 350 int acp_platform_unregister(struct device *dev) 351 { 352 return 0; 353 } 354 EXPORT_SYMBOL_NS_GPL(acp_platform_unregister, "SND_SOC_ACP_COMMON"); 355 356 MODULE_DESCRIPTION("AMD ACP PCM Driver"); 357 MODULE_LICENSE("Dual BSD/GPL"); 358 MODULE_ALIAS(DRV_NAME); 359