1e8a33a94SV sujith kumar Reddy // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) 2e8a33a94SV sujith kumar Reddy // 3e8a33a94SV sujith kumar Reddy // This file is provided under a dual BSD/GPLv2 license. When using or 4e8a33a94SV sujith kumar Reddy // redistributing this file, you may do so under either license. 5e8a33a94SV sujith kumar Reddy // 6e8a33a94SV sujith kumar Reddy // Copyright(c) 2022 Advanced Micro Devices, Inc. 7e8a33a94SV sujith kumar Reddy // 8e8a33a94SV sujith kumar Reddy // Authors: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com> 9e8a33a94SV sujith kumar Reddy // V sujith kumar Reddy <Vsujithkumar.Reddy@amd.com> 10e8a33a94SV sujith kumar Reddy /* 11e8a33a94SV sujith kumar Reddy * Hardware interface for Renoir ACP block 12e8a33a94SV sujith kumar Reddy */ 13e8a33a94SV sujith kumar Reddy 14e8a33a94SV sujith kumar Reddy #include <linux/platform_device.h> 15e8a33a94SV sujith kumar Reddy #include <linux/module.h> 16e8a33a94SV sujith kumar Reddy #include <linux/err.h> 17e8a33a94SV sujith kumar Reddy #include <linux/io.h> 18e8a33a94SV sujith kumar Reddy #include <sound/pcm_params.h> 19e8a33a94SV sujith kumar Reddy #include <sound/soc.h> 20e8a33a94SV sujith kumar Reddy #include <sound/soc-dai.h> 21e8a33a94SV sujith kumar Reddy #include <linux/dma-mapping.h> 227ad6fb9dSSyed Saba Kareem #include <linux/pci.h> 23e8a33a94SV sujith kumar Reddy 24e8a33a94SV sujith kumar Reddy #include "amd.h" 25e8a33a94SV sujith kumar Reddy 26e8a33a94SV sujith kumar Reddy #define DRV_NAME "acp_asoc_rembrandt" 27e8a33a94SV sujith kumar Reddy 287ad6fb9dSSyed Saba Kareem #define MP1_C2PMSG_69 0x3B10A14 297ad6fb9dSSyed Saba Kareem #define MP1_C2PMSG_85 0x3B10A54 307ad6fb9dSSyed Saba Kareem #define MP1_C2PMSG_93 0x3B10A74 317ad6fb9dSSyed Saba Kareem #define HOST_BRIDGE_ID 0x14B5 327ad6fb9dSSyed Saba Kareem 33e8a33a94SV sujith kumar Reddy static struct acp_resource rsrc = { 34e8a33a94SV sujith kumar Reddy .offset = 0, 35e8a33a94SV sujith kumar Reddy .no_of_ctrls = 2, 36e8a33a94SV sujith kumar Reddy .irqp_used = 1, 37e8a33a94SV sujith kumar Reddy .soc_mclk = true, 38e8a33a94SV sujith kumar Reddy .irq_reg_offset = 0x1a00, 39e8a33a94SV sujith kumar Reddy .i2s_pin_cfg_offset = 0x1440, 40e8a33a94SV sujith kumar Reddy .i2s_mode = 0x0a, 41e8a33a94SV sujith kumar Reddy .scratch_reg_offset = 0x12800, 42e8a33a94SV sujith kumar Reddy .sram_pte_offset = 0x03802800, 43e8a33a94SV sujith kumar Reddy }; 44e8a33a94SV sujith kumar Reddy 45e8a33a94SV sujith kumar Reddy static struct snd_soc_acpi_codecs amp_rt1019 = { 46e8a33a94SV sujith kumar Reddy .num_codecs = 1, 47e8a33a94SV sujith kumar Reddy .codecs = {"10EC1019"} 48e8a33a94SV sujith kumar Reddy }; 49e8a33a94SV sujith kumar Reddy 50e8a33a94SV sujith kumar Reddy static struct snd_soc_acpi_codecs amp_max = { 51e8a33a94SV sujith kumar Reddy .num_codecs = 1, 52e8a33a94SV sujith kumar Reddy .codecs = {"MX98360A"} 53e8a33a94SV sujith kumar Reddy }; 54e8a33a94SV sujith kumar Reddy 55e8a33a94SV sujith kumar Reddy static struct snd_soc_acpi_mach snd_soc_acpi_amd_rmb_acp_machines[] = { 56e8a33a94SV sujith kumar Reddy { 57e8a33a94SV sujith kumar Reddy .id = "10508825", 58e8a33a94SV sujith kumar Reddy .drv_name = "rmb-nau8825-max", 59e8a33a94SV sujith kumar Reddy .machine_quirk = snd_soc_acpi_codec_list, 60e8a33a94SV sujith kumar Reddy .quirk_data = &_max, 61e8a33a94SV sujith kumar Reddy }, 62e8a33a94SV sujith kumar Reddy { 63e8a33a94SV sujith kumar Reddy .id = "AMDI0007", 64e8a33a94SV sujith kumar Reddy .drv_name = "rembrandt-acp", 65e8a33a94SV sujith kumar Reddy }, 66e8a33a94SV sujith kumar Reddy { 67e8a33a94SV sujith kumar Reddy .id = "RTL5682", 68e8a33a94SV sujith kumar Reddy .drv_name = "rmb-rt5682s-rt1019", 69e8a33a94SV sujith kumar Reddy .machine_quirk = snd_soc_acpi_codec_list, 70e8a33a94SV sujith kumar Reddy .quirk_data = &_rt1019, 71e8a33a94SV sujith kumar Reddy }, 72e8a33a94SV sujith kumar Reddy {}, 73e8a33a94SV sujith kumar Reddy }; 74e8a33a94SV sujith kumar Reddy 75e8a33a94SV sujith kumar Reddy static struct snd_soc_dai_driver acp_rmb_dai[] = { 76e8a33a94SV sujith kumar Reddy { 77e8a33a94SV sujith kumar Reddy .name = "acp-i2s-sp", 78e8a33a94SV sujith kumar Reddy .id = I2S_SP_INSTANCE, 79e8a33a94SV sujith kumar Reddy .playback = { 80e8a33a94SV sujith kumar Reddy .stream_name = "I2S SP Playback", 81e8a33a94SV sujith kumar Reddy .rates = SNDRV_PCM_RATE_8000_96000, 82e8a33a94SV sujith kumar Reddy .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | 83e8a33a94SV sujith kumar Reddy SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, 84e8a33a94SV sujith kumar Reddy .channels_min = 2, 85e8a33a94SV sujith kumar Reddy .channels_max = 8, 86e8a33a94SV sujith kumar Reddy .rate_min = 8000, 87e8a33a94SV sujith kumar Reddy .rate_max = 96000, 88e8a33a94SV sujith kumar Reddy }, 89e8a33a94SV sujith kumar Reddy .capture = { 90e8a33a94SV sujith kumar Reddy .stream_name = "I2S SP Capture", 91e8a33a94SV sujith kumar Reddy .rates = SNDRV_PCM_RATE_8000_48000, 92e8a33a94SV sujith kumar Reddy .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | 93e8a33a94SV sujith kumar Reddy SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, 94e8a33a94SV sujith kumar Reddy .channels_min = 2, 95e8a33a94SV sujith kumar Reddy .channels_max = 2, 96e8a33a94SV sujith kumar Reddy .rate_min = 8000, 97e8a33a94SV sujith kumar Reddy .rate_max = 48000, 98e8a33a94SV sujith kumar Reddy }, 99e8a33a94SV sujith kumar Reddy .ops = &asoc_acp_cpu_dai_ops, 100e8a33a94SV sujith kumar Reddy .probe = &asoc_acp_i2s_probe, 101e8a33a94SV sujith kumar Reddy }, 102e8a33a94SV sujith kumar Reddy { 103e8a33a94SV sujith kumar Reddy .name = "acp-i2s-bt", 104e8a33a94SV sujith kumar Reddy .id = I2S_BT_INSTANCE, 105e8a33a94SV sujith kumar Reddy .playback = { 106e8a33a94SV sujith kumar Reddy .stream_name = "I2S BT Playback", 107e8a33a94SV sujith kumar Reddy .rates = SNDRV_PCM_RATE_8000_96000, 108e8a33a94SV sujith kumar Reddy .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | 109e8a33a94SV sujith kumar Reddy SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, 110e8a33a94SV sujith kumar Reddy .channels_min = 2, 111e8a33a94SV sujith kumar Reddy .channels_max = 8, 112e8a33a94SV sujith kumar Reddy .rate_min = 8000, 113e8a33a94SV sujith kumar Reddy .rate_max = 96000, 114e8a33a94SV sujith kumar Reddy }, 115e8a33a94SV sujith kumar Reddy .capture = { 116e8a33a94SV sujith kumar Reddy .stream_name = "I2S BT Capture", 117e8a33a94SV sujith kumar Reddy .rates = SNDRV_PCM_RATE_8000_48000, 118e8a33a94SV sujith kumar Reddy .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | 119e8a33a94SV sujith kumar Reddy SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, 120e8a33a94SV sujith kumar Reddy .channels_min = 2, 121e8a33a94SV sujith kumar Reddy .channels_max = 2, 122e8a33a94SV sujith kumar Reddy .rate_min = 8000, 123e8a33a94SV sujith kumar Reddy .rate_max = 48000, 124e8a33a94SV sujith kumar Reddy }, 125e8a33a94SV sujith kumar Reddy .ops = &asoc_acp_cpu_dai_ops, 126e8a33a94SV sujith kumar Reddy .probe = &asoc_acp_i2s_probe, 127e8a33a94SV sujith kumar Reddy }, 128e8a33a94SV sujith kumar Reddy { 129e8a33a94SV sujith kumar Reddy .name = "acp-i2s-hs", 130e8a33a94SV sujith kumar Reddy .id = I2S_HS_INSTANCE, 131e8a33a94SV sujith kumar Reddy .playback = { 132e8a33a94SV sujith kumar Reddy .stream_name = "I2S HS Playback", 133e8a33a94SV sujith kumar Reddy .rates = SNDRV_PCM_RATE_8000_96000, 134e8a33a94SV sujith kumar Reddy .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | 135e8a33a94SV sujith kumar Reddy SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, 136e8a33a94SV sujith kumar Reddy .channels_min = 2, 137e8a33a94SV sujith kumar Reddy .channels_max = 8, 138e8a33a94SV sujith kumar Reddy .rate_min = 8000, 139e8a33a94SV sujith kumar Reddy .rate_max = 96000, 140e8a33a94SV sujith kumar Reddy }, 141e8a33a94SV sujith kumar Reddy .capture = { 142e8a33a94SV sujith kumar Reddy .stream_name = "I2S HS Capture", 143e8a33a94SV sujith kumar Reddy .rates = SNDRV_PCM_RATE_8000_48000, 144e8a33a94SV sujith kumar Reddy .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | 145e8a33a94SV sujith kumar Reddy SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, 146e8a33a94SV sujith kumar Reddy .channels_min = 2, 147e8a33a94SV sujith kumar Reddy .channels_max = 8, 148e8a33a94SV sujith kumar Reddy .rate_min = 8000, 149e8a33a94SV sujith kumar Reddy .rate_max = 48000, 150e8a33a94SV sujith kumar Reddy }, 151e8a33a94SV sujith kumar Reddy .ops = &asoc_acp_cpu_dai_ops, 152e8a33a94SV sujith kumar Reddy .probe = &asoc_acp_i2s_probe, 153e8a33a94SV sujith kumar Reddy }, 154e8a33a94SV sujith kumar Reddy { 155e8a33a94SV sujith kumar Reddy .name = "acp-pdm-dmic", 156e8a33a94SV sujith kumar Reddy .id = DMIC_INSTANCE, 157e8a33a94SV sujith kumar Reddy .capture = { 158e8a33a94SV sujith kumar Reddy .rates = SNDRV_PCM_RATE_8000_48000, 159e8a33a94SV sujith kumar Reddy .formats = SNDRV_PCM_FMTBIT_S32_LE, 160e8a33a94SV sujith kumar Reddy .channels_min = 2, 161e8a33a94SV sujith kumar Reddy .channels_max = 2, 162e8a33a94SV sujith kumar Reddy .rate_min = 8000, 163e8a33a94SV sujith kumar Reddy .rate_max = 48000, 164e8a33a94SV sujith kumar Reddy }, 165e8a33a94SV sujith kumar Reddy .ops = &acp_dmic_dai_ops, 166e8a33a94SV sujith kumar Reddy }, 167e8a33a94SV sujith kumar Reddy }; 168e8a33a94SV sujith kumar Reddy 1697ad6fb9dSSyed Saba Kareem static int acp6x_master_clock_generate(struct device *dev) 1707ad6fb9dSSyed Saba Kareem { 1717ad6fb9dSSyed Saba Kareem int data = 0; 1727ad6fb9dSSyed Saba Kareem struct pci_dev *smn_dev; 1737ad6fb9dSSyed Saba Kareem 1747ad6fb9dSSyed Saba Kareem smn_dev = pci_get_device(PCI_VENDOR_ID_AMD, HOST_BRIDGE_ID, NULL); 1757ad6fb9dSSyed Saba Kareem if (!smn_dev) { 1767ad6fb9dSSyed Saba Kareem dev_err(dev, "Failed to get host bridge device\n"); 1777ad6fb9dSSyed Saba Kareem return -ENODEV; 1787ad6fb9dSSyed Saba Kareem } 1797ad6fb9dSSyed Saba Kareem 1807ad6fb9dSSyed Saba Kareem smn_write(smn_dev, MP1_C2PMSG_93, 0); 1817ad6fb9dSSyed Saba Kareem smn_write(smn_dev, MP1_C2PMSG_85, 0xC4); 1827ad6fb9dSSyed Saba Kareem smn_write(smn_dev, MP1_C2PMSG_69, 0x4); 1837ad6fb9dSSyed Saba Kareem read_poll_timeout(smn_read, data, data, DELAY_US, 1847ad6fb9dSSyed Saba Kareem ACP_TIMEOUT, false, smn_dev, MP1_C2PMSG_93); 1857ad6fb9dSSyed Saba Kareem return 0; 1867ad6fb9dSSyed Saba Kareem } 1877ad6fb9dSSyed Saba Kareem 188e8a33a94SV sujith kumar Reddy static int rembrandt_audio_probe(struct platform_device *pdev) 189e8a33a94SV sujith kumar Reddy { 190e8a33a94SV sujith kumar Reddy struct device *dev = &pdev->dev; 191e8a33a94SV sujith kumar Reddy struct acp_chip_info *chip; 192e8a33a94SV sujith kumar Reddy struct acp_dev_data *adata; 193e8a33a94SV sujith kumar Reddy struct resource *res; 194e8a33a94SV sujith kumar Reddy 195e8a33a94SV sujith kumar Reddy chip = dev_get_platdata(&pdev->dev); 196e8a33a94SV sujith kumar Reddy if (!chip || !chip->base) { 197e8a33a94SV sujith kumar Reddy dev_err(&pdev->dev, "ACP chip data is NULL\n"); 198e8a33a94SV sujith kumar Reddy return -ENODEV; 199e8a33a94SV sujith kumar Reddy } 200e8a33a94SV sujith kumar Reddy 201e8a33a94SV sujith kumar Reddy if (chip->acp_rev != ACP6X_DEV) { 202e8a33a94SV sujith kumar Reddy dev_err(&pdev->dev, "Un-supported ACP Revision %d\n", chip->acp_rev); 203e8a33a94SV sujith kumar Reddy return -ENODEV; 204e8a33a94SV sujith kumar Reddy } 205e8a33a94SV sujith kumar Reddy 206e8a33a94SV sujith kumar Reddy adata = devm_kzalloc(dev, sizeof(struct acp_dev_data), GFP_KERNEL); 207e8a33a94SV sujith kumar Reddy if (!adata) 208e8a33a94SV sujith kumar Reddy return -ENOMEM; 209e8a33a94SV sujith kumar Reddy 210e8a33a94SV sujith kumar Reddy res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "acp_mem"); 211e8a33a94SV sujith kumar Reddy if (!res) { 212e8a33a94SV sujith kumar Reddy dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n"); 213e8a33a94SV sujith kumar Reddy return -ENODEV; 214e8a33a94SV sujith kumar Reddy } 215e8a33a94SV sujith kumar Reddy 216e8a33a94SV sujith kumar Reddy adata->acp_base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); 217e8a33a94SV sujith kumar Reddy if (!adata->acp_base) 218e8a33a94SV sujith kumar Reddy return -ENOMEM; 219e8a33a94SV sujith kumar Reddy 220e8a33a94SV sujith kumar Reddy res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "acp_dai_irq"); 221e8a33a94SV sujith kumar Reddy if (!res) { 222e8a33a94SV sujith kumar Reddy dev_err(&pdev->dev, "IORESOURCE_IRQ FAILED\n"); 223e8a33a94SV sujith kumar Reddy return -ENODEV; 224e8a33a94SV sujith kumar Reddy } 225e8a33a94SV sujith kumar Reddy 226e8a33a94SV sujith kumar Reddy adata->i2s_irq = res->start; 227e8a33a94SV sujith kumar Reddy adata->dev = dev; 228e8a33a94SV sujith kumar Reddy adata->dai_driver = acp_rmb_dai; 229e8a33a94SV sujith kumar Reddy adata->num_dai = ARRAY_SIZE(acp_rmb_dai); 230e8a33a94SV sujith kumar Reddy adata->rsrc = &rsrc; 231e8a33a94SV sujith kumar Reddy 232e8a33a94SV sujith kumar Reddy adata->machines = snd_soc_acpi_amd_rmb_acp_machines; 233e8a33a94SV sujith kumar Reddy acp_machine_select(adata); 234e8a33a94SV sujith kumar Reddy 235e8a33a94SV sujith kumar Reddy dev_set_drvdata(dev, adata); 2367ad6fb9dSSyed Saba Kareem acp6x_master_clock_generate(dev); 237*fc11d326SSyed Saba Kareem acp_enable_interrupts(adata); 238e8a33a94SV sujith kumar Reddy acp_platform_register(dev); 239e8a33a94SV sujith kumar Reddy 240e8a33a94SV sujith kumar Reddy return 0; 241e8a33a94SV sujith kumar Reddy } 242e8a33a94SV sujith kumar Reddy 24337846af6SUwe Kleine-König static void rembrandt_audio_remove(struct platform_device *pdev) 244e8a33a94SV sujith kumar Reddy { 245e8a33a94SV sujith kumar Reddy struct device *dev = &pdev->dev; 246e8a33a94SV sujith kumar Reddy struct acp_dev_data *adata = dev_get_drvdata(dev); 247e8a33a94SV sujith kumar Reddy 248*fc11d326SSyed Saba Kareem acp_disable_interrupts(adata); 249e8a33a94SV sujith kumar Reddy acp_platform_unregister(dev); 250e8a33a94SV sujith kumar Reddy } 251e8a33a94SV sujith kumar Reddy 252e8a33a94SV sujith kumar Reddy static struct platform_driver rembrandt_driver = { 253e8a33a94SV sujith kumar Reddy .probe = rembrandt_audio_probe, 25437846af6SUwe Kleine-König .remove_new = rembrandt_audio_remove, 255e8a33a94SV sujith kumar Reddy .driver = { 256e8a33a94SV sujith kumar Reddy .name = "acp_asoc_rembrandt", 257e8a33a94SV sujith kumar Reddy }, 258e8a33a94SV sujith kumar Reddy }; 259e8a33a94SV sujith kumar Reddy 260e8a33a94SV sujith kumar Reddy module_platform_driver(rembrandt_driver); 261e8a33a94SV sujith kumar Reddy 262e8a33a94SV sujith kumar Reddy MODULE_DESCRIPTION("AMD ACP Rembrandt Driver"); 263e8a33a94SV sujith kumar Reddy MODULE_IMPORT_NS(SND_SOC_ACP_COMMON); 264e8a33a94SV sujith kumar Reddy MODULE_LICENSE("Dual BSD/GPL"); 265e8a33a94SV sujith kumar Reddy MODULE_ALIAS("platform:" DRV_NAME); 266