1*d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2272b5eddSBrian Austin /* 3272b5eddSBrian Austin * cs42l56.c -- CS42L56 ALSA SoC audio driver 4272b5eddSBrian Austin * 5272b5eddSBrian Austin * Copyright 2014 CirrusLogic, Inc. 6272b5eddSBrian Austin * 7272b5eddSBrian Austin * Author: Brian Austin <brian.austin@cirrus.com> 8272b5eddSBrian Austin */ 9272b5eddSBrian Austin 10272b5eddSBrian Austin #include <linux/module.h> 11272b5eddSBrian Austin #include <linux/moduleparam.h> 12272b5eddSBrian Austin #include <linux/kernel.h> 13272b5eddSBrian Austin #include <linux/init.h> 14272b5eddSBrian Austin #include <linux/delay.h> 15272b5eddSBrian Austin #include <linux/pm.h> 16272b5eddSBrian Austin #include <linux/i2c.h> 17272b5eddSBrian Austin #include <linux/input.h> 18272b5eddSBrian Austin #include <linux/regmap.h> 19272b5eddSBrian Austin #include <linux/slab.h> 20272b5eddSBrian Austin #include <linux/workqueue.h> 21272b5eddSBrian Austin #include <linux/platform_device.h> 22272b5eddSBrian Austin #include <linux/regulator/consumer.h> 23272b5eddSBrian Austin #include <linux/of_device.h> 24272b5eddSBrian Austin #include <linux/of_gpio.h> 25272b5eddSBrian Austin #include <sound/core.h> 26272b5eddSBrian Austin #include <sound/pcm.h> 27272b5eddSBrian Austin #include <sound/pcm_params.h> 28272b5eddSBrian Austin #include <sound/soc.h> 29272b5eddSBrian Austin #include <sound/soc-dapm.h> 30272b5eddSBrian Austin #include <sound/initval.h> 31272b5eddSBrian Austin #include <sound/tlv.h> 32272b5eddSBrian Austin #include <sound/cs42l56.h> 33272b5eddSBrian Austin #include "cs42l56.h" 34272b5eddSBrian Austin 35272b5eddSBrian Austin #define CS42L56_NUM_SUPPLIES 3 36272b5eddSBrian Austin static const char *const cs42l56_supply_names[CS42L56_NUM_SUPPLIES] = { 37272b5eddSBrian Austin "VA", 38272b5eddSBrian Austin "VCP", 39272b5eddSBrian Austin "VLDO", 40272b5eddSBrian Austin }; 41272b5eddSBrian Austin 42272b5eddSBrian Austin struct cs42l56_private { 43272b5eddSBrian Austin struct regmap *regmap; 44e48f7466SKuninori Morimoto struct snd_soc_component *component; 45272b5eddSBrian Austin struct device *dev; 46272b5eddSBrian Austin struct cs42l56_platform_data pdata; 47272b5eddSBrian Austin struct regulator_bulk_data supplies[CS42L56_NUM_SUPPLIES]; 48272b5eddSBrian Austin u32 mclk; 49272b5eddSBrian Austin u8 mclk_prediv; 50272b5eddSBrian Austin u8 mclk_div2; 51272b5eddSBrian Austin u8 mclk_ratio; 52272b5eddSBrian Austin u8 iface; 53272b5eddSBrian Austin u8 iface_fmt; 54272b5eddSBrian Austin u8 iface_inv; 55de06f22fSJavier Martinez Canillas #if IS_ENABLED(CONFIG_INPUT) 56272b5eddSBrian Austin struct input_dev *beep; 57272b5eddSBrian Austin struct work_struct beep_work; 58272b5eddSBrian Austin int beep_rate; 59272b5eddSBrian Austin #endif 60272b5eddSBrian Austin }; 61272b5eddSBrian Austin 62272b5eddSBrian Austin static const struct reg_default cs42l56_reg_defaults[] = { 63272b5eddSBrian Austin { 3, 0x7f }, /* r03 - Power Ctl 1 */ 64272b5eddSBrian Austin { 4, 0xff }, /* r04 - Power Ctl 2 */ 65272b5eddSBrian Austin { 5, 0x00 }, /* ro5 - Clocking Ctl 1 */ 66272b5eddSBrian Austin { 6, 0x0b }, /* r06 - Clocking Ctl 2 */ 67272b5eddSBrian Austin { 7, 0x00 }, /* r07 - Serial Format */ 68272b5eddSBrian Austin { 8, 0x05 }, /* r08 - Class H Ctl */ 69272b5eddSBrian Austin { 9, 0x0c }, /* r09 - Misc Ctl */ 70272b5eddSBrian Austin { 10, 0x80 }, /* r0a - INT Status */ 71272b5eddSBrian Austin { 11, 0x00 }, /* r0b - Playback Ctl */ 72272b5eddSBrian Austin { 12, 0x0c }, /* r0c - DSP Mute Ctl */ 73272b5eddSBrian Austin { 13, 0x00 }, /* r0d - ADCA Mixer Volume */ 74272b5eddSBrian Austin { 14, 0x00 }, /* r0e - ADCB Mixer Volume */ 75272b5eddSBrian Austin { 15, 0x00 }, /* r0f - PCMA Mixer Volume */ 76272b5eddSBrian Austin { 16, 0x00 }, /* r10 - PCMB Mixer Volume */ 77272b5eddSBrian Austin { 17, 0x00 }, /* r11 - Analog Input Advisory Volume */ 78272b5eddSBrian Austin { 18, 0x00 }, /* r12 - Digital Input Advisory Volume */ 79272b5eddSBrian Austin { 19, 0x00 }, /* r13 - Master A Volume */ 80272b5eddSBrian Austin { 20, 0x00 }, /* r14 - Master B Volume */ 81272b5eddSBrian Austin { 21, 0x00 }, /* r15 - Beep Freq / On Time */ 82272b5eddSBrian Austin { 22, 0x00 }, /* r16 - Beep Volume / Off Time */ 83272b5eddSBrian Austin { 23, 0x00 }, /* r17 - Beep Tone Ctl */ 84272b5eddSBrian Austin { 24, 0x88 }, /* r18 - Tone Ctl */ 85272b5eddSBrian Austin { 25, 0x00 }, /* r19 - Channel Mixer & Swap */ 86272b5eddSBrian Austin { 26, 0x00 }, /* r1a - AIN Ref Config / ADC Mux */ 87272b5eddSBrian Austin { 27, 0xa0 }, /* r1b - High-Pass Filter Ctl */ 88272b5eddSBrian Austin { 28, 0x00 }, /* r1c - Misc ADC Ctl */ 89272b5eddSBrian Austin { 29, 0x00 }, /* r1d - Gain & Bias Ctl */ 90272b5eddSBrian Austin { 30, 0x00 }, /* r1e - PGAA Mux & Volume */ 91272b5eddSBrian Austin { 31, 0x00 }, /* r1f - PGAB Mux & Volume */ 92272b5eddSBrian Austin { 32, 0x00 }, /* r20 - ADCA Attenuator */ 93272b5eddSBrian Austin { 33, 0x00 }, /* r21 - ADCB Attenuator */ 94272b5eddSBrian Austin { 34, 0x00 }, /* r22 - ALC Enable & Attack Rate */ 95272b5eddSBrian Austin { 35, 0xbf }, /* r23 - ALC Release Rate */ 96272b5eddSBrian Austin { 36, 0x00 }, /* r24 - ALC Threshold */ 97272b5eddSBrian Austin { 37, 0x00 }, /* r25 - Noise Gate Ctl */ 98272b5eddSBrian Austin { 38, 0x00 }, /* r26 - ALC, Limiter, SFT, ZeroCross */ 99272b5eddSBrian Austin { 39, 0x00 }, /* r27 - Analog Mute, LO & HP Mux */ 100272b5eddSBrian Austin { 40, 0x00 }, /* r28 - HP A Volume */ 101272b5eddSBrian Austin { 41, 0x00 }, /* r29 - HP B Volume */ 102272b5eddSBrian Austin { 42, 0x00 }, /* r2a - LINEOUT A Volume */ 103272b5eddSBrian Austin { 43, 0x00 }, /* r2b - LINEOUT B Volume */ 104272b5eddSBrian Austin { 44, 0x00 }, /* r2c - Limit Threshold Ctl */ 105272b5eddSBrian Austin { 45, 0x7f }, /* r2d - Limiter Ctl & Release Rate */ 106272b5eddSBrian Austin { 46, 0x00 }, /* r2e - Limiter Attack Rate */ 107272b5eddSBrian Austin }; 108272b5eddSBrian Austin 109272b5eddSBrian Austin static bool cs42l56_readable_register(struct device *dev, unsigned int reg) 110272b5eddSBrian Austin { 111272b5eddSBrian Austin switch (reg) { 1127f325bfcSAxel Lin case CS42L56_CHIP_ID_1 ... CS42L56_LIM_ATTACK_RATE: 113272b5eddSBrian Austin return true; 114272b5eddSBrian Austin default: 115272b5eddSBrian Austin return false; 116272b5eddSBrian Austin } 117272b5eddSBrian Austin } 118272b5eddSBrian Austin 119272b5eddSBrian Austin static bool cs42l56_volatile_register(struct device *dev, unsigned int reg) 120272b5eddSBrian Austin { 121272b5eddSBrian Austin switch (reg) { 122272b5eddSBrian Austin case CS42L56_INT_STATUS: 123c2b49ae6SBrian Austin return true; 124272b5eddSBrian Austin default: 125c2b49ae6SBrian Austin return false; 126272b5eddSBrian Austin } 127272b5eddSBrian Austin } 128272b5eddSBrian Austin 129272b5eddSBrian Austin static DECLARE_TLV_DB_SCALE(beep_tlv, -5000, 200, 0); 130272b5eddSBrian Austin static DECLARE_TLV_DB_SCALE(hl_tlv, -6000, 50, 0); 131272b5eddSBrian Austin static DECLARE_TLV_DB_SCALE(adv_tlv, -10200, 50, 0); 132272b5eddSBrian Austin static DECLARE_TLV_DB_SCALE(adc_tlv, -9600, 100, 0); 133272b5eddSBrian Austin static DECLARE_TLV_DB_SCALE(tone_tlv, -1050, 150, 0); 134272b5eddSBrian Austin static DECLARE_TLV_DB_SCALE(preamp_tlv, 0, 1000, 0); 135272b5eddSBrian Austin static DECLARE_TLV_DB_SCALE(pga_tlv, -600, 50, 0); 136272b5eddSBrian Austin 13737879bafSLars-Peter Clausen static const DECLARE_TLV_DB_RANGE(ngnb_tlv, 138272b5eddSBrian Austin 0, 1, TLV_DB_SCALE_ITEM(-8200, 600, 0), 13937879bafSLars-Peter Clausen 2, 5, TLV_DB_SCALE_ITEM(-7600, 300, 0) 14037879bafSLars-Peter Clausen ); 14137879bafSLars-Peter Clausen static const DECLARE_TLV_DB_RANGE(ngb_tlv, 142272b5eddSBrian Austin 0, 2, TLV_DB_SCALE_ITEM(-6400, 600, 0), 14337879bafSLars-Peter Clausen 3, 7, TLV_DB_SCALE_ITEM(-4600, 300, 0) 14437879bafSLars-Peter Clausen ); 14537879bafSLars-Peter Clausen static const DECLARE_TLV_DB_RANGE(alc_tlv, 146272b5eddSBrian Austin 0, 2, TLV_DB_SCALE_ITEM(-3000, 600, 0), 14737879bafSLars-Peter Clausen 3, 7, TLV_DB_SCALE_ITEM(-1200, 300, 0) 14837879bafSLars-Peter Clausen ); 149272b5eddSBrian Austin 150272b5eddSBrian Austin static const char * const beep_config_text[] = { 151272b5eddSBrian Austin "Off", "Single", "Multiple", "Continuous" 152272b5eddSBrian Austin }; 153272b5eddSBrian Austin 154272b5eddSBrian Austin static const struct soc_enum beep_config_enum = 155272b5eddSBrian Austin SOC_ENUM_SINGLE(CS42L56_BEEP_TONE_CFG, 6, 156272b5eddSBrian Austin ARRAY_SIZE(beep_config_text), beep_config_text); 157272b5eddSBrian Austin 158272b5eddSBrian Austin static const char * const beep_pitch_text[] = { 159272b5eddSBrian Austin "C4", "C5", "D5", "E5", "F5", "G5", "A5", "B5", 160272b5eddSBrian Austin "C6", "D6", "E6", "F6", "G6", "A6", "B6", "C7" 161272b5eddSBrian Austin }; 162272b5eddSBrian Austin 163272b5eddSBrian Austin static const struct soc_enum beep_pitch_enum = 164272b5eddSBrian Austin SOC_ENUM_SINGLE(CS42L56_BEEP_FREQ_ONTIME, 4, 165272b5eddSBrian Austin ARRAY_SIZE(beep_pitch_text), beep_pitch_text); 166272b5eddSBrian Austin 167272b5eddSBrian Austin static const char * const beep_ontime_text[] = { 168272b5eddSBrian Austin "86 ms", "430 ms", "780 ms", "1.20 s", "1.50 s", 169272b5eddSBrian Austin "1.80 s", "2.20 s", "2.50 s", "2.80 s", "3.20 s", 170272b5eddSBrian Austin "3.50 s", "3.80 s", "4.20 s", "4.50 s", "4.80 s", "5.20 s" 171272b5eddSBrian Austin }; 172272b5eddSBrian Austin 173272b5eddSBrian Austin static const struct soc_enum beep_ontime_enum = 174272b5eddSBrian Austin SOC_ENUM_SINGLE(CS42L56_BEEP_FREQ_ONTIME, 0, 175272b5eddSBrian Austin ARRAY_SIZE(beep_ontime_text), beep_ontime_text); 176272b5eddSBrian Austin 177272b5eddSBrian Austin static const char * const beep_offtime_text[] = { 178272b5eddSBrian Austin "1.23 s", "2.58 s", "3.90 s", "5.20 s", 179272b5eddSBrian Austin "6.60 s", "8.05 s", "9.35 s", "10.80 s" 180272b5eddSBrian Austin }; 181272b5eddSBrian Austin 182272b5eddSBrian Austin static const struct soc_enum beep_offtime_enum = 183272b5eddSBrian Austin SOC_ENUM_SINGLE(CS42L56_BEEP_FREQ_OFFTIME, 5, 184272b5eddSBrian Austin ARRAY_SIZE(beep_offtime_text), beep_offtime_text); 185272b5eddSBrian Austin 186272b5eddSBrian Austin static const char * const beep_treble_text[] = { 187272b5eddSBrian Austin "5kHz", "7kHz", "10kHz", "15kHz" 188272b5eddSBrian Austin }; 189272b5eddSBrian Austin 190272b5eddSBrian Austin static const struct soc_enum beep_treble_enum = 191272b5eddSBrian Austin SOC_ENUM_SINGLE(CS42L56_BEEP_TONE_CFG, 3, 192272b5eddSBrian Austin ARRAY_SIZE(beep_treble_text), beep_treble_text); 193272b5eddSBrian Austin 194272b5eddSBrian Austin static const char * const beep_bass_text[] = { 195272b5eddSBrian Austin "50Hz", "100Hz", "200Hz", "250Hz" 196272b5eddSBrian Austin }; 197272b5eddSBrian Austin 198272b5eddSBrian Austin static const struct soc_enum beep_bass_enum = 199272b5eddSBrian Austin SOC_ENUM_SINGLE(CS42L56_BEEP_TONE_CFG, 1, 200272b5eddSBrian Austin ARRAY_SIZE(beep_bass_text), beep_bass_text); 201272b5eddSBrian Austin 202272b5eddSBrian Austin static const char * const adc_swap_text[] = { 203272b5eddSBrian Austin "None", "A+B/2", "A-B/2", "Swap" 204272b5eddSBrian Austin }; 205272b5eddSBrian Austin 206272b5eddSBrian Austin static const struct soc_enum adc_swap_enum = 207272b5eddSBrian Austin SOC_ENUM_SINGLE(CS42L56_MISC_ADC_CTL, 3, 208272b5eddSBrian Austin ARRAY_SIZE(adc_swap_text), adc_swap_text); 209272b5eddSBrian Austin 210272b5eddSBrian Austin static const char * const pgaa_mux_text[] = { 211272b5eddSBrian Austin "AIN1A", "AIN2A", "AIN3A"}; 212272b5eddSBrian Austin 213272b5eddSBrian Austin static const struct soc_enum pgaa_mux_enum = 214272b5eddSBrian Austin SOC_ENUM_SINGLE(CS42L56_PGAA_MUX_VOLUME, 0, 215272b5eddSBrian Austin ARRAY_SIZE(pgaa_mux_text), 216272b5eddSBrian Austin pgaa_mux_text); 217272b5eddSBrian Austin 218272b5eddSBrian Austin static const struct snd_kcontrol_new pgaa_mux = 219272b5eddSBrian Austin SOC_DAPM_ENUM("Route", pgaa_mux_enum); 220272b5eddSBrian Austin 221272b5eddSBrian Austin static const char * const pgab_mux_text[] = { 222272b5eddSBrian Austin "AIN1B", "AIN2B", "AIN3B"}; 223272b5eddSBrian Austin 224272b5eddSBrian Austin static const struct soc_enum pgab_mux_enum = 225272b5eddSBrian Austin SOC_ENUM_SINGLE(CS42L56_PGAB_MUX_VOLUME, 0, 226272b5eddSBrian Austin ARRAY_SIZE(pgab_mux_text), 227272b5eddSBrian Austin pgab_mux_text); 228272b5eddSBrian Austin 229272b5eddSBrian Austin static const struct snd_kcontrol_new pgab_mux = 230272b5eddSBrian Austin SOC_DAPM_ENUM("Route", pgab_mux_enum); 231272b5eddSBrian Austin 232272b5eddSBrian Austin static const char * const adca_mux_text[] = { 233272b5eddSBrian Austin "PGAA", "AIN1A", "AIN2A", "AIN3A"}; 234272b5eddSBrian Austin 235272b5eddSBrian Austin static const struct soc_enum adca_mux_enum = 236272b5eddSBrian Austin SOC_ENUM_SINGLE(CS42L56_AIN_REFCFG_ADC_MUX, 0, 237272b5eddSBrian Austin ARRAY_SIZE(adca_mux_text), 238272b5eddSBrian Austin adca_mux_text); 239272b5eddSBrian Austin 240272b5eddSBrian Austin static const struct snd_kcontrol_new adca_mux = 241272b5eddSBrian Austin SOC_DAPM_ENUM("Route", adca_mux_enum); 242272b5eddSBrian Austin 243272b5eddSBrian Austin static const char * const adcb_mux_text[] = { 244272b5eddSBrian Austin "PGAB", "AIN1B", "AIN2B", "AIN3B"}; 245272b5eddSBrian Austin 246272b5eddSBrian Austin static const struct soc_enum adcb_mux_enum = 247272b5eddSBrian Austin SOC_ENUM_SINGLE(CS42L56_AIN_REFCFG_ADC_MUX, 2, 248272b5eddSBrian Austin ARRAY_SIZE(adcb_mux_text), 249272b5eddSBrian Austin adcb_mux_text); 250272b5eddSBrian Austin 251272b5eddSBrian Austin static const struct snd_kcontrol_new adcb_mux = 252272b5eddSBrian Austin SOC_DAPM_ENUM("Route", adcb_mux_enum); 253272b5eddSBrian Austin 254272b5eddSBrian Austin static const char * const left_swap_text[] = { 255272b5eddSBrian Austin "Left", "LR 2", "Right"}; 256272b5eddSBrian Austin 257272b5eddSBrian Austin static const char * const right_swap_text[] = { 258272b5eddSBrian Austin "Right", "LR 2", "Left"}; 259272b5eddSBrian Austin 260272b5eddSBrian Austin static const unsigned int swap_values[] = { 0, 1, 3 }; 261272b5eddSBrian Austin 262272b5eddSBrian Austin static const struct soc_enum adca_swap_enum = 263272b5eddSBrian Austin SOC_VALUE_ENUM_SINGLE(CS42L56_CHAN_MIX_SWAP, 0, 3, 264272b5eddSBrian Austin ARRAY_SIZE(left_swap_text), 265272b5eddSBrian Austin left_swap_text, 266272b5eddSBrian Austin swap_values); 267c4324bfaSBrian Austin static const struct snd_kcontrol_new adca_swap_mux = 268c4324bfaSBrian Austin SOC_DAPM_ENUM("Route", adca_swap_enum); 269272b5eddSBrian Austin 270272b5eddSBrian Austin static const struct soc_enum pcma_swap_enum = 271272b5eddSBrian Austin SOC_VALUE_ENUM_SINGLE(CS42L56_CHAN_MIX_SWAP, 4, 3, 272272b5eddSBrian Austin ARRAY_SIZE(left_swap_text), 273272b5eddSBrian Austin left_swap_text, 274272b5eddSBrian Austin swap_values); 275c4324bfaSBrian Austin static const struct snd_kcontrol_new pcma_swap_mux = 276c4324bfaSBrian Austin SOC_DAPM_ENUM("Route", pcma_swap_enum); 277272b5eddSBrian Austin 278272b5eddSBrian Austin static const struct soc_enum adcb_swap_enum = 279272b5eddSBrian Austin SOC_VALUE_ENUM_SINGLE(CS42L56_CHAN_MIX_SWAP, 2, 3, 280272b5eddSBrian Austin ARRAY_SIZE(right_swap_text), 281272b5eddSBrian Austin right_swap_text, 282272b5eddSBrian Austin swap_values); 283c4324bfaSBrian Austin static const struct snd_kcontrol_new adcb_swap_mux = 284c4324bfaSBrian Austin SOC_DAPM_ENUM("Route", adcb_swap_enum); 285272b5eddSBrian Austin 286272b5eddSBrian Austin static const struct soc_enum pcmb_swap_enum = 287272b5eddSBrian Austin SOC_VALUE_ENUM_SINGLE(CS42L56_CHAN_MIX_SWAP, 6, 3, 288272b5eddSBrian Austin ARRAY_SIZE(right_swap_text), 289272b5eddSBrian Austin right_swap_text, 290272b5eddSBrian Austin swap_values); 291c4324bfaSBrian Austin static const struct snd_kcontrol_new pcmb_swap_mux = 292c4324bfaSBrian Austin SOC_DAPM_ENUM("Route", pcmb_swap_enum); 293272b5eddSBrian Austin 294272b5eddSBrian Austin static const struct snd_kcontrol_new hpa_switch = 295272b5eddSBrian Austin SOC_DAPM_SINGLE("Switch", CS42L56_PWRCTL_2, 6, 1, 1); 296272b5eddSBrian Austin 297272b5eddSBrian Austin static const struct snd_kcontrol_new hpb_switch = 298272b5eddSBrian Austin SOC_DAPM_SINGLE("Switch", CS42L56_PWRCTL_2, 4, 1, 1); 299272b5eddSBrian Austin 300272b5eddSBrian Austin static const struct snd_kcontrol_new loa_switch = 301272b5eddSBrian Austin SOC_DAPM_SINGLE("Switch", CS42L56_PWRCTL_2, 2, 1, 1); 302272b5eddSBrian Austin 303272b5eddSBrian Austin static const struct snd_kcontrol_new lob_switch = 304272b5eddSBrian Austin SOC_DAPM_SINGLE("Switch", CS42L56_PWRCTL_2, 0, 1, 1); 305272b5eddSBrian Austin 306272b5eddSBrian Austin static const char * const hploa_input_text[] = { 307272b5eddSBrian Austin "DACA", "PGAA"}; 308272b5eddSBrian Austin 309272b5eddSBrian Austin static const struct soc_enum lineouta_input_enum = 310272b5eddSBrian Austin SOC_ENUM_SINGLE(CS42L56_AMUTE_HPLO_MUX, 2, 311272b5eddSBrian Austin ARRAY_SIZE(hploa_input_text), 312272b5eddSBrian Austin hploa_input_text); 313272b5eddSBrian Austin 314272b5eddSBrian Austin static const struct snd_kcontrol_new lineouta_input = 315272b5eddSBrian Austin SOC_DAPM_ENUM("Route", lineouta_input_enum); 316272b5eddSBrian Austin 317272b5eddSBrian Austin static const struct soc_enum hpa_input_enum = 318272b5eddSBrian Austin SOC_ENUM_SINGLE(CS42L56_AMUTE_HPLO_MUX, 0, 319272b5eddSBrian Austin ARRAY_SIZE(hploa_input_text), 320272b5eddSBrian Austin hploa_input_text); 321272b5eddSBrian Austin 322272b5eddSBrian Austin static const struct snd_kcontrol_new hpa_input = 323272b5eddSBrian Austin SOC_DAPM_ENUM("Route", hpa_input_enum); 324272b5eddSBrian Austin 325272b5eddSBrian Austin static const char * const hplob_input_text[] = { 326272b5eddSBrian Austin "DACB", "PGAB"}; 327272b5eddSBrian Austin 328272b5eddSBrian Austin static const struct soc_enum lineoutb_input_enum = 329272b5eddSBrian Austin SOC_ENUM_SINGLE(CS42L56_AMUTE_HPLO_MUX, 3, 330272b5eddSBrian Austin ARRAY_SIZE(hplob_input_text), 331272b5eddSBrian Austin hplob_input_text); 332272b5eddSBrian Austin 333272b5eddSBrian Austin static const struct snd_kcontrol_new lineoutb_input = 334272b5eddSBrian Austin SOC_DAPM_ENUM("Route", lineoutb_input_enum); 335272b5eddSBrian Austin 336272b5eddSBrian Austin static const struct soc_enum hpb_input_enum = 337272b5eddSBrian Austin SOC_ENUM_SINGLE(CS42L56_AMUTE_HPLO_MUX, 1, 338272b5eddSBrian Austin ARRAY_SIZE(hplob_input_text), 339272b5eddSBrian Austin hplob_input_text); 340272b5eddSBrian Austin 341272b5eddSBrian Austin static const struct snd_kcontrol_new hpb_input = 342272b5eddSBrian Austin SOC_DAPM_ENUM("Route", hpb_input_enum); 343272b5eddSBrian Austin 344272b5eddSBrian Austin static const char * const dig_mux_text[] = { 345272b5eddSBrian Austin "ADC", "DSP"}; 346272b5eddSBrian Austin 347272b5eddSBrian Austin static const struct soc_enum dig_mux_enum = 348272b5eddSBrian Austin SOC_ENUM_SINGLE(CS42L56_MISC_CTL, 7, 349272b5eddSBrian Austin ARRAY_SIZE(dig_mux_text), 350272b5eddSBrian Austin dig_mux_text); 351272b5eddSBrian Austin 352272b5eddSBrian Austin static const struct snd_kcontrol_new dig_mux = 353272b5eddSBrian Austin SOC_DAPM_ENUM("Route", dig_mux_enum); 354272b5eddSBrian Austin 355272b5eddSBrian Austin static const char * const hpf_freq_text[] = { 356272b5eddSBrian Austin "1.8Hz", "119Hz", "236Hz", "464Hz" 357272b5eddSBrian Austin }; 358272b5eddSBrian Austin 359272b5eddSBrian Austin static const struct soc_enum hpfa_freq_enum = 360272b5eddSBrian Austin SOC_ENUM_SINGLE(CS42L56_HPF_CTL, 0, 361272b5eddSBrian Austin ARRAY_SIZE(hpf_freq_text), hpf_freq_text); 362272b5eddSBrian Austin 363272b5eddSBrian Austin static const struct soc_enum hpfb_freq_enum = 364272b5eddSBrian Austin SOC_ENUM_SINGLE(CS42L56_HPF_CTL, 2, 365272b5eddSBrian Austin ARRAY_SIZE(hpf_freq_text), hpf_freq_text); 366272b5eddSBrian Austin 367272b5eddSBrian Austin static const char * const ng_delay_text[] = { 368272b5eddSBrian Austin "50ms", "100ms", "150ms", "200ms" 369272b5eddSBrian Austin }; 370272b5eddSBrian Austin 371272b5eddSBrian Austin static const struct soc_enum ng_delay_enum = 372272b5eddSBrian Austin SOC_ENUM_SINGLE(CS42L56_NOISE_GATE_CTL, 0, 373272b5eddSBrian Austin ARRAY_SIZE(ng_delay_text), ng_delay_text); 374272b5eddSBrian Austin 375272b5eddSBrian Austin static const struct snd_kcontrol_new cs42l56_snd_controls[] = { 376272b5eddSBrian Austin 377272b5eddSBrian Austin SOC_DOUBLE_R_SX_TLV("Master Volume", CS42L56_MASTER_A_VOLUME, 378a0465587SBrian Austin CS42L56_MASTER_B_VOLUME, 0, 0x34, 0xE4, adv_tlv), 379272b5eddSBrian Austin SOC_DOUBLE("Master Mute Switch", CS42L56_DSP_MUTE_CTL, 0, 1, 1, 1), 380272b5eddSBrian Austin 381272b5eddSBrian Austin SOC_DOUBLE_R_SX_TLV("ADC Mixer Volume", CS42L56_ADCA_MIX_VOLUME, 382a0465587SBrian Austin CS42L56_ADCB_MIX_VOLUME, 0, 0x88, 0x90, hl_tlv), 383272b5eddSBrian Austin SOC_DOUBLE("ADC Mixer Mute Switch", CS42L56_DSP_MUTE_CTL, 6, 7, 1, 1), 384272b5eddSBrian Austin 385272b5eddSBrian Austin SOC_DOUBLE_R_SX_TLV("PCM Mixer Volume", CS42L56_PCMA_MIX_VOLUME, 386a0465587SBrian Austin CS42L56_PCMB_MIX_VOLUME, 0, 0x88, 0x90, hl_tlv), 387272b5eddSBrian Austin SOC_DOUBLE("PCM Mixer Mute Switch", CS42L56_DSP_MUTE_CTL, 4, 5, 1, 1), 388272b5eddSBrian Austin 389272b5eddSBrian Austin SOC_SINGLE_TLV("Analog Advisory Volume", 390272b5eddSBrian Austin CS42L56_ANAINPUT_ADV_VOLUME, 0, 0x00, 1, adv_tlv), 391272b5eddSBrian Austin SOC_SINGLE_TLV("Digital Advisory Volume", 392272b5eddSBrian Austin CS42L56_DIGINPUT_ADV_VOLUME, 0, 0x00, 1, adv_tlv), 393272b5eddSBrian Austin 394272b5eddSBrian Austin SOC_DOUBLE_R_SX_TLV("PGA Volume", CS42L56_PGAA_MUX_VOLUME, 395a0465587SBrian Austin CS42L56_PGAB_MUX_VOLUME, 0, 0x34, 0x24, pga_tlv), 396272b5eddSBrian Austin SOC_DOUBLE_R_TLV("ADC Volume", CS42L56_ADCA_ATTENUATOR, 397272b5eddSBrian Austin CS42L56_ADCB_ATTENUATOR, 0, 0x00, 1, adc_tlv), 398272b5eddSBrian Austin SOC_DOUBLE("ADC Mute Switch", CS42L56_MISC_ADC_CTL, 2, 3, 1, 1), 399272b5eddSBrian Austin SOC_DOUBLE("ADC Boost Switch", CS42L56_GAIN_BIAS_CTL, 3, 2, 1, 1), 400272b5eddSBrian Austin 401272b5eddSBrian Austin SOC_DOUBLE_R_SX_TLV("Headphone Volume", CS42L56_HPA_VOLUME, 402a0465587SBrian Austin CS42L56_HPB_VOLUME, 0, 0x84, 0x48, hl_tlv), 403272b5eddSBrian Austin SOC_DOUBLE_R_SX_TLV("LineOut Volume", CS42L56_LOA_VOLUME, 404a0465587SBrian Austin CS42L56_LOB_VOLUME, 0, 0x84, 0x48, hl_tlv), 405272b5eddSBrian Austin 406272b5eddSBrian Austin SOC_SINGLE_TLV("Bass Shelving Volume", CS42L56_TONE_CTL, 407272b5eddSBrian Austin 0, 0x00, 1, tone_tlv), 408272b5eddSBrian Austin SOC_SINGLE_TLV("Treble Shelving Volume", CS42L56_TONE_CTL, 409272b5eddSBrian Austin 4, 0x00, 1, tone_tlv), 410272b5eddSBrian Austin 411272b5eddSBrian Austin SOC_DOUBLE_TLV("PGA Preamp Volume", CS42L56_GAIN_BIAS_CTL, 412272b5eddSBrian Austin 4, 6, 0x02, 1, preamp_tlv), 413272b5eddSBrian Austin 414272b5eddSBrian Austin SOC_SINGLE("DSP Switch", CS42L56_PLAYBACK_CTL, 7, 1, 1), 415272b5eddSBrian Austin SOC_SINGLE("Gang Playback Switch", CS42L56_PLAYBACK_CTL, 4, 1, 1), 416272b5eddSBrian Austin SOC_SINGLE("Gang ADC Switch", CS42L56_MISC_ADC_CTL, 7, 1, 1), 417272b5eddSBrian Austin SOC_SINGLE("Gang PGA Switch", CS42L56_MISC_ADC_CTL, 6, 1, 1), 418272b5eddSBrian Austin 419272b5eddSBrian Austin SOC_SINGLE("PCMA Invert", CS42L56_PLAYBACK_CTL, 2, 1, 1), 420272b5eddSBrian Austin SOC_SINGLE("PCMB Invert", CS42L56_PLAYBACK_CTL, 3, 1, 1), 421272b5eddSBrian Austin SOC_SINGLE("ADCA Invert", CS42L56_MISC_ADC_CTL, 2, 1, 1), 422272b5eddSBrian Austin SOC_SINGLE("ADCB Invert", CS42L56_MISC_ADC_CTL, 3, 1, 1), 423272b5eddSBrian Austin 424272b5eddSBrian Austin SOC_DOUBLE("HPF Switch", CS42L56_HPF_CTL, 5, 7, 1, 1), 425272b5eddSBrian Austin SOC_DOUBLE("HPF Freeze Switch", CS42L56_HPF_CTL, 4, 6, 1, 1), 426272b5eddSBrian Austin SOC_ENUM("HPFA Corner Freq", hpfa_freq_enum), 427272b5eddSBrian Austin SOC_ENUM("HPFB Corner Freq", hpfb_freq_enum), 428272b5eddSBrian Austin 429272b5eddSBrian Austin SOC_SINGLE("Analog Soft Ramp", CS42L56_MISC_CTL, 4, 1, 1), 430272b5eddSBrian Austin SOC_DOUBLE("Analog Soft Ramp Disable", CS42L56_ALC_LIM_SFT_ZC, 431272b5eddSBrian Austin 7, 5, 1, 1), 432272b5eddSBrian Austin SOC_SINGLE("Analog Zero Cross", CS42L56_MISC_CTL, 3, 1, 1), 433272b5eddSBrian Austin SOC_DOUBLE("Analog Zero Cross Disable", CS42L56_ALC_LIM_SFT_ZC, 434272b5eddSBrian Austin 6, 4, 1, 1), 435272b5eddSBrian Austin SOC_SINGLE("Digital Soft Ramp", CS42L56_MISC_CTL, 2, 1, 1), 436272b5eddSBrian Austin SOC_SINGLE("Digital Soft Ramp Disable", CS42L56_ALC_LIM_SFT_ZC, 437272b5eddSBrian Austin 3, 1, 1), 438272b5eddSBrian Austin 439272b5eddSBrian Austin SOC_SINGLE("HL Deemphasis", CS42L56_PLAYBACK_CTL, 6, 1, 1), 440272b5eddSBrian Austin 441272b5eddSBrian Austin SOC_SINGLE("ALC Switch", CS42L56_ALC_EN_ATTACK_RATE, 6, 1, 1), 442272b5eddSBrian Austin SOC_SINGLE("ALC Limit All Switch", CS42L56_ALC_RELEASE_RATE, 7, 1, 1), 443272b5eddSBrian Austin SOC_SINGLE_RANGE("ALC Attack", CS42L56_ALC_EN_ATTACK_RATE, 444272b5eddSBrian Austin 0, 0, 0x3f, 0), 445272b5eddSBrian Austin SOC_SINGLE_RANGE("ALC Release", CS42L56_ALC_RELEASE_RATE, 446272b5eddSBrian Austin 0, 0x3f, 0, 0), 447272b5eddSBrian Austin SOC_SINGLE_TLV("ALC MAX", CS42L56_ALC_THRESHOLD, 448272b5eddSBrian Austin 5, 0x07, 1, alc_tlv), 449272b5eddSBrian Austin SOC_SINGLE_TLV("ALC MIN", CS42L56_ALC_THRESHOLD, 450272b5eddSBrian Austin 2, 0x07, 1, alc_tlv), 451272b5eddSBrian Austin 452272b5eddSBrian Austin SOC_SINGLE("Limiter Switch", CS42L56_LIM_CTL_RELEASE_RATE, 7, 1, 1), 453272b5eddSBrian Austin SOC_SINGLE("Limit All Switch", CS42L56_LIM_CTL_RELEASE_RATE, 6, 1, 1), 454272b5eddSBrian Austin SOC_SINGLE_RANGE("Limiter Attack", CS42L56_LIM_ATTACK_RATE, 455272b5eddSBrian Austin 0, 0, 0x3f, 0), 456272b5eddSBrian Austin SOC_SINGLE_RANGE("Limiter Release", CS42L56_LIM_CTL_RELEASE_RATE, 457272b5eddSBrian Austin 0, 0x3f, 0, 0), 458272b5eddSBrian Austin SOC_SINGLE_TLV("Limiter MAX", CS42L56_LIM_THRESHOLD_CTL, 459272b5eddSBrian Austin 5, 0x07, 1, alc_tlv), 460272b5eddSBrian Austin SOC_SINGLE_TLV("Limiter Cushion", CS42L56_ALC_THRESHOLD, 461272b5eddSBrian Austin 2, 0x07, 1, alc_tlv), 462272b5eddSBrian Austin 463272b5eddSBrian Austin SOC_SINGLE("NG Switch", CS42L56_NOISE_GATE_CTL, 6, 1, 1), 464272b5eddSBrian Austin SOC_SINGLE("NG All Switch", CS42L56_NOISE_GATE_CTL, 7, 1, 1), 465272b5eddSBrian Austin SOC_SINGLE("NG Boost Switch", CS42L56_NOISE_GATE_CTL, 5, 1, 1), 466272b5eddSBrian Austin SOC_SINGLE_TLV("NG Unboost Threshold", CS42L56_NOISE_GATE_CTL, 467272b5eddSBrian Austin 2, 0x07, 1, ngnb_tlv), 468272b5eddSBrian Austin SOC_SINGLE_TLV("NG Boost Threshold", CS42L56_NOISE_GATE_CTL, 469272b5eddSBrian Austin 2, 0x07, 1, ngb_tlv), 470272b5eddSBrian Austin SOC_ENUM("NG Delay", ng_delay_enum), 471272b5eddSBrian Austin 472272b5eddSBrian Austin SOC_ENUM("Beep Config", beep_config_enum), 473272b5eddSBrian Austin SOC_ENUM("Beep Pitch", beep_pitch_enum), 474272b5eddSBrian Austin SOC_ENUM("Beep on Time", beep_ontime_enum), 475272b5eddSBrian Austin SOC_ENUM("Beep off Time", beep_offtime_enum), 476272b5eddSBrian Austin SOC_SINGLE_SX_TLV("Beep Volume", CS42L56_BEEP_FREQ_OFFTIME, 477272b5eddSBrian Austin 0, 0x07, 0x23, beep_tlv), 478272b5eddSBrian Austin SOC_SINGLE("Beep Tone Ctl Switch", CS42L56_BEEP_TONE_CFG, 0, 1, 1), 479272b5eddSBrian Austin SOC_ENUM("Beep Treble Corner Freq", beep_treble_enum), 480272b5eddSBrian Austin SOC_ENUM("Beep Bass Corner Freq", beep_bass_enum), 481272b5eddSBrian Austin 482272b5eddSBrian Austin }; 483272b5eddSBrian Austin 484272b5eddSBrian Austin static const struct snd_soc_dapm_widget cs42l56_dapm_widgets[] = { 485272b5eddSBrian Austin 486272b5eddSBrian Austin SND_SOC_DAPM_SIGGEN("Beep"), 487272b5eddSBrian Austin SND_SOC_DAPM_SUPPLY("VBUF", CS42L56_PWRCTL_1, 5, 1, NULL, 0), 488272b5eddSBrian Austin SND_SOC_DAPM_MICBIAS("MIC1 Bias", CS42L56_PWRCTL_1, 4, 1), 489272b5eddSBrian Austin SND_SOC_DAPM_SUPPLY("Charge Pump", CS42L56_PWRCTL_1, 3, 1, NULL, 0), 490272b5eddSBrian Austin 491272b5eddSBrian Austin SND_SOC_DAPM_INPUT("AIN1A"), 492272b5eddSBrian Austin SND_SOC_DAPM_INPUT("AIN2A"), 493272b5eddSBrian Austin SND_SOC_DAPM_INPUT("AIN1B"), 494272b5eddSBrian Austin SND_SOC_DAPM_INPUT("AIN2B"), 495272b5eddSBrian Austin SND_SOC_DAPM_INPUT("AIN3A"), 496272b5eddSBrian Austin SND_SOC_DAPM_INPUT("AIN3B"), 497272b5eddSBrian Austin 498272b5eddSBrian Austin SND_SOC_DAPM_AIF_OUT("SDOUT", NULL, 0, 499272b5eddSBrian Austin SND_SOC_NOPM, 0, 0), 500272b5eddSBrian Austin 501272b5eddSBrian Austin SND_SOC_DAPM_AIF_IN("SDIN", NULL, 0, 502272b5eddSBrian Austin SND_SOC_NOPM, 0, 0), 503272b5eddSBrian Austin 504272b5eddSBrian Austin SND_SOC_DAPM_MUX("Digital Output Mux", SND_SOC_NOPM, 505272b5eddSBrian Austin 0, 0, &dig_mux), 506272b5eddSBrian Austin 507272b5eddSBrian Austin SND_SOC_DAPM_PGA("PGAA", SND_SOC_NOPM, 0, 0, NULL, 0), 508272b5eddSBrian Austin SND_SOC_DAPM_PGA("PGAB", SND_SOC_NOPM, 0, 0, NULL, 0), 509272b5eddSBrian Austin SND_SOC_DAPM_MUX("PGAA Input Mux", 510272b5eddSBrian Austin SND_SOC_NOPM, 0, 0, &pgaa_mux), 511272b5eddSBrian Austin SND_SOC_DAPM_MUX("PGAB Input Mux", 512272b5eddSBrian Austin SND_SOC_NOPM, 0, 0, &pgab_mux), 513272b5eddSBrian Austin 514272b5eddSBrian Austin SND_SOC_DAPM_MUX("ADCA Mux", SND_SOC_NOPM, 515272b5eddSBrian Austin 0, 0, &adca_mux), 516272b5eddSBrian Austin SND_SOC_DAPM_MUX("ADCB Mux", SND_SOC_NOPM, 517272b5eddSBrian Austin 0, 0, &adcb_mux), 518272b5eddSBrian Austin 519272b5eddSBrian Austin SND_SOC_DAPM_ADC("ADCA", NULL, CS42L56_PWRCTL_1, 1, 1), 520272b5eddSBrian Austin SND_SOC_DAPM_ADC("ADCB", NULL, CS42L56_PWRCTL_1, 2, 1), 521272b5eddSBrian Austin 522c4324bfaSBrian Austin SND_SOC_DAPM_MUX("ADCA Swap Mux", SND_SOC_NOPM, 0, 0, 523c4324bfaSBrian Austin &adca_swap_mux), 524c4324bfaSBrian Austin SND_SOC_DAPM_MUX("ADCB Swap Mux", SND_SOC_NOPM, 0, 0, 525c4324bfaSBrian Austin &adcb_swap_mux), 526c4324bfaSBrian Austin 527c4324bfaSBrian Austin SND_SOC_DAPM_MUX("PCMA Swap Mux", SND_SOC_NOPM, 0, 0, 528c4324bfaSBrian Austin &pcma_swap_mux), 529c4324bfaSBrian Austin SND_SOC_DAPM_MUX("PCMB Swap Mux", SND_SOC_NOPM, 0, 0, 530c4324bfaSBrian Austin &pcmb_swap_mux), 531c4324bfaSBrian Austin 532272b5eddSBrian Austin SND_SOC_DAPM_DAC("DACA", NULL, SND_SOC_NOPM, 0, 0), 533272b5eddSBrian Austin SND_SOC_DAPM_DAC("DACB", NULL, SND_SOC_NOPM, 0, 0), 534272b5eddSBrian Austin 535272b5eddSBrian Austin SND_SOC_DAPM_OUTPUT("HPA"), 536272b5eddSBrian Austin SND_SOC_DAPM_OUTPUT("LOA"), 537272b5eddSBrian Austin SND_SOC_DAPM_OUTPUT("HPB"), 538272b5eddSBrian Austin SND_SOC_DAPM_OUTPUT("LOB"), 539272b5eddSBrian Austin 540272b5eddSBrian Austin SND_SOC_DAPM_SWITCH("Headphone Right", 541272b5eddSBrian Austin CS42L56_PWRCTL_2, 4, 1, &hpb_switch), 542272b5eddSBrian Austin SND_SOC_DAPM_SWITCH("Headphone Left", 543272b5eddSBrian Austin CS42L56_PWRCTL_2, 6, 1, &hpa_switch), 544272b5eddSBrian Austin 545272b5eddSBrian Austin SND_SOC_DAPM_SWITCH("Lineout Right", 546272b5eddSBrian Austin CS42L56_PWRCTL_2, 0, 1, &lob_switch), 547272b5eddSBrian Austin SND_SOC_DAPM_SWITCH("Lineout Left", 548272b5eddSBrian Austin CS42L56_PWRCTL_2, 2, 1, &loa_switch), 549272b5eddSBrian Austin 550272b5eddSBrian Austin SND_SOC_DAPM_MUX("LINEOUTA Input Mux", SND_SOC_NOPM, 551272b5eddSBrian Austin 0, 0, &lineouta_input), 552272b5eddSBrian Austin SND_SOC_DAPM_MUX("LINEOUTB Input Mux", SND_SOC_NOPM, 553272b5eddSBrian Austin 0, 0, &lineoutb_input), 554272b5eddSBrian Austin SND_SOC_DAPM_MUX("HPA Input Mux", SND_SOC_NOPM, 555272b5eddSBrian Austin 0, 0, &hpa_input), 556272b5eddSBrian Austin SND_SOC_DAPM_MUX("HPB Input Mux", SND_SOC_NOPM, 557272b5eddSBrian Austin 0, 0, &hpb_input), 558272b5eddSBrian Austin 559272b5eddSBrian Austin }; 560272b5eddSBrian Austin 561272b5eddSBrian Austin static const struct snd_soc_dapm_route cs42l56_audio_map[] = { 562272b5eddSBrian Austin 563272b5eddSBrian Austin {"HiFi Capture", "DSP", "Digital Output Mux"}, 564272b5eddSBrian Austin {"HiFi Capture", "ADC", "Digital Output Mux"}, 565272b5eddSBrian Austin 566272b5eddSBrian Austin {"Digital Output Mux", NULL, "ADCA"}, 567272b5eddSBrian Austin {"Digital Output Mux", NULL, "ADCB"}, 568272b5eddSBrian Austin 569c4324bfaSBrian Austin {"ADCB", NULL, "ADCB Swap Mux"}, 570c4324bfaSBrian Austin {"ADCA", NULL, "ADCA Swap Mux"}, 571c4324bfaSBrian Austin 572c4324bfaSBrian Austin {"ADCA Swap Mux", NULL, "ADCA"}, 573c4324bfaSBrian Austin {"ADCB Swap Mux", NULL, "ADCB"}, 574c4324bfaSBrian Austin 575c4324bfaSBrian Austin {"DACA", "Left", "ADCA Swap Mux"}, 576c4324bfaSBrian Austin {"DACA", "LR 2", "ADCA Swap Mux"}, 577c4324bfaSBrian Austin {"DACA", "Right", "ADCA Swap Mux"}, 578c4324bfaSBrian Austin 579c4324bfaSBrian Austin {"DACB", "Left", "ADCB Swap Mux"}, 580c4324bfaSBrian Austin {"DACB", "LR 2", "ADCB Swap Mux"}, 581c4324bfaSBrian Austin {"DACB", "Right", "ADCB Swap Mux"}, 582272b5eddSBrian Austin 583272b5eddSBrian Austin {"ADCA Mux", NULL, "AIN3A"}, 584272b5eddSBrian Austin {"ADCA Mux", NULL, "AIN2A"}, 585272b5eddSBrian Austin {"ADCA Mux", NULL, "AIN1A"}, 586272b5eddSBrian Austin {"ADCA Mux", NULL, "PGAA"}, 587272b5eddSBrian Austin {"ADCB Mux", NULL, "AIN3B"}, 588272b5eddSBrian Austin {"ADCB Mux", NULL, "AIN2B"}, 589272b5eddSBrian Austin {"ADCB Mux", NULL, "AIN1B"}, 590272b5eddSBrian Austin {"ADCB Mux", NULL, "PGAB"}, 591272b5eddSBrian Austin 592272b5eddSBrian Austin {"PGAA", "AIN1A", "PGAA Input Mux"}, 593272b5eddSBrian Austin {"PGAA", "AIN2A", "PGAA Input Mux"}, 594272b5eddSBrian Austin {"PGAA", "AIN3A", "PGAA Input Mux"}, 595272b5eddSBrian Austin {"PGAB", "AIN1B", "PGAB Input Mux"}, 596272b5eddSBrian Austin {"PGAB", "AIN2B", "PGAB Input Mux"}, 597272b5eddSBrian Austin {"PGAB", "AIN3B", "PGAB Input Mux"}, 598272b5eddSBrian Austin 599272b5eddSBrian Austin {"PGAA Input Mux", NULL, "AIN1A"}, 600272b5eddSBrian Austin {"PGAA Input Mux", NULL, "AIN2A"}, 601272b5eddSBrian Austin {"PGAA Input Mux", NULL, "AIN3A"}, 602272b5eddSBrian Austin {"PGAB Input Mux", NULL, "AIN1B"}, 603272b5eddSBrian Austin {"PGAB Input Mux", NULL, "AIN2B"}, 604272b5eddSBrian Austin {"PGAB Input Mux", NULL, "AIN3B"}, 605272b5eddSBrian Austin 606c4324bfaSBrian Austin {"LOB", "Switch", "LINEOUTB Input Mux"}, 607c4324bfaSBrian Austin {"LOA", "Switch", "LINEOUTA Input Mux"}, 608272b5eddSBrian Austin 609272b5eddSBrian Austin {"LINEOUTA Input Mux", "PGAA", "PGAA"}, 610272b5eddSBrian Austin {"LINEOUTB Input Mux", "PGAB", "PGAB"}, 611272b5eddSBrian Austin {"LINEOUTA Input Mux", "DACA", "DACA"}, 612272b5eddSBrian Austin {"LINEOUTB Input Mux", "DACB", "DACB"}, 613272b5eddSBrian Austin 614c4324bfaSBrian Austin {"HPA", "Switch", "HPB Input Mux"}, 615c4324bfaSBrian Austin {"HPB", "Switch", "HPA Input Mux"}, 616272b5eddSBrian Austin 617272b5eddSBrian Austin {"HPA Input Mux", "PGAA", "PGAA"}, 618272b5eddSBrian Austin {"HPB Input Mux", "PGAB", "PGAB"}, 619272b5eddSBrian Austin {"HPA Input Mux", "DACA", "DACA"}, 620272b5eddSBrian Austin {"HPB Input Mux", "DACB", "DACB"}, 621272b5eddSBrian Austin 622c4324bfaSBrian Austin {"DACA", NULL, "PCMA Swap Mux"}, 623c4324bfaSBrian Austin {"DACB", NULL, "PCMB Swap Mux"}, 624c4324bfaSBrian Austin 625c4324bfaSBrian Austin {"PCMB Swap Mux", "Left", "HiFi Playback"}, 626c4324bfaSBrian Austin {"PCMB Swap Mux", "LR 2", "HiFi Playback"}, 627c4324bfaSBrian Austin {"PCMB Swap Mux", "Right", "HiFi Playback"}, 628c4324bfaSBrian Austin 629c4324bfaSBrian Austin {"PCMA Swap Mux", "Left", "HiFi Playback"}, 630c4324bfaSBrian Austin {"PCMA Swap Mux", "LR 2", "HiFi Playback"}, 631c4324bfaSBrian Austin {"PCMA Swap Mux", "Right", "HiFi Playback"}, 632272b5eddSBrian Austin 633272b5eddSBrian Austin }; 634272b5eddSBrian Austin 635272b5eddSBrian Austin struct cs42l56_clk_para { 636272b5eddSBrian Austin u32 mclk; 637272b5eddSBrian Austin u32 srate; 638272b5eddSBrian Austin u8 ratio; 639272b5eddSBrian Austin }; 640272b5eddSBrian Austin 641272b5eddSBrian Austin static const struct cs42l56_clk_para clk_ratio_table[] = { 642272b5eddSBrian Austin /* 8k */ 643272b5eddSBrian Austin { 6000000, 8000, CS42L56_MCLK_LRCLK_768 }, 644272b5eddSBrian Austin { 6144000, 8000, CS42L56_MCLK_LRCLK_750 }, 645272b5eddSBrian Austin { 12000000, 8000, CS42L56_MCLK_LRCLK_768 }, 646272b5eddSBrian Austin { 12288000, 8000, CS42L56_MCLK_LRCLK_750 }, 647272b5eddSBrian Austin { 24000000, 8000, CS42L56_MCLK_LRCLK_768 }, 648272b5eddSBrian Austin { 24576000, 8000, CS42L56_MCLK_LRCLK_750 }, 649272b5eddSBrian Austin /* 11.025k */ 650272b5eddSBrian Austin { 5644800, 11025, CS42L56_MCLK_LRCLK_512}, 651272b5eddSBrian Austin { 11289600, 11025, CS42L56_MCLK_LRCLK_512}, 652272b5eddSBrian Austin { 22579200, 11025, CS42L56_MCLK_LRCLK_512 }, 653272b5eddSBrian Austin /* 11.0294k */ 654272b5eddSBrian Austin { 6000000, 110294, CS42L56_MCLK_LRCLK_544 }, 655272b5eddSBrian Austin { 12000000, 110294, CS42L56_MCLK_LRCLK_544 }, 656272b5eddSBrian Austin { 24000000, 110294, CS42L56_MCLK_LRCLK_544 }, 657272b5eddSBrian Austin /* 12k */ 658272b5eddSBrian Austin { 6000000, 12000, CS42L56_MCLK_LRCLK_500 }, 659272b5eddSBrian Austin { 6144000, 12000, CS42L56_MCLK_LRCLK_512 }, 660272b5eddSBrian Austin { 12000000, 12000, CS42L56_MCLK_LRCLK_500 }, 661272b5eddSBrian Austin { 12288000, 12000, CS42L56_MCLK_LRCLK_512 }, 662272b5eddSBrian Austin { 24000000, 12000, CS42L56_MCLK_LRCLK_500 }, 663272b5eddSBrian Austin { 24576000, 12000, CS42L56_MCLK_LRCLK_512 }, 664272b5eddSBrian Austin /* 16k */ 665272b5eddSBrian Austin { 6000000, 16000, CS42L56_MCLK_LRCLK_375 }, 666272b5eddSBrian Austin { 6144000, 16000, CS42L56_MCLK_LRCLK_384 }, 667272b5eddSBrian Austin { 12000000, 16000, CS42L56_MCLK_LRCLK_375 }, 668272b5eddSBrian Austin { 12288000, 16000, CS42L56_MCLK_LRCLK_384 }, 669272b5eddSBrian Austin { 24000000, 16000, CS42L56_MCLK_LRCLK_375 }, 670272b5eddSBrian Austin { 24576000, 16000, CS42L56_MCLK_LRCLK_384 }, 671272b5eddSBrian Austin /* 22.050k */ 672272b5eddSBrian Austin { 5644800, 22050, CS42L56_MCLK_LRCLK_256 }, 673272b5eddSBrian Austin { 11289600, 22050, CS42L56_MCLK_LRCLK_256 }, 674272b5eddSBrian Austin { 22579200, 22050, CS42L56_MCLK_LRCLK_256 }, 675272b5eddSBrian Austin /* 22.0588k */ 676272b5eddSBrian Austin { 6000000, 220588, CS42L56_MCLK_LRCLK_272 }, 677272b5eddSBrian Austin { 12000000, 220588, CS42L56_MCLK_LRCLK_272 }, 678272b5eddSBrian Austin { 24000000, 220588, CS42L56_MCLK_LRCLK_272 }, 679272b5eddSBrian Austin /* 24k */ 680272b5eddSBrian Austin { 6000000, 24000, CS42L56_MCLK_LRCLK_250 }, 681272b5eddSBrian Austin { 6144000, 24000, CS42L56_MCLK_LRCLK_256 }, 682272b5eddSBrian Austin { 12000000, 24000, CS42L56_MCLK_LRCLK_250 }, 683272b5eddSBrian Austin { 12288000, 24000, CS42L56_MCLK_LRCLK_256 }, 684272b5eddSBrian Austin { 24000000, 24000, CS42L56_MCLK_LRCLK_250 }, 685272b5eddSBrian Austin { 24576000, 24000, CS42L56_MCLK_LRCLK_256 }, 686272b5eddSBrian Austin /* 32k */ 687272b5eddSBrian Austin { 6000000, 32000, CS42L56_MCLK_LRCLK_187P5 }, 688272b5eddSBrian Austin { 6144000, 32000, CS42L56_MCLK_LRCLK_192 }, 689272b5eddSBrian Austin { 12000000, 32000, CS42L56_MCLK_LRCLK_187P5 }, 690272b5eddSBrian Austin { 12288000, 32000, CS42L56_MCLK_LRCLK_192 }, 691272b5eddSBrian Austin { 24000000, 32000, CS42L56_MCLK_LRCLK_187P5 }, 692272b5eddSBrian Austin { 24576000, 32000, CS42L56_MCLK_LRCLK_192 }, 693272b5eddSBrian Austin /* 44.118k */ 694272b5eddSBrian Austin { 6000000, 44118, CS42L56_MCLK_LRCLK_136 }, 695272b5eddSBrian Austin { 12000000, 44118, CS42L56_MCLK_LRCLK_136 }, 696272b5eddSBrian Austin { 24000000, 44118, CS42L56_MCLK_LRCLK_136 }, 697272b5eddSBrian Austin /* 44.1k */ 698272b5eddSBrian Austin { 5644800, 44100, CS42L56_MCLK_LRCLK_128 }, 699272b5eddSBrian Austin { 11289600, 44100, CS42L56_MCLK_LRCLK_128 }, 700272b5eddSBrian Austin { 22579200, 44100, CS42L56_MCLK_LRCLK_128 }, 701272b5eddSBrian Austin /* 48k */ 702272b5eddSBrian Austin { 6000000, 48000, CS42L56_MCLK_LRCLK_125 }, 703272b5eddSBrian Austin { 6144000, 48000, CS42L56_MCLK_LRCLK_128 }, 704272b5eddSBrian Austin { 12000000, 48000, CS42L56_MCLK_LRCLK_125 }, 705272b5eddSBrian Austin { 12288000, 48000, CS42L56_MCLK_LRCLK_128 }, 706272b5eddSBrian Austin { 24000000, 48000, CS42L56_MCLK_LRCLK_125 }, 707272b5eddSBrian Austin { 24576000, 48000, CS42L56_MCLK_LRCLK_128 }, 708272b5eddSBrian Austin }; 709272b5eddSBrian Austin 710272b5eddSBrian Austin static int cs42l56_get_mclk_ratio(int mclk, int rate) 711272b5eddSBrian Austin { 712272b5eddSBrian Austin int i; 713272b5eddSBrian Austin 714272b5eddSBrian Austin for (i = 0; i < ARRAY_SIZE(clk_ratio_table); i++) { 715272b5eddSBrian Austin if (clk_ratio_table[i].mclk == mclk && 716272b5eddSBrian Austin clk_ratio_table[i].srate == rate) 717272b5eddSBrian Austin return clk_ratio_table[i].ratio; 718272b5eddSBrian Austin } 719272b5eddSBrian Austin return -EINVAL; 720272b5eddSBrian Austin } 721272b5eddSBrian Austin 722272b5eddSBrian Austin static int cs42l56_set_sysclk(struct snd_soc_dai *codec_dai, 723272b5eddSBrian Austin int clk_id, unsigned int freq, int dir) 724272b5eddSBrian Austin { 725e48f7466SKuninori Morimoto struct snd_soc_component *component = codec_dai->component; 726e48f7466SKuninori Morimoto struct cs42l56_private *cs42l56 = snd_soc_component_get_drvdata(component); 727272b5eddSBrian Austin 728272b5eddSBrian Austin switch (freq) { 729272b5eddSBrian Austin case CS42L56_MCLK_5P6448MHZ: 730272b5eddSBrian Austin case CS42L56_MCLK_6MHZ: 731272b5eddSBrian Austin case CS42L56_MCLK_6P144MHZ: 732272b5eddSBrian Austin cs42l56->mclk_div2 = 0; 733272b5eddSBrian Austin cs42l56->mclk_prediv = 0; 734272b5eddSBrian Austin break; 735272b5eddSBrian Austin case CS42L56_MCLK_11P2896MHZ: 736272b5eddSBrian Austin case CS42L56_MCLK_12MHZ: 737272b5eddSBrian Austin case CS42L56_MCLK_12P288MHZ: 7384641c771SAxel Lin cs42l56->mclk_div2 = CS42L56_MCLK_DIV2; 739272b5eddSBrian Austin cs42l56->mclk_prediv = 0; 740272b5eddSBrian Austin break; 741272b5eddSBrian Austin case CS42L56_MCLK_22P5792MHZ: 742272b5eddSBrian Austin case CS42L56_MCLK_24MHZ: 743272b5eddSBrian Austin case CS42L56_MCLK_24P576MHZ: 7444641c771SAxel Lin cs42l56->mclk_div2 = CS42L56_MCLK_DIV2; 7454641c771SAxel Lin cs42l56->mclk_prediv = CS42L56_MCLK_PREDIV; 746272b5eddSBrian Austin break; 747272b5eddSBrian Austin default: 748272b5eddSBrian Austin return -EINVAL; 749272b5eddSBrian Austin } 750272b5eddSBrian Austin cs42l56->mclk = freq; 751272b5eddSBrian Austin 752e48f7466SKuninori Morimoto snd_soc_component_update_bits(component, CS42L56_CLKCTL_1, 753272b5eddSBrian Austin CS42L56_MCLK_PREDIV_MASK, 754272b5eddSBrian Austin cs42l56->mclk_prediv); 755e48f7466SKuninori Morimoto snd_soc_component_update_bits(component, CS42L56_CLKCTL_1, 756272b5eddSBrian Austin CS42L56_MCLK_DIV2_MASK, 757272b5eddSBrian Austin cs42l56->mclk_div2); 758272b5eddSBrian Austin 759272b5eddSBrian Austin return 0; 760272b5eddSBrian Austin } 761272b5eddSBrian Austin 762272b5eddSBrian Austin static int cs42l56_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) 763272b5eddSBrian Austin { 764e48f7466SKuninori Morimoto struct snd_soc_component *component = codec_dai->component; 765e48f7466SKuninori Morimoto struct cs42l56_private *cs42l56 = snd_soc_component_get_drvdata(component); 766272b5eddSBrian Austin 767272b5eddSBrian Austin switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 768272b5eddSBrian Austin case SND_SOC_DAIFMT_CBM_CFM: 769272b5eddSBrian Austin cs42l56->iface = CS42L56_MASTER_MODE; 770272b5eddSBrian Austin break; 771272b5eddSBrian Austin case SND_SOC_DAIFMT_CBS_CFS: 772272b5eddSBrian Austin cs42l56->iface = CS42L56_SLAVE_MODE; 773272b5eddSBrian Austin break; 774272b5eddSBrian Austin default: 775272b5eddSBrian Austin return -EINVAL; 776272b5eddSBrian Austin } 777272b5eddSBrian Austin 778272b5eddSBrian Austin /* interface format */ 779272b5eddSBrian Austin switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 780272b5eddSBrian Austin case SND_SOC_DAIFMT_I2S: 781272b5eddSBrian Austin cs42l56->iface_fmt = CS42L56_DIG_FMT_I2S; 782272b5eddSBrian Austin break; 783272b5eddSBrian Austin case SND_SOC_DAIFMT_LEFT_J: 784272b5eddSBrian Austin cs42l56->iface_fmt = CS42L56_DIG_FMT_LEFT_J; 785272b5eddSBrian Austin break; 786272b5eddSBrian Austin default: 787272b5eddSBrian Austin return -EINVAL; 788272b5eddSBrian Austin } 789272b5eddSBrian Austin 790272b5eddSBrian Austin /* sclk inversion */ 791272b5eddSBrian Austin switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 792272b5eddSBrian Austin case SND_SOC_DAIFMT_NB_NF: 793272b5eddSBrian Austin cs42l56->iface_inv = 0; 794272b5eddSBrian Austin break; 795272b5eddSBrian Austin case SND_SOC_DAIFMT_IB_NF: 796272b5eddSBrian Austin cs42l56->iface_inv = CS42L56_SCLK_INV; 797272b5eddSBrian Austin break; 798272b5eddSBrian Austin default: 799272b5eddSBrian Austin return -EINVAL; 800272b5eddSBrian Austin } 801272b5eddSBrian Austin 802e48f7466SKuninori Morimoto snd_soc_component_update_bits(component, CS42L56_CLKCTL_1, 803272b5eddSBrian Austin CS42L56_MS_MODE_MASK, cs42l56->iface); 804e48f7466SKuninori Morimoto snd_soc_component_update_bits(component, CS42L56_SERIAL_FMT, 805272b5eddSBrian Austin CS42L56_DIG_FMT_MASK, cs42l56->iface_fmt); 806e48f7466SKuninori Morimoto snd_soc_component_update_bits(component, CS42L56_CLKCTL_1, 807272b5eddSBrian Austin CS42L56_SCLK_INV_MASK, cs42l56->iface_inv); 808272b5eddSBrian Austin return 0; 809272b5eddSBrian Austin } 810272b5eddSBrian Austin 811272b5eddSBrian Austin static int cs42l56_digital_mute(struct snd_soc_dai *dai, int mute) 812272b5eddSBrian Austin { 813e48f7466SKuninori Morimoto struct snd_soc_component *component = dai->component; 814272b5eddSBrian Austin 815272b5eddSBrian Austin if (mute) { 816272b5eddSBrian Austin /* Hit the DSP Mixer first */ 817e48f7466SKuninori Morimoto snd_soc_component_update_bits(component, CS42L56_DSP_MUTE_CTL, 818272b5eddSBrian Austin CS42L56_ADCAMIX_MUTE_MASK | 819272b5eddSBrian Austin CS42L56_ADCBMIX_MUTE_MASK | 820272b5eddSBrian Austin CS42L56_PCMAMIX_MUTE_MASK | 821272b5eddSBrian Austin CS42L56_PCMBMIX_MUTE_MASK | 822272b5eddSBrian Austin CS42L56_MSTB_MUTE_MASK | 823272b5eddSBrian Austin CS42L56_MSTA_MUTE_MASK, 8244641c771SAxel Lin CS42L56_MUTE_ALL); 825272b5eddSBrian Austin /* Mute ADC's */ 826e48f7466SKuninori Morimoto snd_soc_component_update_bits(component, CS42L56_MISC_ADC_CTL, 827272b5eddSBrian Austin CS42L56_ADCA_MUTE_MASK | 828272b5eddSBrian Austin CS42L56_ADCB_MUTE_MASK, 8294641c771SAxel Lin CS42L56_MUTE_ALL); 830272b5eddSBrian Austin /* HP And LO */ 831e48f7466SKuninori Morimoto snd_soc_component_update_bits(component, CS42L56_HPA_VOLUME, 8324641c771SAxel Lin CS42L56_HP_MUTE_MASK, CS42L56_MUTE_ALL); 833e48f7466SKuninori Morimoto snd_soc_component_update_bits(component, CS42L56_HPB_VOLUME, 8344641c771SAxel Lin CS42L56_HP_MUTE_MASK, CS42L56_MUTE_ALL); 835e48f7466SKuninori Morimoto snd_soc_component_update_bits(component, CS42L56_LOA_VOLUME, 8364641c771SAxel Lin CS42L56_LO_MUTE_MASK, CS42L56_MUTE_ALL); 837e48f7466SKuninori Morimoto snd_soc_component_update_bits(component, CS42L56_LOB_VOLUME, 8384641c771SAxel Lin CS42L56_LO_MUTE_MASK, CS42L56_MUTE_ALL); 839272b5eddSBrian Austin } else { 840e48f7466SKuninori Morimoto snd_soc_component_update_bits(component, CS42L56_DSP_MUTE_CTL, 841272b5eddSBrian Austin CS42L56_ADCAMIX_MUTE_MASK | 842272b5eddSBrian Austin CS42L56_ADCBMIX_MUTE_MASK | 843272b5eddSBrian Austin CS42L56_PCMAMIX_MUTE_MASK | 844272b5eddSBrian Austin CS42L56_PCMBMIX_MUTE_MASK | 845272b5eddSBrian Austin CS42L56_MSTB_MUTE_MASK | 846272b5eddSBrian Austin CS42L56_MSTA_MUTE_MASK, 847272b5eddSBrian Austin CS42L56_UNMUTE); 8484641c771SAxel Lin 849e48f7466SKuninori Morimoto snd_soc_component_update_bits(component, CS42L56_MISC_ADC_CTL, 850272b5eddSBrian Austin CS42L56_ADCA_MUTE_MASK | 851272b5eddSBrian Austin CS42L56_ADCB_MUTE_MASK, 852272b5eddSBrian Austin CS42L56_UNMUTE); 8534641c771SAxel Lin 854e48f7466SKuninori Morimoto snd_soc_component_update_bits(component, CS42L56_HPA_VOLUME, 8554641c771SAxel Lin CS42L56_HP_MUTE_MASK, CS42L56_UNMUTE); 856e48f7466SKuninori Morimoto snd_soc_component_update_bits(component, CS42L56_HPB_VOLUME, 8574641c771SAxel Lin CS42L56_HP_MUTE_MASK, CS42L56_UNMUTE); 858e48f7466SKuninori Morimoto snd_soc_component_update_bits(component, CS42L56_LOA_VOLUME, 8594641c771SAxel Lin CS42L56_LO_MUTE_MASK, CS42L56_UNMUTE); 860e48f7466SKuninori Morimoto snd_soc_component_update_bits(component, CS42L56_LOB_VOLUME, 8614641c771SAxel Lin CS42L56_LO_MUTE_MASK, CS42L56_UNMUTE); 862272b5eddSBrian Austin } 863272b5eddSBrian Austin return 0; 864272b5eddSBrian Austin } 865272b5eddSBrian Austin 866272b5eddSBrian Austin static int cs42l56_pcm_hw_params(struct snd_pcm_substream *substream, 867272b5eddSBrian Austin struct snd_pcm_hw_params *params, 868272b5eddSBrian Austin struct snd_soc_dai *dai) 869272b5eddSBrian Austin { 870e48f7466SKuninori Morimoto struct snd_soc_component *component = dai->component; 871e48f7466SKuninori Morimoto struct cs42l56_private *cs42l56 = snd_soc_component_get_drvdata(component); 872272b5eddSBrian Austin int ratio; 873272b5eddSBrian Austin 874272b5eddSBrian Austin ratio = cs42l56_get_mclk_ratio(cs42l56->mclk, params_rate(params)); 875272b5eddSBrian Austin if (ratio >= 0) { 876e48f7466SKuninori Morimoto snd_soc_component_update_bits(component, CS42L56_CLKCTL_2, 877272b5eddSBrian Austin CS42L56_CLK_RATIO_MASK, ratio); 878272b5eddSBrian Austin } else { 879e48f7466SKuninori Morimoto dev_err(component->dev, "unsupported mclk/sclk/lrclk ratio\n"); 880272b5eddSBrian Austin return -EINVAL; 881272b5eddSBrian Austin } 882272b5eddSBrian Austin 883272b5eddSBrian Austin return 0; 884272b5eddSBrian Austin } 885272b5eddSBrian Austin 886e48f7466SKuninori Morimoto static int cs42l56_set_bias_level(struct snd_soc_component *component, 887272b5eddSBrian Austin enum snd_soc_bias_level level) 888272b5eddSBrian Austin { 889e48f7466SKuninori Morimoto struct cs42l56_private *cs42l56 = snd_soc_component_get_drvdata(component); 890272b5eddSBrian Austin int ret; 891272b5eddSBrian Austin 892272b5eddSBrian Austin switch (level) { 893272b5eddSBrian Austin case SND_SOC_BIAS_ON: 894272b5eddSBrian Austin break; 895272b5eddSBrian Austin case SND_SOC_BIAS_PREPARE: 896e48f7466SKuninori Morimoto snd_soc_component_update_bits(component, CS42L56_CLKCTL_1, 897272b5eddSBrian Austin CS42L56_MCLK_DIS_MASK, 0); 898e48f7466SKuninori Morimoto snd_soc_component_update_bits(component, CS42L56_PWRCTL_1, 899272b5eddSBrian Austin CS42L56_PDN_ALL_MASK, 0); 900272b5eddSBrian Austin break; 901272b5eddSBrian Austin case SND_SOC_BIAS_STANDBY: 902e48f7466SKuninori Morimoto if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) { 903272b5eddSBrian Austin regcache_cache_only(cs42l56->regmap, false); 904272b5eddSBrian Austin regcache_sync(cs42l56->regmap); 905272b5eddSBrian Austin ret = regulator_bulk_enable(ARRAY_SIZE(cs42l56->supplies), 906272b5eddSBrian Austin cs42l56->supplies); 907272b5eddSBrian Austin if (ret != 0) { 908272b5eddSBrian Austin dev_err(cs42l56->dev, 909272b5eddSBrian Austin "Failed to enable regulators: %d\n", 910272b5eddSBrian Austin ret); 911272b5eddSBrian Austin return ret; 912272b5eddSBrian Austin } 913272b5eddSBrian Austin } 914e48f7466SKuninori Morimoto snd_soc_component_update_bits(component, CS42L56_PWRCTL_1, 915272b5eddSBrian Austin CS42L56_PDN_ALL_MASK, 1); 916272b5eddSBrian Austin break; 917272b5eddSBrian Austin case SND_SOC_BIAS_OFF: 918e48f7466SKuninori Morimoto snd_soc_component_update_bits(component, CS42L56_PWRCTL_1, 919272b5eddSBrian Austin CS42L56_PDN_ALL_MASK, 1); 920e48f7466SKuninori Morimoto snd_soc_component_update_bits(component, CS42L56_CLKCTL_1, 921272b5eddSBrian Austin CS42L56_MCLK_DIS_MASK, 1); 922272b5eddSBrian Austin regcache_cache_only(cs42l56->regmap, true); 923272b5eddSBrian Austin regulator_bulk_disable(ARRAY_SIZE(cs42l56->supplies), 924272b5eddSBrian Austin cs42l56->supplies); 925272b5eddSBrian Austin break; 926272b5eddSBrian Austin } 927272b5eddSBrian Austin 928272b5eddSBrian Austin return 0; 929272b5eddSBrian Austin } 930272b5eddSBrian Austin 931272b5eddSBrian Austin #define CS42L56_RATES (SNDRV_PCM_RATE_8000_48000) 932272b5eddSBrian Austin 933272b5eddSBrian Austin #define CS42L56_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE | \ 934272b5eddSBrian Austin SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE | \ 935272b5eddSBrian Austin SNDRV_PCM_FMTBIT_S32_LE) 936272b5eddSBrian Austin 937272b5eddSBrian Austin 93864793047SAxel Lin static const struct snd_soc_dai_ops cs42l56_ops = { 939272b5eddSBrian Austin .hw_params = cs42l56_pcm_hw_params, 940272b5eddSBrian Austin .digital_mute = cs42l56_digital_mute, 941272b5eddSBrian Austin .set_fmt = cs42l56_set_dai_fmt, 942272b5eddSBrian Austin .set_sysclk = cs42l56_set_sysclk, 943272b5eddSBrian Austin }; 944272b5eddSBrian Austin 945272b5eddSBrian Austin static struct snd_soc_dai_driver cs42l56_dai = { 946272b5eddSBrian Austin .name = "cs42l56", 947272b5eddSBrian Austin .playback = { 948272b5eddSBrian Austin .stream_name = "HiFi Playback", 949272b5eddSBrian Austin .channels_min = 1, 950272b5eddSBrian Austin .channels_max = 2, 951272b5eddSBrian Austin .rates = CS42L56_RATES, 952272b5eddSBrian Austin .formats = CS42L56_FORMATS, 953272b5eddSBrian Austin }, 954272b5eddSBrian Austin .capture = { 955272b5eddSBrian Austin .stream_name = "HiFi Capture", 956272b5eddSBrian Austin .channels_min = 1, 957272b5eddSBrian Austin .channels_max = 2, 958272b5eddSBrian Austin .rates = CS42L56_RATES, 959272b5eddSBrian Austin .formats = CS42L56_FORMATS, 960272b5eddSBrian Austin }, 961272b5eddSBrian Austin .ops = &cs42l56_ops, 962272b5eddSBrian Austin }; 963272b5eddSBrian Austin 964272b5eddSBrian Austin static int beep_freq[] = { 965272b5eddSBrian Austin 261, 522, 585, 667, 706, 774, 889, 1000, 966272b5eddSBrian Austin 1043, 1200, 1333, 1412, 1600, 1714, 2000, 2182 967272b5eddSBrian Austin }; 968272b5eddSBrian Austin 969272b5eddSBrian Austin static void cs42l56_beep_work(struct work_struct *work) 970272b5eddSBrian Austin { 971272b5eddSBrian Austin struct cs42l56_private *cs42l56 = 972272b5eddSBrian Austin container_of(work, struct cs42l56_private, beep_work); 973e48f7466SKuninori Morimoto struct snd_soc_component *component = cs42l56->component; 974e48f7466SKuninori Morimoto struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); 975272b5eddSBrian Austin int i; 976272b5eddSBrian Austin int val = 0; 977272b5eddSBrian Austin int best = 0; 978272b5eddSBrian Austin 979272b5eddSBrian Austin if (cs42l56->beep_rate) { 980272b5eddSBrian Austin for (i = 0; i < ARRAY_SIZE(beep_freq); i++) { 981272b5eddSBrian Austin if (abs(cs42l56->beep_rate - beep_freq[i]) < 982272b5eddSBrian Austin abs(cs42l56->beep_rate - beep_freq[best])) 983272b5eddSBrian Austin best = i; 984272b5eddSBrian Austin } 985272b5eddSBrian Austin 986e48f7466SKuninori Morimoto dev_dbg(component->dev, "Set beep rate %dHz for requested %dHz\n", 987272b5eddSBrian Austin beep_freq[best], cs42l56->beep_rate); 988272b5eddSBrian Austin 989272b5eddSBrian Austin val = (best << CS42L56_BEEP_RATE_SHIFT); 990272b5eddSBrian Austin 991272b5eddSBrian Austin snd_soc_dapm_enable_pin(dapm, "Beep"); 992272b5eddSBrian Austin } else { 993e48f7466SKuninori Morimoto dev_dbg(component->dev, "Disabling beep\n"); 994272b5eddSBrian Austin snd_soc_dapm_disable_pin(dapm, "Beep"); 995272b5eddSBrian Austin } 996272b5eddSBrian Austin 997e48f7466SKuninori Morimoto snd_soc_component_update_bits(component, CS42L56_BEEP_FREQ_ONTIME, 998272b5eddSBrian Austin CS42L56_BEEP_FREQ_MASK, val); 999272b5eddSBrian Austin 1000272b5eddSBrian Austin snd_soc_dapm_sync(dapm); 1001272b5eddSBrian Austin } 1002272b5eddSBrian Austin 1003272b5eddSBrian Austin /* For usability define a way of injecting beep events for the device - 1004272b5eddSBrian Austin * many systems will not have a keyboard. 1005272b5eddSBrian Austin */ 1006272b5eddSBrian Austin static int cs42l56_beep_event(struct input_dev *dev, unsigned int type, 1007272b5eddSBrian Austin unsigned int code, int hz) 1008272b5eddSBrian Austin { 1009e48f7466SKuninori Morimoto struct snd_soc_component *component = input_get_drvdata(dev); 1010e48f7466SKuninori Morimoto struct cs42l56_private *cs42l56 = snd_soc_component_get_drvdata(component); 1011272b5eddSBrian Austin 1012e48f7466SKuninori Morimoto dev_dbg(component->dev, "Beep event %x %x\n", code, hz); 1013272b5eddSBrian Austin 1014272b5eddSBrian Austin switch (code) { 1015272b5eddSBrian Austin case SND_BELL: 1016272b5eddSBrian Austin if (hz) 1017272b5eddSBrian Austin hz = 261; 1018272b5eddSBrian Austin case SND_TONE: 1019272b5eddSBrian Austin break; 1020272b5eddSBrian Austin default: 1021272b5eddSBrian Austin return -1; 1022272b5eddSBrian Austin } 1023272b5eddSBrian Austin 1024272b5eddSBrian Austin /* Kick the beep from a workqueue */ 1025272b5eddSBrian Austin cs42l56->beep_rate = hz; 1026272b5eddSBrian Austin schedule_work(&cs42l56->beep_work); 1027272b5eddSBrian Austin return 0; 1028272b5eddSBrian Austin } 1029272b5eddSBrian Austin 1030272b5eddSBrian Austin static ssize_t cs42l56_beep_set(struct device *dev, 1031272b5eddSBrian Austin struct device_attribute *attr, 1032272b5eddSBrian Austin const char *buf, size_t count) 1033272b5eddSBrian Austin { 1034272b5eddSBrian Austin struct cs42l56_private *cs42l56 = dev_get_drvdata(dev); 1035272b5eddSBrian Austin long int time; 1036272b5eddSBrian Austin int ret; 1037272b5eddSBrian Austin 1038272b5eddSBrian Austin ret = kstrtol(buf, 10, &time); 1039272b5eddSBrian Austin if (ret != 0) 1040272b5eddSBrian Austin return ret; 1041272b5eddSBrian Austin 1042272b5eddSBrian Austin input_event(cs42l56->beep, EV_SND, SND_TONE, time); 1043272b5eddSBrian Austin 1044272b5eddSBrian Austin return count; 1045272b5eddSBrian Austin } 1046272b5eddSBrian Austin 1047272b5eddSBrian Austin static DEVICE_ATTR(beep, 0200, NULL, cs42l56_beep_set); 1048272b5eddSBrian Austin 1049e48f7466SKuninori Morimoto static void cs42l56_init_beep(struct snd_soc_component *component) 1050272b5eddSBrian Austin { 1051e48f7466SKuninori Morimoto struct cs42l56_private *cs42l56 = snd_soc_component_get_drvdata(component); 1052272b5eddSBrian Austin int ret; 1053272b5eddSBrian Austin 1054e48f7466SKuninori Morimoto cs42l56->beep = devm_input_allocate_device(component->dev); 1055272b5eddSBrian Austin if (!cs42l56->beep) { 1056e48f7466SKuninori Morimoto dev_err(component->dev, "Failed to allocate beep device\n"); 1057272b5eddSBrian Austin return; 1058272b5eddSBrian Austin } 1059272b5eddSBrian Austin 1060272b5eddSBrian Austin INIT_WORK(&cs42l56->beep_work, cs42l56_beep_work); 1061272b5eddSBrian Austin cs42l56->beep_rate = 0; 1062272b5eddSBrian Austin 1063272b5eddSBrian Austin cs42l56->beep->name = "CS42L56 Beep Generator"; 1064e48f7466SKuninori Morimoto cs42l56->beep->phys = dev_name(component->dev); 1065272b5eddSBrian Austin cs42l56->beep->id.bustype = BUS_I2C; 1066272b5eddSBrian Austin 1067272b5eddSBrian Austin cs42l56->beep->evbit[0] = BIT_MASK(EV_SND); 1068272b5eddSBrian Austin cs42l56->beep->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE); 1069272b5eddSBrian Austin cs42l56->beep->event = cs42l56_beep_event; 1070e48f7466SKuninori Morimoto cs42l56->beep->dev.parent = component->dev; 1071e48f7466SKuninori Morimoto input_set_drvdata(cs42l56->beep, component); 1072272b5eddSBrian Austin 1073272b5eddSBrian Austin ret = input_register_device(cs42l56->beep); 1074272b5eddSBrian Austin if (ret != 0) { 1075272b5eddSBrian Austin cs42l56->beep = NULL; 1076e48f7466SKuninori Morimoto dev_err(component->dev, "Failed to register beep device\n"); 1077272b5eddSBrian Austin } 1078272b5eddSBrian Austin 1079e48f7466SKuninori Morimoto ret = device_create_file(component->dev, &dev_attr_beep); 1080272b5eddSBrian Austin if (ret != 0) { 1081e48f7466SKuninori Morimoto dev_err(component->dev, "Failed to create keyclick file: %d\n", 1082272b5eddSBrian Austin ret); 1083272b5eddSBrian Austin } 1084272b5eddSBrian Austin } 1085272b5eddSBrian Austin 1086e48f7466SKuninori Morimoto static void cs42l56_free_beep(struct snd_soc_component *component) 1087272b5eddSBrian Austin { 1088e48f7466SKuninori Morimoto struct cs42l56_private *cs42l56 = snd_soc_component_get_drvdata(component); 1089272b5eddSBrian Austin 1090e48f7466SKuninori Morimoto device_remove_file(component->dev, &dev_attr_beep); 1091272b5eddSBrian Austin cancel_work_sync(&cs42l56->beep_work); 1092272b5eddSBrian Austin cs42l56->beep = NULL; 1093272b5eddSBrian Austin 1094e48f7466SKuninori Morimoto snd_soc_component_update_bits(component, CS42L56_BEEP_TONE_CFG, 1095272b5eddSBrian Austin CS42L56_BEEP_EN_MASK, 0); 1096272b5eddSBrian Austin } 1097272b5eddSBrian Austin 1098e48f7466SKuninori Morimoto static int cs42l56_probe(struct snd_soc_component *component) 1099272b5eddSBrian Austin { 1100e48f7466SKuninori Morimoto cs42l56_init_beep(component); 1101272b5eddSBrian Austin 1102272b5eddSBrian Austin return 0; 1103272b5eddSBrian Austin } 1104272b5eddSBrian Austin 1105e48f7466SKuninori Morimoto static void cs42l56_remove(struct snd_soc_component *component) 1106272b5eddSBrian Austin { 1107e48f7466SKuninori Morimoto cs42l56_free_beep(component); 1108272b5eddSBrian Austin } 1109272b5eddSBrian Austin 1110e48f7466SKuninori Morimoto static const struct snd_soc_component_driver soc_component_dev_cs42l56 = { 1111272b5eddSBrian Austin .probe = cs42l56_probe, 1112272b5eddSBrian Austin .remove = cs42l56_remove, 1113272b5eddSBrian Austin .set_bias_level = cs42l56_set_bias_level, 1114561828f8SKuninori Morimoto .controls = cs42l56_snd_controls, 1115561828f8SKuninori Morimoto .num_controls = ARRAY_SIZE(cs42l56_snd_controls), 1116272b5eddSBrian Austin .dapm_widgets = cs42l56_dapm_widgets, 1117272b5eddSBrian Austin .num_dapm_widgets = ARRAY_SIZE(cs42l56_dapm_widgets), 1118272b5eddSBrian Austin .dapm_routes = cs42l56_audio_map, 1119272b5eddSBrian Austin .num_dapm_routes = ARRAY_SIZE(cs42l56_audio_map), 1120e48f7466SKuninori Morimoto .suspend_bias_off = 1, 1121e48f7466SKuninori Morimoto .idle_bias_on = 1, 1122e48f7466SKuninori Morimoto .use_pmdown_time = 1, 1123e48f7466SKuninori Morimoto .endianness = 1, 1124e48f7466SKuninori Morimoto .non_legacy_dai_naming = 1, 1125272b5eddSBrian Austin }; 1126272b5eddSBrian Austin 1127cf0efa1cSKrzysztof Kozlowski static const struct regmap_config cs42l56_regmap = { 1128272b5eddSBrian Austin .reg_bits = 8, 1129272b5eddSBrian Austin .val_bits = 8, 1130272b5eddSBrian Austin 1131272b5eddSBrian Austin .max_register = CS42L56_MAX_REGISTER, 1132272b5eddSBrian Austin .reg_defaults = cs42l56_reg_defaults, 1133272b5eddSBrian Austin .num_reg_defaults = ARRAY_SIZE(cs42l56_reg_defaults), 1134272b5eddSBrian Austin .readable_reg = cs42l56_readable_register, 1135272b5eddSBrian Austin .volatile_reg = cs42l56_volatile_register, 1136272b5eddSBrian Austin .cache_type = REGCACHE_RBTREE, 1137272b5eddSBrian Austin }; 1138272b5eddSBrian Austin 1139272b5eddSBrian Austin static int cs42l56_handle_of_data(struct i2c_client *i2c_client, 1140272b5eddSBrian Austin struct cs42l56_platform_data *pdata) 1141272b5eddSBrian Austin { 1142272b5eddSBrian Austin struct device_node *np = i2c_client->dev.of_node; 1143272b5eddSBrian Austin u32 val32; 1144272b5eddSBrian Austin 1145272b5eddSBrian Austin if (of_property_read_bool(np, "cirrus,ain1a-reference-cfg")) 1146272b5eddSBrian Austin pdata->ain1a_ref_cfg = true; 1147272b5eddSBrian Austin 1148272b5eddSBrian Austin if (of_property_read_bool(np, "cirrus,ain2a-reference-cfg")) 1149272b5eddSBrian Austin pdata->ain2a_ref_cfg = true; 1150272b5eddSBrian Austin 1151272b5eddSBrian Austin if (of_property_read_bool(np, "cirrus,ain1b-reference-cfg")) 1152272b5eddSBrian Austin pdata->ain1b_ref_cfg = true; 1153272b5eddSBrian Austin 1154272b5eddSBrian Austin if (of_property_read_bool(np, "cirrus,ain2b-reference-cfg")) 1155272b5eddSBrian Austin pdata->ain2b_ref_cfg = true; 1156272b5eddSBrian Austin 1157272b5eddSBrian Austin if (of_property_read_u32(np, "cirrus,micbias-lvl", &val32) >= 0) 1158272b5eddSBrian Austin pdata->micbias_lvl = val32; 1159272b5eddSBrian Austin 1160272b5eddSBrian Austin if (of_property_read_u32(np, "cirrus,chgfreq-divisor", &val32) >= 0) 1161272b5eddSBrian Austin pdata->chgfreq = val32; 1162272b5eddSBrian Austin 1163272b5eddSBrian Austin if (of_property_read_u32(np, "cirrus,adaptive-pwr-cfg", &val32) >= 0) 1164272b5eddSBrian Austin pdata->adaptive_pwr = val32; 1165272b5eddSBrian Austin 1166272b5eddSBrian Austin if (of_property_read_u32(np, "cirrus,hpf-left-freq", &val32) >= 0) 1167272b5eddSBrian Austin pdata->hpfa_freq = val32; 1168272b5eddSBrian Austin 1169272b5eddSBrian Austin if (of_property_read_u32(np, "cirrus,hpf-left-freq", &val32) >= 0) 1170272b5eddSBrian Austin pdata->hpfb_freq = val32; 1171272b5eddSBrian Austin 1172272b5eddSBrian Austin pdata->gpio_nreset = of_get_named_gpio(np, "cirrus,gpio-nreset", 0); 1173272b5eddSBrian Austin 1174272b5eddSBrian Austin return 0; 1175272b5eddSBrian Austin } 1176272b5eddSBrian Austin 1177272b5eddSBrian Austin static int cs42l56_i2c_probe(struct i2c_client *i2c_client, 1178272b5eddSBrian Austin const struct i2c_device_id *id) 1179272b5eddSBrian Austin { 1180272b5eddSBrian Austin struct cs42l56_private *cs42l56; 1181272b5eddSBrian Austin struct cs42l56_platform_data *pdata = 1182272b5eddSBrian Austin dev_get_platdata(&i2c_client->dev); 1183272b5eddSBrian Austin int ret, i; 1184272b5eddSBrian Austin unsigned int devid = 0; 1185272b5eddSBrian Austin unsigned int alpha_rev, metal_rev; 1186272b5eddSBrian Austin unsigned int reg; 1187272b5eddSBrian Austin 1188e8d8b98cSMarkus Elfring cs42l56 = devm_kzalloc(&i2c_client->dev, sizeof(*cs42l56), GFP_KERNEL); 1189272b5eddSBrian Austin if (cs42l56 == NULL) 1190272b5eddSBrian Austin return -ENOMEM; 1191272b5eddSBrian Austin cs42l56->dev = &i2c_client->dev; 1192272b5eddSBrian Austin 1193272b5eddSBrian Austin cs42l56->regmap = devm_regmap_init_i2c(i2c_client, &cs42l56_regmap); 1194272b5eddSBrian Austin if (IS_ERR(cs42l56->regmap)) { 1195272b5eddSBrian Austin ret = PTR_ERR(cs42l56->regmap); 1196272b5eddSBrian Austin dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret); 1197272b5eddSBrian Austin return ret; 1198272b5eddSBrian Austin } 1199272b5eddSBrian Austin 1200272b5eddSBrian Austin if (pdata) { 1201272b5eddSBrian Austin cs42l56->pdata = *pdata; 1202272b5eddSBrian Austin } else { 1203e8d8b98cSMarkus Elfring pdata = devm_kzalloc(&i2c_client->dev, sizeof(*pdata), 1204272b5eddSBrian Austin GFP_KERNEL); 1205277631ccSMarkus Elfring if (!pdata) 1206272b5eddSBrian Austin return -ENOMEM; 1207277631ccSMarkus Elfring 1208272b5eddSBrian Austin if (i2c_client->dev.of_node) { 1209272b5eddSBrian Austin ret = cs42l56_handle_of_data(i2c_client, 1210272b5eddSBrian Austin &cs42l56->pdata); 1211272b5eddSBrian Austin if (ret != 0) 1212272b5eddSBrian Austin return ret; 1213272b5eddSBrian Austin } 1214272b5eddSBrian Austin cs42l56->pdata = *pdata; 1215272b5eddSBrian Austin } 1216272b5eddSBrian Austin 1217272b5eddSBrian Austin if (cs42l56->pdata.gpio_nreset) { 1218272b5eddSBrian Austin ret = gpio_request_one(cs42l56->pdata.gpio_nreset, 1219272b5eddSBrian Austin GPIOF_OUT_INIT_HIGH, "CS42L56 /RST"); 1220272b5eddSBrian Austin if (ret < 0) { 1221272b5eddSBrian Austin dev_err(&i2c_client->dev, 1222272b5eddSBrian Austin "Failed to request /RST %d: %d\n", 1223272b5eddSBrian Austin cs42l56->pdata.gpio_nreset, ret); 1224272b5eddSBrian Austin return ret; 1225272b5eddSBrian Austin } 1226272b5eddSBrian Austin gpio_set_value_cansleep(cs42l56->pdata.gpio_nreset, 0); 1227272b5eddSBrian Austin gpio_set_value_cansleep(cs42l56->pdata.gpio_nreset, 1); 1228272b5eddSBrian Austin } 1229272b5eddSBrian Austin 1230272b5eddSBrian Austin 1231272b5eddSBrian Austin i2c_set_clientdata(i2c_client, cs42l56); 1232272b5eddSBrian Austin 1233272b5eddSBrian Austin for (i = 0; i < ARRAY_SIZE(cs42l56->supplies); i++) 1234272b5eddSBrian Austin cs42l56->supplies[i].supply = cs42l56_supply_names[i]; 1235272b5eddSBrian Austin 1236272b5eddSBrian Austin ret = devm_regulator_bulk_get(&i2c_client->dev, 1237272b5eddSBrian Austin ARRAY_SIZE(cs42l56->supplies), 1238272b5eddSBrian Austin cs42l56->supplies); 1239272b5eddSBrian Austin if (ret != 0) { 1240272b5eddSBrian Austin dev_err(&i2c_client->dev, 1241272b5eddSBrian Austin "Failed to request supplies: %d\n", ret); 1242272b5eddSBrian Austin return ret; 1243272b5eddSBrian Austin } 1244272b5eddSBrian Austin 1245272b5eddSBrian Austin ret = regulator_bulk_enable(ARRAY_SIZE(cs42l56->supplies), 1246272b5eddSBrian Austin cs42l56->supplies); 1247272b5eddSBrian Austin if (ret != 0) { 1248272b5eddSBrian Austin dev_err(&i2c_client->dev, 1249272b5eddSBrian Austin "Failed to enable supplies: %d\n", ret); 1250272b5eddSBrian Austin return ret; 1251272b5eddSBrian Austin } 1252272b5eddSBrian Austin 1253272b5eddSBrian Austin ret = regmap_read(cs42l56->regmap, CS42L56_CHIP_ID_1, ®); 1254272b5eddSBrian Austin devid = reg & CS42L56_CHIP_ID_MASK; 1255272b5eddSBrian Austin if (devid != CS42L56_DEVID) { 1256272b5eddSBrian Austin dev_err(&i2c_client->dev, 1257272b5eddSBrian Austin "CS42L56 Device ID (%X). Expected %X\n", 1258272b5eddSBrian Austin devid, CS42L56_DEVID); 1259272b5eddSBrian Austin goto err_enable; 1260272b5eddSBrian Austin } 1261272b5eddSBrian Austin alpha_rev = reg & CS42L56_AREV_MASK; 1262272b5eddSBrian Austin metal_rev = reg & CS42L56_MTLREV_MASK; 1263272b5eddSBrian Austin 1264272b5eddSBrian Austin dev_info(&i2c_client->dev, "Cirrus Logic CS42L56 "); 1265272b5eddSBrian Austin dev_info(&i2c_client->dev, "Alpha Rev %X Metal Rev %X\n", 1266272b5eddSBrian Austin alpha_rev, metal_rev); 1267272b5eddSBrian Austin 1268272b5eddSBrian Austin if (cs42l56->pdata.ain1a_ref_cfg) 1269272b5eddSBrian Austin regmap_update_bits(cs42l56->regmap, CS42L56_AIN_REFCFG_ADC_MUX, 12708c317fafSFlorian Vaussard CS42L56_AIN1A_REF_MASK, 12718c317fafSFlorian Vaussard CS42L56_AIN1A_REF_MASK); 1272272b5eddSBrian Austin 1273272b5eddSBrian Austin if (cs42l56->pdata.ain1b_ref_cfg) 1274272b5eddSBrian Austin regmap_update_bits(cs42l56->regmap, CS42L56_AIN_REFCFG_ADC_MUX, 12758c317fafSFlorian Vaussard CS42L56_AIN1B_REF_MASK, 12768c317fafSFlorian Vaussard CS42L56_AIN1B_REF_MASK); 1277272b5eddSBrian Austin 1278272b5eddSBrian Austin if (cs42l56->pdata.ain2a_ref_cfg) 1279272b5eddSBrian Austin regmap_update_bits(cs42l56->regmap, CS42L56_AIN_REFCFG_ADC_MUX, 12808c317fafSFlorian Vaussard CS42L56_AIN2A_REF_MASK, 12818c317fafSFlorian Vaussard CS42L56_AIN2A_REF_MASK); 1282272b5eddSBrian Austin 1283272b5eddSBrian Austin if (cs42l56->pdata.ain2b_ref_cfg) 1284272b5eddSBrian Austin regmap_update_bits(cs42l56->regmap, CS42L56_AIN_REFCFG_ADC_MUX, 12858c317fafSFlorian Vaussard CS42L56_AIN2B_REF_MASK, 12868c317fafSFlorian Vaussard CS42L56_AIN2B_REF_MASK); 1287272b5eddSBrian Austin 1288272b5eddSBrian Austin if (cs42l56->pdata.micbias_lvl) 1289272b5eddSBrian Austin regmap_update_bits(cs42l56->regmap, CS42L56_GAIN_BIAS_CTL, 1290272b5eddSBrian Austin CS42L56_MIC_BIAS_MASK, 1291272b5eddSBrian Austin cs42l56->pdata.micbias_lvl); 1292272b5eddSBrian Austin 1293272b5eddSBrian Austin if (cs42l56->pdata.chgfreq) 1294272b5eddSBrian Austin regmap_update_bits(cs42l56->regmap, CS42L56_CLASSH_CTL, 1295272b5eddSBrian Austin CS42L56_CHRG_FREQ_MASK, 1296272b5eddSBrian Austin cs42l56->pdata.chgfreq); 1297272b5eddSBrian Austin 1298272b5eddSBrian Austin if (cs42l56->pdata.hpfb_freq) 1299272b5eddSBrian Austin regmap_update_bits(cs42l56->regmap, CS42L56_HPF_CTL, 1300272b5eddSBrian Austin CS42L56_HPFB_FREQ_MASK, 1301272b5eddSBrian Austin cs42l56->pdata.hpfb_freq); 1302272b5eddSBrian Austin 1303272b5eddSBrian Austin if (cs42l56->pdata.hpfa_freq) 1304272b5eddSBrian Austin regmap_update_bits(cs42l56->regmap, CS42L56_HPF_CTL, 1305272b5eddSBrian Austin CS42L56_HPFA_FREQ_MASK, 1306272b5eddSBrian Austin cs42l56->pdata.hpfa_freq); 1307272b5eddSBrian Austin 1308272b5eddSBrian Austin if (cs42l56->pdata.adaptive_pwr) 1309272b5eddSBrian Austin regmap_update_bits(cs42l56->regmap, CS42L56_CLASSH_CTL, 1310272b5eddSBrian Austin CS42L56_ADAPT_PWR_MASK, 1311272b5eddSBrian Austin cs42l56->pdata.adaptive_pwr); 1312272b5eddSBrian Austin 1313e48f7466SKuninori Morimoto ret = devm_snd_soc_register_component(&i2c_client->dev, 1314e48f7466SKuninori Morimoto &soc_component_dev_cs42l56, &cs42l56_dai, 1); 1315272b5eddSBrian Austin if (ret < 0) 1316272b5eddSBrian Austin return ret; 1317272b5eddSBrian Austin 1318272b5eddSBrian Austin return 0; 1319272b5eddSBrian Austin 1320272b5eddSBrian Austin err_enable: 1321272b5eddSBrian Austin regulator_bulk_disable(ARRAY_SIZE(cs42l56->supplies), 1322272b5eddSBrian Austin cs42l56->supplies); 1323272b5eddSBrian Austin return ret; 1324272b5eddSBrian Austin } 1325272b5eddSBrian Austin 1326272b5eddSBrian Austin static int cs42l56_i2c_remove(struct i2c_client *client) 1327272b5eddSBrian Austin { 1328272b5eddSBrian Austin struct cs42l56_private *cs42l56 = i2c_get_clientdata(client); 1329272b5eddSBrian Austin 1330272b5eddSBrian Austin regulator_bulk_disable(ARRAY_SIZE(cs42l56->supplies), 1331272b5eddSBrian Austin cs42l56->supplies); 1332272b5eddSBrian Austin return 0; 1333272b5eddSBrian Austin } 1334272b5eddSBrian Austin 1335272b5eddSBrian Austin static const struct of_device_id cs42l56_of_match[] = { 1336272b5eddSBrian Austin { .compatible = "cirrus,cs42l56", }, 1337272b5eddSBrian Austin { } 1338272b5eddSBrian Austin }; 1339272b5eddSBrian Austin MODULE_DEVICE_TABLE(of, cs42l56_of_match); 1340272b5eddSBrian Austin 1341272b5eddSBrian Austin 1342272b5eddSBrian Austin static const struct i2c_device_id cs42l56_id[] = { 1343272b5eddSBrian Austin { "cs42l56", 0 }, 1344272b5eddSBrian Austin { } 1345272b5eddSBrian Austin }; 1346272b5eddSBrian Austin MODULE_DEVICE_TABLE(i2c, cs42l56_id); 1347272b5eddSBrian Austin 1348272b5eddSBrian Austin static struct i2c_driver cs42l56_i2c_driver = { 1349272b5eddSBrian Austin .driver = { 1350272b5eddSBrian Austin .name = "cs42l56", 1351272b5eddSBrian Austin .of_match_table = cs42l56_of_match, 1352272b5eddSBrian Austin }, 1353272b5eddSBrian Austin .id_table = cs42l56_id, 1354272b5eddSBrian Austin .probe = cs42l56_i2c_probe, 1355272b5eddSBrian Austin .remove = cs42l56_i2c_remove, 1356272b5eddSBrian Austin }; 1357272b5eddSBrian Austin 1358272b5eddSBrian Austin module_i2c_driver(cs42l56_i2c_driver); 1359272b5eddSBrian Austin 1360272b5eddSBrian Austin MODULE_DESCRIPTION("ASoC CS42L56 driver"); 1361272b5eddSBrian Austin MODULE_AUTHOR("Brian Austin, Cirrus Logic Inc, <brian.austin@cirrus.com>"); 1362272b5eddSBrian Austin MODULE_LICENSE("GPL"); 1363