brintos

brintos / linux-shallow public Read only

0
0
Text · 33.4 KiB · 28f4be3 Raw
1110 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * cs53l30.c  --  CS53l30 ALSA Soc Audio driver4 *5 * Copyright 2015 Cirrus Logic, Inc.6 *7 * Authors: Paul Handrigan <Paul.Handrigan@cirrus.com>,8 *          Tim Howe <Tim.Howe@cirrus.com>9 */10 11#include <linux/clk.h>12#include <linux/delay.h>13#include <linux/i2c.h>14#include <linux/module.h>15#include <linux/gpio/consumer.h>16#include <linux/regulator/consumer.h>17#include <sound/pcm_params.h>18#include <sound/soc.h>19#include <sound/tlv.h>20 21#include "cs53l30.h"22#include "cirrus_legacy.h"23 24#define CS53L30_NUM_SUPPLIES 225static const char *const cs53l30_supply_names[CS53L30_NUM_SUPPLIES] = {26	"VA",27	"VP",28};29 30struct cs53l30_private {31	struct regulator_bulk_data	supplies[CS53L30_NUM_SUPPLIES];32	struct regmap			*regmap;33	struct gpio_desc		*reset_gpio;34	struct gpio_desc		*mute_gpio;35	struct clk			*mclk;36	bool				use_sdout2;37	u32				mclk_rate;38};39 40static const struct reg_default cs53l30_reg_defaults[] = {41	{ CS53L30_PWRCTL,		CS53L30_PWRCTL_DEFAULT },42	{ CS53L30_MCLKCTL,		CS53L30_MCLKCTL_DEFAULT },43	{ CS53L30_INT_SR_CTL,		CS53L30_INT_SR_CTL_DEFAULT },44	{ CS53L30_MICBIAS_CTL,		CS53L30_MICBIAS_CTL_DEFAULT },45	{ CS53L30_ASPCFG_CTL,		CS53L30_ASPCFG_CTL_DEFAULT },46	{ CS53L30_ASP_CTL1,		CS53L30_ASP_CTL1_DEFAULT },47	{ CS53L30_ASP_TDMTX_CTL1,	CS53L30_ASP_TDMTX_CTLx_DEFAULT },48	{ CS53L30_ASP_TDMTX_CTL2,	CS53L30_ASP_TDMTX_CTLx_DEFAULT },49	{ CS53L30_ASP_TDMTX_CTL3,	CS53L30_ASP_TDMTX_CTLx_DEFAULT },50	{ CS53L30_ASP_TDMTX_CTL4,	CS53L30_ASP_TDMTX_CTLx_DEFAULT },51	{ CS53L30_ASP_TDMTX_EN1,	CS53L30_ASP_TDMTX_ENx_DEFAULT },52	{ CS53L30_ASP_TDMTX_EN2,	CS53L30_ASP_TDMTX_ENx_DEFAULT },53	{ CS53L30_ASP_TDMTX_EN3,	CS53L30_ASP_TDMTX_ENx_DEFAULT },54	{ CS53L30_ASP_TDMTX_EN4,	CS53L30_ASP_TDMTX_ENx_DEFAULT },55	{ CS53L30_ASP_TDMTX_EN5,	CS53L30_ASP_TDMTX_ENx_DEFAULT },56	{ CS53L30_ASP_TDMTX_EN6,	CS53L30_ASP_TDMTX_ENx_DEFAULT },57	{ CS53L30_ASP_CTL2,		CS53L30_ASP_CTL2_DEFAULT },58	{ CS53L30_SFT_RAMP,		CS53L30_SFT_RMP_DEFAULT },59	{ CS53L30_LRCK_CTL1,		CS53L30_LRCK_CTLx_DEFAULT },60	{ CS53L30_LRCK_CTL2,		CS53L30_LRCK_CTLx_DEFAULT },61	{ CS53L30_MUTEP_CTL1,		CS53L30_MUTEP_CTL1_DEFAULT },62	{ CS53L30_MUTEP_CTL2,		CS53L30_MUTEP_CTL2_DEFAULT },63	{ CS53L30_INBIAS_CTL1,		CS53L30_INBIAS_CTL1_DEFAULT },64	{ CS53L30_INBIAS_CTL2,		CS53L30_INBIAS_CTL2_DEFAULT },65	{ CS53L30_DMIC1_STR_CTL,	CS53L30_DMIC1_STR_CTL_DEFAULT },66	{ CS53L30_DMIC2_STR_CTL,	CS53L30_DMIC2_STR_CTL_DEFAULT },67	{ CS53L30_ADCDMIC1_CTL1,	CS53L30_ADCDMICx_CTL1_DEFAULT },68	{ CS53L30_ADCDMIC1_CTL2,	CS53L30_ADCDMIC1_CTL2_DEFAULT },69	{ CS53L30_ADC1_CTL3,		CS53L30_ADCx_CTL3_DEFAULT },70	{ CS53L30_ADC1_NG_CTL,		CS53L30_ADCx_NG_CTL_DEFAULT },71	{ CS53L30_ADC1A_AFE_CTL,	CS53L30_ADCxy_AFE_CTL_DEFAULT },72	{ CS53L30_ADC1B_AFE_CTL,	CS53L30_ADCxy_AFE_CTL_DEFAULT },73	{ CS53L30_ADC1A_DIG_VOL,	CS53L30_ADCxy_DIG_VOL_DEFAULT },74	{ CS53L30_ADC1B_DIG_VOL,	CS53L30_ADCxy_DIG_VOL_DEFAULT },75	{ CS53L30_ADCDMIC2_CTL1,	CS53L30_ADCDMICx_CTL1_DEFAULT },76	{ CS53L30_ADCDMIC2_CTL2,	CS53L30_ADCDMIC1_CTL2_DEFAULT },77	{ CS53L30_ADC2_CTL3,		CS53L30_ADCx_CTL3_DEFAULT },78	{ CS53L30_ADC2_NG_CTL,		CS53L30_ADCx_NG_CTL_DEFAULT },79	{ CS53L30_ADC2A_AFE_CTL,	CS53L30_ADCxy_AFE_CTL_DEFAULT },80	{ CS53L30_ADC2B_AFE_CTL,	CS53L30_ADCxy_AFE_CTL_DEFAULT },81	{ CS53L30_ADC2A_DIG_VOL,	CS53L30_ADCxy_DIG_VOL_DEFAULT },82	{ CS53L30_ADC2B_DIG_VOL,	CS53L30_ADCxy_DIG_VOL_DEFAULT },83	{ CS53L30_INT_MASK,		CS53L30_DEVICE_INT_MASK },84};85 86static bool cs53l30_volatile_register(struct device *dev, unsigned int reg)87{88	if (reg == CS53L30_IS)89		return true;90	else91		return false;92}93 94static bool cs53l30_writeable_register(struct device *dev, unsigned int reg)95{96	switch (reg) {97	case CS53L30_DEVID_AB:98	case CS53L30_DEVID_CD:99	case CS53L30_DEVID_E:100	case CS53L30_REVID:101	case CS53L30_IS:102		return false;103	default:104		return true;105	}106}107 108static bool cs53l30_readable_register(struct device *dev, unsigned int reg)109{110	switch (reg) {111	case CS53L30_DEVID_AB:112	case CS53L30_DEVID_CD:113	case CS53L30_DEVID_E:114	case CS53L30_REVID:115	case CS53L30_PWRCTL:116	case CS53L30_MCLKCTL:117	case CS53L30_INT_SR_CTL:118	case CS53L30_MICBIAS_CTL:119	case CS53L30_ASPCFG_CTL:120	case CS53L30_ASP_CTL1:121	case CS53L30_ASP_TDMTX_CTL1:122	case CS53L30_ASP_TDMTX_CTL2:123	case CS53L30_ASP_TDMTX_CTL3:124	case CS53L30_ASP_TDMTX_CTL4:125	case CS53L30_ASP_TDMTX_EN1:126	case CS53L30_ASP_TDMTX_EN2:127	case CS53L30_ASP_TDMTX_EN3:128	case CS53L30_ASP_TDMTX_EN4:129	case CS53L30_ASP_TDMTX_EN5:130	case CS53L30_ASP_TDMTX_EN6:131	case CS53L30_ASP_CTL2:132	case CS53L30_SFT_RAMP:133	case CS53L30_LRCK_CTL1:134	case CS53L30_LRCK_CTL2:135	case CS53L30_MUTEP_CTL1:136	case CS53L30_MUTEP_CTL2:137	case CS53L30_INBIAS_CTL1:138	case CS53L30_INBIAS_CTL2:139	case CS53L30_DMIC1_STR_CTL:140	case CS53L30_DMIC2_STR_CTL:141	case CS53L30_ADCDMIC1_CTL1:142	case CS53L30_ADCDMIC1_CTL2:143	case CS53L30_ADC1_CTL3:144	case CS53L30_ADC1_NG_CTL:145	case CS53L30_ADC1A_AFE_CTL:146	case CS53L30_ADC1B_AFE_CTL:147	case CS53L30_ADC1A_DIG_VOL:148	case CS53L30_ADC1B_DIG_VOL:149	case CS53L30_ADCDMIC2_CTL1:150	case CS53L30_ADCDMIC2_CTL2:151	case CS53L30_ADC2_CTL3:152	case CS53L30_ADC2_NG_CTL:153	case CS53L30_ADC2A_AFE_CTL:154	case CS53L30_ADC2B_AFE_CTL:155	case CS53L30_ADC2A_DIG_VOL:156	case CS53L30_ADC2B_DIG_VOL:157	case CS53L30_INT_MASK:158		return true;159	default:160		return false;161	}162}163 164static DECLARE_TLV_DB_SCALE(adc_boost_tlv, 0, 2000, 0);165static DECLARE_TLV_DB_SCALE(adc_ng_boost_tlv, 0, 3000, 0);166static DECLARE_TLV_DB_SCALE(pga_tlv, -600, 50, 0);167static DECLARE_TLV_DB_SCALE(dig_tlv, -9600, 100, 1);168static DECLARE_TLV_DB_SCALE(pga_preamp_tlv, 0, 10000, 0);169 170static const char * const input1_sel_text[] = {171	"DMIC1 On AB In",172	"DMIC1 On A In",173	"DMIC1 On B In",174	"ADC1 On AB In",175	"ADC1 On A In",176	"ADC1 On B In",177	"DMIC1 Off ADC1 Off",178};179 180static unsigned int const input1_sel_values[] = {181	CS53L30_CH_TYPE,182	CS53L30_ADCxB_PDN | CS53L30_CH_TYPE,183	CS53L30_ADCxA_PDN | CS53L30_CH_TYPE,184	CS53L30_DMICx_PDN,185	CS53L30_ADCxB_PDN | CS53L30_DMICx_PDN,186	CS53L30_ADCxA_PDN | CS53L30_DMICx_PDN,187	CS53L30_ADCxA_PDN | CS53L30_ADCxB_PDN | CS53L30_DMICx_PDN,188};189 190static const char * const input2_sel_text[] = {191	"DMIC2 On AB In",192	"DMIC2 On A In",193	"DMIC2 On B In",194	"ADC2 On AB In",195	"ADC2 On A In",196	"ADC2 On B In",197	"DMIC2 Off ADC2 Off",198};199 200static unsigned int const input2_sel_values[] = {201	0x0,202	CS53L30_ADCxB_PDN,203	CS53L30_ADCxA_PDN,204	CS53L30_DMICx_PDN,205	CS53L30_ADCxB_PDN | CS53L30_DMICx_PDN,206	CS53L30_ADCxA_PDN | CS53L30_DMICx_PDN,207	CS53L30_ADCxA_PDN | CS53L30_ADCxB_PDN | CS53L30_DMICx_PDN,208};209 210static const char * const input1_route_sel_text[] = {211	"ADC1_SEL", "DMIC1_SEL",212};213 214static const struct soc_enum input1_route_sel_enum =215	SOC_ENUM_SINGLE(CS53L30_ADCDMIC1_CTL1, CS53L30_CH_TYPE_SHIFT,216			ARRAY_SIZE(input1_route_sel_text),217			input1_route_sel_text);218 219static SOC_VALUE_ENUM_SINGLE_DECL(input1_sel_enum, CS53L30_ADCDMIC1_CTL1, 0,220				  CS53L30_ADCDMICx_PDN_MASK, input1_sel_text,221				  input1_sel_values);222 223static const struct snd_kcontrol_new input1_route_sel_mux =224	SOC_DAPM_ENUM("Input 1 Route", input1_route_sel_enum);225 226static const char * const input2_route_sel_text[] = {227	"ADC2_SEL", "DMIC2_SEL",228};229 230/* Note: CS53L30_ADCDMIC1_CTL1 CH_TYPE controls inputs 1 and 2 */231static const struct soc_enum input2_route_sel_enum =232	SOC_ENUM_SINGLE(CS53L30_ADCDMIC1_CTL1, 0,233			ARRAY_SIZE(input2_route_sel_text),234			input2_route_sel_text);235 236static SOC_VALUE_ENUM_SINGLE_DECL(input2_sel_enum, CS53L30_ADCDMIC2_CTL1, 0,237				  CS53L30_ADCDMICx_PDN_MASK, input2_sel_text,238				  input2_sel_values);239 240static const struct snd_kcontrol_new input2_route_sel_mux =241	SOC_DAPM_ENUM("Input 2 Route", input2_route_sel_enum);242 243/*244 * TB = 6144*(MCLK(int) scaling factor)/MCLK(internal)245 * TB - Time base246 * NOTE: If MCLK_INT_SCALE = 0, then TB=1247 */248static const char * const cs53l30_ng_delay_text[] = {249	"TB*50ms", "TB*100ms", "TB*150ms", "TB*200ms",250};251 252static const struct soc_enum adc1_ng_delay_enum =253	SOC_ENUM_SINGLE(CS53L30_ADC1_NG_CTL, CS53L30_ADCx_NG_DELAY_SHIFT,254			ARRAY_SIZE(cs53l30_ng_delay_text),255			cs53l30_ng_delay_text);256 257static const struct soc_enum adc2_ng_delay_enum =258	SOC_ENUM_SINGLE(CS53L30_ADC2_NG_CTL, CS53L30_ADCx_NG_DELAY_SHIFT,259			ARRAY_SIZE(cs53l30_ng_delay_text),260			cs53l30_ng_delay_text);261 262/* The noise gate threshold selected will depend on NG Boost */263static const char * const cs53l30_ng_thres_text[] = {264	"-64dB/-34dB", "-66dB/-36dB", "-70dB/-40dB", "-73dB/-43dB",265	"-76dB/-46dB", "-82dB/-52dB", "-58dB", "-64dB",266};267 268static const struct soc_enum adc1_ng_thres_enum =269	SOC_ENUM_SINGLE(CS53L30_ADC1_NG_CTL, CS53L30_ADCx_NG_THRESH_SHIFT,270			ARRAY_SIZE(cs53l30_ng_thres_text),271			cs53l30_ng_thres_text);272 273static const struct soc_enum adc2_ng_thres_enum =274	SOC_ENUM_SINGLE(CS53L30_ADC2_NG_CTL, CS53L30_ADCx_NG_THRESH_SHIFT,275			ARRAY_SIZE(cs53l30_ng_thres_text),276			cs53l30_ng_thres_text);277 278/* Corner frequencies are with an Fs of 48kHz. */279static const char * const hpf_corner_freq_text[] = {280	"1.86Hz", "120Hz", "235Hz", "466Hz",281};282 283static const struct soc_enum adc1_hpf_enum =284	SOC_ENUM_SINGLE(CS53L30_ADC1_CTL3, CS53L30_ADCx_HPF_CF_SHIFT,285			ARRAY_SIZE(hpf_corner_freq_text), hpf_corner_freq_text);286 287static const struct soc_enum adc2_hpf_enum =288	SOC_ENUM_SINGLE(CS53L30_ADC2_CTL3, CS53L30_ADCx_HPF_CF_SHIFT,289			ARRAY_SIZE(hpf_corner_freq_text), hpf_corner_freq_text);290 291static const struct snd_kcontrol_new cs53l30_snd_controls[] = {292	SOC_SINGLE("Digital Soft-Ramp Switch", CS53L30_SFT_RAMP,293		   CS53L30_DIGSFT_SHIFT, 1, 0),294	SOC_SINGLE("ADC1 Noise Gate Ganging Switch", CS53L30_ADC1_CTL3,295		   CS53L30_ADCx_NG_ALL_SHIFT, 1, 0),296	SOC_SINGLE("ADC2 Noise Gate Ganging Switch", CS53L30_ADC2_CTL3,297		   CS53L30_ADCx_NG_ALL_SHIFT, 1, 0),298	SOC_SINGLE("ADC1A Noise Gate Enable Switch", CS53L30_ADC1_NG_CTL,299		   CS53L30_ADCxA_NG_SHIFT, 1, 0),300	SOC_SINGLE("ADC1B Noise Gate Enable Switch", CS53L30_ADC1_NG_CTL,301		   CS53L30_ADCxB_NG_SHIFT, 1, 0),302	SOC_SINGLE("ADC2A Noise Gate Enable Switch", CS53L30_ADC2_NG_CTL,303		   CS53L30_ADCxA_NG_SHIFT, 1, 0),304	SOC_SINGLE("ADC2B Noise Gate Enable Switch", CS53L30_ADC2_NG_CTL,305		   CS53L30_ADCxB_NG_SHIFT, 1, 0),306	SOC_SINGLE("ADC1 Notch Filter Switch", CS53L30_ADCDMIC1_CTL2,307		   CS53L30_ADCx_NOTCH_DIS_SHIFT, 1, 1),308	SOC_SINGLE("ADC2 Notch Filter Switch", CS53L30_ADCDMIC2_CTL2,309		   CS53L30_ADCx_NOTCH_DIS_SHIFT, 1, 1),310	SOC_SINGLE("ADC1A Invert Switch", CS53L30_ADCDMIC1_CTL2,311		   CS53L30_ADCxA_INV_SHIFT, 1, 0),312	SOC_SINGLE("ADC1B Invert Switch", CS53L30_ADCDMIC1_CTL2,313		   CS53L30_ADCxB_INV_SHIFT, 1, 0),314	SOC_SINGLE("ADC2A Invert Switch", CS53L30_ADCDMIC2_CTL2,315		   CS53L30_ADCxA_INV_SHIFT, 1, 0),316	SOC_SINGLE("ADC2B Invert Switch", CS53L30_ADCDMIC2_CTL2,317		   CS53L30_ADCxB_INV_SHIFT, 1, 0),318 319	SOC_SINGLE_TLV("ADC1A Digital Boost Volume", CS53L30_ADCDMIC1_CTL2,320		       CS53L30_ADCxA_DIG_BOOST_SHIFT, 1, 0, adc_boost_tlv),321	SOC_SINGLE_TLV("ADC1B Digital Boost Volume", CS53L30_ADCDMIC1_CTL2,322		       CS53L30_ADCxB_DIG_BOOST_SHIFT, 1, 0, adc_boost_tlv),323	SOC_SINGLE_TLV("ADC2A Digital Boost Volume", CS53L30_ADCDMIC2_CTL2,324		       CS53L30_ADCxA_DIG_BOOST_SHIFT, 1, 0, adc_boost_tlv),325	SOC_SINGLE_TLV("ADC2B Digital Boost Volume", CS53L30_ADCDMIC2_CTL2,326		       CS53L30_ADCxB_DIG_BOOST_SHIFT, 1, 0, adc_boost_tlv),327	SOC_SINGLE_TLV("ADC1 NG Boost Volume", CS53L30_ADC1_NG_CTL,328		       CS53L30_ADCx_NG_BOOST_SHIFT, 1, 0, adc_ng_boost_tlv),329	SOC_SINGLE_TLV("ADC2 NG Boost Volume", CS53L30_ADC2_NG_CTL,330		       CS53L30_ADCx_NG_BOOST_SHIFT, 1, 0, adc_ng_boost_tlv),331 332	SOC_DOUBLE_R_TLV("ADC1 Preamplifier Volume", CS53L30_ADC1A_AFE_CTL,333			 CS53L30_ADC1B_AFE_CTL, CS53L30_ADCxy_PREAMP_SHIFT,334			 2, 0, pga_preamp_tlv),335	SOC_DOUBLE_R_TLV("ADC2 Preamplifier Volume", CS53L30_ADC2A_AFE_CTL,336			 CS53L30_ADC2B_AFE_CTL, CS53L30_ADCxy_PREAMP_SHIFT,337			 2, 0, pga_preamp_tlv),338 339	SOC_ENUM("Input 1 Channel Select", input1_sel_enum),340	SOC_ENUM("Input 2 Channel Select", input2_sel_enum),341 342	SOC_ENUM("ADC1 HPF Select", adc1_hpf_enum),343	SOC_ENUM("ADC2 HPF Select", adc2_hpf_enum),344	SOC_ENUM("ADC1 NG Threshold", adc1_ng_thres_enum),345	SOC_ENUM("ADC2 NG Threshold", adc2_ng_thres_enum),346	SOC_ENUM("ADC1 NG Delay", adc1_ng_delay_enum),347	SOC_ENUM("ADC2 NG Delay", adc2_ng_delay_enum),348 349	SOC_SINGLE_SX_TLV("ADC1A PGA Volume",350		    CS53L30_ADC1A_AFE_CTL, 0, 0x34, 0x24, pga_tlv),351	SOC_SINGLE_SX_TLV("ADC1B PGA Volume",352		    CS53L30_ADC1B_AFE_CTL, 0, 0x34, 0x24, pga_tlv),353	SOC_SINGLE_SX_TLV("ADC2A PGA Volume",354		    CS53L30_ADC2A_AFE_CTL, 0, 0x34, 0x24, pga_tlv),355	SOC_SINGLE_SX_TLV("ADC2B PGA Volume",356		    CS53L30_ADC2B_AFE_CTL, 0, 0x34, 0x24, pga_tlv),357 358	SOC_SINGLE_SX_TLV("ADC1A Digital Volume",359		    CS53L30_ADC1A_DIG_VOL, 0, 0xA0, 0x6C, dig_tlv),360	SOC_SINGLE_SX_TLV("ADC1B Digital Volume",361		    CS53L30_ADC1B_DIG_VOL, 0, 0xA0, 0x6C, dig_tlv),362	SOC_SINGLE_SX_TLV("ADC2A Digital Volume",363		    CS53L30_ADC2A_DIG_VOL, 0, 0xA0, 0x6C, dig_tlv),364	SOC_SINGLE_SX_TLV("ADC2B Digital Volume",365		    CS53L30_ADC2B_DIG_VOL, 0, 0xA0, 0x6C, dig_tlv),366};367 368static const struct snd_soc_dapm_widget cs53l30_dapm_widgets[] = {369	SND_SOC_DAPM_INPUT("IN1_DMIC1"),370	SND_SOC_DAPM_INPUT("IN2"),371	SND_SOC_DAPM_INPUT("IN3_DMIC2"),372	SND_SOC_DAPM_INPUT("IN4"),373	SND_SOC_DAPM_SUPPLY("MIC1 Bias", CS53L30_MICBIAS_CTL,374			    CS53L30_MIC1_BIAS_PDN_SHIFT, 1, NULL, 0),375	SND_SOC_DAPM_SUPPLY("MIC2 Bias", CS53L30_MICBIAS_CTL,376			    CS53L30_MIC2_BIAS_PDN_SHIFT, 1, NULL, 0),377	SND_SOC_DAPM_SUPPLY("MIC3 Bias", CS53L30_MICBIAS_CTL,378			    CS53L30_MIC3_BIAS_PDN_SHIFT, 1, NULL, 0),379	SND_SOC_DAPM_SUPPLY("MIC4 Bias", CS53L30_MICBIAS_CTL,380			    CS53L30_MIC4_BIAS_PDN_SHIFT, 1, NULL, 0),381 382	SND_SOC_DAPM_AIF_OUT("ASP_SDOUT1", NULL, 0, CS53L30_ASP_CTL1,383			     CS53L30_ASP_SDOUTx_PDN_SHIFT, 1),384	SND_SOC_DAPM_AIF_OUT("ASP_SDOUT2", NULL, 0, CS53L30_ASP_CTL2,385			     CS53L30_ASP_SDOUTx_PDN_SHIFT, 1),386 387	SND_SOC_DAPM_MUX("Input Mux 1", SND_SOC_NOPM, 0, 0,388			 &input1_route_sel_mux),389	SND_SOC_DAPM_MUX("Input Mux 2", SND_SOC_NOPM, 0, 0,390			 &input2_route_sel_mux),391 392	SND_SOC_DAPM_ADC("ADC1A", NULL, CS53L30_ADCDMIC1_CTL1,393			 CS53L30_ADCxA_PDN_SHIFT, 1),394	SND_SOC_DAPM_ADC("ADC1B", NULL, CS53L30_ADCDMIC1_CTL1,395			 CS53L30_ADCxB_PDN_SHIFT, 1),396	SND_SOC_DAPM_ADC("ADC2A", NULL, CS53L30_ADCDMIC2_CTL1,397			 CS53L30_ADCxA_PDN_SHIFT, 1),398	SND_SOC_DAPM_ADC("ADC2B", NULL, CS53L30_ADCDMIC2_CTL1,399			 CS53L30_ADCxB_PDN_SHIFT, 1),400	SND_SOC_DAPM_ADC("DMIC1", NULL, CS53L30_ADCDMIC1_CTL1,401			 CS53L30_DMICx_PDN_SHIFT, 1),402	SND_SOC_DAPM_ADC("DMIC2", NULL, CS53L30_ADCDMIC2_CTL1,403			 CS53L30_DMICx_PDN_SHIFT, 1),404};405 406static const struct snd_soc_dapm_route cs53l30_dapm_routes[] = {407	/* ADC Input Paths */408	{"ADC1A", NULL, "IN1_DMIC1"},409	{"Input Mux 1", "ADC1_SEL", "ADC1A"},410	{"ADC1B", NULL, "IN2"},411 412	{"ADC2A", NULL, "IN3_DMIC2"},413	{"Input Mux 2", "ADC2_SEL", "ADC2A"},414	{"ADC2B", NULL, "IN4"},415 416	/* MIC Bias Paths */417	{"ADC1A", NULL, "MIC1 Bias"},418	{"ADC1B", NULL, "MIC2 Bias"},419	{"ADC2A", NULL, "MIC3 Bias"},420	{"ADC2B", NULL, "MIC4 Bias"},421 422	/* DMIC Paths */423	{"DMIC1", NULL, "IN1_DMIC1"},424	{"Input Mux 1", "DMIC1_SEL", "DMIC1"},425 426	{"DMIC2", NULL, "IN3_DMIC2"},427	{"Input Mux 2", "DMIC2_SEL", "DMIC2"},428};429 430static const struct snd_soc_dapm_route cs53l30_dapm_routes_sdout1[] = {431	/* Output Paths when using SDOUT1 only */432	{"ASP_SDOUT1", NULL, "ADC1A" },433	{"ASP_SDOUT1", NULL, "Input Mux 1"},434	{"ASP_SDOUT1", NULL, "ADC1B"},435 436	{"ASP_SDOUT1", NULL, "ADC2A"},437	{"ASP_SDOUT1", NULL, "Input Mux 2"},438	{"ASP_SDOUT1", NULL, "ADC2B"},439 440	{"Capture", NULL, "ASP_SDOUT1"},441};442 443static const struct snd_soc_dapm_route cs53l30_dapm_routes_sdout2[] = {444	/* Output Paths when using both SDOUT1 and SDOUT2 */445	{"ASP_SDOUT1", NULL, "ADC1A" },446	{"ASP_SDOUT1", NULL, "Input Mux 1"},447	{"ASP_SDOUT1", NULL, "ADC1B"},448 449	{"ASP_SDOUT2", NULL, "ADC2A"},450	{"ASP_SDOUT2", NULL, "Input Mux 2"},451	{"ASP_SDOUT2", NULL, "ADC2B"},452 453	{"Capture", NULL, "ASP_SDOUT1"},454	{"Capture", NULL, "ASP_SDOUT2"},455};456 457struct cs53l30_mclk_div {458	u32 mclk_rate;459	u32 srate;460	u8 asp_rate;461	u8 internal_fs_ratio;462	u8 mclk_int_scale;463};464 465static const struct cs53l30_mclk_div cs53l30_mclk_coeffs[] = {466	/* NOTE: Enable MCLK_INT_SCALE to save power. */467 468	/* MCLK, Sample Rate, asp_rate, internal_fs_ratio, mclk_int_scale */469	{5644800, 11025, 0x4, CS53L30_INTRNL_FS_RATIO, CS53L30_MCLK_INT_SCALE},470	{5644800, 22050, 0x8, CS53L30_INTRNL_FS_RATIO, CS53L30_MCLK_INT_SCALE},471	{5644800, 44100, 0xC, CS53L30_INTRNL_FS_RATIO, CS53L30_MCLK_INT_SCALE},472 473	{6000000,  8000, 0x1, 0, CS53L30_MCLK_INT_SCALE},474	{6000000, 11025, 0x2, 0, CS53L30_MCLK_INT_SCALE},475	{6000000, 12000, 0x4, 0, CS53L30_MCLK_INT_SCALE},476	{6000000, 16000, 0x5, 0, CS53L30_MCLK_INT_SCALE},477	{6000000, 22050, 0x6, 0, CS53L30_MCLK_INT_SCALE},478	{6000000, 24000, 0x8, 0, CS53L30_MCLK_INT_SCALE},479	{6000000, 32000, 0x9, 0, CS53L30_MCLK_INT_SCALE},480	{6000000, 44100, 0xA, 0, CS53L30_MCLK_INT_SCALE},481	{6000000, 48000, 0xC, 0, CS53L30_MCLK_INT_SCALE},482 483	{6144000,  8000, 0x1, CS53L30_INTRNL_FS_RATIO, CS53L30_MCLK_INT_SCALE},484	{6144000, 11025, 0x2, CS53L30_INTRNL_FS_RATIO, CS53L30_MCLK_INT_SCALE},485	{6144000, 12000, 0x4, CS53L30_INTRNL_FS_RATIO, CS53L30_MCLK_INT_SCALE},486	{6144000, 16000, 0x5, CS53L30_INTRNL_FS_RATIO, CS53L30_MCLK_INT_SCALE},487	{6144000, 22050, 0x6, CS53L30_INTRNL_FS_RATIO, CS53L30_MCLK_INT_SCALE},488	{6144000, 24000, 0x8, CS53L30_INTRNL_FS_RATIO, CS53L30_MCLK_INT_SCALE},489	{6144000, 32000, 0x9, CS53L30_INTRNL_FS_RATIO, CS53L30_MCLK_INT_SCALE},490	{6144000, 44100, 0xA, CS53L30_INTRNL_FS_RATIO, CS53L30_MCLK_INT_SCALE},491	{6144000, 48000, 0xC, CS53L30_INTRNL_FS_RATIO, CS53L30_MCLK_INT_SCALE},492 493	{6400000,  8000, 0x1, CS53L30_INTRNL_FS_RATIO, CS53L30_MCLK_INT_SCALE},494	{6400000, 11025, 0x2, CS53L30_INTRNL_FS_RATIO, CS53L30_MCLK_INT_SCALE},495	{6400000, 12000, 0x4, CS53L30_INTRNL_FS_RATIO, CS53L30_MCLK_INT_SCALE},496	{6400000, 16000, 0x5, CS53L30_INTRNL_FS_RATIO, CS53L30_MCLK_INT_SCALE},497	{6400000, 22050, 0x6, CS53L30_INTRNL_FS_RATIO, CS53L30_MCLK_INT_SCALE},498	{6400000, 24000, 0x8, CS53L30_INTRNL_FS_RATIO, CS53L30_MCLK_INT_SCALE},499	{6400000, 32000, 0x9, CS53L30_INTRNL_FS_RATIO, CS53L30_MCLK_INT_SCALE},500	{6400000, 44100, 0xA, CS53L30_INTRNL_FS_RATIO, CS53L30_MCLK_INT_SCALE},501	{6400000, 48000, 0xC, CS53L30_INTRNL_FS_RATIO, CS53L30_MCLK_INT_SCALE},502};503 504struct cs53l30_mclkx_div {505	u32 mclkx;506	u8 ratio;507	u8 mclkdiv;508};509 510static const struct cs53l30_mclkx_div cs53l30_mclkx_coeffs[] = {511	{5644800,  1, CS53L30_MCLK_DIV_BY_1},512	{6000000,  1, CS53L30_MCLK_DIV_BY_1},513	{6144000,  1, CS53L30_MCLK_DIV_BY_1},514	{11289600, 2, CS53L30_MCLK_DIV_BY_2},515	{12288000, 2, CS53L30_MCLK_DIV_BY_2},516	{12000000, 2, CS53L30_MCLK_DIV_BY_2},517	{19200000, 3, CS53L30_MCLK_DIV_BY_3},518};519 520static int cs53l30_get_mclkx_coeff(int mclkx)521{522	int i;523 524	for (i = 0; i < ARRAY_SIZE(cs53l30_mclkx_coeffs); i++) {525		if (cs53l30_mclkx_coeffs[i].mclkx == mclkx)526			return i;527	}528 529	return -EINVAL;530}531 532static int cs53l30_get_mclk_coeff(int mclk_rate, int srate)533{534	int i;535 536	for (i = 0; i < ARRAY_SIZE(cs53l30_mclk_coeffs); i++) {537		if (cs53l30_mclk_coeffs[i].mclk_rate == mclk_rate &&538		    cs53l30_mclk_coeffs[i].srate == srate)539			return i;540	}541 542	return -EINVAL;543}544 545static int cs53l30_set_sysclk(struct snd_soc_dai *dai,546			      int clk_id, unsigned int freq, int dir)547{548	struct cs53l30_private *priv = snd_soc_component_get_drvdata(dai->component);549	int mclkx_coeff;550	u32 mclk_rate;551 552	/* MCLKX -> MCLK */553	mclkx_coeff = cs53l30_get_mclkx_coeff(freq);554	if (mclkx_coeff < 0)555		return mclkx_coeff;556 557	mclk_rate = cs53l30_mclkx_coeffs[mclkx_coeff].mclkx /558		    cs53l30_mclkx_coeffs[mclkx_coeff].ratio;559 560	regmap_update_bits(priv->regmap, CS53L30_MCLKCTL,561			   CS53L30_MCLK_DIV_MASK,562			   cs53l30_mclkx_coeffs[mclkx_coeff].mclkdiv);563 564	priv->mclk_rate = mclk_rate;565 566	return 0;567}568 569static int cs53l30_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)570{571	struct cs53l30_private *priv = snd_soc_component_get_drvdata(dai->component);572	u8 aspcfg = 0, aspctl1 = 0;573 574	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {575	case SND_SOC_DAIFMT_CBM_CFM:576		aspcfg |= CS53L30_ASP_MS;577		break;578	case SND_SOC_DAIFMT_CBS_CFS:579		break;580	default:581		return -EINVAL;582	}583 584	/* DAI mode */585	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {586	case SND_SOC_DAIFMT_I2S:587		/* Set TDM_PDN to turn off TDM mode -- Reset default */588		aspctl1 |= CS53L30_ASP_TDM_PDN;589		break;590	case SND_SOC_DAIFMT_DSP_A:591		/*592		 * Clear TDM_PDN to turn on TDM mode; Use ASP_SCLK_INV = 0593		 * with SHIFT_LEFT = 1 combination as Figure 4-13 shows in594		 * the CS53L30 datasheet595		 */596		aspctl1 |= CS53L30_SHIFT_LEFT;597		break;598	default:599		return -EINVAL;600	}601 602	/* Check to see if the SCLK is inverted */603	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {604	case SND_SOC_DAIFMT_IB_NF:605	case SND_SOC_DAIFMT_IB_IF:606		aspcfg ^= CS53L30_ASP_SCLK_INV;607		break;608	default:609		break;610	}611 612	regmap_update_bits(priv->regmap, CS53L30_ASPCFG_CTL,613			   CS53L30_ASP_MS | CS53L30_ASP_SCLK_INV, aspcfg);614 615	regmap_update_bits(priv->regmap, CS53L30_ASP_CTL1,616			   CS53L30_ASP_TDM_PDN | CS53L30_SHIFT_LEFT, aspctl1);617 618	return 0;619}620 621static int cs53l30_pcm_hw_params(struct snd_pcm_substream *substream,622				 struct snd_pcm_hw_params *params,623				 struct snd_soc_dai *dai)624{625	struct cs53l30_private *priv = snd_soc_component_get_drvdata(dai->component);626	int srate = params_rate(params);627	int mclk_coeff;628 629	/* MCLK -> srate */630	mclk_coeff = cs53l30_get_mclk_coeff(priv->mclk_rate, srate);631	if (mclk_coeff < 0)632		return -EINVAL;633 634	regmap_update_bits(priv->regmap, CS53L30_INT_SR_CTL,635			   CS53L30_INTRNL_FS_RATIO_MASK,636			   cs53l30_mclk_coeffs[mclk_coeff].internal_fs_ratio);637 638	regmap_update_bits(priv->regmap, CS53L30_MCLKCTL,639			   CS53L30_MCLK_INT_SCALE_MASK,640			   cs53l30_mclk_coeffs[mclk_coeff].mclk_int_scale);641 642	regmap_update_bits(priv->regmap, CS53L30_ASPCFG_CTL,643			   CS53L30_ASP_RATE_MASK,644			   cs53l30_mclk_coeffs[mclk_coeff].asp_rate);645 646	return 0;647}648 649static int cs53l30_set_bias_level(struct snd_soc_component *component,650				  enum snd_soc_bias_level level)651{652	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);653	struct cs53l30_private *priv = snd_soc_component_get_drvdata(component);654	unsigned int reg;655	int i, inter_max_check, ret;656 657	switch (level) {658	case SND_SOC_BIAS_ON:659		break;660	case SND_SOC_BIAS_PREPARE:661		if (dapm->bias_level == SND_SOC_BIAS_STANDBY)662			regmap_update_bits(priv->regmap, CS53L30_PWRCTL,663					   CS53L30_PDN_LP_MASK, 0);664		break;665	case SND_SOC_BIAS_STANDBY:666		if (dapm->bias_level == SND_SOC_BIAS_OFF) {667			ret = clk_prepare_enable(priv->mclk);668			if (ret) {669				dev_err(component->dev,670					"failed to enable MCLK: %d\n", ret);671				return ret;672			}673			regmap_update_bits(priv->regmap, CS53L30_MCLKCTL,674					   CS53L30_MCLK_DIS_MASK, 0);675			regmap_update_bits(priv->regmap, CS53L30_PWRCTL,676					   CS53L30_PDN_ULP_MASK, 0);677			msleep(50);678		} else {679			regmap_update_bits(priv->regmap, CS53L30_PWRCTL,680					   CS53L30_PDN_ULP_MASK,681					   CS53L30_PDN_ULP);682		}683		break;684	case SND_SOC_BIAS_OFF:685		regmap_update_bits(priv->regmap, CS53L30_INT_MASK,686				   CS53L30_PDN_DONE, 0);687		/*688		 * If digital softramp is set, the amount of time required689		 * for power down increases and depends on the digital690		 * volume setting.691		 */692 693		/* Set the max possible time if digsft is set */694		regmap_read(priv->regmap, CS53L30_SFT_RAMP, &reg);695		if (reg & CS53L30_DIGSFT_MASK)696			inter_max_check = CS53L30_PDN_POLL_MAX;697		else698			inter_max_check = 10;699 700		regmap_update_bits(priv->regmap, CS53L30_PWRCTL,701				   CS53L30_PDN_ULP_MASK,702				   CS53L30_PDN_ULP);703		/* PDN_DONE will take a min of 20ms to be set.*/704		msleep(20);705		/* Clr status */706		regmap_read(priv->regmap, CS53L30_IS, &reg);707		for (i = 0; i < inter_max_check; i++) {708			if (inter_max_check < 10) {709				usleep_range(1000, 1100);710				regmap_read(priv->regmap, CS53L30_IS, &reg);711				if (reg & CS53L30_PDN_DONE)712					break;713			} else {714				usleep_range(10000, 10100);715				regmap_read(priv->regmap, CS53L30_IS, &reg);716				if (reg & CS53L30_PDN_DONE)717					break;718			}719		}720		/* PDN_DONE is set. We now can disable the MCLK */721		regmap_update_bits(priv->regmap, CS53L30_INT_MASK,722				   CS53L30_PDN_DONE, CS53L30_PDN_DONE);723		regmap_update_bits(priv->regmap, CS53L30_MCLKCTL,724				   CS53L30_MCLK_DIS_MASK,725				   CS53L30_MCLK_DIS);726		clk_disable_unprepare(priv->mclk);727		break;728	}729 730	return 0;731}732 733static int cs53l30_set_tristate(struct snd_soc_dai *dai, int tristate)734{735	struct cs53l30_private *priv = snd_soc_component_get_drvdata(dai->component);736	u8 val = tristate ? CS53L30_ASP_3ST : 0;737 738	return regmap_update_bits(priv->regmap, CS53L30_ASP_CTL1,739				  CS53L30_ASP_3ST_MASK, val);740}741 742/*743 * Note: CS53L30 counts the slot number per byte while ASoC counts the slot744 * number per slot_width. So there is a difference between the slots of ASoC745 * and the slots of CS53L30.746 */747static int cs53l30_set_dai_tdm_slot(struct snd_soc_dai *dai,748				    unsigned int tx_mask, unsigned int rx_mask,749				    int slots, int slot_width)750{751	struct cs53l30_private *priv = snd_soc_component_get_drvdata(dai->component);752	unsigned int loc[CS53L30_TDM_SLOT_MAX] = {48, 48, 48, 48};753	unsigned int slot_next, slot_step;754	u64 tx_enable = 0;755	int i;756 757	if (!rx_mask) {758		dev_err(dai->dev, "rx masks must not be 0\n");759		return -EINVAL;760	}761 762	/* Assuming slot_width is not supposed to be greater than 64 */763	if (slots <= 0 || slot_width <= 0 || slot_width > 64) {764		dev_err(dai->dev, "invalid slot number or slot width\n");765		return -EINVAL;766	}767 768	if (slot_width & 0x7) {769		dev_err(dai->dev, "slot width must count in byte\n");770		return -EINVAL;771	}772 773	/* How many bytes in each ASoC slot */774	slot_step = slot_width >> 3;775 776	for (i = 0; rx_mask && i < CS53L30_TDM_SLOT_MAX; i++) {777		/* Find the first slot from LSB */778		slot_next = __ffs(rx_mask);779		/* Save the slot location by converting to CS53L30 slot */780		loc[i] = slot_next * slot_step;781		/* Create the mask of CS53L30 slot */782		tx_enable |= (u64)((u64)(1 << slot_step) - 1) << (u64)loc[i];783		/* Clear this slot from rx_mask */784		rx_mask &= ~(1 << slot_next);785	}786 787	/* Error out to avoid slot shift */788	if (rx_mask && i == CS53L30_TDM_SLOT_MAX) {789		dev_err(dai->dev, "rx_mask exceeds max slot number: %d\n",790			CS53L30_TDM_SLOT_MAX);791		return -EINVAL;792	}793 794	/* Validate the last active CS53L30 slot */795	slot_next = loc[i - 1] + slot_step - 1;796	if (slot_next > 47) {797		dev_err(dai->dev, "slot selection out of bounds: %u\n",798			slot_next);799		return -EINVAL;800	}801 802	for (i = 0; i < CS53L30_TDM_SLOT_MAX && loc[i] != 48; i++) {803		regmap_update_bits(priv->regmap, CS53L30_ASP_TDMTX_CTL(i),804				   CS53L30_ASP_CHx_TX_LOC_MASK, loc[i]);805		dev_dbg(dai->dev, "loc[%d]=%x\n", i, loc[i]);806	}807 808	for (i = 0; i < CS53L30_ASP_TDMTX_ENx_MAX && tx_enable; i++) {809		regmap_write(priv->regmap, CS53L30_ASP_TDMTX_ENx(i),810			     tx_enable & 0xff);811		tx_enable >>= 8;812		dev_dbg(dai->dev, "en_reg=%x, tx_enable=%llx\n",813			CS53L30_ASP_TDMTX_ENx(i), tx_enable & 0xff);814	}815 816	return 0;817}818 819static int cs53l30_mute_stream(struct snd_soc_dai *dai, int mute, int stream)820{821	struct cs53l30_private *priv = snd_soc_component_get_drvdata(dai->component);822 823	gpiod_set_value_cansleep(priv->mute_gpio, mute);824 825	return 0;826}827 828#define CS53L30_RATES (SNDRV_PCM_RATE_8000_48000 |	\829		       SNDRV_PCM_RATE_12000 |		\830		       SNDRV_PCM_RATE_24000)831 832#define CS53L30_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\833			SNDRV_PCM_FMTBIT_S24_LE)834 835static const struct snd_soc_dai_ops cs53l30_ops = {836	.hw_params = cs53l30_pcm_hw_params,837	.set_fmt = cs53l30_set_dai_fmt,838	.set_sysclk = cs53l30_set_sysclk,839	.set_tristate = cs53l30_set_tristate,840	.set_tdm_slot = cs53l30_set_dai_tdm_slot,841	.mute_stream = cs53l30_mute_stream,842};843 844static struct snd_soc_dai_driver cs53l30_dai = {845	.name = "cs53l30",846	.capture = {847		.stream_name = "Capture",848		.channels_min = 1,849		.channels_max = 4,850		.rates = CS53L30_RATES,851		.formats = CS53L30_FORMATS,852	},853	.ops = &cs53l30_ops,854	.symmetric_rate = 1,855};856 857static int cs53l30_component_probe(struct snd_soc_component *component)858{859	struct cs53l30_private *priv = snd_soc_component_get_drvdata(component);860	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);861 862	if (priv->use_sdout2)863		snd_soc_dapm_add_routes(dapm, cs53l30_dapm_routes_sdout2,864					ARRAY_SIZE(cs53l30_dapm_routes_sdout2));865	else866		snd_soc_dapm_add_routes(dapm, cs53l30_dapm_routes_sdout1,867					ARRAY_SIZE(cs53l30_dapm_routes_sdout1));868 869	return 0;870}871 872static const struct snd_soc_component_driver cs53l30_driver = {873	.probe			= cs53l30_component_probe,874	.set_bias_level		= cs53l30_set_bias_level,875	.controls		= cs53l30_snd_controls,876	.num_controls		= ARRAY_SIZE(cs53l30_snd_controls),877	.dapm_widgets		= cs53l30_dapm_widgets,878	.num_dapm_widgets	= ARRAY_SIZE(cs53l30_dapm_widgets),879	.dapm_routes		= cs53l30_dapm_routes,880	.num_dapm_routes	= ARRAY_SIZE(cs53l30_dapm_routes),881	.use_pmdown_time	= 1,882	.endianness		= 1,883};884 885static const struct regmap_config cs53l30_regmap = {886	.reg_bits = 8,887	.val_bits = 8,888 889	.max_register = CS53L30_MAX_REGISTER,890	.reg_defaults = cs53l30_reg_defaults,891	.num_reg_defaults = ARRAY_SIZE(cs53l30_reg_defaults),892	.volatile_reg = cs53l30_volatile_register,893	.writeable_reg = cs53l30_writeable_register,894	.readable_reg = cs53l30_readable_register,895	.cache_type = REGCACHE_MAPLE,896 897	.use_single_read = true,898	.use_single_write = true,899};900 901static int cs53l30_i2c_probe(struct i2c_client *client)902{903	const struct device_node *np = client->dev.of_node;904	struct device *dev = &client->dev;905	struct cs53l30_private *cs53l30;906	unsigned int reg;907	int ret = 0, i, devid;908	u8 val;909 910	cs53l30 = devm_kzalloc(dev, sizeof(*cs53l30), GFP_KERNEL);911	if (!cs53l30)912		return -ENOMEM;913 914	for (i = 0; i < ARRAY_SIZE(cs53l30->supplies); i++)915		cs53l30->supplies[i].supply = cs53l30_supply_names[i];916 917	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(cs53l30->supplies),918				      cs53l30->supplies);919	if (ret) {920		dev_err(dev, "failed to get supplies: %d\n", ret);921		return ret;922	}923 924	ret = regulator_bulk_enable(ARRAY_SIZE(cs53l30->supplies),925				    cs53l30->supplies);926	if (ret) {927		dev_err(dev, "failed to enable supplies: %d\n", ret);928		return ret;929	}930 931	/* Reset the Device */932	cs53l30->reset_gpio = devm_gpiod_get_optional(dev, "reset",933						      GPIOD_OUT_LOW);934	if (IS_ERR(cs53l30->reset_gpio)) {935		ret = PTR_ERR(cs53l30->reset_gpio);936		goto error_supplies;937	}938 939	gpiod_set_value_cansleep(cs53l30->reset_gpio, 1);940 941	i2c_set_clientdata(client, cs53l30);942 943	cs53l30->mclk_rate = 0;944 945	cs53l30->regmap = devm_regmap_init_i2c(client, &cs53l30_regmap);946	if (IS_ERR(cs53l30->regmap)) {947		ret = PTR_ERR(cs53l30->regmap);948		dev_err(dev, "regmap_init() failed: %d\n", ret);949		goto error;950	}951 952	/* Initialize codec */953	devid = cirrus_read_device_id(cs53l30->regmap, CS53L30_DEVID_AB);954	if (devid < 0) {955		ret = devid;956		dev_err(dev, "Failed to read device ID: %d\n", ret);957		goto error;958	}959 960	if (devid != CS53L30_DEVID) {961		ret = -ENODEV;962		dev_err(dev, "Device ID (%X). Expected %X\n",963			devid, CS53L30_DEVID);964		goto error;965	}966 967	ret = regmap_read(cs53l30->regmap, CS53L30_REVID, &reg);968	if (ret < 0) {969		dev_err(dev, "failed to get Revision ID: %d\n", ret);970		goto error;971	}972 973	/* Check if MCLK provided */974	cs53l30->mclk = devm_clk_get_optional(dev, "mclk");975	if (IS_ERR(cs53l30->mclk)) {976		ret = PTR_ERR(cs53l30->mclk);977		goto error;978	}979 980	/* Fetch the MUTE control */981	cs53l30->mute_gpio = devm_gpiod_get_optional(dev, "mute",982						     GPIOD_OUT_HIGH);983	if (IS_ERR(cs53l30->mute_gpio)) {984		ret = PTR_ERR(cs53l30->mute_gpio);985		goto error;986	}987 988	if (cs53l30->mute_gpio) {989		/* Enable MUTE controls via MUTE pin */990		regmap_write(cs53l30->regmap, CS53L30_MUTEP_CTL1,991			     CS53L30_MUTEP_CTL1_MUTEALL);992		/* Flip the polarity of MUTE pin */993		if (gpiod_is_active_low(cs53l30->mute_gpio))994			regmap_update_bits(cs53l30->regmap, CS53L30_MUTEP_CTL2,995					   CS53L30_MUTE_PIN_POLARITY, 0);996	}997 998	if (!of_property_read_u8(np, "cirrus,micbias-lvl", &val))999		regmap_update_bits(cs53l30->regmap, CS53L30_MICBIAS_CTL,1000				   CS53L30_MIC_BIAS_CTRL_MASK, val);1001 1002	if (of_property_read_bool(np, "cirrus,use-sdout2"))1003		cs53l30->use_sdout2 = true;1004 1005	dev_info(dev, "Cirrus Logic CS53L30, Revision: %02X\n", reg & 0xFF);1006 1007	ret = devm_snd_soc_register_component(dev, &cs53l30_driver, &cs53l30_dai, 1);1008	if (ret) {1009		dev_err(dev, "failed to register component: %d\n", ret);1010		goto error;1011	}1012 1013	return 0;1014 1015error:1016	gpiod_set_value_cansleep(cs53l30->reset_gpio, 0);1017error_supplies:1018	regulator_bulk_disable(ARRAY_SIZE(cs53l30->supplies),1019			       cs53l30->supplies);1020	return ret;1021}1022 1023static void cs53l30_i2c_remove(struct i2c_client *client)1024{1025	struct cs53l30_private *cs53l30 = i2c_get_clientdata(client);1026 1027	/* Hold down reset */1028	gpiod_set_value_cansleep(cs53l30->reset_gpio, 0);1029 1030	regulator_bulk_disable(ARRAY_SIZE(cs53l30->supplies),1031			       cs53l30->supplies);1032}1033 1034#ifdef CONFIG_PM1035static int cs53l30_runtime_suspend(struct device *dev)1036{1037	struct cs53l30_private *cs53l30 = dev_get_drvdata(dev);1038 1039	regcache_cache_only(cs53l30->regmap, true);1040 1041	/* Hold down reset */1042	gpiod_set_value_cansleep(cs53l30->reset_gpio, 0);1043 1044	regulator_bulk_disable(ARRAY_SIZE(cs53l30->supplies),1045			       cs53l30->supplies);1046 1047	return 0;1048}1049 1050static int cs53l30_runtime_resume(struct device *dev)1051{1052	struct cs53l30_private *cs53l30 = dev_get_drvdata(dev);1053	int ret;1054 1055	ret = regulator_bulk_enable(ARRAY_SIZE(cs53l30->supplies),1056				    cs53l30->supplies);1057	if (ret) {1058		dev_err(dev, "failed to enable supplies: %d\n", ret);1059		return ret;1060	}1061 1062	gpiod_set_value_cansleep(cs53l30->reset_gpio, 1);1063 1064	regcache_cache_only(cs53l30->regmap, false);1065	ret = regcache_sync(cs53l30->regmap);1066	if (ret) {1067		dev_err(dev, "failed to synchronize regcache: %d\n", ret);1068		return ret;1069	}1070 1071	return 0;1072}1073#endif1074 1075static const struct dev_pm_ops cs53l30_runtime_pm = {1076	SET_RUNTIME_PM_OPS(cs53l30_runtime_suspend, cs53l30_runtime_resume,1077			   NULL)1078};1079 1080static const struct of_device_id cs53l30_of_match[] = {1081	{ .compatible = "cirrus,cs53l30", },1082	{},1083};1084 1085MODULE_DEVICE_TABLE(of, cs53l30_of_match);1086 1087static const struct i2c_device_id cs53l30_id[] = {1088	{ "cs53l30" },1089	{}1090};1091 1092MODULE_DEVICE_TABLE(i2c, cs53l30_id);1093 1094static struct i2c_driver cs53l30_i2c_driver = {1095	.driver = {1096		.name = "cs53l30",1097		.of_match_table = cs53l30_of_match,1098		.pm = &cs53l30_runtime_pm,1099	},1100	.id_table = cs53l30_id,1101	.probe = cs53l30_i2c_probe,1102	.remove = cs53l30_i2c_remove,1103};1104 1105module_i2c_driver(cs53l30_i2c_driver);1106 1107MODULE_DESCRIPTION("ASoC CS53L30 driver");1108MODULE_AUTHOR("Paul Handrigan, Cirrus Logic Inc, <Paul.Handrigan@cirrus.com>");1109MODULE_LICENSE("GPL");1110