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) 2021 Advanced Micro Devices, Inc. 7 // 8 // Authors: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com> 9 // 10 11 /* 12 * Hardware interface for Renoir ACP block 13 */ 14 15 #include <linux/platform_device.h> 16 #include <linux/module.h> 17 #include <linux/err.h> 18 #include <linux/io.h> 19 #include <sound/pcm_params.h> 20 #include <sound/soc.h> 21 #include <sound/soc-dai.h> 22 #include <linux/dma-mapping.h> 23 24 #include "amd.h" 25 26 #define DRV_NAME "acp_asoc_renoir" 27 28 #define ACP_SOFT_RST_DONE_MASK 0x00010001 29 30 #define ACP_PWR_ON_MASK 0x01 31 #define ACP_PWR_OFF_MASK 0x00 32 #define ACP_PGFSM_STAT_MASK 0x03 33 #define ACP_POWERED_ON 0x00 34 #define ACP_PWR_ON_IN_PROGRESS 0x01 35 #define ACP_POWERED_OFF 0x02 36 #define DELAY_US 5 37 #define ACP_TIMEOUT 500 38 39 #define ACP_ERROR_MASK 0x20000000 40 #define ACP_EXT_INTR_STAT_CLEAR_MASK 0xFFFFFFFF 41 42 static struct acp_resource rsrc = { 43 .offset = 20, 44 .no_of_ctrls = 1, 45 .irqp_used = 0, 46 .irq_reg_offset = 0x1800, 47 .i2s_pin_cfg_offset = 0x1400, 48 .i2s_mode = 0x04, 49 .scratch_reg_offset = 0x12800, 50 .sram_pte_offset = 0x02052800, 51 }; 52 53 static struct snd_soc_acpi_codecs amp_rt1019 = { 54 .num_codecs = 1, 55 .codecs = {"10EC1019"} 56 }; 57 58 static struct snd_soc_acpi_codecs amp_max = { 59 .num_codecs = 1, 60 .codecs = {"MX98360A"} 61 }; 62 63 static struct snd_soc_acpi_mach snd_soc_acpi_amd_acp_machines[] = { 64 { 65 .id = "10EC5682", 66 .drv_name = "acp3xalc56821019", 67 .machine_quirk = snd_soc_acpi_codec_list, 68 .quirk_data = &_rt1019, 69 }, 70 { 71 .id = "RTL5682", 72 .drv_name = "acp3xalc5682sm98360", 73 .machine_quirk = snd_soc_acpi_codec_list, 74 .quirk_data = &_max, 75 }, 76 { 77 .id = "RTL5682", 78 .drv_name = "acp3xalc5682s1019", 79 .machine_quirk = snd_soc_acpi_codec_list, 80 .quirk_data = &_rt1019, 81 }, 82 { 83 .id = "AMDI1019", 84 .drv_name = "renoir-acp", 85 }, 86 {}, 87 }; 88 89 static struct snd_soc_dai_driver acp_renoir_dai[] = { 90 { 91 .name = "acp-i2s-sp", 92 .id = I2S_SP_INSTANCE, 93 .playback = { 94 .stream_name = "I2S SP Playback", 95 .rates = SNDRV_PCM_RATE_8000_96000, 96 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | 97 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, 98 .channels_min = 2, 99 .channels_max = 8, 100 .rate_min = 8000, 101 .rate_max = 96000, 102 }, 103 .capture = { 104 .stream_name = "I2S SP Capture", 105 .rates = SNDRV_PCM_RATE_8000_48000, 106 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | 107 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, 108 .channels_min = 2, 109 .channels_max = 2, 110 .rate_min = 8000, 111 .rate_max = 48000, 112 }, 113 .ops = &asoc_acp_cpu_dai_ops, 114 .probe = &asoc_acp_i2s_probe, 115 }, 116 { 117 .name = "acp-i2s-bt", 118 .id = I2S_BT_INSTANCE, 119 .playback = { 120 .stream_name = "I2S BT Playback", 121 .rates = SNDRV_PCM_RATE_8000_96000, 122 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | 123 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, 124 .channels_min = 2, 125 .channels_max = 8, 126 .rate_min = 8000, 127 .rate_max = 96000, 128 }, 129 .capture = { 130 .stream_name = "I2S BT Capture", 131 .rates = SNDRV_PCM_RATE_8000_48000, 132 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | 133 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, 134 .channels_min = 2, 135 .channels_max = 2, 136 .rate_min = 8000, 137 .rate_max = 48000, 138 }, 139 .ops = &asoc_acp_cpu_dai_ops, 140 .probe = &asoc_acp_i2s_probe, 141 }, 142 { 143 .name = "acp-pdm-dmic", 144 .id = DMIC_INSTANCE, 145 .capture = { 146 .rates = SNDRV_PCM_RATE_8000_48000, 147 .formats = SNDRV_PCM_FMTBIT_S32_LE, 148 .channels_min = 2, 149 .channels_max = 2, 150 .rate_min = 8000, 151 .rate_max = 48000, 152 }, 153 .ops = &acp_dmic_dai_ops, 154 }, 155 }; 156 157 static int acp3x_power_on(void __iomem *base) 158 { 159 u32 val; 160 161 val = readl(base + ACP_PGFSM_STATUS); 162 163 if (val == ACP_POWERED_ON) 164 return 0; 165 166 if ((val & ACP_PGFSM_STAT_MASK) != ACP_PWR_ON_IN_PROGRESS) 167 writel(ACP_PWR_ON_MASK, base + ACP_PGFSM_CONTROL); 168 169 return readl_poll_timeout(base + ACP_PGFSM_STATUS, val, !val, DELAY_US, ACP_TIMEOUT); 170 } 171 172 static int acp3x_reset(void __iomem *base) 173 { 174 u32 val; 175 int ret; 176 177 writel(1, base + ACP_SOFT_RESET); 178 179 ret = readl_poll_timeout(base + ACP_SOFT_RESET, val, val & ACP_SOFT_RST_DONE_MASK, 180 DELAY_US, ACP_TIMEOUT); 181 if (ret) 182 return ret; 183 184 writel(0, base + ACP_SOFT_RESET); 185 186 return readl_poll_timeout(base + ACP_SOFT_RESET, val, !val, DELAY_US, ACP_TIMEOUT); 187 } 188 189 static void acp3x_enable_interrupts(struct acp_dev_data *adata) 190 { 191 struct acp_resource *rsrc = adata->rsrc; 192 u32 ext_intr_ctrl; 193 194 writel(0x01, ACP_EXTERNAL_INTR_ENB(adata)); 195 ext_intr_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used)); 196 ext_intr_ctrl |= ACP_ERROR_MASK; 197 writel(ext_intr_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used)); 198 } 199 200 static void acp3x_disable_interrupts(struct acp_dev_data *adata) 201 { 202 struct acp_resource *rsrc = adata->rsrc; 203 204 writel(ACP_EXT_INTR_STAT_CLEAR_MASK, 205 ACP_EXTERNAL_INTR_STAT(adata, rsrc->irqp_used)); 206 writel(0x00, ACP_EXTERNAL_INTR_ENB(adata)); 207 } 208 209 static int rn_acp_init(void __iomem *base) 210 { 211 int ret; 212 213 /* power on */ 214 ret = acp3x_power_on(base); 215 if (ret) 216 return ret; 217 218 writel(0x01, base + ACP_CONTROL); 219 220 /* Reset */ 221 ret = acp3x_reset(base); 222 if (ret) 223 return ret; 224 225 return 0; 226 } 227 228 static int rn_acp_deinit(void __iomem *base) 229 { 230 int ret = 0; 231 232 /* Reset */ 233 ret = acp3x_reset(base); 234 if (ret) 235 return ret; 236 237 writel(0x00, base + ACP_CONTROL); 238 return 0; 239 } 240 static int renoir_audio_probe(struct platform_device *pdev) 241 { 242 struct device *dev = &pdev->dev; 243 struct acp_chip_info *chip; 244 struct acp_dev_data *adata; 245 struct resource *res; 246 int ret; 247 248 chip = dev_get_platdata(&pdev->dev); 249 if (!chip || !chip->base) { 250 dev_err(&pdev->dev, "ACP chip data is NULL\n"); 251 return -ENODEV; 252 } 253 254 if (chip->acp_rev != ACP3X_DEV) { 255 dev_err(&pdev->dev, "Un-supported ACP Revision %d\n", chip->acp_rev); 256 return -ENODEV; 257 } 258 259 ret = rn_acp_init(chip->base); 260 if (ret) { 261 dev_err(&pdev->dev, "ACP Init failed\n"); 262 return -EINVAL; 263 } 264 265 adata = devm_kzalloc(dev, sizeof(struct acp_dev_data), GFP_KERNEL); 266 if (!adata) 267 return -ENOMEM; 268 269 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "acp_mem"); 270 if (!res) { 271 dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n"); 272 return -ENODEV; 273 } 274 275 adata->acp_base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); 276 if (!adata->acp_base) 277 return -ENOMEM; 278 279 ret = platform_get_irq_byname(pdev, "acp_dai_irq"); 280 if (ret < 0) 281 return ret; 282 adata->i2s_irq = ret; 283 284 adata->dev = dev; 285 adata->dai_driver = acp_renoir_dai; 286 adata->num_dai = ARRAY_SIZE(acp_renoir_dai); 287 adata->rsrc = &rsrc; 288 289 adata->machines = snd_soc_acpi_amd_acp_machines; 290 acp_machine_select(adata); 291 292 dev_set_drvdata(dev, adata); 293 acp3x_enable_interrupts(adata); 294 acp_platform_register(dev); 295 296 return 0; 297 } 298 299 static void renoir_audio_remove(struct platform_device *pdev) 300 { 301 struct device *dev = &pdev->dev; 302 struct acp_dev_data *adata = dev_get_drvdata(dev); 303 struct acp_chip_info *chip; 304 int ret; 305 306 chip = dev_get_platdata(&pdev->dev); 307 308 acp3x_disable_interrupts(adata); 309 310 ret = rn_acp_deinit(chip->base); 311 if (ret) 312 dev_err(&pdev->dev, "ACP de-init Failed (%pe)\n", ERR_PTR(ret)); 313 314 acp_platform_unregister(dev); 315 } 316 317 static struct platform_driver renoir_driver = { 318 .probe = renoir_audio_probe, 319 .remove_new = renoir_audio_remove, 320 .driver = { 321 .name = "acp_asoc_renoir", 322 }, 323 }; 324 325 module_platform_driver(renoir_driver); 326 327 MODULE_DESCRIPTION("AMD ACP Renoir Driver"); 328 MODULE_IMPORT_NS(SND_SOC_ACP_COMMON); 329 MODULE_LICENSE("Dual BSD/GPL"); 330 MODULE_ALIAS("platform:" DRV_NAME); 331