linux/sound/soc/sunxi/sun4i-codec.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Copyright 2014 Emilio López <emilio@elopez.com.ar>
   4 * Copyright 2014 Jon Smirl <jonsmirl@gmail.com>
   5 * Copyright 2015 Maxime Ripard <maxime.ripard@free-electrons.com>
   6 * Copyright 2015 Adam Sampson <ats@offog.org>
   7 * Copyright 2016 Chen-Yu Tsai <wens@csie.org>
   8 * Copyright 2018 Mesih Kilinc <mesihkilinc@gmail.com>
   9 *
  10 * Based on the Allwinner SDK driver, released under the GPL.
  11 */
  12
  13#include <linux/init.h>
  14#include <linux/kernel.h>
  15#include <linux/module.h>
  16#include <linux/platform_device.h>
  17#include <linux/delay.h>
  18#include <linux/slab.h>
  19#include <linux/clk.h>
  20#include <linux/regmap.h>
  21#include <linux/reset.h>
  22#include <linux/gpio/consumer.h>
  23
  24#include <sound/core.h>
  25#include <sound/jack.h>
  26#include <sound/pcm.h>
  27#include <sound/pcm_params.h>
  28#include <sound/soc.h>
  29#include <sound/tlv.h>
  30#include <sound/initval.h>
  31#include <sound/dmaengine_pcm.h>
  32
  33/* Codec DAC digital controls and FIFO registers */
  34#define SUN4I_CODEC_DAC_DPC                     (0x00)
  35#define SUN4I_CODEC_DAC_DPC_EN_DA                       (31)
  36#define SUN4I_CODEC_DAC_DPC_DVOL                        (12)
  37#define SUN4I_CODEC_DAC_FIFOC                   (0x04)
  38#define SUN4I_CODEC_DAC_FIFOC_DAC_FS                    (29)
  39#define SUN4I_CODEC_DAC_FIFOC_FIR_VERSION               (28)
  40#define SUN4I_CODEC_DAC_FIFOC_SEND_LASAT                (26)
  41#define SUN4I_CODEC_DAC_FIFOC_TX_FIFO_MODE              (24)
  42#define SUN4I_CODEC_DAC_FIFOC_DRQ_CLR_CNT               (21)
  43#define SUN4I_CODEC_DAC_FIFOC_TX_TRIG_LEVEL             (8)
  44#define SUN4I_CODEC_DAC_FIFOC_MONO_EN                   (6)
  45#define SUN4I_CODEC_DAC_FIFOC_TX_SAMPLE_BITS            (5)
  46#define SUN4I_CODEC_DAC_FIFOC_DAC_DRQ_EN                (4)
  47#define SUN4I_CODEC_DAC_FIFOC_FIFO_FLUSH                (0)
  48#define SUN4I_CODEC_DAC_FIFOS                   (0x08)
  49#define SUN4I_CODEC_DAC_TXDATA                  (0x0c)
  50
  51/* Codec DAC side analog signal controls */
  52#define SUN4I_CODEC_DAC_ACTL                    (0x10)
  53#define SUN4I_CODEC_DAC_ACTL_DACAENR                    (31)
  54#define SUN4I_CODEC_DAC_ACTL_DACAENL                    (30)
  55#define SUN4I_CODEC_DAC_ACTL_MIXEN                      (29)
  56#define SUN4I_CODEC_DAC_ACTL_LNG                        (26)
  57#define SUN4I_CODEC_DAC_ACTL_FMG                        (23)
  58#define SUN4I_CODEC_DAC_ACTL_MICG                       (20)
  59#define SUN4I_CODEC_DAC_ACTL_LLNS                       (19)
  60#define SUN4I_CODEC_DAC_ACTL_RLNS                       (18)
  61#define SUN4I_CODEC_DAC_ACTL_LFMS                       (17)
  62#define SUN4I_CODEC_DAC_ACTL_RFMS                       (16)
  63#define SUN4I_CODEC_DAC_ACTL_LDACLMIXS                  (15)
  64#define SUN4I_CODEC_DAC_ACTL_RDACRMIXS                  (14)
  65#define SUN4I_CODEC_DAC_ACTL_LDACRMIXS                  (13)
  66#define SUN4I_CODEC_DAC_ACTL_MIC1LS                     (12)
  67#define SUN4I_CODEC_DAC_ACTL_MIC1RS                     (11)
  68#define SUN4I_CODEC_DAC_ACTL_MIC2LS                     (10)
  69#define SUN4I_CODEC_DAC_ACTL_MIC2RS                     (9)
  70#define SUN4I_CODEC_DAC_ACTL_DACPAS                     (8)
  71#define SUN4I_CODEC_DAC_ACTL_MIXPAS                     (7)
  72#define SUN4I_CODEC_DAC_ACTL_PA_MUTE                    (6)
  73#define SUN4I_CODEC_DAC_ACTL_PA_VOL                     (0)
  74#define SUN4I_CODEC_DAC_TUNE                    (0x14)
  75#define SUN4I_CODEC_DAC_DEBUG                   (0x18)
  76
  77/* Codec ADC digital controls and FIFO registers */
  78#define SUN4I_CODEC_ADC_FIFOC                   (0x1c)
  79#define SUN4I_CODEC_ADC_FIFOC_ADC_FS                    (29)
  80#define SUN4I_CODEC_ADC_FIFOC_EN_AD                     (28)
  81#define SUN4I_CODEC_ADC_FIFOC_RX_FIFO_MODE              (24)
  82#define SUN4I_CODEC_ADC_FIFOC_RX_TRIG_LEVEL             (8)
  83#define SUN4I_CODEC_ADC_FIFOC_MONO_EN                   (7)
  84#define SUN4I_CODEC_ADC_FIFOC_RX_SAMPLE_BITS            (6)
  85#define SUN4I_CODEC_ADC_FIFOC_ADC_DRQ_EN                (4)
  86#define SUN4I_CODEC_ADC_FIFOC_FIFO_FLUSH                (0)
  87#define SUN4I_CODEC_ADC_FIFOS                   (0x20)
  88#define SUN4I_CODEC_ADC_RXDATA                  (0x24)
  89
  90/* Codec ADC side analog signal controls */
  91#define SUN4I_CODEC_ADC_ACTL                    (0x28)
  92#define SUN4I_CODEC_ADC_ACTL_ADC_R_EN                   (31)
  93#define SUN4I_CODEC_ADC_ACTL_ADC_L_EN                   (30)
  94#define SUN4I_CODEC_ADC_ACTL_PREG1EN                    (29)
  95#define SUN4I_CODEC_ADC_ACTL_PREG2EN                    (28)
  96#define SUN4I_CODEC_ADC_ACTL_VMICEN                     (27)
  97#define SUN4I_CODEC_ADC_ACTL_PREG1                      (25)
  98#define SUN4I_CODEC_ADC_ACTL_PREG2                      (23)
  99#define SUN4I_CODEC_ADC_ACTL_VADCG                      (20)
 100#define SUN4I_CODEC_ADC_ACTL_ADCIS                      (17)
 101#define SUN4I_CODEC_ADC_ACTL_LNPREG                     (13)
 102#define SUN4I_CODEC_ADC_ACTL_PA_EN                      (4)
 103#define SUN4I_CODEC_ADC_ACTL_DDE                        (3)
 104#define SUN4I_CODEC_ADC_DEBUG                   (0x2c)
 105
 106/* FIFO counters */
 107#define SUN4I_CODEC_DAC_TXCNT                   (0x30)
 108#define SUN4I_CODEC_ADC_RXCNT                   (0x34)
 109
 110/* Calibration register (sun7i only) */
 111#define SUN7I_CODEC_AC_DAC_CAL                  (0x38)
 112
 113/* Microphone controls (sun7i only) */
 114#define SUN7I_CODEC_AC_MIC_PHONE_CAL            (0x3c)
 115
 116#define SUN7I_CODEC_AC_MIC_PHONE_CAL_PREG1              (29)
 117#define SUN7I_CODEC_AC_MIC_PHONE_CAL_PREG2              (26)
 118
 119/*
 120 * sun6i specific registers
 121 *
 122 * sun6i shares the same digital control and FIFO registers as sun4i,
 123 * but only the DAC digital controls are at the same offset. The others
 124 * have been moved around to accommodate extra analog controls.
 125 */
 126
 127/* Codec DAC digital controls and FIFO registers */
 128#define SUN6I_CODEC_ADC_FIFOC                   (0x10)
 129#define SUN6I_CODEC_ADC_FIFOC_EN_AD                     (28)
 130#define SUN6I_CODEC_ADC_FIFOS                   (0x14)
 131#define SUN6I_CODEC_ADC_RXDATA                  (0x18)
 132
 133/* Output mixer and gain controls */
 134#define SUN6I_CODEC_OM_DACA_CTRL                (0x20)
 135#define SUN6I_CODEC_OM_DACA_CTRL_DACAREN                (31)
 136#define SUN6I_CODEC_OM_DACA_CTRL_DACALEN                (30)
 137#define SUN6I_CODEC_OM_DACA_CTRL_RMIXEN                 (29)
 138#define SUN6I_CODEC_OM_DACA_CTRL_LMIXEN                 (28)
 139#define SUN6I_CODEC_OM_DACA_CTRL_RMIX_MIC1              (23)
 140#define SUN6I_CODEC_OM_DACA_CTRL_RMIX_MIC2              (22)
 141#define SUN6I_CODEC_OM_DACA_CTRL_RMIX_PHONE             (21)
 142#define SUN6I_CODEC_OM_DACA_CTRL_RMIX_PHONEP            (20)
 143#define SUN6I_CODEC_OM_DACA_CTRL_RMIX_LINEINR           (19)
 144#define SUN6I_CODEC_OM_DACA_CTRL_RMIX_DACR              (18)
 145#define SUN6I_CODEC_OM_DACA_CTRL_RMIX_DACL              (17)
 146#define SUN6I_CODEC_OM_DACA_CTRL_LMIX_MIC1              (16)
 147#define SUN6I_CODEC_OM_DACA_CTRL_LMIX_MIC2              (15)
 148#define SUN6I_CODEC_OM_DACA_CTRL_LMIX_PHONE             (14)
 149#define SUN6I_CODEC_OM_DACA_CTRL_LMIX_PHONEN            (13)
 150#define SUN6I_CODEC_OM_DACA_CTRL_LMIX_LINEINL           (12)
 151#define SUN6I_CODEC_OM_DACA_CTRL_LMIX_DACL              (11)
 152#define SUN6I_CODEC_OM_DACA_CTRL_LMIX_DACR              (10)
 153#define SUN6I_CODEC_OM_DACA_CTRL_RHPIS                  (9)
 154#define SUN6I_CODEC_OM_DACA_CTRL_LHPIS                  (8)
 155#define SUN6I_CODEC_OM_DACA_CTRL_RHPPAMUTE              (7)
 156#define SUN6I_CODEC_OM_DACA_CTRL_LHPPAMUTE              (6)
 157#define SUN6I_CODEC_OM_DACA_CTRL_HPVOL                  (0)
 158#define SUN6I_CODEC_OM_PA_CTRL                  (0x24)
 159#define SUN6I_CODEC_OM_PA_CTRL_HPPAEN                   (31)
 160#define SUN6I_CODEC_OM_PA_CTRL_HPCOM_CTL                (29)
 161#define SUN6I_CODEC_OM_PA_CTRL_COMPTEN                  (28)
 162#define SUN6I_CODEC_OM_PA_CTRL_MIC1G                    (15)
 163#define SUN6I_CODEC_OM_PA_CTRL_MIC2G                    (12)
 164#define SUN6I_CODEC_OM_PA_CTRL_LINEING                  (9)
 165#define SUN6I_CODEC_OM_PA_CTRL_PHONEG                   (6)
 166#define SUN6I_CODEC_OM_PA_CTRL_PHONEPG                  (3)
 167#define SUN6I_CODEC_OM_PA_CTRL_PHONENG                  (0)
 168
 169/* Microphone, line out and phone out controls */
 170#define SUN6I_CODEC_MIC_CTRL                    (0x28)
 171#define SUN6I_CODEC_MIC_CTRL_HBIASEN                    (31)
 172#define SUN6I_CODEC_MIC_CTRL_MBIASEN                    (30)
 173#define SUN6I_CODEC_MIC_CTRL_MIC1AMPEN                  (28)
 174#define SUN6I_CODEC_MIC_CTRL_MIC1BOOST                  (25)
 175#define SUN6I_CODEC_MIC_CTRL_MIC2AMPEN                  (24)
 176#define SUN6I_CODEC_MIC_CTRL_MIC2BOOST                  (21)
 177#define SUN6I_CODEC_MIC_CTRL_MIC2SLT                    (20)
 178#define SUN6I_CODEC_MIC_CTRL_LINEOUTLEN                 (19)
 179#define SUN6I_CODEC_MIC_CTRL_LINEOUTREN                 (18)
 180#define SUN6I_CODEC_MIC_CTRL_LINEOUTLSRC                (17)
 181#define SUN6I_CODEC_MIC_CTRL_LINEOUTRSRC                (16)
 182#define SUN6I_CODEC_MIC_CTRL_LINEOUTVC                  (11)
 183#define SUN6I_CODEC_MIC_CTRL_PHONEPREG                  (8)
 184
 185/* ADC mixer controls */
 186#define SUN6I_CODEC_ADC_ACTL                    (0x2c)
 187#define SUN6I_CODEC_ADC_ACTL_ADCREN                     (31)
 188#define SUN6I_CODEC_ADC_ACTL_ADCLEN                     (30)
 189#define SUN6I_CODEC_ADC_ACTL_ADCRG                      (27)
 190#define SUN6I_CODEC_ADC_ACTL_ADCLG                      (24)
 191#define SUN6I_CODEC_ADC_ACTL_RADCMIX_MIC1               (13)
 192#define SUN6I_CODEC_ADC_ACTL_RADCMIX_MIC2               (12)
 193#define SUN6I_CODEC_ADC_ACTL_RADCMIX_PHONE              (11)
 194#define SUN6I_CODEC_ADC_ACTL_RADCMIX_PHONEP             (10)
 195#define SUN6I_CODEC_ADC_ACTL_RADCMIX_LINEINR            (9)
 196#define SUN6I_CODEC_ADC_ACTL_RADCMIX_OMIXR              (8)
 197#define SUN6I_CODEC_ADC_ACTL_RADCMIX_OMIXL              (7)
 198#define SUN6I_CODEC_ADC_ACTL_LADCMIX_MIC1               (6)
 199#define SUN6I_CODEC_ADC_ACTL_LADCMIX_MIC2               (5)
 200#define SUN6I_CODEC_ADC_ACTL_LADCMIX_PHONE              (4)
 201#define SUN6I_CODEC_ADC_ACTL_LADCMIX_PHONEN             (3)
 202#define SUN6I_CODEC_ADC_ACTL_LADCMIX_LINEINL            (2)
 203#define SUN6I_CODEC_ADC_ACTL_LADCMIX_OMIXL              (1)
 204#define SUN6I_CODEC_ADC_ACTL_LADCMIX_OMIXR              (0)
 205
 206/* Analog performance tuning controls */
 207#define SUN6I_CODEC_ADDA_TUNE                   (0x30)
 208
 209/* Calibration controls */
 210#define SUN6I_CODEC_CALIBRATION                 (0x34)
 211
 212/* FIFO counters */
 213#define SUN6I_CODEC_DAC_TXCNT                   (0x40)
 214#define SUN6I_CODEC_ADC_RXCNT                   (0x44)
 215
 216/* headset jack detection and button support registers */
 217#define SUN6I_CODEC_HMIC_CTL                    (0x50)
 218#define SUN6I_CODEC_HMIC_DATA                   (0x54)
 219
 220/* TODO sun6i DAP (Digital Audio Processing) bits */
 221
 222/* FIFO counters moved on A23 */
 223#define SUN8I_A23_CODEC_DAC_TXCNT               (0x1c)
 224#define SUN8I_A23_CODEC_ADC_RXCNT               (0x20)
 225
 226/* TX FIFO moved on H3 */
 227#define SUN8I_H3_CODEC_DAC_TXDATA               (0x20)
 228#define SUN8I_H3_CODEC_DAC_DBG                  (0x48)
 229#define SUN8I_H3_CODEC_ADC_DBG                  (0x4c)
 230
 231/* H616 specific registers */
 232#define SUN50I_H616_CODEC_DAC_FIFOC             (0x10)
 233
 234#define SUN50I_DAC_FIFO_STA                     (0x14)
 235#define SUN50I_DAC_TXE_INT                      (3)
 236#define SUN50I_DAC_TXU_INT                      (2)
 237#define SUN50I_DAC_TXO_INT                      (1)
 238
 239#define SUN50I_DAC_CNT                          (0x24)
 240#define SUN50I_DAC_DG_REG                       (0x28)
 241#define SUN50I_DAC_DAP_CTL                      (0xf0)
 242
 243#define SUN50I_H616_DAC_AC_DAC_REG              (0x310)
 244#define SUN50I_H616_DAC_LEN                     (15)
 245#define SUN50I_H616_DAC_REN                     (14)
 246#define SUN50I_H616_LINEOUTL_EN                 (13)
 247#define SUN50I_H616_LMUTE                       (12)
 248#define SUN50I_H616_LINEOUTR_EN                 (11)
 249#define SUN50I_H616_RMUTE                       (10)
 250#define SUN50I_H616_RSWITCH                     (9)
 251#define SUN50I_H616_RAMPEN                      (8)
 252#define SUN50I_H616_LINEOUTL_SEL                (6)
 253#define SUN50I_H616_LINEOUTR_SEL                (5)
 254#define SUN50I_H616_LINEOUT_VOL                 (0)
 255
 256#define SUN50I_H616_DAC_AC_MIXER_REG            (0x314)
 257#define SUN50I_H616_LMIX_LDAC                   (21)
 258#define SUN50I_H616_LMIX_RDAC                   (20)
 259#define SUN50I_H616_RMIX_RDAC                   (17)
 260#define SUN50I_H616_RMIX_LDAC                   (16)
 261#define SUN50I_H616_LMIXEN                      (11)
 262#define SUN50I_H616_RMIXEN                      (10)
 263
 264#define SUN50I_H616_DAC_AC_RAMP_REG             (0x31c)
 265#define SUN50I_H616_RAMP_STEP                   (4)
 266#define SUN50I_H616_RDEN                        (0)
 267
 268/* TODO H3 DAP (Digital Audio Processing) bits */
 269
 270#define SUN4I_DMA_MAX_BURST                     (8)
 271
 272/* suniv specific registers */
 273
 274#define SUNIV_DMA_MAX_BURST                     (4)
 275
 276/* Codec DAC digital controls and FIFO registers */
 277#define SUNIV_CODEC_ADC_FIFOC                   (0x10)
 278#define SUNIV_CODEC_ADC_FIFOC_EN_AD             (28)
 279#define SUNIV_CODEC_ADC_FIFOS                   (0x14)
 280#define SUNIV_CODEC_ADC_RXDATA                  (0x18)
 281
 282/* Output mixer and gain controls */
 283#define SUNIV_CODEC_OM_DACA_CTRL                        (0x20)
 284#define SUNIV_CODEC_OM_DACA_CTRL_DACAREN                (31)
 285#define SUNIV_CODEC_OM_DACA_CTRL_DACALEN                (30)
 286#define SUNIV_CODEC_OM_DACA_CTRL_RMIXEN                 (29)
 287#define SUNIV_CODEC_OM_DACA_CTRL_LMIXEN                 (28)
 288#define SUNIV_CODEC_OM_DACA_CTRL_RHPPAMUTE              (27)
 289#define SUNIV_CODEC_OM_DACA_CTRL_LHPPAMUTE              (26)
 290#define SUNIV_CODEC_OM_DACA_CTRL_RHPIS                  (25)
 291#define SUNIV_CODEC_OM_DACA_CTRL_LHPIS                  (24)
 292#define SUNIV_CODEC_OM_DACA_CTRL_HPCOM_CTL              (22)
 293#define SUNIV_CODEC_OM_DACA_CTRL_COMPTEN                (21)
 294#define SUNIV_CODEC_OM_DACA_CTRL_RMIXMUTE_MICIN         (20)
 295#define SUNIV_CODEC_OM_DACA_CTRL_RMIXMUTE_LINEIN        (19)
 296#define SUNIV_CODEC_OM_DACA_CTRL_RMIXMUTE_FMIN          (18)
 297#define SUNIV_CODEC_OM_DACA_CTRL_RMIXMUTE_RDAC          (17)
 298#define SUNIV_CODEC_OM_DACA_CTRL_RMIXMUTE_LDAC          (16)
 299#define SUNIV_CODEC_OM_DACA_CTRL_HPPAEN                 (15)
 300#define SUNIV_CODEC_OM_DACA_CTRL_LMIXMUTE_MICIN         (12)
 301#define SUNIV_CODEC_OM_DACA_CTRL_LMIXMUTE_LINEIN        (11)
 302#define SUNIV_CODEC_OM_DACA_CTRL_LMIXMUTE_FMIN          (10)
 303#define SUNIV_CODEC_OM_DACA_CTRL_LMIXMUTE_LDAC          (9)
 304#define SUNIV_CODEC_OM_DACA_CTRL_LMIXMUTE_RDAC          (8)
 305#define SUNIV_CODEC_OM_DACA_CTRL_LTLNMUTE               (7)
 306#define SUNIV_CODEC_OM_DACA_CTRL_RTLNMUTE               (6)
 307#define SUNIV_CODEC_OM_DACA_CTRL_HPVOL                  (0)
 308
 309/* Analog Input Mixer controls */
 310#define SUNIV_CODEC_ADC_ACTL            (0x24)
 311#define SUNIV_CODEC_ADC_ADCEN           (31)
 312#define SUNIV_CODEC_ADC_MICG            (24)
 313#define SUNIV_CODEC_ADC_LINEINVOL       (21)
 314#define SUNIV_CODEC_ADC_ADCG            (16)
 315#define SUNIV_CODEC_ADC_ADCMIX_MIC      (13)
 316#define SUNIV_CODEC_ADC_ADCMIX_FMINL    (12)
 317#define SUNIV_CODEC_ADC_ADCMIX_FMINR    (11)
 318#define SUNIV_CODEC_ADC_ADCMIX_LINEIN   (10)
 319#define SUNIV_CODEC_ADC_ADCMIX_LOUT     (9)
 320#define SUNIV_CODEC_ADC_ADCMIX_ROUT     (8)
 321#define SUNIV_CODEC_ADC_PASPEEDSELECT   (7)
 322#define SUNIV_CODEC_ADC_FMINVOL         (4)
 323#define SUNIV_CODEC_ADC_MICAMPEN        (3)
 324#define SUNIV_CODEC_ADC_MICBOOST        (0)
 325
 326#define SUNIV_CODEC_ADC_DBG             (0x4c)
 327
 328struct sun4i_codec {
 329        struct device   *dev;
 330        struct regmap   *regmap;
 331        struct clk      *clk_apb;
 332        struct clk      *clk_module;
 333        struct reset_control *rst;
 334        struct gpio_desc *gpio_pa;
 335        struct gpio_desc *gpio_hp;
 336
 337        /* ADC_FIFOC register is at different offset on different SoCs */
 338        struct regmap_field *reg_adc_fifoc;
 339        /* DAC_FIFOC register is at different offset on different SoCs */
 340        struct regmap_field *reg_dac_fifoc;
 341
 342        struct snd_dmaengine_dai_dma_data       capture_dma_data;
 343        struct snd_dmaengine_dai_dma_data       playback_dma_data;
 344};
 345
 346static void sun4i_codec_start_playback(struct sun4i_codec *scodec)
 347{
 348        /* Flush TX FIFO */
 349        regmap_field_set_bits(scodec->reg_dac_fifoc,
 350                              BIT(SUN4I_CODEC_DAC_FIFOC_FIFO_FLUSH));
 351
 352        /* Enable DAC DRQ */
 353        regmap_field_set_bits(scodec->reg_dac_fifoc,
 354                              BIT(SUN4I_CODEC_DAC_FIFOC_DAC_DRQ_EN));
 355}
 356
 357static void sun4i_codec_stop_playback(struct sun4i_codec *scodec)
 358{
 359        /* Disable DAC DRQ */
 360        regmap_field_clear_bits(scodec->reg_dac_fifoc,
 361                                BIT(SUN4I_CODEC_DAC_FIFOC_DAC_DRQ_EN));
 362}
 363
 364static void sun4i_codec_start_capture(struct sun4i_codec *scodec)
 365{
 366        /* Enable ADC DRQ */
 367        regmap_field_set_bits(scodec->reg_adc_fifoc,
 368                              BIT(SUN4I_CODEC_ADC_FIFOC_ADC_DRQ_EN));
 369}
 370
 371static void sun4i_codec_stop_capture(struct sun4i_codec *scodec)
 372{
 373        /* Disable ADC DRQ */
 374        regmap_field_clear_bits(scodec->reg_adc_fifoc,
 375                                 BIT(SUN4I_CODEC_ADC_FIFOC_ADC_DRQ_EN));
 376}
 377
 378static int sun4i_codec_trigger(struct snd_pcm_substream *substream, int cmd,
 379                               struct snd_soc_dai *dai)
 380{
 381        struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
 382        struct sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card);
 383
 384        switch (cmd) {
 385        case SNDRV_PCM_TRIGGER_START:
 386        case SNDRV_PCM_TRIGGER_RESUME:
 387        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 388                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 389                        sun4i_codec_start_playback(scodec);
 390                else
 391                        sun4i_codec_start_capture(scodec);
 392                break;
 393
 394        case SNDRV_PCM_TRIGGER_STOP:
 395        case SNDRV_PCM_TRIGGER_SUSPEND:
 396        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 397                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 398                        sun4i_codec_stop_playback(scodec);
 399                else
 400                        sun4i_codec_stop_capture(scodec);
 401                break;
 402
 403        default:
 404                return -EINVAL;
 405        }
 406
 407        return 0;
 408}
 409
 410static int sun4i_codec_prepare_capture(struct snd_pcm_substream *substream,
 411                                       struct snd_soc_dai *dai)
 412{
 413        struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
 414        struct sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card);
 415
 416
 417        /* Flush RX FIFO */
 418        regmap_field_set_bits(scodec->reg_adc_fifoc,
 419                                 BIT(SUN4I_CODEC_ADC_FIFOC_FIFO_FLUSH));
 420
 421
 422        /* Set RX FIFO trigger level */
 423        regmap_field_update_bits(scodec->reg_adc_fifoc,
 424                                 0xf << SUN4I_CODEC_ADC_FIFOC_RX_TRIG_LEVEL,
 425                                 0x7 << SUN4I_CODEC_ADC_FIFOC_RX_TRIG_LEVEL);
 426
 427        /*
 428         * FIXME: Undocumented in the datasheet, but
 429         *        Allwinner's code mentions that it is
 430         *        related to microphone gain
 431         */
 432        if (of_device_is_compatible(scodec->dev->of_node,
 433                                    "allwinner,sun4i-a10-codec") ||
 434            of_device_is_compatible(scodec->dev->of_node,
 435                                    "allwinner,sun7i-a20-codec")) {
 436                regmap_update_bits(scodec->regmap, SUN4I_CODEC_ADC_ACTL,
 437                                   0x3 << 25,
 438                                   0x1 << 25);
 439        }
 440
 441        if (of_device_is_compatible(scodec->dev->of_node,
 442                                    "allwinner,sun7i-a20-codec"))
 443                /* FIXME: Undocumented bits */
 444                regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_TUNE,
 445                                   0x3 << 8,
 446                                   0x1 << 8);
 447
 448        return 0;
 449}
 450
 451static int sun4i_codec_prepare_playback(struct snd_pcm_substream *substream,
 452                                        struct snd_soc_dai *dai)
 453{
 454        struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
 455        struct sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card);
 456        u32 val;
 457
 458        /* Flush the TX FIFO */
 459        regmap_field_set_bits(scodec->reg_dac_fifoc,
 460                              BIT(SUN4I_CODEC_DAC_FIFOC_FIFO_FLUSH));
 461
 462        /* Set TX FIFO Empty Trigger Level */
 463        regmap_field_update_bits(scodec->reg_dac_fifoc,
 464                                 0x3f << SUN4I_CODEC_DAC_FIFOC_TX_TRIG_LEVEL,
 465                                 0xf << SUN4I_CODEC_DAC_FIFOC_TX_TRIG_LEVEL);
 466
 467        if (substream->runtime->rate > 32000)
 468                /* Use 64 bits FIR filter */
 469                val = 0;
 470        else
 471                /* Use 32 bits FIR filter */
 472                val = BIT(SUN4I_CODEC_DAC_FIFOC_FIR_VERSION);
 473
 474        regmap_field_update_bits(scodec->reg_dac_fifoc,
 475                                 BIT(SUN4I_CODEC_DAC_FIFOC_FIR_VERSION),
 476                                 val);
 477
 478        /* Send zeros when we have an underrun */
 479        regmap_field_clear_bits(scodec->reg_dac_fifoc,
 480                                BIT(SUN4I_CODEC_DAC_FIFOC_SEND_LASAT));
 481
 482        return 0;
 483};
 484
 485static int sun4i_codec_prepare(struct snd_pcm_substream *substream,
 486                               struct snd_soc_dai *dai)
 487{
 488        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 489                return sun4i_codec_prepare_playback(substream, dai);
 490
 491        return sun4i_codec_prepare_capture(substream, dai);
 492}
 493
 494static unsigned long sun4i_codec_get_mod_freq(struct snd_pcm_hw_params *params)
 495{
 496        unsigned int rate = params_rate(params);
 497
 498        switch (rate) {
 499        case 176400:
 500        case 88200:
 501        case 44100:
 502        case 33075:
 503        case 22050:
 504        case 14700:
 505        case 11025:
 506        case 7350:
 507                return 22579200;
 508
 509        case 192000:
 510        case 96000:
 511        case 48000:
 512        case 32000:
 513        case 24000:
 514        case 16000:
 515        case 12000:
 516        case 8000:
 517                return 24576000;
 518
 519        default:
 520                return 0;
 521        }
 522}
 523
 524static int sun4i_codec_get_hw_rate(struct snd_pcm_hw_params *params)
 525{
 526        unsigned int rate = params_rate(params);
 527
 528        switch (rate) {
 529        case 192000:
 530        case 176400:
 531                return 6;
 532
 533        case 96000:
 534        case 88200:
 535                return 7;
 536
 537        case 48000:
 538        case 44100:
 539                return 0;
 540
 541        case 32000:
 542        case 33075:
 543                return 1;
 544
 545        case 24000:
 546        case 22050:
 547                return 2;
 548
 549        case 16000:
 550        case 14700:
 551                return 3;
 552
 553        case 12000:
 554        case 11025:
 555                return 4;
 556
 557        case 8000:
 558        case 7350:
 559                return 5;
 560
 561        default:
 562                return -EINVAL;
 563        }
 564}
 565
 566static int sun4i_codec_hw_params_capture(struct sun4i_codec *scodec,
 567                                         struct snd_pcm_hw_params *params,
 568                                         unsigned int hwrate)
 569{
 570        /* Set ADC sample rate */
 571        regmap_field_update_bits(scodec->reg_adc_fifoc,
 572                                 7 << SUN4I_CODEC_ADC_FIFOC_ADC_FS,
 573                                 hwrate << SUN4I_CODEC_ADC_FIFOC_ADC_FS);
 574
 575        /* Set the number of channels we want to use */
 576        if (params_channels(params) == 1)
 577                regmap_field_set_bits(scodec->reg_adc_fifoc,
 578                                         BIT(SUN4I_CODEC_ADC_FIFOC_MONO_EN));
 579        else
 580                regmap_field_clear_bits(scodec->reg_adc_fifoc,
 581                                         BIT(SUN4I_CODEC_ADC_FIFOC_MONO_EN));
 582
 583        /* Set the number of sample bits to either 16 or 24 bits */
 584        if (hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS)->min == 32) {
 585                regmap_field_set_bits(scodec->reg_adc_fifoc,
 586                                   BIT(SUN4I_CODEC_ADC_FIFOC_RX_SAMPLE_BITS));
 587
 588                regmap_field_clear_bits(scodec->reg_adc_fifoc,
 589                                   BIT(SUN4I_CODEC_ADC_FIFOC_RX_FIFO_MODE));
 590
 591                scodec->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
 592        } else {
 593                regmap_field_clear_bits(scodec->reg_adc_fifoc,
 594                                   BIT(SUN4I_CODEC_ADC_FIFOC_RX_SAMPLE_BITS));
 595
 596                /* Fill most significant bits with valid data MSB */
 597                regmap_field_set_bits(scodec->reg_adc_fifoc,
 598                                   BIT(SUN4I_CODEC_ADC_FIFOC_RX_FIFO_MODE));
 599
 600                scodec->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
 601        }
 602
 603        return 0;
 604}
 605
 606static int sun4i_codec_hw_params_playback(struct sun4i_codec *scodec,
 607                                          struct snd_pcm_hw_params *params,
 608                                          unsigned int hwrate)
 609{
 610        u32 val;
 611
 612        /* Set DAC sample rate */
 613        regmap_field_update_bits(scodec->reg_dac_fifoc,
 614                                 7 << SUN4I_CODEC_DAC_FIFOC_DAC_FS,
 615                                 hwrate << SUN4I_CODEC_DAC_FIFOC_DAC_FS);
 616
 617        /* Set the number of channels we want to use */
 618        if (params_channels(params) == 1)
 619                val = BIT(SUN4I_CODEC_DAC_FIFOC_MONO_EN);
 620        else
 621                val = 0;
 622
 623        regmap_field_update_bits(scodec->reg_dac_fifoc,
 624                                 BIT(SUN4I_CODEC_DAC_FIFOC_MONO_EN),
 625                                 val);
 626
 627        /* Set the number of sample bits to either 16 or 24 bits */
 628        if (hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS)->min == 32) {
 629                regmap_field_set_bits(scodec->reg_dac_fifoc,
 630                                      BIT(SUN4I_CODEC_DAC_FIFOC_TX_SAMPLE_BITS));
 631
 632                /* Set TX FIFO mode to padding the LSBs with 0 */
 633                regmap_field_clear_bits(scodec->reg_dac_fifoc,
 634                                        BIT(SUN4I_CODEC_DAC_FIFOC_TX_FIFO_MODE));
 635
 636                scodec->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
 637        } else {
 638                regmap_field_clear_bits(scodec->reg_dac_fifoc,
 639                                        BIT(SUN4I_CODEC_DAC_FIFOC_TX_SAMPLE_BITS));
 640
 641                /* Set TX FIFO mode to repeat the MSB */
 642                regmap_field_set_bits(scodec->reg_dac_fifoc,
 643                                      BIT(SUN4I_CODEC_DAC_FIFOC_TX_FIFO_MODE));
 644
 645                scodec->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
 646        }
 647
 648        return 0;
 649}
 650
 651static int sun4i_codec_hw_params(struct snd_pcm_substream *substream,
 652                                 struct snd_pcm_hw_params *params,
 653                                 struct snd_soc_dai *dai)
 654{
 655        struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
 656        struct sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card);
 657        unsigned long clk_freq;
 658        int ret, hwrate;
 659
 660        clk_freq = sun4i_codec_get_mod_freq(params);
 661        if (!clk_freq)
 662                return -EINVAL;
 663
 664        ret = clk_set_rate(scodec->clk_module, clk_freq);
 665        if (ret)
 666                return ret;
 667
 668        hwrate = sun4i_codec_get_hw_rate(params);
 669        if (hwrate < 0)
 670                return hwrate;
 671
 672        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 673                return sun4i_codec_hw_params_playback(scodec, params,
 674                                                      hwrate);
 675
 676        return sun4i_codec_hw_params_capture(scodec, params,
 677                                             hwrate);
 678}
 679
 680static int sun4i_codec_startup(struct snd_pcm_substream *substream,
 681                               struct snd_soc_dai *dai)
 682{
 683        struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
 684        struct sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card);
 685
 686        /*
 687         * Stop issuing DRQ when we have room for less than 16 samples
 688         * in our TX FIFO
 689         */
 690        regmap_field_set_bits(scodec->reg_dac_fifoc,
 691                              3 << SUN4I_CODEC_DAC_FIFOC_DRQ_CLR_CNT);
 692
 693        return clk_prepare_enable(scodec->clk_module);
 694}
 695
 696static void sun4i_codec_shutdown(struct snd_pcm_substream *substream,
 697                                 struct snd_soc_dai *dai)
 698{
 699        struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
 700        struct sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card);
 701
 702        clk_disable_unprepare(scodec->clk_module);
 703}
 704
 705static const struct snd_soc_dai_ops sun4i_codec_dai_ops = {
 706        .startup        = sun4i_codec_startup,
 707        .shutdown       = sun4i_codec_shutdown,
 708        .trigger        = sun4i_codec_trigger,
 709        .hw_params      = sun4i_codec_hw_params,
 710        .prepare        = sun4i_codec_prepare,
 711};
 712
 713#define SUN4I_CODEC_RATES (                     \
 714                SNDRV_PCM_RATE_8000_48000 |     \
 715                SNDRV_PCM_RATE_12000 |          \
 716                SNDRV_PCM_RATE_24000 |          \
 717                SNDRV_PCM_RATE_96000 |          \
 718                SNDRV_PCM_RATE_192000)
 719
 720static struct snd_soc_dai_driver sun4i_codec_dai = {
 721        .name   = "Codec",
 722        .ops    = &sun4i_codec_dai_ops,
 723        .playback = {
 724                .stream_name    = "Codec Playback",
 725                .channels_min   = 1,
 726                .channels_max   = 2,
 727                .rate_min       = 8000,
 728                .rate_max       = 192000,
 729                .rates          = SUN4I_CODEC_RATES,
 730                .formats        = SNDRV_PCM_FMTBIT_S16_LE |
 731                                  SNDRV_PCM_FMTBIT_S32_LE,
 732                .sig_bits       = 24,
 733        },
 734        .capture = {
 735                .stream_name    = "Codec Capture",
 736                .channels_min   = 1,
 737                .channels_max   = 2,
 738                .rate_min       = 8000,
 739                .rate_max       = 48000,
 740                .rates          = SUN4I_CODEC_RATES,
 741                .formats        = SNDRV_PCM_FMTBIT_S16_LE |
 742                                  SNDRV_PCM_FMTBIT_S32_LE,
 743                .sig_bits       = 24,
 744        },
 745};
 746
 747/*** sun4i Codec ***/
 748static const struct snd_kcontrol_new sun4i_codec_pa_mute =
 749        SOC_DAPM_SINGLE("Switch", SUN4I_CODEC_DAC_ACTL,
 750                        SUN4I_CODEC_DAC_ACTL_PA_MUTE, 1, 0);
 751
 752static DECLARE_TLV_DB_SCALE(sun4i_codec_pa_volume_scale, -6300, 100, 1);
 753static DECLARE_TLV_DB_SCALE(sun4i_codec_linein_loopback_gain_scale, -150, 150,
 754                            0);
 755static DECLARE_TLV_DB_SCALE(sun4i_codec_linein_preamp_gain_scale, -1200, 300,
 756                            0);
 757static DECLARE_TLV_DB_SCALE(sun4i_codec_fmin_loopback_gain_scale, -450, 150,
 758                            0);
 759static DECLARE_TLV_DB_SCALE(sun4i_codec_micin_loopback_gain_scale, -450, 150,
 760                            0);
 761static DECLARE_TLV_DB_RANGE(sun4i_codec_micin_preamp_gain_scale,
 762                            0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
 763                            1, 7, TLV_DB_SCALE_ITEM(3500, 300, 0));
 764static DECLARE_TLV_DB_RANGE(sun7i_codec_micin_preamp_gain_scale,
 765                            0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
 766                            1, 7, TLV_DB_SCALE_ITEM(2400, 300, 0));
 767
 768static const struct snd_kcontrol_new sun4i_codec_controls[] = {
 769        SOC_SINGLE_TLV("Power Amplifier Volume", SUN4I_CODEC_DAC_ACTL,
 770                       SUN4I_CODEC_DAC_ACTL_PA_VOL, 0x3F, 0,
 771                       sun4i_codec_pa_volume_scale),
 772        SOC_SINGLE_TLV("Line Playback Volume", SUN4I_CODEC_DAC_ACTL,
 773                       SUN4I_CODEC_DAC_ACTL_LNG, 1, 0,
 774                       sun4i_codec_linein_loopback_gain_scale),
 775        SOC_SINGLE_TLV("Line Boost Volume", SUN4I_CODEC_ADC_ACTL,
 776                       SUN4I_CODEC_ADC_ACTL_LNPREG, 7, 0,
 777                       sun4i_codec_linein_preamp_gain_scale),
 778        SOC_SINGLE_TLV("FM Playback Volume", SUN4I_CODEC_DAC_ACTL,
 779                       SUN4I_CODEC_DAC_ACTL_FMG, 3, 0,
 780                       sun4i_codec_fmin_loopback_gain_scale),
 781        SOC_SINGLE_TLV("Mic Playback Volume", SUN4I_CODEC_DAC_ACTL,
 782                       SUN4I_CODEC_DAC_ACTL_MICG, 7, 0,
 783                       sun4i_codec_micin_loopback_gain_scale),
 784        SOC_SINGLE_TLV("Mic1 Boost Volume", SUN4I_CODEC_ADC_ACTL,
 785                       SUN4I_CODEC_ADC_ACTL_PREG1, 3, 0,
 786                       sun4i_codec_micin_preamp_gain_scale),
 787        SOC_SINGLE_TLV("Mic2 Boost Volume", SUN4I_CODEC_ADC_ACTL,
 788                       SUN4I_CODEC_ADC_ACTL_PREG2, 3, 0,
 789                       sun4i_codec_micin_preamp_gain_scale),
 790};
 791
 792static const struct snd_kcontrol_new sun7i_codec_controls[] = {
 793        SOC_SINGLE_TLV("Power Amplifier Volume", SUN4I_CODEC_DAC_ACTL,
 794                       SUN4I_CODEC_DAC_ACTL_PA_VOL, 0x3F, 0,
 795                       sun4i_codec_pa_volume_scale),
 796        SOC_SINGLE_TLV("Line Playback Volume", SUN4I_CODEC_DAC_ACTL,
 797                       SUN4I_CODEC_DAC_ACTL_LNG, 1, 0,
 798                       sun4i_codec_linein_loopback_gain_scale),
 799        SOC_SINGLE_TLV("Line Boost Volume", SUN4I_CODEC_ADC_ACTL,
 800                       SUN4I_CODEC_ADC_ACTL_LNPREG, 7, 0,
 801                       sun4i_codec_linein_preamp_gain_scale),
 802        SOC_SINGLE_TLV("FM Playback Volume", SUN4I_CODEC_DAC_ACTL,
 803                       SUN4I_CODEC_DAC_ACTL_FMG, 3, 0,
 804                       sun4i_codec_fmin_loopback_gain_scale),
 805        SOC_SINGLE_TLV("Mic Playback Volume", SUN4I_CODEC_DAC_ACTL,
 806                       SUN4I_CODEC_DAC_ACTL_MICG, 7, 0,
 807                       sun4i_codec_micin_loopback_gain_scale),
 808        SOC_SINGLE_TLV("Mic1 Boost Volume", SUN7I_CODEC_AC_MIC_PHONE_CAL,
 809                       SUN7I_CODEC_AC_MIC_PHONE_CAL_PREG1, 7, 0,
 810                       sun7i_codec_micin_preamp_gain_scale),
 811        SOC_SINGLE_TLV("Mic2 Boost Volume", SUN7I_CODEC_AC_MIC_PHONE_CAL,
 812                       SUN7I_CODEC_AC_MIC_PHONE_CAL_PREG2, 7, 0,
 813                       sun7i_codec_micin_preamp_gain_scale),
 814};
 815
 816static const struct snd_kcontrol_new sun4i_codec_mixer_controls[] = {
 817        SOC_DAPM_SINGLE("Left Mixer Left DAC Playback Switch",
 818                        SUN4I_CODEC_DAC_ACTL, SUN4I_CODEC_DAC_ACTL_LDACLMIXS,
 819                        1, 0),
 820        SOC_DAPM_SINGLE("Right Mixer Right DAC Playback Switch",
 821                        SUN4I_CODEC_DAC_ACTL, SUN4I_CODEC_DAC_ACTL_RDACRMIXS,
 822                        1, 0),
 823        SOC_DAPM_SINGLE("Right Mixer Left DAC Playback Switch",
 824                        SUN4I_CODEC_DAC_ACTL,
 825                        SUN4I_CODEC_DAC_ACTL_LDACRMIXS, 1, 0),
 826        SOC_DAPM_DOUBLE("Line Playback Switch", SUN4I_CODEC_DAC_ACTL,
 827                        SUN4I_CODEC_DAC_ACTL_LLNS,
 828                        SUN4I_CODEC_DAC_ACTL_RLNS, 1, 0),
 829        SOC_DAPM_DOUBLE("FM Playback Switch", SUN4I_CODEC_DAC_ACTL,
 830                        SUN4I_CODEC_DAC_ACTL_LFMS,
 831                        SUN4I_CODEC_DAC_ACTL_RFMS, 1, 0),
 832        SOC_DAPM_DOUBLE("Mic1 Playback Switch", SUN4I_CODEC_DAC_ACTL,
 833                        SUN4I_CODEC_DAC_ACTL_MIC1LS,
 834                        SUN4I_CODEC_DAC_ACTL_MIC1RS, 1, 0),
 835        SOC_DAPM_DOUBLE("Mic2 Playback Switch", SUN4I_CODEC_DAC_ACTL,
 836                        SUN4I_CODEC_DAC_ACTL_MIC2LS,
 837                        SUN4I_CODEC_DAC_ACTL_MIC2RS, 1, 0),
 838};
 839
 840static const struct snd_kcontrol_new sun4i_codec_pa_mixer_controls[] = {
 841        SOC_DAPM_SINGLE("DAC Playback Switch", SUN4I_CODEC_DAC_ACTL,
 842                        SUN4I_CODEC_DAC_ACTL_DACPAS, 1, 0),
 843        SOC_DAPM_SINGLE("Mixer Playback Switch", SUN4I_CODEC_DAC_ACTL,
 844                        SUN4I_CODEC_DAC_ACTL_MIXPAS, 1, 0),
 845};
 846
 847static const struct snd_soc_dapm_widget sun4i_codec_codec_dapm_widgets[] = {
 848        /* Digital parts of the ADCs */
 849        SND_SOC_DAPM_SUPPLY("ADC", SUN4I_CODEC_ADC_FIFOC,
 850                            SUN4I_CODEC_ADC_FIFOC_EN_AD, 0,
 851                            NULL, 0),
 852
 853        /* Digital parts of the DACs */
 854        SND_SOC_DAPM_SUPPLY("DAC", SUN4I_CODEC_DAC_DPC,
 855                            SUN4I_CODEC_DAC_DPC_EN_DA, 0,
 856                            NULL, 0),
 857
 858        /* Analog parts of the ADCs */
 859        SND_SOC_DAPM_ADC("Left ADC", "Codec Capture", SUN4I_CODEC_ADC_ACTL,
 860                         SUN4I_CODEC_ADC_ACTL_ADC_L_EN, 0),
 861        SND_SOC_DAPM_ADC("Right ADC", "Codec Capture", SUN4I_CODEC_ADC_ACTL,
 862                         SUN4I_CODEC_ADC_ACTL_ADC_R_EN, 0),
 863
 864        /* Analog parts of the DACs */
 865        SND_SOC_DAPM_DAC("Left DAC", "Codec Playback", SUN4I_CODEC_DAC_ACTL,
 866                         SUN4I_CODEC_DAC_ACTL_DACAENL, 0),
 867        SND_SOC_DAPM_DAC("Right DAC", "Codec Playback", SUN4I_CODEC_DAC_ACTL,
 868                         SUN4I_CODEC_DAC_ACTL_DACAENR, 0),
 869
 870        /* Mixers */
 871        SND_SOC_DAPM_MIXER("Left Mixer", SND_SOC_NOPM, 0, 0,
 872                           sun4i_codec_mixer_controls,
 873                           ARRAY_SIZE(sun4i_codec_mixer_controls)),
 874        SND_SOC_DAPM_MIXER("Right Mixer", SND_SOC_NOPM, 0, 0,
 875                           sun4i_codec_mixer_controls,
 876                           ARRAY_SIZE(sun4i_codec_mixer_controls)),
 877
 878        /* Global Mixer Enable */
 879        SND_SOC_DAPM_SUPPLY("Mixer Enable", SUN4I_CODEC_DAC_ACTL,
 880                            SUN4I_CODEC_DAC_ACTL_MIXEN, 0, NULL, 0),
 881
 882        /* VMIC */
 883        SND_SOC_DAPM_SUPPLY("VMIC", SUN4I_CODEC_ADC_ACTL,
 884                            SUN4I_CODEC_ADC_ACTL_VMICEN, 0, NULL, 0),
 885
 886        /* Mic Pre-Amplifiers */
 887        SND_SOC_DAPM_PGA("MIC1 Pre-Amplifier", SUN4I_CODEC_ADC_ACTL,
 888                         SUN4I_CODEC_ADC_ACTL_PREG1EN, 0, NULL, 0),
 889        SND_SOC_DAPM_PGA("MIC2 Pre-Amplifier", SUN4I_CODEC_ADC_ACTL,
 890                         SUN4I_CODEC_ADC_ACTL_PREG2EN, 0, NULL, 0),
 891
 892        /* Power Amplifier */
 893        SND_SOC_DAPM_MIXER("Power Amplifier", SUN4I_CODEC_ADC_ACTL,
 894                           SUN4I_CODEC_ADC_ACTL_PA_EN, 0,
 895                           sun4i_codec_pa_mixer_controls,
 896                           ARRAY_SIZE(sun4i_codec_pa_mixer_controls)),
 897        SND_SOC_DAPM_SWITCH("Power Amplifier Mute", SND_SOC_NOPM, 0, 0,
 898                            &sun4i_codec_pa_mute),
 899
 900        SND_SOC_DAPM_INPUT("Line Right"),
 901        SND_SOC_DAPM_INPUT("Line Left"),
 902        SND_SOC_DAPM_INPUT("FM Right"),
 903        SND_SOC_DAPM_INPUT("FM Left"),
 904        SND_SOC_DAPM_INPUT("Mic1"),
 905        SND_SOC_DAPM_INPUT("Mic2"),
 906
 907        SND_SOC_DAPM_OUTPUT("HP Right"),
 908        SND_SOC_DAPM_OUTPUT("HP Left"),
 909};
 910
 911static const struct snd_soc_dapm_route sun4i_codec_codec_dapm_routes[] = {
 912        /* Left ADC / DAC Routes */
 913        { "Left ADC", NULL, "ADC" },
 914        { "Left DAC", NULL, "DAC" },
 915
 916        /* Right ADC / DAC Routes */
 917        { "Right ADC", NULL, "ADC" },
 918        { "Right DAC", NULL, "DAC" },
 919
 920        /* Right Mixer Routes */
 921        { "Right Mixer", NULL, "Mixer Enable" },
 922        { "Right Mixer", "Right Mixer Left DAC Playback Switch", "Left DAC" },
 923        { "Right Mixer", "Right Mixer Right DAC Playback Switch", "Right DAC" },
 924        { "Right Mixer", "Line Playback Switch", "Line Right" },
 925        { "Right Mixer", "FM Playback Switch", "FM Right" },
 926        { "Right Mixer", "Mic1 Playback Switch", "MIC1 Pre-Amplifier" },
 927        { "Right Mixer", "Mic2 Playback Switch", "MIC2 Pre-Amplifier" },
 928
 929        /* Left Mixer Routes */
 930        { "Left Mixer", NULL, "Mixer Enable" },
 931        { "Left Mixer", "Left Mixer Left DAC Playback Switch", "Left DAC" },
 932        { "Left Mixer", "Line Playback Switch", "Line Left" },
 933        { "Left Mixer", "FM Playback Switch", "FM Left" },
 934        { "Left Mixer", "Mic1 Playback Switch", "MIC1 Pre-Amplifier" },
 935        { "Left Mixer", "Mic2 Playback Switch", "MIC2 Pre-Amplifier" },
 936
 937        /* Power Amplifier Routes */
 938        { "Power Amplifier", "Mixer Playback Switch", "Left Mixer" },
 939        { "Power Amplifier", "Mixer Playback Switch", "Right Mixer" },
 940        { "Power Amplifier", "DAC Playback Switch", "Left DAC" },
 941        { "Power Amplifier", "DAC Playback Switch", "Right DAC" },
 942
 943        /* Headphone Output Routes */
 944        { "Power Amplifier Mute", "Switch", "Power Amplifier" },
 945        { "HP Right", NULL, "Power Amplifier Mute" },
 946        { "HP Left", NULL, "Power Amplifier Mute" },
 947
 948        /* Mic1 Routes */
 949        { "Left ADC", NULL, "MIC1 Pre-Amplifier" },
 950        { "Right ADC", NULL, "MIC1 Pre-Amplifier" },
 951        { "MIC1 Pre-Amplifier", NULL, "Mic1"},
 952        { "Mic1", NULL, "VMIC" },
 953
 954        /* Mic2 Routes */
 955        { "Left ADC", NULL, "MIC2 Pre-Amplifier" },
 956        { "Right ADC", NULL, "MIC2 Pre-Amplifier" },
 957        { "MIC2 Pre-Amplifier", NULL, "Mic2"},
 958        { "Mic2", NULL, "VMIC" },
 959};
 960
 961static const struct snd_soc_component_driver sun4i_codec_codec = {
 962        .controls               = sun4i_codec_controls,
 963        .num_controls           = ARRAY_SIZE(sun4i_codec_controls),
 964        .dapm_widgets           = sun4i_codec_codec_dapm_widgets,
 965        .num_dapm_widgets       = ARRAY_SIZE(sun4i_codec_codec_dapm_widgets),
 966        .dapm_routes            = sun4i_codec_codec_dapm_routes,
 967        .num_dapm_routes        = ARRAY_SIZE(sun4i_codec_codec_dapm_routes),
 968        .idle_bias_on           = 1,
 969        .use_pmdown_time        = 1,
 970        .endianness             = 1,
 971};
 972
 973static const struct snd_soc_component_driver sun7i_codec_codec = {
 974        .controls               = sun7i_codec_controls,
 975        .num_controls           = ARRAY_SIZE(sun7i_codec_controls),
 976        .dapm_widgets           = sun4i_codec_codec_dapm_widgets,
 977        .num_dapm_widgets       = ARRAY_SIZE(sun4i_codec_codec_dapm_widgets),
 978        .dapm_routes            = sun4i_codec_codec_dapm_routes,
 979        .num_dapm_routes        = ARRAY_SIZE(sun4i_codec_codec_dapm_routes),
 980        .idle_bias_on           = 1,
 981        .use_pmdown_time        = 1,
 982        .endianness             = 1,
 983};
 984
 985/*** sun6i Codec ***/
 986
 987/* mixer controls */
 988static const struct snd_kcontrol_new sun6i_codec_mixer_controls[] = {
 989        SOC_DAPM_DOUBLE("DAC Playback Switch",
 990                        SUN6I_CODEC_OM_DACA_CTRL,
 991                        SUN6I_CODEC_OM_DACA_CTRL_LMIX_DACL,
 992                        SUN6I_CODEC_OM_DACA_CTRL_RMIX_DACR, 1, 0),
 993        SOC_DAPM_DOUBLE("DAC Reversed Playback Switch",
 994                        SUN6I_CODEC_OM_DACA_CTRL,
 995                        SUN6I_CODEC_OM_DACA_CTRL_LMIX_DACR,
 996                        SUN6I_CODEC_OM_DACA_CTRL_RMIX_DACL, 1, 0),
 997        SOC_DAPM_DOUBLE("Line In Playback Switch",
 998                        SUN6I_CODEC_OM_DACA_CTRL,
 999                        SUN6I_CODEC_OM_DACA_CTRL_LMIX_LINEINL,
1000                        SUN6I_CODEC_OM_DACA_CTRL_RMIX_LINEINR, 1, 0),
1001        SOC_DAPM_DOUBLE("Mic1 Playback Switch",
1002                        SUN6I_CODEC_OM_DACA_CTRL,
1003                        SUN6I_CODEC_OM_DACA_CTRL_LMIX_MIC1,
1004                        SUN6I_CODEC_OM_DACA_CTRL_RMIX_MIC1, 1, 0),
1005        SOC_DAPM_DOUBLE("Mic2 Playback Switch",
1006                        SUN6I_CODEC_OM_DACA_CTRL,
1007                        SUN6I_CODEC_OM_DACA_CTRL_LMIX_MIC2,
1008                        SUN6I_CODEC_OM_DACA_CTRL_RMIX_MIC2, 1, 0),
1009};
1010
1011/* ADC mixer controls */
1012static const struct snd_kcontrol_new sun6i_codec_adc_mixer_controls[] = {
1013        SOC_DAPM_DOUBLE("Mixer Capture Switch",
1014                        SUN6I_CODEC_ADC_ACTL,
1015                        SUN6I_CODEC_ADC_ACTL_LADCMIX_OMIXL,
1016                        SUN6I_CODEC_ADC_ACTL_RADCMIX_OMIXR, 1, 0),
1017        SOC_DAPM_DOUBLE("Mixer Reversed Capture Switch",
1018                        SUN6I_CODEC_ADC_ACTL,
1019                        SUN6I_CODEC_ADC_ACTL_LADCMIX_OMIXR,
1020                        SUN6I_CODEC_ADC_ACTL_RADCMIX_OMIXL, 1, 0),
1021        SOC_DAPM_DOUBLE("Line In Capture Switch",
1022                        SUN6I_CODEC_ADC_ACTL,
1023                        SUN6I_CODEC_ADC_ACTL_LADCMIX_LINEINL,
1024                        SUN6I_CODEC_ADC_ACTL_RADCMIX_LINEINR, 1, 0),
1025        SOC_DAPM_DOUBLE("Mic1 Capture Switch",
1026                        SUN6I_CODEC_ADC_ACTL,
1027                        SUN6I_CODEC_ADC_ACTL_LADCMIX_MIC1,
1028                        SUN6I_CODEC_ADC_ACTL_RADCMIX_MIC1, 1, 0),
1029        SOC_DAPM_DOUBLE("Mic2 Capture Switch",
1030                        SUN6I_CODEC_ADC_ACTL,
1031                        SUN6I_CODEC_ADC_ACTL_LADCMIX_MIC2,
1032                        SUN6I_CODEC_ADC_ACTL_RADCMIX_MIC2, 1, 0),
1033};
1034
1035/* headphone controls */
1036static const char * const sun6i_codec_hp_src_enum_text[] = {
1037        "DAC", "Mixer",
1038};
1039
1040static SOC_ENUM_DOUBLE_DECL(sun6i_codec_hp_src_enum,
1041                            SUN6I_CODEC_OM_DACA_CTRL,
1042                            SUN6I_CODEC_OM_DACA_CTRL_LHPIS,
1043                            SUN6I_CODEC_OM_DACA_CTRL_RHPIS,
1044                            sun6i_codec_hp_src_enum_text);
1045
1046static const struct snd_kcontrol_new sun6i_codec_hp_src[] = {
1047        SOC_DAPM_ENUM("Headphone Source Playback Route",
1048                      sun6i_codec_hp_src_enum),
1049};
1050
1051/* microphone controls */
1052static const char * const sun6i_codec_mic2_src_enum_text[] = {
1053        "Mic2", "Mic3",
1054};
1055
1056static SOC_ENUM_SINGLE_DECL(sun6i_codec_mic2_src_enum,
1057                            SUN6I_CODEC_MIC_CTRL,
1058                            SUN6I_CODEC_MIC_CTRL_MIC2SLT,
1059                            sun6i_codec_mic2_src_enum_text);
1060
1061static const struct snd_kcontrol_new sun6i_codec_mic2_src[] = {
1062        SOC_DAPM_ENUM("Mic2 Amplifier Source Route",
1063                      sun6i_codec_mic2_src_enum),
1064};
1065
1066/* line out controls */
1067static const char * const sun6i_codec_lineout_src_enum_text[] = {
1068        "Stereo", "Mono Differential",
1069};
1070
1071static SOC_ENUM_DOUBLE_DECL(sun6i_codec_lineout_src_enum,
1072                            SUN6I_CODEC_MIC_CTRL,
1073                            SUN6I_CODEC_MIC_CTRL_LINEOUTLSRC,
1074                            SUN6I_CODEC_MIC_CTRL_LINEOUTRSRC,
1075                            sun6i_codec_lineout_src_enum_text);
1076
1077static const struct snd_kcontrol_new sun6i_codec_lineout_src[] = {
1078        SOC_DAPM_ENUM("Line Out Source Playback Route",
1079                      sun6i_codec_lineout_src_enum),
1080};
1081
1082/* volume / mute controls */
1083static const DECLARE_TLV_DB_SCALE(sun6i_codec_dvol_scale, -7308, 116, 0);
1084static const DECLARE_TLV_DB_SCALE(sun6i_codec_hp_vol_scale, -6300, 100, 1);
1085static const DECLARE_TLV_DB_SCALE(sun6i_codec_out_mixer_pregain_scale,
1086                                  -450, 150, 0);
1087static const DECLARE_TLV_DB_RANGE(sun6i_codec_lineout_vol_scale,
1088        0, 1, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1),
1089        2, 31, TLV_DB_SCALE_ITEM(-4350, 150, 0),
1090);
1091static const DECLARE_TLV_DB_RANGE(sun6i_codec_mic_gain_scale,
1092        0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
1093        1, 7, TLV_DB_SCALE_ITEM(2400, 300, 0),
1094);
1095
1096static const struct snd_kcontrol_new sun6i_codec_codec_widgets[] = {
1097        SOC_SINGLE_TLV("DAC Playback Volume", SUN4I_CODEC_DAC_DPC,
1098                       SUN4I_CODEC_DAC_DPC_DVOL, 0x3f, 1,
1099                       sun6i_codec_dvol_scale),
1100        SOC_SINGLE_TLV("Headphone Playback Volume",
1101                       SUN6I_CODEC_OM_DACA_CTRL,
1102                       SUN6I_CODEC_OM_DACA_CTRL_HPVOL, 0x3f, 0,
1103                       sun6i_codec_hp_vol_scale),
1104        SOC_SINGLE_TLV("Line Out Playback Volume",
1105                       SUN6I_CODEC_MIC_CTRL,
1106                       SUN6I_CODEC_MIC_CTRL_LINEOUTVC, 0x1f, 0,
1107                       sun6i_codec_lineout_vol_scale),
1108        SOC_DOUBLE("Headphone Playback Switch",
1109                   SUN6I_CODEC_OM_DACA_CTRL,
1110                   SUN6I_CODEC_OM_DACA_CTRL_LHPPAMUTE,
1111                   SUN6I_CODEC_OM_DACA_CTRL_RHPPAMUTE, 1, 0),
1112        SOC_DOUBLE("Line Out Playback Switch",
1113                   SUN6I_CODEC_MIC_CTRL,
1114                   SUN6I_CODEC_MIC_CTRL_LINEOUTLEN,
1115                   SUN6I_CODEC_MIC_CTRL_LINEOUTREN, 1, 0),
1116        /* Mixer pre-gains */
1117        SOC_SINGLE_TLV("Line In Playback Volume",
1118                       SUN6I_CODEC_OM_PA_CTRL, SUN6I_CODEC_OM_PA_CTRL_LINEING,
1119                       0x7, 0, sun6i_codec_out_mixer_pregain_scale),
1120        SOC_SINGLE_TLV("Mic1 Playback Volume",
1121                       SUN6I_CODEC_OM_PA_CTRL, SUN6I_CODEC_OM_PA_CTRL_MIC1G,
1122                       0x7, 0, sun6i_codec_out_mixer_pregain_scale),
1123        SOC_SINGLE_TLV("Mic2 Playback Volume",
1124                       SUN6I_CODEC_OM_PA_CTRL, SUN6I_CODEC_OM_PA_CTRL_MIC2G,
1125                       0x7, 0, sun6i_codec_out_mixer_pregain_scale),
1126
1127        /* Microphone Amp boost gains */
1128        SOC_SINGLE_TLV("Mic1 Boost Volume", SUN6I_CODEC_MIC_CTRL,
1129                       SUN6I_CODEC_MIC_CTRL_MIC1BOOST, 0x7, 0,
1130                       sun6i_codec_mic_gain_scale),
1131        SOC_SINGLE_TLV("Mic2 Boost Volume", SUN6I_CODEC_MIC_CTRL,
1132                       SUN6I_CODEC_MIC_CTRL_MIC2BOOST, 0x7, 0,
1133                       sun6i_codec_mic_gain_scale),
1134        SOC_DOUBLE_TLV("ADC Capture Volume",
1135                       SUN6I_CODEC_ADC_ACTL, SUN6I_CODEC_ADC_ACTL_ADCLG,
1136                       SUN6I_CODEC_ADC_ACTL_ADCRG, 0x7, 0,
1137                       sun6i_codec_out_mixer_pregain_scale),
1138};
1139
1140static const struct snd_soc_dapm_widget sun6i_codec_codec_dapm_widgets[] = {
1141        /* Microphone inputs */
1142        SND_SOC_DAPM_INPUT("MIC1"),
1143        SND_SOC_DAPM_INPUT("MIC2"),
1144        SND_SOC_DAPM_INPUT("MIC3"),
1145
1146        /* Microphone Bias */
1147        SND_SOC_DAPM_SUPPLY("HBIAS", SUN6I_CODEC_MIC_CTRL,
1148                            SUN6I_CODEC_MIC_CTRL_HBIASEN, 0, NULL, 0),
1149        SND_SOC_DAPM_SUPPLY("MBIAS", SUN6I_CODEC_MIC_CTRL,
1150                            SUN6I_CODEC_MIC_CTRL_MBIASEN, 0, NULL, 0),
1151
1152        /* Mic input path */
1153        SND_SOC_DAPM_MUX("Mic2 Amplifier Source Route",
1154                         SND_SOC_NOPM, 0, 0, sun6i_codec_mic2_src),
1155        SND_SOC_DAPM_PGA("Mic1 Amplifier", SUN6I_CODEC_MIC_CTRL,
1156                         SUN6I_CODEC_MIC_CTRL_MIC1AMPEN, 0, NULL, 0),
1157        SND_SOC_DAPM_PGA("Mic2 Amplifier", SUN6I_CODEC_MIC_CTRL,
1158                         SUN6I_CODEC_MIC_CTRL_MIC2AMPEN, 0, NULL, 0),
1159
1160        /* Line In */
1161        SND_SOC_DAPM_INPUT("LINEIN"),
1162
1163        /* Digital parts of the ADCs */
1164        SND_SOC_DAPM_SUPPLY("ADC Enable", SUN6I_CODEC_ADC_FIFOC,
1165                            SUN6I_CODEC_ADC_FIFOC_EN_AD, 0,
1166                            NULL, 0),
1167
1168        /* Analog parts of the ADCs */
1169        SND_SOC_DAPM_ADC("Left ADC", "Codec Capture", SUN6I_CODEC_ADC_ACTL,
1170                         SUN6I_CODEC_ADC_ACTL_ADCLEN, 0),
1171        SND_SOC_DAPM_ADC("Right ADC", "Codec Capture", SUN6I_CODEC_ADC_ACTL,
1172                         SUN6I_CODEC_ADC_ACTL_ADCREN, 0),
1173
1174        /* ADC Mixers */
1175        SOC_MIXER_ARRAY("Left ADC Mixer", SND_SOC_NOPM, 0, 0,
1176                        sun6i_codec_adc_mixer_controls),
1177        SOC_MIXER_ARRAY("Right ADC Mixer", SND_SOC_NOPM, 0, 0,
1178                        sun6i_codec_adc_mixer_controls),
1179
1180        /* Digital parts of the DACs */
1181        SND_SOC_DAPM_SUPPLY("DAC Enable", SUN4I_CODEC_DAC_DPC,
1182                            SUN4I_CODEC_DAC_DPC_EN_DA, 0,
1183                            NULL, 0),
1184
1185        /* Analog parts of the DACs */
1186        SND_SOC_DAPM_DAC("Left DAC", "Codec Playback",
1187                         SUN6I_CODEC_OM_DACA_CTRL,
1188                         SUN6I_CODEC_OM_DACA_CTRL_DACALEN, 0),
1189        SND_SOC_DAPM_DAC("Right DAC", "Codec Playback",
1190                         SUN6I_CODEC_OM_DACA_CTRL,
1191                         SUN6I_CODEC_OM_DACA_CTRL_DACAREN, 0),
1192
1193        /* Mixers */
1194        SOC_MIXER_ARRAY("Left Mixer", SUN6I_CODEC_OM_DACA_CTRL,
1195                        SUN6I_CODEC_OM_DACA_CTRL_LMIXEN, 0,
1196                        sun6i_codec_mixer_controls),
1197        SOC_MIXER_ARRAY("Right Mixer", SUN6I_CODEC_OM_DACA_CTRL,
1198                        SUN6I_CODEC_OM_DACA_CTRL_RMIXEN, 0,
1199                        sun6i_codec_mixer_controls),
1200
1201        /* Headphone output path */
1202        SND_SOC_DAPM_MUX("Headphone Source Playback Route",
1203                         SND_SOC_NOPM, 0, 0, sun6i_codec_hp_src),
1204        SND_SOC_DAPM_OUT_DRV("Headphone Amp", SUN6I_CODEC_OM_PA_CTRL,
1205                             SUN6I_CODEC_OM_PA_CTRL_HPPAEN, 0, NULL, 0),
1206        SND_SOC_DAPM_SUPPLY("HPCOM Protection", SUN6I_CODEC_OM_PA_CTRL,
1207                            SUN6I_CODEC_OM_PA_CTRL_COMPTEN, 0, NULL, 0),
1208        SND_SOC_DAPM_REG(snd_soc_dapm_supply, "HPCOM", SUN6I_CODEC_OM_PA_CTRL,
1209                         SUN6I_CODEC_OM_PA_CTRL_HPCOM_CTL, 0x3, 0x3, 0),
1210        SND_SOC_DAPM_OUTPUT("HP"),
1211
1212        /* Line Out path */
1213        SND_SOC_DAPM_MUX("Line Out Source Playback Route",
1214                         SND_SOC_NOPM, 0, 0, sun6i_codec_lineout_src),
1215        SND_SOC_DAPM_OUTPUT("LINEOUT"),
1216};
1217
1218static const struct snd_soc_dapm_route sun6i_codec_codec_dapm_routes[] = {
1219        /* DAC Routes */
1220        { "Left DAC", NULL, "DAC Enable" },
1221        { "Right DAC", NULL, "DAC Enable" },
1222
1223        /* Microphone Routes */
1224        { "Mic1 Amplifier", NULL, "MIC1"},
1225        { "Mic2 Amplifier Source Route", "Mic2", "MIC2" },
1226        { "Mic2 Amplifier Source Route", "Mic3", "MIC3" },
1227        { "Mic2 Amplifier", NULL, "Mic2 Amplifier Source Route"},
1228
1229        /* Left Mixer Routes */
1230        { "Left Mixer", "DAC Playback Switch", "Left DAC" },
1231        { "Left Mixer", "DAC Reversed Playback Switch", "Right DAC" },
1232        { "Left Mixer", "Line In Playback Switch", "LINEIN" },
1233        { "Left Mixer", "Mic1 Playback Switch", "Mic1 Amplifier" },
1234        { "Left Mixer", "Mic2 Playback Switch", "Mic2 Amplifier" },
1235
1236        /* Right Mixer Routes */
1237        { "Right Mixer", "DAC Playback Switch", "Right DAC" },
1238        { "Right Mixer", "DAC Reversed Playback Switch", "Left DAC" },
1239        { "Right Mixer", "Line In Playback Switch", "LINEIN" },
1240        { "Right Mixer", "Mic1 Playback Switch", "Mic1 Amplifier" },
1241        { "Right Mixer", "Mic2 Playback Switch", "Mic2 Amplifier" },
1242
1243        /* Left ADC Mixer Routes */
1244        { "Left ADC Mixer", "Mixer Capture Switch", "Left Mixer" },
1245        { "Left ADC Mixer", "Mixer Reversed Capture Switch", "Right Mixer" },
1246        { "Left ADC Mixer", "Line In Capture Switch", "LINEIN" },
1247        { "Left ADC Mixer", "Mic1 Capture Switch", "Mic1 Amplifier" },
1248        { "Left ADC Mixer", "Mic2 Capture Switch", "Mic2 Amplifier" },
1249
1250        /* Right ADC Mixer Routes */
1251        { "Right ADC Mixer", "Mixer Capture Switch", "Right Mixer" },
1252        { "Right ADC Mixer", "Mixer Reversed Capture Switch", "Left Mixer" },
1253        { "Right ADC Mixer", "Line In Capture Switch", "LINEIN" },
1254        { "Right ADC Mixer", "Mic1 Capture Switch", "Mic1 Amplifier" },
1255        { "Right ADC Mixer", "Mic2 Capture Switch", "Mic2 Amplifier" },
1256
1257        /* Headphone Routes */
1258        { "Headphone Source Playback Route", "DAC", "Left DAC" },
1259        { "Headphone Source Playback Route", "DAC", "Right DAC" },
1260        { "Headphone Source Playback Route", "Mixer", "Left Mixer" },
1261        { "Headphone Source Playback Route", "Mixer", "Right Mixer" },
1262        { "Headphone Amp", NULL, "Headphone Source Playback Route" },
1263        { "HP", NULL, "Headphone Amp" },
1264        { "HPCOM", NULL, "HPCOM Protection" },
1265
1266        /* Line Out Routes */
1267        { "Line Out Source Playback Route", "Stereo", "Left Mixer" },
1268        { "Line Out Source Playback Route", "Stereo", "Right Mixer" },
1269        { "Line Out Source Playback Route", "Mono Differential", "Left Mixer" },
1270        { "Line Out Source Playback Route", "Mono Differential", "Right Mixer" },
1271        { "LINEOUT", NULL, "Line Out Source Playback Route" },
1272
1273        /* ADC Routes */
1274        { "Left ADC", NULL, "ADC Enable" },
1275        { "Right ADC", NULL, "ADC Enable" },
1276        { "Left ADC", NULL, "Left ADC Mixer" },
1277        { "Right ADC", NULL, "Right ADC Mixer" },
1278};
1279
1280static const struct snd_soc_component_driver sun6i_codec_codec = {
1281        .controls               = sun6i_codec_codec_widgets,
1282        .num_controls           = ARRAY_SIZE(sun6i_codec_codec_widgets),
1283        .dapm_widgets           = sun6i_codec_codec_dapm_widgets,
1284        .num_dapm_widgets       = ARRAY_SIZE(sun6i_codec_codec_dapm_widgets),
1285        .dapm_routes            = sun6i_codec_codec_dapm_routes,
1286        .num_dapm_routes        = ARRAY_SIZE(sun6i_codec_codec_dapm_routes),
1287        .idle_bias_on           = 1,
1288        .use_pmdown_time        = 1,
1289        .endianness             = 1,
1290};
1291
1292/* sun8i A23 codec */
1293static const struct snd_kcontrol_new sun8i_a23_codec_codec_controls[] = {
1294        SOC_SINGLE_TLV("DAC Playback Volume", SUN4I_CODEC_DAC_DPC,
1295                       SUN4I_CODEC_DAC_DPC_DVOL, 0x3f, 1,
1296                       sun6i_codec_dvol_scale),
1297};
1298
1299static const struct snd_soc_dapm_widget sun8i_a23_codec_codec_widgets[] = {
1300        /* Digital parts of the ADCs */
1301        SND_SOC_DAPM_SUPPLY("ADC Enable", SUN6I_CODEC_ADC_FIFOC,
1302                            SUN6I_CODEC_ADC_FIFOC_EN_AD, 0, NULL, 0),
1303        /* Digital parts of the DACs */
1304        SND_SOC_DAPM_SUPPLY("DAC Enable", SUN4I_CODEC_DAC_DPC,
1305                            SUN4I_CODEC_DAC_DPC_EN_DA, 0, NULL, 0),
1306
1307};
1308
1309static const struct snd_soc_component_driver sun8i_a23_codec_codec = {
1310        .controls               = sun8i_a23_codec_codec_controls,
1311        .num_controls           = ARRAY_SIZE(sun8i_a23_codec_codec_controls),
1312        .dapm_widgets           = sun8i_a23_codec_codec_widgets,
1313        .num_dapm_widgets       = ARRAY_SIZE(sun8i_a23_codec_codec_widgets),
1314        .idle_bias_on           = 1,
1315        .use_pmdown_time        = 1,
1316        .endianness             = 1,
1317};
1318
1319/*suniv F1C100s codec */
1320
1321/* headphone controls */
1322static const char * const suniv_codec_hp_src_enum_text[] = {
1323        "DAC", "Mixer",
1324};
1325
1326static SOC_ENUM_DOUBLE_DECL(suniv_codec_hp_src_enum,
1327                            SUNIV_CODEC_OM_DACA_CTRL,
1328                            SUNIV_CODEC_OM_DACA_CTRL_LHPIS,
1329                            SUNIV_CODEC_OM_DACA_CTRL_RHPIS,
1330                            suniv_codec_hp_src_enum_text);
1331
1332static const struct snd_kcontrol_new suniv_codec_hp_src[] = {
1333        SOC_DAPM_ENUM("Headphone Source Playback Route",
1334                      suniv_codec_hp_src_enum),
1335};
1336
1337/* mixer controls */
1338static const struct snd_kcontrol_new suniv_codec_adc_mixer_controls[] = {
1339        SOC_DAPM_SINGLE("Right Out Capture Switch", SUNIV_CODEC_ADC_ACTL,
1340                        SUNIV_CODEC_ADC_ADCMIX_ROUT, 1, 0),
1341        SOC_DAPM_SINGLE("Left Out Capture Switch", SUNIV_CODEC_ADC_ACTL,
1342                        SUNIV_CODEC_ADC_ADCMIX_LOUT, 1, 0),
1343        SOC_DAPM_SINGLE("Line In Capture Switch", SUNIV_CODEC_ADC_ACTL,
1344                        SUNIV_CODEC_ADC_ADCMIX_LINEIN, 1, 0),
1345        SOC_DAPM_SINGLE("Right FM In Capture Switch", SUNIV_CODEC_ADC_ACTL,
1346                        SUNIV_CODEC_ADC_ADCMIX_FMINR, 1, 0),
1347        SOC_DAPM_SINGLE("Left FM In Capture Switch", SUNIV_CODEC_ADC_ACTL,
1348                        SUNIV_CODEC_ADC_ADCMIX_FMINL, 1, 0),
1349        SOC_DAPM_SINGLE("Mic Capture Switch", SUNIV_CODEC_ADC_ACTL,
1350                        SUNIV_CODEC_ADC_ADCMIX_MIC, 1, 0),
1351};
1352
1353static const struct snd_kcontrol_new suniv_codec_dac_lmixer_controls[] = {
1354        SOC_DAPM_SINGLE("Right DAC Playback Switch", SUNIV_CODEC_OM_DACA_CTRL,
1355                        SUNIV_CODEC_OM_DACA_CTRL_LMIXMUTE_RDAC, 1, 0),
1356        SOC_DAPM_SINGLE("Left DAC Playback Switch", SUNIV_CODEC_OM_DACA_CTRL,
1357                        SUNIV_CODEC_OM_DACA_CTRL_LMIXMUTE_LDAC, 1, 0),
1358        SOC_DAPM_SINGLE("FM In Playback Switch", SUNIV_CODEC_OM_DACA_CTRL,
1359                        SUNIV_CODEC_OM_DACA_CTRL_LMIXMUTE_FMIN, 1, 0),
1360        SOC_DAPM_SINGLE("Line In Playback Switch", SUNIV_CODEC_OM_DACA_CTRL,
1361                        SUNIV_CODEC_OM_DACA_CTRL_LMIXMUTE_LINEIN, 1, 0),
1362        SOC_DAPM_SINGLE("Mic In Playback Switch", SUNIV_CODEC_OM_DACA_CTRL,
1363                        SUNIV_CODEC_OM_DACA_CTRL_LMIXMUTE_MICIN, 1, 0),
1364};
1365
1366static const struct snd_kcontrol_new suniv_codec_dac_rmixer_controls[] = {
1367        SOC_DAPM_SINGLE("Left DAC Playback Switch", SUNIV_CODEC_OM_DACA_CTRL,
1368                        SUNIV_CODEC_OM_DACA_CTRL_RMIXMUTE_LDAC, 1, 0),
1369        SOC_DAPM_SINGLE("Right DAC Playback Switch", SUNIV_CODEC_OM_DACA_CTRL,
1370                        SUNIV_CODEC_OM_DACA_CTRL_RMIXMUTE_RDAC, 1, 0),
1371        SOC_DAPM_SINGLE("FM In Playback Switch", SUNIV_CODEC_OM_DACA_CTRL,
1372                        SUNIV_CODEC_OM_DACA_CTRL_RMIXMUTE_FMIN, 1, 0),
1373        SOC_DAPM_SINGLE("Line In Playback Switch", SUNIV_CODEC_OM_DACA_CTRL,
1374                        SUNIV_CODEC_OM_DACA_CTRL_RMIXMUTE_LINEIN, 1, 0),
1375        SOC_DAPM_SINGLE("Mic In Playback Switch", SUNIV_CODEC_OM_DACA_CTRL,
1376                        SUNIV_CODEC_OM_DACA_CTRL_RMIXMUTE_MICIN, 1, 0),
1377};
1378
1379static const DECLARE_TLV_DB_SCALE(suniv_codec_dvol_scale, -7308, 116, 0);
1380static const DECLARE_TLV_DB_SCALE(suniv_codec_hp_vol_scale, -6300, 100, 1);
1381static const DECLARE_TLV_DB_SCALE(suniv_codec_out_mixer_pregain_scale,
1382                                  -450, 150, 0);
1383
1384static const DECLARE_TLV_DB_RANGE(suniv_codec_mic_gain_scale,
1385        0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
1386        1, 7, TLV_DB_SCALE_ITEM(2400, 300, 0),
1387);
1388
1389static const struct snd_kcontrol_new suniv_codec_codec_widgets[] = {
1390        SOC_SINGLE_TLV("DAC Playback Volume", SUN4I_CODEC_DAC_DPC,
1391                       SUN4I_CODEC_DAC_DPC_DVOL, 0x3f, 1,
1392                       suniv_codec_dvol_scale),
1393        SOC_SINGLE_TLV("Headphone Playback Volume",
1394                       SUNIV_CODEC_OM_DACA_CTRL,
1395                       SUNIV_CODEC_OM_DACA_CTRL_HPVOL, 0x3f, 0,
1396                       suniv_codec_hp_vol_scale),
1397        SOC_DOUBLE("Headphone Playback Switch",
1398                   SUNIV_CODEC_OM_DACA_CTRL,
1399                   SUNIV_CODEC_OM_DACA_CTRL_LHPPAMUTE,
1400                   SUNIV_CODEC_OM_DACA_CTRL_RHPPAMUTE, 1, 0),
1401        SOC_SINGLE_TLV("Line In Playback Volume",
1402                       SUNIV_CODEC_ADC_ACTL, SUNIV_CODEC_ADC_LINEINVOL,
1403                       0x7, 0, suniv_codec_out_mixer_pregain_scale),
1404        SOC_SINGLE_TLV("FM In Playback Volume",
1405                       SUNIV_CODEC_ADC_ACTL, SUNIV_CODEC_ADC_FMINVOL,
1406                       0x7, 0, suniv_codec_out_mixer_pregain_scale),
1407        SOC_SINGLE_TLV("Mic In Playback Volume",
1408                       SUNIV_CODEC_ADC_ACTL, SUNIV_CODEC_ADC_MICG,
1409                       0x7, 0, suniv_codec_out_mixer_pregain_scale),
1410
1411        /* Microphone Amp boost gains */
1412        SOC_SINGLE_TLV("Mic Boost Volume", SUNIV_CODEC_ADC_ACTL,
1413                       SUNIV_CODEC_ADC_MICBOOST, 0x7, 0,
1414                       suniv_codec_mic_gain_scale),
1415        SOC_SINGLE_TLV("ADC Capture Volume",
1416                       SUNIV_CODEC_ADC_ACTL, SUNIV_CODEC_ADC_ADCG,
1417                       0x7, 0, suniv_codec_out_mixer_pregain_scale),
1418};
1419
1420static const struct snd_soc_dapm_widget suniv_codec_codec_dapm_widgets[] = {
1421        /* Microphone inputs */
1422        SND_SOC_DAPM_INPUT("MIC"),
1423
1424        /* Microphone Bias */
1425        /* deleted: HBIAS, MBIAS */
1426
1427        /* Mic input path */
1428        SND_SOC_DAPM_PGA("Mic Amplifier", SUNIV_CODEC_ADC_ACTL,
1429                         SUNIV_CODEC_ADC_MICAMPEN, 0, NULL, 0),
1430
1431        /* Line In */
1432        SND_SOC_DAPM_INPUT("LINEIN"),
1433
1434        /* FM In */
1435        SND_SOC_DAPM_INPUT("FMINR"),
1436        SND_SOC_DAPM_INPUT("FMINL"),
1437
1438        /* Digital parts of the ADCs */
1439        SND_SOC_DAPM_SUPPLY("ADC Enable", SUNIV_CODEC_ADC_FIFOC,
1440                            SUNIV_CODEC_ADC_FIFOC_EN_AD, 0,
1441                            NULL, 0),
1442
1443        /* Analog parts of the ADCs */
1444        SND_SOC_DAPM_ADC("ADC", "Codec Capture", SUNIV_CODEC_ADC_ACTL,
1445                         SUNIV_CODEC_ADC_ADCEN, 0),
1446
1447        /* ADC Mixers */
1448        SOC_MIXER_ARRAY("ADC Mixer", SUNIV_CODEC_ADC_ACTL,
1449                        SND_SOC_NOPM, 0,
1450                        suniv_codec_adc_mixer_controls),
1451
1452        /* Digital parts of the DACs */
1453        SND_SOC_DAPM_SUPPLY("DAC Enable", SUN4I_CODEC_DAC_DPC,
1454                            SUN4I_CODEC_DAC_DPC_EN_DA, 0,
1455                            NULL, 0),
1456
1457        /* Analog parts of the DACs */
1458        SND_SOC_DAPM_DAC("Left DAC", "Codec Playback",
1459                         SUNIV_CODEC_OM_DACA_CTRL,
1460                         SUNIV_CODEC_OM_DACA_CTRL_DACALEN, 0),
1461        SND_SOC_DAPM_DAC("Right DAC", "Codec Playback",
1462                         SUNIV_CODEC_OM_DACA_CTRL,
1463                         SUNIV_CODEC_OM_DACA_CTRL_DACAREN, 0),
1464
1465        /* Mixers */
1466        SOC_MIXER_ARRAY("Left Mixer", SUNIV_CODEC_OM_DACA_CTRL,
1467                        SUNIV_CODEC_OM_DACA_CTRL_LMIXEN, 0,
1468                        suniv_codec_dac_lmixer_controls),
1469        SOC_MIXER_ARRAY("Right Mixer", SUNIV_CODEC_OM_DACA_CTRL,
1470                        SUNIV_CODEC_OM_DACA_CTRL_RMIXEN, 0,
1471                        suniv_codec_dac_rmixer_controls),
1472
1473        /* Headphone output path */
1474        SND_SOC_DAPM_MUX("Headphone Source Playback Route",
1475                         SND_SOC_NOPM, 0, 0, suniv_codec_hp_src),
1476        SND_SOC_DAPM_OUT_DRV("Headphone Amp", SUNIV_CODEC_OM_DACA_CTRL,
1477                             SUNIV_CODEC_OM_DACA_CTRL_HPPAEN, 0, NULL, 0),
1478        SND_SOC_DAPM_SUPPLY("HPCOM Protection", SUNIV_CODEC_OM_DACA_CTRL,
1479                            SUNIV_CODEC_OM_DACA_CTRL_COMPTEN, 0, NULL, 0),
1480        SND_SOC_DAPM_REG(snd_soc_dapm_supply, "HPCOM", SUNIV_CODEC_OM_DACA_CTRL,
1481                         SUNIV_CODEC_OM_DACA_CTRL_HPCOM_CTL, 0x3, 0x3, 0),
1482        SND_SOC_DAPM_OUTPUT("HP"),
1483};
1484
1485static const struct snd_soc_dapm_route suniv_codec_codec_dapm_routes[] = {
1486        /* DAC Routes */
1487        { "Left DAC", NULL, "DAC Enable" },
1488        { "Right DAC", NULL, "DAC Enable" },
1489
1490        /* Microphone Routes */
1491        { "Mic Amplifier", NULL, "MIC"},
1492
1493        /* Left Mixer Routes */
1494        { "Left Mixer", "Right DAC Playback Switch", "Right DAC" },
1495        { "Left Mixer", "Left DAC Playback Switch", "Left DAC" },
1496        { "Left Mixer", "FM In Playback Switch", "FMINL" },
1497        { "Left Mixer", "Line In Playback Switch", "LINEIN" },
1498        { "Left Mixer", "Mic In Playback Switch", "Mic Amplifier" },
1499
1500        /* Right Mixer Routes */
1501        { "Right Mixer", "Left DAC Playback Switch", "Left DAC" },
1502        { "Right Mixer", "Right DAC Playback Switch", "Right DAC" },
1503        { "Right Mixer", "FM In Playback Switch", "FMINR" },
1504        { "Right Mixer", "Line In Playback Switch", "LINEIN" },
1505        { "Right Mixer", "Mic In Playback Switch", "Mic Amplifier" },
1506
1507        /* ADC Mixer Routes */
1508        { "ADC Mixer", "Right Out Capture Switch", "Right Mixer" },
1509        { "ADC Mixer", "Left Out Capture Switch", "Left Mixer" },
1510        { "ADC Mixer", "Line In Capture Switch", "LINEIN" },
1511        { "ADC Mixer", "Right FM In Capture Switch", "FMINR" },
1512        { "ADC Mixer", "Left FM In Capture Switch", "FMINL" },
1513        { "ADC Mixer", "Mic Capture Switch", "Mic Amplifier" },
1514
1515        /* Headphone Routes */
1516        { "Headphone Source Playback Route", "DAC", "Left DAC" },
1517        { "Headphone Source Playback Route", "DAC", "Right DAC" },
1518        { "Headphone Source Playback Route", "Mixer", "Left Mixer" },
1519        { "Headphone Source Playback Route", "Mixer", "Right Mixer" },
1520        { "Headphone Amp", NULL, "Headphone Source Playback Route" },
1521        { "HP", NULL, "Headphone Amp" },
1522        { "HPCOM", NULL, "HPCOM Protection" },
1523
1524        /* ADC Routes */
1525        { "ADC", NULL, "ADC Mixer" },
1526        { "ADC", NULL, "ADC Enable" },
1527};
1528
1529static const struct snd_soc_component_driver suniv_codec_codec = {
1530        .controls               = suniv_codec_codec_widgets,
1531        .num_controls           = ARRAY_SIZE(suniv_codec_codec_widgets),
1532        .dapm_widgets           = suniv_codec_codec_dapm_widgets,
1533        .num_dapm_widgets       = ARRAY_SIZE(suniv_codec_codec_dapm_widgets),
1534        .dapm_routes            = suniv_codec_codec_dapm_routes,
1535        .num_dapm_routes        = ARRAY_SIZE(suniv_codec_codec_dapm_routes),
1536        .idle_bias_on           = 1,
1537        .use_pmdown_time        = 1,
1538        .endianness             = 1,
1539};
1540
1541static const struct snd_soc_component_driver sun4i_codec_component = {
1542        .name                   = "sun4i-codec",
1543        .legacy_dai_naming      = 1,
1544#ifdef CONFIG_DEBUG_FS
1545        .debugfs_prefix         = "cpu",
1546#endif
1547};
1548
1549#define SUN4I_CODEC_FORMATS     (SNDRV_PCM_FMTBIT_S16_LE | \
1550                                 SNDRV_PCM_FMTBIT_S32_LE)
1551
1552static int sun4i_codec_dai_probe(struct snd_soc_dai *dai)
1553{
1554        struct snd_soc_card *card = snd_soc_dai_get_drvdata(dai);
1555        struct sun4i_codec *scodec = snd_soc_card_get_drvdata(card);
1556
1557        snd_soc_dai_init_dma_data(dai, &scodec->playback_dma_data,
1558                                  &scodec->capture_dma_data);
1559
1560        return 0;
1561}
1562
1563static const struct snd_soc_dai_ops dummy_dai_ops = {
1564        .probe  = sun4i_codec_dai_probe,
1565};
1566
1567static struct snd_soc_dai_driver dummy_cpu_dai = {
1568        .name   = "sun4i-codec-cpu-dai",
1569        .playback = {
1570                .stream_name    = "Playback",
1571                .channels_min   = 1,
1572                .channels_max   = 2,
1573                .rates          = SUN4I_CODEC_RATES,
1574                .formats        = SUN4I_CODEC_FORMATS,
1575                .sig_bits       = 24,
1576        },
1577        .capture = {
1578                .stream_name    = "Capture",
1579                .channels_min   = 1,
1580                .channels_max   = 2,
1581                .rates          = SUN4I_CODEC_RATES,
1582                .formats        = SUN4I_CODEC_FORMATS,
1583                .sig_bits       = 24,
1584         },
1585        .ops = &dummy_dai_ops,
1586};
1587
1588static struct snd_soc_jack sun4i_headphone_jack;
1589
1590static struct snd_soc_jack_pin sun4i_headphone_jack_pins[] = {
1591        { .pin = "Headphone", .mask = SND_JACK_HEADPHONE },
1592};
1593
1594static struct snd_soc_jack_gpio sun4i_headphone_jack_gpio = {
1595        .name = "hp-det",
1596        .report = SND_JACK_HEADPHONE,
1597        .debounce_time = 150,
1598};
1599
1600static int sun4i_codec_machine_init(struct snd_soc_pcm_runtime *rtd)
1601{
1602        struct snd_soc_card *card = rtd->card;
1603        struct sun4i_codec *scodec = snd_soc_card_get_drvdata(card);
1604        int ret;
1605
1606        if (scodec->gpio_hp) {
1607                ret = snd_soc_card_jack_new_pins(card, "Headphone Jack",
1608                                                 SND_JACK_HEADPHONE,
1609                                                 &sun4i_headphone_jack,
1610                                                 sun4i_headphone_jack_pins,
1611                                                 ARRAY_SIZE(sun4i_headphone_jack_pins));
1612                if (ret) {
1613                        dev_err(rtd->dev,
1614                                "Headphone jack creation failed: %d\n", ret);
1615                        return ret;
1616                }
1617
1618                sun4i_headphone_jack_gpio.desc = scodec->gpio_hp;
1619                ret = snd_soc_jack_add_gpios(&sun4i_headphone_jack, 1,
1620                                             &sun4i_headphone_jack_gpio);
1621
1622                if (ret) {
1623                        dev_err(rtd->dev, "Headphone GPIO not added: %d\n", ret);
1624                        return ret;
1625                }
1626        }
1627
1628        return 0;
1629}
1630
1631static struct snd_soc_dai_link *sun4i_codec_create_link(struct device *dev,
1632                                                        int *num_links)
1633{
1634        struct snd_soc_dai_link *link = devm_kzalloc(dev, sizeof(*link),
1635                                                     GFP_KERNEL);
1636        struct snd_soc_dai_link_component *dlc = devm_kzalloc(dev,
1637                                                3 * sizeof(*dlc), GFP_KERNEL);
1638        if (!link || !dlc)
1639                return NULL;
1640
1641        link->cpus      = &dlc[0];
1642        link->codecs    = &dlc[1];
1643        link->platforms = &dlc[2];
1644
1645        link->num_cpus          = 1;
1646        link->num_codecs        = 1;
1647        link->num_platforms     = 1;
1648
1649        link->name              = "cdc";
1650        link->stream_name       = "CDC PCM";
1651        link->codecs->dai_name  = "Codec";
1652        link->cpus->dai_name    = dev_name(dev);
1653        link->codecs->name      = dev_name(dev);
1654        link->platforms->name   = dev_name(dev);
1655        link->dai_fmt           = SND_SOC_DAIFMT_I2S;
1656        link->init              = sun4i_codec_machine_init;
1657
1658        *num_links = 1;
1659
1660        return link;
1661};
1662
1663static int sun4i_codec_spk_event(struct snd_soc_dapm_widget *w,
1664                                 struct snd_kcontrol *k, int event)
1665{
1666        struct sun4i_codec *scodec = snd_soc_card_get_drvdata(w->dapm->card);
1667
1668        gpiod_set_value_cansleep(scodec->gpio_pa,
1669                                 !!SND_SOC_DAPM_EVENT_ON(event));
1670
1671        if (SND_SOC_DAPM_EVENT_ON(event)) {
1672                /*
1673                 * Need a delay to wait for DAC to push the data. 700ms seems
1674                 * to be the best compromise not to feel this delay while
1675                 * playing a sound.
1676                 */
1677                msleep(700);
1678        }
1679
1680        return 0;
1681}
1682
1683static const struct snd_soc_dapm_widget sun4i_codec_card_dapm_widgets[] = {
1684        SND_SOC_DAPM_SPK("Speaker", sun4i_codec_spk_event),
1685};
1686
1687static const struct snd_soc_dapm_route sun4i_codec_card_dapm_routes[] = {
1688        { "Speaker", NULL, "HP Right" },
1689        { "Speaker", NULL, "HP Left" },
1690};
1691
1692static struct snd_soc_card *sun4i_codec_create_card(struct device *dev)
1693{
1694        struct snd_soc_card *card;
1695
1696        card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
1697        if (!card)
1698                return ERR_PTR(-ENOMEM);
1699
1700        card->dai_link = sun4i_codec_create_link(dev, &card->num_links);
1701        if (!card->dai_link)
1702                return ERR_PTR(-ENOMEM);
1703
1704        card->dev               = dev;
1705        card->owner             = THIS_MODULE;
1706        card->name              = "sun4i-codec";
1707        card->dapm_widgets      = sun4i_codec_card_dapm_widgets;
1708        card->num_dapm_widgets  = ARRAY_SIZE(sun4i_codec_card_dapm_widgets);
1709        card->dapm_routes       = sun4i_codec_card_dapm_routes;
1710        card->num_dapm_routes   = ARRAY_SIZE(sun4i_codec_card_dapm_routes);
1711
1712        return card;
1713};
1714
1715static const struct snd_soc_dapm_widget sun6i_codec_card_dapm_widgets[] = {
1716        SND_SOC_DAPM_HP("Headphone", NULL),
1717        SND_SOC_DAPM_LINE("Line In", NULL),
1718        SND_SOC_DAPM_LINE("Line Out", NULL),
1719        SND_SOC_DAPM_MIC("Headset Mic", NULL),
1720        SND_SOC_DAPM_MIC("Mic", NULL),
1721        SND_SOC_DAPM_SPK("Speaker", sun4i_codec_spk_event),
1722};
1723
1724static struct snd_soc_card *sun6i_codec_create_card(struct device *dev)
1725{
1726        struct snd_soc_card *card;
1727        int ret;
1728
1729        card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
1730        if (!card)
1731                return ERR_PTR(-ENOMEM);
1732
1733        card->dai_link = sun4i_codec_create_link(dev, &card->num_links);
1734        if (!card->dai_link)
1735                return ERR_PTR(-ENOMEM);
1736
1737        card->dev               = dev;
1738        card->owner             = THIS_MODULE;
1739        card->name              = "A31 Audio Codec";
1740        card->dapm_widgets      = sun6i_codec_card_dapm_widgets;
1741        card->num_dapm_widgets  = ARRAY_SIZE(sun6i_codec_card_dapm_widgets);
1742        card->fully_routed      = true;
1743
1744        ret = snd_soc_of_parse_audio_routing(card, "allwinner,audio-routing");
1745        if (ret)
1746                dev_warn(dev, "failed to parse audio-routing: %d\n", ret);
1747
1748        return card;
1749};
1750
1751/* Connect digital side enables to analog side widgets */
1752static const struct snd_soc_dapm_route sun8i_codec_card_routes[] = {
1753        /* ADC Routes */
1754        { "Left ADC", NULL, "ADC Enable" },
1755        { "Right ADC", NULL, "ADC Enable" },
1756        { "Codec Capture", NULL, "Left ADC" },
1757        { "Codec Capture", NULL, "Right ADC" },
1758
1759        /* DAC Routes */
1760        { "Left DAC", NULL, "DAC Enable" },
1761        { "Right DAC", NULL, "DAC Enable" },
1762        { "Left DAC", NULL, "Codec Playback" },
1763        { "Right DAC", NULL, "Codec Playback" },
1764};
1765
1766static struct snd_soc_aux_dev aux_dev = {
1767        .dlc = COMP_EMPTY(),
1768};
1769
1770static struct snd_soc_card *sun8i_a23_codec_create_card(struct device *dev)
1771{
1772        struct snd_soc_card *card;
1773        int ret;
1774
1775        card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
1776        if (!card)
1777                return ERR_PTR(-ENOMEM);
1778
1779        aux_dev.dlc.of_node = of_parse_phandle(dev->of_node,
1780                                                 "allwinner,codec-analog-controls",
1781                                                 0);
1782        if (!aux_dev.dlc.of_node) {
1783                dev_err(dev, "Can't find analog controls for codec.\n");
1784                return ERR_PTR(-EINVAL);
1785        }
1786
1787        card->dai_link = sun4i_codec_create_link(dev, &card->num_links);
1788        if (!card->dai_link)
1789                return ERR_PTR(-ENOMEM);
1790
1791        card->dev               = dev;
1792        card->owner             = THIS_MODULE;
1793        card->name              = "A23 Audio Codec";
1794        card->dapm_widgets      = sun6i_codec_card_dapm_widgets;
1795        card->num_dapm_widgets  = ARRAY_SIZE(sun6i_codec_card_dapm_widgets);
1796        card->dapm_routes       = sun8i_codec_card_routes;
1797        card->num_dapm_routes   = ARRAY_SIZE(sun8i_codec_card_routes);
1798        card->aux_dev           = &aux_dev;
1799        card->num_aux_devs      = 1;
1800        card->fully_routed      = true;
1801
1802        ret = snd_soc_of_parse_audio_routing(card, "allwinner,audio-routing");
1803        if (ret)
1804                dev_warn(dev, "failed to parse audio-routing: %d\n", ret);
1805
1806        return card;
1807};
1808
1809static struct snd_soc_card *sun8i_h3_codec_create_card(struct device *dev)
1810{
1811        struct snd_soc_card *card;
1812        int ret;
1813
1814        card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
1815        if (!card)
1816                return ERR_PTR(-ENOMEM);
1817
1818        aux_dev.dlc.of_node = of_parse_phandle(dev->of_node,
1819                                                 "allwinner,codec-analog-controls",
1820                                                 0);
1821        if (!aux_dev.dlc.of_node) {
1822                dev_err(dev, "Can't find analog controls for codec.\n");
1823                return ERR_PTR(-EINVAL);
1824        }
1825
1826        card->dai_link = sun4i_codec_create_link(dev, &card->num_links);
1827        if (!card->dai_link)
1828                return ERR_PTR(-ENOMEM);
1829
1830        card->dev               = dev;
1831        card->owner             = THIS_MODULE;
1832        card->name              = "H3 Audio Codec";
1833        card->dapm_widgets      = sun6i_codec_card_dapm_widgets;
1834        card->num_dapm_widgets  = ARRAY_SIZE(sun6i_codec_card_dapm_widgets);
1835        card->dapm_routes       = sun8i_codec_card_routes;
1836        card->num_dapm_routes   = ARRAY_SIZE(sun8i_codec_card_routes);
1837        card->aux_dev           = &aux_dev;
1838        card->num_aux_devs      = 1;
1839        card->fully_routed      = true;
1840
1841        ret = snd_soc_of_parse_audio_routing(card, "allwinner,audio-routing");
1842        if (ret)
1843                dev_warn(dev, "failed to parse audio-routing: %d\n", ret);
1844
1845        return card;
1846};
1847
1848static struct snd_soc_card *sun8i_v3s_codec_create_card(struct device *dev)
1849{
1850        struct snd_soc_card *card;
1851        int ret;
1852
1853        card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
1854        if (!card)
1855                return ERR_PTR(-ENOMEM);
1856
1857        aux_dev.dlc.of_node = of_parse_phandle(dev->of_node,
1858                                                 "allwinner,codec-analog-controls",
1859                                                 0);
1860        if (!aux_dev.dlc.of_node) {
1861                dev_err(dev, "Can't find analog controls for codec.\n");
1862                return ERR_PTR(-EINVAL);
1863        }
1864
1865        card->dai_link = sun4i_codec_create_link(dev, &card->num_links);
1866        if (!card->dai_link)
1867                return ERR_PTR(-ENOMEM);
1868
1869        card->dev               = dev;
1870        card->owner             = THIS_MODULE;
1871        card->name              = "V3s Audio Codec";
1872        card->dapm_widgets      = sun6i_codec_card_dapm_widgets;
1873        card->num_dapm_widgets  = ARRAY_SIZE(sun6i_codec_card_dapm_widgets);
1874        card->dapm_routes       = sun8i_codec_card_routes;
1875        card->num_dapm_routes   = ARRAY_SIZE(sun8i_codec_card_routes);
1876        card->aux_dev           = &aux_dev;
1877        card->num_aux_devs      = 1;
1878        card->fully_routed      = true;
1879
1880        ret = snd_soc_of_parse_audio_routing(card, "allwinner,audio-routing");
1881        if (ret)
1882                dev_warn(dev, "failed to parse audio-routing: %d\n", ret);
1883
1884        return card;
1885};
1886
1887static const struct snd_kcontrol_new sun50i_h616_codec_codec_controls[] = {
1888        SOC_SINGLE_TLV("DAC Playback Volume", SUN4I_CODEC_DAC_DPC,
1889                       SUN4I_CODEC_DAC_DPC_DVOL, 0x3f, 1,
1890                       sun6i_codec_dvol_scale),
1891        SOC_SINGLE_TLV("Line Out Playback Volume",
1892                       SUN50I_H616_DAC_AC_DAC_REG,
1893                       SUN50I_H616_LINEOUT_VOL, 0x1f, 0,
1894                       sun6i_codec_lineout_vol_scale),
1895        SOC_DOUBLE("Line Out Playback Switch",
1896                   SUN50I_H616_DAC_AC_DAC_REG,
1897                   SUN50I_H616_LINEOUTL_EN,
1898                   SUN50I_H616_LINEOUTR_EN, 1, 0),
1899};
1900
1901static const struct snd_kcontrol_new sun50i_h616_codec_mixer_controls[] = {
1902        SOC_DAPM_DOUBLE("DAC Playback Switch",
1903                        SUN50I_H616_DAC_AC_MIXER_REG,
1904                        SUN50I_H616_LMIX_LDAC,
1905                        SUN50I_H616_RMIX_RDAC, 1, 0),
1906        SOC_DAPM_DOUBLE("DAC Reversed Playback Switch",
1907                        SUN50I_H616_DAC_AC_MIXER_REG,
1908                        SUN50I_H616_LMIX_RDAC,
1909                        SUN50I_H616_RMIX_LDAC, 1, 0),
1910};
1911
1912static SOC_ENUM_DOUBLE_DECL(sun50i_h616_codec_lineout_src_enum,
1913                            SUN50I_H616_DAC_AC_DAC_REG,
1914                            SUN50I_H616_LINEOUTL_SEL,
1915                            SUN50I_H616_LINEOUTR_SEL,
1916                            sun6i_codec_lineout_src_enum_text);
1917
1918static const struct snd_kcontrol_new sun50i_h616_codec_lineout_src[] = {
1919                SOC_DAPM_ENUM("Line Out Source Playback Route",
1920                              sun50i_h616_codec_lineout_src_enum),
1921};
1922
1923static const struct snd_soc_dapm_widget sun50i_h616_codec_codec_widgets[] = {
1924        /* Digital parts of the DACs */
1925        SND_SOC_DAPM_SUPPLY("DAC Enable", SUN4I_CODEC_DAC_DPC,
1926                            SUN4I_CODEC_DAC_DPC_EN_DA, 0,
1927                            NULL, 0),
1928
1929        /* Analog parts of the DACs */
1930        SND_SOC_DAPM_DAC("Left DAC", "Codec Playback",
1931                         SUN50I_H616_DAC_AC_DAC_REG,
1932                         SUN50I_H616_DAC_LEN, 0),
1933        SND_SOC_DAPM_DAC("Right DAC", "Codec Playback",
1934                         SUN50I_H616_DAC_AC_DAC_REG,
1935                         SUN50I_H616_DAC_REN, 0),
1936
1937        /* Mixers */
1938        SOC_MIXER_ARRAY("Left Mixer", SUN50I_H616_DAC_AC_MIXER_REG,
1939                        SUN50I_H616_LMIXEN, 0,
1940                        sun50i_h616_codec_mixer_controls),
1941        SOC_MIXER_ARRAY("Right Mixer", SUN50I_H616_DAC_AC_MIXER_REG,
1942                        SUN50I_H616_RMIXEN, 0,
1943                        sun50i_h616_codec_mixer_controls),
1944
1945        /* Line Out path */
1946        SND_SOC_DAPM_MUX("Line Out Source Playback Route",
1947                         SND_SOC_NOPM, 0, 0, sun50i_h616_codec_lineout_src),
1948        SND_SOC_DAPM_OUT_DRV("Line Out Ramp Controller",
1949                             SUN50I_H616_DAC_AC_RAMP_REG,
1950                             SUN50I_H616_RDEN, 0, NULL, 0),
1951        SND_SOC_DAPM_OUTPUT("LINEOUT"),
1952};
1953
1954static const struct snd_soc_component_driver sun50i_h616_codec_codec = {
1955        .controls   = sun50i_h616_codec_codec_controls,
1956        .num_controls   = ARRAY_SIZE(sun50i_h616_codec_codec_controls),
1957        .dapm_widgets   = sun50i_h616_codec_codec_widgets,
1958        .num_dapm_widgets = ARRAY_SIZE(sun50i_h616_codec_codec_widgets),
1959        .idle_bias_on   = 1,
1960        .use_pmdown_time  = 1,
1961        .endianness   = 1,
1962};
1963
1964static const struct snd_kcontrol_new sun50i_h616_card_controls[] = {
1965        SOC_DAPM_PIN_SWITCH("Speaker"),
1966};
1967
1968static const struct snd_soc_dapm_widget sun50i_h616_codec_card_dapm_widgets[] = {
1969        SND_SOC_DAPM_HP("Headphone", NULL),
1970        SND_SOC_DAPM_LINE("Line Out", NULL),
1971        SND_SOC_DAPM_SPK("Speaker", sun4i_codec_spk_event),
1972};
1973
1974/* Connect digital side enables to analog side widgets */
1975static const struct snd_soc_dapm_route sun50i_h616_codec_card_routes[] = {
1976        /* DAC Routes */
1977        { "Left DAC", NULL, "DAC Enable" },
1978        { "Right DAC", NULL, "DAC Enable" },
1979
1980        /* Left Mixer Routes */
1981        { "Left Mixer", "DAC Playback Switch", "Left DAC" },
1982        { "Left Mixer", "DAC Reversed Playback Switch", "Right DAC" },
1983
1984        /* Right Mixer Routes */
1985        { "Right Mixer", "DAC Playback Switch", "Right DAC" },
1986        { "Right Mixer", "DAC Reversed Playback Switch", "Left DAC" },
1987
1988        /* Line Out Routes */
1989        { "Line Out Source Playback Route", "Stereo", "Left Mixer" },
1990        { "Line Out Source Playback Route", "Stereo", "Right Mixer" },
1991        { "Line Out Source Playback Route", "Mono Differential", "Left Mixer" },
1992        { "Line Out Source Playback Route", "Mono Differential", "Right Mixer" },
1993        { "Line Out Ramp Controller", NULL, "Line Out Source Playback Route" },
1994        { "LINEOUT", NULL, "Line Out Ramp Controller" },
1995};
1996
1997static struct snd_soc_card *sun50i_h616_codec_create_card(struct device *dev)
1998{
1999        struct snd_soc_card *card;
2000        int ret;
2001
2002        card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
2003        if (!card)
2004                return ERR_PTR(-ENOMEM);
2005
2006        card->dai_link = sun4i_codec_create_link(dev, &card->num_links);
2007        if (!card->dai_link)
2008                return ERR_PTR(-ENOMEM);
2009
2010        card->dai_link->playback_only = true;
2011        card->dai_link->capture_only = false;
2012
2013        card->dev               = dev;
2014        card->owner             = THIS_MODULE;
2015        card->name              = "H616 Audio Codec";
2016        card->long_name         = "h616-audio-codec";
2017        card->driver_name       = "sun4i-codec";
2018        card->controls          = sun50i_h616_card_controls;
2019        card->num_controls      = ARRAY_SIZE(sun50i_h616_card_controls);
2020        card->dapm_widgets      = sun50i_h616_codec_card_dapm_widgets;
2021        card->num_dapm_widgets  = ARRAY_SIZE(sun50i_h616_codec_card_dapm_widgets);
2022        card->dapm_routes       = sun50i_h616_codec_card_routes;
2023        card->num_dapm_routes   = ARRAY_SIZE(sun50i_h616_codec_card_routes);
2024        card->fully_routed      = true;
2025
2026        ret = snd_soc_of_parse_audio_routing(card, "allwinner,audio-routing");
2027        if (ret)
2028                dev_warn(dev, "failed to parse audio-routing: %d\n", ret);
2029
2030        return card;
2031};
2032
2033static const struct snd_soc_dapm_widget suniv_codec_card_dapm_widgets[] = {
2034        SND_SOC_DAPM_HP("Headphone", NULL),
2035        SND_SOC_DAPM_LINE("Line In", NULL),
2036        SND_SOC_DAPM_LINE("Right FM In", NULL),
2037        SND_SOC_DAPM_LINE("Left FM In", NULL),
2038        SND_SOC_DAPM_MIC("Mic", NULL),
2039        SND_SOC_DAPM_SPK("Speaker", sun4i_codec_spk_event),
2040};
2041
2042/* Connect digital side enables to analog side widgets */
2043static const struct snd_soc_dapm_route suniv_codec_card_routes[] = {
2044        /* ADC Routes */
2045        { "ADC", NULL, "ADC Enable" },
2046        { "Codec Capture", NULL, "ADC" },
2047
2048        /* DAC Routes */
2049        { "Left DAC", NULL, "DAC Enable" },
2050        { "Right DAC", NULL, "DAC Enable" },
2051        { "Left DAC", NULL, "Codec Playback" },
2052        { "Right DAC", NULL, "Codec Playback" },
2053};
2054
2055static struct snd_soc_card *suniv_codec_create_card(struct device *dev)
2056{
2057        struct snd_soc_card *card;
2058        int ret;
2059
2060        card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
2061        if (!card)
2062                return ERR_PTR(-ENOMEM);
2063
2064        card->dai_link = sun4i_codec_create_link(dev, &card->num_links);
2065        if (!card->dai_link)
2066                return ERR_PTR(-ENOMEM);
2067
2068        card->dev               = dev;
2069        card->name              = "F1C100s Audio Codec";
2070        card->dapm_widgets      = suniv_codec_card_dapm_widgets;
2071        card->num_dapm_widgets  = ARRAY_SIZE(suniv_codec_card_dapm_widgets);
2072        card->dapm_routes       = suniv_codec_card_routes;
2073        card->num_dapm_routes   = ARRAY_SIZE(suniv_codec_card_routes);
2074        card->fully_routed      = true;
2075
2076        ret = snd_soc_of_parse_audio_routing(card, "allwinner,audio-routing");
2077        if (ret)
2078                dev_warn(dev, "failed to parse audio-routing: %d\n", ret);
2079
2080        return card;
2081};
2082
2083static const struct regmap_config sun4i_codec_regmap_config = {
2084        .reg_bits       = 32,
2085        .reg_stride     = 4,
2086        .val_bits       = 32,
2087        .max_register   = SUN4I_CODEC_ADC_RXCNT,
2088};
2089
2090static const struct regmap_config sun6i_codec_regmap_config = {
2091        .reg_bits       = 32,
2092        .reg_stride     = 4,
2093        .val_bits       = 32,
2094        .max_register   = SUN6I_CODEC_HMIC_DATA,
2095};
2096
2097static const struct regmap_config sun7i_codec_regmap_config = {
2098        .reg_bits       = 32,
2099        .reg_stride     = 4,
2100        .val_bits       = 32,
2101        .max_register   = SUN7I_CODEC_AC_MIC_PHONE_CAL,
2102};
2103
2104static const struct regmap_config sun8i_a23_codec_regmap_config = {
2105        .reg_bits       = 32,
2106        .reg_stride     = 4,
2107        .val_bits       = 32,
2108        .max_register   = SUN8I_A23_CODEC_ADC_RXCNT,
2109};
2110
2111static const struct regmap_config sun8i_h3_codec_regmap_config = {
2112        .reg_bits       = 32,
2113        .reg_stride     = 4,
2114        .val_bits       = 32,
2115        .max_register   = SUN8I_H3_CODEC_ADC_DBG,
2116};
2117
2118static const struct regmap_config sun8i_v3s_codec_regmap_config = {
2119        .reg_bits       = 32,
2120        .reg_stride     = 4,
2121        .val_bits       = 32,
2122        .max_register   = SUN8I_H3_CODEC_ADC_DBG,
2123};
2124
2125static const struct regmap_config sun50i_h616_codec_regmap_config = {
2126        .reg_bits       = 32,
2127        .reg_stride     = 4,
2128        .val_bits       = 32,
2129        .max_register   = SUN50I_H616_DAC_AC_RAMP_REG,
2130        .cache_type     = REGCACHE_NONE,
2131};
2132
2133static const struct regmap_config suniv_codec_regmap_config = {
2134        .reg_bits       = 32,
2135        .reg_stride     = 4,
2136        .val_bits       = 32,
2137        .max_register   = SUNIV_CODEC_ADC_DBG,
2138};
2139
2140struct sun4i_codec_quirks {
2141        const struct regmap_config *regmap_config;
2142        const struct snd_soc_component_driver *codec;
2143        struct snd_soc_card * (*create_card)(struct device *dev);
2144        struct reg_field reg_adc_fifoc; /* used for regmap_field */
2145        struct reg_field reg_dac_fifoc; /* used for regmap_field */
2146        unsigned int reg_dac_txdata;    /* TX FIFO offset for DMA config */
2147        unsigned int reg_adc_rxdata;    /* RX FIFO offset for DMA config */
2148        bool has_reset;
2149        bool playback_only;
2150        u32 dma_max_burst;
2151};
2152
2153static const struct sun4i_codec_quirks sun4i_codec_quirks = {
2154        .regmap_config  = &sun4i_codec_regmap_config,
2155        .codec          = &sun4i_codec_codec,
2156        .create_card    = sun4i_codec_create_card,
2157        .reg_adc_fifoc  = REG_FIELD(SUN4I_CODEC_ADC_FIFOC, 0, 31),
2158        .reg_dac_fifoc  = REG_FIELD(SUN4I_CODEC_DAC_FIFOC, 0, 31),
2159        .reg_dac_txdata = SUN4I_CODEC_DAC_TXDATA,
2160        .reg_adc_rxdata = SUN4I_CODEC_ADC_RXDATA,
2161        .dma_max_burst  = SUN4I_DMA_MAX_BURST,
2162};
2163
2164static const struct sun4i_codec_quirks sun6i_a31_codec_quirks = {
2165        .regmap_config  = &sun6i_codec_regmap_config,
2166        .codec          = &sun6i_codec_codec,
2167        .create_card    = sun6i_codec_create_card,
2168        .reg_adc_fifoc  = REG_FIELD(SUN6I_CODEC_ADC_FIFOC, 0, 31),
2169        .reg_dac_fifoc  = REG_FIELD(SUN4I_CODEC_DAC_FIFOC, 0, 31),
2170        .reg_dac_txdata = SUN4I_CODEC_DAC_TXDATA,
2171        .reg_adc_rxdata = SUN6I_CODEC_ADC_RXDATA,
2172        .has_reset      = true,
2173        .dma_max_burst  = SUN4I_DMA_MAX_BURST,
2174};
2175
2176static const struct sun4i_codec_quirks sun7i_codec_quirks = {
2177        .regmap_config  = &sun7i_codec_regmap_config,
2178        .codec          = &sun7i_codec_codec,
2179        .create_card    = sun4i_codec_create_card,
2180        .reg_adc_fifoc  = REG_FIELD(SUN4I_CODEC_ADC_FIFOC, 0, 31),
2181        .reg_dac_fifoc  = REG_FIELD(SUN4I_CODEC_DAC_FIFOC, 0, 31),
2182        .reg_dac_txdata = SUN4I_CODEC_DAC_TXDATA,
2183        .reg_adc_rxdata = SUN4I_CODEC_ADC_RXDATA,
2184        .dma_max_burst  = SUN4I_DMA_MAX_BURST,
2185};
2186
2187static const struct sun4i_codec_quirks sun8i_a23_codec_quirks = {
2188        .regmap_config  = &sun8i_a23_codec_regmap_config,
2189        .codec          = &sun8i_a23_codec_codec,
2190        .create_card    = sun8i_a23_codec_create_card,
2191        .reg_adc_fifoc  = REG_FIELD(SUN6I_CODEC_ADC_FIFOC, 0, 31),
2192        .reg_dac_fifoc  = REG_FIELD(SUN4I_CODEC_DAC_FIFOC, 0, 31),
2193        .reg_dac_txdata = SUN4I_CODEC_DAC_TXDATA,
2194        .reg_adc_rxdata = SUN6I_CODEC_ADC_RXDATA,
2195        .has_reset      = true,
2196        .dma_max_burst  = SUN4I_DMA_MAX_BURST,
2197};
2198
2199static const struct sun4i_codec_quirks sun8i_h3_codec_quirks = {
2200        .regmap_config  = &sun8i_h3_codec_regmap_config,
2201        /*
2202         * TODO Share the codec structure with A23 for now.
2203         * This should be split out when adding digital audio
2204         * processing support for the H3.
2205         */
2206        .codec          = &sun8i_a23_codec_codec,
2207        .create_card    = sun8i_h3_codec_create_card,
2208        .reg_adc_fifoc  = REG_FIELD(SUN6I_CODEC_ADC_FIFOC, 0, 31),
2209        .reg_dac_fifoc  = REG_FIELD(SUN4I_CODEC_DAC_FIFOC, 0, 31),
2210        .reg_dac_txdata = SUN8I_H3_CODEC_DAC_TXDATA,
2211        .reg_adc_rxdata = SUN6I_CODEC_ADC_RXDATA,
2212        .has_reset      = true,
2213        .dma_max_burst  = SUN4I_DMA_MAX_BURST,
2214};
2215
2216static const struct sun4i_codec_quirks sun8i_v3s_codec_quirks = {
2217        .regmap_config  = &sun8i_v3s_codec_regmap_config,
2218        /*
2219         * TODO The codec structure should be split out, like
2220         * H3, when adding digital audio processing support.
2221         */
2222        .codec          = &sun8i_a23_codec_codec,
2223        .create_card    = sun8i_v3s_codec_create_card,
2224        .reg_adc_fifoc  = REG_FIELD(SUN6I_CODEC_ADC_FIFOC, 0, 31),
2225        .reg_dac_fifoc  = REG_FIELD(SUN4I_CODEC_DAC_FIFOC, 0, 31),
2226        .reg_dac_txdata = SUN8I_H3_CODEC_DAC_TXDATA,
2227        .reg_adc_rxdata = SUN6I_CODEC_ADC_RXDATA,
2228        .has_reset      = true,
2229        .dma_max_burst  = SUN4I_DMA_MAX_BURST,
2230};
2231
2232static const struct sun4i_codec_quirks sun50i_h616_codec_quirks = {
2233        .regmap_config  = &sun50i_h616_codec_regmap_config,
2234        .codec          = &sun50i_h616_codec_codec,
2235        .create_card    = sun50i_h616_codec_create_card,
2236        .reg_dac_fifoc  = REG_FIELD(SUN50I_H616_CODEC_DAC_FIFOC, 0, 31),
2237        .reg_dac_txdata = SUN8I_H3_CODEC_DAC_TXDATA,
2238        .has_reset      = true,
2239        .dma_max_burst  = SUN4I_DMA_MAX_BURST,
2240};
2241
2242static const struct sun4i_codec_quirks suniv_f1c100s_codec_quirks = {
2243        .regmap_config  = &suniv_codec_regmap_config,
2244        .codec          = &suniv_codec_codec,
2245        .create_card    = suniv_codec_create_card,
2246        .reg_adc_fifoc  = REG_FIELD(SUNIV_CODEC_ADC_FIFOC, 0, 31),
2247        .reg_dac_fifoc  = REG_FIELD(SUN4I_CODEC_DAC_FIFOC, 0, 31),
2248        .reg_dac_txdata = SUN4I_CODEC_DAC_TXDATA,
2249        .reg_adc_rxdata = SUNIV_CODEC_ADC_RXDATA,
2250        .has_reset      = true,
2251        .dma_max_burst  = SUNIV_DMA_MAX_BURST,
2252};
2253
2254static const struct of_device_id sun4i_codec_of_match[] = {
2255        {
2256                .compatible = "allwinner,sun4i-a10-codec",
2257                .data = &sun4i_codec_quirks,
2258        },
2259        {
2260                .compatible = "allwinner,sun6i-a31-codec",
2261                .data = &sun6i_a31_codec_quirks,
2262        },
2263        {
2264                .compatible = "allwinner,sun7i-a20-codec",
2265                .data = &sun7i_codec_quirks,
2266        },
2267        {
2268                .compatible = "allwinner,sun8i-a23-codec",
2269                .data = &sun8i_a23_codec_quirks,
2270        },
2271        {
2272                .compatible = "allwinner,sun8i-h3-codec",
2273                .data = &sun8i_h3_codec_quirks,
2274        },
2275        {
2276                .compatible = "allwinner,sun8i-v3s-codec",
2277                .data = &sun8i_v3s_codec_quirks,
2278        },
2279        {
2280                .compatible = "allwinner,sun50i-h616-codec",
2281                .data = &sun50i_h616_codec_quirks,
2282        },
2283        {
2284                .compatible = "allwinner,suniv-f1c100s-codec",
2285                .data = &suniv_f1c100s_codec_quirks,
2286        },
2287        {}
2288};
2289MODULE_DEVICE_TABLE(of, sun4i_codec_of_match);
2290
2291static int sun4i_codec_probe(struct platform_device *pdev)
2292{
2293        struct snd_soc_card *card;
2294        struct sun4i_codec *scodec;
2295        const struct sun4i_codec_quirks *quirks;
2296        struct resource *res;
2297        void __iomem *base;
2298        int ret;
2299
2300        scodec = devm_kzalloc(&pdev->dev, sizeof(*scodec), GFP_KERNEL);
2301        if (!scodec)
2302                return -ENOMEM;
2303
2304        scodec->dev = &pdev->dev;
2305
2306        base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
2307        if (IS_ERR(base))
2308                return PTR_ERR(base);
2309
2310        quirks = of_device_get_match_data(&pdev->dev);
2311        if (quirks == NULL) {
2312                dev_err(&pdev->dev, "Failed to determine the quirks to use\n");
2313                return -ENODEV;
2314        }
2315
2316        scodec->regmap = devm_regmap_init_mmio(&pdev->dev, base,
2317                                               quirks->regmap_config);
2318        if (IS_ERR(scodec->regmap)) {
2319                dev_err(&pdev->dev, "Failed to create our regmap\n");
2320                return PTR_ERR(scodec->regmap);
2321        }
2322
2323        /* Get the clocks from the DT */
2324        scodec->clk_apb = devm_clk_get_enabled(&pdev->dev, "apb");
2325        if (IS_ERR(scodec->clk_apb)) {
2326                dev_err(&pdev->dev, "Failed to get the APB clock\n");
2327                return PTR_ERR(scodec->clk_apb);
2328        }
2329
2330        scodec->clk_module = devm_clk_get(&pdev->dev, "codec");
2331        if (IS_ERR(scodec->clk_module)) {
2332                dev_err(&pdev->dev, "Failed to get the module clock\n");
2333                return PTR_ERR(scodec->clk_module);
2334        }
2335
2336        if (quirks->has_reset) {
2337                scodec->rst = devm_reset_control_get_exclusive_deasserted(&pdev->dev, NULL);
2338                if (IS_ERR(scodec->rst)) {
2339                        dev_err(&pdev->dev, "Failed to get reset control\n");
2340                        return PTR_ERR(scodec->rst);
2341                }
2342        }
2343
2344        scodec->gpio_pa = devm_gpiod_get_optional(&pdev->dev, "allwinner,pa",
2345                                                  GPIOD_OUT_LOW);
2346        if (IS_ERR(scodec->gpio_pa)) {
2347                ret = PTR_ERR(scodec->gpio_pa);
2348                dev_err_probe(&pdev->dev, ret, "Failed to get pa gpio\n");
2349                return ret;
2350        }
2351
2352        scodec->gpio_hp = devm_gpiod_get_optional(&pdev->dev, "hp-det", GPIOD_IN);
2353        if (IS_ERR(scodec->gpio_hp)) {
2354                ret = PTR_ERR(scodec->gpio_hp);
2355                dev_err_probe(&pdev->dev, ret, "Failed to get hp-det gpio\n");
2356                return ret;
2357        }
2358
2359        /* reg_field setup */
2360        scodec->reg_adc_fifoc = devm_regmap_field_alloc(&pdev->dev,
2361                                                        scodec->regmap,
2362                                                        quirks->reg_adc_fifoc);
2363        if (IS_ERR(scodec->reg_adc_fifoc)) {
2364                ret = PTR_ERR(scodec->reg_adc_fifoc);
2365                dev_err(&pdev->dev, "Failed to create regmap fields: %d\n",
2366                        ret);
2367                return ret;
2368        }
2369
2370        scodec->reg_dac_fifoc = devm_regmap_field_alloc(&pdev->dev,
2371                                                        scodec->regmap,
2372                                                        quirks->reg_dac_fifoc);
2373        if (IS_ERR(scodec->reg_dac_fifoc)) {
2374                ret = PTR_ERR(scodec->reg_dac_fifoc);
2375                dev_err(&pdev->dev, "Failed to create regmap fields: %d\n",
2376                        ret);
2377                return ret;
2378        }
2379
2380        /* DMA configuration for TX FIFO */
2381        scodec->playback_dma_data.addr = res->start + quirks->reg_dac_txdata;
2382        scodec->playback_dma_data.maxburst = quirks->dma_max_burst;
2383        scodec->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
2384
2385        if (!quirks->playback_only) {
2386                /* DMA configuration for RX FIFO */
2387                scodec->capture_dma_data.addr = res->start +
2388                                                quirks->reg_adc_rxdata;
2389                scodec->capture_dma_data.maxburst = quirks->dma_max_burst;
2390                scodec->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
2391        }
2392
2393        ret = devm_snd_soc_register_component(&pdev->dev, quirks->codec,
2394                                     &sun4i_codec_dai, 1);
2395        if (ret) {
2396                dev_err(&pdev->dev, "Failed to register our codec\n");
2397                return ret;
2398        }
2399
2400        ret = devm_snd_soc_register_component(&pdev->dev,
2401                                              &sun4i_codec_component,
2402                                              &dummy_cpu_dai, 1);
2403        if (ret) {
2404                dev_err(&pdev->dev, "Failed to register our DAI\n");
2405                return ret;
2406        }
2407
2408        ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
2409        if (ret) {
2410                dev_err(&pdev->dev, "Failed to register against DMAEngine\n");
2411                return ret;
2412        }
2413
2414        card = quirks->create_card(&pdev->dev);
2415        if (IS_ERR(card)) {
2416                ret = PTR_ERR(card);
2417                dev_err(&pdev->dev, "Failed to create our card\n");
2418                return ret;
2419        }
2420
2421        snd_soc_card_set_drvdata(card, scodec);
2422
2423        ret = snd_soc_register_card(card);
2424        if (ret) {
2425                dev_err_probe(&pdev->dev, ret, "Failed to register our card\n");
2426                return ret;
2427        }
2428
2429        return 0;
2430}
2431
2432static void sun4i_codec_remove(struct platform_device *pdev)
2433{
2434        struct snd_soc_card *card = platform_get_drvdata(pdev);
2435
2436        snd_soc_unregister_card(card);
2437}
2438
2439static struct platform_driver sun4i_codec_driver = {
2440        .driver = {
2441                .name = "sun4i-codec",
2442                .of_match_table = sun4i_codec_of_match,
2443        },
2444        .probe = sun4i_codec_probe,
2445        .remove = sun4i_codec_remove,
2446};
2447module_platform_driver(sun4i_codec_driver);
2448
2449MODULE_DESCRIPTION("Allwinner A10 codec driver");
2450MODULE_AUTHOR("Emilio López <emilio@elopez.com.ar>");
2451MODULE_AUTHOR("Jon Smirl <jonsmirl@gmail.com>");
2452MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
2453MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>");
2454MODULE_AUTHOR("Ryan Walklin <ryan@testtoast.com");
2455MODULE_AUTHOR("Mesih Kilinc <mesikilinc@gmail.com>");
2456MODULE_LICENSE("GPL");
2457