linux/sound/soc/sunxi/sun4i-codec.c
<<
>>
Prefs
   1/*
   2 * Copyright 2014 Emilio López <emilio@elopez.com.ar>
   3 * Copyright 2014 Jon Smirl <jonsmirl@gmail.com>
   4 * Copyright 2015 Maxime Ripard <maxime.ripard@free-electrons.com>
   5 * Copyright 2015 Adam Sampson <ats@offog.org>
   6 *
   7 * Based on the Allwinner SDK driver, released under the GPL.
   8 *
   9 * This program is free software; you can redistribute it and/or modify
  10 * it under the terms of the GNU General Public License as published by
  11 * the Free Software Foundation; either version 2 of the License, or
  12 * (at your option) any later version.
  13 *
  14 * This program is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17 * GNU General Public License for more details.
  18 */
  19
  20#include <linux/init.h>
  21#include <linux/kernel.h>
  22#include <linux/module.h>
  23#include <linux/platform_device.h>
  24#include <linux/delay.h>
  25#include <linux/slab.h>
  26#include <linux/of.h>
  27#include <linux/of_platform.h>
  28#include <linux/of_address.h>
  29#include <linux/clk.h>
  30#include <linux/regmap.h>
  31#include <linux/gpio/consumer.h>
  32
  33#include <sound/core.h>
  34#include <sound/pcm.h>
  35#include <sound/pcm_params.h>
  36#include <sound/soc.h>
  37#include <sound/tlv.h>
  38#include <sound/initval.h>
  39#include <sound/dmaengine_pcm.h>
  40
  41/* Codec DAC register offsets and bit fields */
  42#define SUN4I_CODEC_DAC_DPC                     (0x00)
  43#define SUN4I_CODEC_DAC_DPC_EN_DA                       (31)
  44#define SUN4I_CODEC_DAC_DPC_DVOL                        (12)
  45#define SUN4I_CODEC_DAC_FIFOC                   (0x04)
  46#define SUN4I_CODEC_DAC_FIFOC_DAC_FS                    (29)
  47#define SUN4I_CODEC_DAC_FIFOC_FIR_VERSION               (28)
  48#define SUN4I_CODEC_DAC_FIFOC_SEND_LASAT                (26)
  49#define SUN4I_CODEC_DAC_FIFOC_TX_FIFO_MODE              (24)
  50#define SUN4I_CODEC_DAC_FIFOC_DRQ_CLR_CNT               (21)
  51#define SUN4I_CODEC_DAC_FIFOC_TX_TRIG_LEVEL             (8)
  52#define SUN4I_CODEC_DAC_FIFOC_MONO_EN                   (6)
  53#define SUN4I_CODEC_DAC_FIFOC_TX_SAMPLE_BITS            (5)
  54#define SUN4I_CODEC_DAC_FIFOC_DAC_DRQ_EN                (4)
  55#define SUN4I_CODEC_DAC_FIFOC_FIFO_FLUSH                (0)
  56#define SUN4I_CODEC_DAC_FIFOS                   (0x08)
  57#define SUN4I_CODEC_DAC_TXDATA                  (0x0c)
  58#define SUN4I_CODEC_DAC_ACTL                    (0x10)
  59#define SUN4I_CODEC_DAC_ACTL_DACAENR                    (31)
  60#define SUN4I_CODEC_DAC_ACTL_DACAENL                    (30)
  61#define SUN4I_CODEC_DAC_ACTL_MIXEN                      (29)
  62#define SUN4I_CODEC_DAC_ACTL_LDACLMIXS                  (15)
  63#define SUN4I_CODEC_DAC_ACTL_RDACRMIXS                  (14)
  64#define SUN4I_CODEC_DAC_ACTL_LDACRMIXS                  (13)
  65#define SUN4I_CODEC_DAC_ACTL_DACPAS                     (8)
  66#define SUN4I_CODEC_DAC_ACTL_MIXPAS                     (7)
  67#define SUN4I_CODEC_DAC_ACTL_PA_MUTE                    (6)
  68#define SUN4I_CODEC_DAC_ACTL_PA_VOL                     (0)
  69#define SUN4I_CODEC_DAC_TUNE                    (0x14)
  70#define SUN4I_CODEC_DAC_DEBUG                   (0x18)
  71
  72/* Codec ADC register offsets and bit fields */
  73#define SUN4I_CODEC_ADC_FIFOC                   (0x1c)
  74#define SUN4I_CODEC_ADC_FIFOC_ADC_FS                    (29)
  75#define SUN4I_CODEC_ADC_FIFOC_EN_AD                     (28)
  76#define SUN4I_CODEC_ADC_FIFOC_RX_FIFO_MODE              (24)
  77#define SUN4I_CODEC_ADC_FIFOC_RX_TRIG_LEVEL             (8)
  78#define SUN4I_CODEC_ADC_FIFOC_MONO_EN                   (7)
  79#define SUN4I_CODEC_ADC_FIFOC_RX_SAMPLE_BITS            (6)
  80#define SUN4I_CODEC_ADC_FIFOC_ADC_DRQ_EN                (4)
  81#define SUN4I_CODEC_ADC_FIFOC_FIFO_FLUSH                (0)
  82#define SUN4I_CODEC_ADC_FIFOS                   (0x20)
  83#define SUN4I_CODEC_ADC_RXDATA                  (0x24)
  84#define SUN4I_CODEC_ADC_ACTL                    (0x28)
  85#define SUN4I_CODEC_ADC_ACTL_ADC_R_EN                   (31)
  86#define SUN4I_CODEC_ADC_ACTL_ADC_L_EN                   (30)
  87#define SUN4I_CODEC_ADC_ACTL_PREG1EN                    (29)
  88#define SUN4I_CODEC_ADC_ACTL_PREG2EN                    (28)
  89#define SUN4I_CODEC_ADC_ACTL_VMICEN                     (27)
  90#define SUN4I_CODEC_ADC_ACTL_VADCG                      (20)
  91#define SUN4I_CODEC_ADC_ACTL_ADCIS                      (17)
  92#define SUN4I_CODEC_ADC_ACTL_PA_EN                      (4)
  93#define SUN4I_CODEC_ADC_ACTL_DDE                        (3)
  94#define SUN4I_CODEC_ADC_DEBUG                   (0x2c)
  95
  96/* Other various ADC registers */
  97#define SUN4I_CODEC_DAC_TXCNT                   (0x30)
  98#define SUN4I_CODEC_ADC_RXCNT                   (0x34)
  99#define SUN4I_CODEC_AC_SYS_VERI                 (0x38)
 100#define SUN4I_CODEC_AC_MIC_PHONE_CAL            (0x3c)
 101
 102struct sun4i_codec {
 103        struct device   *dev;
 104        struct regmap   *regmap;
 105        struct clk      *clk_apb;
 106        struct clk      *clk_module;
 107        struct gpio_desc *gpio_pa;
 108
 109        struct snd_dmaengine_dai_dma_data       capture_dma_data;
 110        struct snd_dmaengine_dai_dma_data       playback_dma_data;
 111};
 112
 113static void sun4i_codec_start_playback(struct sun4i_codec *scodec)
 114{
 115        /* Flush TX FIFO */
 116        regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
 117                           BIT(SUN4I_CODEC_DAC_FIFOC_FIFO_FLUSH),
 118                           BIT(SUN4I_CODEC_DAC_FIFOC_FIFO_FLUSH));
 119
 120        /* Enable DAC DRQ */
 121        regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
 122                           BIT(SUN4I_CODEC_DAC_FIFOC_DAC_DRQ_EN),
 123                           BIT(SUN4I_CODEC_DAC_FIFOC_DAC_DRQ_EN));
 124}
 125
 126static void sun4i_codec_stop_playback(struct sun4i_codec *scodec)
 127{
 128        /* Disable DAC DRQ */
 129        regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
 130                           BIT(SUN4I_CODEC_DAC_FIFOC_DAC_DRQ_EN),
 131                           0);
 132}
 133
 134static void sun4i_codec_start_capture(struct sun4i_codec *scodec)
 135{
 136        /* Enable ADC DRQ */
 137        regmap_update_bits(scodec->regmap, SUN4I_CODEC_ADC_FIFOC,
 138                           BIT(SUN4I_CODEC_ADC_FIFOC_ADC_DRQ_EN),
 139                           BIT(SUN4I_CODEC_ADC_FIFOC_ADC_DRQ_EN));
 140}
 141
 142static void sun4i_codec_stop_capture(struct sun4i_codec *scodec)
 143{
 144        /* Disable ADC DRQ */
 145        regmap_update_bits(scodec->regmap, SUN4I_CODEC_ADC_FIFOC,
 146                           BIT(SUN4I_CODEC_ADC_FIFOC_ADC_DRQ_EN), 0);
 147}
 148
 149static int sun4i_codec_trigger(struct snd_pcm_substream *substream, int cmd,
 150                               struct snd_soc_dai *dai)
 151{
 152        struct snd_soc_pcm_runtime *rtd = substream->private_data;
 153        struct sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card);
 154
 155        switch (cmd) {
 156        case SNDRV_PCM_TRIGGER_START:
 157        case SNDRV_PCM_TRIGGER_RESUME:
 158        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 159                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 160                        sun4i_codec_start_playback(scodec);
 161                else
 162                        sun4i_codec_start_capture(scodec);
 163                break;
 164
 165        case SNDRV_PCM_TRIGGER_STOP:
 166        case SNDRV_PCM_TRIGGER_SUSPEND:
 167        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 168                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 169                        sun4i_codec_stop_playback(scodec);
 170                else
 171                        sun4i_codec_stop_capture(scodec);
 172                break;
 173
 174        default:
 175                return -EINVAL;
 176        }
 177
 178        return 0;
 179}
 180
 181static int sun4i_codec_prepare_capture(struct snd_pcm_substream *substream,
 182                                       struct snd_soc_dai *dai)
 183{
 184        struct snd_soc_pcm_runtime *rtd = substream->private_data;
 185        struct sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card);
 186
 187
 188        /* Flush RX FIFO */
 189        regmap_update_bits(scodec->regmap, SUN4I_CODEC_ADC_FIFOC,
 190                           BIT(SUN4I_CODEC_ADC_FIFOC_FIFO_FLUSH),
 191                           BIT(SUN4I_CODEC_ADC_FIFOC_FIFO_FLUSH));
 192
 193
 194        /* Set RX FIFO trigger level */
 195        regmap_update_bits(scodec->regmap, SUN4I_CODEC_ADC_FIFOC,
 196                           0xf << SUN4I_CODEC_ADC_FIFOC_RX_TRIG_LEVEL,
 197                           0x7 << SUN4I_CODEC_ADC_FIFOC_RX_TRIG_LEVEL);
 198
 199        /*
 200         * FIXME: Undocumented in the datasheet, but
 201         *        Allwinner's code mentions that it is related
 202         *        related to microphone gain
 203         */
 204        regmap_update_bits(scodec->regmap, SUN4I_CODEC_ADC_ACTL,
 205                           0x3 << 25,
 206                           0x1 << 25);
 207
 208        if (of_device_is_compatible(scodec->dev->of_node,
 209                                    "allwinner,sun7i-a20-codec"))
 210                /* FIXME: Undocumented bits */
 211                regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_TUNE,
 212                                   0x3 << 8,
 213                                   0x1 << 8);
 214
 215        /* Fill most significant bits with valid data MSB */
 216        regmap_update_bits(scodec->regmap, SUN4I_CODEC_ADC_FIFOC,
 217                           BIT(SUN4I_CODEC_ADC_FIFOC_RX_FIFO_MODE),
 218                           BIT(SUN4I_CODEC_ADC_FIFOC_RX_FIFO_MODE));
 219
 220        return 0;
 221}
 222
 223static int sun4i_codec_prepare_playback(struct snd_pcm_substream *substream,
 224                                        struct snd_soc_dai *dai)
 225{
 226        struct snd_soc_pcm_runtime *rtd = substream->private_data;
 227        struct sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card);
 228        u32 val;
 229
 230        /* Flush the TX FIFO */
 231        regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
 232                           BIT(SUN4I_CODEC_DAC_FIFOC_FIFO_FLUSH),
 233                           BIT(SUN4I_CODEC_DAC_FIFOC_FIFO_FLUSH));
 234
 235        /* Set TX FIFO Empty Trigger Level */
 236        regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
 237                           0x3f << SUN4I_CODEC_DAC_FIFOC_TX_TRIG_LEVEL,
 238                           0xf << SUN4I_CODEC_DAC_FIFOC_TX_TRIG_LEVEL);
 239
 240        if (substream->runtime->rate > 32000)
 241                /* Use 64 bits FIR filter */
 242                val = 0;
 243        else
 244                /* Use 32 bits FIR filter */
 245                val = BIT(SUN4I_CODEC_DAC_FIFOC_FIR_VERSION);
 246
 247        regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
 248                           BIT(SUN4I_CODEC_DAC_FIFOC_FIR_VERSION),
 249                           val);
 250
 251        /* Send zeros when we have an underrun */
 252        regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
 253                           BIT(SUN4I_CODEC_DAC_FIFOC_SEND_LASAT),
 254                           0);
 255
 256        return 0;
 257};
 258
 259static int sun4i_codec_prepare(struct snd_pcm_substream *substream,
 260                               struct snd_soc_dai *dai)
 261{
 262        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 263                return sun4i_codec_prepare_playback(substream, dai);
 264
 265        return sun4i_codec_prepare_capture(substream, dai);
 266}
 267
 268static unsigned long sun4i_codec_get_mod_freq(struct snd_pcm_hw_params *params)
 269{
 270        unsigned int rate = params_rate(params);
 271
 272        switch (rate) {
 273        case 176400:
 274        case 88200:
 275        case 44100:
 276        case 33075:
 277        case 22050:
 278        case 14700:
 279        case 11025:
 280        case 7350:
 281                return 22579200;
 282
 283        case 192000:
 284        case 96000:
 285        case 48000:
 286        case 32000:
 287        case 24000:
 288        case 16000:
 289        case 12000:
 290        case 8000:
 291                return 24576000;
 292
 293        default:
 294                return 0;
 295        }
 296}
 297
 298static int sun4i_codec_get_hw_rate(struct snd_pcm_hw_params *params)
 299{
 300        unsigned int rate = params_rate(params);
 301
 302        switch (rate) {
 303        case 192000:
 304        case 176400:
 305                return 6;
 306
 307        case 96000:
 308        case 88200:
 309                return 7;
 310
 311        case 48000:
 312        case 44100:
 313                return 0;
 314
 315        case 32000:
 316        case 33075:
 317                return 1;
 318
 319        case 24000:
 320        case 22050:
 321                return 2;
 322
 323        case 16000:
 324        case 14700:
 325                return 3;
 326
 327        case 12000:
 328        case 11025:
 329                return 4;
 330
 331        case 8000:
 332        case 7350:
 333                return 5;
 334
 335        default:
 336                return -EINVAL;
 337        }
 338}
 339
 340static int sun4i_codec_hw_params_capture(struct sun4i_codec *scodec,
 341                                         struct snd_pcm_hw_params *params,
 342                                         unsigned int hwrate)
 343{
 344        /* Set ADC sample rate */
 345        regmap_update_bits(scodec->regmap, SUN4I_CODEC_ADC_FIFOC,
 346                           7 << SUN4I_CODEC_ADC_FIFOC_ADC_FS,
 347                           hwrate << SUN4I_CODEC_ADC_FIFOC_ADC_FS);
 348
 349        /* Set the number of channels we want to use */
 350        if (params_channels(params) == 1)
 351                regmap_update_bits(scodec->regmap, SUN4I_CODEC_ADC_FIFOC,
 352                                   BIT(SUN4I_CODEC_ADC_FIFOC_MONO_EN),
 353                                   BIT(SUN4I_CODEC_ADC_FIFOC_MONO_EN));
 354        else
 355                regmap_update_bits(scodec->regmap, SUN4I_CODEC_ADC_FIFOC,
 356                                   BIT(SUN4I_CODEC_ADC_FIFOC_MONO_EN), 0);
 357
 358        return 0;
 359}
 360
 361static int sun4i_codec_hw_params_playback(struct sun4i_codec *scodec,
 362                                          struct snd_pcm_hw_params *params,
 363                                          unsigned int hwrate)
 364{
 365        u32 val;
 366
 367        /* Set DAC sample rate */
 368        regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
 369                           7 << SUN4I_CODEC_DAC_FIFOC_DAC_FS,
 370                           hwrate << SUN4I_CODEC_DAC_FIFOC_DAC_FS);
 371
 372        /* Set the number of channels we want to use */
 373        if (params_channels(params) == 1)
 374                val = BIT(SUN4I_CODEC_DAC_FIFOC_MONO_EN);
 375        else
 376                val = 0;
 377
 378        regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
 379                           BIT(SUN4I_CODEC_DAC_FIFOC_MONO_EN),
 380                           val);
 381
 382        /* Set the number of sample bits to either 16 or 24 bits */
 383        if (hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS)->min == 32) {
 384                regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
 385                                   BIT(SUN4I_CODEC_DAC_FIFOC_TX_SAMPLE_BITS),
 386                                   BIT(SUN4I_CODEC_DAC_FIFOC_TX_SAMPLE_BITS));
 387
 388                /* Set TX FIFO mode to padding the LSBs with 0 */
 389                regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
 390                                   BIT(SUN4I_CODEC_DAC_FIFOC_TX_FIFO_MODE),
 391                                   0);
 392
 393                scodec->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
 394        } else {
 395                regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
 396                                   BIT(SUN4I_CODEC_DAC_FIFOC_TX_SAMPLE_BITS),
 397                                   0);
 398
 399                /* Set TX FIFO mode to repeat the MSB */
 400                regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
 401                                   BIT(SUN4I_CODEC_DAC_FIFOC_TX_FIFO_MODE),
 402                                   BIT(SUN4I_CODEC_DAC_FIFOC_TX_FIFO_MODE));
 403
 404                scodec->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
 405        }
 406
 407        return 0;
 408}
 409
 410static int sun4i_codec_hw_params(struct snd_pcm_substream *substream,
 411                                 struct snd_pcm_hw_params *params,
 412                                 struct snd_soc_dai *dai)
 413{
 414        struct snd_soc_pcm_runtime *rtd = substream->private_data;
 415        struct sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card);
 416        unsigned long clk_freq;
 417        int ret, hwrate;
 418
 419        clk_freq = sun4i_codec_get_mod_freq(params);
 420        if (!clk_freq)
 421                return -EINVAL;
 422
 423        ret = clk_set_rate(scodec->clk_module, clk_freq);
 424        if (ret)
 425                return ret;
 426
 427        hwrate = sun4i_codec_get_hw_rate(params);
 428        if (hwrate < 0)
 429                return hwrate;
 430
 431        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 432                return sun4i_codec_hw_params_playback(scodec, params,
 433                                                      hwrate);
 434
 435        return sun4i_codec_hw_params_capture(scodec, params,
 436                                             hwrate);
 437}
 438
 439static int sun4i_codec_startup(struct snd_pcm_substream *substream,
 440                               struct snd_soc_dai *dai)
 441{
 442        struct snd_soc_pcm_runtime *rtd = substream->private_data;
 443        struct sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card);
 444
 445        /*
 446         * Stop issuing DRQ when we have room for less than 16 samples
 447         * in our TX FIFO
 448         */
 449        regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
 450                           3 << SUN4I_CODEC_DAC_FIFOC_DRQ_CLR_CNT,
 451                           3 << SUN4I_CODEC_DAC_FIFOC_DRQ_CLR_CNT);
 452
 453        return clk_prepare_enable(scodec->clk_module);
 454}
 455
 456static void sun4i_codec_shutdown(struct snd_pcm_substream *substream,
 457                                 struct snd_soc_dai *dai)
 458{
 459        struct snd_soc_pcm_runtime *rtd = substream->private_data;
 460        struct sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card);
 461
 462        clk_disable_unprepare(scodec->clk_module);
 463}
 464
 465static const struct snd_soc_dai_ops sun4i_codec_dai_ops = {
 466        .startup        = sun4i_codec_startup,
 467        .shutdown       = sun4i_codec_shutdown,
 468        .trigger        = sun4i_codec_trigger,
 469        .hw_params      = sun4i_codec_hw_params,
 470        .prepare        = sun4i_codec_prepare,
 471};
 472
 473static struct snd_soc_dai_driver sun4i_codec_dai = {
 474        .name   = "Codec",
 475        .ops    = &sun4i_codec_dai_ops,
 476        .playback = {
 477                .stream_name    = "Codec Playback",
 478                .channels_min   = 1,
 479                .channels_max   = 2,
 480                .rate_min       = 8000,
 481                .rate_max       = 192000,
 482                .rates          = SNDRV_PCM_RATE_8000_48000 |
 483                                  SNDRV_PCM_RATE_96000 |
 484                                  SNDRV_PCM_RATE_192000,
 485                .formats        = SNDRV_PCM_FMTBIT_S16_LE |
 486                                  SNDRV_PCM_FMTBIT_S32_LE,
 487                .sig_bits       = 24,
 488        },
 489        .capture = {
 490                .stream_name    = "Codec Capture",
 491                .channels_min   = 1,
 492                .channels_max   = 2,
 493                .rate_min       = 8000,
 494                .rate_max       = 192000,
 495                .rates          = SNDRV_PCM_RATE_8000_48000 |
 496                                  SNDRV_PCM_RATE_96000 |
 497                                  SNDRV_PCM_RATE_192000 |
 498                                  SNDRV_PCM_RATE_KNOT,
 499                .formats        = SNDRV_PCM_FMTBIT_S16_LE |
 500                                  SNDRV_PCM_FMTBIT_S32_LE,
 501                .sig_bits       = 24,
 502        },
 503};
 504
 505/*** Codec ***/
 506static const struct snd_kcontrol_new sun4i_codec_pa_mute =
 507        SOC_DAPM_SINGLE("Switch", SUN4I_CODEC_DAC_ACTL,
 508                        SUN4I_CODEC_DAC_ACTL_PA_MUTE, 1, 0);
 509
 510static DECLARE_TLV_DB_SCALE(sun4i_codec_pa_volume_scale, -6300, 100, 1);
 511
 512static const struct snd_kcontrol_new sun4i_codec_widgets[] = {
 513        SOC_SINGLE_TLV("Power Amplifier Volume", SUN4I_CODEC_DAC_ACTL,
 514                       SUN4I_CODEC_DAC_ACTL_PA_VOL, 0x3F, 0,
 515                       sun4i_codec_pa_volume_scale),
 516};
 517
 518static const struct snd_kcontrol_new sun4i_codec_left_mixer_controls[] = {
 519        SOC_DAPM_SINGLE("Left DAC Playback Switch", SUN4I_CODEC_DAC_ACTL,
 520                        SUN4I_CODEC_DAC_ACTL_LDACLMIXS, 1, 0),
 521};
 522
 523static const struct snd_kcontrol_new sun4i_codec_right_mixer_controls[] = {
 524        SOC_DAPM_SINGLE("Right DAC Playback Switch", SUN4I_CODEC_DAC_ACTL,
 525                        SUN4I_CODEC_DAC_ACTL_RDACRMIXS, 1, 0),
 526        SOC_DAPM_SINGLE("Left DAC Playback Switch", SUN4I_CODEC_DAC_ACTL,
 527                        SUN4I_CODEC_DAC_ACTL_LDACRMIXS, 1, 0),
 528};
 529
 530static const struct snd_kcontrol_new sun4i_codec_pa_mixer_controls[] = {
 531        SOC_DAPM_SINGLE("DAC Playback Switch", SUN4I_CODEC_DAC_ACTL,
 532                        SUN4I_CODEC_DAC_ACTL_DACPAS, 1, 0),
 533        SOC_DAPM_SINGLE("Mixer Playback Switch", SUN4I_CODEC_DAC_ACTL,
 534                        SUN4I_CODEC_DAC_ACTL_MIXPAS, 1, 0),
 535};
 536
 537static const struct snd_soc_dapm_widget sun4i_codec_codec_dapm_widgets[] = {
 538        /* Digital parts of the ADCs */
 539        SND_SOC_DAPM_SUPPLY("ADC", SUN4I_CODEC_ADC_FIFOC,
 540                            SUN4I_CODEC_ADC_FIFOC_EN_AD, 0,
 541                            NULL, 0),
 542
 543        /* Digital parts of the DACs */
 544        SND_SOC_DAPM_SUPPLY("DAC", SUN4I_CODEC_DAC_DPC,
 545                            SUN4I_CODEC_DAC_DPC_EN_DA, 0,
 546                            NULL, 0),
 547
 548        /* Analog parts of the ADCs */
 549        SND_SOC_DAPM_ADC("Left ADC", "Codec Capture", SUN4I_CODEC_ADC_ACTL,
 550                         SUN4I_CODEC_ADC_ACTL_ADC_L_EN, 0),
 551        SND_SOC_DAPM_ADC("Right ADC", "Codec Capture", SUN4I_CODEC_ADC_ACTL,
 552                         SUN4I_CODEC_ADC_ACTL_ADC_R_EN, 0),
 553
 554        /* Analog parts of the DACs */
 555        SND_SOC_DAPM_DAC("Left DAC", "Codec Playback", SUN4I_CODEC_DAC_ACTL,
 556                         SUN4I_CODEC_DAC_ACTL_DACAENL, 0),
 557        SND_SOC_DAPM_DAC("Right DAC", "Codec Playback", SUN4I_CODEC_DAC_ACTL,
 558                         SUN4I_CODEC_DAC_ACTL_DACAENR, 0),
 559
 560        /* Mixers */
 561        SND_SOC_DAPM_MIXER("Left Mixer", SND_SOC_NOPM, 0, 0,
 562                           sun4i_codec_left_mixer_controls,
 563                           ARRAY_SIZE(sun4i_codec_left_mixer_controls)),
 564        SND_SOC_DAPM_MIXER("Right Mixer", SND_SOC_NOPM, 0, 0,
 565                           sun4i_codec_right_mixer_controls,
 566                           ARRAY_SIZE(sun4i_codec_right_mixer_controls)),
 567
 568        /* Global Mixer Enable */
 569        SND_SOC_DAPM_SUPPLY("Mixer Enable", SUN4I_CODEC_DAC_ACTL,
 570                            SUN4I_CODEC_DAC_ACTL_MIXEN, 0, NULL, 0),
 571
 572        /* VMIC */
 573        SND_SOC_DAPM_SUPPLY("VMIC", SUN4I_CODEC_ADC_ACTL,
 574                            SUN4I_CODEC_ADC_ACTL_VMICEN, 0, NULL, 0),
 575
 576        /* Mic Pre-Amplifiers */
 577        SND_SOC_DAPM_PGA("MIC1 Pre-Amplifier", SUN4I_CODEC_ADC_ACTL,
 578                         SUN4I_CODEC_ADC_ACTL_PREG1EN, 0, NULL, 0),
 579
 580        /* Power Amplifier */
 581        SND_SOC_DAPM_MIXER("Power Amplifier", SUN4I_CODEC_ADC_ACTL,
 582                           SUN4I_CODEC_ADC_ACTL_PA_EN, 0,
 583                           sun4i_codec_pa_mixer_controls,
 584                           ARRAY_SIZE(sun4i_codec_pa_mixer_controls)),
 585        SND_SOC_DAPM_SWITCH("Power Amplifier Mute", SND_SOC_NOPM, 0, 0,
 586                            &sun4i_codec_pa_mute),
 587
 588        SND_SOC_DAPM_INPUT("Mic1"),
 589
 590        SND_SOC_DAPM_OUTPUT("HP Right"),
 591        SND_SOC_DAPM_OUTPUT("HP Left"),
 592};
 593
 594static const struct snd_soc_dapm_route sun4i_codec_codec_dapm_routes[] = {
 595        /* Left ADC / DAC Routes */
 596        { "Left ADC", NULL, "ADC" },
 597        { "Left DAC", NULL, "DAC" },
 598
 599        /* Right ADC / DAC Routes */
 600        { "Right ADC", NULL, "ADC" },
 601        { "Right DAC", NULL, "DAC" },
 602
 603        /* Right Mixer Routes */
 604        { "Right Mixer", NULL, "Mixer Enable" },
 605        { "Right Mixer", "Left DAC Playback Switch", "Left DAC" },
 606        { "Right Mixer", "Right DAC Playback Switch", "Right DAC" },
 607
 608        /* Left Mixer Routes */
 609        { "Left Mixer", NULL, "Mixer Enable" },
 610        { "Left Mixer", "Left DAC Playback Switch", "Left DAC" },
 611
 612        /* Power Amplifier Routes */
 613        { "Power Amplifier", "Mixer Playback Switch", "Left Mixer" },
 614        { "Power Amplifier", "Mixer Playback Switch", "Right Mixer" },
 615        { "Power Amplifier", "DAC Playback Switch", "Left DAC" },
 616        { "Power Amplifier", "DAC Playback Switch", "Right DAC" },
 617
 618        /* Headphone Output Routes */
 619        { "Power Amplifier Mute", "Switch", "Power Amplifier" },
 620        { "HP Right", NULL, "Power Amplifier Mute" },
 621        { "HP Left", NULL, "Power Amplifier Mute" },
 622
 623        /* Mic1 Routes */
 624        { "Left ADC", NULL, "MIC1 Pre-Amplifier" },
 625        { "Right ADC", NULL, "MIC1 Pre-Amplifier" },
 626        { "MIC1 Pre-Amplifier", NULL, "Mic1"},
 627        { "Mic1", NULL, "VMIC" },
 628};
 629
 630static struct snd_soc_codec_driver sun4i_codec_codec = {
 631        .controls               = sun4i_codec_widgets,
 632        .num_controls           = ARRAY_SIZE(sun4i_codec_widgets),
 633        .dapm_widgets           = sun4i_codec_codec_dapm_widgets,
 634        .num_dapm_widgets       = ARRAY_SIZE(sun4i_codec_codec_dapm_widgets),
 635        .dapm_routes            = sun4i_codec_codec_dapm_routes,
 636        .num_dapm_routes        = ARRAY_SIZE(sun4i_codec_codec_dapm_routes),
 637};
 638
 639static const struct snd_soc_component_driver sun4i_codec_component = {
 640        .name = "sun4i-codec",
 641};
 642
 643#define SUN4I_CODEC_RATES       SNDRV_PCM_RATE_8000_192000
 644#define SUN4I_CODEC_FORMATS     (SNDRV_PCM_FMTBIT_S16_LE | \
 645                                 SNDRV_PCM_FMTBIT_S32_LE)
 646
 647static int sun4i_codec_dai_probe(struct snd_soc_dai *dai)
 648{
 649        struct snd_soc_card *card = snd_soc_dai_get_drvdata(dai);
 650        struct sun4i_codec *scodec = snd_soc_card_get_drvdata(card);
 651
 652        snd_soc_dai_init_dma_data(dai, &scodec->playback_dma_data,
 653                                  &scodec->capture_dma_data);
 654
 655        return 0;
 656}
 657
 658static struct snd_soc_dai_driver dummy_cpu_dai = {
 659        .name   = "sun4i-codec-cpu-dai",
 660        .probe  = sun4i_codec_dai_probe,
 661        .playback = {
 662                .stream_name    = "Playback",
 663                .channels_min   = 1,
 664                .channels_max   = 2,
 665                .rates          = SUN4I_CODEC_RATES,
 666                .formats        = SUN4I_CODEC_FORMATS,
 667                .sig_bits       = 24,
 668        },
 669        .capture = {
 670                .stream_name    = "Capture",
 671                .channels_min   = 1,
 672                .channels_max   = 2,
 673                .rates          = SUN4I_CODEC_RATES,
 674                .formats        = SUN4I_CODEC_FORMATS,
 675                .sig_bits       = 24,
 676         },
 677};
 678
 679static const struct regmap_config sun4i_codec_regmap_config = {
 680        .reg_bits       = 32,
 681        .reg_stride     = 4,
 682        .val_bits       = 32,
 683        .max_register   = SUN4I_CODEC_AC_MIC_PHONE_CAL,
 684};
 685
 686static const struct of_device_id sun4i_codec_of_match[] = {
 687        { .compatible = "allwinner,sun4i-a10-codec" },
 688        { .compatible = "allwinner,sun7i-a20-codec" },
 689        {}
 690};
 691MODULE_DEVICE_TABLE(of, sun4i_codec_of_match);
 692
 693static struct snd_soc_dai_link *sun4i_codec_create_link(struct device *dev,
 694                                                        int *num_links)
 695{
 696        struct snd_soc_dai_link *link = devm_kzalloc(dev, sizeof(*link),
 697                                                     GFP_KERNEL);
 698        if (!link)
 699                return NULL;
 700
 701        link->name              = "cdc";
 702        link->stream_name       = "CDC PCM";
 703        link->codec_dai_name    = "Codec";
 704        link->cpu_dai_name      = dev_name(dev);
 705        link->codec_name        = dev_name(dev);
 706        link->platform_name     = dev_name(dev);
 707        link->dai_fmt           = SND_SOC_DAIFMT_I2S;
 708
 709        *num_links = 1;
 710
 711        return link;
 712};
 713
 714static int sun4i_codec_spk_event(struct snd_soc_dapm_widget *w,
 715                                 struct snd_kcontrol *k, int event)
 716{
 717        struct sun4i_codec *scodec = snd_soc_card_get_drvdata(w->dapm->card);
 718
 719        if (scodec->gpio_pa)
 720                gpiod_set_value_cansleep(scodec->gpio_pa,
 721                                         !!SND_SOC_DAPM_EVENT_ON(event));
 722
 723        return 0;
 724}
 725
 726static const struct snd_soc_dapm_widget sun4i_codec_card_dapm_widgets[] = {
 727        SND_SOC_DAPM_SPK("Speaker", sun4i_codec_spk_event),
 728};
 729
 730static const struct snd_soc_dapm_route sun4i_codec_card_dapm_routes[] = {
 731        { "Speaker", NULL, "HP Right" },
 732        { "Speaker", NULL, "HP Left" },
 733};
 734
 735static struct snd_soc_card *sun4i_codec_create_card(struct device *dev)
 736{
 737        struct snd_soc_card *card;
 738
 739        card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
 740        if (!card)
 741                return NULL;
 742
 743        card->dai_link = sun4i_codec_create_link(dev, &card->num_links);
 744        if (!card->dai_link)
 745                return NULL;
 746
 747        card->dev               = dev;
 748        card->name              = "sun4i-codec";
 749        card->dapm_widgets      = sun4i_codec_card_dapm_widgets;
 750        card->num_dapm_widgets  = ARRAY_SIZE(sun4i_codec_card_dapm_widgets);
 751        card->dapm_routes       = sun4i_codec_card_dapm_routes;
 752        card->num_dapm_routes   = ARRAY_SIZE(sun4i_codec_card_dapm_routes);
 753
 754        return card;
 755};
 756
 757static int sun4i_codec_probe(struct platform_device *pdev)
 758{
 759        struct snd_soc_card *card;
 760        struct sun4i_codec *scodec;
 761        struct resource *res;
 762        void __iomem *base;
 763        int ret;
 764
 765        scodec = devm_kzalloc(&pdev->dev, sizeof(*scodec), GFP_KERNEL);
 766        if (!scodec)
 767                return -ENOMEM;
 768
 769        scodec->dev = &pdev->dev;
 770
 771        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 772        base = devm_ioremap_resource(&pdev->dev, res);
 773        if (IS_ERR(base)) {
 774                dev_err(&pdev->dev, "Failed to map the registers\n");
 775                return PTR_ERR(base);
 776        }
 777
 778        scodec->regmap = devm_regmap_init_mmio(&pdev->dev, base,
 779                                             &sun4i_codec_regmap_config);
 780        if (IS_ERR(scodec->regmap)) {
 781                dev_err(&pdev->dev, "Failed to create our regmap\n");
 782                return PTR_ERR(scodec->regmap);
 783        }
 784
 785        /* Get the clocks from the DT */
 786        scodec->clk_apb = devm_clk_get(&pdev->dev, "apb");
 787        if (IS_ERR(scodec->clk_apb)) {
 788                dev_err(&pdev->dev, "Failed to get the APB clock\n");
 789                return PTR_ERR(scodec->clk_apb);
 790        }
 791
 792        scodec->clk_module = devm_clk_get(&pdev->dev, "codec");
 793        if (IS_ERR(scodec->clk_module)) {
 794                dev_err(&pdev->dev, "Failed to get the module clock\n");
 795                return PTR_ERR(scodec->clk_module);
 796        }
 797
 798        /* Enable the bus clock */
 799        if (clk_prepare_enable(scodec->clk_apb)) {
 800                dev_err(&pdev->dev, "Failed to enable the APB clock\n");
 801                return -EINVAL;
 802        }
 803
 804        scodec->gpio_pa = devm_gpiod_get_optional(&pdev->dev, "allwinner,pa",
 805                                                  GPIOD_OUT_LOW);
 806        if (IS_ERR(scodec->gpio_pa)) {
 807                ret = PTR_ERR(scodec->gpio_pa);
 808                if (ret != -EPROBE_DEFER)
 809                        dev_err(&pdev->dev, "Failed to get pa gpio: %d\n", ret);
 810                return ret;
 811        }
 812
 813        /* DMA configuration for TX FIFO */
 814        scodec->playback_dma_data.addr = res->start + SUN4I_CODEC_DAC_TXDATA;
 815        scodec->playback_dma_data.maxburst = 4;
 816        scodec->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
 817
 818        /* DMA configuration for RX FIFO */
 819        scodec->capture_dma_data.addr = res->start + SUN4I_CODEC_ADC_RXDATA;
 820        scodec->capture_dma_data.maxburst = 4;
 821        scodec->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
 822
 823        ret = snd_soc_register_codec(&pdev->dev, &sun4i_codec_codec,
 824                                     &sun4i_codec_dai, 1);
 825        if (ret) {
 826                dev_err(&pdev->dev, "Failed to register our codec\n");
 827                goto err_clk_disable;
 828        }
 829
 830        ret = devm_snd_soc_register_component(&pdev->dev,
 831                                              &sun4i_codec_component,
 832                                              &dummy_cpu_dai, 1);
 833        if (ret) {
 834                dev_err(&pdev->dev, "Failed to register our DAI\n");
 835                goto err_unregister_codec;
 836        }
 837
 838        ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
 839        if (ret) {
 840                dev_err(&pdev->dev, "Failed to register against DMAEngine\n");
 841                goto err_unregister_codec;
 842        }
 843
 844        card = sun4i_codec_create_card(&pdev->dev);
 845        if (!card) {
 846                dev_err(&pdev->dev, "Failed to create our card\n");
 847                goto err_unregister_codec;
 848        }
 849
 850        platform_set_drvdata(pdev, card);
 851        snd_soc_card_set_drvdata(card, scodec);
 852
 853        ret = snd_soc_register_card(card);
 854        if (ret) {
 855                dev_err(&pdev->dev, "Failed to register our card\n");
 856                goto err_unregister_codec;
 857        }
 858
 859        return 0;
 860
 861err_unregister_codec:
 862        snd_soc_unregister_codec(&pdev->dev);
 863err_clk_disable:
 864        clk_disable_unprepare(scodec->clk_apb);
 865        return ret;
 866}
 867
 868static int sun4i_codec_remove(struct platform_device *pdev)
 869{
 870        struct snd_soc_card *card = platform_get_drvdata(pdev);
 871        struct sun4i_codec *scodec = snd_soc_card_get_drvdata(card);
 872
 873        snd_soc_unregister_card(card);
 874        snd_soc_unregister_codec(&pdev->dev);
 875        clk_disable_unprepare(scodec->clk_apb);
 876
 877        return 0;
 878}
 879
 880static struct platform_driver sun4i_codec_driver = {
 881        .driver = {
 882                .name = "sun4i-codec",
 883                .of_match_table = sun4i_codec_of_match,
 884        },
 885        .probe = sun4i_codec_probe,
 886        .remove = sun4i_codec_remove,
 887};
 888module_platform_driver(sun4i_codec_driver);
 889
 890MODULE_DESCRIPTION("Allwinner A10 codec driver");
 891MODULE_AUTHOR("Emilio López <emilio@elopez.com.ar>");
 892MODULE_AUTHOR("Jon Smirl <jonsmirl@gmail.com>");
 893MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
 894MODULE_LICENSE("GPL");
 895