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 * Hardware interface for ACP6.3 block 11 */ 12 13 #include <linux/platform_device.h> 14 #include <linux/module.h> 15 #include <linux/err.h> 16 #include <linux/io.h> 17 #include <sound/pcm_params.h> 18 #include <sound/soc.h> 19 #include <sound/soc-dai.h> 20 #include <linux/dma-mapping.h> 21 #include <linux/pm_runtime.h> 22 #include <linux/pci.h> 23 #include "amd.h" 24 #include "acp-mach.h" 25 #include "../mach-config.h" 26 27 #define DRV_NAME "acp_asoc_acp63" 28 29 #define CLK_PLL_PWR_REQ_N0 0X0006C2C0 30 #define CLK_SPLL_FIELD_2_N0 0X0006C114 31 #define CLK_PLL_REQ_N0 0X0006C0DC 32 #define CLK_DFSBYPASS_CONTR 0X0006C2C8 33 #define CLK_DFS_CNTL_N0 0X0006C1A4 34 35 #define PLL_AUTO_STOP_REQ BIT(4) 36 #define PLL_AUTO_START_REQ BIT(0) 37 #define PLL_FRANCE_EN BIT(4) 38 #define EXIT_DPF_BYPASS_0 BIT(16) 39 #define EXIT_DPF_BYPASS_1 BIT(17) 40 #define CLK0_DIVIDER 0X30 41 42 union clk_pll_req_no { 43 struct { 44 u32 fb_mult_int : 9; 45 u32 reserved : 3; 46 u32 pll_spine_div : 4; 47 u32 gb_mult_frac : 16; 48 } bitfields, bits; 49 u32 clk_pll_req_no_reg; 50 }; 51 52 static struct acp_resource rsrc = { 53 .offset = 0, 54 .no_of_ctrls = 2, 55 .irqp_used = 1, 56 .soc_mclk = true, 57 .irq_reg_offset = 0x1a00, 58 .i2s_pin_cfg_offset = 0x1440, 59 .i2s_mode = 0x0a, 60 .scratch_reg_offset = 0x12800, 61 .sram_pte_offset = 0x03802800, 62 }; 63 64 static struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_acp_machines[] = { 65 { 66 .id = "AMDI0052", 67 .drv_name = "acp63-acp", 68 }, 69 {}, 70 }; 71 72 static struct snd_soc_dai_driver acp63_dai[] = { 73 { 74 .name = "acp-i2s-sp", 75 .id = I2S_SP_INSTANCE, 76 .playback = { 77 .stream_name = "I2S SP Playback", 78 .rates = SNDRV_PCM_RATE_8000_96000, 79 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | 80 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, 81 .channels_min = 2, 82 .channels_max = 8, 83 .rate_min = 8000, 84 .rate_max = 96000, 85 }, 86 .capture = { 87 .stream_name = "I2S SP Capture", 88 .rates = SNDRV_PCM_RATE_8000_48000, 89 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | 90 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, 91 .channels_min = 2, 92 .channels_max = 2, 93 .rate_min = 8000, 94 .rate_max = 48000, 95 }, 96 .ops = &asoc_acp_cpu_dai_ops, 97 }, 98 { 99 .name = "acp-i2s-bt", 100 .id = I2S_BT_INSTANCE, 101 .playback = { 102 .stream_name = "I2S BT Playback", 103 .rates = SNDRV_PCM_RATE_8000_96000, 104 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | 105 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, 106 .channels_min = 2, 107 .channels_max = 8, 108 .rate_min = 8000, 109 .rate_max = 96000, 110 }, 111 .capture = { 112 .stream_name = "I2S BT Capture", 113 .rates = SNDRV_PCM_RATE_8000_48000, 114 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | 115 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, 116 .channels_min = 2, 117 .channels_max = 2, 118 .rate_min = 8000, 119 .rate_max = 48000, 120 }, 121 .ops = &asoc_acp_cpu_dai_ops, 122 }, 123 { 124 .name = "acp-i2s-hs", 125 .id = I2S_HS_INSTANCE, 126 .playback = { 127 .stream_name = "I2S HS Playback", 128 .rates = SNDRV_PCM_RATE_8000_96000, 129 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | 130 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, 131 .channels_min = 2, 132 .channels_max = 8, 133 .rate_min = 8000, 134 .rate_max = 96000, 135 }, 136 .capture = { 137 .stream_name = "I2S HS Capture", 138 .rates = SNDRV_PCM_RATE_8000_48000, 139 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | 140 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, 141 .channels_min = 2, 142 .channels_max = 8, 143 .rate_min = 8000, 144 .rate_max = 48000, 145 }, 146 .ops = &asoc_acp_cpu_dai_ops, 147 }, 148 { 149 .name = "acp-pdm-dmic", 150 .id = DMIC_INSTANCE, 151 .capture = { 152 .rates = SNDRV_PCM_RATE_8000_48000, 153 .formats = SNDRV_PCM_FMTBIT_S32_LE, 154 .channels_min = 2, 155 .channels_max = 2, 156 .rate_min = 8000, 157 .rate_max = 48000, 158 }, 159 .ops = &acp_dmic_dai_ops, 160 }, 161 }; 162 163 static int acp63_i2s_master_clock_generate(struct acp_dev_data *adata) 164 { 165 u32 data; 166 union clk_pll_req_no clk_pll; 167 struct pci_dev *smn_dev; 168 169 smn_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x14E8, NULL); 170 if (!smn_dev) 171 return -ENODEV; 172 173 /* Clk5 pll register values to get mclk as 196.6MHz*/ 174 clk_pll.bits.fb_mult_int = 0x31; 175 clk_pll.bits.pll_spine_div = 0; 176 clk_pll.bits.gb_mult_frac = 0x26E9; 177 178 data = smn_read(smn_dev, CLK_PLL_PWR_REQ_N0); 179 smn_write(smn_dev, CLK_PLL_PWR_REQ_N0, data | PLL_AUTO_STOP_REQ); 180 181 data = smn_read(smn_dev, CLK_SPLL_FIELD_2_N0); 182 if (data & PLL_FRANCE_EN) 183 smn_write(smn_dev, CLK_SPLL_FIELD_2_N0, data | PLL_FRANCE_EN); 184 185 smn_write(smn_dev, CLK_PLL_REQ_N0, clk_pll.clk_pll_req_no_reg); 186 187 data = smn_read(smn_dev, CLK_PLL_PWR_REQ_N0); 188 smn_write(smn_dev, CLK_PLL_PWR_REQ_N0, data | PLL_AUTO_START_REQ); 189 190 data = smn_read(smn_dev, CLK_DFSBYPASS_CONTR); 191 smn_write(smn_dev, CLK_DFSBYPASS_CONTR, data | EXIT_DPF_BYPASS_0); 192 smn_write(smn_dev, CLK_DFSBYPASS_CONTR, data | EXIT_DPF_BYPASS_1); 193 194 smn_write(smn_dev, CLK_DFS_CNTL_N0, CLK0_DIVIDER); 195 return 0; 196 } 197 198 static int acp63_audio_probe(struct platform_device *pdev) 199 { 200 struct device *dev = &pdev->dev; 201 struct acp_chip_info *chip; 202 struct acp_dev_data *adata; 203 struct resource *res; 204 int ret; 205 206 chip = dev_get_platdata(&pdev->dev); 207 if (!chip || !chip->base) { 208 dev_err(&pdev->dev, "ACP chip data is NULL\n"); 209 return -ENODEV; 210 } 211 212 if (chip->acp_rev != ACP63_DEV) { 213 dev_err(&pdev->dev, "Un-supported ACP Revision %d\n", chip->acp_rev); 214 return -ENODEV; 215 } 216 217 adata = devm_kzalloc(dev, sizeof(struct acp_dev_data), GFP_KERNEL); 218 if (!adata) 219 return -ENOMEM; 220 221 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "acp_mem"); 222 if (!res) { 223 dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n"); 224 return -ENODEV; 225 } 226 227 adata->acp_base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); 228 if (!adata->acp_base) 229 return -ENOMEM; 230 231 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "acp_dai_irq"); 232 if (!res) { 233 dev_err(&pdev->dev, "IORESOURCE_IRQ FAILED\n"); 234 return -ENODEV; 235 } 236 237 adata->i2s_irq = res->start; 238 adata->dev = dev; 239 adata->dai_driver = acp63_dai; 240 adata->num_dai = ARRAY_SIZE(acp63_dai); 241 adata->rsrc = &rsrc; 242 adata->platform = ACP63; 243 adata->flag = chip->flag; 244 adata->machines = snd_soc_acpi_amd_acp63_acp_machines; 245 acp_machine_select(adata); 246 dev_set_drvdata(dev, adata); 247 248 if (chip->flag != FLAG_AMD_LEGACY_ONLY_DMIC) { 249 ret = acp63_i2s_master_clock_generate(adata); 250 if (ret) 251 return ret; 252 } 253 acp_enable_interrupts(adata); 254 acp_platform_register(dev); 255 pm_runtime_set_autosuspend_delay(&pdev->dev, ACP_SUSPEND_DELAY_MS); 256 pm_runtime_use_autosuspend(&pdev->dev); 257 pm_runtime_mark_last_busy(&pdev->dev); 258 pm_runtime_set_active(&pdev->dev); 259 pm_runtime_enable(&pdev->dev); 260 return 0; 261 } 262 263 static void acp63_audio_remove(struct platform_device *pdev) 264 { 265 struct device *dev = &pdev->dev; 266 struct acp_dev_data *adata = dev_get_drvdata(dev); 267 268 acp_disable_interrupts(adata); 269 acp_platform_unregister(dev); 270 pm_runtime_disable(&pdev->dev); 271 } 272 273 static int __maybe_unused acp63_pcm_resume(struct device *dev) 274 { 275 struct acp_dev_data *adata = dev_get_drvdata(dev); 276 struct acp_stream *stream; 277 struct snd_pcm_substream *substream; 278 snd_pcm_uframes_t buf_in_frames; 279 u64 buf_size; 280 281 if (adata->flag != FLAG_AMD_LEGACY_ONLY_DMIC) 282 acp63_i2s_master_clock_generate(adata); 283 284 spin_lock(&adata->acp_lock); 285 list_for_each_entry(stream, &adata->stream_list, list) { 286 substream = stream->substream; 287 if (substream && substream->runtime) { 288 buf_in_frames = (substream->runtime->buffer_size); 289 buf_size = frames_to_bytes(substream->runtime, buf_in_frames); 290 config_pte_for_stream(adata, stream); 291 config_acp_dma(adata, stream, buf_size); 292 if (stream->dai_id) 293 restore_acp_i2s_params(substream, adata, stream); 294 else 295 restore_acp_pdm_params(substream, adata); 296 } 297 } 298 spin_unlock(&adata->acp_lock); 299 return 0; 300 } 301 302 static const struct dev_pm_ops acp63_dma_pm_ops = { 303 SET_SYSTEM_SLEEP_PM_OPS(NULL, acp63_pcm_resume) 304 }; 305 306 static struct platform_driver acp63_driver = { 307 .probe = acp63_audio_probe, 308 .remove_new = acp63_audio_remove, 309 .driver = { 310 .name = "acp_asoc_acp63", 311 .pm = &acp63_dma_pm_ops, 312 }, 313 }; 314 315 module_platform_driver(acp63_driver); 316 317 MODULE_DESCRIPTION("AMD ACP acp63 Driver"); 318 MODULE_IMPORT_NS(SND_SOC_ACP_COMMON); 319 MODULE_LICENSE("Dual BSD/GPL"); 320 MODULE_ALIAS("platform:" DRV_NAME); 321