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