FILE
acp-legacy-common.c
File preview with syntax highlighting.
linux-6.19.14/sound/soc/amd/acp/acp-legacy-common.c
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) 2023 Advanced Micro Devices, Inc. 7// 8// Authors: Syed Saba Kareem <Syed.SabaKareem@amd.com> 9// 10 11/* 12 * Common file to be used by amd platforms 13 */ 14 15#include "amd.h" 16#include <linux/acpi.h> 17#include <linux/pci.h> 18#include <linux/export.h> 19 20#include "../mach-config.h" 21 22#define ACP_RENOIR_PDM_ADDR 0x02 23#define ACP_REMBRANDT_PDM_ADDR 0x03 24#define ACP63_PDM_ADDR 0x02 25#define ACP70_PDM_ADDR 0x02 26 27struct acp_resource rn_rsrc = { 28 .offset = 20, 29 .no_of_ctrls = 1, 30 .irqp_used = 0, 31 .irq_reg_offset = 0x1800, 32 .scratch_reg_offset = 0x12800, 33 .sram_pte_offset = 0x02052800, 34}; 35EXPORT_SYMBOL_NS_GPL(rn_rsrc, "SND_SOC_ACP_COMMON"); 36 37struct acp_resource rmb_rsrc = { 38 .offset = 0, 39 .no_of_ctrls = 2, 40 .irqp_used = 1, 41 .soc_mclk = true, 42 .irq_reg_offset = 0x1a00, 43 .scratch_reg_offset = 0x12800, 44 .sram_pte_offset = 0x03802800, 45}; 46EXPORT_SYMBOL_NS_GPL(rmb_rsrc, "SND_SOC_ACP_COMMON"); 47 48struct acp_resource acp63_rsrc = { 49 .offset = 0, 50 .no_of_ctrls = 2, 51 .irqp_used = 1, 52 .soc_mclk = true, 53 .irq_reg_offset = 0x1a00, 54 .scratch_reg_offset = 0x12800, 55 .sram_pte_offset = 0x03802800, 56}; 57EXPORT_SYMBOL_NS_GPL(acp63_rsrc, "SND_SOC_ACP_COMMON"); 58 59struct acp_resource acp70_rsrc = { 60 .offset = 0, 61 .no_of_ctrls = 2, 62 .irqp_used = 1, 63 .soc_mclk = true, 64 .irq_reg_offset = 0x1a00, 65 .scratch_reg_offset = 0x10000, 66 .sram_pte_offset = 0x03800000, 67}; 68EXPORT_SYMBOL_NS_GPL(acp70_rsrc, "SND_SOC_ACP_COMMON"); 69 70static const struct snd_acp_hw_ops acp_common_hw_ops = { 71 /* ACP hardware initilizations */ 72 .acp_init = acp_init, 73 .acp_deinit = acp_deinit, 74 75 /* ACP Interrupts*/ 76 .irq = acp_irq_handler, 77 .en_interrupts = acp_enable_interrupts, 78 .dis_interrupts = acp_disable_interrupts, 79}; 80 81irqreturn_t acp_irq_handler(int irq, void *data) 82{ 83 struct acp_chip_info *chip = data; 84 struct acp_resource *rsrc = chip->rsrc; 85 struct acp_stream *stream; 86 u16 i2s_flag = 0; 87 u32 ext_intr_stat, ext_intr_stat1; 88 89 if (rsrc->no_of_ctrls == 2) 90 ext_intr_stat1 = readl(ACP_EXTERNAL_INTR_STAT(chip, (rsrc->irqp_used - 1))); 91 92 ext_intr_stat = readl(ACP_EXTERNAL_INTR_STAT(chip, rsrc->irqp_used)); 93 94 spin_lock(&chip->acp_lock); 95 list_for_each_entry(stream, &chip->stream_list, list) { 96 if (ext_intr_stat & stream->irq_bit) { 97 writel(stream->irq_bit, 98 ACP_EXTERNAL_INTR_STAT(chip, rsrc->irqp_used)); 99 snd_pcm_period_elapsed(stream->substream); 100 i2s_flag = 1; 101 } 102 if (chip->rsrc->no_of_ctrls == 2) { 103 if (ext_intr_stat1 & stream->irq_bit) { 104 writel(stream->irq_bit, ACP_EXTERNAL_INTR_STAT(chip, 105 (rsrc->irqp_used - 1))); 106 snd_pcm_period_elapsed(stream->substream); 107 i2s_flag = 1; 108 } 109 } 110 } 111 spin_unlock(&chip->acp_lock); 112 if (i2s_flag) 113 return IRQ_HANDLED; 114 115 return IRQ_NONE; 116} 117 118int acp_enable_interrupts(struct acp_chip_info *chip) 119{ 120 struct acp_resource *rsrc; 121 u32 ext_intr_ctrl; 122 123 rsrc = chip->rsrc; 124 writel(0x01, ACP_EXTERNAL_INTR_ENB(chip)); 125 ext_intr_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(chip, rsrc->irqp_used)); 126 ext_intr_ctrl |= ACP_ERROR_MASK; 127 writel(ext_intr_ctrl, ACP_EXTERNAL_INTR_CNTL(chip, rsrc->irqp_used)); 128 129 return 0; 130} 131EXPORT_SYMBOL_NS_GPL(acp_enable_interrupts, "SND_SOC_ACP_COMMON"); 132 133int acp_disable_interrupts(struct acp_chip_info *chip) 134{ 135 struct acp_resource *rsrc; 136 137 rsrc = chip->rsrc; 138 writel(ACP_EXT_INTR_STAT_CLEAR_MASK, ACP_EXTERNAL_INTR_STAT(chip, rsrc->irqp_used)); 139 writel(0x00, ACP_EXTERNAL_INTR_ENB(chip)); 140 141 return 0; 142} 143EXPORT_SYMBOL_NS_GPL(acp_disable_interrupts, "SND_SOC_ACP_COMMON"); 144 145static void set_acp_pdm_ring_buffer(struct snd_pcm_substream *substream, 146 struct snd_soc_dai *dai) 147{ 148 struct snd_pcm_runtime *runtime = substream->runtime; 149 struct acp_stream *stream = runtime->private_data; 150 struct device *dev = dai->component->dev; 151 struct acp_chip_info *chip = dev_get_platdata(dev); 152 153 u32 physical_addr, pdm_size, period_bytes; 154 155 period_bytes = frames_to_bytes(runtime, runtime->period_size); 156 pdm_size = frames_to_bytes(runtime, runtime->buffer_size); 157 physical_addr = stream->reg_offset + MEM_WINDOW_START; 158 159 /* Init ACP PDM Ring buffer */ 160 writel(physical_addr, chip->base + ACP_WOV_RX_RINGBUFADDR); 161 writel(pdm_size, chip->base + ACP_WOV_RX_RINGBUFSIZE); 162 writel(period_bytes, chip->base + ACP_WOV_RX_INTR_WATERMARK_SIZE); 163 writel(0x01, chip->base + ACPAXI2AXI_ATU_CTRL); 164} 165 166static void set_acp_pdm_clk(struct snd_pcm_substream *substream, 167 struct snd_soc_dai *dai) 168{ 169 struct device *dev = dai->component->dev; 170 struct acp_chip_info *chip = dev_get_platdata(dev); 171 unsigned int pdm_ctrl; 172 173 /* Enable default ACP PDM clk */ 174 writel(PDM_CLK_FREQ_MASK, chip->base + ACP_WOV_CLK_CTRL); 175 pdm_ctrl = readl(chip->base + ACP_WOV_MISC_CTRL); 176 pdm_ctrl |= PDM_MISC_CTRL_MASK; 177 writel(pdm_ctrl, chip->base + ACP_WOV_MISC_CTRL); 178 set_acp_pdm_ring_buffer(substream, dai); 179} 180 181void restore_acp_pdm_params(struct snd_pcm_substream *substream, 182 struct acp_chip_info *chip) 183{ 184 struct snd_soc_dai *dai; 185 struct snd_soc_pcm_runtime *soc_runtime; 186 u32 ext_int_ctrl; 187 188 soc_runtime = snd_soc_substream_to_rtd(substream); 189 dai = snd_soc_rtd_to_cpu(soc_runtime, 0); 190 191 /* Programming channel mask and sampling rate */ 192 writel(chip->ch_mask, chip->base + ACP_WOV_PDM_NO_OF_CHANNELS); 193 writel(PDM_DEC_64, chip->base + ACP_WOV_PDM_DECIMATION_FACTOR); 194 195 /* Enabling ACP Pdm interuppts */ 196 ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(chip, 0)); 197 ext_int_ctrl |= PDM_DMA_INTR_MASK; 198 writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(chip, 0)); 199 set_acp_pdm_clk(substream, dai); 200} 201EXPORT_SYMBOL_NS_GPL(restore_acp_pdm_params, "SND_SOC_ACP_COMMON"); 202 203static int set_acp_i2s_dma_fifo(struct snd_pcm_substream *substream, 204 struct snd_soc_dai *dai) 205{ 206 struct device *dev = dai->component->dev; 207 struct acp_chip_info *chip = dev_get_platdata(dev); 208 struct acp_resource *rsrc = chip->rsrc; 209 struct acp_stream *stream = substream->runtime->private_data; 210 u32 reg_dma_size, reg_fifo_size, reg_fifo_addr; 211 u32 phy_addr, acp_fifo_addr, ext_int_ctrl; 212 unsigned int dir = substream->stream; 213 214 switch (dai->driver->id) { 215 case I2S_SP_INSTANCE: 216 if (dir == SNDRV_PCM_STREAM_PLAYBACK) { 217 reg_dma_size = ACP_I2S_TX_DMA_SIZE(chip); 218 acp_fifo_addr = rsrc->sram_pte_offset + 219 SP_PB_FIFO_ADDR_OFFSET; 220 reg_fifo_addr = ACP_I2S_TX_FIFOADDR(chip); 221 reg_fifo_size = ACP_I2S_TX_FIFOSIZE(chip); 222 if (chip->acp_rev >= ACP70_PCI_ID) 223 phy_addr = ACP7x_I2S_SP_TX_MEM_WINDOW_START; 224 else 225 phy_addr = I2S_SP_TX_MEM_WINDOW_START + stream->reg_offset; 226 writel(phy_addr, chip->base + ACP_I2S_TX_RINGBUFADDR(chip)); 227 } else { 228 reg_dma_size = ACP_I2S_RX_DMA_SIZE(chip); 229 acp_fifo_addr = rsrc->sram_pte_offset + 230 SP_CAPT_FIFO_ADDR_OFFSET; 231 reg_fifo_addr = ACP_I2S_RX_FIFOADDR(chip); 232 reg_fifo_size = ACP_I2S_RX_FIFOSIZE(chip); 233 if (chip->acp_rev >= ACP70_PCI_ID) 234 phy_addr = ACP7x_I2S_SP_RX_MEM_WINDOW_START; 235 else 236 phy_addr = I2S_SP_RX_MEM_WINDOW_START + stream->reg_offset; 237 writel(phy_addr, chip->base + ACP_I2S_RX_RINGBUFADDR(chip)); 238 } 239 break; 240 case I2S_BT_INSTANCE: 241 if (dir == SNDRV_PCM_STREAM_PLAYBACK) { 242 reg_dma_size = ACP_BT_TX_DMA_SIZE(chip); 243 acp_fifo_addr = rsrc->sram_pte_offset + 244 BT_PB_FIFO_ADDR_OFFSET; 245 reg_fifo_addr = ACP_BT_TX_FIFOADDR(chip); 246 reg_fifo_size = ACP_BT_TX_FIFOSIZE(chip); 247 if (chip->acp_rev >= ACP70_PCI_ID) 248 phy_addr = ACP7x_I2S_BT_TX_MEM_WINDOW_START; 249 else 250 phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset; 251 writel(phy_addr, chip->base + ACP_BT_TX_RINGBUFADDR(chip)); 252 } else { 253 reg_dma_size = ACP_BT_RX_DMA_SIZE(chip); 254 acp_fifo_addr = rsrc->sram_pte_offset + 255 BT_CAPT_FIFO_ADDR_OFFSET; 256 reg_fifo_addr = ACP_BT_RX_FIFOADDR(chip); 257 reg_fifo_size = ACP_BT_RX_FIFOSIZE(chip); 258 if (chip->acp_rev >= ACP70_PCI_ID) 259 phy_addr = ACP7x_I2S_BT_RX_MEM_WINDOW_START; 260 else 261 phy_addr = I2S_BT_RX_MEM_WINDOW_START + stream->reg_offset; 262 writel(phy_addr, chip->base + ACP_BT_RX_RINGBUFADDR(chip)); 263 } 264 break; 265 case I2S_HS_INSTANCE: 266 if (dir == SNDRV_PCM_STREAM_PLAYBACK) { 267 reg_dma_size = ACP_HS_TX_DMA_SIZE; 268 acp_fifo_addr = rsrc->sram_pte_offset + 269 HS_PB_FIFO_ADDR_OFFSET; 270 reg_fifo_addr = ACP_HS_TX_FIFOADDR; 271 reg_fifo_size = ACP_HS_TX_FIFOSIZE; 272 if (chip->acp_rev >= ACP70_PCI_ID) 273 phy_addr = ACP7x_I2S_HS_TX_MEM_WINDOW_START; 274 else 275 phy_addr = I2S_HS_TX_MEM_WINDOW_START + stream->reg_offset; 276 writel(phy_addr, chip->base + ACP_HS_TX_RINGBUFADDR); 277 } else { 278 reg_dma_size = ACP_HS_RX_DMA_SIZE; 279 acp_fifo_addr = rsrc->sram_pte_offset + 280 HS_CAPT_FIFO_ADDR_OFFSET; 281 reg_fifo_addr = ACP_HS_RX_FIFOADDR; 282 reg_fifo_size = ACP_HS_RX_FIFOSIZE; 283 if (chip->acp_rev >= ACP70_PCI_ID) 284 phy_addr = ACP7x_I2S_HS_RX_MEM_WINDOW_START; 285 else 286 phy_addr = I2S_HS_RX_MEM_WINDOW_START + stream->reg_offset; 287 writel(phy_addr, chip->base + ACP_HS_RX_RINGBUFADDR); 288 } 289 break; 290 default: 291 dev_err(dev, "Invalid dai id %x\n", dai->driver->id); 292 return -EINVAL; 293 } 294 295 writel(DMA_SIZE, chip->base + reg_dma_size); 296 writel(acp_fifo_addr, chip->base + reg_fifo_addr); 297 writel(FIFO_SIZE, chip->base + reg_fifo_size); 298 299 ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(chip, rsrc->irqp_used)); 300 ext_int_ctrl |= BIT(I2S_RX_THRESHOLD(rsrc->offset)) | 301 BIT(BT_RX_THRESHOLD(rsrc->offset)) | 302 BIT(I2S_TX_THRESHOLD(rsrc->offset)) | 303 BIT(BT_TX_THRESHOLD(rsrc->offset)) | 304 BIT(HS_RX_THRESHOLD(rsrc->offset)) | 305 BIT(HS_TX_THRESHOLD(rsrc->offset)); 306 307 writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(chip, rsrc->irqp_used)); 308 return 0; 309} 310 311int restore_acp_i2s_params(struct snd_pcm_substream *substream, 312 struct acp_chip_info *chip, 313 struct acp_stream *stream) 314{ 315 struct snd_soc_dai *dai; 316 struct snd_soc_pcm_runtime *soc_runtime; 317 u32 tdm_fmt, reg_val, fmt_reg, val; 318 319 soc_runtime = snd_soc_substream_to_rtd(substream); 320 dai = snd_soc_rtd_to_cpu(soc_runtime, 0); 321 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 322 tdm_fmt = chip->tdm_tx_fmt[stream->dai_id - 1]; 323 switch (stream->dai_id) { 324 case I2S_BT_INSTANCE: 325 reg_val = ACP_BTTDM_ITER; 326 fmt_reg = ACP_BTTDM_TXFRMT; 327 break; 328 case I2S_SP_INSTANCE: 329 reg_val = ACP_I2STDM_ITER; 330 fmt_reg = ACP_I2STDM_TXFRMT; 331 break; 332 case I2S_HS_INSTANCE: 333 reg_val = ACP_HSTDM_ITER; 334 fmt_reg = ACP_HSTDM_TXFRMT; 335 break; 336 default: 337 pr_err("Invalid dai id %x\n", stream->dai_id); 338 return -EINVAL; 339 } 340 val = chip->xfer_tx_resolution[stream->dai_id - 1] << 3; 341 } else { 342 tdm_fmt = chip->tdm_rx_fmt[stream->dai_id - 1]; 343 switch (stream->dai_id) { 344 case I2S_BT_INSTANCE: 345 reg_val = ACP_BTTDM_IRER; 346 fmt_reg = ACP_BTTDM_RXFRMT; 347 break; 348 case I2S_SP_INSTANCE: 349 reg_val = ACP_I2STDM_IRER; 350 fmt_reg = ACP_I2STDM_RXFRMT; 351 break; 352 case I2S_HS_INSTANCE: 353 reg_val = ACP_HSTDM_IRER; 354 fmt_reg = ACP_HSTDM_RXFRMT; 355 break; 356 default: 357 pr_err("Invalid dai id %x\n", stream->dai_id); 358 return -EINVAL; 359 } 360 val = chip->xfer_rx_resolution[stream->dai_id - 1] << 3; 361 } 362 writel(val, chip->base + reg_val); 363 if (chip->tdm_mode == TDM_ENABLE) { 364 writel(tdm_fmt, chip->base + fmt_reg); 365 val = readl(chip->base + reg_val); 366 writel(val | 0x2, chip->base + reg_val); 367 } 368 return set_acp_i2s_dma_fifo(substream, dai); 369} 370EXPORT_SYMBOL_NS_GPL(restore_acp_i2s_params, "SND_SOC_ACP_COMMON"); 371 372static int acp_power_on(struct acp_chip_info *chip) 373{ 374 u32 val, acp_pgfsm_stat_reg, acp_pgfsm_ctrl_reg; 375 void __iomem *base; 376 377 base = chip->base; 378 switch (chip->acp_rev) { 379 case ACP_RN_PCI_ID: 380 acp_pgfsm_stat_reg = ACP_PGFSM_STATUS; 381 acp_pgfsm_ctrl_reg = ACP_PGFSM_CONTROL; 382 break; 383 case ACP_RMB_PCI_ID: 384 acp_pgfsm_stat_reg = ACP6X_PGFSM_STATUS; 385 acp_pgfsm_ctrl_reg = ACP6X_PGFSM_CONTROL; 386 break; 387 case ACP63_PCI_ID: 388 acp_pgfsm_stat_reg = ACP63_PGFSM_STATUS; 389 acp_pgfsm_ctrl_reg = ACP63_PGFSM_CONTROL; 390 break; 391 case ACP70_PCI_ID: 392 case ACP71_PCI_ID: 393 case ACP72_PCI_ID: 394 acp_pgfsm_stat_reg = ACP70_PGFSM_STATUS; 395 acp_pgfsm_ctrl_reg = ACP70_PGFSM_CONTROL; 396 break; 397 default: 398 return -EINVAL; 399 } 400 401 val = readl(base + acp_pgfsm_stat_reg); 402 if (val == ACP_POWERED_ON) 403 return 0; 404 405 if ((val & ACP_PGFSM_STATUS_MASK) != ACP_POWER_ON_IN_PROGRESS) 406 writel(ACP_PGFSM_CNTL_POWER_ON_MASK, base + acp_pgfsm_ctrl_reg); 407 408 return readl_poll_timeout(base + acp_pgfsm_stat_reg, val, 409 !val, DELAY_US, ACP_TIMEOUT); 410} 411 412static int acp_reset(void __iomem *base) 413{ 414 u32 val; 415 int ret; 416 417 writel(1, base + ACP_SOFT_RESET); 418 ret = readl_poll_timeout(base + ACP_SOFT_RESET, val, val & ACP_SOFT_RST_DONE_MASK, 419 DELAY_US, ACP_TIMEOUT); 420 if (ret) 421 return ret; 422 423 writel(0, base + ACP_SOFT_RESET); 424 return readl_poll_timeout(base + ACP_SOFT_RESET, val, !val, DELAY_US, ACP_TIMEOUT); 425} 426 427int acp_init(struct acp_chip_info *chip) 428{ 429 int ret; 430 431 /* power on */ 432 ret = acp_power_on(chip); 433 if (ret) { 434 pr_err("ACP power on failed\n"); 435 return ret; 436 } 437 writel(0x01, chip->base + ACP_CONTROL); 438 439 /* Reset */ 440 ret = acp_reset(chip->base); 441 if (ret) { 442 pr_err("ACP reset failed\n"); 443 return ret; 444 } 445 if (chip->acp_rev >= ACP70_PCI_ID) 446 writel(0, chip->base + ACP_ZSC_DSP_CTRL); 447 return 0; 448} 449EXPORT_SYMBOL_NS_GPL(acp_init, "SND_SOC_ACP_COMMON"); 450 451int acp_deinit(struct acp_chip_info *chip) 452{ 453 int ret; 454 455 /* Reset */ 456 ret = acp_reset(chip->base); 457 if (ret) 458 return ret; 459 460 if (chip->acp_rev < ACP70_PCI_ID) 461 writel(0, chip->base + ACP_CONTROL); 462 else 463 writel(0x01, chip->base + ACP_ZSC_DSP_CTRL); 464 return 0; 465} 466EXPORT_SYMBOL_NS_GPL(acp_deinit, "SND_SOC_ACP_COMMON"); 467int acp_machine_select(struct acp_chip_info *chip) 468{ 469 struct snd_soc_acpi_mach *mach; 470 int size, platform; 471 472 if (chip->flag == FLAG_AMD_LEGACY_ONLY_DMIC && chip->is_pdm_dev) { 473 platform = chip->acp_rev; 474 chip->mach_dev = platform_device_register_data(chip->dev, "acp-pdm-mach", 475 PLATFORM_DEVID_NONE, &platform, 476 sizeof(platform)); 477 } else { 478 size = sizeof(*chip->machines); 479 mach = snd_soc_acpi_find_machine(chip->machines); 480 if (!mach) { 481 dev_err(chip->dev, "warning: No matching ASoC machine driver found\n"); 482 return -EINVAL; 483 } 484 mach->mach_params.subsystem_rev = chip->acp_rev; 485 chip->mach_dev = platform_device_register_data(chip->dev, mach->drv_name, 486 PLATFORM_DEVID_NONE, mach, size); 487 } 488 if (IS_ERR(chip->mach_dev)) 489 dev_warn(chip->dev, "Unable to register Machine device\n"); 490 return 0; 491} 492EXPORT_SYMBOL_NS_GPL(acp_machine_select, "SND_SOC_ACP_COMMON"); 493 494static void check_acp3x_config(struct acp_chip_info *chip) 495{ 496 u32 val; 497 498 val = readl(chip->base + ACP3X_PIN_CONFIG); 499 switch (val) { 500 case ACP_CONFIG_4: 501 chip->is_i2s_config = true; 502 chip->is_pdm_config = true; 503 break; 504 default: 505 chip->is_pdm_config = true; 506 break; 507 } 508} 509 510static void check_acp6x_config(struct acp_chip_info *chip) 511{ 512 u32 val; 513 514 val = readl(chip->base + ACP_PIN_CONFIG); 515 switch (val) { 516 case ACP_CONFIG_4: 517 case ACP_CONFIG_5: 518 case ACP_CONFIG_6: 519 case ACP_CONFIG_7: 520 case ACP_CONFIG_8: 521 case ACP_CONFIG_11: 522 case ACP_CONFIG_14: 523 chip->is_pdm_config = true; 524 break; 525 case ACP_CONFIG_9: 526 chip->is_i2s_config = true; 527 break; 528 case ACP_CONFIG_10: 529 case ACP_CONFIG_12: 530 case ACP_CONFIG_13: 531 chip->is_i2s_config = true; 532 chip->is_pdm_config = true; 533 break; 534 default: 535 break; 536 } 537} 538 539static void check_acp70_config(struct acp_chip_info *chip) 540{ 541 u32 val; 542 543 val = readl(chip->base + ACP_PIN_CONFIG); 544 switch (val) { 545 case ACP_CONFIG_4: 546 case ACP_CONFIG_5: 547 case ACP_CONFIG_6: 548 case ACP_CONFIG_7: 549 case ACP_CONFIG_8: 550 case ACP_CONFIG_11: 551 case ACP_CONFIG_14: 552 case ACP_CONFIG_17: 553 case ACP_CONFIG_18: 554 chip->is_pdm_config = true; 555 break; 556 case ACP_CONFIG_9: 557 chip->is_i2s_config = true; 558 break; 559 case ACP_CONFIG_10: 560 case ACP_CONFIG_12: 561 case ACP_CONFIG_13: 562 case ACP_CONFIG_19: 563 case ACP_CONFIG_20: 564 chip->is_i2s_config = true; 565 chip->is_pdm_config = true; 566 break; 567 default: 568 break; 569 } 570} 571 572void check_acp_config(struct pci_dev *pci, struct acp_chip_info *chip) 573{ 574 struct acpi_device *pdm_dev; 575 const union acpi_object *obj; 576 acpi_handle handle; 577 acpi_integer dmic_status; 578 u32 pdm_addr, ret; 579 580 switch (chip->acp_rev) { 581 case ACP_RN_PCI_ID: 582 pdm_addr = ACP_RENOIR_PDM_ADDR; 583 check_acp3x_config(chip); 584 break; 585 case ACP_RMB_PCI_ID: 586 pdm_addr = ACP_REMBRANDT_PDM_ADDR; 587 check_acp6x_config(chip); 588 break; 589 case ACP63_PCI_ID: 590 pdm_addr = ACP63_PDM_ADDR; 591 check_acp6x_config(chip); 592 break; 593 case ACP70_PCI_ID: 594 case ACP71_PCI_ID: 595 case ACP72_PCI_ID: 596 pdm_addr = ACP70_PDM_ADDR; 597 check_acp70_config(chip); 598 break; 599 default: 600 break; 601 } 602 603 if (chip->is_pdm_config) { 604 pdm_dev = acpi_find_child_device(ACPI_COMPANION(&pci->dev), pdm_addr, 0); 605 if (pdm_dev) { 606 if (!acpi_dev_get_property(pdm_dev, "acp-audio-device-type", 607 ACPI_TYPE_INTEGER, &obj) && 608 obj->integer.value == pdm_addr) 609 chip->is_pdm_dev = true; 610 } 611 612 handle = ACPI_HANDLE(&pci->dev); 613 ret = acpi_evaluate_integer(handle, "_WOV", NULL, &dmic_status); 614 if (!ACPI_FAILURE(ret)) 615 chip->is_pdm_dev = dmic_status; 616 } 617} 618EXPORT_SYMBOL_NS_GPL(check_acp_config, "SND_SOC_ACP_COMMON"); 619 620struct snd_acp_hw_ops acp31_common_hw_ops; 621EXPORT_SYMBOL_NS_GPL(acp31_common_hw_ops, "SND_SOC_ACP_COMMON"); 622int acp31_hw_ops_init(struct acp_chip_info *chip) 623{ 624 memcpy(&acp31_common_hw_ops, &acp_common_hw_ops, sizeof(acp_common_hw_ops)); 625 chip->acp_hw_ops = &acp31_common_hw_ops; 626 627 return 0; 628} 629EXPORT_SYMBOL_NS_GPL(acp31_hw_ops_init, "SND_SOC_ACP_COMMON"); 630 631struct snd_acp_hw_ops acp6x_common_hw_ops; 632EXPORT_SYMBOL_NS_GPL(acp6x_common_hw_ops, "SND_SOC_ACP_COMMON"); 633int acp6x_hw_ops_init(struct acp_chip_info *chip) 634{ 635 memcpy(&acp6x_common_hw_ops, &acp_common_hw_ops, sizeof(acp_common_hw_ops)); 636 chip->acp_hw_ops = &acp6x_common_hw_ops; 637 638 return 0; 639} 640EXPORT_SYMBOL_NS_GPL(acp6x_hw_ops_init, "SND_SOC_ACP_COMMON"); 641 642struct snd_acp_hw_ops acp63_common_hw_ops; 643EXPORT_SYMBOL_NS_GPL(acp63_common_hw_ops, "SND_SOC_ACP_COMMON"); 644int acp63_hw_ops_init(struct acp_chip_info *chip) 645{ 646 memcpy(&acp63_common_hw_ops, &acp_common_hw_ops, sizeof(acp_common_hw_ops)); 647 chip->acp_hw_ops = &acp63_common_hw_ops; 648 649 return 0; 650} 651EXPORT_SYMBOL_NS_GPL(acp63_hw_ops_init, "SND_SOC_ACP_COMMON"); 652 653struct snd_acp_hw_ops acp70_common_hw_ops; 654EXPORT_SYMBOL_NS_GPL(acp70_common_hw_ops, "SND_SOC_ACP_COMMON"); 655int acp70_hw_ops_init(struct acp_chip_info *chip) 656{ 657 memcpy(&acp70_common_hw_ops, &acp_common_hw_ops, sizeof(acp_common_hw_ops)); 658 chip->acp_hw_ops = &acp70_common_hw_ops; 659 660 return 0; 661} 662EXPORT_SYMBOL_NS_GPL(acp70_hw_ops_init, "SND_SOC_ACP_COMMON"); 663 664MODULE_DESCRIPTION("AMD ACP legacy common features"); 665MODULE_LICENSE("Dual BSD/GPL");
~/
Read-only file preview.