File Index
Files and directories
Sign in
FILE

sun4i-codec.c

File preview with syntax highlighting.

linux-6.19.14/sound/soc/sunxi/sun4i-codec.c C
   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 snd_soc_card *card = snd_soc_dapm_to_card(w->dapm);
1667	struct sun4i_codec *scodec = snd_soc_card_get_drvdata(card);
1668
1669	gpiod_set_value_cansleep(scodec->gpio_pa,
1670				 !!SND_SOC_DAPM_EVENT_ON(event));
1671
1672	if (SND_SOC_DAPM_EVENT_ON(event)) {
1673		/*
1674		 * Need a delay to wait for DAC to push the data. 700ms seems
1675		 * to be the best compromise not to feel this delay while
1676		 * playing a sound.
1677		 */
1678		msleep(700);
1679	}
1680
1681	return 0;
1682}
1683
1684static const struct snd_soc_dapm_widget sun4i_codec_card_dapm_widgets[] = {
1685	SND_SOC_DAPM_SPK("Speaker", sun4i_codec_spk_event),
1686};
1687
1688static const struct snd_soc_dapm_route sun4i_codec_card_dapm_routes[] = {
1689	{ "Speaker", NULL, "HP Right" },
1690	{ "Speaker", NULL, "HP Left" },
1691};
1692
1693static struct snd_soc_card *sun4i_codec_create_card(struct device *dev)
1694{
1695	struct snd_soc_card *card;
1696
1697	card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
1698	if (!card)
1699		return ERR_PTR(-ENOMEM);
1700
1701	card->dai_link = sun4i_codec_create_link(dev, &card->num_links);
1702	if (!card->dai_link)
1703		return ERR_PTR(-ENOMEM);
1704
1705	card->dev		= dev;
1706	card->owner		= THIS_MODULE;
1707	card->name		= "sun4i-codec";
1708	card->dapm_widgets	= sun4i_codec_card_dapm_widgets;
1709	card->num_dapm_widgets	= ARRAY_SIZE(sun4i_codec_card_dapm_widgets);
1710	card->dapm_routes	= sun4i_codec_card_dapm_routes;
1711	card->num_dapm_routes	= ARRAY_SIZE(sun4i_codec_card_dapm_routes);
1712
1713	return card;
1714};
1715
1716static const struct snd_soc_dapm_widget sun6i_codec_card_dapm_widgets[] = {
1717	SND_SOC_DAPM_HP("Headphone", NULL),
1718	SND_SOC_DAPM_LINE("Line In", NULL),
1719	SND_SOC_DAPM_LINE("Line Out", NULL),
1720	SND_SOC_DAPM_MIC("Headset Mic", NULL),
1721	SND_SOC_DAPM_MIC("Mic", NULL),
1722	SND_SOC_DAPM_SPK("Speaker", sun4i_codec_spk_event),
1723};
1724
1725static struct snd_soc_card *sun6i_codec_create_card(struct device *dev)
1726{
1727	struct snd_soc_card *card;
1728	int ret;
1729
1730	card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
1731	if (!card)
1732		return ERR_PTR(-ENOMEM);
1733
1734	card->dai_link = sun4i_codec_create_link(dev, &card->num_links);
1735	if (!card->dai_link)
1736		return ERR_PTR(-ENOMEM);
1737
1738	card->dev		= dev;
1739	card->owner		= THIS_MODULE;
1740	card->name		= "A31 Audio Codec";
1741	card->dapm_widgets	= sun6i_codec_card_dapm_widgets;
1742	card->num_dapm_widgets	= ARRAY_SIZE(sun6i_codec_card_dapm_widgets);
1743	card->fully_routed	= true;
1744
1745	ret = snd_soc_of_parse_audio_routing(card, "allwinner,audio-routing");
1746	if (ret)
1747		dev_warn(dev, "failed to parse audio-routing: %d\n", ret);
1748
1749	return card;
1750};
1751
1752/* Connect digital side enables to analog side widgets */
1753static const struct snd_soc_dapm_route sun8i_codec_card_routes[] = {
1754	/* ADC Routes */
1755	{ "Left ADC", NULL, "ADC Enable" },
1756	{ "Right ADC", NULL, "ADC Enable" },
1757	{ "Codec Capture", NULL, "Left ADC" },
1758	{ "Codec Capture", NULL, "Right ADC" },
1759
1760	/* DAC Routes */
1761	{ "Left DAC", NULL, "DAC Enable" },
1762	{ "Right DAC", NULL, "DAC Enable" },
1763	{ "Left DAC", NULL, "Codec Playback" },
1764	{ "Right DAC", NULL, "Codec Playback" },
1765};
1766
1767static struct snd_soc_aux_dev aux_dev = {
1768	.dlc = COMP_EMPTY(),
1769};
1770
1771static struct snd_soc_card *sun8i_a23_codec_create_card(struct device *dev)
1772{
1773	struct snd_soc_card *card;
1774	int ret;
1775
1776	card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
1777	if (!card)
1778		return ERR_PTR(-ENOMEM);
1779
1780	aux_dev.dlc.of_node = of_parse_phandle(dev->of_node,
1781						 "allwinner,codec-analog-controls",
1782						 0);
1783	if (!aux_dev.dlc.of_node) {
1784		dev_err(dev, "Can't find analog controls for codec.\n");
1785		return ERR_PTR(-EINVAL);
1786	}
1787
1788	card->dai_link = sun4i_codec_create_link(dev, &card->num_links);
1789	if (!card->dai_link)
1790		return ERR_PTR(-ENOMEM);
1791
1792	card->dev		= dev;
1793	card->owner		= THIS_MODULE;
1794	card->name		= "A23 Audio Codec";
1795	card->dapm_widgets	= sun6i_codec_card_dapm_widgets;
1796	card->num_dapm_widgets	= ARRAY_SIZE(sun6i_codec_card_dapm_widgets);
1797	card->dapm_routes	= sun8i_codec_card_routes;
1798	card->num_dapm_routes	= ARRAY_SIZE(sun8i_codec_card_routes);
1799	card->aux_dev		= &aux_dev;
1800	card->num_aux_devs	= 1;
1801	card->fully_routed	= true;
1802
1803	ret = snd_soc_of_parse_audio_routing(card, "allwinner,audio-routing");
1804	if (ret)
1805		dev_warn(dev, "failed to parse audio-routing: %d\n", ret);
1806
1807	return card;
1808};
1809
1810static struct snd_soc_card *sun8i_h3_codec_create_card(struct device *dev)
1811{
1812	struct snd_soc_card *card;
1813	int ret;
1814
1815	card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
1816	if (!card)
1817		return ERR_PTR(-ENOMEM);
1818
1819	aux_dev.dlc.of_node = of_parse_phandle(dev->of_node,
1820						 "allwinner,codec-analog-controls",
1821						 0);
1822	if (!aux_dev.dlc.of_node) {
1823		dev_err(dev, "Can't find analog controls for codec.\n");
1824		return ERR_PTR(-EINVAL);
1825	}
1826
1827	card->dai_link = sun4i_codec_create_link(dev, &card->num_links);
1828	if (!card->dai_link)
1829		return ERR_PTR(-ENOMEM);
1830
1831	card->dev		= dev;
1832	card->owner		= THIS_MODULE;
1833	card->name		= "H3 Audio Codec";
1834	card->dapm_widgets	= sun6i_codec_card_dapm_widgets;
1835	card->num_dapm_widgets	= ARRAY_SIZE(sun6i_codec_card_dapm_widgets);
1836	card->dapm_routes	= sun8i_codec_card_routes;
1837	card->num_dapm_routes	= ARRAY_SIZE(sun8i_codec_card_routes);
1838	card->aux_dev		= &aux_dev;
1839	card->num_aux_devs	= 1;
1840	card->fully_routed	= true;
1841
1842	ret = snd_soc_of_parse_audio_routing(card, "allwinner,audio-routing");
1843	if (ret)
1844		dev_warn(dev, "failed to parse audio-routing: %d\n", ret);
1845
1846	return card;
1847};
1848
1849static struct snd_soc_card *sun8i_v3s_codec_create_card(struct device *dev)
1850{
1851	struct snd_soc_card *card;
1852	int ret;
1853
1854	card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
1855	if (!card)
1856		return ERR_PTR(-ENOMEM);
1857
1858	aux_dev.dlc.of_node = of_parse_phandle(dev->of_node,
1859						 "allwinner,codec-analog-controls",
1860						 0);
1861	if (!aux_dev.dlc.of_node) {
1862		dev_err(dev, "Can't find analog controls for codec.\n");
1863		return ERR_PTR(-EINVAL);
1864	}
1865
1866	card->dai_link = sun4i_codec_create_link(dev, &card->num_links);
1867	if (!card->dai_link)
1868		return ERR_PTR(-ENOMEM);
1869
1870	card->dev		= dev;
1871	card->owner		= THIS_MODULE;
1872	card->name		= "V3s Audio Codec";
1873	card->dapm_widgets	= sun6i_codec_card_dapm_widgets;
1874	card->num_dapm_widgets	= ARRAY_SIZE(sun6i_codec_card_dapm_widgets);
1875	card->dapm_routes	= sun8i_codec_card_routes;
1876	card->num_dapm_routes	= ARRAY_SIZE(sun8i_codec_card_routes);
1877	card->aux_dev		= &aux_dev;
1878	card->num_aux_devs	= 1;
1879	card->fully_routed	= true;
1880
1881	ret = snd_soc_of_parse_audio_routing(card, "allwinner,audio-routing");
1882	if (ret)
1883		dev_warn(dev, "failed to parse audio-routing: %d\n", ret);
1884
1885	return card;
1886};
1887
1888static const struct snd_kcontrol_new sun50i_h616_codec_codec_controls[] = {
1889	SOC_SINGLE_TLV("DAC Playback Volume", SUN4I_CODEC_DAC_DPC,
1890		       SUN4I_CODEC_DAC_DPC_DVOL, 0x3f, 1,
1891		       sun6i_codec_dvol_scale),
1892	SOC_SINGLE_TLV("Line Out Playback Volume",
1893		       SUN50I_H616_DAC_AC_DAC_REG,
1894		       SUN50I_H616_LINEOUT_VOL, 0x1f, 0,
1895		       sun6i_codec_lineout_vol_scale),
1896	SOC_DOUBLE("Line Out Playback Switch",
1897		   SUN50I_H616_DAC_AC_DAC_REG,
1898		   SUN50I_H616_LINEOUTL_EN,
1899		   SUN50I_H616_LINEOUTR_EN, 1, 0),
1900};
1901
1902static const struct snd_kcontrol_new sun50i_h616_codec_mixer_controls[] = {
1903	SOC_DAPM_DOUBLE("DAC Playback Switch",
1904			SUN50I_H616_DAC_AC_MIXER_REG,
1905			SUN50I_H616_LMIX_LDAC,
1906			SUN50I_H616_RMIX_RDAC, 1, 0),
1907	SOC_DAPM_DOUBLE("DAC Reversed Playback Switch",
1908			SUN50I_H616_DAC_AC_MIXER_REG,
1909			SUN50I_H616_LMIX_RDAC,
1910			SUN50I_H616_RMIX_LDAC, 1, 0),
1911};
1912
1913static SOC_ENUM_DOUBLE_DECL(sun50i_h616_codec_lineout_src_enum,
1914			    SUN50I_H616_DAC_AC_DAC_REG,
1915			    SUN50I_H616_LINEOUTL_SEL,
1916			    SUN50I_H616_LINEOUTR_SEL,
1917			    sun6i_codec_lineout_src_enum_text);
1918
1919static const struct snd_kcontrol_new sun50i_h616_codec_lineout_src[] = {
1920		SOC_DAPM_ENUM("Line Out Source Playback Route",
1921			      sun50i_h616_codec_lineout_src_enum),
1922};
1923
1924static const struct snd_soc_dapm_widget sun50i_h616_codec_codec_widgets[] = {
1925	/* Digital parts of the DACs */
1926	SND_SOC_DAPM_SUPPLY("DAC Enable", SUN4I_CODEC_DAC_DPC,
1927			    SUN4I_CODEC_DAC_DPC_EN_DA, 0,
1928			    NULL, 0),
1929
1930	/* Analog parts of the DACs */
1931	SND_SOC_DAPM_DAC("Left DAC", "Codec Playback",
1932			 SUN50I_H616_DAC_AC_DAC_REG,
1933			 SUN50I_H616_DAC_LEN, 0),
1934	SND_SOC_DAPM_DAC("Right DAC", "Codec Playback",
1935			 SUN50I_H616_DAC_AC_DAC_REG,
1936			 SUN50I_H616_DAC_REN, 0),
1937
1938	/* Mixers */
1939	SOC_MIXER_ARRAY("Left Mixer", SUN50I_H616_DAC_AC_MIXER_REG,
1940			SUN50I_H616_LMIXEN, 0,
1941			sun50i_h616_codec_mixer_controls),
1942	SOC_MIXER_ARRAY("Right Mixer", SUN50I_H616_DAC_AC_MIXER_REG,
1943			SUN50I_H616_RMIXEN, 0,
1944			sun50i_h616_codec_mixer_controls),
1945
1946	/* Line Out path */
1947	SND_SOC_DAPM_MUX("Line Out Source Playback Route",
1948			 SND_SOC_NOPM, 0, 0, sun50i_h616_codec_lineout_src),
1949	SND_SOC_DAPM_OUT_DRV("Line Out Ramp Controller",
1950			     SUN50I_H616_DAC_AC_RAMP_REG,
1951			     SUN50I_H616_RDEN, 0, NULL, 0),
1952	SND_SOC_DAPM_OUTPUT("LINEOUT"),
1953};
1954
1955static const struct snd_soc_component_driver sun50i_h616_codec_codec = {
1956	.controls   = sun50i_h616_codec_codec_controls,
1957	.num_controls   = ARRAY_SIZE(sun50i_h616_codec_codec_controls),
1958	.dapm_widgets   = sun50i_h616_codec_codec_widgets,
1959	.num_dapm_widgets = ARRAY_SIZE(sun50i_h616_codec_codec_widgets),
1960	.idle_bias_on   = 1,
1961	.use_pmdown_time  = 1,
1962	.endianness   = 1,
1963};
1964
1965static const struct snd_kcontrol_new sun50i_h616_card_controls[] = {
1966	SOC_DAPM_PIN_SWITCH("Speaker"),
1967};
1968
1969static const struct snd_soc_dapm_widget sun50i_h616_codec_card_dapm_widgets[] = {
1970	SND_SOC_DAPM_HP("Headphone", NULL),
1971	SND_SOC_DAPM_LINE("Line Out", NULL),
1972	SND_SOC_DAPM_SPK("Speaker", sun4i_codec_spk_event),
1973};
1974
1975/* Connect digital side enables to analog side widgets */
1976static const struct snd_soc_dapm_route sun50i_h616_codec_card_routes[] = {
1977	/* DAC Routes */
1978	{ "Left DAC", NULL, "DAC Enable" },
1979	{ "Right DAC", NULL, "DAC Enable" },
1980
1981	/* Left Mixer Routes */
1982	{ "Left Mixer", "DAC Playback Switch", "Left DAC" },
1983	{ "Left Mixer", "DAC Reversed Playback Switch", "Right DAC" },
1984
1985	/* Right Mixer Routes */
1986	{ "Right Mixer", "DAC Playback Switch", "Right DAC" },
1987	{ "Right Mixer", "DAC Reversed Playback Switch", "Left DAC" },
1988
1989	/* Line Out Routes */
1990	{ "Line Out Source Playback Route", "Stereo", "Left Mixer" },
1991	{ "Line Out Source Playback Route", "Stereo", "Right Mixer" },
1992	{ "Line Out Source Playback Route", "Mono Differential", "Left Mixer" },
1993	{ "Line Out Source Playback Route", "Mono Differential", "Right Mixer" },
1994	{ "Line Out Ramp Controller", NULL, "Line Out Source Playback Route" },
1995	{ "LINEOUT", NULL, "Line Out Ramp Controller" },
1996};
1997
1998static struct snd_soc_card *sun50i_h616_codec_create_card(struct device *dev)
1999{
2000	struct snd_soc_card *card;
2001	int ret;
2002
2003	card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
2004	if (!card)
2005		return ERR_PTR(-ENOMEM);
2006
2007	card->dai_link = sun4i_codec_create_link(dev, &card->num_links);
2008	if (!card->dai_link)
2009		return ERR_PTR(-ENOMEM);
2010
2011	card->dai_link->playback_only = true;
2012	card->dai_link->capture_only = false;
2013
2014	card->dev		= dev;
2015	card->owner		= THIS_MODULE;
2016	card->name		= "H616 Audio Codec";
2017	card->long_name		= "h616-audio-codec";
2018	card->driver_name	= "sun4i-codec";
2019	card->controls		= sun50i_h616_card_controls;
2020	card->num_controls	= ARRAY_SIZE(sun50i_h616_card_controls);
2021	card->dapm_widgets	= sun50i_h616_codec_card_dapm_widgets;
2022	card->num_dapm_widgets	= ARRAY_SIZE(sun50i_h616_codec_card_dapm_widgets);
2023	card->dapm_routes	= sun50i_h616_codec_card_routes;
2024	card->num_dapm_routes	= ARRAY_SIZE(sun50i_h616_codec_card_routes);
2025	card->fully_routed	= true;
2026
2027	ret = snd_soc_of_parse_audio_routing(card, "allwinner,audio-routing");
2028	if (ret)
2029		dev_warn(dev, "failed to parse audio-routing: %d\n", ret);
2030
2031	return card;
2032};
2033
2034static const struct snd_soc_dapm_widget suniv_codec_card_dapm_widgets[] = {
2035	SND_SOC_DAPM_HP("Headphone", NULL),
2036	SND_SOC_DAPM_LINE("Line In", NULL),
2037	SND_SOC_DAPM_LINE("Right FM In", NULL),
2038	SND_SOC_DAPM_LINE("Left FM In", NULL),
2039	SND_SOC_DAPM_MIC("Mic", NULL),
2040	SND_SOC_DAPM_SPK("Speaker", sun4i_codec_spk_event),
2041};
2042
2043/* Connect digital side enables to analog side widgets */
2044static const struct snd_soc_dapm_route suniv_codec_card_routes[] = {
2045	/* ADC Routes */
2046	{ "ADC", NULL, "ADC Enable" },
2047	{ "Codec Capture", NULL, "ADC" },
2048
2049	/* DAC Routes */
2050	{ "Left DAC", NULL, "DAC Enable" },
2051	{ "Right DAC", NULL, "DAC Enable" },
2052	{ "Left DAC", NULL, "Codec Playback" },
2053	{ "Right DAC", NULL, "Codec Playback" },
2054};
2055
2056static struct snd_soc_card *suniv_codec_create_card(struct device *dev)
2057{
2058	struct snd_soc_card *card;
2059	int ret;
2060
2061	card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
2062	if (!card)
2063		return ERR_PTR(-ENOMEM);
2064
2065	card->dai_link = sun4i_codec_create_link(dev, &card->num_links);
2066	if (!card->dai_link)
2067		return ERR_PTR(-ENOMEM);
2068
2069	card->dev		= dev;
2070	card->name		= "F1C100s Audio Codec";
2071	card->dapm_widgets	= suniv_codec_card_dapm_widgets;
2072	card->num_dapm_widgets	= ARRAY_SIZE(suniv_codec_card_dapm_widgets);
2073	card->dapm_routes	= suniv_codec_card_routes;
2074	card->num_dapm_routes	= ARRAY_SIZE(suniv_codec_card_routes);
2075	card->fully_routed	= true;
2076
2077	ret = snd_soc_of_parse_audio_routing(card, "allwinner,audio-routing");
2078	if (ret)
2079		dev_warn(dev, "failed to parse audio-routing: %d\n", ret);
2080
2081	return card;
2082};
2083
2084static const struct regmap_config sun4i_codec_regmap_config = {
2085	.reg_bits	= 32,
2086	.reg_stride	= 4,
2087	.val_bits	= 32,
2088	.max_register	= SUN4I_CODEC_ADC_RXCNT,
2089};
2090
2091static const struct regmap_config sun6i_codec_regmap_config = {
2092	.reg_bits	= 32,
2093	.reg_stride	= 4,
2094	.val_bits	= 32,
2095	.max_register	= SUN6I_CODEC_HMIC_DATA,
2096};
2097
2098static const struct regmap_config sun7i_codec_regmap_config = {
2099	.reg_bits	= 32,
2100	.reg_stride	= 4,
2101	.val_bits	= 32,
2102	.max_register	= SUN7I_CODEC_AC_MIC_PHONE_CAL,
2103};
2104
2105static const struct regmap_config sun8i_a23_codec_regmap_config = {
2106	.reg_bits	= 32,
2107	.reg_stride	= 4,
2108	.val_bits	= 32,
2109	.max_register	= SUN8I_A23_CODEC_ADC_RXCNT,
2110};
2111
2112static const struct regmap_config sun8i_h3_codec_regmap_config = {
2113	.reg_bits	= 32,
2114	.reg_stride	= 4,
2115	.val_bits	= 32,
2116	.max_register	= SUN8I_H3_CODEC_ADC_DBG,
2117};
2118
2119static const struct regmap_config sun8i_v3s_codec_regmap_config = {
2120	.reg_bits	= 32,
2121	.reg_stride	= 4,
2122	.val_bits	= 32,
2123	.max_register	= SUN8I_H3_CODEC_ADC_DBG,
2124};
2125
2126static const struct regmap_config sun50i_h616_codec_regmap_config = {
2127	.reg_bits	= 32,
2128	.reg_stride	= 4,
2129	.val_bits	= 32,
2130	.max_register	= SUN50I_H616_DAC_AC_RAMP_REG,
2131	.cache_type	= REGCACHE_NONE,
2132};
2133
2134static const struct regmap_config suniv_codec_regmap_config = {
2135	.reg_bits	= 32,
2136	.reg_stride	= 4,
2137	.val_bits	= 32,
2138	.max_register	= SUNIV_CODEC_ADC_DBG,
2139};
2140
2141struct sun4i_codec_quirks {
2142	const struct regmap_config *regmap_config;
2143	const struct snd_soc_component_driver *codec;
2144	struct snd_soc_card * (*create_card)(struct device *dev);
2145	struct reg_field reg_adc_fifoc;	/* used for regmap_field */
2146	struct reg_field reg_dac_fifoc;	/* used for regmap_field */
2147	unsigned int reg_dac_txdata;	/* TX FIFO offset for DMA config */
2148	unsigned int reg_adc_rxdata;	/* RX FIFO offset for DMA config */
2149	bool has_reset;
2150	bool playback_only;
2151	u32 dma_max_burst;
2152};
2153
2154static const struct sun4i_codec_quirks sun4i_codec_quirks = {
2155	.regmap_config	= &sun4i_codec_regmap_config,
2156	.codec		= &sun4i_codec_codec,
2157	.create_card	= sun4i_codec_create_card,
2158	.reg_adc_fifoc	= REG_FIELD(SUN4I_CODEC_ADC_FIFOC, 0, 31),
2159	.reg_dac_fifoc	= REG_FIELD(SUN4I_CODEC_DAC_FIFOC, 0, 31),
2160	.reg_dac_txdata	= SUN4I_CODEC_DAC_TXDATA,
2161	.reg_adc_rxdata	= SUN4I_CODEC_ADC_RXDATA,
2162	.dma_max_burst	= SUN4I_DMA_MAX_BURST,
2163};
2164
2165static const struct sun4i_codec_quirks sun6i_a31_codec_quirks = {
2166	.regmap_config	= &sun6i_codec_regmap_config,
2167	.codec		= &sun6i_codec_codec,
2168	.create_card	= sun6i_codec_create_card,
2169	.reg_adc_fifoc	= REG_FIELD(SUN6I_CODEC_ADC_FIFOC, 0, 31),
2170	.reg_dac_fifoc	= REG_FIELD(SUN4I_CODEC_DAC_FIFOC, 0, 31),
2171	.reg_dac_txdata	= SUN4I_CODEC_DAC_TXDATA,
2172	.reg_adc_rxdata	= SUN6I_CODEC_ADC_RXDATA,
2173	.has_reset	= true,
2174	.dma_max_burst	= SUN4I_DMA_MAX_BURST,
2175};
2176
2177static const struct sun4i_codec_quirks sun7i_codec_quirks = {
2178	.regmap_config	= &sun7i_codec_regmap_config,
2179	.codec		= &sun7i_codec_codec,
2180	.create_card	= sun4i_codec_create_card,
2181	.reg_adc_fifoc	= REG_FIELD(SUN4I_CODEC_ADC_FIFOC, 0, 31),
2182	.reg_dac_fifoc	= REG_FIELD(SUN4I_CODEC_DAC_FIFOC, 0, 31),
2183	.reg_dac_txdata	= SUN4I_CODEC_DAC_TXDATA,
2184	.reg_adc_rxdata	= SUN4I_CODEC_ADC_RXDATA,
2185	.dma_max_burst	= SUN4I_DMA_MAX_BURST,
2186};
2187
2188static const struct sun4i_codec_quirks sun8i_a23_codec_quirks = {
2189	.regmap_config	= &sun8i_a23_codec_regmap_config,
2190	.codec		= &sun8i_a23_codec_codec,
2191	.create_card	= sun8i_a23_codec_create_card,
2192	.reg_adc_fifoc	= REG_FIELD(SUN6I_CODEC_ADC_FIFOC, 0, 31),
2193	.reg_dac_fifoc	= REG_FIELD(SUN4I_CODEC_DAC_FIFOC, 0, 31),
2194	.reg_dac_txdata	= SUN4I_CODEC_DAC_TXDATA,
2195	.reg_adc_rxdata	= SUN6I_CODEC_ADC_RXDATA,
2196	.has_reset	= true,
2197	.dma_max_burst	= SUN4I_DMA_MAX_BURST,
2198};
2199
2200static const struct sun4i_codec_quirks sun8i_h3_codec_quirks = {
2201	.regmap_config	= &sun8i_h3_codec_regmap_config,
2202	/*
2203	 * TODO Share the codec structure with A23 for now.
2204	 * This should be split out when adding digital audio
2205	 * processing support for the H3.
2206	 */
2207	.codec		= &sun8i_a23_codec_codec,
2208	.create_card	= sun8i_h3_codec_create_card,
2209	.reg_adc_fifoc	= REG_FIELD(SUN6I_CODEC_ADC_FIFOC, 0, 31),
2210	.reg_dac_fifoc	= REG_FIELD(SUN4I_CODEC_DAC_FIFOC, 0, 31),
2211	.reg_dac_txdata	= SUN8I_H3_CODEC_DAC_TXDATA,
2212	.reg_adc_rxdata	= SUN6I_CODEC_ADC_RXDATA,
2213	.has_reset	= true,
2214	.dma_max_burst	= SUN4I_DMA_MAX_BURST,
2215};
2216
2217static const struct sun4i_codec_quirks sun8i_v3s_codec_quirks = {
2218	.regmap_config	= &sun8i_v3s_codec_regmap_config,
2219	/*
2220	 * TODO The codec structure should be split out, like
2221	 * H3, when adding digital audio processing support.
2222	 */
2223	.codec		= &sun8i_a23_codec_codec,
2224	.create_card	= sun8i_v3s_codec_create_card,
2225	.reg_adc_fifoc	= REG_FIELD(SUN6I_CODEC_ADC_FIFOC, 0, 31),
2226	.reg_dac_fifoc	= REG_FIELD(SUN4I_CODEC_DAC_FIFOC, 0, 31),
2227	.reg_dac_txdata	= SUN8I_H3_CODEC_DAC_TXDATA,
2228	.reg_adc_rxdata	= SUN6I_CODEC_ADC_RXDATA,
2229	.has_reset	= true,
2230	.dma_max_burst	= SUN4I_DMA_MAX_BURST,
2231};
2232
2233static const struct sun4i_codec_quirks sun50i_h616_codec_quirks = {
2234	.regmap_config	= &sun50i_h616_codec_regmap_config,
2235	.codec		= &sun50i_h616_codec_codec,
2236	.create_card	= sun50i_h616_codec_create_card,
2237	.reg_dac_fifoc	= REG_FIELD(SUN50I_H616_CODEC_DAC_FIFOC, 0, 31),
2238	.reg_dac_txdata	= SUN8I_H3_CODEC_DAC_TXDATA,
2239	.has_reset	= true,
2240	.dma_max_burst	= SUN4I_DMA_MAX_BURST,
2241};
2242
2243static const struct sun4i_codec_quirks suniv_f1c100s_codec_quirks = {
2244	.regmap_config	= &suniv_codec_regmap_config,
2245	.codec		= &suniv_codec_codec,
2246	.create_card	= suniv_codec_create_card,
2247	.reg_adc_fifoc	= REG_FIELD(SUNIV_CODEC_ADC_FIFOC, 0, 31),
2248	.reg_dac_fifoc	= REG_FIELD(SUN4I_CODEC_DAC_FIFOC, 0, 31),
2249	.reg_dac_txdata	= SUN4I_CODEC_DAC_TXDATA,
2250	.reg_adc_rxdata	= SUNIV_CODEC_ADC_RXDATA,
2251	.has_reset	= true,
2252	.dma_max_burst	= SUNIV_DMA_MAX_BURST,
2253};
2254
2255static const struct of_device_id sun4i_codec_of_match[] = {
2256	{
2257		.compatible = "allwinner,sun4i-a10-codec",
2258		.data = &sun4i_codec_quirks,
2259	},
2260	{
2261		.compatible = "allwinner,sun6i-a31-codec",
2262		.data = &sun6i_a31_codec_quirks,
2263	},
2264	{
2265		.compatible = "allwinner,sun7i-a20-codec",
2266		.data = &sun7i_codec_quirks,
2267	},
2268	{
2269		.compatible = "allwinner,sun8i-a23-codec",
2270		.data = &sun8i_a23_codec_quirks,
2271	},
2272	{
2273		.compatible = "allwinner,sun8i-h3-codec",
2274		.data = &sun8i_h3_codec_quirks,
2275	},
2276	{
2277		.compatible = "allwinner,sun8i-v3s-codec",
2278		.data = &sun8i_v3s_codec_quirks,
2279	},
2280	{
2281		.compatible = "allwinner,sun50i-h616-codec",
2282		.data = &sun50i_h616_codec_quirks,
2283	},
2284	{
2285		.compatible = "allwinner,suniv-f1c100s-codec",
2286		.data = &suniv_f1c100s_codec_quirks,
2287	},
2288	{}
2289};
2290MODULE_DEVICE_TABLE(of, sun4i_codec_of_match);
2291
2292static int sun4i_codec_probe(struct platform_device *pdev)
2293{
2294	struct snd_soc_card *card;
2295	struct sun4i_codec *scodec;
2296	const struct sun4i_codec_quirks *quirks;
2297	struct resource *res;
2298	void __iomem *base;
2299	int ret;
2300
2301	scodec = devm_kzalloc(&pdev->dev, sizeof(*scodec), GFP_KERNEL);
2302	if (!scodec)
2303		return -ENOMEM;
2304
2305	scodec->dev = &pdev->dev;
2306
2307	base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
2308	if (IS_ERR(base))
2309		return PTR_ERR(base);
2310
2311	quirks = of_device_get_match_data(&pdev->dev);
2312	if (quirks == NULL) {
2313		dev_err(&pdev->dev, "Failed to determine the quirks to use\n");
2314		return -ENODEV;
2315	}
2316
2317	scodec->regmap = devm_regmap_init_mmio(&pdev->dev, base,
2318					       quirks->regmap_config);
2319	if (IS_ERR(scodec->regmap)) {
2320		dev_err(&pdev->dev, "Failed to create our regmap\n");
2321		return PTR_ERR(scodec->regmap);
2322	}
2323
2324	/* Get the clocks from the DT */
2325	scodec->clk_apb = devm_clk_get_enabled(&pdev->dev, "apb");
2326	if (IS_ERR(scodec->clk_apb)) {
2327		dev_err(&pdev->dev, "Failed to get the APB clock\n");
2328		return PTR_ERR(scodec->clk_apb);
2329	}
2330
2331	scodec->clk_module = devm_clk_get(&pdev->dev, "codec");
2332	if (IS_ERR(scodec->clk_module)) {
2333		dev_err(&pdev->dev, "Failed to get the module clock\n");
2334		return PTR_ERR(scodec->clk_module);
2335	}
2336
2337	if (quirks->has_reset) {
2338		scodec->rst = devm_reset_control_get_exclusive_deasserted(&pdev->dev, NULL);
2339		if (IS_ERR(scodec->rst)) {
2340			dev_err(&pdev->dev, "Failed to get reset control\n");
2341			return PTR_ERR(scodec->rst);
2342		}
2343	}
2344
2345	scodec->gpio_pa = devm_gpiod_get_optional(&pdev->dev, "allwinner,pa",
2346						  GPIOD_OUT_LOW);
2347	if (IS_ERR(scodec->gpio_pa)) {
2348		ret = PTR_ERR(scodec->gpio_pa);
2349		dev_err_probe(&pdev->dev, ret, "Failed to get pa gpio\n");
2350		return ret;
2351	}
2352
2353	scodec->gpio_hp = devm_gpiod_get_optional(&pdev->dev, "hp-det", GPIOD_IN);
2354	if (IS_ERR(scodec->gpio_hp)) {
2355		ret = PTR_ERR(scodec->gpio_hp);
2356		dev_err_probe(&pdev->dev, ret, "Failed to get hp-det gpio\n");
2357		return ret;
2358	}
2359
2360	/* reg_field setup */
2361	scodec->reg_adc_fifoc = devm_regmap_field_alloc(&pdev->dev,
2362							scodec->regmap,
2363							quirks->reg_adc_fifoc);
2364	if (IS_ERR(scodec->reg_adc_fifoc)) {
2365		ret = PTR_ERR(scodec->reg_adc_fifoc);
2366		dev_err(&pdev->dev, "Failed to create regmap fields: %d\n",
2367			ret);
2368		return ret;
2369	}
2370
2371	scodec->reg_dac_fifoc = devm_regmap_field_alloc(&pdev->dev,
2372							scodec->regmap,
2373							quirks->reg_dac_fifoc);
2374	if (IS_ERR(scodec->reg_dac_fifoc)) {
2375		ret = PTR_ERR(scodec->reg_dac_fifoc);
2376		dev_err(&pdev->dev, "Failed to create regmap fields: %d\n",
2377			ret);
2378		return ret;
2379	}
2380
2381	/* DMA configuration for TX FIFO */
2382	scodec->playback_dma_data.addr = res->start + quirks->reg_dac_txdata;
2383	scodec->playback_dma_data.maxburst = quirks->dma_max_burst;
2384	scodec->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
2385
2386	if (!quirks->playback_only) {
2387		/* DMA configuration for RX FIFO */
2388		scodec->capture_dma_data.addr = res->start +
2389						quirks->reg_adc_rxdata;
2390		scodec->capture_dma_data.maxburst = quirks->dma_max_burst;
2391		scodec->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
2392	}
2393
2394	ret = devm_snd_soc_register_component(&pdev->dev, quirks->codec,
2395				     &sun4i_codec_dai, 1);
2396	if (ret) {
2397		dev_err(&pdev->dev, "Failed to register our codec\n");
2398		return ret;
2399	}
2400
2401	ret = devm_snd_soc_register_component(&pdev->dev,
2402					      &sun4i_codec_component,
2403					      &dummy_cpu_dai, 1);
2404	if (ret) {
2405		dev_err(&pdev->dev, "Failed to register our DAI\n");
2406		return ret;
2407	}
2408
2409	ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
2410	if (ret) {
2411		dev_err(&pdev->dev, "Failed to register against DMAEngine\n");
2412		return ret;
2413	}
2414
2415	card = quirks->create_card(&pdev->dev);
2416	if (IS_ERR(card)) {
2417		ret = PTR_ERR(card);
2418		dev_err(&pdev->dev, "Failed to create our card\n");
2419		return ret;
2420	}
2421
2422	snd_soc_card_set_drvdata(card, scodec);
2423
2424	ret = snd_soc_register_card(card);
2425	if (ret) {
2426		dev_err_probe(&pdev->dev, ret, "Failed to register our card\n");
2427		return ret;
2428	}
2429
2430	return 0;
2431}
2432
2433static void sun4i_codec_remove(struct platform_device *pdev)
2434{
2435	struct snd_soc_card *card = platform_get_drvdata(pdev);
2436
2437	snd_soc_unregister_card(card);
2438}
2439
2440static struct platform_driver sun4i_codec_driver = {
2441	.driver = {
2442		.name = "sun4i-codec",
2443		.of_match_table = sun4i_codec_of_match,
2444	},
2445	.probe = sun4i_codec_probe,
2446	.remove = sun4i_codec_remove,
2447};
2448module_platform_driver(sun4i_codec_driver);
2449
2450MODULE_DESCRIPTION("Allwinner A10 codec driver");
2451MODULE_AUTHOR("Emilio López <emilio@elopez.com.ar>");
2452MODULE_AUTHOR("Jon Smirl <jonsmirl@gmail.com>");
2453MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
2454MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>");
2455MODULE_AUTHOR("Ryan Walklin <ryan@testtoast.com");
2456MODULE_AUTHOR("Mesih Kilinc <mesikilinc@gmail.com>");
2457MODULE_LICENSE("GPL");
~/ Read-only file preview.