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