Skip to content

Commit 09068d6

Browse files
vijendarmukundabroonie
authored andcommitted
ASoC: amd: acp: fix for acp platform device creation failure
ACP pin configuration varies based on acp version. ACP PCI driver should read the ACP PIN config value and based on config value, it has to create a platform device in below two conditions. 1) If ACP PDM configuration is selected from BIOS and ACP PDM controller exists. 2) If ACP I2S configuration is selected from BIOS. Other than above scenarios, ACP PCI driver should skip the platform device creation logic, i.e. ACP PCI driver probe sequence should never fail if other acp pin configuration is selected. It should skip platform device creation logic. check_acp_pdm() function was implemented for ACP6.x platforms to check ACP PDM configuration. Previously, this code was safe guarded by FLAG_AMD_LEGACY_ONLY_DMIC flag check. This implementation breaks audio use cases for Huawei Matebooks which are based on ACP3.x varaint uses I2S configuration. In current scenario, check_acp_pdm() function returns -ENODEV value which results in ACP PCI driver probe failure without creating a platform device even in case of valid ACP pin configuration. Implement check_acp_config() as a common function which invokes platform specific acp pin configuration check functions for ACP3.x, ACP6.0 & ACP6.3 & ACP7.0 variants and checks for ACP PDM controller. Closes: https://bugzilla.kernel.org/show_bug.cgi?id=218780 Fixes: 4af565d ("ASoC: amd: acp: fix for acp pdm configuration check") Signed-off-by: Vijendar Mukunda <Vijendar.Mukunda@amd.com> Link: https://lore.kernel.org/r/20240502140340.4049021-1-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent c5782bb commit 09068d6

File tree

4 files changed

+95
-21
lines changed

4 files changed

+95
-21
lines changed

sound/soc/amd/acp/acp-legacy-common.c

Lines changed: 81 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -358,11 +358,25 @@ int smn_read(struct pci_dev *dev, u32 smn_addr)
358358
}
359359
EXPORT_SYMBOL_NS_GPL(smn_read, SND_SOC_ACP_COMMON);
360360

361-
int check_acp_pdm(struct pci_dev *pci, struct acp_chip_info *chip)
361+
static void check_acp3x_config(struct acp_chip_info *chip)
362362
{
363-
struct acpi_device *pdm_dev;
364-
const union acpi_object *obj;
365-
u32 pdm_addr, val;
363+
u32 val;
364+
365+
val = readl(chip->base + ACP3X_PIN_CONFIG);
366+
switch (val) {
367+
case ACP_CONFIG_4:
368+
chip->is_i2s_config = true;
369+
chip->is_pdm_config = true;
370+
break;
371+
default:
372+
chip->is_pdm_config = true;
373+
break;
374+
}
375+
}
376+
377+
static void check_acp6x_config(struct acp_chip_info *chip)
378+
{
379+
u32 val;
366380

367381
val = readl(chip->base + ACP_PIN_CONFIG);
368382
switch (val) {
@@ -371,42 +385,94 @@ int check_acp_pdm(struct pci_dev *pci, struct acp_chip_info *chip)
371385
case ACP_CONFIG_6:
372386
case ACP_CONFIG_7:
373387
case ACP_CONFIG_8:
374-
case ACP_CONFIG_10:
375388
case ACP_CONFIG_11:
389+
case ACP_CONFIG_14:
390+
chip->is_pdm_config = true;
391+
break;
392+
case ACP_CONFIG_9:
393+
chip->is_i2s_config = true;
394+
break;
395+
case ACP_CONFIG_10:
376396
case ACP_CONFIG_12:
377397
case ACP_CONFIG_13:
398+
chip->is_i2s_config = true;
399+
chip->is_pdm_config = true;
400+
break;
401+
default:
402+
break;
403+
}
404+
}
405+
406+
static void check_acp70_config(struct acp_chip_info *chip)
407+
{
408+
u32 val;
409+
410+
val = readl(chip->base + ACP_PIN_CONFIG);
411+
switch (val) {
412+
case ACP_CONFIG_4:
413+
case ACP_CONFIG_5:
414+
case ACP_CONFIG_6:
415+
case ACP_CONFIG_7:
416+
case ACP_CONFIG_8:
417+
case ACP_CONFIG_11:
378418
case ACP_CONFIG_14:
419+
case ACP_CONFIG_17:
420+
case ACP_CONFIG_18:
421+
chip->is_pdm_config = true;
422+
break;
423+
case ACP_CONFIG_9:
424+
chip->is_i2s_config = true;
425+
break;
426+
case ACP_CONFIG_10:
427+
case ACP_CONFIG_12:
428+
case ACP_CONFIG_13:
429+
case ACP_CONFIG_19:
430+
case ACP_CONFIG_20:
431+
chip->is_i2s_config = true;
432+
chip->is_pdm_config = true;
379433
break;
380434
default:
381-
return -EINVAL;
435+
break;
382436
}
437+
}
438+
439+
void check_acp_config(struct pci_dev *pci, struct acp_chip_info *chip)
440+
{
441+
struct acpi_device *pdm_dev;
442+
const union acpi_object *obj;
443+
u32 pdm_addr;
383444

384445
switch (chip->acp_rev) {
385446
case ACP3X_DEV:
386447
pdm_addr = ACP_RENOIR_PDM_ADDR;
448+
check_acp3x_config(chip);
387449
break;
388450
case ACP6X_DEV:
389451
pdm_addr = ACP_REMBRANDT_PDM_ADDR;
452+
check_acp6x_config(chip);
390453
break;
391454
case ACP63_DEV:
392455
pdm_addr = ACP63_PDM_ADDR;
456+
check_acp6x_config(chip);
393457
break;
394458
case ACP70_DEV:
395459
pdm_addr = ACP70_PDM_ADDR;
460+
check_acp70_config(chip);
396461
break;
397462
default:
398-
return -EINVAL;
463+
break;
399464
}
400465

401-
pdm_dev = acpi_find_child_device(ACPI_COMPANION(&pci->dev), pdm_addr, 0);
402-
if (pdm_dev) {
403-
if (!acpi_dev_get_property(pdm_dev, "acp-audio-device-type",
404-
ACPI_TYPE_INTEGER, &obj) &&
405-
obj->integer.value == pdm_addr)
406-
return 0;
466+
if (chip->is_pdm_config) {
467+
pdm_dev = acpi_find_child_device(ACPI_COMPANION(&pci->dev), pdm_addr, 0);
468+
if (pdm_dev) {
469+
if (!acpi_dev_get_property(pdm_dev, "acp-audio-device-type",
470+
ACPI_TYPE_INTEGER, &obj) &&
471+
obj->integer.value == pdm_addr)
472+
chip->is_pdm_dev = true;
473+
}
407474
}
408-
return -ENODEV;
409475
}
410-
EXPORT_SYMBOL_NS_GPL(check_acp_pdm, SND_SOC_ACP_COMMON);
476+
EXPORT_SYMBOL_NS_GPL(check_acp_config, SND_SOC_ACP_COMMON);
411477

412478
MODULE_LICENSE("Dual BSD/GPL");

sound/soc/amd/acp/acp-pci.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,6 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id
100100
ret = -EINVAL;
101101
goto release_regions;
102102
}
103-
104103
dmic_dev = platform_device_register_data(dev, "dmic-codec", PLATFORM_DEVID_NONE, NULL, 0);
105104
if (IS_ERR(dmic_dev)) {
106105
dev_err(dev, "failed to create DMIC device\n");
@@ -119,6 +118,10 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id
119118
if (ret)
120119
goto unregister_dmic_dev;
121120

121+
check_acp_config(pci, chip);
122+
if (!chip->is_pdm_dev && !chip->is_i2s_config)
123+
goto skip_pdev_creation;
124+
122125
res = devm_kcalloc(&pci->dev, num_res, sizeof(struct resource), GFP_KERNEL);
123126
if (!res) {
124127
ret = -ENOMEM;
@@ -136,10 +139,6 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id
136139
}
137140
}
138141

