1 // SPDX-License-Identifier: GPL-2.0-or-later 2 // 3 // This driver supports the DMIC in Allwinner's H6 SoCs. 4 // 5 // Copyright 2021 Ban Tao <fengzheng923@gmail.com> 6 7 #include <linux/clk.h> 8 #include <linux/device.h> 9 #include <linux/mod_devicetable.h> 10 #include <linux/module.h> 11 #include <linux/platform_device.h> 12 #include <linux/pm_runtime.h> 13 #include <linux/reset.h> 14 #include <sound/dmaengine_pcm.h> 15 #include <sound/pcm_params.h> 16 #include <sound/soc.h> 17 18 #define SUN50I_DMIC_EN_CTL (0x00) 19 #define SUN50I_DMIC_EN_CTL_GLOBE BIT(8) 20 #define SUN50I_DMIC_EN_CTL_CHAN(v) ((v) << 0) 21 #define SUN50I_DMIC_EN_CTL_CHAN_MASK GENMASK(7, 0) 22 #define SUN50I_DMIC_SR (0x04) 23 #define SUN50I_DMIC_SR_SAMPLE_RATE(v) ((v) << 0) 24 #define SUN50I_DMIC_SR_SAMPLE_RATE_MASK GENMASK(2, 0) 25 #define SUN50I_DMIC_CTL (0x08) 26 #define SUN50I_DMIC_CTL_OVERSAMPLE_RATE BIT(0) 27 #define SUN50I_DMIC_DATA (0x10) 28 #define SUN50I_DMIC_INTC (0x14) 29 #define SUN50I_DMIC_FIFO_DRQ_EN BIT(2) 30 #define SUN50I_DMIC_INT_STA (0x18) 31 #define SUN50I_DMIC_INT_STA_OVERRUN_IRQ_PENDING BIT(1) 32 #define SUN50I_DMIC_INT_STA_DATA_IRQ_PENDING BIT(0) 33 #define SUN50I_DMIC_RXFIFO_CTL (0x1c) 34 #define SUN50I_DMIC_RXFIFO_CTL_FLUSH BIT(31) 35 #define SUN50I_DMIC_RXFIFO_CTL_MODE_MASK BIT(9) 36 #define SUN50I_DMIC_RXFIFO_CTL_MODE_LSB (0 << 9) 37 #define SUN50I_DMIC_RXFIFO_CTL_MODE_MSB (1 << 9) 38 #define SUN50I_DMIC_RXFIFO_CTL_SAMPLE_MASK BIT(8) 39 #define SUN50I_DMIC_RXFIFO_CTL_SAMPLE_16 (0 << 8) 40 #define SUN50I_DMIC_RXFIFO_CTL_SAMPLE_24 (1 << 8) 41 #define SUN50I_DMIC_CH_NUM (0x24) 42 #define SUN50I_DMIC_CH_NUM_N(v) ((v) << 0) 43 #define SUN50I_DMIC_CH_NUM_N_MASK GENMASK(2, 0) 44 #define SUN50I_DMIC_CNT (0x2c) 45 #define SUN50I_DMIC_CNT_N (1 << 0) 46 #define SUN50I_DMIC_HPF_CTRL (0x38) 47 #define SUN50I_DMIC_VERSION (0x50) 48 49 struct sun50i_dmic_dev { 50 struct clk *dmic_clk; 51 struct clk *bus_clk; 52 struct reset_control *rst; 53 struct regmap *regmap; 54 struct snd_dmaengine_dai_dma_data dma_params_rx; 55 }; 56 57 struct dmic_rate { 58 unsigned int samplerate; 59 unsigned int rate_bit; 60 }; 61 62 static const struct dmic_rate dmic_rate_s[] = { 63 {48000, 0x0}, 64 {44100, 0x0}, 65 {32000, 0x1}, 66 {24000, 0x2}, 67 {22050, 0x2}, 68 {16000, 0x3}, 69 {12000, 0x4}, 70 {11025, 0x4}, 71 {8000, 0x5}, 72 }; 73 74 static int sun50i_dmic_startup(struct snd_pcm_substream *substream, 75 struct snd_soc_dai *cpu_dai) 76 { 77 struct snd_soc_pcm_runtime *rtd = substream->private_data; 78 struct sun50i_dmic_dev *host = snd_soc_dai_get_drvdata(snd_soc_rtd_to_cpu(rtd, 0)); 79 80 /* only support capture */ 81 if (substream->stream != SNDRV_PCM_STREAM_CAPTURE) 82 return -EINVAL; 83 84 regmap_update_bits(host->regmap, SUN50I_DMIC_RXFIFO_CTL, 85 SUN50I_DMIC_RXFIFO_CTL_FLUSH, 86 SUN50I_DMIC_RXFIFO_CTL_FLUSH); 87 regmap_write(host->regmap, SUN50I_DMIC_CNT, SUN50I_DMIC_CNT_N); 88 89 return 0; 90 } 91 92 static int sun50i_dmic_hw_params(struct snd_pcm_substream *substream, 93 struct snd_pcm_hw_params *params, 94 struct snd_soc_dai *cpu_dai) 95 { 96 int i = 0; 97 unsigned long rate = params_rate(params); 98 unsigned int mclk = 0; 99 unsigned int channels = params_channels(params); 100 unsigned int chan_en = (1 << channels) - 1; 101 struct sun50i_dmic_dev *host = snd_soc_dai_get_drvdata(cpu_dai); 102 103 /* DMIC num is N+1 */ 104 regmap_update_bits(host->regmap, SUN50I_DMIC_CH_NUM, 105 SUN50I_DMIC_CH_NUM_N_MASK, 106 SUN50I_DMIC_CH_NUM_N(channels - 1)); 107 regmap_write(host->regmap, SUN50I_DMIC_HPF_CTRL, chan_en); 108 regmap_update_bits(host->regmap, SUN50I_DMIC_EN_CTL, 109 SUN50I_DMIC_EN_CTL_CHAN_MASK, 110 SUN50I_DMIC_EN_CTL_CHAN(chan_en)); 111 112 switch (params_format(params)) { 113 case SNDRV_PCM_FORMAT_S16_LE: 114 regmap_update_bits(host->regmap, SUN50I_DMIC_RXFIFO_CTL, 115 SUN50I_DMIC_RXFIFO_CTL_SAMPLE_MASK, 116 SUN50I_DMIC_RXFIFO_CTL_SAMPLE_16); 117 break; 118 case SNDRV_PCM_FORMAT_S24_LE: 119 regmap_update_bits(host->regmap, SUN50I_DMIC_RXFIFO_CTL, 120 SUN50I_DMIC_RXFIFO_CTL_SAMPLE_MASK, 121 SUN50I_DMIC_RXFIFO_CTL_SAMPLE_24); 122 break; 123 default: 124 dev_err(cpu_dai->dev, "Invalid format!\n"); 125 return -EINVAL; 126 } 127 /* The hardware supports FIFO mode 1 for 24-bit samples */ 128 regmap_update_bits(host->regmap, SUN50I_DMIC_RXFIFO_CTL, 129 SUN50I_DMIC_RXFIFO_CTL_MODE_MASK, 130 SUN50I_DMIC_RXFIFO_CTL_MODE_MSB); 131 132 switch (rate) { 133 case 11025: 134 case 22050: 135 case 44100: 136 mclk = 22579200; 137 break; 138 case 8000: 139 case 12000: 140 case 16000: 141 case 24000: 142 case 32000: 143 case 48000: 144 mclk = 24576000; 145 break; 146 default: 147 dev_err(cpu_dai->dev, "Invalid rate!\n"); 148 return -EINVAL; 149 } 150 151 if (clk_set_rate(host->dmic_clk, mclk)) { 152 dev_err(cpu_dai->dev, "mclk : %u not support\n", mclk); 153 return -EINVAL; 154 } 155 156 for (i = 0; i < ARRAY_SIZE(dmic_rate_s); i++) { 157 if (dmic_rate_s[i].samplerate == rate) { 158 regmap_update_bits(host->regmap, SUN50I_DMIC_SR, 159 SUN50I_DMIC_SR_SAMPLE_RATE_MASK, 160 SUN50I_DMIC_SR_SAMPLE_RATE(dmic_rate_s[i].rate_bit)); 161 break; 162 } 163 } 164 165 switch (params_physical_width(params)) { 166 case 16: 167 host->dma_params_rx.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; 168 break; 169 case 32: 170 host->dma_params_rx.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 171 break; 172 default: 173 dev_err(cpu_dai->dev, "Unsupported physical sample width: %d\n", 174 params_physical_width(params)); 175 return -EINVAL; 176 } 177 178 /* oversamplerate adjust */ 179 if (params_rate(params) >= 24000) 180 regmap_update_bits(host->regmap, SUN50I_DMIC_CTL, 181 SUN50I_DMIC_CTL_OVERSAMPLE_RATE, 182 SUN50I_DMIC_CTL_OVERSAMPLE_RATE); 183 else 184 regmap_update_bits(host->regmap, SUN50I_DMIC_CTL, 185 SUN50I_DMIC_CTL_OVERSAMPLE_RATE, 0); 186 187 return 0; 188 } 189 190 static int sun50i_dmic_trigger(struct snd_pcm_substream *substream, int cmd, 191 struct snd_soc_dai *dai) 192 { 193 int ret = 0; 194 struct sun50i_dmic_dev *host = snd_soc_dai_get_drvdata(dai); 195 196 if (substream->stream != SNDRV_PCM_STREAM_CAPTURE) 197 return -EINVAL; 198 199 switch (cmd) { 200 case SNDRV_PCM_TRIGGER_START: 201 case SNDRV_PCM_TRIGGER_RESUME: 202 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 203 /* DRQ ENABLE */ 204 regmap_update_bits(host->regmap, SUN50I_DMIC_INTC, 205 SUN50I_DMIC_FIFO_DRQ_EN, 206 SUN50I_DMIC_FIFO_DRQ_EN); 207 /* Global enable */ 208 regmap_update_bits(host->regmap, SUN50I_DMIC_EN_CTL, 209 SUN50I_DMIC_EN_CTL_GLOBE, 210 SUN50I_DMIC_EN_CTL_GLOBE); 211 break; 212 case SNDRV_PCM_TRIGGER_STOP: 213 case SNDRV_PCM_TRIGGER_SUSPEND: 214 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 215 /* DRQ DISABLE */ 216 regmap_update_bits(host->regmap, SUN50I_DMIC_INTC, 217 SUN50I_DMIC_FIFO_DRQ_EN, 0); 218 /* Global disable */ 219 regmap_update_bits(host->regmap, SUN50I_DMIC_EN_CTL, 220 SUN50I_DMIC_EN_CTL_GLOBE, 0); 221 break; 222 default: 223 ret = -EINVAL; 224 break; 225 } 226 return ret; 227 } 228 229 static int sun50i_dmic_soc_dai_probe(struct snd_soc_dai *dai) 230 { 231 struct sun50i_dmic_dev *host = snd_soc_dai_get_drvdata(dai); 232 233 snd_soc_dai_init_dma_data(dai, NULL, &host->dma_params_rx); 234 235 return 0; 236 } 237 238 static const struct snd_soc_dai_ops sun50i_dmic_dai_ops = { 239 .probe = sun50i_dmic_soc_dai_probe, 240 .startup = sun50i_dmic_startup, 241 .trigger = sun50i_dmic_trigger, 242 .hw_params = sun50i_dmic_hw_params, 243 }; 244 245 static const struct regmap_config sun50i_dmic_regmap_config = { 246 .reg_bits = 32, 247 .reg_stride = 4, 248 .val_bits = 32, 249 .max_register = SUN50I_DMIC_VERSION, 250 .cache_type = REGCACHE_NONE, 251 }; 252 253 #define SUN50I_DMIC_RATES (SNDRV_PCM_RATE_8000_48000) 254 #define SUN50I_DMIC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE) 255 256 static struct snd_soc_dai_driver sun50i_dmic_dai = { 257 .capture = { 258 .channels_min = 1, 259 .channels_max = 8, 260 .rates = SUN50I_DMIC_RATES, 261 .formats = SUN50I_DMIC_FORMATS, 262 .sig_bits = 21, 263 }, 264 .ops = &sun50i_dmic_dai_ops, 265 .name = "dmic", 266 }; 267 268 static const struct of_device_id sun50i_dmic_of_match[] = { 269 { 270 .compatible = "allwinner,sun50i-h6-dmic", 271 }, 272 { /* sentinel */ } 273 }; 274 MODULE_DEVICE_TABLE(of, sun50i_dmic_of_match); 275 276 static const struct snd_soc_component_driver sun50i_dmic_component = { 277 .name = "sun50i-dmic", 278 }; 279 280 static int sun50i_dmic_runtime_suspend(struct device *dev) 281 { 282 struct sun50i_dmic_dev *host = dev_get_drvdata(dev); 283 284 clk_disable_unprepare(host->dmic_clk); 285 clk_disable_unprepare(host->bus_clk); 286 287 return 0; 288 } 289 290 static int sun50i_dmic_runtime_resume(struct device *dev) 291 { 292 struct sun50i_dmic_dev *host = dev_get_drvdata(dev); 293 int ret; 294 295 ret = clk_prepare_enable(host->dmic_clk); 296 if (ret) 297 return ret; 298 299 ret = clk_prepare_enable(host->bus_clk); 300 if (ret) { 301 clk_disable_unprepare(host->dmic_clk); 302 return ret; 303 } 304 305 return 0; 306 } 307 308 static int sun50i_dmic_probe(struct platform_device *pdev) 309 { 310 struct sun50i_dmic_dev *host; 311 struct resource *res; 312 int ret; 313 void __iomem *base; 314 315 host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL); 316 if (!host) 317 return -ENOMEM; 318 319 /* Get the addresses */ 320 base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); 321 if (IS_ERR(base)) 322 return dev_err_probe(&pdev->dev, PTR_ERR(base), 323 "get resource failed.\n"); 324 325 host->regmap = devm_regmap_init_mmio(&pdev->dev, base, 326 &sun50i_dmic_regmap_config); 327 328 /* Clocks */ 329 host->bus_clk = devm_clk_get(&pdev->dev, "bus"); 330 if (IS_ERR(host->bus_clk)) 331 return dev_err_probe(&pdev->dev, PTR_ERR(host->bus_clk), 332 "failed to get bus clock.\n"); 333 334 host->dmic_clk = devm_clk_get(&pdev->dev, "mod"); 335 if (IS_ERR(host->dmic_clk)) 336 return dev_err_probe(&pdev->dev, PTR_ERR(host->dmic_clk), 337 "failed to get dmic clock.\n"); 338 339 host->dma_params_rx.addr = res->start + SUN50I_DMIC_DATA; 340 host->dma_params_rx.maxburst = 8; 341 342 platform_set_drvdata(pdev, host); 343 344 host->rst = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL); 345 if (IS_ERR(host->rst)) 346 return dev_err_probe(&pdev->dev, PTR_ERR(host->rst), 347 "Failed to get reset.\n"); 348 reset_control_deassert(host->rst); 349 350 ret = devm_snd_soc_register_component(&pdev->dev, &sun50i_dmic_component, 351 &sun50i_dmic_dai, 1); 352 if (ret) 353 return dev_err_probe(&pdev->dev, ret, 354 "failed to register component.\n"); 355 356 pm_runtime_enable(&pdev->dev); 357 if (!pm_runtime_enabled(&pdev->dev)) { 358 ret = sun50i_dmic_runtime_resume(&pdev->dev); 359 if (ret) 360 goto err_disable_runtime_pm; 361 } 362 363 ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); 364 if (ret) 365 goto err_suspend; 366 367 return 0; 368 err_suspend: 369 if (!pm_runtime_status_suspended(&pdev->dev)) 370 sun50i_dmic_runtime_suspend(&pdev->dev); 371 err_disable_runtime_pm: 372 pm_runtime_disable(&pdev->dev); 373 return ret; 374 } 375 376 static void sun50i_dmic_remove(struct platform_device *pdev) 377 { 378 pm_runtime_disable(&pdev->dev); 379 if (!pm_runtime_status_suspended(&pdev->dev)) 380 sun50i_dmic_runtime_suspend(&pdev->dev); 381 } 382 383 static const struct dev_pm_ops sun50i_dmic_pm = { 384 SET_RUNTIME_PM_OPS(sun50i_dmic_runtime_suspend, 385 sun50i_dmic_runtime_resume, NULL) 386 }; 387 388 static struct platform_driver sun50i_dmic_driver = { 389 .driver = { 390 .name = "sun50i-dmic", 391 .of_match_table = sun50i_dmic_of_match, 392 .pm = &sun50i_dmic_pm, 393 }, 394 .probe = sun50i_dmic_probe, 395 .remove_new = sun50i_dmic_remove, 396 }; 397 398 module_platform_driver(sun50i_dmic_driver); 399 400 MODULE_DESCRIPTION("Allwinner sun50i DMIC SoC Interface"); 401 MODULE_AUTHOR("Ban Tao <fengzheng923@gmail.com>"); 402 MODULE_LICENSE("GPL"); 403 MODULE_ALIAS("platform:sun50i-dmic"); 404