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, &reg);
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