139-
ret = check_acp_pdm(pci, chip);
140-
if (ret < 0)
141-
goto skip_pdev_creation;
142-
143142
chip->flag = flag;
144143
memset(&pdevinfo, 0, sizeof(pdevinfo));
145144

sound/soc/amd/acp/amd.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,9 @@ struct acp_chip_info {
138138
void __iomem *base; /* ACP memory PCI base */
139139
struct platform_device *chip_pdev;
140140
unsigned int flag; /* Distinguish b/w Legacy or Only PDM */
141+
bool is_pdm_dev; /* flag set to true when ACP PDM controller exists */
142+
bool is_pdm_config; /* flag set to true when PDM configuration is selected from BIOS */
143+
bool is_i2s_config; /* flag set to true when I2S configuration is selected from BIOS */
141144
};
142145

143146
struct acp_stream {
@@ -212,6 +215,11 @@ enum acp_config {
212215
ACP_CONFIG_13,
213216
ACP_CONFIG_14,
214217
ACP_CONFIG_15,
218+
ACP_CONFIG_16,
219+
ACP_CONFIG_17,
220+
ACP_CONFIG_18,
221+
ACP_CONFIG_19,
222+
ACP_CONFIG_20,
215223
};
216224

217225
extern const struct snd_soc_dai_ops asoc_acp_cpu_dai_ops;
@@ -240,7 +248,7 @@ void restore_acp_pdm_params(struct snd_pcm_substream *substream,
240248
int restore_acp_i2s_params(struct snd_pcm_substream *substream,
241249
struct acp_dev_data *adata, struct acp_stream *stream);
242250

243-
int check_acp_pdm(struct pci_dev *pci, struct acp_chip_info *chip);
251+
void check_acp_config(struct pci_dev *pci, struct acp_chip_info *chip);
244252

245253
static inline u64 acp_get_byte_count(struct acp_dev_data *adata, int dai_id, int direction)
246254
{

sound/soc/amd/acp/chip_offset_byte.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#define ACP_SOFT_RESET 0x1000
2121
#define ACP_CONTROL 0x1004
2222
#define ACP_PIN_CONFIG 0x1440
23+
#define ACP3X_PIN_CONFIG 0x1400
2324

2425
#define ACP_EXTERNAL_INTR_REG_ADDR(adata, offset, ctrl) \
2526
(adata->acp_base + adata->rsrc->irq_reg_offset + offset + (ctrl * 0x04))

0 commit comments

Comments
 (0)