diff options
Diffstat (limited to 'sound/soc/amd/acp/acp70.c')
-rw-r--r-- | sound/soc/amd/acp/acp70.c | 87 |
1 files changed, 64 insertions, 23 deletions
diff --git a/sound/soc/amd/acp/acp70.c b/sound/soc/amd/acp/acp70.c index a2cbdcca4313..68d2590e1a4e 100644 --- a/sound/soc/amd/acp/acp70.c +++ b/sound/soc/amd/acp/acp70.c @@ -25,14 +25,17 @@ #define DRV_NAME "acp_asoc_acp70" +#define CLK7_CLK0_DFS_CNTL_N1 0X0006C1A4 +#define CLK0_DIVIDER 0X19 + static struct acp_resource rsrc = { .offset = 0, .no_of_ctrls = 2, .irqp_used = 1, .soc_mclk = true, .irq_reg_offset = 0x1a00, - .scratch_reg_offset = 0x12800, - .sram_pte_offset = 0x03802800, + .scratch_reg_offset = 0x10000, + .sram_pte_offset = 0x03800000, }; static struct snd_soc_acpi_mach snd_soc_acpi_amd_acp70_acp_machines[] = { @@ -49,23 +52,23 @@ static struct snd_soc_dai_driver acp70_dai[] = { .id = I2S_SP_INSTANCE, .playback = { .stream_name = "I2S SP Playback", - .rates = SNDRV_PCM_RATE_8000_96000, + .rates = SNDRV_PCM_RATE_8000_192000, .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 2, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, - .rate_max = 96000, + .rate_max = 192000, }, .capture = { .stream_name = "I2S SP Capture", - .rates = SNDRV_PCM_RATE_8000_48000, + .rates = SNDRV_PCM_RATE_8000_192000, .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 2, - .channels_max = 2, + .channels_max = 32, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 192000, }, .ops = &asoc_acp_cpu_dai_ops, }, @@ -74,23 +77,23 @@ static struct snd_soc_dai_driver acp70_dai[] = { .id = I2S_BT_INSTANCE, .playback = { .stream_name = "I2S BT Playback", - .rates = SNDRV_PCM_RATE_8000_96000, + .rates = SNDRV_PCM_RATE_8000_192000, .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 2, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, - .rate_max = 96000, + .rate_max = 192000, }, .capture = { .stream_name = "I2S BT Capture", - .rates = SNDRV_PCM_RATE_8000_48000, + .rates = SNDRV_PCM_RATE_8000_192000, .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 2, - .channels_max = 2, + .channels_max = 32, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 192000, }, .ops = &asoc_acp_cpu_dai_ops, }, @@ -99,23 +102,23 @@ static struct snd_soc_dai_driver acp70_dai[] = { .id = I2S_HS_INSTANCE, .playback = { .stream_name = "I2S HS Playback", - .rates = SNDRV_PCM_RATE_8000_96000, + .rates = SNDRV_PCM_RATE_8000_192000, .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 2, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, - .rate_max = 96000, + .rate_max = 192000, }, .capture = { .stream_name = "I2S HS Capture", - .rates = SNDRV_PCM_RATE_8000_48000, + .rates = SNDRV_PCM_RATE_8000_192000, .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 2, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 192000, }, .ops = &asoc_acp_cpu_dai_ops, }, @@ -134,12 +137,36 @@ static struct snd_soc_dai_driver acp70_dai[] = { }, }; +static int acp70_i2s_master_clock_generate(struct acp_dev_data *adata) +{ + struct pci_dev *smn_dev; + u32 device_id; + + if (adata->platform == ACP70) + device_id = 0x1507; + else if (adata->platform == ACP71) + device_id = 0x1122; + else + return -ENODEV; + + smn_dev = pci_get_device(PCI_VENDOR_ID_AMD, device_id, NULL); + + if (!smn_dev) + return -ENODEV; + + /* Set clk7 DFS clock divider register value to get mclk as 196.608MHz*/ + smn_write(smn_dev, CLK7_CLK0_DFS_CNTL_N1, CLK0_DIVIDER); + + return 0; +} + static int acp_acp70_audio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct acp_chip_info *chip; struct acp_dev_data *adata; struct resource *res; + int ret; chip = dev_get_platdata(&pdev->dev); if (!chip || !chip->base) { @@ -147,7 +174,11 @@ static int acp_acp70_audio_probe(struct platform_device *pdev) return -ENODEV; } - if (chip->acp_rev != ACP70_DEV) { + switch (chip->acp_rev) { + case ACP70_DEV: + case ACP71_DEV: + break; + default: dev_err(&pdev->dev, "Un-supported ACP Revision %d\n", chip->acp_rev); return -ENODEV; } @@ -178,11 +209,21 @@ static int acp_acp70_audio_probe(struct platform_device *pdev) adata->num_dai = ARRAY_SIZE(acp70_dai); adata->rsrc = &rsrc; adata->machines = snd_soc_acpi_amd_acp70_acp_machines; - adata->platform = ACP70; + if (chip->acp_rev == ACP70_DEV) + adata->platform = ACP70; + else + adata->platform = ACP71; + adata->flag = chip->flag; acp_machine_select(adata); dev_set_drvdata(dev, adata); + + ret = acp70_i2s_master_clock_generate(adata); + if (ret) { + dev_err(&pdev->dev, "Failed to set I2S master clock as 196.608MHz\n"); + return ret; + } acp_enable_interrupts(adata); acp_platform_register(dev); pm_runtime_set_autosuspend_delay(&pdev->dev, ACP_SUSPEND_DELAY_MS); @@ -237,7 +278,7 @@ static const struct dev_pm_ops acp70_dma_pm_ops = { static struct platform_driver acp70_driver = { .probe = acp_acp70_audio_probe, - .remove_new = acp_acp70_audio_remove, + .remove = acp_acp70_audio_remove, .driver = { .name = "acp_asoc_acp70", .pm = &acp70_dma_pm_ops, |