1*f10485e7SMark Brown /* 2*f10485e7SMark Brown * wm8990.c -- WM8990 ALSA Soc Audio driver 3*f10485e7SMark Brown * 4*f10485e7SMark Brown * Copyright 2008 Wolfson Microelectronics PLC. 5*f10485e7SMark Brown * Author: Liam Girdwood 6*f10485e7SMark Brown * lg@opensource.wolfsonmicro.com or linux@wolfsonmicro.com 7*f10485e7SMark Brown * 8*f10485e7SMark Brown * This program is free software; you can redistribute it and/or modify it 9*f10485e7SMark Brown * under the terms of the GNU General Public License as published by the 10*f10485e7SMark Brown * Free Software Foundation; either version 2 of the License, or (at your 11*f10485e7SMark Brown * option) any later version. 12*f10485e7SMark Brown */ 13*f10485e7SMark Brown 14*f10485e7SMark Brown #include <linux/module.h> 15*f10485e7SMark Brown #include <linux/moduleparam.h> 16*f10485e7SMark Brown #include <linux/kernel.h> 17*f10485e7SMark Brown #include <linux/init.h> 18*f10485e7SMark Brown #include <linux/delay.h> 19*f10485e7SMark Brown #include <linux/pm.h> 20*f10485e7SMark Brown #include <linux/i2c.h> 21*f10485e7SMark Brown #include <linux/platform_device.h> 22*f10485e7SMark Brown #include <sound/core.h> 23*f10485e7SMark Brown #include <sound/pcm.h> 24*f10485e7SMark Brown #include <sound/pcm_params.h> 25*f10485e7SMark Brown #include <sound/soc.h> 26*f10485e7SMark Brown #include <sound/soc-dapm.h> 27*f10485e7SMark Brown #include <sound/initval.h> 28*f10485e7SMark Brown #include <sound/tlv.h> 29*f10485e7SMark Brown #include <asm/div64.h> 30*f10485e7SMark Brown 31*f10485e7SMark Brown #include "wm8990.h" 32*f10485e7SMark Brown 33*f10485e7SMark Brown #define AUDIO_NAME "wm8990" 34*f10485e7SMark Brown #define WM8990_VERSION "0.2" 35*f10485e7SMark Brown 36*f10485e7SMark Brown /* 37*f10485e7SMark Brown * Debug 38*f10485e7SMark Brown */ 39*f10485e7SMark Brown 40*f10485e7SMark Brown #define WM8990_DEBUG 0 41*f10485e7SMark Brown 42*f10485e7SMark Brown #ifdef WM8990_DEBUG 43*f10485e7SMark Brown #define dbg(format, arg...) \ 44*f10485e7SMark Brown printk(KERN_DEBUG AUDIO_NAME ": " format "\n" , ## arg) 45*f10485e7SMark Brown #else 46*f10485e7SMark Brown #define dbg(format, arg...) do {} while (0) 47*f10485e7SMark Brown #endif 48*f10485e7SMark Brown #define err(format, arg...) \ 49*f10485e7SMark Brown printk(KERN_ERR AUDIO_NAME ": " format "\n" , ## arg) 50*f10485e7SMark Brown #define info(format, arg...) \ 51*f10485e7SMark Brown printk(KERN_INFO AUDIO_NAME ": " format "\n" , ## arg) 52*f10485e7SMark Brown #define warn(format, arg...) \ 53*f10485e7SMark Brown printk(KERN_WARNING AUDIO_NAME ": " format "\n" , ## arg) 54*f10485e7SMark Brown 55*f10485e7SMark Brown /* codec private data */ 56*f10485e7SMark Brown struct wm8990_priv { 57*f10485e7SMark Brown unsigned int sysclk; 58*f10485e7SMark Brown unsigned int pcmclk; 59*f10485e7SMark Brown }; 60*f10485e7SMark Brown 61*f10485e7SMark Brown /* 62*f10485e7SMark Brown * wm8990 register cache. Note that register 0 is not included in the 63*f10485e7SMark Brown * cache. 64*f10485e7SMark Brown */ 65*f10485e7SMark Brown static const u16 wm8990_reg[] = { 66*f10485e7SMark Brown 0x8990, /* R0 - Reset */ 67*f10485e7SMark Brown 0x0000, /* R1 - Power Management (1) */ 68*f10485e7SMark Brown 0x6000, /* R2 - Power Management (2) */ 69*f10485e7SMark Brown 0x0000, /* R3 - Power Management (3) */ 70*f10485e7SMark Brown 0x4050, /* R4 - Audio Interface (1) */ 71*f10485e7SMark Brown 0x4000, /* R5 - Audio Interface (2) */ 72*f10485e7SMark Brown 0x01C8, /* R6 - Clocking (1) */ 73*f10485e7SMark Brown 0x0000, /* R7 - Clocking (2) */ 74*f10485e7SMark Brown 0x0040, /* R8 - Audio Interface (3) */ 75*f10485e7SMark Brown 0x0040, /* R9 - Audio Interface (4) */ 76*f10485e7SMark Brown 0x0004, /* R10 - DAC CTRL */ 77*f10485e7SMark Brown 0x00C0, /* R11 - Left DAC Digital Volume */ 78*f10485e7SMark Brown 0x00C0, /* R12 - Right DAC Digital Volume */ 79*f10485e7SMark Brown 0x0000, /* R13 - Digital Side Tone */ 80*f10485e7SMark Brown 0x0100, /* R14 - ADC CTRL */ 81*f10485e7SMark Brown 0x00C0, /* R15 - Left ADC Digital Volume */ 82*f10485e7SMark Brown 0x00C0, /* R16 - Right ADC Digital Volume */ 83*f10485e7SMark Brown 0x0000, /* R17 */ 84*f10485e7SMark Brown 0x0000, /* R18 - GPIO CTRL 1 */ 85*f10485e7SMark Brown 0x1000, /* R19 - GPIO1 & GPIO2 */ 86*f10485e7SMark Brown 0x1010, /* R20 - GPIO3 & GPIO4 */ 87*f10485e7SMark Brown 0x1010, /* R21 - GPIO5 & GPIO6 */ 88*f10485e7SMark Brown 0x8000, /* R22 - GPIOCTRL 2 */ 89*f10485e7SMark Brown 0x0800, /* R23 - GPIO_POL */ 90*f10485e7SMark Brown 0x008B, /* R24 - Left Line Input 1&2 Volume */ 91*f10485e7SMark Brown 0x008B, /* R25 - Left Line Input 3&4 Volume */ 92*f10485e7SMark Brown 0x008B, /* R26 - Right Line Input 1&2 Volume */ 93*f10485e7SMark Brown 0x008B, /* R27 - Right Line Input 3&4 Volume */ 94*f10485e7SMark Brown 0x0000, /* R28 - Left Output Volume */ 95*f10485e7SMark Brown 0x0000, /* R29 - Right Output Volume */ 96*f10485e7SMark Brown 0x0066, /* R30 - Line Outputs Volume */ 97*f10485e7SMark Brown 0x0022, /* R31 - Out3/4 Volume */ 98*f10485e7SMark Brown 0x0079, /* R32 - Left OPGA Volume */ 99*f10485e7SMark Brown 0x0079, /* R33 - Right OPGA Volume */ 100*f10485e7SMark Brown 0x0003, /* R34 - Speaker Volume */ 101*f10485e7SMark Brown 0x0003, /* R35 - ClassD1 */ 102*f10485e7SMark Brown 0x0000, /* R36 */ 103*f10485e7SMark Brown 0x0100, /* R37 - ClassD3 */ 104*f10485e7SMark Brown 0x0000, /* R38 */ 105*f10485e7SMark Brown 0x0000, /* R39 - Input Mixer1 */ 106*f10485e7SMark Brown 0x0000, /* R40 - Input Mixer2 */ 107*f10485e7SMark Brown 0x0000, /* R41 - Input Mixer3 */ 108*f10485e7SMark Brown 0x0000, /* R42 - Input Mixer4 */ 109*f10485e7SMark Brown 0x0000, /* R43 - Input Mixer5 */ 110*f10485e7SMark Brown 0x0000, /* R44 - Input Mixer6 */ 111*f10485e7SMark Brown 0x0000, /* R45 - Output Mixer1 */ 112*f10485e7SMark Brown 0x0000, /* R46 - Output Mixer2 */ 113*f10485e7SMark Brown 0x0000, /* R47 - Output Mixer3 */ 114*f10485e7SMark Brown 0x0000, /* R48 - Output Mixer4 */ 115*f10485e7SMark Brown 0x0000, /* R49 - Output Mixer5 */ 116*f10485e7SMark Brown 0x0000, /* R50 - Output Mixer6 */ 117*f10485e7SMark Brown 0x0180, /* R51 - Out3/4 Mixer */ 118*f10485e7SMark Brown 0x0000, /* R52 - Line Mixer1 */ 119*f10485e7SMark Brown 0x0000, /* R53 - Line Mixer2 */ 120*f10485e7SMark Brown 0x0000, /* R54 - Speaker Mixer */ 121*f10485e7SMark Brown 0x0000, /* R55 - Additional Control */ 122*f10485e7SMark Brown 0x0000, /* R56 - AntiPOP1 */ 123*f10485e7SMark Brown 0x0000, /* R57 - AntiPOP2 */ 124*f10485e7SMark Brown 0x0000, /* R58 - MICBIAS */ 125*f10485e7SMark Brown 0x0000, /* R59 */ 126*f10485e7SMark Brown 0x0008, /* R60 - PLL1 */ 127*f10485e7SMark Brown 0x0031, /* R61 - PLL2 */ 128*f10485e7SMark Brown 0x0026, /* R62 - PLL3 */ 129*f10485e7SMark Brown }; 130*f10485e7SMark Brown 131*f10485e7SMark Brown /* 132*f10485e7SMark Brown * read wm8990 register cache 133*f10485e7SMark Brown */ 134*f10485e7SMark Brown static inline unsigned int wm8990_read_reg_cache(struct snd_soc_codec *codec, 135*f10485e7SMark Brown unsigned int reg) 136*f10485e7SMark Brown { 137*f10485e7SMark Brown u16 *cache = codec->reg_cache; 138*f10485e7SMark Brown BUG_ON(reg > (ARRAY_SIZE(wm8990_reg)) - 1); 139*f10485e7SMark Brown return cache[reg]; 140*f10485e7SMark Brown } 141*f10485e7SMark Brown 142*f10485e7SMark Brown /* 143*f10485e7SMark Brown * write wm8990 register cache 144*f10485e7SMark Brown */ 145*f10485e7SMark Brown static inline void wm8990_write_reg_cache(struct snd_soc_codec *codec, 146*f10485e7SMark Brown unsigned int reg, unsigned int value) 147*f10485e7SMark Brown { 148*f10485e7SMark Brown u16 *cache = codec->reg_cache; 149*f10485e7SMark Brown BUG_ON(reg > (ARRAY_SIZE(wm8990_reg)) - 1); 150*f10485e7SMark Brown 151*f10485e7SMark Brown /* Reset register is uncached */ 152*f10485e7SMark Brown if (reg == 0) 153*f10485e7SMark Brown return; 154*f10485e7SMark Brown 155*f10485e7SMark Brown cache[reg] = value; 156*f10485e7SMark Brown } 157*f10485e7SMark Brown 158*f10485e7SMark Brown /* 159*f10485e7SMark Brown * write to the wm8990 register space 160*f10485e7SMark Brown */ 161*f10485e7SMark Brown static int wm8990_write(struct snd_soc_codec *codec, unsigned int reg, 162*f10485e7SMark Brown unsigned int value) 163*f10485e7SMark Brown { 164*f10485e7SMark Brown u8 data[3]; 165*f10485e7SMark Brown 166*f10485e7SMark Brown data[0] = reg & 0xFF; 167*f10485e7SMark Brown data[1] = (value >> 8) & 0xFF; 168*f10485e7SMark Brown data[2] = value & 0xFF; 169*f10485e7SMark Brown 170*f10485e7SMark Brown wm8990_write_reg_cache(codec, reg, value); 171*f10485e7SMark Brown 172*f10485e7SMark Brown if (codec->hw_write(codec->control_data, data, 3) == 2) 173*f10485e7SMark Brown return 0; 174*f10485e7SMark Brown else 175*f10485e7SMark Brown return -EIO; 176*f10485e7SMark Brown } 177*f10485e7SMark Brown 178*f10485e7SMark Brown #define wm8990_reset(c) wm8990_write(c, WM8990_RESET, 0) 179*f10485e7SMark Brown 180*f10485e7SMark Brown static const DECLARE_TLV_DB_LINEAR(rec_mix_tlv, -1500, 600); 181*f10485e7SMark Brown 182*f10485e7SMark Brown static const DECLARE_TLV_DB_LINEAR(in_pga_tlv, -1650, 3000); 183*f10485e7SMark Brown 184*f10485e7SMark Brown static const DECLARE_TLV_DB_LINEAR(out_mix_tlv, 0, -2100); 185*f10485e7SMark Brown 186*f10485e7SMark Brown static const DECLARE_TLV_DB_LINEAR(out_pga_tlv, -7300, 600); 187*f10485e7SMark Brown 188*f10485e7SMark Brown static const DECLARE_TLV_DB_LINEAR(out_omix_tlv, -600, 0); 189*f10485e7SMark Brown 190*f10485e7SMark Brown static const DECLARE_TLV_DB_LINEAR(out_dac_tlv, -7163, 0); 191*f10485e7SMark Brown 192*f10485e7SMark Brown static const DECLARE_TLV_DB_LINEAR(in_adc_tlv, -7163, 1763); 193*f10485e7SMark Brown 194*f10485e7SMark Brown static const DECLARE_TLV_DB_LINEAR(out_sidetone_tlv, -3600, 0); 195*f10485e7SMark Brown 196*f10485e7SMark Brown static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol, 197*f10485e7SMark Brown struct snd_ctl_elem_value *ucontrol) 198*f10485e7SMark Brown { 199*f10485e7SMark Brown struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 200*f10485e7SMark Brown int reg = kcontrol->private_value & 0xff; 201*f10485e7SMark Brown int ret; 202*f10485e7SMark Brown u16 val; 203*f10485e7SMark Brown 204*f10485e7SMark Brown ret = snd_soc_put_volsw(kcontrol, ucontrol); 205*f10485e7SMark Brown if (ret < 0) 206*f10485e7SMark Brown return ret; 207*f10485e7SMark Brown 208*f10485e7SMark Brown /* now hit the volume update bits (always bit 8) */ 209*f10485e7SMark Brown val = wm8990_read_reg_cache(codec, reg); 210*f10485e7SMark Brown return wm8990_write(codec, reg, val | 0x0100); 211*f10485e7SMark Brown } 212*f10485e7SMark Brown 213*f10485e7SMark Brown #define SOC_WM899X_OUTPGA_SINGLE_R_TLV(xname, reg, shift, max, invert,\ 214*f10485e7SMark Brown tlv_array) {\ 215*f10485e7SMark Brown .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ 216*f10485e7SMark Brown .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ 217*f10485e7SMark Brown SNDRV_CTL_ELEM_ACCESS_READWRITE,\ 218*f10485e7SMark Brown .tlv.p = (tlv_array), \ 219*f10485e7SMark Brown .info = snd_soc_info_volsw, \ 220*f10485e7SMark Brown .get = snd_soc_get_volsw, .put = wm899x_outpga_put_volsw_vu, \ 221*f10485e7SMark Brown .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } 222*f10485e7SMark Brown 223*f10485e7SMark Brown 224*f10485e7SMark Brown static const char *wm8990_digital_sidetone[] = 225*f10485e7SMark Brown {"None", "Left ADC", "Right ADC", "Reserved"}; 226*f10485e7SMark Brown 227*f10485e7SMark Brown static const struct soc_enum wm8990_left_digital_sidetone_enum = 228*f10485e7SMark Brown SOC_ENUM_SINGLE(WM8990_DIGITAL_SIDE_TONE, 229*f10485e7SMark Brown WM8990_ADC_TO_DACL_SHIFT, 230*f10485e7SMark Brown WM8990_ADC_TO_DACL_MASK, 231*f10485e7SMark Brown wm8990_digital_sidetone); 232*f10485e7SMark Brown 233*f10485e7SMark Brown static const struct soc_enum wm8990_right_digital_sidetone_enum = 234*f10485e7SMark Brown SOC_ENUM_SINGLE(WM8990_DIGITAL_SIDE_TONE, 235*f10485e7SMark Brown WM8990_ADC_TO_DACR_SHIFT, 236*f10485e7SMark Brown WM8990_ADC_TO_DACR_MASK, 237*f10485e7SMark Brown wm8990_digital_sidetone); 238*f10485e7SMark Brown 239*f10485e7SMark Brown static const char *wm8990_adcmode[] = 240*f10485e7SMark Brown {"Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"}; 241*f10485e7SMark Brown 242*f10485e7SMark Brown static const struct soc_enum wm8990_right_adcmode_enum = 243*f10485e7SMark Brown SOC_ENUM_SINGLE(WM8990_ADC_CTRL, 244*f10485e7SMark Brown WM8990_ADC_HPF_CUT_SHIFT, 245*f10485e7SMark Brown WM8990_ADC_HPF_CUT_MASK, 246*f10485e7SMark Brown wm8990_adcmode); 247*f10485e7SMark Brown 248*f10485e7SMark Brown static const struct snd_kcontrol_new wm8990_snd_controls[] = { 249*f10485e7SMark Brown /* INMIXL */ 250*f10485e7SMark Brown SOC_SINGLE("LIN12 PGA Boost", WM8990_INPUT_MIXER3, WM8990_L12MNBST_BIT, 1, 0), 251*f10485e7SMark Brown SOC_SINGLE("LIN34 PGA Boost", WM8990_INPUT_MIXER3, WM8990_L34MNBST_BIT, 1, 0), 252*f10485e7SMark Brown /* INMIXR */ 253*f10485e7SMark Brown SOC_SINGLE("RIN12 PGA Boost", WM8990_INPUT_MIXER3, WM8990_R12MNBST_BIT, 1, 0), 254*f10485e7SMark Brown SOC_SINGLE("RIN34 PGA Boost", WM8990_INPUT_MIXER3, WM8990_R34MNBST_BIT, 1, 0), 255*f10485e7SMark Brown 256*f10485e7SMark Brown /* LOMIX */ 257*f10485e7SMark Brown SOC_SINGLE_TLV("LOMIX LIN3 Bypass Volume", WM8990_OUTPUT_MIXER3, 258*f10485e7SMark Brown WM8990_LLI3LOVOL_SHIFT, WM8990_LLI3LOVOL_MASK, 1, out_mix_tlv), 259*f10485e7SMark Brown SOC_SINGLE_TLV("LOMIX RIN12 PGA Bypass Volume", WM8990_OUTPUT_MIXER3, 260*f10485e7SMark Brown WM8990_LR12LOVOL_SHIFT, WM8990_LR12LOVOL_MASK, 1, out_mix_tlv), 261*f10485e7SMark Brown SOC_SINGLE_TLV("LOMIX LIN12 PGA Bypass Volume", WM8990_OUTPUT_MIXER3, 262*f10485e7SMark Brown WM8990_LL12LOVOL_SHIFT, WM8990_LL12LOVOL_MASK, 1, out_mix_tlv), 263*f10485e7SMark Brown SOC_SINGLE_TLV("LOMIX RIN3 Bypass Volume", WM8990_OUTPUT_MIXER5, 264*f10485e7SMark Brown WM8990_LRI3LOVOL_SHIFT, WM8990_LRI3LOVOL_MASK, 1, out_mix_tlv), 265*f10485e7SMark Brown SOC_SINGLE_TLV("LOMIX AINRMUX Bypass Volume", WM8990_OUTPUT_MIXER5, 266*f10485e7SMark Brown WM8990_LRBLOVOL_SHIFT, WM8990_LRBLOVOL_MASK, 1, out_mix_tlv), 267*f10485e7SMark Brown SOC_SINGLE_TLV("LOMIX AINLMUX Bypass Volume", WM8990_OUTPUT_MIXER5, 268*f10485e7SMark Brown WM8990_LRBLOVOL_SHIFT, WM8990_LRBLOVOL_MASK, 1, out_mix_tlv), 269*f10485e7SMark Brown 270*f10485e7SMark Brown /* ROMIX */ 271*f10485e7SMark Brown SOC_SINGLE_TLV("ROMIX RIN3 Bypass Volume", WM8990_OUTPUT_MIXER4, 272*f10485e7SMark Brown WM8990_RRI3ROVOL_SHIFT, WM8990_RRI3ROVOL_MASK, 1, out_mix_tlv), 273*f10485e7SMark Brown SOC_SINGLE_TLV("ROMIX LIN12 PGA Bypass Volume", WM8990_OUTPUT_MIXER4, 274*f10485e7SMark Brown WM8990_RL12ROVOL_SHIFT, WM8990_RL12ROVOL_MASK, 1, out_mix_tlv), 275*f10485e7SMark Brown SOC_SINGLE_TLV("ROMIX RIN12 PGA Bypass Volume", WM8990_OUTPUT_MIXER4, 276*f10485e7SMark Brown WM8990_RR12ROVOL_SHIFT, WM8990_RR12ROVOL_MASK, 1, out_mix_tlv), 277*f10485e7SMark Brown SOC_SINGLE_TLV("ROMIX LIN3 Bypass Volume", WM8990_OUTPUT_MIXER6, 278*f10485e7SMark Brown WM8990_RLI3ROVOL_SHIFT, WM8990_RLI3ROVOL_MASK, 1, out_mix_tlv), 279*f10485e7SMark Brown SOC_SINGLE_TLV("ROMIX AINLMUX Bypass Volume", WM8990_OUTPUT_MIXER6, 280*f10485e7SMark Brown WM8990_RLBROVOL_SHIFT, WM8990_RLBROVOL_MASK, 1, out_mix_tlv), 281*f10485e7SMark Brown SOC_SINGLE_TLV("ROMIX AINRMUX Bypass Volume", WM8990_OUTPUT_MIXER6, 282*f10485e7SMark Brown WM8990_RRBROVOL_SHIFT, WM8990_RRBROVOL_MASK, 1, out_mix_tlv), 283*f10485e7SMark Brown 284*f10485e7SMark Brown /* LOUT */ 285*f10485e7SMark Brown SOC_WM899X_OUTPGA_SINGLE_R_TLV("LOUT Volume", WM8990_LEFT_OUTPUT_VOLUME, 286*f10485e7SMark Brown WM8990_LOUTVOL_SHIFT, WM8990_LOUTVOL_MASK, 0, out_pga_tlv), 287*f10485e7SMark Brown SOC_SINGLE("LOUT ZC", WM8990_LEFT_OUTPUT_VOLUME, WM8990_LOZC_BIT, 1, 0), 288*f10485e7SMark Brown 289*f10485e7SMark Brown /* ROUT */ 290*f10485e7SMark Brown SOC_WM899X_OUTPGA_SINGLE_R_TLV("ROUT Volume", WM8990_RIGHT_OUTPUT_VOLUME, 291*f10485e7SMark Brown WM8990_ROUTVOL_SHIFT, WM8990_ROUTVOL_MASK, 0, out_pga_tlv), 292*f10485e7SMark Brown SOC_SINGLE("ROUT ZC", WM8990_RIGHT_OUTPUT_VOLUME, WM8990_ROZC_BIT, 1, 0), 293*f10485e7SMark Brown 294*f10485e7SMark Brown /* LOPGA */ 295*f10485e7SMark Brown SOC_WM899X_OUTPGA_SINGLE_R_TLV("LOPGA Volume", WM8990_LEFT_OPGA_VOLUME, 296*f10485e7SMark Brown WM8990_LOPGAVOL_SHIFT, WM8990_LOPGAVOL_MASK, 0, out_pga_tlv), 297*f10485e7SMark Brown SOC_SINGLE("LOPGA ZC Switch", WM8990_LEFT_OPGA_VOLUME, 298*f10485e7SMark Brown WM8990_LOPGAZC_BIT, 1, 0), 299*f10485e7SMark Brown 300*f10485e7SMark Brown /* ROPGA */ 301*f10485e7SMark Brown SOC_WM899X_OUTPGA_SINGLE_R_TLV("ROPGA Volume", WM8990_RIGHT_OPGA_VOLUME, 302*f10485e7SMark Brown WM8990_ROPGAVOL_SHIFT, WM8990_ROPGAVOL_MASK, 0, out_pga_tlv), 303*f10485e7SMark Brown SOC_SINGLE("ROPGA ZC Switch", WM8990_RIGHT_OPGA_VOLUME, 304*f10485e7SMark Brown WM8990_ROPGAZC_BIT, 1, 0), 305*f10485e7SMark Brown 306*f10485e7SMark Brown SOC_SINGLE("LON Mute Switch", WM8990_LINE_OUTPUTS_VOLUME, 307*f10485e7SMark Brown WM8990_LONMUTE_BIT, 1, 0), 308*f10485e7SMark Brown SOC_SINGLE("LOP Mute Switch", WM8990_LINE_OUTPUTS_VOLUME, 309*f10485e7SMark Brown WM8990_LOPMUTE_BIT, 1, 0), 310*f10485e7SMark Brown SOC_SINGLE("LOP Attenuation Switch", WM8990_LINE_OUTPUTS_VOLUME, 311*f10485e7SMark Brown WM8990_LOATTN_BIT, 1, 0), 312*f10485e7SMark Brown SOC_SINGLE("RON Mute Switch", WM8990_LINE_OUTPUTS_VOLUME, 313*f10485e7SMark Brown WM8990_RONMUTE_BIT, 1, 0), 314*f10485e7SMark Brown SOC_SINGLE("ROP Mute Switch", WM8990_LINE_OUTPUTS_VOLUME, 315*f10485e7SMark Brown WM8990_ROPMUTE_BIT, 1, 0), 316*f10485e7SMark Brown SOC_SINGLE("ROP Attenuation Switch", WM8990_LINE_OUTPUTS_VOLUME, 317*f10485e7SMark Brown WM8990_ROATTN_BIT, 1, 0), 318*f10485e7SMark Brown 319*f10485e7SMark Brown SOC_SINGLE("OUT3 Mute Switch", WM8990_OUT3_4_VOLUME, 320*f10485e7SMark Brown WM8990_OUT3MUTE_BIT, 1, 0), 321*f10485e7SMark Brown SOC_SINGLE("OUT3 Attenuation Switch", WM8990_OUT3_4_VOLUME, 322*f10485e7SMark Brown WM8990_OUT3ATTN_BIT, 1, 0), 323*f10485e7SMark Brown 324*f10485e7SMark Brown SOC_SINGLE("OUT4 Mute Switch", WM8990_OUT3_4_VOLUME, 325*f10485e7SMark Brown WM8990_OUT4MUTE_BIT, 1, 0), 326*f10485e7SMark Brown SOC_SINGLE("OUT4 Attenuation Switch", WM8990_OUT3_4_VOLUME, 327*f10485e7SMark Brown WM8990_OUT4ATTN_BIT, 1, 0), 328*f10485e7SMark Brown 329*f10485e7SMark Brown SOC_SINGLE("Speaker Mode Switch", WM8990_CLASSD1, 330*f10485e7SMark Brown WM8990_CDMODE_BIT, 1, 0), 331*f10485e7SMark Brown 332*f10485e7SMark Brown SOC_SINGLE("Speaker Output Attenuation Volume", WM8990_SPEAKER_VOLUME, 333*f10485e7SMark Brown WM8990_SPKVOL_SHIFT, WM8990_SPKVOL_MASK, 0), 334*f10485e7SMark Brown SOC_SINGLE("Speaker DC Boost Volume", WM8990_CLASSD3, 335*f10485e7SMark Brown WM8990_DCGAIN_SHIFT, WM8990_DCGAIN_MASK, 0), 336*f10485e7SMark Brown SOC_SINGLE("Speaker AC Boost Volume", WM8990_CLASSD3, 337*f10485e7SMark Brown WM8990_ACGAIN_SHIFT, WM8990_ACGAIN_MASK, 0), 338*f10485e7SMark Brown 339*f10485e7SMark Brown SOC_WM899X_OUTPGA_SINGLE_R_TLV("Left DAC Digital Volume", 340*f10485e7SMark Brown WM8990_LEFT_DAC_DIGITAL_VOLUME, 341*f10485e7SMark Brown WM8990_DACL_VOL_SHIFT, 342*f10485e7SMark Brown WM8990_DACL_VOL_MASK, 343*f10485e7SMark Brown 0, 344*f10485e7SMark Brown out_dac_tlv), 345*f10485e7SMark Brown 346*f10485e7SMark Brown SOC_WM899X_OUTPGA_SINGLE_R_TLV("Right DAC Digital Volume", 347*f10485e7SMark Brown WM8990_RIGHT_DAC_DIGITAL_VOLUME, 348*f10485e7SMark Brown WM8990_DACR_VOL_SHIFT, 349*f10485e7SMark Brown WM8990_DACR_VOL_MASK, 350*f10485e7SMark Brown 0, 351*f10485e7SMark Brown out_dac_tlv), 352*f10485e7SMark Brown 353*f10485e7SMark Brown SOC_ENUM("Left Digital Sidetone", wm8990_left_digital_sidetone_enum), 354*f10485e7SMark Brown SOC_ENUM("Right Digital Sidetone", wm8990_right_digital_sidetone_enum), 355*f10485e7SMark Brown 356*f10485e7SMark Brown SOC_SINGLE_TLV("Left Digital Sidetone Volume", WM8990_DIGITAL_SIDE_TONE, 357*f10485e7SMark Brown WM8990_ADCL_DAC_SVOL_SHIFT, WM8990_ADCL_DAC_SVOL_MASK, 0, 358*f10485e7SMark Brown out_sidetone_tlv), 359*f10485e7SMark Brown SOC_SINGLE_TLV("Right Digital Sidetone Volume", WM8990_DIGITAL_SIDE_TONE, 360*f10485e7SMark Brown WM8990_ADCR_DAC_SVOL_SHIFT, WM8990_ADCR_DAC_SVOL_MASK, 0, 361*f10485e7SMark Brown out_sidetone_tlv), 362*f10485e7SMark Brown 363*f10485e7SMark Brown SOC_SINGLE("ADC Digital High Pass Filter Switch", WM8990_ADC_CTRL, 364*f10485e7SMark Brown WM8990_ADC_HPF_ENA_BIT, 1, 0), 365*f10485e7SMark Brown 366*f10485e7SMark Brown SOC_ENUM("ADC HPF Mode", wm8990_right_adcmode_enum), 367*f10485e7SMark Brown 368*f10485e7SMark Brown SOC_WM899X_OUTPGA_SINGLE_R_TLV("Left ADC Digital Volume", 369*f10485e7SMark Brown WM8990_LEFT_ADC_DIGITAL_VOLUME, 370*f10485e7SMark Brown WM8990_ADCL_VOL_SHIFT, 371*f10485e7SMark Brown WM8990_ADCL_VOL_MASK, 372*f10485e7SMark Brown 0, 373*f10485e7SMark Brown in_adc_tlv), 374*f10485e7SMark Brown 375*f10485e7SMark Brown SOC_WM899X_OUTPGA_SINGLE_R_TLV("Right ADC Digital Volume", 376*f10485e7SMark Brown WM8990_RIGHT_ADC_DIGITAL_VOLUME, 377*f10485e7SMark Brown WM8990_ADCR_VOL_SHIFT, 378*f10485e7SMark Brown WM8990_ADCR_VOL_MASK, 379*f10485e7SMark Brown 0, 380*f10485e7SMark Brown in_adc_tlv), 381*f10485e7SMark Brown 382*f10485e7SMark Brown SOC_WM899X_OUTPGA_SINGLE_R_TLV("LIN12 Volume", 383*f10485e7SMark Brown WM8990_LEFT_LINE_INPUT_1_2_VOLUME, 384*f10485e7SMark Brown WM8990_LIN12VOL_SHIFT, 385*f10485e7SMark Brown WM8990_LIN12VOL_MASK, 386*f10485e7SMark Brown 0, 387*f10485e7SMark Brown in_pga_tlv), 388*f10485e7SMark Brown 389*f10485e7SMark Brown SOC_SINGLE("LIN12 ZC Switch", WM8990_LEFT_LINE_INPUT_1_2_VOLUME, 390*f10485e7SMark Brown WM8990_LI12ZC_BIT, 1, 0), 391*f10485e7SMark Brown 392*f10485e7SMark Brown SOC_SINGLE("LIN12 Mute Switch", WM8990_LEFT_LINE_INPUT_1_2_VOLUME, 393*f10485e7SMark Brown WM8990_LI12MUTE_BIT, 1, 0), 394*f10485e7SMark Brown 395*f10485e7SMark Brown SOC_WM899X_OUTPGA_SINGLE_R_TLV("LIN34 Volume", 396*f10485e7SMark Brown WM8990_LEFT_LINE_INPUT_3_4_VOLUME, 397*f10485e7SMark Brown WM8990_LIN34VOL_SHIFT, 398*f10485e7SMark Brown WM8990_LIN34VOL_MASK, 399*f10485e7SMark Brown 0, 400*f10485e7SMark Brown in_pga_tlv), 401*f10485e7SMark Brown 402*f10485e7SMark Brown SOC_SINGLE("LIN34 ZC Switch", WM8990_LEFT_LINE_INPUT_3_4_VOLUME, 403*f10485e7SMark Brown WM8990_LI34ZC_BIT, 1, 0), 404*f10485e7SMark Brown 405*f10485e7SMark Brown SOC_SINGLE("LIN34 Mute Switch", WM8990_LEFT_LINE_INPUT_3_4_VOLUME, 406*f10485e7SMark Brown WM8990_LI34MUTE_BIT, 1, 0), 407*f10485e7SMark Brown 408*f10485e7SMark Brown SOC_WM899X_OUTPGA_SINGLE_R_TLV("RIN12 Volume", 409*f10485e7SMark Brown WM8990_RIGHT_LINE_INPUT_1_2_VOLUME, 410*f10485e7SMark Brown WM8990_RIN12VOL_SHIFT, 411*f10485e7SMark Brown WM8990_RIN12VOL_MASK, 412*f10485e7SMark Brown 0, 413*f10485e7SMark Brown in_pga_tlv), 414*f10485e7SMark Brown 415*f10485e7SMark Brown SOC_SINGLE("RIN12 ZC Switch", WM8990_RIGHT_LINE_INPUT_1_2_VOLUME, 416*f10485e7SMark Brown WM8990_RI12ZC_BIT, 1, 0), 417*f10485e7SMark Brown 418*f10485e7SMark Brown SOC_SINGLE("RIN12 Mute Switch", WM8990_RIGHT_LINE_INPUT_1_2_VOLUME, 419*f10485e7SMark Brown WM8990_RI12MUTE_BIT, 1, 0), 420*f10485e7SMark Brown 421*f10485e7SMark Brown SOC_WM899X_OUTPGA_SINGLE_R_TLV("RIN34 Volume", 422*f10485e7SMark Brown WM8990_RIGHT_LINE_INPUT_3_4_VOLUME, 423*f10485e7SMark Brown WM8990_RIN34VOL_SHIFT, 424*f10485e7SMark Brown WM8990_RIN34VOL_MASK, 425*f10485e7SMark Brown 0, 426*f10485e7SMark Brown in_pga_tlv), 427*f10485e7SMark Brown 428*f10485e7SMark Brown SOC_SINGLE("RIN34 ZC Switch", WM8990_RIGHT_LINE_INPUT_3_4_VOLUME, 429*f10485e7SMark Brown WM8990_RI34ZC_BIT, 1, 0), 430*f10485e7SMark Brown 431*f10485e7SMark Brown SOC_SINGLE("RIN34 Mute Switch", WM8990_RIGHT_LINE_INPUT_3_4_VOLUME, 432*f10485e7SMark Brown WM8990_RI34MUTE_BIT, 1, 0), 433*f10485e7SMark Brown 434*f10485e7SMark Brown }; 435*f10485e7SMark Brown 436*f10485e7SMark Brown /* add non dapm controls */ 437*f10485e7SMark Brown static int wm8990_add_controls(struct snd_soc_codec *codec) 438*f10485e7SMark Brown { 439*f10485e7SMark Brown int err, i; 440*f10485e7SMark Brown 441*f10485e7SMark Brown for (i = 0; i < ARRAY_SIZE(wm8990_snd_controls); i++) { 442*f10485e7SMark Brown err = snd_ctl_add(codec->card, 443*f10485e7SMark Brown snd_soc_cnew(&wm8990_snd_controls[i], codec, 444*f10485e7SMark Brown NULL)); 445*f10485e7SMark Brown if (err < 0) 446*f10485e7SMark Brown return err; 447*f10485e7SMark Brown } 448*f10485e7SMark Brown return 0; 449*f10485e7SMark Brown } 450*f10485e7SMark Brown 451*f10485e7SMark Brown /* 452*f10485e7SMark Brown * _DAPM_ Controls 453*f10485e7SMark Brown */ 454*f10485e7SMark Brown 455*f10485e7SMark Brown static int inmixer_event(struct snd_soc_dapm_widget *w, 456*f10485e7SMark Brown struct snd_kcontrol *kcontrol, int event) 457*f10485e7SMark Brown { 458*f10485e7SMark Brown u16 reg, fakepower; 459*f10485e7SMark Brown 460*f10485e7SMark Brown reg = wm8990_read_reg_cache(w->codec, WM8990_POWER_MANAGEMENT_2); 461*f10485e7SMark Brown fakepower = wm8990_read_reg_cache(w->codec, WM8990_INTDRIVBITS); 462*f10485e7SMark Brown 463*f10485e7SMark Brown if (fakepower & ((1 << WM8990_INMIXL_PWR_BIT) | 464*f10485e7SMark Brown (1 << WM8990_AINLMUX_PWR_BIT))) { 465*f10485e7SMark Brown reg |= WM8990_AINL_ENA; 466*f10485e7SMark Brown } else { 467*f10485e7SMark Brown reg &= ~WM8990_AINL_ENA; 468*f10485e7SMark Brown } 469*f10485e7SMark Brown 470*f10485e7SMark Brown if (fakepower & ((1 << WM8990_INMIXR_PWR_BIT) | 471*f10485e7SMark Brown (1 << WM8990_AINRMUX_PWR_BIT))) { 472*f10485e7SMark Brown reg |= WM8990_AINR_ENA; 473*f10485e7SMark Brown } else { 474*f10485e7SMark Brown reg &= ~WM8990_AINL_ENA; 475*f10485e7SMark Brown } 476*f10485e7SMark Brown wm8990_write(w->codec, WM8990_POWER_MANAGEMENT_2, reg); 477*f10485e7SMark Brown 478*f10485e7SMark Brown return 0; 479*f10485e7SMark Brown } 480*f10485e7SMark Brown 481*f10485e7SMark Brown static int outmixer_event(struct snd_soc_dapm_widget *w, 482*f10485e7SMark Brown struct snd_kcontrol *kcontrol, int event) 483*f10485e7SMark Brown { 484*f10485e7SMark Brown u32 reg_shift = kcontrol->private_value & 0xfff; 485*f10485e7SMark Brown int ret = 0; 486*f10485e7SMark Brown u16 reg; 487*f10485e7SMark Brown 488*f10485e7SMark Brown switch (reg_shift) { 489*f10485e7SMark Brown case WM8990_SPEAKER_MIXER | (WM8990_LDSPK_BIT << 8) : 490*f10485e7SMark Brown reg = wm8990_read_reg_cache(w->codec, WM8990_OUTPUT_MIXER1); 491*f10485e7SMark Brown if (reg & WM8990_LDLO) { 492*f10485e7SMark Brown printk(KERN_WARNING 493*f10485e7SMark Brown "Cannot set as Output Mixer 1 LDLO Set\n"); 494*f10485e7SMark Brown ret = -1; 495*f10485e7SMark Brown } 496*f10485e7SMark Brown break; 497*f10485e7SMark Brown case WM8990_SPEAKER_MIXER | (WM8990_RDSPK_BIT << 8): 498*f10485e7SMark Brown reg = wm8990_read_reg_cache(w->codec, WM8990_OUTPUT_MIXER2); 499*f10485e7SMark Brown if (reg & WM8990_RDRO) { 500*f10485e7SMark Brown printk(KERN_WARNING 501*f10485e7SMark Brown "Cannot set as Output Mixer 2 RDRO Set\n"); 502*f10485e7SMark Brown ret = -1; 503*f10485e7SMark Brown } 504*f10485e7SMark Brown break; 505*f10485e7SMark Brown case WM8990_OUTPUT_MIXER1 | (WM8990_LDLO_BIT << 8): 506*f10485e7SMark Brown reg = wm8990_read_reg_cache(w->codec, WM8990_SPEAKER_MIXER); 507*f10485e7SMark Brown if (reg & WM8990_LDSPK) { 508*f10485e7SMark Brown printk(KERN_WARNING 509*f10485e7SMark Brown "Cannot set as Speaker Mixer LDSPK Set\n"); 510*f10485e7SMark Brown ret = -1; 511*f10485e7SMark Brown } 512*f10485e7SMark Brown break; 513*f10485e7SMark Brown case WM8990_OUTPUT_MIXER2 | (WM8990_RDRO_BIT << 8): 514*f10485e7SMark Brown reg = wm8990_read_reg_cache(w->codec, WM8990_SPEAKER_MIXER); 515*f10485e7SMark Brown if (reg & WM8990_RDSPK) { 516*f10485e7SMark Brown printk(KERN_WARNING 517*f10485e7SMark Brown "Cannot set as Speaker Mixer RDSPK Set\n"); 518*f10485e7SMark Brown ret = -1; 519*f10485e7SMark Brown } 520*f10485e7SMark Brown break; 521*f10485e7SMark Brown } 522*f10485e7SMark Brown 523*f10485e7SMark Brown return ret; 524*f10485e7SMark Brown } 525*f10485e7SMark Brown 526*f10485e7SMark Brown /* INMIX dB values */ 527*f10485e7SMark Brown static const unsigned int in_mix_tlv[] = { 528*f10485e7SMark Brown TLV_DB_RANGE_HEAD(1), 529*f10485e7SMark Brown 0, 7, TLV_DB_LINEAR_ITEM(-1200, 600), 530*f10485e7SMark Brown }; 531*f10485e7SMark Brown 532*f10485e7SMark Brown /* Left In PGA Connections */ 533*f10485e7SMark Brown static const struct snd_kcontrol_new wm8990_dapm_lin12_pga_controls[] = { 534*f10485e7SMark Brown SOC_DAPM_SINGLE("LIN1 Switch", WM8990_INPUT_MIXER2, WM8990_LMN1_BIT, 1, 0), 535*f10485e7SMark Brown SOC_DAPM_SINGLE("LIN2 Switch", WM8990_INPUT_MIXER2, WM8990_LMP2_BIT, 1, 0), 536*f10485e7SMark Brown }; 537*f10485e7SMark Brown 538*f10485e7SMark Brown static const struct snd_kcontrol_new wm8990_dapm_lin34_pga_controls[] = { 539*f10485e7SMark Brown SOC_DAPM_SINGLE("LIN3 Switch", WM8990_INPUT_MIXER2, WM8990_LMN3_BIT, 1, 0), 540*f10485e7SMark Brown SOC_DAPM_SINGLE("LIN4 Switch", WM8990_INPUT_MIXER2, WM8990_LMP4_BIT, 1, 0), 541*f10485e7SMark Brown }; 542*f10485e7SMark Brown 543*f10485e7SMark Brown /* Right In PGA Connections */ 544*f10485e7SMark Brown static const struct snd_kcontrol_new wm8990_dapm_rin12_pga_controls[] = { 545*f10485e7SMark Brown SOC_DAPM_SINGLE("RIN1 Switch", WM8990_INPUT_MIXER2, WM8990_RMN1_BIT, 1, 0), 546*f10485e7SMark Brown SOC_DAPM_SINGLE("RIN2 Switch", WM8990_INPUT_MIXER2, WM8990_RMP2_BIT, 1, 0), 547*f10485e7SMark Brown }; 548*f10485e7SMark Brown 549*f10485e7SMark Brown static const struct snd_kcontrol_new wm8990_dapm_rin34_pga_controls[] = { 550*f10485e7SMark Brown SOC_DAPM_SINGLE("RIN3 Switch", WM8990_INPUT_MIXER2, WM8990_RMN3_BIT, 1, 0), 551*f10485e7SMark Brown SOC_DAPM_SINGLE("RIN4 Switch", WM8990_INPUT_MIXER2, WM8990_RMP4_BIT, 1, 0), 552*f10485e7SMark Brown }; 553*f10485e7SMark Brown 554*f10485e7SMark Brown /* INMIXL */ 555*f10485e7SMark Brown static const struct snd_kcontrol_new wm8990_dapm_inmixl_controls[] = { 556*f10485e7SMark Brown SOC_DAPM_SINGLE_TLV("Record Left Volume", WM8990_INPUT_MIXER3, 557*f10485e7SMark Brown WM8990_LDBVOL_SHIFT, WM8990_LDBVOL_MASK, 0, in_mix_tlv), 558*f10485e7SMark Brown SOC_DAPM_SINGLE_TLV("LIN2 Volume", WM8990_INPUT_MIXER5, WM8990_LI2BVOL_SHIFT, 559*f10485e7SMark Brown 7, 0, in_mix_tlv), 560*f10485e7SMark Brown SOC_DAPM_SINGLE("LINPGA12 Switch", WM8990_INPUT_MIXER3, WM8990_L12MNB_BIT, 561*f10485e7SMark Brown 1, 0), 562*f10485e7SMark Brown SOC_DAPM_SINGLE("LINPGA34 Switch", WM8990_INPUT_MIXER3, WM8990_L34MNB_BIT, 563*f10485e7SMark Brown 1, 0), 564*f10485e7SMark Brown }; 565*f10485e7SMark Brown 566*f10485e7SMark Brown /* INMIXR */ 567*f10485e7SMark Brown static const struct snd_kcontrol_new wm8990_dapm_inmixr_controls[] = { 568*f10485e7SMark Brown SOC_DAPM_SINGLE_TLV("Record Right Volume", WM8990_INPUT_MIXER4, 569*f10485e7SMark Brown WM8990_RDBVOL_SHIFT, WM8990_RDBVOL_MASK, 0, in_mix_tlv), 570*f10485e7SMark Brown SOC_DAPM_SINGLE_TLV("RIN2 Volume", WM8990_INPUT_MIXER6, WM8990_RI2BVOL_SHIFT, 571*f10485e7SMark Brown 7, 0, in_mix_tlv), 572*f10485e7SMark Brown SOC_DAPM_SINGLE("RINPGA12 Switch", WM8990_INPUT_MIXER3, WM8990_L12MNB_BIT, 573*f10485e7SMark Brown 1, 0), 574*f10485e7SMark Brown SOC_DAPM_SINGLE("RINPGA34 Switch", WM8990_INPUT_MIXER3, WM8990_L34MNB_BIT, 575*f10485e7SMark Brown 1, 0), 576*f10485e7SMark Brown }; 577*f10485e7SMark Brown 578*f10485e7SMark Brown /* AINLMUX */ 579*f10485e7SMark Brown static const char *wm8990_ainlmux[] = 580*f10485e7SMark Brown {"INMIXL Mix", "RXVOICE Mix", "DIFFINL Mix"}; 581*f10485e7SMark Brown 582*f10485e7SMark Brown static const struct soc_enum wm8990_ainlmux_enum = 583*f10485e7SMark Brown SOC_ENUM_SINGLE(WM8990_INPUT_MIXER1, WM8990_AINLMODE_SHIFT, 584*f10485e7SMark Brown ARRAY_SIZE(wm8990_ainlmux), wm8990_ainlmux); 585*f10485e7SMark Brown 586*f10485e7SMark Brown static const struct snd_kcontrol_new wm8990_dapm_ainlmux_controls = 587*f10485e7SMark Brown SOC_DAPM_ENUM("Route", wm8990_ainlmux_enum); 588*f10485e7SMark Brown 589*f10485e7SMark Brown /* DIFFINL */ 590*f10485e7SMark Brown 591*f10485e7SMark Brown /* AINRMUX */ 592*f10485e7SMark Brown static const char *wm8990_ainrmux[] = 593*f10485e7SMark Brown {"INMIXR Mix", "RXVOICE Mix", "DIFFINR Mix"}; 594*f10485e7SMark Brown 595*f10485e7SMark Brown static const struct soc_enum wm8990_ainrmux_enum = 596*f10485e7SMark Brown SOC_ENUM_SINGLE(WM8990_INPUT_MIXER1, WM8990_AINRMODE_SHIFT, 597*f10485e7SMark Brown ARRAY_SIZE(wm8990_ainrmux), wm8990_ainrmux); 598*f10485e7SMark Brown 599*f10485e7SMark Brown static const struct snd_kcontrol_new wm8990_dapm_ainrmux_controls = 600*f10485e7SMark Brown SOC_DAPM_ENUM("Route", wm8990_ainrmux_enum); 601*f10485e7SMark Brown 602*f10485e7SMark Brown /* RXVOICE */ 603*f10485e7SMark Brown static const struct snd_kcontrol_new wm8990_dapm_rxvoice_controls[] = { 604*f10485e7SMark Brown SOC_DAPM_SINGLE_TLV("LIN4/RXN", WM8990_INPUT_MIXER5, WM8990_LR4BVOL_SHIFT, 605*f10485e7SMark Brown WM8990_LR4BVOL_MASK, 0, in_mix_tlv), 606*f10485e7SMark Brown SOC_DAPM_SINGLE_TLV("RIN4/RXP", WM8990_INPUT_MIXER6, WM8990_RL4BVOL_SHIFT, 607*f10485e7SMark Brown WM8990_RL4BVOL_MASK, 0, in_mix_tlv), 608*f10485e7SMark Brown }; 609*f10485e7SMark Brown 610*f10485e7SMark Brown /* LOMIX */ 611*f10485e7SMark Brown static const struct snd_kcontrol_new wm8990_dapm_lomix_controls[] = { 612*f10485e7SMark Brown SOC_DAPM_SINGLE("LOMIX Right ADC Bypass Switch", WM8990_OUTPUT_MIXER1, 613*f10485e7SMark Brown WM8990_LRBLO_BIT, 1, 0), 614*f10485e7SMark Brown SOC_DAPM_SINGLE("LOMIX Left ADC Bypass Switch", WM8990_OUTPUT_MIXER1, 615*f10485e7SMark Brown WM8990_LLBLO_BIT, 1, 0), 616*f10485e7SMark Brown SOC_DAPM_SINGLE("LOMIX RIN3 Bypass Switch", WM8990_OUTPUT_MIXER1, 617*f10485e7SMark Brown WM8990_LRI3LO_BIT, 1, 0), 618*f10485e7SMark Brown SOC_DAPM_SINGLE("LOMIX LIN3 Bypass Switch", WM8990_OUTPUT_MIXER1, 619*f10485e7SMark Brown WM8990_LLI3LO_BIT, 1, 0), 620*f10485e7SMark Brown SOC_DAPM_SINGLE("LOMIX RIN12 PGA Bypass Switch", WM8990_OUTPUT_MIXER1, 621*f10485e7SMark Brown WM8990_LR12LO_BIT, 1, 0), 622*f10485e7SMark Brown SOC_DAPM_SINGLE("LOMIX LIN12 PGA Bypass Switch", WM8990_OUTPUT_MIXER1, 623*f10485e7SMark Brown WM8990_LL12LO_BIT, 1, 0), 624*f10485e7SMark Brown SOC_DAPM_SINGLE("LOMIX Left DAC Switch", WM8990_OUTPUT_MIXER1, 625*f10485e7SMark Brown WM8990_LDLO_BIT, 1, 0), 626*f10485e7SMark Brown }; 627*f10485e7SMark Brown 628*f10485e7SMark Brown /* ROMIX */ 629*f10485e7SMark Brown static const struct snd_kcontrol_new wm8990_dapm_romix_controls[] = { 630*f10485e7SMark Brown SOC_DAPM_SINGLE("ROMIX Left ADC Bypass Switch", WM8990_OUTPUT_MIXER2, 631*f10485e7SMark Brown WM8990_RLBRO_BIT, 1, 0), 632*f10485e7SMark Brown SOC_DAPM_SINGLE("ROMIX Right ADC Bypass Switch", WM8990_OUTPUT_MIXER2, 633*f10485e7SMark Brown WM8990_RRBRO_BIT, 1, 0), 634*f10485e7SMark Brown SOC_DAPM_SINGLE("ROMIX LIN3 Bypass Switch", WM8990_OUTPUT_MIXER2, 635*f10485e7SMark Brown WM8990_RLI3RO_BIT, 1, 0), 636*f10485e7SMark Brown SOC_DAPM_SINGLE("ROMIX RIN3 Bypass Switch", WM8990_OUTPUT_MIXER2, 637*f10485e7SMark Brown WM8990_RRI3RO_BIT, 1, 0), 638*f10485e7SMark Brown SOC_DAPM_SINGLE("ROMIX LIN12 PGA Bypass Switch", WM8990_OUTPUT_MIXER2, 639*f10485e7SMark Brown WM8990_RL12RO_BIT, 1, 0), 640*f10485e7SMark Brown SOC_DAPM_SINGLE("ROMIX RIN12 PGA Bypass Switch", WM8990_OUTPUT_MIXER2, 641*f10485e7SMark Brown WM8990_RR12RO_BIT, 1, 0), 642*f10485e7SMark Brown SOC_DAPM_SINGLE("ROMIX Right DAC Switch", WM8990_OUTPUT_MIXER2, 643*f10485e7SMark Brown WM8990_RDRO_BIT, 1, 0), 644*f10485e7SMark Brown }; 645*f10485e7SMark Brown 646*f10485e7SMark Brown /* LONMIX */ 647*f10485e7SMark Brown static const struct snd_kcontrol_new wm8990_dapm_lonmix_controls[] = { 648*f10485e7SMark Brown SOC_DAPM_SINGLE("LONMIX Left Mixer PGA Switch", WM8990_LINE_MIXER1, 649*f10485e7SMark Brown WM8990_LLOPGALON_BIT, 1, 0), 650*f10485e7SMark Brown SOC_DAPM_SINGLE("LONMIX Right Mixer PGA Switch", WM8990_LINE_MIXER1, 651*f10485e7SMark Brown WM8990_LROPGALON_BIT, 1, 0), 652*f10485e7SMark Brown SOC_DAPM_SINGLE("LONMIX Inverted LOP Switch", WM8990_LINE_MIXER1, 653*f10485e7SMark Brown WM8990_LOPLON_BIT, 1, 0), 654*f10485e7SMark Brown }; 655*f10485e7SMark Brown 656*f10485e7SMark Brown /* LOPMIX */ 657*f10485e7SMark Brown static const struct snd_kcontrol_new wm8990_dapm_lopmix_controls[] = { 658*f10485e7SMark Brown SOC_DAPM_SINGLE("LOPMIX Right Mic Bypass Switch", WM8990_LINE_MIXER1, 659*f10485e7SMark Brown WM8990_LR12LOP_BIT, 1, 0), 660*f10485e7SMark Brown SOC_DAPM_SINGLE("LOPMIX Left Mic Bypass Switch", WM8990_LINE_MIXER1, 661*f10485e7SMark Brown WM8990_LL12LOP_BIT, 1, 0), 662*f10485e7SMark Brown SOC_DAPM_SINGLE("LOPMIX Left Mixer PGA Switch", WM8990_LINE_MIXER1, 663*f10485e7SMark Brown WM8990_LLOPGALOP_BIT, 1, 0), 664*f10485e7SMark Brown }; 665*f10485e7SMark Brown 666*f10485e7SMark Brown /* RONMIX */ 667*f10485e7SMark Brown static const struct snd_kcontrol_new wm8990_dapm_ronmix_controls[] = { 668*f10485e7SMark Brown SOC_DAPM_SINGLE("RONMIX Right Mixer PGA Switch", WM8990_LINE_MIXER2, 669*f10485e7SMark Brown WM8990_RROPGARON_BIT, 1, 0), 670*f10485e7SMark Brown SOC_DAPM_SINGLE("RONMIX Left Mixer PGA Switch", WM8990_LINE_MIXER2, 671*f10485e7SMark Brown WM8990_RLOPGARON_BIT, 1, 0), 672*f10485e7SMark Brown SOC_DAPM_SINGLE("RONMIX Inverted ROP Switch", WM8990_LINE_MIXER2, 673*f10485e7SMark Brown WM8990_ROPRON_BIT, 1, 0), 674*f10485e7SMark Brown }; 675*f10485e7SMark Brown 676*f10485e7SMark Brown /* ROPMIX */ 677*f10485e7SMark Brown static const struct snd_kcontrol_new wm8990_dapm_ropmix_controls[] = { 678*f10485e7SMark Brown SOC_DAPM_SINGLE("ROPMIX Left Mic Bypass Switch", WM8990_LINE_MIXER2, 679*f10485e7SMark Brown WM8990_RL12ROP_BIT, 1, 0), 680*f10485e7SMark Brown SOC_DAPM_SINGLE("ROPMIX Right Mic Bypass Switch", WM8990_LINE_MIXER2, 681*f10485e7SMark Brown WM8990_RR12ROP_BIT, 1, 0), 682*f10485e7SMark Brown SOC_DAPM_SINGLE("ROPMIX Right Mixer PGA Switch", WM8990_LINE_MIXER2, 683*f10485e7SMark Brown WM8990_RROPGAROP_BIT, 1, 0), 684*f10485e7SMark Brown }; 685*f10485e7SMark Brown 686*f10485e7SMark Brown /* OUT3MIX */ 687*f10485e7SMark Brown static const struct snd_kcontrol_new wm8990_dapm_out3mix_controls[] = { 688*f10485e7SMark Brown SOC_DAPM_SINGLE("OUT3MIX LIN4/RXP Bypass Switch", WM8990_OUT3_4_MIXER, 689*f10485e7SMark Brown WM8990_LI4O3_BIT, 1, 0), 690*f10485e7SMark Brown SOC_DAPM_SINGLE("OUT3MIX Left Out PGA Switch", WM8990_OUT3_4_MIXER, 691*f10485e7SMark Brown WM8990_LPGAO3_BIT, 1, 0), 692*f10485e7SMark Brown }; 693*f10485e7SMark Brown 694*f10485e7SMark Brown /* OUT4MIX */ 695*f10485e7SMark Brown static const struct snd_kcontrol_new wm8990_dapm_out4mix_controls[] = { 696*f10485e7SMark Brown SOC_DAPM_SINGLE("OUT4MIX Right Out PGA Switch", WM8990_OUT3_4_MIXER, 697*f10485e7SMark Brown WM8990_RPGAO4_BIT, 1, 0), 698*f10485e7SMark Brown SOC_DAPM_SINGLE("OUT4MIX RIN4/RXP Bypass Switch", WM8990_OUT3_4_MIXER, 699*f10485e7SMark Brown WM8990_RI4O4_BIT, 1, 0), 700*f10485e7SMark Brown }; 701*f10485e7SMark Brown 702*f10485e7SMark Brown /* SPKMIX */ 703*f10485e7SMark Brown static const struct snd_kcontrol_new wm8990_dapm_spkmix_controls[] = { 704*f10485e7SMark Brown SOC_DAPM_SINGLE("SPKMIX LIN2 Bypass Switch", WM8990_SPEAKER_MIXER, 705*f10485e7SMark Brown WM8990_LI2SPK_BIT, 1, 0), 706*f10485e7SMark Brown SOC_DAPM_SINGLE("SPKMIX LADC Bypass Switch", WM8990_SPEAKER_MIXER, 707*f10485e7SMark Brown WM8990_LB2SPK_BIT, 1, 0), 708*f10485e7SMark Brown SOC_DAPM_SINGLE("SPKMIX Left Mixer PGA Switch", WM8990_SPEAKER_MIXER, 709*f10485e7SMark Brown WM8990_LOPGASPK_BIT, 1, 0), 710*f10485e7SMark Brown SOC_DAPM_SINGLE("SPKMIX Left DAC Switch", WM8990_SPEAKER_MIXER, 711*f10485e7SMark Brown WM8990_LDSPK_BIT, 1, 0), 712*f10485e7SMark Brown SOC_DAPM_SINGLE("SPKMIX Right DAC Switch", WM8990_SPEAKER_MIXER, 713*f10485e7SMark Brown WM8990_RDSPK_BIT, 1, 0), 714*f10485e7SMark Brown SOC_DAPM_SINGLE("SPKMIX Right Mixer PGA Switch", WM8990_SPEAKER_MIXER, 715*f10485e7SMark Brown WM8990_ROPGASPK_BIT, 1, 0), 716*f10485e7SMark Brown SOC_DAPM_SINGLE("SPKMIX RADC Bypass Switch", WM8990_SPEAKER_MIXER, 717*f10485e7SMark Brown WM8990_RL12ROP_BIT, 1, 0), 718*f10485e7SMark Brown SOC_DAPM_SINGLE("SPKMIX RIN2 Bypass Switch", WM8990_SPEAKER_MIXER, 719*f10485e7SMark Brown WM8990_RI2SPK_BIT, 1, 0), 720*f10485e7SMark Brown }; 721*f10485e7SMark Brown 722*f10485e7SMark Brown static const struct snd_soc_dapm_widget wm8990_dapm_widgets[] = { 723*f10485e7SMark Brown /* Input Side */ 724*f10485e7SMark Brown /* Input Lines */ 725*f10485e7SMark Brown SND_SOC_DAPM_INPUT("LIN1"), 726*f10485e7SMark Brown SND_SOC_DAPM_INPUT("LIN2"), 727*f10485e7SMark Brown SND_SOC_DAPM_INPUT("LIN3"), 728*f10485e7SMark Brown SND_SOC_DAPM_INPUT("LIN4/RXN"), 729*f10485e7SMark Brown SND_SOC_DAPM_INPUT("RIN3"), 730*f10485e7SMark Brown SND_SOC_DAPM_INPUT("RIN4/RXP"), 731*f10485e7SMark Brown SND_SOC_DAPM_INPUT("RIN1"), 732*f10485e7SMark Brown SND_SOC_DAPM_INPUT("RIN2"), 733*f10485e7SMark Brown SND_SOC_DAPM_INPUT("Internal ADC Source"), 734*f10485e7SMark Brown 735*f10485e7SMark Brown /* DACs */ 736*f10485e7SMark Brown SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8990_POWER_MANAGEMENT_2, 737*f10485e7SMark Brown WM8990_ADCL_ENA_BIT, 0), 738*f10485e7SMark Brown SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8990_POWER_MANAGEMENT_2, 739*f10485e7SMark Brown WM8990_ADCR_ENA_BIT, 0), 740*f10485e7SMark Brown 741*f10485e7SMark Brown /* Input PGAs */ 742*f10485e7SMark Brown SND_SOC_DAPM_MIXER("LIN12 PGA", WM8990_POWER_MANAGEMENT_2, WM8990_LIN12_ENA_BIT, 743*f10485e7SMark Brown 0, &wm8990_dapm_lin12_pga_controls[0], 744*f10485e7SMark Brown ARRAY_SIZE(wm8990_dapm_lin12_pga_controls)), 745*f10485e7SMark Brown SND_SOC_DAPM_MIXER("LIN34 PGA", WM8990_POWER_MANAGEMENT_2, WM8990_LIN34_ENA_BIT, 746*f10485e7SMark Brown 0, &wm8990_dapm_lin34_pga_controls[0], 747*f10485e7SMark Brown ARRAY_SIZE(wm8990_dapm_lin34_pga_controls)), 748*f10485e7SMark Brown SND_SOC_DAPM_MIXER("RIN12 PGA", WM8990_POWER_MANAGEMENT_2, WM8990_RIN12_ENA_BIT, 749*f10485e7SMark Brown 0, &wm8990_dapm_rin12_pga_controls[0], 750*f10485e7SMark Brown ARRAY_SIZE(wm8990_dapm_rin12_pga_controls)), 751*f10485e7SMark Brown SND_SOC_DAPM_MIXER("RIN34 PGA", WM8990_POWER_MANAGEMENT_2, WM8990_RIN34_ENA_BIT, 752*f10485e7SMark Brown 0, &wm8990_dapm_rin34_pga_controls[0], 753*f10485e7SMark Brown ARRAY_SIZE(wm8990_dapm_rin34_pga_controls)), 754*f10485e7SMark Brown 755*f10485e7SMark Brown /* INMIXL */ 756*f10485e7SMark Brown SND_SOC_DAPM_MIXER_E("INMIXL", WM8990_INTDRIVBITS, WM8990_INMIXL_PWR_BIT, 0, 757*f10485e7SMark Brown &wm8990_dapm_inmixl_controls[0], 758*f10485e7SMark Brown ARRAY_SIZE(wm8990_dapm_inmixl_controls), 759*f10485e7SMark Brown inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), 760*f10485e7SMark Brown 761*f10485e7SMark Brown /* AINLMUX */ 762*f10485e7SMark Brown SND_SOC_DAPM_MUX_E("AILNMUX", WM8990_INTDRIVBITS, WM8990_AINLMUX_PWR_BIT, 0, 763*f10485e7SMark Brown &wm8990_dapm_ainlmux_controls, inmixer_event, 764*f10485e7SMark Brown SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), 765*f10485e7SMark Brown 766*f10485e7SMark Brown /* INMIXR */ 767*f10485e7SMark Brown SND_SOC_DAPM_MIXER_E("INMIXR", WM8990_INTDRIVBITS, WM8990_INMIXR_PWR_BIT, 0, 768*f10485e7SMark Brown &wm8990_dapm_inmixr_controls[0], 769*f10485e7SMark Brown ARRAY_SIZE(wm8990_dapm_inmixr_controls), 770*f10485e7SMark Brown inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), 771*f10485e7SMark Brown 772*f10485e7SMark Brown /* AINRMUX */ 773*f10485e7SMark Brown SND_SOC_DAPM_MUX_E("AIRNMUX", WM8990_INTDRIVBITS, WM8990_AINRMUX_PWR_BIT, 0, 774*f10485e7SMark Brown &wm8990_dapm_ainrmux_controls, inmixer_event, 775*f10485e7SMark Brown SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), 776*f10485e7SMark Brown 777*f10485e7SMark Brown /* Output Side */ 778*f10485e7SMark Brown /* DACs */ 779*f10485e7SMark Brown SND_SOC_DAPM_DAC("Left DAC", "Left Playback", WM8990_POWER_MANAGEMENT_3, 780*f10485e7SMark Brown WM8990_DACL_ENA_BIT, 0), 781*f10485e7SMark Brown SND_SOC_DAPM_DAC("Right DAC", "Right Playback", WM8990_POWER_MANAGEMENT_3, 782*f10485e7SMark Brown WM8990_DACR_ENA_BIT, 0), 783*f10485e7SMark Brown 784*f10485e7SMark Brown /* LOMIX */ 785*f10485e7SMark Brown SND_SOC_DAPM_MIXER_E("LOMIX", WM8990_POWER_MANAGEMENT_3, WM8990_LOMIX_ENA_BIT, 786*f10485e7SMark Brown 0, &wm8990_dapm_lomix_controls[0], 787*f10485e7SMark Brown ARRAY_SIZE(wm8990_dapm_lomix_controls), 788*f10485e7SMark Brown outmixer_event, SND_SOC_DAPM_PRE_REG), 789*f10485e7SMark Brown 790*f10485e7SMark Brown /* LONMIX */ 791*f10485e7SMark Brown SND_SOC_DAPM_MIXER("LONMIX", WM8990_POWER_MANAGEMENT_3, WM8990_LON_ENA_BIT, 0, 792*f10485e7SMark Brown &wm8990_dapm_lonmix_controls[0], 793*f10485e7SMark Brown ARRAY_SIZE(wm8990_dapm_lonmix_controls)), 794*f10485e7SMark Brown 795*f10485e7SMark Brown /* LOPMIX */ 796*f10485e7SMark Brown SND_SOC_DAPM_MIXER("LOPMIX", WM8990_POWER_MANAGEMENT_3, WM8990_LOP_ENA_BIT, 0, 797*f10485e7SMark Brown &wm8990_dapm_lopmix_controls[0], 798*f10485e7SMark Brown ARRAY_SIZE(wm8990_dapm_lopmix_controls)), 799*f10485e7SMark Brown 800*f10485e7SMark Brown /* OUT3MIX */ 801*f10485e7SMark Brown SND_SOC_DAPM_MIXER("OUT3MIX", WM8990_POWER_MANAGEMENT_1, WM8990_OUT3_ENA_BIT, 0, 802*f10485e7SMark Brown &wm8990_dapm_out3mix_controls[0], 803*f10485e7SMark Brown ARRAY_SIZE(wm8990_dapm_out3mix_controls)), 804*f10485e7SMark Brown 805*f10485e7SMark Brown /* SPKMIX */ 806*f10485e7SMark Brown SND_SOC_DAPM_MIXER_E("SPKMIX", WM8990_POWER_MANAGEMENT_1, WM8990_SPK_ENA_BIT, 0, 807*f10485e7SMark Brown &wm8990_dapm_spkmix_controls[0], 808*f10485e7SMark Brown ARRAY_SIZE(wm8990_dapm_spkmix_controls), outmixer_event, 809*f10485e7SMark Brown SND_SOC_DAPM_PRE_REG), 810*f10485e7SMark Brown 811*f10485e7SMark Brown /* OUT4MIX */ 812*f10485e7SMark Brown SND_SOC_DAPM_MIXER("OUT4MIX", WM8990_POWER_MANAGEMENT_1, WM8990_OUT4_ENA_BIT, 0, 813*f10485e7SMark Brown &wm8990_dapm_out4mix_controls[0], 814*f10485e7SMark Brown ARRAY_SIZE(wm8990_dapm_out4mix_controls)), 815*f10485e7SMark Brown 816*f10485e7SMark Brown /* ROPMIX */ 817*f10485e7SMark Brown SND_SOC_DAPM_MIXER("ROPMIX", WM8990_POWER_MANAGEMENT_3, WM8990_ROP_ENA_BIT, 0, 818*f10485e7SMark Brown &wm8990_dapm_ropmix_controls[0], 819*f10485e7SMark Brown ARRAY_SIZE(wm8990_dapm_ropmix_controls)), 820*f10485e7SMark Brown 821*f10485e7SMark Brown /* RONMIX */ 822*f10485e7SMark Brown SND_SOC_DAPM_MIXER("RONMIX", WM8990_POWER_MANAGEMENT_3, WM8990_RON_ENA_BIT, 0, 823*f10485e7SMark Brown &wm8990_dapm_ronmix_controls[0], 824*f10485e7SMark Brown ARRAY_SIZE(wm8990_dapm_ronmix_controls)), 825*f10485e7SMark Brown 826*f10485e7SMark Brown /* ROMIX */ 827*f10485e7SMark Brown SND_SOC_DAPM_MIXER_E("ROMIX", WM8990_POWER_MANAGEMENT_3, WM8990_ROMIX_ENA_BIT, 828*f10485e7SMark Brown 0, &wm8990_dapm_romix_controls[0], 829*f10485e7SMark Brown ARRAY_SIZE(wm8990_dapm_romix_controls), 830*f10485e7SMark Brown outmixer_event, SND_SOC_DAPM_PRE_REG), 831*f10485e7SMark Brown 832*f10485e7SMark Brown /* LOUT PGA */ 833*f10485e7SMark Brown SND_SOC_DAPM_PGA("LOUT PGA", WM8990_POWER_MANAGEMENT_1, WM8990_LOUT_ENA_BIT, 0, 834*f10485e7SMark Brown NULL, 0), 835*f10485e7SMark Brown 836*f10485e7SMark Brown /* ROUT PGA */ 837*f10485e7SMark Brown SND_SOC_DAPM_PGA("ROUT PGA", WM8990_POWER_MANAGEMENT_1, WM8990_ROUT_ENA_BIT, 0, 838*f10485e7SMark Brown NULL, 0), 839*f10485e7SMark Brown 840*f10485e7SMark Brown /* LOPGA */ 841*f10485e7SMark Brown SND_SOC_DAPM_PGA("LOPGA", WM8990_POWER_MANAGEMENT_3, WM8990_LOPGA_ENA_BIT, 0, 842*f10485e7SMark Brown NULL, 0), 843*f10485e7SMark Brown 844*f10485e7SMark Brown /* ROPGA */ 845*f10485e7SMark Brown SND_SOC_DAPM_PGA("ROPGA", WM8990_POWER_MANAGEMENT_3, WM8990_ROPGA_ENA_BIT, 0, 846*f10485e7SMark Brown NULL, 0), 847*f10485e7SMark Brown 848*f10485e7SMark Brown /* MICBIAS */ 849*f10485e7SMark Brown SND_SOC_DAPM_MICBIAS("MICBIAS", WM8990_POWER_MANAGEMENT_1, 850*f10485e7SMark Brown WM8990_MICBIAS_ENA_BIT, 0), 851*f10485e7SMark Brown 852*f10485e7SMark Brown SND_SOC_DAPM_OUTPUT("LON"), 853*f10485e7SMark Brown SND_SOC_DAPM_OUTPUT("LOP"), 854*f10485e7SMark Brown SND_SOC_DAPM_OUTPUT("OUT3"), 855*f10485e7SMark Brown SND_SOC_DAPM_OUTPUT("LOUT"), 856*f10485e7SMark Brown SND_SOC_DAPM_OUTPUT("SPKN"), 857*f10485e7SMark Brown SND_SOC_DAPM_OUTPUT("SPKP"), 858*f10485e7SMark Brown SND_SOC_DAPM_OUTPUT("ROUT"), 859*f10485e7SMark Brown SND_SOC_DAPM_OUTPUT("OUT4"), 860*f10485e7SMark Brown SND_SOC_DAPM_OUTPUT("ROP"), 861*f10485e7SMark Brown SND_SOC_DAPM_OUTPUT("RON"), 862*f10485e7SMark Brown 863*f10485e7SMark Brown SND_SOC_DAPM_OUTPUT("Internal DAC Sink"), 864*f10485e7SMark Brown }; 865*f10485e7SMark Brown 866*f10485e7SMark Brown static const struct snd_soc_dapm_route audio_map[] = { 867*f10485e7SMark Brown /* Make DACs turn on when playing even if not mixed into any outputs */ 868*f10485e7SMark Brown {"Internal DAC Sink", NULL, "Left DAC"}, 869*f10485e7SMark Brown {"Internal DAC Sink", NULL, "Right DAC"}, 870*f10485e7SMark Brown 871*f10485e7SMark Brown /* Make ADCs turn on when recording even if not mixed from any inputs */ 872*f10485e7SMark Brown {"Left ADC", NULL, "Internal ADC Source"}, 873*f10485e7SMark Brown {"Right ADC", NULL, "Internal ADC Source"}, 874*f10485e7SMark Brown 875*f10485e7SMark Brown /* Input Side */ 876*f10485e7SMark Brown /* LIN12 PGA */ 877*f10485e7SMark Brown {"LIN12 PGA", "LIN1 Switch", "LIN1"}, 878*f10485e7SMark Brown {"LIN12 PGA", "LIN2 Switch", "LIN2"}, 879*f10485e7SMark Brown /* LIN34 PGA */ 880*f10485e7SMark Brown {"LIN34 PGA", "LIN3 Switch", "LIN3"}, 881*f10485e7SMark Brown {"LIN34 PGA", "LIN4 Switch", "LIN4"}, 882*f10485e7SMark Brown /* INMIXL */ 883*f10485e7SMark Brown {"INMIXL", "Record Left Volume", "LOMIX"}, 884*f10485e7SMark Brown {"INMIXL", "LIN2 Volume", "LIN2"}, 885*f10485e7SMark Brown {"INMIXL", "LINPGA12 Switch", "LIN12 PGA"}, 886*f10485e7SMark Brown {"INMIXL", "LINPGA34 Switch", "LIN34 PGA"}, 887*f10485e7SMark Brown /* AILNMUX */ 888*f10485e7SMark Brown {"AILNMUX", "INMIXL Mix", "INMIXL"}, 889*f10485e7SMark Brown {"AILNMUX", "DIFFINL Mix", "LIN12PGA"}, 890*f10485e7SMark Brown {"AILNMUX", "DIFFINL Mix", "LIN34PGA"}, 891*f10485e7SMark Brown {"AILNMUX", "RXVOICE Mix", "LIN4/RXN"}, 892*f10485e7SMark Brown {"AILNMUX", "RXVOICE Mix", "RIN4/RXP"}, 893*f10485e7SMark Brown /* ADC */ 894*f10485e7SMark Brown {"Left ADC", NULL, "AILNMUX"}, 895*f10485e7SMark Brown 896*f10485e7SMark Brown /* RIN12 PGA */ 897*f10485e7SMark Brown {"RIN12 PGA", "RIN1 Switch", "RIN1"}, 898*f10485e7SMark Brown {"RIN12 PGA", "RIN2 Switch", "RIN2"}, 899*f10485e7SMark Brown /* RIN34 PGA */ 900*f10485e7SMark Brown {"RIN34 PGA", "RIN3 Switch", "RIN3"}, 901*f10485e7SMark Brown {"RIN34 PGA", "RIN4 Switch", "RIN4"}, 902*f10485e7SMark Brown /* INMIXL */ 903*f10485e7SMark Brown {"INMIXR", "Record Right Volume", "ROMIX"}, 904*f10485e7SMark Brown {"INMIXR", "RIN2 Volume", "RIN2"}, 905*f10485e7SMark Brown {"INMIXR", "RINPGA12 Switch", "RIN12 PGA"}, 906*f10485e7SMark Brown {"INMIXR", "RINPGA34 Switch", "RIN34 PGA"}, 907*f10485e7SMark Brown /* AIRNMUX */ 908*f10485e7SMark Brown {"AIRNMUX", "INMIXR Mix", "INMIXR"}, 909*f10485e7SMark Brown {"AIRNMUX", "DIFFINR Mix", "RIN12PGA"}, 910*f10485e7SMark Brown {"AIRNMUX", "DIFFINR Mix", "RIN34PGA"}, 911*f10485e7SMark Brown {"AIRNMUX", "RXVOICE Mix", "RIN4/RXN"}, 912*f10485e7SMark Brown {"AIRNMUX", "RXVOICE Mix", "RIN4/RXP"}, 913*f10485e7SMark Brown /* ADC */ 914*f10485e7SMark Brown {"Right ADC", NULL, "AIRNMUX"}, 915*f10485e7SMark Brown 916*f10485e7SMark Brown /* LOMIX */ 917*f10485e7SMark Brown {"LOMIX", "LOMIX RIN3 Bypass Switch", "RIN3"}, 918*f10485e7SMark Brown {"LOMIX", "LOMIX LIN3 Bypass Switch", "LIN3"}, 919*f10485e7SMark Brown {"LOMIX", "LOMIX LIN12 PGA Bypass Switch", "LIN12 PGA"}, 920*f10485e7SMark Brown {"LOMIX", "LOMIX RIN12 PGA Bypass Switch", "RIN12 PGA"}, 921*f10485e7SMark Brown {"LOMIX", "LOMIX Right ADC Bypass Switch", "AINRMUX"}, 922*f10485e7SMark Brown {"LOMIX", "LOMIX Left ADC Bypass Switch", "AINLMUX"}, 923*f10485e7SMark Brown {"LOMIX", "LOMIX Left DAC Switch", "Left DAC"}, 924*f10485e7SMark Brown 925*f10485e7SMark Brown /* ROMIX */ 926*f10485e7SMark Brown {"ROMIX", "ROMIX RIN3 Bypass Switch", "RIN3"}, 927*f10485e7SMark Brown {"ROMIX", "ROMIX LIN3 Bypass Switch", "LIN3"}, 928*f10485e7SMark Brown {"ROMIX", "ROMIX LIN12 PGA Bypass Switch", "LIN12 PGA"}, 929*f10485e7SMark Brown {"ROMIX", "ROMIX RIN12 PGA Bypass Switch", "RIN12 PGA"}, 930*f10485e7SMark Brown {"ROMIX", "ROMIX Right ADC Bypass Switch", "AINRMUX"}, 931*f10485e7SMark Brown {"ROMIX", "ROMIX Left ADC Bypass Switch", "AINLMUX"}, 932*f10485e7SMark Brown {"ROMIX", "ROMIX Right DAC Switch", "Right DAC"}, 933*f10485e7SMark Brown 934*f10485e7SMark Brown /* SPKMIX */ 935*f10485e7SMark Brown {"SPKMIX", "SPKMIX LIN2 Bypass Switch", "LIN2"}, 936*f10485e7SMark Brown {"SPKMIX", "SPKMIX RIN2 Bypass Switch", "RIN2"}, 937*f10485e7SMark Brown {"SPKMIX", "SPKMIX LADC Bypass Switch", "AINLMUX"}, 938*f10485e7SMark Brown {"SPKMIX", "SPKMIX RADC Bypass Switch", "AINRMUX"}, 939*f10485e7SMark Brown {"SPKMIX", "SPKMIX Left Mixer PGA Switch", "LOPGA"}, 940*f10485e7SMark Brown {"SPKMIX", "SPKMIX Right Mixer PGA Switch", "ROPGA"}, 941*f10485e7SMark Brown {"SPKMIX", "SPKMIX Right DAC Switch", "Right DAC"}, 942*f10485e7SMark Brown {"SPKMIX", "SPKMIX Left DAC Switch", "Right DAC"}, 943*f10485e7SMark Brown 944*f10485e7SMark Brown /* LONMIX */ 945*f10485e7SMark Brown {"LONMIX", "LONMIX Left Mixer PGA Switch", "LOPGA"}, 946*f10485e7SMark Brown {"LONMIX", "LONMIX Right Mixer PGA Switch", "ROPGA"}, 947*f10485e7SMark Brown {"LONMIX", "LONMIX Inverted LOP Switch", "LOPMIX"}, 948*f10485e7SMark Brown 949*f10485e7SMark Brown /* LOPMIX */ 950*f10485e7SMark Brown {"LOPMIX", "LOPMIX Right Mic Bypass Switch", "RIN12 PGA"}, 951*f10485e7SMark Brown {"LOPMIX", "LOPMIX Left Mic Bypass Switch", "LIN12 PGA"}, 952*f10485e7SMark Brown {"LOPMIX", "LOPMIX Left Mixer PGA Switch", "LOPGA"}, 953*f10485e7SMark Brown 954*f10485e7SMark Brown /* OUT3MIX */ 955*f10485e7SMark Brown {"OUT3MIX", "OUT3MIX LIN4/RXP Bypass Switch", "LIN4/RXP"}, 956*f10485e7SMark Brown {"OUT3MIX", "OUT3MIX Left Out PGA Switch", "LOPGA"}, 957*f10485e7SMark Brown 958*f10485e7SMark Brown /* OUT4MIX */ 959*f10485e7SMark Brown {"OUT4MIX", "OUT4MIX Right Out PGA Switch", "ROPGA"}, 960*f10485e7SMark Brown {"OUT4MIX", "OUT4MIX RIN4/RXP Bypass Switch", "RIN4/RXP"}, 961*f10485e7SMark Brown 962*f10485e7SMark Brown /* RONMIX */ 963*f10485e7SMark Brown {"RONMIX", "RONMIX Right Mixer PGA Switch", "ROPGA"}, 964*f10485e7SMark Brown {"RONMIX", "RONMIX Left Mixer PGA Switch", "LOPGA"}, 965*f10485e7SMark Brown {"RONMIX", "RONMIX Inverted ROP Switch", "ROPMIX"}, 966*f10485e7SMark Brown 967*f10485e7SMark Brown /* ROPMIX */ 968*f10485e7SMark Brown {"ROPMIX", "ROPMIX Left Mic Bypass Switch", "LIN12 PGA"}, 969*f10485e7SMark Brown {"ROPMIX", "ROPMIX Right Mic Bypass Switch", "RIN12 PGA"}, 970*f10485e7SMark Brown {"ROPMIX", "ROPMIX Right Mixer PGA Switch", "ROPGA"}, 971*f10485e7SMark Brown 972*f10485e7SMark Brown /* Out Mixer PGAs */ 973*f10485e7SMark Brown {"LOPGA", NULL, "LOMIX"}, 974*f10485e7SMark Brown {"ROPGA", NULL, "ROMIX"}, 975*f10485e7SMark Brown 976*f10485e7SMark Brown {"LOUT PGA", NULL, "LOMIX"}, 977*f10485e7SMark Brown {"ROUT PGA", NULL, "ROMIX"}, 978*f10485e7SMark Brown 979*f10485e7SMark Brown /* Output Pins */ 980*f10485e7SMark Brown {"LON", NULL, "LONMIX"}, 981*f10485e7SMark Brown {"LOP", NULL, "LOPMIX"}, 982*f10485e7SMark Brown {"OUT", NULL, "OUT3MIX"}, 983*f10485e7SMark Brown {"LOUT", NULL, "LOUT PGA"}, 984*f10485e7SMark Brown {"SPKN", NULL, "SPKMIX"}, 985*f10485e7SMark Brown {"ROUT", NULL, "ROUT PGA"}, 986*f10485e7SMark Brown {"OUT4", NULL, "OUT4MIX"}, 987*f10485e7SMark Brown {"ROP", NULL, "ROPMIX"}, 988*f10485e7SMark Brown {"RON", NULL, "RONMIX"}, 989*f10485e7SMark Brown }; 990*f10485e7SMark Brown 991*f10485e7SMark Brown static int wm8990_add_widgets(struct snd_soc_codec *codec) 992*f10485e7SMark Brown { 993*f10485e7SMark Brown snd_soc_dapm_new_controls(codec, wm8990_dapm_widgets, 994*f10485e7SMark Brown ARRAY_SIZE(wm8990_dapm_widgets)); 995*f10485e7SMark Brown 996*f10485e7SMark Brown /* set up the WM8990 audio map */ 997*f10485e7SMark Brown snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); 998*f10485e7SMark Brown 999*f10485e7SMark Brown snd_soc_dapm_new_widgets(codec); 1000*f10485e7SMark Brown return 0; 1001*f10485e7SMark Brown } 1002*f10485e7SMark Brown 1003*f10485e7SMark Brown /* PLL divisors */ 1004*f10485e7SMark Brown struct _pll_div { 1005*f10485e7SMark Brown u32 div2; 1006*f10485e7SMark Brown u32 n; 1007*f10485e7SMark Brown u32 k; 1008*f10485e7SMark Brown }; 1009*f10485e7SMark Brown 1010*f10485e7SMark Brown /* The size in bits of the pll divide multiplied by 10 1011*f10485e7SMark Brown * to allow rounding later */ 1012*f10485e7SMark Brown #define FIXED_PLL_SIZE ((1 << 16) * 10) 1013*f10485e7SMark Brown 1014*f10485e7SMark Brown static void pll_factors(struct _pll_div *pll_div, unsigned int target, 1015*f10485e7SMark Brown unsigned int source) 1016*f10485e7SMark Brown { 1017*f10485e7SMark Brown u64 Kpart; 1018*f10485e7SMark Brown unsigned int K, Ndiv, Nmod; 1019*f10485e7SMark Brown 1020*f10485e7SMark Brown 1021*f10485e7SMark Brown Ndiv = target / source; 1022*f10485e7SMark Brown if (Ndiv < 6) { 1023*f10485e7SMark Brown source >>= 1; 1024*f10485e7SMark Brown pll_div->div2 = 1; 1025*f10485e7SMark Brown Ndiv = target / source; 1026*f10485e7SMark Brown } else 1027*f10485e7SMark Brown pll_div->div2 = 0; 1028*f10485e7SMark Brown 1029*f10485e7SMark Brown if ((Ndiv < 6) || (Ndiv > 12)) 1030*f10485e7SMark Brown printk(KERN_WARNING 1031*f10485e7SMark Brown "WM8990 N value outwith recommended range! N = %d\n", Ndiv); 1032*f10485e7SMark Brown 1033*f10485e7SMark Brown pll_div->n = Ndiv; 1034*f10485e7SMark Brown Nmod = target % source; 1035*f10485e7SMark Brown Kpart = FIXED_PLL_SIZE * (long long)Nmod; 1036*f10485e7SMark Brown 1037*f10485e7SMark Brown do_div(Kpart, source); 1038*f10485e7SMark Brown 1039*f10485e7SMark Brown K = Kpart & 0xFFFFFFFF; 1040*f10485e7SMark Brown 1041*f10485e7SMark Brown /* Check if we need to round */ 1042*f10485e7SMark Brown if ((K % 10) >= 5) 1043*f10485e7SMark Brown K += 5; 1044*f10485e7SMark Brown 1045*f10485e7SMark Brown /* Move down to proper range now rounding is done */ 1046*f10485e7SMark Brown K /= 10; 1047*f10485e7SMark Brown 1048*f10485e7SMark Brown pll_div->k = K; 1049*f10485e7SMark Brown } 1050*f10485e7SMark Brown 1051*f10485e7SMark Brown static int wm8990_set_dai_pll(struct snd_soc_codec_dai *codec_dai, 1052*f10485e7SMark Brown int pll_id, unsigned int freq_in, unsigned int freq_out) 1053*f10485e7SMark Brown { 1054*f10485e7SMark Brown u16 reg; 1055*f10485e7SMark Brown struct snd_soc_codec *codec = codec_dai->codec; 1056*f10485e7SMark Brown struct _pll_div pll_div; 1057*f10485e7SMark Brown 1058*f10485e7SMark Brown if (freq_in && freq_out) { 1059*f10485e7SMark Brown pll_factors(&pll_div, freq_out * 4, freq_in); 1060*f10485e7SMark Brown 1061*f10485e7SMark Brown /* Turn on PLL */ 1062*f10485e7SMark Brown reg = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_2); 1063*f10485e7SMark Brown reg |= WM8990_PLL_ENA; 1064*f10485e7SMark Brown wm8990_write(codec, WM8990_POWER_MANAGEMENT_2, reg); 1065*f10485e7SMark Brown 1066*f10485e7SMark Brown /* sysclk comes from PLL */ 1067*f10485e7SMark Brown reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_2); 1068*f10485e7SMark Brown wm8990_write(codec, WM8990_CLOCKING_2, reg | WM8990_SYSCLK_SRC); 1069*f10485e7SMark Brown 1070*f10485e7SMark Brown /* set up N , fractional mode and pre-divisor if neccessary */ 1071*f10485e7SMark Brown wm8990_write(codec, WM8990_PLL1, pll_div.n | WM8990_SDM | 1072*f10485e7SMark Brown (pll_div.div2?WM8990_PRESCALE:0)); 1073*f10485e7SMark Brown wm8990_write(codec, WM8990_PLL2, (u8)(pll_div.k>>8)); 1074*f10485e7SMark Brown wm8990_write(codec, WM8990_PLL3, (u8)(pll_div.k & 0xFF)); 1075*f10485e7SMark Brown } else { 1076*f10485e7SMark Brown /* Turn on PLL */ 1077*f10485e7SMark Brown reg = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_2); 1078*f10485e7SMark Brown reg &= ~WM8990_PLL_ENA; 1079*f10485e7SMark Brown wm8990_write(codec, WM8990_POWER_MANAGEMENT_2, reg); 1080*f10485e7SMark Brown } 1081*f10485e7SMark Brown return 0; 1082*f10485e7SMark Brown } 1083*f10485e7SMark Brown 1084*f10485e7SMark Brown /* 1085*f10485e7SMark Brown * Clock after PLL and dividers 1086*f10485e7SMark Brown */ 1087*f10485e7SMark Brown static int wm8990_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai, 1088*f10485e7SMark Brown int clk_id, unsigned int freq, int dir) 1089*f10485e7SMark Brown { 1090*f10485e7SMark Brown struct snd_soc_codec *codec = codec_dai->codec; 1091*f10485e7SMark Brown struct wm8990_priv *wm8990 = codec->private_data; 1092*f10485e7SMark Brown 1093*f10485e7SMark Brown wm8990->sysclk = freq; 1094*f10485e7SMark Brown return 0; 1095*f10485e7SMark Brown } 1096*f10485e7SMark Brown 1097*f10485e7SMark Brown /* 1098*f10485e7SMark Brown * Set's ADC and Voice DAC format. 1099*f10485e7SMark Brown */ 1100*f10485e7SMark Brown static int wm8990_set_dai_fmt(struct snd_soc_codec_dai *codec_dai, 1101*f10485e7SMark Brown unsigned int fmt) 1102*f10485e7SMark Brown { 1103*f10485e7SMark Brown struct snd_soc_codec *codec = codec_dai->codec; 1104*f10485e7SMark Brown u16 audio1, audio3; 1105*f10485e7SMark Brown 1106*f10485e7SMark Brown audio1 = wm8990_read_reg_cache(codec, WM8990_AUDIO_INTERFACE_1); 1107*f10485e7SMark Brown audio3 = wm8990_read_reg_cache(codec, WM8990_AUDIO_INTERFACE_3); 1108*f10485e7SMark Brown 1109*f10485e7SMark Brown /* set master/slave audio interface */ 1110*f10485e7SMark Brown switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 1111*f10485e7SMark Brown case SND_SOC_DAIFMT_CBS_CFS: 1112*f10485e7SMark Brown audio3 &= ~WM8990_AIF_MSTR1; 1113*f10485e7SMark Brown break; 1114*f10485e7SMark Brown case SND_SOC_DAIFMT_CBM_CFM: 1115*f10485e7SMark Brown audio3 |= WM8990_AIF_MSTR1; 1116*f10485e7SMark Brown break; 1117*f10485e7SMark Brown default: 1118*f10485e7SMark Brown return -EINVAL; 1119*f10485e7SMark Brown } 1120*f10485e7SMark Brown 1121*f10485e7SMark Brown audio1 &= ~WM8990_AIF_FMT_MASK; 1122*f10485e7SMark Brown 1123*f10485e7SMark Brown /* interface format */ 1124*f10485e7SMark Brown switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 1125*f10485e7SMark Brown case SND_SOC_DAIFMT_I2S: 1126*f10485e7SMark Brown audio1 |= WM8990_AIF_TMF_I2S; 1127*f10485e7SMark Brown audio1 &= ~WM8990_AIF_LRCLK_INV; 1128*f10485e7SMark Brown break; 1129*f10485e7SMark Brown case SND_SOC_DAIFMT_RIGHT_J: 1130*f10485e7SMark Brown audio1 |= WM8990_AIF_TMF_RIGHTJ; 1131*f10485e7SMark Brown audio1 &= ~WM8990_AIF_LRCLK_INV; 1132*f10485e7SMark Brown break; 1133*f10485e7SMark Brown case SND_SOC_DAIFMT_LEFT_J: 1134*f10485e7SMark Brown audio1 |= WM8990_AIF_TMF_LEFTJ; 1135*f10485e7SMark Brown audio1 &= ~WM8990_AIF_LRCLK_INV; 1136*f10485e7SMark Brown break; 1137*f10485e7SMark Brown case SND_SOC_DAIFMT_DSP_A: 1138*f10485e7SMark Brown audio1 |= WM8990_AIF_TMF_DSP; 1139*f10485e7SMark Brown audio1 &= ~WM8990_AIF_LRCLK_INV; 1140*f10485e7SMark Brown break; 1141*f10485e7SMark Brown case SND_SOC_DAIFMT_DSP_B: 1142*f10485e7SMark Brown audio1 |= WM8990_AIF_TMF_DSP | WM8990_AIF_LRCLK_INV; 1143*f10485e7SMark Brown break; 1144*f10485e7SMark Brown default: 1145*f10485e7SMark Brown return -EINVAL; 1146*f10485e7SMark Brown } 1147*f10485e7SMark Brown 1148*f10485e7SMark Brown wm8990_write(codec, WM8990_AUDIO_INTERFACE_1, audio1); 1149*f10485e7SMark Brown wm8990_write(codec, WM8990_AUDIO_INTERFACE_3, audio3); 1150*f10485e7SMark Brown return 0; 1151*f10485e7SMark Brown } 1152*f10485e7SMark Brown 1153*f10485e7SMark Brown static int wm8990_set_dai_clkdiv(struct snd_soc_codec_dai *codec_dai, 1154*f10485e7SMark Brown int div_id, int div) 1155*f10485e7SMark Brown { 1156*f10485e7SMark Brown struct snd_soc_codec *codec = codec_dai->codec; 1157*f10485e7SMark Brown u16 reg; 1158*f10485e7SMark Brown 1159*f10485e7SMark Brown switch (div_id) { 1160*f10485e7SMark Brown case WM8990_MCLK_DIV: 1161*f10485e7SMark Brown reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_2) & 1162*f10485e7SMark Brown ~WM8990_MCLK_DIV_MASK; 1163*f10485e7SMark Brown wm8990_write(codec, WM8990_CLOCKING_2, reg | div); 1164*f10485e7SMark Brown break; 1165*f10485e7SMark Brown case WM8990_DACCLK_DIV: 1166*f10485e7SMark Brown reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_2) & 1167*f10485e7SMark Brown ~WM8990_DAC_CLKDIV_MASK; 1168*f10485e7SMark Brown wm8990_write(codec, WM8990_CLOCKING_2, reg | div); 1169*f10485e7SMark Brown break; 1170*f10485e7SMark Brown case WM8990_ADCCLK_DIV: 1171*f10485e7SMark Brown reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_2) & 1172*f10485e7SMark Brown ~WM8990_ADC_CLKDIV_MASK; 1173*f10485e7SMark Brown wm8990_write(codec, WM8990_CLOCKING_2, reg | div); 1174*f10485e7SMark Brown break; 1175*f10485e7SMark Brown case WM8990_BCLK_DIV: 1176*f10485e7SMark Brown reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_1) & 1177*f10485e7SMark Brown ~WM8990_BCLK_DIV_MASK; 1178*f10485e7SMark Brown wm8990_write(codec, WM8990_CLOCKING_1, reg | div); 1179*f10485e7SMark Brown break; 1180*f10485e7SMark Brown default: 1181*f10485e7SMark Brown return -EINVAL; 1182*f10485e7SMark Brown } 1183*f10485e7SMark Brown 1184*f10485e7SMark Brown return 0; 1185*f10485e7SMark Brown } 1186*f10485e7SMark Brown 1187*f10485e7SMark Brown /* 1188*f10485e7SMark Brown * Set PCM DAI bit size and sample rate. 1189*f10485e7SMark Brown */ 1190*f10485e7SMark Brown static int wm8990_hw_params(struct snd_pcm_substream *substream, 1191*f10485e7SMark Brown struct snd_pcm_hw_params *params) 1192*f10485e7SMark Brown { 1193*f10485e7SMark Brown struct snd_soc_pcm_runtime *rtd = substream->private_data; 1194*f10485e7SMark Brown struct snd_soc_device *socdev = rtd->socdev; 1195*f10485e7SMark Brown struct snd_soc_codec *codec = socdev->codec; 1196*f10485e7SMark Brown u16 audio1 = wm8990_read_reg_cache(codec, WM8990_AUDIO_INTERFACE_1); 1197*f10485e7SMark Brown 1198*f10485e7SMark Brown audio1 &= ~WM8990_AIF_WL_MASK; 1199*f10485e7SMark Brown /* bit size */ 1200*f10485e7SMark Brown switch (params_format(params)) { 1201*f10485e7SMark Brown case SNDRV_PCM_FORMAT_S16_LE: 1202*f10485e7SMark Brown break; 1203*f10485e7SMark Brown case SNDRV_PCM_FORMAT_S20_3LE: 1204*f10485e7SMark Brown audio1 |= WM8990_AIF_WL_20BITS; 1205*f10485e7SMark Brown break; 1206*f10485e7SMark Brown case SNDRV_PCM_FORMAT_S24_LE: 1207*f10485e7SMark Brown audio1 |= WM8990_AIF_WL_24BITS; 1208*f10485e7SMark Brown break; 1209*f10485e7SMark Brown case SNDRV_PCM_FORMAT_S32_LE: 1210*f10485e7SMark Brown audio1 |= WM8990_AIF_WL_32BITS; 1211*f10485e7SMark Brown break; 1212*f10485e7SMark Brown } 1213*f10485e7SMark Brown 1214*f10485e7SMark Brown wm8990_write(codec, WM8990_AUDIO_INTERFACE_1, audio1); 1215*f10485e7SMark Brown return 0; 1216*f10485e7SMark Brown } 1217*f10485e7SMark Brown 1218*f10485e7SMark Brown static int wm8990_mute(struct snd_soc_codec_dai *dai, int mute) 1219*f10485e7SMark Brown { 1220*f10485e7SMark Brown struct snd_soc_codec *codec = dai->codec; 1221*f10485e7SMark Brown u16 val; 1222*f10485e7SMark Brown 1223*f10485e7SMark Brown val = wm8990_read_reg_cache(codec, WM8990_DAC_CTRL) & ~WM8990_DAC_MUTE; 1224*f10485e7SMark Brown 1225*f10485e7SMark Brown if (mute) 1226*f10485e7SMark Brown wm8990_write(codec, WM8990_DAC_CTRL, val | WM8990_DAC_MUTE); 1227*f10485e7SMark Brown else 1228*f10485e7SMark Brown wm8990_write(codec, WM8990_DAC_CTRL, val); 1229*f10485e7SMark Brown 1230*f10485e7SMark Brown return 0; 1231*f10485e7SMark Brown } 1232*f10485e7SMark Brown 1233*f10485e7SMark Brown static int wm8990_set_bias_level(struct snd_soc_codec *codec, 1234*f10485e7SMark Brown enum snd_soc_bias_level level) 1235*f10485e7SMark Brown { 1236*f10485e7SMark Brown u16 val; 1237*f10485e7SMark Brown 1238*f10485e7SMark Brown switch (level) { 1239*f10485e7SMark Brown case SND_SOC_BIAS_ON: 1240*f10485e7SMark Brown break; 1241*f10485e7SMark Brown case SND_SOC_BIAS_PREPARE: 1242*f10485e7SMark Brown break; 1243*f10485e7SMark Brown case SND_SOC_BIAS_STANDBY: 1244*f10485e7SMark Brown if (codec->bias_level == SND_SOC_BIAS_OFF) { 1245*f10485e7SMark Brown /* Enable all output discharge bits */ 1246*f10485e7SMark Brown wm8990_write(codec, WM8990_ANTIPOP1, WM8990_DIS_LLINE | 1247*f10485e7SMark Brown WM8990_DIS_RLINE | WM8990_DIS_OUT3 | 1248*f10485e7SMark Brown WM8990_DIS_OUT4 | WM8990_DIS_LOUT | 1249*f10485e7SMark Brown WM8990_DIS_ROUT); 1250*f10485e7SMark Brown 1251*f10485e7SMark Brown /* Enable POBCTRL, SOFT_ST, VMIDTOG and BUFDCOPEN */ 1252*f10485e7SMark Brown wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST | 1253*f10485e7SMark Brown WM8990_BUFDCOPEN | WM8990_POBCTRL | 1254*f10485e7SMark Brown WM8990_VMIDTOG); 1255*f10485e7SMark Brown 1256*f10485e7SMark Brown /* Delay to allow output caps to discharge */ 1257*f10485e7SMark Brown msleep(msecs_to_jiffies(300)); 1258*f10485e7SMark Brown 1259*f10485e7SMark Brown /* Disable VMIDTOG */ 1260*f10485e7SMark Brown wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST | 1261*f10485e7SMark Brown WM8990_BUFDCOPEN | WM8990_POBCTRL); 1262*f10485e7SMark Brown 1263*f10485e7SMark Brown /* disable all output discharge bits */ 1264*f10485e7SMark Brown wm8990_write(codec, WM8990_ANTIPOP1, 0); 1265*f10485e7SMark Brown 1266*f10485e7SMark Brown /* Enable outputs */ 1267*f10485e7SMark Brown wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1b00); 1268*f10485e7SMark Brown 1269*f10485e7SMark Brown msleep(msecs_to_jiffies(50)); 1270*f10485e7SMark Brown 1271*f10485e7SMark Brown /* Enable VMID at 2x50k */ 1272*f10485e7SMark Brown wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f02); 1273*f10485e7SMark Brown 1274*f10485e7SMark Brown msleep(msecs_to_jiffies(100)); 1275*f10485e7SMark Brown 1276*f10485e7SMark Brown /* Enable VREF */ 1277*f10485e7SMark Brown wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f03); 1278*f10485e7SMark Brown 1279*f10485e7SMark Brown msleep(msecs_to_jiffies(600)); 1280*f10485e7SMark Brown 1281*f10485e7SMark Brown /* Enable BUFIOEN */ 1282*f10485e7SMark Brown wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST | 1283*f10485e7SMark Brown WM8990_BUFDCOPEN | WM8990_POBCTRL | 1284*f10485e7SMark Brown WM8990_BUFIOEN); 1285*f10485e7SMark Brown 1286*f10485e7SMark Brown /* Disable outputs */ 1287*f10485e7SMark Brown wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x3); 1288*f10485e7SMark Brown 1289*f10485e7SMark Brown /* disable POBCTRL, SOFT_ST and BUFDCOPEN */ 1290*f10485e7SMark Brown wm8990_write(codec, WM8990_ANTIPOP2, WM8990_BUFIOEN); 1291*f10485e7SMark Brown } else { 1292*f10485e7SMark Brown /* ON -> standby */ 1293*f10485e7SMark Brown 1294*f10485e7SMark Brown } 1295*f10485e7SMark Brown break; 1296*f10485e7SMark Brown 1297*f10485e7SMark Brown case SND_SOC_BIAS_OFF: 1298*f10485e7SMark Brown /* Enable POBCTRL and SOFT_ST */ 1299*f10485e7SMark Brown wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST | 1300*f10485e7SMark Brown WM8990_POBCTRL | WM8990_BUFIOEN); 1301*f10485e7SMark Brown 1302*f10485e7SMark Brown /* Enable POBCTRL, SOFT_ST and BUFDCOPEN */ 1303*f10485e7SMark Brown wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST | 1304*f10485e7SMark Brown WM8990_BUFDCOPEN | WM8990_POBCTRL | 1305*f10485e7SMark Brown WM8990_BUFIOEN); 1306*f10485e7SMark Brown 1307*f10485e7SMark Brown /* mute DAC */ 1308*f10485e7SMark Brown val = wm8990_read_reg_cache(codec, WM8990_DAC_CTRL); 1309*f10485e7SMark Brown wm8990_write(codec, WM8990_DAC_CTRL, val | WM8990_DAC_MUTE); 1310*f10485e7SMark Brown 1311*f10485e7SMark Brown /* Enable any disabled outputs */ 1312*f10485e7SMark Brown wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f03); 1313*f10485e7SMark Brown 1314*f10485e7SMark Brown /* Disable VMID */ 1315*f10485e7SMark Brown wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f01); 1316*f10485e7SMark Brown 1317*f10485e7SMark Brown msleep(msecs_to_jiffies(300)); 1318*f10485e7SMark Brown 1319*f10485e7SMark Brown /* Enable all output discharge bits */ 1320*f10485e7SMark Brown wm8990_write(codec, WM8990_ANTIPOP1, WM8990_DIS_LLINE | 1321*f10485e7SMark Brown WM8990_DIS_RLINE | WM8990_DIS_OUT3 | 1322*f10485e7SMark Brown WM8990_DIS_OUT4 | WM8990_DIS_LOUT | 1323*f10485e7SMark Brown WM8990_DIS_ROUT); 1324*f10485e7SMark Brown 1325*f10485e7SMark Brown /* Disable VREF */ 1326*f10485e7SMark Brown wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x0); 1327*f10485e7SMark Brown 1328*f10485e7SMark Brown /* disable POBCTRL, SOFT_ST and BUFDCOPEN */ 1329*f10485e7SMark Brown wm8990_write(codec, WM8990_ANTIPOP2, 0x0); 1330*f10485e7SMark Brown break; 1331*f10485e7SMark Brown } 1332*f10485e7SMark Brown 1333*f10485e7SMark Brown codec->bias_level = level; 1334*f10485e7SMark Brown return 0; 1335*f10485e7SMark Brown } 1336*f10485e7SMark Brown 1337*f10485e7SMark Brown #define WM8990_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ 1338*f10485e7SMark Brown SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \ 1339*f10485e7SMark Brown SNDRV_PCM_RATE_48000) 1340*f10485e7SMark Brown 1341*f10485e7SMark Brown #define WM8990_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ 1342*f10485e7SMark Brown SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) 1343*f10485e7SMark Brown 1344*f10485e7SMark Brown /* 1345*f10485e7SMark Brown * The WM8990 supports 2 different and mutually exclusive DAI 1346*f10485e7SMark Brown * configurations. 1347*f10485e7SMark Brown * 1348*f10485e7SMark Brown * 1. ADC/DAC on Primary Interface 1349*f10485e7SMark Brown * 2. ADC on Primary Interface/DAC on secondary 1350*f10485e7SMark Brown */ 1351*f10485e7SMark Brown struct snd_soc_codec_dai wm8990_dai = { 1352*f10485e7SMark Brown /* ADC/DAC on primary */ 1353*f10485e7SMark Brown .name = "WM8990 ADC/DAC Primary", 1354*f10485e7SMark Brown .id = 1, 1355*f10485e7SMark Brown .playback = { 1356*f10485e7SMark Brown .stream_name = "Playback", 1357*f10485e7SMark Brown .channels_min = 1, 1358*f10485e7SMark Brown .channels_max = 2, 1359*f10485e7SMark Brown .rates = WM8990_RATES, 1360*f10485e7SMark Brown .formats = WM8990_FORMATS,}, 1361*f10485e7SMark Brown .capture = { 1362*f10485e7SMark Brown .stream_name = "Capture", 1363*f10485e7SMark Brown .channels_min = 1, 1364*f10485e7SMark Brown .channels_max = 2, 1365*f10485e7SMark Brown .rates = WM8990_RATES, 1366*f10485e7SMark Brown .formats = WM8990_FORMATS,}, 1367*f10485e7SMark Brown .ops = { 1368*f10485e7SMark Brown .hw_params = wm8990_hw_params,}, 1369*f10485e7SMark Brown .dai_ops = { 1370*f10485e7SMark Brown .digital_mute = wm8990_mute, 1371*f10485e7SMark Brown .set_fmt = wm8990_set_dai_fmt, 1372*f10485e7SMark Brown .set_clkdiv = wm8990_set_dai_clkdiv, 1373*f10485e7SMark Brown .set_pll = wm8990_set_dai_pll, 1374*f10485e7SMark Brown .set_sysclk = wm8990_set_dai_sysclk, 1375*f10485e7SMark Brown }, 1376*f10485e7SMark Brown }; 1377*f10485e7SMark Brown EXPORT_SYMBOL_GPL(wm8990_dai); 1378*f10485e7SMark Brown 1379*f10485e7SMark Brown static int wm8990_suspend(struct platform_device *pdev, pm_message_t state) 1380*f10485e7SMark Brown { 1381*f10485e7SMark Brown struct snd_soc_device *socdev = platform_get_drvdata(pdev); 1382*f10485e7SMark Brown struct snd_soc_codec *codec = socdev->codec; 1383*f10485e7SMark Brown 1384*f10485e7SMark Brown /* we only need to suspend if we are a valid card */ 1385*f10485e7SMark Brown if (!codec->card) 1386*f10485e7SMark Brown return 0; 1387*f10485e7SMark Brown 1388*f10485e7SMark Brown wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF); 1389*f10485e7SMark Brown return 0; 1390*f10485e7SMark Brown } 1391*f10485e7SMark Brown 1392*f10485e7SMark Brown static int wm8990_resume(struct platform_device *pdev) 1393*f10485e7SMark Brown { 1394*f10485e7SMark Brown struct snd_soc_device *socdev = platform_get_drvdata(pdev); 1395*f10485e7SMark Brown struct snd_soc_codec *codec = socdev->codec; 1396*f10485e7SMark Brown int i; 1397*f10485e7SMark Brown u8 data[2]; 1398*f10485e7SMark Brown u16 *cache = codec->reg_cache; 1399*f10485e7SMark Brown 1400*f10485e7SMark Brown /* we only need to resume if we are a valid card */ 1401*f10485e7SMark Brown if (!codec->card) 1402*f10485e7SMark Brown return 0; 1403*f10485e7SMark Brown 1404*f10485e7SMark Brown /* Sync reg_cache with the hardware */ 1405*f10485e7SMark Brown for (i = 0; i < ARRAY_SIZE(wm8990_reg); i++) { 1406*f10485e7SMark Brown if (i + 1 == WM8990_RESET) 1407*f10485e7SMark Brown continue; 1408*f10485e7SMark Brown data[0] = ((i + 1) << 1) | ((cache[i] >> 8) & 0x0001); 1409*f10485e7SMark Brown data[1] = cache[i] & 0x00ff; 1410*f10485e7SMark Brown codec->hw_write(codec->control_data, data, 2); 1411*f10485e7SMark Brown } 1412*f10485e7SMark Brown 1413*f10485e7SMark Brown wm8990_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1414*f10485e7SMark Brown return 0; 1415*f10485e7SMark Brown } 1416*f10485e7SMark Brown 1417*f10485e7SMark Brown /* 1418*f10485e7SMark Brown * initialise the WM8990 driver 1419*f10485e7SMark Brown * register the mixer and dsp interfaces with the kernel 1420*f10485e7SMark Brown */ 1421*f10485e7SMark Brown static int wm8990_init(struct snd_soc_device *socdev) 1422*f10485e7SMark Brown { 1423*f10485e7SMark Brown struct snd_soc_codec *codec = socdev->codec; 1424*f10485e7SMark Brown u16 reg; 1425*f10485e7SMark Brown int ret = 0; 1426*f10485e7SMark Brown 1427*f10485e7SMark Brown codec->name = "WM8990"; 1428*f10485e7SMark Brown codec->owner = THIS_MODULE; 1429*f10485e7SMark Brown codec->read = wm8990_read_reg_cache; 1430*f10485e7SMark Brown codec->write = wm8990_write; 1431*f10485e7SMark Brown codec->set_bias_level = wm8990_set_bias_level; 1432*f10485e7SMark Brown codec->dai = &wm8990_dai; 1433*f10485e7SMark Brown codec->num_dai = 2; 1434*f10485e7SMark Brown codec->reg_cache_size = ARRAY_SIZE(wm8990_reg); 1435*f10485e7SMark Brown codec->reg_cache = kmemdup(wm8990_reg, sizeof(wm8990_reg), GFP_KERNEL); 1436*f10485e7SMark Brown 1437*f10485e7SMark Brown if (codec->reg_cache == NULL) 1438*f10485e7SMark Brown return -ENOMEM; 1439*f10485e7SMark Brown 1440*f10485e7SMark Brown wm8990_reset(codec); 1441*f10485e7SMark Brown 1442*f10485e7SMark Brown /* register pcms */ 1443*f10485e7SMark Brown ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); 1444*f10485e7SMark Brown if (ret < 0) { 1445*f10485e7SMark Brown printk(KERN_ERR "wm8990: failed to create pcms\n"); 1446*f10485e7SMark Brown goto pcm_err; 1447*f10485e7SMark Brown } 1448*f10485e7SMark Brown 1449*f10485e7SMark Brown /* charge output caps */ 1450*f10485e7SMark Brown codec->bias_level = SND_SOC_BIAS_OFF; 1451*f10485e7SMark Brown wm8990_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1452*f10485e7SMark Brown 1453*f10485e7SMark Brown reg = wm8990_read_reg_cache(codec, WM8990_AUDIO_INTERFACE_4); 1454*f10485e7SMark Brown wm8990_write(codec, WM8990_AUDIO_INTERFACE_4, reg | WM8990_ALRCGPIO1); 1455*f10485e7SMark Brown 1456*f10485e7SMark Brown reg = wm8990_read_reg_cache(codec, WM8990_GPIO1_GPIO2) & 1457*f10485e7SMark Brown ~WM8990_GPIO1_SEL_MASK; 1458*f10485e7SMark Brown wm8990_write(codec, WM8990_GPIO1_GPIO2, reg | 1); 1459*f10485e7SMark Brown 1460*f10485e7SMark Brown reg = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_2); 1461*f10485e7SMark Brown wm8990_write(codec, WM8990_POWER_MANAGEMENT_2, reg | WM8990_OPCLK_ENA); 1462*f10485e7SMark Brown 1463*f10485e7SMark Brown wm8990_write(codec, WM8990_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8)); 1464*f10485e7SMark Brown wm8990_write(codec, WM8990_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8)); 1465*f10485e7SMark Brown 1466*f10485e7SMark Brown wm8990_add_controls(codec); 1467*f10485e7SMark Brown wm8990_add_widgets(codec); 1468*f10485e7SMark Brown ret = snd_soc_register_card(socdev); 1469*f10485e7SMark Brown if (ret < 0) { 1470*f10485e7SMark Brown printk(KERN_ERR "wm8990: failed to register card\n"); 1471*f10485e7SMark Brown goto card_err; 1472*f10485e7SMark Brown } 1473*f10485e7SMark Brown return ret; 1474*f10485e7SMark Brown 1475*f10485e7SMark Brown card_err: 1476*f10485e7SMark Brown snd_soc_free_pcms(socdev); 1477*f10485e7SMark Brown snd_soc_dapm_free(socdev); 1478*f10485e7SMark Brown pcm_err: 1479*f10485e7SMark Brown kfree(codec->reg_cache); 1480*f10485e7SMark Brown return ret; 1481*f10485e7SMark Brown } 1482*f10485e7SMark Brown 1483*f10485e7SMark Brown /* If the i2c layer weren't so broken, we could pass this kind of data 1484*f10485e7SMark Brown around */ 1485*f10485e7SMark Brown static struct snd_soc_device *wm8990_socdev; 1486*f10485e7SMark Brown 1487*f10485e7SMark Brown #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 1488*f10485e7SMark Brown 1489*f10485e7SMark Brown /* 1490*f10485e7SMark Brown * WM891 2 wire address is determined by GPIO5 1491*f10485e7SMark Brown * state during powerup. 1492*f10485e7SMark Brown * low = 0x34 1493*f10485e7SMark Brown * high = 0x36 1494*f10485e7SMark Brown */ 1495*f10485e7SMark Brown static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END }; 1496*f10485e7SMark Brown 1497*f10485e7SMark Brown /* Magic definition of all other variables and things */ 1498*f10485e7SMark Brown I2C_CLIENT_INSMOD; 1499*f10485e7SMark Brown 1500*f10485e7SMark Brown static struct i2c_driver wm8990_i2c_driver; 1501*f10485e7SMark Brown static struct i2c_client client_template; 1502*f10485e7SMark Brown 1503*f10485e7SMark Brown static int wm8990_codec_probe(struct i2c_adapter *adap, int addr, int kind) 1504*f10485e7SMark Brown { 1505*f10485e7SMark Brown struct snd_soc_device *socdev = wm8990_socdev; 1506*f10485e7SMark Brown struct wm8990_setup_data *setup = socdev->codec_data; 1507*f10485e7SMark Brown struct snd_soc_codec *codec = socdev->codec; 1508*f10485e7SMark Brown struct i2c_client *i2c; 1509*f10485e7SMark Brown int ret; 1510*f10485e7SMark Brown 1511*f10485e7SMark Brown if (addr != setup->i2c_address) 1512*f10485e7SMark Brown return -ENODEV; 1513*f10485e7SMark Brown 1514*f10485e7SMark Brown client_template.adapter = adap; 1515*f10485e7SMark Brown client_template.addr = addr; 1516*f10485e7SMark Brown 1517*f10485e7SMark Brown i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL); 1518*f10485e7SMark Brown if (i2c == NULL) { 1519*f10485e7SMark Brown kfree(codec); 1520*f10485e7SMark Brown return -ENOMEM; 1521*f10485e7SMark Brown } 1522*f10485e7SMark Brown i2c_set_clientdata(i2c, codec); 1523*f10485e7SMark Brown codec->control_data = i2c; 1524*f10485e7SMark Brown 1525*f10485e7SMark Brown ret = i2c_attach_client(i2c); 1526*f10485e7SMark Brown if (ret < 0) { 1527*f10485e7SMark Brown err("failed to attach codec at addr %x\n", addr); 1528*f10485e7SMark Brown goto err; 1529*f10485e7SMark Brown } 1530*f10485e7SMark Brown 1531*f10485e7SMark Brown ret = wm8990_init(socdev); 1532*f10485e7SMark Brown if (ret < 0) { 1533*f10485e7SMark Brown err("failed to initialise WM8990\n"); 1534*f10485e7SMark Brown goto err; 1535*f10485e7SMark Brown } 1536*f10485e7SMark Brown return ret; 1537*f10485e7SMark Brown 1538*f10485e7SMark Brown err: 1539*f10485e7SMark Brown kfree(codec); 1540*f10485e7SMark Brown kfree(i2c); 1541*f10485e7SMark Brown return ret; 1542*f10485e7SMark Brown } 1543*f10485e7SMark Brown 1544*f10485e7SMark Brown static int wm8990_i2c_detach(struct i2c_client *client) 1545*f10485e7SMark Brown { 1546*f10485e7SMark Brown struct snd_soc_codec *codec = i2c_get_clientdata(client); 1547*f10485e7SMark Brown i2c_detach_client(client); 1548*f10485e7SMark Brown kfree(codec->reg_cache); 1549*f10485e7SMark Brown kfree(client); 1550*f10485e7SMark Brown return 0; 1551*f10485e7SMark Brown } 1552*f10485e7SMark Brown 1553*f10485e7SMark Brown static int wm8990_i2c_attach(struct i2c_adapter *adap) 1554*f10485e7SMark Brown { 1555*f10485e7SMark Brown return i2c_probe(adap, &addr_data, wm8990_codec_probe); 1556*f10485e7SMark Brown } 1557*f10485e7SMark Brown 1558*f10485e7SMark Brown static struct i2c_driver wm8990_i2c_driver = { 1559*f10485e7SMark Brown .driver = { 1560*f10485e7SMark Brown .name = "WM8990 I2C Codec", 1561*f10485e7SMark Brown .owner = THIS_MODULE, 1562*f10485e7SMark Brown }, 1563*f10485e7SMark Brown .attach_adapter = wm8990_i2c_attach, 1564*f10485e7SMark Brown .detach_client = wm8990_i2c_detach, 1565*f10485e7SMark Brown .command = NULL, 1566*f10485e7SMark Brown }; 1567*f10485e7SMark Brown 1568*f10485e7SMark Brown static struct i2c_client client_template = { 1569*f10485e7SMark Brown .name = "WM8990", 1570*f10485e7SMark Brown .driver = &wm8990_i2c_driver, 1571*f10485e7SMark Brown }; 1572*f10485e7SMark Brown #endif 1573*f10485e7SMark Brown 1574*f10485e7SMark Brown static int wm8990_probe(struct platform_device *pdev) 1575*f10485e7SMark Brown { 1576*f10485e7SMark Brown struct snd_soc_device *socdev = platform_get_drvdata(pdev); 1577*f10485e7SMark Brown struct wm8990_setup_data *setup; 1578*f10485e7SMark Brown struct snd_soc_codec *codec; 1579*f10485e7SMark Brown struct wm8990_priv *wm8990; 1580*f10485e7SMark Brown int ret = 0; 1581*f10485e7SMark Brown 1582*f10485e7SMark Brown info("WM8990 Audio Codec %s\n", WM8990_VERSION); 1583*f10485e7SMark Brown 1584*f10485e7SMark Brown setup = socdev->codec_data; 1585*f10485e7SMark Brown codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); 1586*f10485e7SMark Brown if (codec == NULL) 1587*f10485e7SMark Brown return -ENOMEM; 1588*f10485e7SMark Brown 1589*f10485e7SMark Brown wm8990 = kzalloc(sizeof(struct wm8990_priv), GFP_KERNEL); 1590*f10485e7SMark Brown if (wm8990 == NULL) { 1591*f10485e7SMark Brown kfree(codec); 1592*f10485e7SMark Brown return -ENOMEM; 1593*f10485e7SMark Brown } 1594*f10485e7SMark Brown 1595*f10485e7SMark Brown codec->private_data = wm8990; 1596*f10485e7SMark Brown socdev->codec = codec; 1597*f10485e7SMark Brown mutex_init(&codec->mutex); 1598*f10485e7SMark Brown INIT_LIST_HEAD(&codec->dapm_widgets); 1599*f10485e7SMark Brown INIT_LIST_HEAD(&codec->dapm_paths); 1600*f10485e7SMark Brown wm8990_socdev = socdev; 1601*f10485e7SMark Brown 1602*f10485e7SMark Brown #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 1603*f10485e7SMark Brown if (setup->i2c_address) { 1604*f10485e7SMark Brown normal_i2c[0] = setup->i2c_address; 1605*f10485e7SMark Brown codec->hw_write = (hw_write_t)i2c_master_send; 1606*f10485e7SMark Brown ret = i2c_add_driver(&wm8990_i2c_driver); 1607*f10485e7SMark Brown if (ret != 0) 1608*f10485e7SMark Brown printk(KERN_ERR "can't add i2c driver"); 1609*f10485e7SMark Brown } 1610*f10485e7SMark Brown #else 1611*f10485e7SMark Brown /* Add other interfaces here */ 1612*f10485e7SMark Brown #endif 1613*f10485e7SMark Brown return ret; 1614*f10485e7SMark Brown } 1615*f10485e7SMark Brown 1616*f10485e7SMark Brown /* power down chip */ 1617*f10485e7SMark Brown static int wm8990_remove(struct platform_device *pdev) 1618*f10485e7SMark Brown { 1619*f10485e7SMark Brown struct snd_soc_device *socdev = platform_get_drvdata(pdev); 1620*f10485e7SMark Brown struct snd_soc_codec *codec = socdev->codec; 1621*f10485e7SMark Brown 1622*f10485e7SMark Brown if (codec->control_data) 1623*f10485e7SMark Brown wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF); 1624*f10485e7SMark Brown snd_soc_free_pcms(socdev); 1625*f10485e7SMark Brown snd_soc_dapm_free(socdev); 1626*f10485e7SMark Brown #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 1627*f10485e7SMark Brown i2c_del_driver(&wm8990_i2c_driver); 1628*f10485e7SMark Brown #endif 1629*f10485e7SMark Brown kfree(codec->private_data); 1630*f10485e7SMark Brown kfree(codec); 1631*f10485e7SMark Brown 1632*f10485e7SMark Brown return 0; 1633*f10485e7SMark Brown } 1634*f10485e7SMark Brown 1635*f10485e7SMark Brown struct snd_soc_codec_device soc_codec_dev_wm8990 = { 1636*f10485e7SMark Brown .probe = wm8990_probe, 1637*f10485e7SMark Brown .remove = wm8990_remove, 1638*f10485e7SMark Brown .suspend = wm8990_suspend, 1639*f10485e7SMark Brown .resume = wm8990_resume, 1640*f10485e7SMark Brown }; 1641*f10485e7SMark Brown EXPORT_SYMBOL_GPL(soc_codec_dev_wm8990); 1642*f10485e7SMark Brown 1643*f10485e7SMark Brown MODULE_DESCRIPTION("ASoC WM8990 driver"); 1644*f10485e7SMark Brown MODULE_AUTHOR("Liam Girdwood"); 1645*f10485e7SMark Brown MODULE_LICENSE("GPL"); 1646