162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * cs42l52.c -- CS42L52 ALSA SoC audio driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright 2012 CirrusLogic, Inc. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Author: Georgi Vlaev <joe@nucleusys.com> 862306a36Sopenharmony_ci * Author: Brian Austin <brian.austin@cirrus.com> 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/module.h> 1262306a36Sopenharmony_ci#include <linux/moduleparam.h> 1362306a36Sopenharmony_ci#include <linux/kernel.h> 1462306a36Sopenharmony_ci#include <linux/init.h> 1562306a36Sopenharmony_ci#include <linux/delay.h> 1662306a36Sopenharmony_ci#include <linux/of_gpio.h> 1762306a36Sopenharmony_ci#include <linux/pm.h> 1862306a36Sopenharmony_ci#include <linux/i2c.h> 1962306a36Sopenharmony_ci#include <linux/input.h> 2062306a36Sopenharmony_ci#include <linux/regmap.h> 2162306a36Sopenharmony_ci#include <linux/slab.h> 2262306a36Sopenharmony_ci#include <linux/workqueue.h> 2362306a36Sopenharmony_ci#include <linux/platform_device.h> 2462306a36Sopenharmony_ci#include <sound/core.h> 2562306a36Sopenharmony_ci#include <sound/pcm.h> 2662306a36Sopenharmony_ci#include <sound/pcm_params.h> 2762306a36Sopenharmony_ci#include <sound/soc.h> 2862306a36Sopenharmony_ci#include <sound/soc-dapm.h> 2962306a36Sopenharmony_ci#include <sound/initval.h> 3062306a36Sopenharmony_ci#include <sound/tlv.h> 3162306a36Sopenharmony_ci#include <sound/cs42l52.h> 3262306a36Sopenharmony_ci#include "cs42l52.h" 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_cistruct sp_config { 3562306a36Sopenharmony_ci u8 spc, format, spfs; 3662306a36Sopenharmony_ci u32 srate; 3762306a36Sopenharmony_ci}; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_cistruct cs42l52_private { 4062306a36Sopenharmony_ci struct regmap *regmap; 4162306a36Sopenharmony_ci struct snd_soc_component *component; 4262306a36Sopenharmony_ci struct device *dev; 4362306a36Sopenharmony_ci struct sp_config config; 4462306a36Sopenharmony_ci struct cs42l52_platform_data pdata; 4562306a36Sopenharmony_ci u32 sysclk; 4662306a36Sopenharmony_ci u8 mclksel; 4762306a36Sopenharmony_ci u32 mclk; 4862306a36Sopenharmony_ci u8 flags; 4962306a36Sopenharmony_ci struct input_dev *beep; 5062306a36Sopenharmony_ci struct work_struct beep_work; 5162306a36Sopenharmony_ci int beep_rate; 5262306a36Sopenharmony_ci}; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_cistatic const struct reg_default cs42l52_reg_defaults[] = { 5562306a36Sopenharmony_ci { CS42L52_PWRCTL1, 0x9F }, /* r02 PWRCTL 1 */ 5662306a36Sopenharmony_ci { CS42L52_PWRCTL2, 0x07 }, /* r03 PWRCTL 2 */ 5762306a36Sopenharmony_ci { CS42L52_PWRCTL3, 0xFF }, /* r04 PWRCTL 3 */ 5862306a36Sopenharmony_ci { CS42L52_CLK_CTL, 0xA0 }, /* r05 Clocking Ctl */ 5962306a36Sopenharmony_ci { CS42L52_IFACE_CTL1, 0x00 }, /* r06 Interface Ctl 1 */ 6062306a36Sopenharmony_ci { CS42L52_ADC_PGA_A, 0x80 }, /* r08 Input A Select */ 6162306a36Sopenharmony_ci { CS42L52_ADC_PGA_B, 0x80 }, /* r09 Input B Select */ 6262306a36Sopenharmony_ci { CS42L52_ANALOG_HPF_CTL, 0xA5 }, /* r0A Analog HPF Ctl */ 6362306a36Sopenharmony_ci { CS42L52_ADC_HPF_FREQ, 0x00 }, /* r0B ADC HPF Corner Freq */ 6462306a36Sopenharmony_ci { CS42L52_ADC_MISC_CTL, 0x00 }, /* r0C Misc. ADC Ctl */ 6562306a36Sopenharmony_ci { CS42L52_PB_CTL1, 0x60 }, /* r0D Playback Ctl 1 */ 6662306a36Sopenharmony_ci { CS42L52_MISC_CTL, 0x02 }, /* r0E Misc. Ctl */ 6762306a36Sopenharmony_ci { CS42L52_PB_CTL2, 0x00 }, /* r0F Playback Ctl 2 */ 6862306a36Sopenharmony_ci { CS42L52_MICA_CTL, 0x00 }, /* r10 MICA Amp Ctl */ 6962306a36Sopenharmony_ci { CS42L52_MICB_CTL, 0x00 }, /* r11 MICB Amp Ctl */ 7062306a36Sopenharmony_ci { CS42L52_PGAA_CTL, 0x00 }, /* r12 PGAA Vol, Misc. */ 7162306a36Sopenharmony_ci { CS42L52_PGAB_CTL, 0x00 }, /* r13 PGAB Vol, Misc. */ 7262306a36Sopenharmony_ci { CS42L52_PASSTHRUA_VOL, 0x00 }, /* r14 Bypass A Vol */ 7362306a36Sopenharmony_ci { CS42L52_PASSTHRUB_VOL, 0x00 }, /* r15 Bypass B Vol */ 7462306a36Sopenharmony_ci { CS42L52_ADCA_VOL, 0x00 }, /* r16 ADCA Volume */ 7562306a36Sopenharmony_ci { CS42L52_ADCB_VOL, 0x00 }, /* r17 ADCB Volume */ 7662306a36Sopenharmony_ci { CS42L52_ADCA_MIXER_VOL, 0x80 }, /* r18 ADCA Mixer Volume */ 7762306a36Sopenharmony_ci { CS42L52_ADCB_MIXER_VOL, 0x80 }, /* r19 ADCB Mixer Volume */ 7862306a36Sopenharmony_ci { CS42L52_PCMA_MIXER_VOL, 0x00 }, /* r1A PCMA Mixer Volume */ 7962306a36Sopenharmony_ci { CS42L52_PCMB_MIXER_VOL, 0x00 }, /* r1B PCMB Mixer Volume */ 8062306a36Sopenharmony_ci { CS42L52_BEEP_FREQ, 0x00 }, /* r1C Beep Freq on Time */ 8162306a36Sopenharmony_ci { CS42L52_BEEP_VOL, 0x00 }, /* r1D Beep Volume off Time */ 8262306a36Sopenharmony_ci { CS42L52_BEEP_TONE_CTL, 0x00 }, /* r1E Beep Tone Cfg. */ 8362306a36Sopenharmony_ci { CS42L52_TONE_CTL, 0x00 }, /* r1F Tone Ctl */ 8462306a36Sopenharmony_ci { CS42L52_MASTERA_VOL, 0x00 }, /* r20 Master A Volume */ 8562306a36Sopenharmony_ci { CS42L52_MASTERB_VOL, 0x00 }, /* r21 Master B Volume */ 8662306a36Sopenharmony_ci { CS42L52_HPA_VOL, 0x00 }, /* r22 Headphone A Volume */ 8762306a36Sopenharmony_ci { CS42L52_HPB_VOL, 0x00 }, /* r23 Headphone B Volume */ 8862306a36Sopenharmony_ci { CS42L52_SPKA_VOL, 0x00 }, /* r24 Speaker A Volume */ 8962306a36Sopenharmony_ci { CS42L52_SPKB_VOL, 0x00 }, /* r25 Speaker B Volume */ 9062306a36Sopenharmony_ci { CS42L52_ADC_PCM_MIXER, 0x00 }, /* r26 Channel Mixer and Swap */ 9162306a36Sopenharmony_ci { CS42L52_LIMITER_CTL1, 0x00 }, /* r27 Limit Ctl 1 Thresholds */ 9262306a36Sopenharmony_ci { CS42L52_LIMITER_CTL2, 0x7F }, /* r28 Limit Ctl 2 Release Rate */ 9362306a36Sopenharmony_ci { CS42L52_LIMITER_AT_RATE, 0xC0 }, /* r29 Limiter Attack Rate */ 9462306a36Sopenharmony_ci { CS42L52_ALC_CTL, 0x00 }, /* r2A ALC Ctl 1 Attack Rate */ 9562306a36Sopenharmony_ci { CS42L52_ALC_RATE, 0x3F }, /* r2B ALC Release Rate */ 9662306a36Sopenharmony_ci { CS42L52_ALC_THRESHOLD, 0x3f }, /* r2C ALC Thresholds */ 9762306a36Sopenharmony_ci { CS42L52_NOISE_GATE_CTL, 0x00 }, /* r2D Noise Gate Ctl */ 9862306a36Sopenharmony_ci { CS42L52_CLK_STATUS, 0x00 }, /* r2E Overflow and Clock Status */ 9962306a36Sopenharmony_ci { CS42L52_BATT_COMPEN, 0x00 }, /* r2F battery Compensation */ 10062306a36Sopenharmony_ci { CS42L52_BATT_LEVEL, 0x00 }, /* r30 VP Battery Level */ 10162306a36Sopenharmony_ci { CS42L52_SPK_STATUS, 0x00 }, /* r31 Speaker Status */ 10262306a36Sopenharmony_ci { CS42L52_TEM_CTL, 0x3B }, /* r32 Temp Ctl */ 10362306a36Sopenharmony_ci { CS42L52_THE_FOLDBACK, 0x00 }, /* r33 Foldback */ 10462306a36Sopenharmony_ci}; 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_cistatic bool cs42l52_readable_register(struct device *dev, unsigned int reg) 10762306a36Sopenharmony_ci{ 10862306a36Sopenharmony_ci switch (reg) { 10962306a36Sopenharmony_ci case CS42L52_CHIP ... CS42L52_CHARGE_PUMP: 11062306a36Sopenharmony_ci return true; 11162306a36Sopenharmony_ci default: 11262306a36Sopenharmony_ci return false; 11362306a36Sopenharmony_ci } 11462306a36Sopenharmony_ci} 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_cistatic bool cs42l52_volatile_register(struct device *dev, unsigned int reg) 11762306a36Sopenharmony_ci{ 11862306a36Sopenharmony_ci switch (reg) { 11962306a36Sopenharmony_ci case CS42L52_IFACE_CTL2: 12062306a36Sopenharmony_ci case CS42L52_CLK_STATUS: 12162306a36Sopenharmony_ci case CS42L52_BATT_LEVEL: 12262306a36Sopenharmony_ci case CS42L52_SPK_STATUS: 12362306a36Sopenharmony_ci case CS42L52_CHARGE_PUMP: 12462306a36Sopenharmony_ci return true; 12562306a36Sopenharmony_ci default: 12662306a36Sopenharmony_ci return false; 12762306a36Sopenharmony_ci } 12862306a36Sopenharmony_ci} 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_cistatic DECLARE_TLV_DB_SCALE(hl_tlv, -10200, 50, 0); 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_cistatic DECLARE_TLV_DB_SCALE(hpd_tlv, -9600, 50, 1); 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_cistatic DECLARE_TLV_DB_SCALE(ipd_tlv, -9600, 100, 0); 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_cistatic DECLARE_TLV_DB_SCALE(mic_tlv, 1600, 100, 0); 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_cistatic DECLARE_TLV_DB_SCALE(pga_tlv, -600, 50, 0); 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_cistatic DECLARE_TLV_DB_SCALE(pass_tlv, -6000, 50, 0); 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_cistatic DECLARE_TLV_DB_SCALE(mix_tlv, -5150, 50, 0); 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_cistatic DECLARE_TLV_DB_SCALE(beep_tlv, -56, 200, 0); 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_cistatic const DECLARE_TLV_DB_RANGE(limiter_tlv, 14762306a36Sopenharmony_ci 0, 2, TLV_DB_SCALE_ITEM(-3000, 600, 0), 14862306a36Sopenharmony_ci 3, 7, TLV_DB_SCALE_ITEM(-1200, 300, 0) 14962306a36Sopenharmony_ci); 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_cistatic const char * const cs42l52_adca_text[] = { 15262306a36Sopenharmony_ci "Input1A", "Input2A", "Input3A", "Input4A", "PGA Input Left"}; 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_cistatic const char * const cs42l52_adcb_text[] = { 15562306a36Sopenharmony_ci "Input1B", "Input2B", "Input3B", "Input4B", "PGA Input Right"}; 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(adca_enum, 15862306a36Sopenharmony_ci CS42L52_ADC_PGA_A, 5, cs42l52_adca_text); 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(adcb_enum, 16162306a36Sopenharmony_ci CS42L52_ADC_PGA_B, 5, cs42l52_adcb_text); 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_cistatic const struct snd_kcontrol_new adca_mux = 16462306a36Sopenharmony_ci SOC_DAPM_ENUM("Left ADC Input Capture Mux", adca_enum); 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_cistatic const struct snd_kcontrol_new adcb_mux = 16762306a36Sopenharmony_ci SOC_DAPM_ENUM("Right ADC Input Capture Mux", adcb_enum); 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_cistatic const char * const mic_bias_level_text[] = { 17062306a36Sopenharmony_ci "0.5 +VA", "0.6 +VA", "0.7 +VA", 17162306a36Sopenharmony_ci "0.8 +VA", "0.83 +VA", "0.91 +VA" 17262306a36Sopenharmony_ci}; 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(mic_bias_level_enum, 17562306a36Sopenharmony_ci CS42L52_IFACE_CTL2, 0, mic_bias_level_text); 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_cistatic const char * const cs42l52_mic_text[] = { "MIC1", "MIC2" }; 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(mica_enum, 18062306a36Sopenharmony_ci CS42L52_MICA_CTL, 5, cs42l52_mic_text); 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(micb_enum, 18362306a36Sopenharmony_ci CS42L52_MICB_CTL, 5, cs42l52_mic_text); 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_cistatic const char * const digital_output_mux_text[] = {"ADC", "DSP"}; 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(digital_output_mux_enum, 18862306a36Sopenharmony_ci CS42L52_ADC_MISC_CTL, 6, 18962306a36Sopenharmony_ci digital_output_mux_text); 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_cistatic const struct snd_kcontrol_new digital_output_mux = 19262306a36Sopenharmony_ci SOC_DAPM_ENUM("Digital Output Mux", digital_output_mux_enum); 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_cistatic const char * const hp_gain_num_text[] = { 19562306a36Sopenharmony_ci "0.3959", "0.4571", "0.5111", "0.6047", 19662306a36Sopenharmony_ci "0.7099", "0.8399", "1.000", "1.1430" 19762306a36Sopenharmony_ci}; 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(hp_gain_enum, 20062306a36Sopenharmony_ci CS42L52_PB_CTL1, 5, 20162306a36Sopenharmony_ci hp_gain_num_text); 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_cistatic const char * const beep_pitch_text[] = { 20462306a36Sopenharmony_ci "C4", "C5", "D5", "E5", "F5", "G5", "A5", "B5", 20562306a36Sopenharmony_ci "C6", "D6", "E6", "F6", "G6", "A6", "B6", "C7" 20662306a36Sopenharmony_ci}; 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(beep_pitch_enum, 20962306a36Sopenharmony_ci CS42L52_BEEP_FREQ, 4, 21062306a36Sopenharmony_ci beep_pitch_text); 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_cistatic const char * const beep_ontime_text[] = { 21362306a36Sopenharmony_ci "86 ms", "430 ms", "780 ms", "1.20 s", "1.50 s", 21462306a36Sopenharmony_ci "1.80 s", "2.20 s", "2.50 s", "2.80 s", "3.20 s", 21562306a36Sopenharmony_ci "3.50 s", "3.80 s", "4.20 s", "4.50 s", "4.80 s", "5.20 s" 21662306a36Sopenharmony_ci}; 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(beep_ontime_enum, 21962306a36Sopenharmony_ci CS42L52_BEEP_FREQ, 0, 22062306a36Sopenharmony_ci beep_ontime_text); 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_cistatic const char * const beep_offtime_text[] = { 22362306a36Sopenharmony_ci "1.23 s", "2.58 s", "3.90 s", "5.20 s", 22462306a36Sopenharmony_ci "6.60 s", "8.05 s", "9.35 s", "10.80 s" 22562306a36Sopenharmony_ci}; 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(beep_offtime_enum, 22862306a36Sopenharmony_ci CS42L52_BEEP_VOL, 5, 22962306a36Sopenharmony_ci beep_offtime_text); 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_cistatic const char * const beep_config_text[] = { 23262306a36Sopenharmony_ci "Off", "Single", "Multiple", "Continuous" 23362306a36Sopenharmony_ci}; 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(beep_config_enum, 23662306a36Sopenharmony_ci CS42L52_BEEP_TONE_CTL, 6, 23762306a36Sopenharmony_ci beep_config_text); 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_cistatic const char * const beep_bass_text[] = { 24062306a36Sopenharmony_ci "50 Hz", "100 Hz", "200 Hz", "250 Hz" 24162306a36Sopenharmony_ci}; 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(beep_bass_enum, 24462306a36Sopenharmony_ci CS42L52_BEEP_TONE_CTL, 1, 24562306a36Sopenharmony_ci beep_bass_text); 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_cistatic const char * const beep_treble_text[] = { 24862306a36Sopenharmony_ci "5 kHz", "7 kHz", "10 kHz", " 15 kHz" 24962306a36Sopenharmony_ci}; 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(beep_treble_enum, 25262306a36Sopenharmony_ci CS42L52_BEEP_TONE_CTL, 3, 25362306a36Sopenharmony_ci beep_treble_text); 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_cistatic const char * const ng_threshold_text[] = { 25662306a36Sopenharmony_ci "-34dB", "-37dB", "-40dB", "-43dB", 25762306a36Sopenharmony_ci "-46dB", "-52dB", "-58dB", "-64dB" 25862306a36Sopenharmony_ci}; 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(ng_threshold_enum, 26162306a36Sopenharmony_ci CS42L52_NOISE_GATE_CTL, 2, 26262306a36Sopenharmony_ci ng_threshold_text); 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_cistatic const char * const cs42l52_ng_delay_text[] = { 26562306a36Sopenharmony_ci "50ms", "100ms", "150ms", "200ms"}; 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(ng_delay_enum, 26862306a36Sopenharmony_ci CS42L52_NOISE_GATE_CTL, 0, 26962306a36Sopenharmony_ci cs42l52_ng_delay_text); 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_cistatic const char * const cs42l52_ng_type_text[] = { 27262306a36Sopenharmony_ci "Apply Specific", "Apply All" 27362306a36Sopenharmony_ci}; 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(ng_type_enum, 27662306a36Sopenharmony_ci CS42L52_NOISE_GATE_CTL, 6, 27762306a36Sopenharmony_ci cs42l52_ng_type_text); 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_cistatic const char * const left_swap_text[] = { 28062306a36Sopenharmony_ci "Left", "LR 2", "Right"}; 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_cistatic const char * const right_swap_text[] = { 28362306a36Sopenharmony_ci "Right", "LR 2", "Left"}; 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_cistatic const unsigned int swap_values[] = { 0, 1, 3 }; 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_cistatic const struct soc_enum adca_swap_enum = 28862306a36Sopenharmony_ci SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 2, 3, 28962306a36Sopenharmony_ci ARRAY_SIZE(left_swap_text), 29062306a36Sopenharmony_ci left_swap_text, 29162306a36Sopenharmony_ci swap_values); 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_cistatic const struct snd_kcontrol_new adca_mixer = 29462306a36Sopenharmony_ci SOC_DAPM_ENUM("Route", adca_swap_enum); 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_cistatic const struct soc_enum pcma_swap_enum = 29762306a36Sopenharmony_ci SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 6, 3, 29862306a36Sopenharmony_ci ARRAY_SIZE(left_swap_text), 29962306a36Sopenharmony_ci left_swap_text, 30062306a36Sopenharmony_ci swap_values); 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_cistatic const struct snd_kcontrol_new pcma_mixer = 30362306a36Sopenharmony_ci SOC_DAPM_ENUM("Route", pcma_swap_enum); 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_cistatic const struct soc_enum adcb_swap_enum = 30662306a36Sopenharmony_ci SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 0, 3, 30762306a36Sopenharmony_ci ARRAY_SIZE(right_swap_text), 30862306a36Sopenharmony_ci right_swap_text, 30962306a36Sopenharmony_ci swap_values); 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_cistatic const struct snd_kcontrol_new adcb_mixer = 31262306a36Sopenharmony_ci SOC_DAPM_ENUM("Route", adcb_swap_enum); 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_cistatic const struct soc_enum pcmb_swap_enum = 31562306a36Sopenharmony_ci SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 4, 3, 31662306a36Sopenharmony_ci ARRAY_SIZE(right_swap_text), 31762306a36Sopenharmony_ci right_swap_text, 31862306a36Sopenharmony_ci swap_values); 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_cistatic const struct snd_kcontrol_new pcmb_mixer = 32162306a36Sopenharmony_ci SOC_DAPM_ENUM("Route", pcmb_swap_enum); 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_cistatic const struct snd_kcontrol_new passthrul_ctl = 32562306a36Sopenharmony_ci SOC_DAPM_SINGLE("Switch", CS42L52_MISC_CTL, 6, 1, 0); 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_cistatic const struct snd_kcontrol_new passthrur_ctl = 32862306a36Sopenharmony_ci SOC_DAPM_SINGLE("Switch", CS42L52_MISC_CTL, 7, 1, 0); 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_cistatic const struct snd_kcontrol_new spkl_ctl = 33162306a36Sopenharmony_ci SOC_DAPM_SINGLE("Switch", CS42L52_PWRCTL3, 0, 1, 1); 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_cistatic const struct snd_kcontrol_new spkr_ctl = 33462306a36Sopenharmony_ci SOC_DAPM_SINGLE("Switch", CS42L52_PWRCTL3, 2, 1, 1); 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_cistatic const struct snd_kcontrol_new hpl_ctl = 33762306a36Sopenharmony_ci SOC_DAPM_SINGLE("Switch", CS42L52_PWRCTL3, 4, 1, 1); 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_cistatic const struct snd_kcontrol_new hpr_ctl = 34062306a36Sopenharmony_ci SOC_DAPM_SINGLE("Switch", CS42L52_PWRCTL3, 6, 1, 1); 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_cistatic const struct snd_kcontrol_new cs42l52_snd_controls[] = { 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci SOC_DOUBLE_R_SX_TLV("Master Volume", CS42L52_MASTERA_VOL, 34562306a36Sopenharmony_ci CS42L52_MASTERB_VOL, 0, 0x34, 0xE4, hl_tlv), 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci SOC_DOUBLE_R_SX_TLV("Headphone Volume", CS42L52_HPA_VOL, 34862306a36Sopenharmony_ci CS42L52_HPB_VOL, 0, 0x34, 0xC0, hpd_tlv), 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci SOC_ENUM("Headphone Analog Gain", hp_gain_enum), 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci SOC_DOUBLE_R_SX_TLV("Speaker Volume", CS42L52_SPKA_VOL, 35362306a36Sopenharmony_ci CS42L52_SPKB_VOL, 0, 0x40, 0xC0, hl_tlv), 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci SOC_DOUBLE_R_SX_TLV("Bypass Volume", CS42L52_PASSTHRUA_VOL, 35662306a36Sopenharmony_ci CS42L52_PASSTHRUB_VOL, 0, 0x88, 0x90, pass_tlv), 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci SOC_DOUBLE("Bypass Mute", CS42L52_MISC_CTL, 4, 5, 1, 0), 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci SOC_DOUBLE_R_TLV("MIC Gain Volume", CS42L52_MICA_CTL, 36162306a36Sopenharmony_ci CS42L52_MICB_CTL, 0, 0x10, 0, mic_tlv), 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci SOC_ENUM("MIC Bias Level", mic_bias_level_enum), 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci SOC_DOUBLE_R_SX_TLV("ADC Volume", CS42L52_ADCA_VOL, 36662306a36Sopenharmony_ci CS42L52_ADCB_VOL, 0, 0xA0, 0x78, ipd_tlv), 36762306a36Sopenharmony_ci SOC_DOUBLE_R_SX_TLV("ADC Mixer Volume", 36862306a36Sopenharmony_ci CS42L52_ADCA_MIXER_VOL, CS42L52_ADCB_MIXER_VOL, 36962306a36Sopenharmony_ci 0, 0x19, 0x7F, mix_tlv), 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci SOC_DOUBLE("ADC Switch", CS42L52_ADC_MISC_CTL, 0, 1, 1, 0), 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci SOC_DOUBLE_R("ADC Mixer Switch", CS42L52_ADCA_MIXER_VOL, 37462306a36Sopenharmony_ci CS42L52_ADCB_MIXER_VOL, 7, 1, 1), 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci SOC_DOUBLE_R_SX_TLV("PGA Volume", CS42L52_PGAA_CTL, 37762306a36Sopenharmony_ci CS42L52_PGAB_CTL, 0, 0x28, 0x24, pga_tlv), 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci SOC_DOUBLE_R_SX_TLV("PCM Mixer Volume", 38062306a36Sopenharmony_ci CS42L52_PCMA_MIXER_VOL, CS42L52_PCMB_MIXER_VOL, 38162306a36Sopenharmony_ci 0, 0x19, 0x7f, mix_tlv), 38262306a36Sopenharmony_ci SOC_DOUBLE_R("PCM Mixer Switch", 38362306a36Sopenharmony_ci CS42L52_PCMA_MIXER_VOL, CS42L52_PCMB_MIXER_VOL, 7, 1, 1), 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci SOC_ENUM("Beep Config", beep_config_enum), 38662306a36Sopenharmony_ci SOC_ENUM("Beep Pitch", beep_pitch_enum), 38762306a36Sopenharmony_ci SOC_ENUM("Beep on Time", beep_ontime_enum), 38862306a36Sopenharmony_ci SOC_ENUM("Beep off Time", beep_offtime_enum), 38962306a36Sopenharmony_ci SOC_SINGLE_SX_TLV("Beep Volume", CS42L52_BEEP_VOL, 39062306a36Sopenharmony_ci 0, 0x07, 0x1f, beep_tlv), 39162306a36Sopenharmony_ci SOC_SINGLE("Beep Mixer Switch", CS42L52_BEEP_TONE_CTL, 5, 1, 1), 39262306a36Sopenharmony_ci SOC_ENUM("Beep Treble Corner Freq", beep_treble_enum), 39362306a36Sopenharmony_ci SOC_ENUM("Beep Bass Corner Freq", beep_bass_enum), 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci SOC_SINGLE("Tone Control Switch", CS42L52_BEEP_TONE_CTL, 0, 1, 1), 39662306a36Sopenharmony_ci SOC_SINGLE_TLV("Treble Gain Volume", 39762306a36Sopenharmony_ci CS42L52_TONE_CTL, 4, 15, 1, hl_tlv), 39862306a36Sopenharmony_ci SOC_SINGLE_TLV("Bass Gain Volume", 39962306a36Sopenharmony_ci CS42L52_TONE_CTL, 0, 15, 1, hl_tlv), 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci /* Limiter */ 40262306a36Sopenharmony_ci SOC_SINGLE_TLV("Limiter Max Threshold Volume", 40362306a36Sopenharmony_ci CS42L52_LIMITER_CTL1, 5, 7, 0, limiter_tlv), 40462306a36Sopenharmony_ci SOC_SINGLE_TLV("Limiter Cushion Threshold Volume", 40562306a36Sopenharmony_ci CS42L52_LIMITER_CTL1, 2, 7, 0, limiter_tlv), 40662306a36Sopenharmony_ci SOC_SINGLE_TLV("Limiter Release Rate Volume", 40762306a36Sopenharmony_ci CS42L52_LIMITER_CTL2, 0, 63, 0, limiter_tlv), 40862306a36Sopenharmony_ci SOC_SINGLE_TLV("Limiter Attack Rate Volume", 40962306a36Sopenharmony_ci CS42L52_LIMITER_AT_RATE, 0, 63, 0, limiter_tlv), 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci SOC_SINGLE("Limiter SR Switch", CS42L52_LIMITER_CTL1, 1, 1, 0), 41262306a36Sopenharmony_ci SOC_SINGLE("Limiter ZC Switch", CS42L52_LIMITER_CTL1, 0, 1, 0), 41362306a36Sopenharmony_ci SOC_SINGLE("Limiter Switch", CS42L52_LIMITER_CTL2, 7, 1, 0), 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci /* ALC */ 41662306a36Sopenharmony_ci SOC_SINGLE_TLV("ALC Attack Rate Volume", CS42L52_ALC_CTL, 41762306a36Sopenharmony_ci 0, 63, 0, limiter_tlv), 41862306a36Sopenharmony_ci SOC_SINGLE_TLV("ALC Release Rate Volume", CS42L52_ALC_RATE, 41962306a36Sopenharmony_ci 0, 63, 0, limiter_tlv), 42062306a36Sopenharmony_ci SOC_SINGLE_TLV("ALC Max Threshold Volume", CS42L52_ALC_THRESHOLD, 42162306a36Sopenharmony_ci 5, 7, 0, limiter_tlv), 42262306a36Sopenharmony_ci SOC_SINGLE_TLV("ALC Min Threshold Volume", CS42L52_ALC_THRESHOLD, 42362306a36Sopenharmony_ci 2, 7, 0, limiter_tlv), 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci SOC_DOUBLE_R("ALC SR Capture Switch", CS42L52_PGAA_CTL, 42662306a36Sopenharmony_ci CS42L52_PGAB_CTL, 7, 1, 1), 42762306a36Sopenharmony_ci SOC_DOUBLE_R("ALC ZC Capture Switch", CS42L52_PGAA_CTL, 42862306a36Sopenharmony_ci CS42L52_PGAB_CTL, 6, 1, 1), 42962306a36Sopenharmony_ci SOC_DOUBLE("ALC Capture Switch", CS42L52_ALC_CTL, 6, 7, 1, 0), 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci /* Noise gate */ 43262306a36Sopenharmony_ci SOC_ENUM("NG Type Switch", ng_type_enum), 43362306a36Sopenharmony_ci SOC_SINGLE("NG Enable Switch", CS42L52_NOISE_GATE_CTL, 6, 1, 0), 43462306a36Sopenharmony_ci SOC_SINGLE("NG Boost Switch", CS42L52_NOISE_GATE_CTL, 5, 1, 1), 43562306a36Sopenharmony_ci SOC_ENUM("NG Threshold", ng_threshold_enum), 43662306a36Sopenharmony_ci SOC_ENUM("NG Delay", ng_delay_enum), 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ci SOC_DOUBLE("HPF Switch", CS42L52_ANALOG_HPF_CTL, 5, 7, 1, 0), 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci SOC_DOUBLE("Analog SR Switch", CS42L52_ANALOG_HPF_CTL, 1, 3, 1, 1), 44162306a36Sopenharmony_ci SOC_DOUBLE("Analog ZC Switch", CS42L52_ANALOG_HPF_CTL, 0, 2, 1, 1), 44262306a36Sopenharmony_ci SOC_SINGLE("Digital SR Switch", CS42L52_MISC_CTL, 1, 1, 0), 44362306a36Sopenharmony_ci SOC_SINGLE("Digital ZC Switch", CS42L52_MISC_CTL, 0, 1, 0), 44462306a36Sopenharmony_ci SOC_SINGLE("Deemphasis Switch", CS42L52_MISC_CTL, 2, 1, 0), 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci SOC_SINGLE("Batt Compensation Switch", CS42L52_BATT_COMPEN, 7, 1, 0), 44762306a36Sopenharmony_ci SOC_SINGLE("Batt VP Monitor Switch", CS42L52_BATT_COMPEN, 6, 1, 0), 44862306a36Sopenharmony_ci SOC_SINGLE("Batt VP ref", CS42L52_BATT_COMPEN, 0, 0x0f, 0), 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_ci SOC_SINGLE("PGA AIN1L Switch", CS42L52_ADC_PGA_A, 0, 1, 0), 45162306a36Sopenharmony_ci SOC_SINGLE("PGA AIN1R Switch", CS42L52_ADC_PGA_B, 0, 1, 0), 45262306a36Sopenharmony_ci SOC_SINGLE("PGA AIN2L Switch", CS42L52_ADC_PGA_A, 1, 1, 0), 45362306a36Sopenharmony_ci SOC_SINGLE("PGA AIN2R Switch", CS42L52_ADC_PGA_B, 1, 1, 0), 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci SOC_SINGLE("PGA AIN3L Switch", CS42L52_ADC_PGA_A, 2, 1, 0), 45662306a36Sopenharmony_ci SOC_SINGLE("PGA AIN3R Switch", CS42L52_ADC_PGA_B, 2, 1, 0), 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci SOC_SINGLE("PGA AIN4L Switch", CS42L52_ADC_PGA_A, 3, 1, 0), 45962306a36Sopenharmony_ci SOC_SINGLE("PGA AIN4R Switch", CS42L52_ADC_PGA_B, 3, 1, 0), 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci SOC_SINGLE("PGA MICA Switch", CS42L52_ADC_PGA_A, 4, 1, 0), 46262306a36Sopenharmony_ci SOC_SINGLE("PGA MICB Switch", CS42L52_ADC_PGA_B, 4, 1, 0), 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci}; 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_cistatic const struct snd_kcontrol_new cs42l52_mica_controls[] = { 46762306a36Sopenharmony_ci SOC_ENUM("MICA Select", mica_enum), 46862306a36Sopenharmony_ci}; 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_cistatic const struct snd_kcontrol_new cs42l52_micb_controls[] = { 47162306a36Sopenharmony_ci SOC_ENUM("MICB Select", micb_enum), 47262306a36Sopenharmony_ci}; 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_cistatic int cs42l52_add_mic_controls(struct snd_soc_component *component) 47562306a36Sopenharmony_ci{ 47662306a36Sopenharmony_ci struct cs42l52_private *cs42l52 = snd_soc_component_get_drvdata(component); 47762306a36Sopenharmony_ci struct cs42l52_platform_data *pdata = &cs42l52->pdata; 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci if (!pdata->mica_diff_cfg) 48062306a36Sopenharmony_ci snd_soc_add_component_controls(component, cs42l52_mica_controls, 48162306a36Sopenharmony_ci ARRAY_SIZE(cs42l52_mica_controls)); 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ci if (!pdata->micb_diff_cfg) 48462306a36Sopenharmony_ci snd_soc_add_component_controls(component, cs42l52_micb_controls, 48562306a36Sopenharmony_ci ARRAY_SIZE(cs42l52_micb_controls)); 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci return 0; 48862306a36Sopenharmony_ci} 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_cistatic const struct snd_soc_dapm_widget cs42l52_dapm_widgets[] = { 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci SND_SOC_DAPM_INPUT("AIN1L"), 49362306a36Sopenharmony_ci SND_SOC_DAPM_INPUT("AIN1R"), 49462306a36Sopenharmony_ci SND_SOC_DAPM_INPUT("AIN2L"), 49562306a36Sopenharmony_ci SND_SOC_DAPM_INPUT("AIN2R"), 49662306a36Sopenharmony_ci SND_SOC_DAPM_INPUT("AIN3L"), 49762306a36Sopenharmony_ci SND_SOC_DAPM_INPUT("AIN3R"), 49862306a36Sopenharmony_ci SND_SOC_DAPM_INPUT("AIN4L"), 49962306a36Sopenharmony_ci SND_SOC_DAPM_INPUT("AIN4R"), 50062306a36Sopenharmony_ci SND_SOC_DAPM_INPUT("MICA"), 50162306a36Sopenharmony_ci SND_SOC_DAPM_INPUT("MICB"), 50262306a36Sopenharmony_ci SND_SOC_DAPM_SIGGEN("Beep"), 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci SND_SOC_DAPM_AIF_OUT("AIFOUTL", NULL, 0, 50562306a36Sopenharmony_ci SND_SOC_NOPM, 0, 0), 50662306a36Sopenharmony_ci SND_SOC_DAPM_AIF_OUT("AIFOUTR", NULL, 0, 50762306a36Sopenharmony_ci SND_SOC_NOPM, 0, 0), 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci SND_SOC_DAPM_ADC("ADC Left", NULL, CS42L52_PWRCTL1, 1, 1), 51062306a36Sopenharmony_ci SND_SOC_DAPM_ADC("ADC Right", NULL, CS42L52_PWRCTL1, 2, 1), 51162306a36Sopenharmony_ci SND_SOC_DAPM_PGA("PGA Left", CS42L52_PWRCTL1, 3, 1, NULL, 0), 51262306a36Sopenharmony_ci SND_SOC_DAPM_PGA("PGA Right", CS42L52_PWRCTL1, 4, 1, NULL, 0), 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci SND_SOC_DAPM_MUX("ADC Left Mux", SND_SOC_NOPM, 0, 0, &adca_mux), 51562306a36Sopenharmony_ci SND_SOC_DAPM_MUX("ADC Right Mux", SND_SOC_NOPM, 0, 0, &adcb_mux), 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_ci SND_SOC_DAPM_MUX("ADC Left Swap", SND_SOC_NOPM, 51862306a36Sopenharmony_ci 0, 0, &adca_mixer), 51962306a36Sopenharmony_ci SND_SOC_DAPM_MUX("ADC Right Swap", SND_SOC_NOPM, 52062306a36Sopenharmony_ci 0, 0, &adcb_mixer), 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci SND_SOC_DAPM_MUX("Output Mux", SND_SOC_NOPM, 52362306a36Sopenharmony_ci 0, 0, &digital_output_mux), 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci SND_SOC_DAPM_PGA("PGA MICA", CS42L52_PWRCTL2, 1, 1, NULL, 0), 52662306a36Sopenharmony_ci SND_SOC_DAPM_PGA("PGA MICB", CS42L52_PWRCTL2, 2, 1, NULL, 0), 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY("Mic Bias", CS42L52_PWRCTL2, 0, 1, NULL, 0), 52962306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY("Charge Pump", CS42L52_PWRCTL1, 7, 1, NULL, 0), 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_ci SND_SOC_DAPM_AIF_IN("AIFINL", NULL, 0, 53262306a36Sopenharmony_ci SND_SOC_NOPM, 0, 0), 53362306a36Sopenharmony_ci SND_SOC_DAPM_AIF_IN("AIFINR", NULL, 0, 53462306a36Sopenharmony_ci SND_SOC_NOPM, 0, 0), 53562306a36Sopenharmony_ci 53662306a36Sopenharmony_ci SND_SOC_DAPM_DAC("DAC Left", NULL, SND_SOC_NOPM, 0, 0), 53762306a36Sopenharmony_ci SND_SOC_DAPM_DAC("DAC Right", NULL, SND_SOC_NOPM, 0, 0), 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci SND_SOC_DAPM_SWITCH("Bypass Left", CS42L52_MISC_CTL, 54062306a36Sopenharmony_ci 6, 0, &passthrul_ctl), 54162306a36Sopenharmony_ci SND_SOC_DAPM_SWITCH("Bypass Right", CS42L52_MISC_CTL, 54262306a36Sopenharmony_ci 7, 0, &passthrur_ctl), 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_ci SND_SOC_DAPM_MUX("PCM Left Swap", SND_SOC_NOPM, 54562306a36Sopenharmony_ci 0, 0, &pcma_mixer), 54662306a36Sopenharmony_ci SND_SOC_DAPM_MUX("PCM Right Swap", SND_SOC_NOPM, 54762306a36Sopenharmony_ci 0, 0, &pcmb_mixer), 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_ci SND_SOC_DAPM_SWITCH("HP Left Amp", SND_SOC_NOPM, 0, 0, &hpl_ctl), 55062306a36Sopenharmony_ci SND_SOC_DAPM_SWITCH("HP Right Amp", SND_SOC_NOPM, 0, 0, &hpr_ctl), 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_ci SND_SOC_DAPM_SWITCH("SPK Left Amp", SND_SOC_NOPM, 0, 0, &spkl_ctl), 55362306a36Sopenharmony_ci SND_SOC_DAPM_SWITCH("SPK Right Amp", SND_SOC_NOPM, 0, 0, &spkr_ctl), 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_ci SND_SOC_DAPM_OUTPUT("HPOUTA"), 55662306a36Sopenharmony_ci SND_SOC_DAPM_OUTPUT("HPOUTB"), 55762306a36Sopenharmony_ci SND_SOC_DAPM_OUTPUT("SPKOUTA"), 55862306a36Sopenharmony_ci SND_SOC_DAPM_OUTPUT("SPKOUTB"), 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_ci}; 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_cistatic const struct snd_soc_dapm_route cs42l52_audio_map[] = { 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_ci {"Capture", NULL, "AIFOUTL"}, 56562306a36Sopenharmony_ci {"Capture", NULL, "AIFOUTL"}, 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_ci {"AIFOUTL", NULL, "Output Mux"}, 56862306a36Sopenharmony_ci {"AIFOUTR", NULL, "Output Mux"}, 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ci {"Output Mux", "ADC", "ADC Left"}, 57162306a36Sopenharmony_ci {"Output Mux", "ADC", "ADC Right"}, 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci {"ADC Left", NULL, "Charge Pump"}, 57462306a36Sopenharmony_ci {"ADC Right", NULL, "Charge Pump"}, 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ci {"Charge Pump", NULL, "ADC Left Mux"}, 57762306a36Sopenharmony_ci {"Charge Pump", NULL, "ADC Right Mux"}, 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci {"ADC Left Mux", "Input1A", "AIN1L"}, 58062306a36Sopenharmony_ci {"ADC Right Mux", "Input1B", "AIN1R"}, 58162306a36Sopenharmony_ci {"ADC Left Mux", "Input2A", "AIN2L"}, 58262306a36Sopenharmony_ci {"ADC Right Mux", "Input2B", "AIN2R"}, 58362306a36Sopenharmony_ci {"ADC Left Mux", "Input3A", "AIN3L"}, 58462306a36Sopenharmony_ci {"ADC Right Mux", "Input3B", "AIN3R"}, 58562306a36Sopenharmony_ci {"ADC Left Mux", "Input4A", "AIN4L"}, 58662306a36Sopenharmony_ci {"ADC Right Mux", "Input4B", "AIN4R"}, 58762306a36Sopenharmony_ci {"ADC Left Mux", "PGA Input Left", "PGA Left"}, 58862306a36Sopenharmony_ci {"ADC Right Mux", "PGA Input Right" , "PGA Right"}, 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci {"PGA Left", "Switch", "AIN1L"}, 59162306a36Sopenharmony_ci {"PGA Right", "Switch", "AIN1R"}, 59262306a36Sopenharmony_ci {"PGA Left", "Switch", "AIN2L"}, 59362306a36Sopenharmony_ci {"PGA Right", "Switch", "AIN2R"}, 59462306a36Sopenharmony_ci {"PGA Left", "Switch", "AIN3L"}, 59562306a36Sopenharmony_ci {"PGA Right", "Switch", "AIN3R"}, 59662306a36Sopenharmony_ci {"PGA Left", "Switch", "AIN4L"}, 59762306a36Sopenharmony_ci {"PGA Right", "Switch", "AIN4R"}, 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ci {"PGA Left", "Switch", "PGA MICA"}, 60062306a36Sopenharmony_ci {"PGA MICA", NULL, "MICA"}, 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_ci {"PGA Right", "Switch", "PGA MICB"}, 60362306a36Sopenharmony_ci {"PGA MICB", NULL, "MICB"}, 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_ci {"HPOUTA", NULL, "HP Left Amp"}, 60662306a36Sopenharmony_ci {"HPOUTB", NULL, "HP Right Amp"}, 60762306a36Sopenharmony_ci {"HP Left Amp", NULL, "Bypass Left"}, 60862306a36Sopenharmony_ci {"HP Right Amp", NULL, "Bypass Right"}, 60962306a36Sopenharmony_ci {"Bypass Left", "Switch", "PGA Left"}, 61062306a36Sopenharmony_ci {"Bypass Right", "Switch", "PGA Right"}, 61162306a36Sopenharmony_ci {"HP Left Amp", "Switch", "DAC Left"}, 61262306a36Sopenharmony_ci {"HP Right Amp", "Switch", "DAC Right"}, 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci {"SPKOUTA", NULL, "SPK Left Amp"}, 61562306a36Sopenharmony_ci {"SPKOUTB", NULL, "SPK Right Amp"}, 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci {"SPK Left Amp", NULL, "Beep"}, 61862306a36Sopenharmony_ci {"SPK Right Amp", NULL, "Beep"}, 61962306a36Sopenharmony_ci {"SPK Left Amp", "Switch", "Playback"}, 62062306a36Sopenharmony_ci {"SPK Right Amp", "Switch", "Playback"}, 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci {"DAC Left", NULL, "Beep"}, 62362306a36Sopenharmony_ci {"DAC Right", NULL, "Beep"}, 62462306a36Sopenharmony_ci {"DAC Left", NULL, "Playback"}, 62562306a36Sopenharmony_ci {"DAC Right", NULL, "Playback"}, 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ci {"Output Mux", "DSP", "Playback"}, 62862306a36Sopenharmony_ci {"Output Mux", "DSP", "Playback"}, 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_ci {"AIFINL", NULL, "Playback"}, 63162306a36Sopenharmony_ci {"AIFINR", NULL, "Playback"}, 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_ci}; 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_cistruct cs42l52_clk_para { 63662306a36Sopenharmony_ci u32 mclk; 63762306a36Sopenharmony_ci u32 rate; 63862306a36Sopenharmony_ci u8 speed; 63962306a36Sopenharmony_ci u8 group; 64062306a36Sopenharmony_ci u8 videoclk; 64162306a36Sopenharmony_ci u8 ratio; 64262306a36Sopenharmony_ci u8 mclkdiv2; 64362306a36Sopenharmony_ci}; 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_cistatic const struct cs42l52_clk_para clk_map_table[] = { 64662306a36Sopenharmony_ci /*8k*/ 64762306a36Sopenharmony_ci {12288000, 8000, CLK_QS_MODE, CLK_32K, CLK_NO_27M, CLK_R_128, 0}, 64862306a36Sopenharmony_ci {18432000, 8000, CLK_QS_MODE, CLK_32K, CLK_NO_27M, CLK_R_128, 0}, 64962306a36Sopenharmony_ci {12000000, 8000, CLK_QS_MODE, CLK_32K, CLK_NO_27M, CLK_R_125, 0}, 65062306a36Sopenharmony_ci {24000000, 8000, CLK_QS_MODE, CLK_32K, CLK_NO_27M, CLK_R_125, 1}, 65162306a36Sopenharmony_ci {27000000, 8000, CLK_QS_MODE, CLK_32K, CLK_27M_MCLK, CLK_R_125, 0}, 65262306a36Sopenharmony_ci 65362306a36Sopenharmony_ci /*11.025k*/ 65462306a36Sopenharmony_ci {11289600, 11025, CLK_QS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0}, 65562306a36Sopenharmony_ci {16934400, 11025, CLK_QS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0}, 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_ci /*16k*/ 65862306a36Sopenharmony_ci {12288000, 16000, CLK_HS_MODE, CLK_32K, CLK_NO_27M, CLK_R_128, 0}, 65962306a36Sopenharmony_ci {18432000, 16000, CLK_HS_MODE, CLK_32K, CLK_NO_27M, CLK_R_128, 0}, 66062306a36Sopenharmony_ci {12000000, 16000, CLK_HS_MODE, CLK_32K, CLK_NO_27M, CLK_R_125, 0}, 66162306a36Sopenharmony_ci {24000000, 16000, CLK_HS_MODE, CLK_32K, CLK_NO_27M, CLK_R_125, 1}, 66262306a36Sopenharmony_ci {27000000, 16000, CLK_HS_MODE, CLK_32K, CLK_27M_MCLK, CLK_R_125, 1}, 66362306a36Sopenharmony_ci 66462306a36Sopenharmony_ci /*22.05k*/ 66562306a36Sopenharmony_ci {11289600, 22050, CLK_HS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0}, 66662306a36Sopenharmony_ci {16934400, 22050, CLK_HS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0}, 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_ci /* 32k */ 66962306a36Sopenharmony_ci {12288000, 32000, CLK_SS_MODE, CLK_32K, CLK_NO_27M, CLK_R_128, 0}, 67062306a36Sopenharmony_ci {18432000, 32000, CLK_SS_MODE, CLK_32K, CLK_NO_27M, CLK_R_128, 0}, 67162306a36Sopenharmony_ci {12000000, 32000, CLK_SS_MODE, CLK_32K, CLK_NO_27M, CLK_R_125, 0}, 67262306a36Sopenharmony_ci {24000000, 32000, CLK_SS_MODE, CLK_32K, CLK_NO_27M, CLK_R_125, 1}, 67362306a36Sopenharmony_ci {27000000, 32000, CLK_SS_MODE, CLK_32K, CLK_27M_MCLK, CLK_R_125, 0}, 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci /* 44.1k */ 67662306a36Sopenharmony_ci {11289600, 44100, CLK_SS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0}, 67762306a36Sopenharmony_ci {16934400, 44100, CLK_SS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0}, 67862306a36Sopenharmony_ci 67962306a36Sopenharmony_ci /* 48k */ 68062306a36Sopenharmony_ci {12288000, 48000, CLK_SS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0}, 68162306a36Sopenharmony_ci {18432000, 48000, CLK_SS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0}, 68262306a36Sopenharmony_ci {12000000, 48000, CLK_SS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_125, 0}, 68362306a36Sopenharmony_ci {24000000, 48000, CLK_SS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_125, 1}, 68462306a36Sopenharmony_ci {27000000, 48000, CLK_SS_MODE, CLK_NO_32K, CLK_27M_MCLK, CLK_R_125, 1}, 68562306a36Sopenharmony_ci 68662306a36Sopenharmony_ci /* 88.2k */ 68762306a36Sopenharmony_ci {11289600, 88200, CLK_DS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0}, 68862306a36Sopenharmony_ci {16934400, 88200, CLK_DS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0}, 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ci /* 96k */ 69162306a36Sopenharmony_ci {12288000, 96000, CLK_DS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0}, 69262306a36Sopenharmony_ci {18432000, 96000, CLK_DS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0}, 69362306a36Sopenharmony_ci {12000000, 96000, CLK_DS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_125, 0}, 69462306a36Sopenharmony_ci {24000000, 96000, CLK_DS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_125, 1}, 69562306a36Sopenharmony_ci}; 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_cistatic int cs42l52_get_clk(int mclk, int rate) 69862306a36Sopenharmony_ci{ 69962306a36Sopenharmony_ci int i, ret = -EINVAL; 70062306a36Sopenharmony_ci u_int mclk1, mclk2 = 0; 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(clk_map_table); i++) { 70362306a36Sopenharmony_ci if (clk_map_table[i].rate == rate) { 70462306a36Sopenharmony_ci mclk1 = clk_map_table[i].mclk; 70562306a36Sopenharmony_ci if (abs(mclk - mclk1) < abs(mclk - mclk2)) { 70662306a36Sopenharmony_ci mclk2 = mclk1; 70762306a36Sopenharmony_ci ret = i; 70862306a36Sopenharmony_ci } 70962306a36Sopenharmony_ci } 71062306a36Sopenharmony_ci } 71162306a36Sopenharmony_ci return ret; 71262306a36Sopenharmony_ci} 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_cistatic int cs42l52_set_sysclk(struct snd_soc_dai *codec_dai, 71562306a36Sopenharmony_ci int clk_id, unsigned int freq, int dir) 71662306a36Sopenharmony_ci{ 71762306a36Sopenharmony_ci struct snd_soc_component *component = codec_dai->component; 71862306a36Sopenharmony_ci struct cs42l52_private *cs42l52 = snd_soc_component_get_drvdata(component); 71962306a36Sopenharmony_ci 72062306a36Sopenharmony_ci if ((freq >= CS42L52_MIN_CLK) && (freq <= CS42L52_MAX_CLK)) { 72162306a36Sopenharmony_ci cs42l52->sysclk = freq; 72262306a36Sopenharmony_ci } else { 72362306a36Sopenharmony_ci dev_err(component->dev, "Invalid freq parameter\n"); 72462306a36Sopenharmony_ci return -EINVAL; 72562306a36Sopenharmony_ci } 72662306a36Sopenharmony_ci return 0; 72762306a36Sopenharmony_ci} 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_cistatic int cs42l52_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) 73062306a36Sopenharmony_ci{ 73162306a36Sopenharmony_ci struct snd_soc_component *component = codec_dai->component; 73262306a36Sopenharmony_ci struct cs42l52_private *cs42l52 = snd_soc_component_get_drvdata(component); 73362306a36Sopenharmony_ci u8 iface = 0; 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 73662306a36Sopenharmony_ci case SND_SOC_DAIFMT_CBM_CFM: 73762306a36Sopenharmony_ci iface = CS42L52_IFACE_CTL1_MASTER; 73862306a36Sopenharmony_ci break; 73962306a36Sopenharmony_ci case SND_SOC_DAIFMT_CBS_CFS: 74062306a36Sopenharmony_ci iface = CS42L52_IFACE_CTL1_SLAVE; 74162306a36Sopenharmony_ci break; 74262306a36Sopenharmony_ci default: 74362306a36Sopenharmony_ci return -EINVAL; 74462306a36Sopenharmony_ci } 74562306a36Sopenharmony_ci 74662306a36Sopenharmony_ci /* interface format */ 74762306a36Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 74862306a36Sopenharmony_ci case SND_SOC_DAIFMT_I2S: 74962306a36Sopenharmony_ci iface |= CS42L52_IFACE_CTL1_ADC_FMT_I2S | 75062306a36Sopenharmony_ci CS42L52_IFACE_CTL1_DAC_FMT_I2S; 75162306a36Sopenharmony_ci break; 75262306a36Sopenharmony_ci case SND_SOC_DAIFMT_RIGHT_J: 75362306a36Sopenharmony_ci iface |= CS42L52_IFACE_CTL1_DAC_FMT_RIGHT_J; 75462306a36Sopenharmony_ci break; 75562306a36Sopenharmony_ci case SND_SOC_DAIFMT_LEFT_J: 75662306a36Sopenharmony_ci iface |= CS42L52_IFACE_CTL1_ADC_FMT_LEFT_J | 75762306a36Sopenharmony_ci CS42L52_IFACE_CTL1_DAC_FMT_LEFT_J; 75862306a36Sopenharmony_ci break; 75962306a36Sopenharmony_ci case SND_SOC_DAIFMT_DSP_A: 76062306a36Sopenharmony_ci iface |= CS42L52_IFACE_CTL1_DSP_MODE_EN; 76162306a36Sopenharmony_ci break; 76262306a36Sopenharmony_ci case SND_SOC_DAIFMT_DSP_B: 76362306a36Sopenharmony_ci break; 76462306a36Sopenharmony_ci default: 76562306a36Sopenharmony_ci return -EINVAL; 76662306a36Sopenharmony_ci } 76762306a36Sopenharmony_ci 76862306a36Sopenharmony_ci /* clock inversion */ 76962306a36Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 77062306a36Sopenharmony_ci case SND_SOC_DAIFMT_NB_NF: 77162306a36Sopenharmony_ci break; 77262306a36Sopenharmony_ci case SND_SOC_DAIFMT_IB_IF: 77362306a36Sopenharmony_ci iface |= CS42L52_IFACE_CTL1_INV_SCLK; 77462306a36Sopenharmony_ci break; 77562306a36Sopenharmony_ci case SND_SOC_DAIFMT_IB_NF: 77662306a36Sopenharmony_ci iface |= CS42L52_IFACE_CTL1_INV_SCLK; 77762306a36Sopenharmony_ci break; 77862306a36Sopenharmony_ci case SND_SOC_DAIFMT_NB_IF: 77962306a36Sopenharmony_ci break; 78062306a36Sopenharmony_ci default: 78162306a36Sopenharmony_ci return -EINVAL; 78262306a36Sopenharmony_ci } 78362306a36Sopenharmony_ci cs42l52->config.format = iface; 78462306a36Sopenharmony_ci snd_soc_component_write(component, CS42L52_IFACE_CTL1, cs42l52->config.format); 78562306a36Sopenharmony_ci 78662306a36Sopenharmony_ci return 0; 78762306a36Sopenharmony_ci} 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_cistatic int cs42l52_mute(struct snd_soc_dai *dai, int mute, int direction) 79062306a36Sopenharmony_ci{ 79162306a36Sopenharmony_ci struct snd_soc_component *component = dai->component; 79262306a36Sopenharmony_ci 79362306a36Sopenharmony_ci if (mute) 79462306a36Sopenharmony_ci snd_soc_component_update_bits(component, CS42L52_PB_CTL1, 79562306a36Sopenharmony_ci CS42L52_PB_CTL1_MUTE_MASK, 79662306a36Sopenharmony_ci CS42L52_PB_CTL1_MUTE); 79762306a36Sopenharmony_ci else 79862306a36Sopenharmony_ci snd_soc_component_update_bits(component, CS42L52_PB_CTL1, 79962306a36Sopenharmony_ci CS42L52_PB_CTL1_MUTE_MASK, 80062306a36Sopenharmony_ci CS42L52_PB_CTL1_UNMUTE); 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_ci return 0; 80362306a36Sopenharmony_ci} 80462306a36Sopenharmony_ci 80562306a36Sopenharmony_cistatic int cs42l52_pcm_hw_params(struct snd_pcm_substream *substream, 80662306a36Sopenharmony_ci struct snd_pcm_hw_params *params, 80762306a36Sopenharmony_ci struct snd_soc_dai *dai) 80862306a36Sopenharmony_ci{ 80962306a36Sopenharmony_ci struct snd_soc_component *component = dai->component; 81062306a36Sopenharmony_ci struct cs42l52_private *cs42l52 = snd_soc_component_get_drvdata(component); 81162306a36Sopenharmony_ci u32 clk = 0; 81262306a36Sopenharmony_ci int index; 81362306a36Sopenharmony_ci 81462306a36Sopenharmony_ci index = cs42l52_get_clk(cs42l52->sysclk, params_rate(params)); 81562306a36Sopenharmony_ci if (index >= 0) { 81662306a36Sopenharmony_ci cs42l52->sysclk = clk_map_table[index].mclk; 81762306a36Sopenharmony_ci 81862306a36Sopenharmony_ci clk |= (clk_map_table[index].speed << CLK_SPEED_SHIFT) | 81962306a36Sopenharmony_ci (clk_map_table[index].group << CLK_32K_SR_SHIFT) | 82062306a36Sopenharmony_ci (clk_map_table[index].videoclk << CLK_27M_MCLK_SHIFT) | 82162306a36Sopenharmony_ci (clk_map_table[index].ratio << CLK_RATIO_SHIFT) | 82262306a36Sopenharmony_ci clk_map_table[index].mclkdiv2; 82362306a36Sopenharmony_ci 82462306a36Sopenharmony_ci snd_soc_component_write(component, CS42L52_CLK_CTL, clk); 82562306a36Sopenharmony_ci } else { 82662306a36Sopenharmony_ci dev_err(component->dev, "can't get correct mclk\n"); 82762306a36Sopenharmony_ci return -EINVAL; 82862306a36Sopenharmony_ci } 82962306a36Sopenharmony_ci 83062306a36Sopenharmony_ci return 0; 83162306a36Sopenharmony_ci} 83262306a36Sopenharmony_ci 83362306a36Sopenharmony_cistatic int cs42l52_set_bias_level(struct snd_soc_component *component, 83462306a36Sopenharmony_ci enum snd_soc_bias_level level) 83562306a36Sopenharmony_ci{ 83662306a36Sopenharmony_ci struct cs42l52_private *cs42l52 = snd_soc_component_get_drvdata(component); 83762306a36Sopenharmony_ci 83862306a36Sopenharmony_ci switch (level) { 83962306a36Sopenharmony_ci case SND_SOC_BIAS_ON: 84062306a36Sopenharmony_ci break; 84162306a36Sopenharmony_ci case SND_SOC_BIAS_PREPARE: 84262306a36Sopenharmony_ci snd_soc_component_update_bits(component, CS42L52_PWRCTL1, 84362306a36Sopenharmony_ci CS42L52_PWRCTL1_PDN_CODEC, 0); 84462306a36Sopenharmony_ci break; 84562306a36Sopenharmony_ci case SND_SOC_BIAS_STANDBY: 84662306a36Sopenharmony_ci if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) { 84762306a36Sopenharmony_ci regcache_cache_only(cs42l52->regmap, false); 84862306a36Sopenharmony_ci regcache_sync(cs42l52->regmap); 84962306a36Sopenharmony_ci } 85062306a36Sopenharmony_ci snd_soc_component_write(component, CS42L52_PWRCTL1, CS42L52_PWRCTL1_PDN_ALL); 85162306a36Sopenharmony_ci break; 85262306a36Sopenharmony_ci case SND_SOC_BIAS_OFF: 85362306a36Sopenharmony_ci snd_soc_component_write(component, CS42L52_PWRCTL1, CS42L52_PWRCTL1_PDN_ALL); 85462306a36Sopenharmony_ci regcache_cache_only(cs42l52->regmap, true); 85562306a36Sopenharmony_ci break; 85662306a36Sopenharmony_ci } 85762306a36Sopenharmony_ci 85862306a36Sopenharmony_ci return 0; 85962306a36Sopenharmony_ci} 86062306a36Sopenharmony_ci 86162306a36Sopenharmony_ci#define CS42L52_RATES (SNDRV_PCM_RATE_8000_96000) 86262306a36Sopenharmony_ci 86362306a36Sopenharmony_ci#define CS42L52_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE | \ 86462306a36Sopenharmony_ci SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_U18_3LE | \ 86562306a36Sopenharmony_ci SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_U20_3LE | \ 86662306a36Sopenharmony_ci SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_U24_LE) 86762306a36Sopenharmony_ci 86862306a36Sopenharmony_cistatic const struct snd_soc_dai_ops cs42l52_ops = { 86962306a36Sopenharmony_ci .hw_params = cs42l52_pcm_hw_params, 87062306a36Sopenharmony_ci .mute_stream = cs42l52_mute, 87162306a36Sopenharmony_ci .set_fmt = cs42l52_set_fmt, 87262306a36Sopenharmony_ci .set_sysclk = cs42l52_set_sysclk, 87362306a36Sopenharmony_ci .no_capture_mute = 1, 87462306a36Sopenharmony_ci}; 87562306a36Sopenharmony_ci 87662306a36Sopenharmony_cistatic struct snd_soc_dai_driver cs42l52_dai = { 87762306a36Sopenharmony_ci .name = "cs42l52", 87862306a36Sopenharmony_ci .playback = { 87962306a36Sopenharmony_ci .stream_name = "Playback", 88062306a36Sopenharmony_ci .channels_min = 1, 88162306a36Sopenharmony_ci .channels_max = 2, 88262306a36Sopenharmony_ci .rates = CS42L52_RATES, 88362306a36Sopenharmony_ci .formats = CS42L52_FORMATS, 88462306a36Sopenharmony_ci }, 88562306a36Sopenharmony_ci .capture = { 88662306a36Sopenharmony_ci .stream_name = "Capture", 88762306a36Sopenharmony_ci .channels_min = 1, 88862306a36Sopenharmony_ci .channels_max = 2, 88962306a36Sopenharmony_ci .rates = CS42L52_RATES, 89062306a36Sopenharmony_ci .formats = CS42L52_FORMATS, 89162306a36Sopenharmony_ci }, 89262306a36Sopenharmony_ci .ops = &cs42l52_ops, 89362306a36Sopenharmony_ci}; 89462306a36Sopenharmony_ci 89562306a36Sopenharmony_cistatic int beep_rates[] = { 89662306a36Sopenharmony_ci 261, 522, 585, 667, 706, 774, 889, 1000, 89762306a36Sopenharmony_ci 1043, 1200, 1333, 1412, 1600, 1714, 2000, 2182 89862306a36Sopenharmony_ci}; 89962306a36Sopenharmony_ci 90062306a36Sopenharmony_cistatic void cs42l52_beep_work(struct work_struct *work) 90162306a36Sopenharmony_ci{ 90262306a36Sopenharmony_ci struct cs42l52_private *cs42l52 = 90362306a36Sopenharmony_ci container_of(work, struct cs42l52_private, beep_work); 90462306a36Sopenharmony_ci struct snd_soc_component *component = cs42l52->component; 90562306a36Sopenharmony_ci struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); 90662306a36Sopenharmony_ci int i; 90762306a36Sopenharmony_ci int val = 0; 90862306a36Sopenharmony_ci int best = 0; 90962306a36Sopenharmony_ci 91062306a36Sopenharmony_ci if (cs42l52->beep_rate) { 91162306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(beep_rates); i++) { 91262306a36Sopenharmony_ci if (abs(cs42l52->beep_rate - beep_rates[i]) < 91362306a36Sopenharmony_ci abs(cs42l52->beep_rate - beep_rates[best])) 91462306a36Sopenharmony_ci best = i; 91562306a36Sopenharmony_ci } 91662306a36Sopenharmony_ci 91762306a36Sopenharmony_ci dev_dbg(component->dev, "Set beep rate %dHz for requested %dHz\n", 91862306a36Sopenharmony_ci beep_rates[best], cs42l52->beep_rate); 91962306a36Sopenharmony_ci 92062306a36Sopenharmony_ci val = (best << CS42L52_BEEP_RATE_SHIFT); 92162306a36Sopenharmony_ci 92262306a36Sopenharmony_ci snd_soc_dapm_enable_pin(dapm, "Beep"); 92362306a36Sopenharmony_ci } else { 92462306a36Sopenharmony_ci dev_dbg(component->dev, "Disabling beep\n"); 92562306a36Sopenharmony_ci snd_soc_dapm_disable_pin(dapm, "Beep"); 92662306a36Sopenharmony_ci } 92762306a36Sopenharmony_ci 92862306a36Sopenharmony_ci snd_soc_component_update_bits(component, CS42L52_BEEP_FREQ, 92962306a36Sopenharmony_ci CS42L52_BEEP_RATE_MASK, val); 93062306a36Sopenharmony_ci 93162306a36Sopenharmony_ci snd_soc_dapm_sync(dapm); 93262306a36Sopenharmony_ci} 93362306a36Sopenharmony_ci 93462306a36Sopenharmony_ci/* For usability define a way of injecting beep events for the device - 93562306a36Sopenharmony_ci * many systems will not have a keyboard. 93662306a36Sopenharmony_ci */ 93762306a36Sopenharmony_cistatic int cs42l52_beep_event(struct input_dev *dev, unsigned int type, 93862306a36Sopenharmony_ci unsigned int code, int hz) 93962306a36Sopenharmony_ci{ 94062306a36Sopenharmony_ci struct snd_soc_component *component = input_get_drvdata(dev); 94162306a36Sopenharmony_ci struct cs42l52_private *cs42l52 = snd_soc_component_get_drvdata(component); 94262306a36Sopenharmony_ci 94362306a36Sopenharmony_ci dev_dbg(component->dev, "Beep event %x %x\n", code, hz); 94462306a36Sopenharmony_ci 94562306a36Sopenharmony_ci switch (code) { 94662306a36Sopenharmony_ci case SND_BELL: 94762306a36Sopenharmony_ci if (hz) 94862306a36Sopenharmony_ci hz = 261; 94962306a36Sopenharmony_ci break; 95062306a36Sopenharmony_ci case SND_TONE: 95162306a36Sopenharmony_ci break; 95262306a36Sopenharmony_ci default: 95362306a36Sopenharmony_ci return -1; 95462306a36Sopenharmony_ci } 95562306a36Sopenharmony_ci 95662306a36Sopenharmony_ci /* Kick the beep from a workqueue */ 95762306a36Sopenharmony_ci cs42l52->beep_rate = hz; 95862306a36Sopenharmony_ci schedule_work(&cs42l52->beep_work); 95962306a36Sopenharmony_ci return 0; 96062306a36Sopenharmony_ci} 96162306a36Sopenharmony_ci 96262306a36Sopenharmony_cistatic ssize_t beep_store(struct device *dev, struct device_attribute *attr, 96362306a36Sopenharmony_ci const char *buf, size_t count) 96462306a36Sopenharmony_ci{ 96562306a36Sopenharmony_ci struct cs42l52_private *cs42l52 = dev_get_drvdata(dev); 96662306a36Sopenharmony_ci long int time; 96762306a36Sopenharmony_ci int ret; 96862306a36Sopenharmony_ci 96962306a36Sopenharmony_ci ret = kstrtol(buf, 10, &time); 97062306a36Sopenharmony_ci if (ret != 0) 97162306a36Sopenharmony_ci return ret; 97262306a36Sopenharmony_ci 97362306a36Sopenharmony_ci input_event(cs42l52->beep, EV_SND, SND_TONE, time); 97462306a36Sopenharmony_ci 97562306a36Sopenharmony_ci return count; 97662306a36Sopenharmony_ci} 97762306a36Sopenharmony_ci 97862306a36Sopenharmony_cistatic DEVICE_ATTR_WO(beep); 97962306a36Sopenharmony_ci 98062306a36Sopenharmony_cistatic void cs42l52_init_beep(struct snd_soc_component *component) 98162306a36Sopenharmony_ci{ 98262306a36Sopenharmony_ci struct cs42l52_private *cs42l52 = snd_soc_component_get_drvdata(component); 98362306a36Sopenharmony_ci int ret; 98462306a36Sopenharmony_ci 98562306a36Sopenharmony_ci cs42l52->beep = devm_input_allocate_device(component->dev); 98662306a36Sopenharmony_ci if (!cs42l52->beep) { 98762306a36Sopenharmony_ci dev_err(component->dev, "Failed to allocate beep device\n"); 98862306a36Sopenharmony_ci return; 98962306a36Sopenharmony_ci } 99062306a36Sopenharmony_ci 99162306a36Sopenharmony_ci INIT_WORK(&cs42l52->beep_work, cs42l52_beep_work); 99262306a36Sopenharmony_ci cs42l52->beep_rate = 0; 99362306a36Sopenharmony_ci 99462306a36Sopenharmony_ci cs42l52->beep->name = "CS42L52 Beep Generator"; 99562306a36Sopenharmony_ci cs42l52->beep->phys = dev_name(component->dev); 99662306a36Sopenharmony_ci cs42l52->beep->id.bustype = BUS_I2C; 99762306a36Sopenharmony_ci 99862306a36Sopenharmony_ci cs42l52->beep->evbit[0] = BIT_MASK(EV_SND); 99962306a36Sopenharmony_ci cs42l52->beep->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE); 100062306a36Sopenharmony_ci cs42l52->beep->event = cs42l52_beep_event; 100162306a36Sopenharmony_ci cs42l52->beep->dev.parent = component->dev; 100262306a36Sopenharmony_ci input_set_drvdata(cs42l52->beep, component); 100362306a36Sopenharmony_ci 100462306a36Sopenharmony_ci ret = input_register_device(cs42l52->beep); 100562306a36Sopenharmony_ci if (ret != 0) { 100662306a36Sopenharmony_ci cs42l52->beep = NULL; 100762306a36Sopenharmony_ci dev_err(component->dev, "Failed to register beep device\n"); 100862306a36Sopenharmony_ci } 100962306a36Sopenharmony_ci 101062306a36Sopenharmony_ci ret = device_create_file(component->dev, &dev_attr_beep); 101162306a36Sopenharmony_ci if (ret != 0) { 101262306a36Sopenharmony_ci dev_err(component->dev, "Failed to create keyclick file: %d\n", 101362306a36Sopenharmony_ci ret); 101462306a36Sopenharmony_ci } 101562306a36Sopenharmony_ci} 101662306a36Sopenharmony_ci 101762306a36Sopenharmony_cistatic void cs42l52_free_beep(struct snd_soc_component *component) 101862306a36Sopenharmony_ci{ 101962306a36Sopenharmony_ci struct cs42l52_private *cs42l52 = snd_soc_component_get_drvdata(component); 102062306a36Sopenharmony_ci 102162306a36Sopenharmony_ci device_remove_file(component->dev, &dev_attr_beep); 102262306a36Sopenharmony_ci cancel_work_sync(&cs42l52->beep_work); 102362306a36Sopenharmony_ci cs42l52->beep = NULL; 102462306a36Sopenharmony_ci 102562306a36Sopenharmony_ci snd_soc_component_update_bits(component, CS42L52_BEEP_TONE_CTL, 102662306a36Sopenharmony_ci CS42L52_BEEP_EN_MASK, 0); 102762306a36Sopenharmony_ci} 102862306a36Sopenharmony_ci 102962306a36Sopenharmony_cistatic int cs42l52_probe(struct snd_soc_component *component) 103062306a36Sopenharmony_ci{ 103162306a36Sopenharmony_ci struct cs42l52_private *cs42l52 = snd_soc_component_get_drvdata(component); 103262306a36Sopenharmony_ci 103362306a36Sopenharmony_ci regcache_cache_only(cs42l52->regmap, true); 103462306a36Sopenharmony_ci 103562306a36Sopenharmony_ci cs42l52_add_mic_controls(component); 103662306a36Sopenharmony_ci 103762306a36Sopenharmony_ci cs42l52_init_beep(component); 103862306a36Sopenharmony_ci 103962306a36Sopenharmony_ci cs42l52->sysclk = CS42L52_DEFAULT_CLK; 104062306a36Sopenharmony_ci cs42l52->config.format = CS42L52_DEFAULT_FORMAT; 104162306a36Sopenharmony_ci 104262306a36Sopenharmony_ci return 0; 104362306a36Sopenharmony_ci} 104462306a36Sopenharmony_ci 104562306a36Sopenharmony_cistatic void cs42l52_remove(struct snd_soc_component *component) 104662306a36Sopenharmony_ci{ 104762306a36Sopenharmony_ci cs42l52_free_beep(component); 104862306a36Sopenharmony_ci} 104962306a36Sopenharmony_ci 105062306a36Sopenharmony_cistatic const struct snd_soc_component_driver soc_component_dev_cs42l52 = { 105162306a36Sopenharmony_ci .probe = cs42l52_probe, 105262306a36Sopenharmony_ci .remove = cs42l52_remove, 105362306a36Sopenharmony_ci .set_bias_level = cs42l52_set_bias_level, 105462306a36Sopenharmony_ci .controls = cs42l52_snd_controls, 105562306a36Sopenharmony_ci .num_controls = ARRAY_SIZE(cs42l52_snd_controls), 105662306a36Sopenharmony_ci .dapm_widgets = cs42l52_dapm_widgets, 105762306a36Sopenharmony_ci .num_dapm_widgets = ARRAY_SIZE(cs42l52_dapm_widgets), 105862306a36Sopenharmony_ci .dapm_routes = cs42l52_audio_map, 105962306a36Sopenharmony_ci .num_dapm_routes = ARRAY_SIZE(cs42l52_audio_map), 106062306a36Sopenharmony_ci .suspend_bias_off = 1, 106162306a36Sopenharmony_ci .idle_bias_on = 1, 106262306a36Sopenharmony_ci .use_pmdown_time = 1, 106362306a36Sopenharmony_ci .endianness = 1, 106462306a36Sopenharmony_ci}; 106562306a36Sopenharmony_ci 106662306a36Sopenharmony_ci/* Current and threshold powerup sequence Pg37 */ 106762306a36Sopenharmony_cistatic const struct reg_sequence cs42l52_threshold_patch[] = { 106862306a36Sopenharmony_ci 106962306a36Sopenharmony_ci { 0x00, 0x99 }, 107062306a36Sopenharmony_ci { 0x3E, 0xBA }, 107162306a36Sopenharmony_ci { 0x47, 0x80 }, 107262306a36Sopenharmony_ci { 0x32, 0xBB }, 107362306a36Sopenharmony_ci { 0x32, 0x3B }, 107462306a36Sopenharmony_ci { 0x00, 0x00 }, 107562306a36Sopenharmony_ci 107662306a36Sopenharmony_ci}; 107762306a36Sopenharmony_ci 107862306a36Sopenharmony_cistatic const struct regmap_config cs42l52_regmap = { 107962306a36Sopenharmony_ci .reg_bits = 8, 108062306a36Sopenharmony_ci .val_bits = 8, 108162306a36Sopenharmony_ci 108262306a36Sopenharmony_ci .max_register = CS42L52_MAX_REGISTER, 108362306a36Sopenharmony_ci .reg_defaults = cs42l52_reg_defaults, 108462306a36Sopenharmony_ci .num_reg_defaults = ARRAY_SIZE(cs42l52_reg_defaults), 108562306a36Sopenharmony_ci .readable_reg = cs42l52_readable_register, 108662306a36Sopenharmony_ci .volatile_reg = cs42l52_volatile_register, 108762306a36Sopenharmony_ci .cache_type = REGCACHE_MAPLE, 108862306a36Sopenharmony_ci}; 108962306a36Sopenharmony_ci 109062306a36Sopenharmony_cistatic int cs42l52_i2c_probe(struct i2c_client *i2c_client) 109162306a36Sopenharmony_ci{ 109262306a36Sopenharmony_ci struct cs42l52_private *cs42l52; 109362306a36Sopenharmony_ci struct cs42l52_platform_data *pdata = dev_get_platdata(&i2c_client->dev); 109462306a36Sopenharmony_ci int ret; 109562306a36Sopenharmony_ci unsigned int devid; 109662306a36Sopenharmony_ci unsigned int reg; 109762306a36Sopenharmony_ci u32 val32; 109862306a36Sopenharmony_ci 109962306a36Sopenharmony_ci cs42l52 = devm_kzalloc(&i2c_client->dev, sizeof(*cs42l52), GFP_KERNEL); 110062306a36Sopenharmony_ci if (cs42l52 == NULL) 110162306a36Sopenharmony_ci return -ENOMEM; 110262306a36Sopenharmony_ci cs42l52->dev = &i2c_client->dev; 110362306a36Sopenharmony_ci 110462306a36Sopenharmony_ci cs42l52->regmap = devm_regmap_init_i2c(i2c_client, &cs42l52_regmap); 110562306a36Sopenharmony_ci if (IS_ERR(cs42l52->regmap)) { 110662306a36Sopenharmony_ci ret = PTR_ERR(cs42l52->regmap); 110762306a36Sopenharmony_ci dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret); 110862306a36Sopenharmony_ci return ret; 110962306a36Sopenharmony_ci } 111062306a36Sopenharmony_ci if (pdata) { 111162306a36Sopenharmony_ci cs42l52->pdata = *pdata; 111262306a36Sopenharmony_ci } else { 111362306a36Sopenharmony_ci pdata = devm_kzalloc(&i2c_client->dev, sizeof(*pdata), 111462306a36Sopenharmony_ci GFP_KERNEL); 111562306a36Sopenharmony_ci if (!pdata) 111662306a36Sopenharmony_ci return -ENOMEM; 111762306a36Sopenharmony_ci 111862306a36Sopenharmony_ci if (i2c_client->dev.of_node) { 111962306a36Sopenharmony_ci if (of_property_read_bool(i2c_client->dev.of_node, 112062306a36Sopenharmony_ci "cirrus,mica-differential-cfg")) 112162306a36Sopenharmony_ci pdata->mica_diff_cfg = true; 112262306a36Sopenharmony_ci 112362306a36Sopenharmony_ci if (of_property_read_bool(i2c_client->dev.of_node, 112462306a36Sopenharmony_ci "cirrus,micb-differential-cfg")) 112562306a36Sopenharmony_ci pdata->micb_diff_cfg = true; 112662306a36Sopenharmony_ci 112762306a36Sopenharmony_ci if (of_property_read_u32(i2c_client->dev.of_node, 112862306a36Sopenharmony_ci "cirrus,micbias-lvl", &val32) >= 0) 112962306a36Sopenharmony_ci pdata->micbias_lvl = val32; 113062306a36Sopenharmony_ci 113162306a36Sopenharmony_ci if (of_property_read_u32(i2c_client->dev.of_node, 113262306a36Sopenharmony_ci "cirrus,chgfreq-divisor", &val32) >= 0) 113362306a36Sopenharmony_ci pdata->chgfreq = val32; 113462306a36Sopenharmony_ci 113562306a36Sopenharmony_ci pdata->reset_gpio = 113662306a36Sopenharmony_ci of_get_named_gpio(i2c_client->dev.of_node, 113762306a36Sopenharmony_ci "cirrus,reset-gpio", 0); 113862306a36Sopenharmony_ci } 113962306a36Sopenharmony_ci cs42l52->pdata = *pdata; 114062306a36Sopenharmony_ci } 114162306a36Sopenharmony_ci 114262306a36Sopenharmony_ci if (cs42l52->pdata.reset_gpio) { 114362306a36Sopenharmony_ci ret = devm_gpio_request_one(&i2c_client->dev, 114462306a36Sopenharmony_ci cs42l52->pdata.reset_gpio, 114562306a36Sopenharmony_ci GPIOF_OUT_INIT_HIGH, 114662306a36Sopenharmony_ci "CS42L52 /RST"); 114762306a36Sopenharmony_ci if (ret < 0) { 114862306a36Sopenharmony_ci dev_err(&i2c_client->dev, "Failed to request /RST %d: %d\n", 114962306a36Sopenharmony_ci cs42l52->pdata.reset_gpio, ret); 115062306a36Sopenharmony_ci return ret; 115162306a36Sopenharmony_ci } 115262306a36Sopenharmony_ci gpio_set_value_cansleep(cs42l52->pdata.reset_gpio, 0); 115362306a36Sopenharmony_ci gpio_set_value_cansleep(cs42l52->pdata.reset_gpio, 1); 115462306a36Sopenharmony_ci } 115562306a36Sopenharmony_ci 115662306a36Sopenharmony_ci i2c_set_clientdata(i2c_client, cs42l52); 115762306a36Sopenharmony_ci 115862306a36Sopenharmony_ci ret = regmap_register_patch(cs42l52->regmap, cs42l52_threshold_patch, 115962306a36Sopenharmony_ci ARRAY_SIZE(cs42l52_threshold_patch)); 116062306a36Sopenharmony_ci if (ret != 0) 116162306a36Sopenharmony_ci dev_warn(cs42l52->dev, "Failed to apply regmap patch: %d\n", 116262306a36Sopenharmony_ci ret); 116362306a36Sopenharmony_ci 116462306a36Sopenharmony_ci ret = regmap_read(cs42l52->regmap, CS42L52_CHIP, ®); 116562306a36Sopenharmony_ci if (ret) { 116662306a36Sopenharmony_ci dev_err(&i2c_client->dev, "Failed to read chip ID: %d\n", ret); 116762306a36Sopenharmony_ci return ret; 116862306a36Sopenharmony_ci } 116962306a36Sopenharmony_ci 117062306a36Sopenharmony_ci devid = reg & CS42L52_CHIP_ID_MASK; 117162306a36Sopenharmony_ci if (devid != CS42L52_CHIP_ID) { 117262306a36Sopenharmony_ci ret = -ENODEV; 117362306a36Sopenharmony_ci dev_err(&i2c_client->dev, 117462306a36Sopenharmony_ci "CS42L52 Device ID (%X). Expected %X\n", 117562306a36Sopenharmony_ci devid, CS42L52_CHIP_ID); 117662306a36Sopenharmony_ci return ret; 117762306a36Sopenharmony_ci } 117862306a36Sopenharmony_ci 117962306a36Sopenharmony_ci dev_info(&i2c_client->dev, "Cirrus Logic CS42L52, Revision: %02X\n", 118062306a36Sopenharmony_ci reg & CS42L52_CHIP_REV_MASK); 118162306a36Sopenharmony_ci 118262306a36Sopenharmony_ci /* Set Platform Data */ 118362306a36Sopenharmony_ci if (cs42l52->pdata.mica_diff_cfg) 118462306a36Sopenharmony_ci regmap_update_bits(cs42l52->regmap, CS42L52_MICA_CTL, 118562306a36Sopenharmony_ci CS42L52_MIC_CTL_TYPE_MASK, 118662306a36Sopenharmony_ci cs42l52->pdata.mica_diff_cfg << 118762306a36Sopenharmony_ci CS42L52_MIC_CTL_TYPE_SHIFT); 118862306a36Sopenharmony_ci 118962306a36Sopenharmony_ci if (cs42l52->pdata.micb_diff_cfg) 119062306a36Sopenharmony_ci regmap_update_bits(cs42l52->regmap, CS42L52_MICB_CTL, 119162306a36Sopenharmony_ci CS42L52_MIC_CTL_TYPE_MASK, 119262306a36Sopenharmony_ci cs42l52->pdata.micb_diff_cfg << 119362306a36Sopenharmony_ci CS42L52_MIC_CTL_TYPE_SHIFT); 119462306a36Sopenharmony_ci 119562306a36Sopenharmony_ci if (cs42l52->pdata.chgfreq) 119662306a36Sopenharmony_ci regmap_update_bits(cs42l52->regmap, CS42L52_CHARGE_PUMP, 119762306a36Sopenharmony_ci CS42L52_CHARGE_PUMP_MASK, 119862306a36Sopenharmony_ci cs42l52->pdata.chgfreq << 119962306a36Sopenharmony_ci CS42L52_CHARGE_PUMP_SHIFT); 120062306a36Sopenharmony_ci 120162306a36Sopenharmony_ci if (cs42l52->pdata.micbias_lvl) 120262306a36Sopenharmony_ci regmap_update_bits(cs42l52->regmap, CS42L52_IFACE_CTL2, 120362306a36Sopenharmony_ci CS42L52_IFACE_CTL2_BIAS_LVL, 120462306a36Sopenharmony_ci cs42l52->pdata.micbias_lvl); 120562306a36Sopenharmony_ci 120662306a36Sopenharmony_ci return devm_snd_soc_register_component(&i2c_client->dev, 120762306a36Sopenharmony_ci &soc_component_dev_cs42l52, &cs42l52_dai, 1); 120862306a36Sopenharmony_ci} 120962306a36Sopenharmony_ci 121062306a36Sopenharmony_cistatic const struct of_device_id cs42l52_of_match[] = { 121162306a36Sopenharmony_ci { .compatible = "cirrus,cs42l52", }, 121262306a36Sopenharmony_ci {}, 121362306a36Sopenharmony_ci}; 121462306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, cs42l52_of_match); 121562306a36Sopenharmony_ci 121662306a36Sopenharmony_ci 121762306a36Sopenharmony_cistatic const struct i2c_device_id cs42l52_id[] = { 121862306a36Sopenharmony_ci { "cs42l52", 0 }, 121962306a36Sopenharmony_ci { } 122062306a36Sopenharmony_ci}; 122162306a36Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, cs42l52_id); 122262306a36Sopenharmony_ci 122362306a36Sopenharmony_cistatic struct i2c_driver cs42l52_i2c_driver = { 122462306a36Sopenharmony_ci .driver = { 122562306a36Sopenharmony_ci .name = "cs42l52", 122662306a36Sopenharmony_ci .of_match_table = cs42l52_of_match, 122762306a36Sopenharmony_ci }, 122862306a36Sopenharmony_ci .id_table = cs42l52_id, 122962306a36Sopenharmony_ci .probe = cs42l52_i2c_probe, 123062306a36Sopenharmony_ci}; 123162306a36Sopenharmony_ci 123262306a36Sopenharmony_cimodule_i2c_driver(cs42l52_i2c_driver); 123362306a36Sopenharmony_ci 123462306a36Sopenharmony_ciMODULE_DESCRIPTION("ASoC CS42L52 driver"); 123562306a36Sopenharmony_ciMODULE_AUTHOR("Georgi Vlaev, Nucleus Systems Ltd, <joe@nucleusys.com>"); 123662306a36Sopenharmony_ciMODULE_AUTHOR("Brian Austin, Cirrus Logic Inc, <brian.austin@cirrus.com>"); 123762306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 1238