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 case ACP72_PCI_ID: 144 switch (stream->dai_id) { 145 case I2S_SP_INSTANCE: 146 if (stream->dir == SNDRV_PCM_STREAM_PLAYBACK) 147 val = 0x0; 148 else 149 val = 0x1000; 150 break; 151 case I2S_BT_INSTANCE: 152 if (stream->dir == SNDRV_PCM_STREAM_PLAYBACK) 153 val = 0x2000; 154 else 155 val = 0x3000; 156 break; 157 case I2S_HS_INSTANCE: 158 if (stream->dir == SNDRV_PCM_STREAM_PLAYBACK) 159 val = 0x4000; 160 else 161 val = 0x5000; 162 break; 163 case DMIC_INSTANCE: 164 val = 0x6000; 165 break; 166 default: 167 dev_err(chip->dev, "Invalid dai id %x\n", stream->dai_id); 168 return; 169 } 170 break; 171 default: 172 val = stream->pte_offset; 173 break; 174 } 175 176 for (page_idx = 0; page_idx < num_pages; page_idx++) { 177 /* Load the low address of page int ACP SRAM through SRBM */ 178 low = lower_32_bits(addr); 179 high = upper_32_bits(addr); 180 writel(low, chip->base + rsrc->scratch_reg_offset + val); 181 high |= BIT(31); 182 writel(high, chip->base + rsrc->scratch_reg_offset + val + 4); 183 184 /* Move to next physically contiguous page */ 185 val += 8; 186 addr += PAGE_SIZE; 187 } 188 } 189 EXPORT_SYMBOL_NS_GPL(config_acp_dma, "SND_SOC_ACP_COMMON"); 190 191 static int acp_dma_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) 192 { 193 struct snd_pcm_runtime *runtime = substream->runtime; 194 struct device *dev = component->dev; 195 struct acp_chip_info *chip; 196 struct acp_stream *stream; 197 int ret; 198 199 stream = kzalloc(sizeof(*stream), GFP_KERNEL); 200 if (!stream) 201 return -ENOMEM; 202 203 stream->substream = substream; 204 chip = dev_get_drvdata(dev->parent); 205 switch (chip->acp_rev) { 206 case ACP63_PCI_ID: 207 case ACP70_PCI_ID: 208 case ACP71_PCI_ID: 209 case ACP72_PCI_ID: 210 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 211 runtime->hw = acp6x_pcm_hardware_playback; 212 else 213 runtime->hw = acp6x_pcm_hardware_capture; 214 break; 215 default: 216 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 217 runtime->hw = acp_pcm_hardware_playback; 218 else 219 runtime->hw = acp_pcm_hardware_capture; 220 break; 221 } 222 223 ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, DMA_SIZE); 224 if (ret) { 225 dev_err(component->dev, "set hw constraint HW_PARAM_PERIOD_BYTES failed\n"); 226 kfree(stream); 227 return ret; 228 } 229 230 ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, DMA_SIZE); 231 if (ret) { 232 dev_err(component->dev, "set hw constraint HW_PARAM_BUFFER_BYTES failed\n"); 233 kfree(stream); 234 return ret; 235 } 236 237 ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); 238 if (ret < 0) { 239 dev_err(component->dev, "set integer constraint failed\n"); 240 kfree(stream); 241 return ret; 242 } 243 runtime->private_data = stream; 244 245 writel(1, ACP_EXTERNAL_INTR_ENB(chip)); 246 247 spin_lock_irq(&chip->acp_lock); 248 list_add_tail(&stream->list, &chip->stream_list); 249 spin_unlock_irq(&chip->acp_lock); 250 251 return ret; 252 } 253 254 static int acp_dma_hw_params(struct snd_soc_component *component, 255 struct snd_pcm_substream *substream, 256 struct snd_pcm_hw_params *params) 257 { 258 struct device *dev = component->dev; 259 struct acp_chip_info *chip = dev_get_drvdata(dev->parent); 260 struct acp_stream *stream = substream->runtime->private_data; 261 u64 size = params_buffer_bytes(params); 262 263 /* Configure ACP DMA block with params */ 264 config_pte_for_stream(chip, stream); 265 config_acp_dma(chip, stream, size); 266 267 return 0; 268 } 269 270 static snd_pcm_uframes_t acp_dma_pointer(struct snd_soc_component *component, 271 struct snd_pcm_substream *substream) 272 { 273 struct device *dev = component->dev; 274 struct acp_chip_info *chip = dev_get_drvdata(dev->parent); 275 struct acp_stream *stream = substream->runtime->private_data; 276 u32 pos, buffersize; 277 u64 bytescount; 278 279 buffersize = frames_to_bytes(substream->runtime, 280 substream->runtime->buffer_size); 281 282 bytescount = acp_get_byte_count(chip, stream->dai_id, substream->stream); 283 284 if (bytescount > stream->bytescount) 285 bytescount -= stream->bytescount; 286 287 pos = do_div(bytescount, buffersize); 288 289 return bytes_to_frames(substream->runtime, pos); 290 } 291 292 static int acp_dma_new(struct snd_soc_component *component, 293 struct snd_soc_pcm_runtime *rtd) 294 { 295 struct device *parent = component->dev->parent; 296 297 snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, 298 parent, MIN_BUFFER, MAX_BUFFER); 299 return 0; 300 } 301 302 static int acp_dma_close(struct snd_soc_component *component, 303 struct snd_pcm_substream *substream) 304 { 305 struct device *dev = component->dev; 306 struct acp_chip_info *chip = dev_get_drvdata(dev->parent); 307 struct acp_stream *stream = substream->runtime->private_data; 308 309 /* Remove entry from list */ 310 spin_lock_irq(&chip->acp_lock); 311 list_del(&stream->list); 312 spin_unlock_irq(&chip->acp_lock); 313 kfree(stream); 314 315 return 0; 316 } 317 318 static const struct snd_soc_component_driver acp_pcm_component = { 319 .name = DRV_NAME, 320 .open = acp_dma_open, 321 .close = acp_dma_close, 322 .hw_params = acp_dma_hw_params, 323 .pointer = acp_dma_pointer, 324 .pcm_construct = acp_dma_new, 325 .legacy_dai_naming = 1, 326 }; 327 328 int acp_platform_register(struct device *dev) 329 { 330 struct acp_chip_info *chip; 331 struct snd_soc_dai_driver; 332 unsigned int status; 333 334 chip = dev_get_platdata(dev); 335 if (!chip || !chip->base) { 336 dev_err(dev, "ACP chip data is NULL\n"); 337 return -ENODEV; 338 } 339 340 status = devm_snd_soc_register_component(dev, &acp_pcm_component, 341 chip->dai_driver, 342 chip->num_dai); 343 if (status) { 344 dev_err(dev, "Fail to register acp i2s component\n"); 345 return status; 346 } 347 348 return 0; 349 } 350 EXPORT_SYMBOL_NS_GPL(acp_platform_register, "SND_SOC_ACP_COMMON"); 351 352 int acp_platform_unregister(struct device *dev) 353 { 354 return 0; 355 } 356 EXPORT_SYMBOL_NS_GPL(acp_platform_unregister, "SND_SOC_ACP_COMMON"); 357 358 MODULE_DESCRIPTION("AMD ACP PCM Driver"); 359 MODULE_LICENSE("Dual BSD/GPL"); 360 MODULE_ALIAS(DRV_NAME); 361