1 // SPDX-License-Identifier: GPL-2.0 2 // 3 // CS530x CODEC driver 4 // 5 // Copyright (C) 2024-2025 Cirrus Logic, Inc. and 6 // Cirrus Logic International Semiconductor Ltd. 7 8 #include <linux/delay.h> 9 #include <linux/i2c.h> 10 #include <linux/init.h> 11 #include <linux/module.h> 12 #include <linux/pm.h> 13 #include <linux/property.h> 14 #include <linux/slab.h> 15 #include <linux/spi/spi.h> 16 #include <sound/core.h> 17 #include <sound/initval.h> 18 #include <sound/pcm.h> 19 #include <sound/pcm_params.h> 20 #include <sound/soc.h> 21 #include <sound/tlv.h> 22 23 #include "cs530x.h" 24 25 static const char *cs530x_supply_names[CS530X_NUM_SUPPLIES] = { 26 "vdd-a", 27 "vdd-io", 28 }; 29 30 static const struct reg_default cs530x_reg_defaults[] = { 31 { CS530X_CLK_CFG_0, 0x30 }, 32 { CS530X_CLK_CFG_1, 0x0001 }, 33 { CS530X_CHIP_ENABLE, 0 }, 34 { CS530X_ASP_CFG, 0 }, 35 { CS530X_SIGNAL_PATH_CFG, 0 }, 36 { CS530X_IN_ENABLES, 0 }, 37 { CS530X_IN_RAMP_SUM, 0x0022 }, 38 { CS530X_IN_FILTER, 0 }, 39 { CS530X_IN_HIZ, 0 }, 40 { CS530X_IN_INV, 0 }, 41 { CS530X_IN_VOL_CTRL1_0, 0x8000 }, 42 { CS530X_IN_VOL_CTRL1_1, 0x8000 }, 43 { CS530X_IN_VOL_CTRL2_0, 0x8000 }, 44 { CS530X_IN_VOL_CTRL2_1, 0x8000 }, 45 { CS530X_IN_VOL_CTRL3_0, 0x8000 }, 46 { CS530X_IN_VOL_CTRL3_1, 0x8000 }, 47 { CS530X_IN_VOL_CTRL4_0, 0x8000 }, 48 { CS530X_IN_VOL_CTRL4_1, 0x8000 }, 49 { CS530X_OUT_ENABLES, 0 }, 50 { CS530X_OUT_RAMP_SUM, 0x0022 }, 51 { CS530X_OUT_FILTER, 0 }, 52 { CS530X_OUT_INV, 0 }, 53 { CS530X_OUT_VOL_CTRL1_0, 0x8000 }, 54 { CS530X_OUT_VOL_CTRL1_1, 0x8000 }, 55 { CS530X_OUT_VOL_CTRL2_0, 0x8000 }, 56 { CS530X_OUT_VOL_CTRL2_1, 0x8000 }, 57 { CS530X_OUT_VOL_CTRL3_0, 0x8000 }, 58 { CS530X_OUT_VOL_CTRL3_1, 0x8000 }, 59 { CS530X_OUT_VOL_CTRL4_0, 0x8000 }, 60 { CS530X_OUT_VOL_CTRL4_1, 0x8000 }, 61 { CS530X_PAD_FN, 0 }, 62 { CS530X_PAD_LVL, 0 }, 63 }; 64 65 static bool cs530x_read_and_write_regs(unsigned int reg) 66 { 67 switch (reg) { 68 case CS530X_CLK_CFG_0: 69 case CS530X_CLK_CFG_1: 70 case CS530X_CHIP_ENABLE: 71 case CS530X_ASP_CFG: 72 case CS530X_SIGNAL_PATH_CFG: 73 case CS530X_IN_ENABLES: 74 case CS530X_IN_RAMP_SUM: 75 case CS530X_IN_FILTER: 76 case CS530X_IN_HIZ: 77 case CS530X_IN_INV: 78 case CS530X_IN_VOL_CTRL1_0: 79 case CS530X_IN_VOL_CTRL1_1: 80 case CS530X_IN_VOL_CTRL2_0: 81 case CS530X_IN_VOL_CTRL2_1: 82 case CS530X_IN_VOL_CTRL3_0: 83 case CS530X_IN_VOL_CTRL3_1: 84 case CS530X_IN_VOL_CTRL4_0: 85 case CS530X_IN_VOL_CTRL4_1: 86 case CS530X_OUT_ENABLES: 87 case CS530X_OUT_RAMP_SUM: 88 case CS530X_OUT_DEEMPH: 89 case CS530X_OUT_FILTER: 90 case CS530X_OUT_INV: 91 case CS530X_OUT_VOL_CTRL1_0: 92 case CS530X_OUT_VOL_CTRL1_1: 93 case CS530X_OUT_VOL_CTRL2_0: 94 case CS530X_OUT_VOL_CTRL2_1: 95 case CS530X_OUT_VOL_CTRL3_0: 96 case CS530X_OUT_VOL_CTRL3_1: 97 case CS530X_OUT_VOL_CTRL4_0: 98 case CS530X_OUT_VOL_CTRL4_1: 99 case CS530X_PAD_FN: 100 case CS530X_PAD_LVL: 101 return true; 102 default: 103 return false; 104 } 105 } 106 107 static bool cs530x_readable_register(struct device *dev, unsigned int reg) 108 { 109 switch (reg) { 110 case CS530X_DEVID: 111 case CS530X_REVID: 112 return true; 113 default: 114 return cs530x_read_and_write_regs(reg); 115 } 116 } 117 118 static bool cs530x_writeable_register(struct device *dev, unsigned int reg) 119 { 120 switch (reg) { 121 case CS530X_SW_RESET: 122 case CS530X_IN_VOL_CTRL5: 123 case CS530X_OUT_VOL_CTRL5: 124 return true; 125 default: 126 return cs530x_read_and_write_regs(reg); 127 } 128 } 129 130 static int cs530x_put_volsw_vu(struct snd_kcontrol *kcontrol, 131 struct snd_ctl_elem_value *ucontrol) 132 { 133 struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 134 struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component); 135 struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component); 136 struct regmap *regmap = cs530x->regmap; 137 int ret; 138 139 snd_soc_dapm_mutex_lock(dapm); 140 141 ret = snd_soc_put_volsw(kcontrol, ucontrol); 142 if (ret) 143 goto volsw_err; 144 145 /* Write INOUT_VU bit for the volume change to take effect */ 146 regmap_write(regmap, CS530X_IN_VOL_CTRL5, CS530X_INOUT_VU); 147 148 volsw_err: 149 snd_soc_dapm_mutex_unlock(dapm); 150 151 return ret; 152 } 153 154 static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -1270, 50, 0); 155 156 static const char * const cs530x_inout_filter_text[] = { 157 "Min Phase Slow Roll-off", 158 "Min Phase Fast Roll-off", 159 "Linear Phase Slow Roll-off", 160 "Linear Phase Fast Roll-off", 161 }; 162 163 static SOC_ENUM_SINGLE_DECL(cs530x_in_filter_enum, CS530X_IN_FILTER, 164 CS530X_INOUT_FILTER_SHIFT, 165 cs530x_inout_filter_text); 166 167 static SOC_ENUM_SINGLE_DECL(cs530x_out_filter_enum, CS530X_OUT_FILTER, 168 CS530X_INOUT_FILTER_SHIFT, 169 cs530x_inout_filter_text); 170 171 static const char * const cs530x_4ch_sum_text[] = { 172 "None", 173 "Groups of 2", 174 "Groups of 4", 175 }; 176 177 static SOC_ENUM_SINGLE_DECL(cs530x_in_sum_ch4_enum, CS530X_IN_RAMP_SUM, 178 CS530X_INOUT_SUM_MODE_SHIFT, 179 cs530x_4ch_sum_text); 180 181 static const struct snd_kcontrol_new cs530x_in_sum_4ch_controls[] = { 182 SOC_ENUM("IN Sum Select", cs530x_in_sum_ch4_enum), 183 }; 184 185 static SOC_ENUM_SINGLE_DECL(cs530x_out_sum_ch4_enum, CS530X_OUT_RAMP_SUM, 186 CS530X_INOUT_SUM_MODE_SHIFT, 187 cs530x_4ch_sum_text); 188 189 static const struct snd_kcontrol_new cs530x_out_sum_4ch_controls[] = { 190 SOC_ENUM("OUT Sum Select", cs530x_out_sum_ch4_enum), 191 }; 192 193 static const char * const cs530x_8ch_sum_text[] = { 194 "None", 195 "Groups of 2", 196 "Groups of 4", 197 "Groups of 8", 198 }; 199 200 static SOC_ENUM_SINGLE_DECL(cs530x_in_sum_ch8_enum, CS530X_IN_RAMP_SUM, 201 CS530X_INOUT_SUM_MODE_SHIFT, 202 cs530x_8ch_sum_text); 203 204 static const struct snd_kcontrol_new cs530x_in_sum_8ch_controls[] = { 205 SOC_ENUM("IN Sum Select", cs530x_in_sum_ch8_enum), 206 }; 207 208 static SOC_ENUM_SINGLE_DECL(cs530x_out_sum_ch8_enum, CS530X_OUT_RAMP_SUM, 209 CS530X_INOUT_SUM_MODE_SHIFT, 210 cs530x_8ch_sum_text); 211 212 static const struct snd_kcontrol_new cs530x_out_sum_8ch_controls[] = { 213 SOC_ENUM("OUT Sum Select", cs530x_out_sum_ch8_enum), 214 }; 215 216 static const char * const cs530x_vol_ramp_text[] = { 217 "0ms/6dB", "0.5ms/6dB", "1ms/6dB", "2ms/6dB", "4ms/6dB", "8ms/6dB", 218 "15ms/6dB", "30ms/6dB", 219 }; 220 221 static SOC_ENUM_SINGLE_DECL(cs530x_ramp_inc_enum, CS530X_IN_RAMP_SUM, 222 CS530X_RAMP_RATE_INC_SHIFT, 223 cs530x_vol_ramp_text); 224 225 static SOC_ENUM_SINGLE_DECL(cs530x_ramp_dec_enum, CS530X_IN_RAMP_SUM, 226 CS530X_RAMP_RATE_DEC_SHIFT, 227 cs530x_vol_ramp_text); 228 229 static const struct snd_kcontrol_new cs530x_in_1_to_2_controls[] = { 230 SOC_SINGLE_EXT_TLV("IN1 Volume", CS530X_IN_VOL_CTRL1_0, 0, 255, 1, 231 snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv), 232 SOC_SINGLE_EXT_TLV("IN2 Volume", CS530X_IN_VOL_CTRL1_1, 0, 255, 1, 233 snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv), 234 235 SOC_ENUM("IN DEC Filter Select", cs530x_in_filter_enum), 236 SOC_ENUM("Input Ramp Up", cs530x_ramp_inc_enum), 237 SOC_ENUM("Input Ramp Down", cs530x_ramp_dec_enum), 238 239 SOC_SINGLE("ADC1 Invert Switch", CS530X_IN_INV, CS530X_INOUT1_INV_SHIFT, 1, 0), 240 SOC_SINGLE("ADC2 Invert Switch", CS530X_IN_INV, CS530X_INOUT2_INV_SHIFT, 1, 0), 241 }; 242 243 static const struct snd_kcontrol_new cs530x_in_3_to_4_controls[] = { 244 SOC_SINGLE_EXT_TLV("IN3 Volume", CS530X_IN_VOL_CTRL2_0, 0, 255, 1, 245 snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv), 246 SOC_SINGLE_EXT_TLV("IN4 Volume", CS530X_IN_VOL_CTRL2_1, 0, 255, 1, 247 snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv), 248 249 SOC_SINGLE("ADC3 Invert Switch", CS530X_IN_INV, CS530X_INOUT3_INV_SHIFT, 1, 0), 250 SOC_SINGLE("ADC4 Invert Switch", CS530X_IN_INV, CS530X_INOUT4_INV_SHIFT, 1, 0), 251 }; 252 253 static const struct snd_kcontrol_new cs530x_in_5_to_8_controls[] = { 254 SOC_SINGLE_EXT_TLV("IN5 Volume", CS530X_IN_VOL_CTRL3_0, 0, 255, 1, 255 snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv), 256 SOC_SINGLE_EXT_TLV("IN6 Volume", CS530X_IN_VOL_CTRL3_1, 0, 255, 1, 257 snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv), 258 SOC_SINGLE_EXT_TLV("IN7 Volume", CS530X_IN_VOL_CTRL4_0, 0, 255, 1, 259 snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv), 260 SOC_SINGLE_EXT_TLV("IN8 Volume", CS530X_IN_VOL_CTRL4_1, 0, 255, 1, 261 snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv), 262 263 SOC_SINGLE("ADC5 Invert Switch", CS530X_IN_INV, CS530X_INOUT5_INV_SHIFT, 1, 0), 264 SOC_SINGLE("ADC6 Invert Switch", CS530X_IN_INV, CS530X_INOUT6_INV_SHIFT, 1, 0), 265 SOC_SINGLE("ADC7 Invert Switch", CS530X_IN_INV, CS530X_INOUT7_INV_SHIFT, 1, 0), 266 SOC_SINGLE("ADC8 Invert Switch", CS530X_IN_INV, CS530X_INOUT8_INV_SHIFT, 1, 0), 267 }; 268 269 static int cs530x_adc_event(struct snd_soc_dapm_widget *w, 270 struct snd_kcontrol *kcontrol, int event) 271 { 272 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 273 struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component); 274 struct regmap *regmap = cs530x->regmap; 275 276 switch (event) { 277 case SND_SOC_DAPM_PRE_PMU: 278 cs530x->adc_pairs_count++; 279 break; 280 case SND_SOC_DAPM_POST_PMU: 281 regmap_clear_bits(regmap, CS530X_IN_VOL_CTRL1_0 + 282 (w->shift * 2), CS530X_INOUT_MUTE); 283 regmap_clear_bits(regmap, CS530X_IN_VOL_CTRL1_0 + 284 ((w->shift + 1) * 2), CS530X_INOUT_MUTE); 285 286 cs530x->adc_pairs_count--; 287 if (!cs530x->adc_pairs_count) { 288 usleep_range(1000, 1100); 289 return regmap_write(regmap, CS530X_IN_VOL_CTRL5, 290 CS530X_INOUT_VU); 291 } 292 break; 293 case SND_SOC_DAPM_PRE_PMD: 294 regmap_set_bits(regmap, CS530X_IN_VOL_CTRL1_0 + 295 (w->shift * 2), CS530X_INOUT_MUTE); 296 regmap_set_bits(regmap, CS530X_IN_VOL_CTRL1_0 + 297 ((w->shift + 1) * 2), CS530X_INOUT_MUTE); 298 return regmap_write(regmap, CS530X_IN_VOL_CTRL5, 299 CS530X_INOUT_VU); 300 default: 301 return -EINVAL; 302 } 303 304 return 0; 305 } 306 307 static SOC_ENUM_SINGLE_DECL(cs530x_ramp_out_inc_enum, CS530X_OUT_RAMP_SUM, 308 CS530X_RAMP_RATE_INC_SHIFT, 309 cs530x_vol_ramp_text); 310 311 static SOC_ENUM_SINGLE_DECL(cs530x_ramp_out_dec_enum, CS530X_OUT_RAMP_SUM, 312 CS530X_RAMP_RATE_DEC_SHIFT, 313 cs530x_vol_ramp_text); 314 315 static const struct snd_kcontrol_new cs530x_out_1_to_2_controls[] = { 316 SOC_SINGLE_EXT_TLV("OUT1 Volume", CS530X_OUT_VOL_CTRL1_0, 0, 255, 1, 317 snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv), 318 SOC_SINGLE_EXT_TLV("OUT2 Volume", CS530X_OUT_VOL_CTRL1_1, 0, 255, 1, 319 snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv), 320 321 SOC_ENUM("OUT DEC Filter Select", cs530x_out_filter_enum), 322 SOC_ENUM("Output Ramp Up", cs530x_ramp_out_inc_enum), 323 SOC_ENUM("Output Ramp Down", cs530x_ramp_out_dec_enum), 324 325 SOC_SINGLE("DAC1 Invert Switch", CS530X_OUT_INV, CS530X_INOUT1_INV_SHIFT, 1, 0), 326 SOC_SINGLE("DAC2 Invert Switch", CS530X_OUT_INV, CS530X_INOUT2_INV_SHIFT, 1, 0), 327 }; 328 329 static const struct snd_kcontrol_new cs530x_out_3_to_4_controls[] = { 330 SOC_SINGLE_EXT_TLV("OUT3 Volume", CS530X_OUT_VOL_CTRL2_0, 0, 255, 1, 331 snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv), 332 SOC_SINGLE_EXT_TLV("OUT4 Volume", CS530X_OUT_VOL_CTRL2_1, 0, 255, 1, 333 snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv), 334 335 SOC_SINGLE("DAC3 Invert Switch", CS530X_OUT_INV, CS530X_INOUT3_INV_SHIFT, 1, 0), 336 SOC_SINGLE("DAC4 Invert Switch", CS530X_OUT_INV, CS530X_INOUT4_INV_SHIFT, 1, 0), 337 }; 338 339 static const struct snd_kcontrol_new cs530x_out_5_to_8_controls[] = { 340 SOC_SINGLE_EXT_TLV("OUT5 Volume", CS530X_OUT_VOL_CTRL3_0, 0, 255, 1, 341 snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv), 342 SOC_SINGLE_EXT_TLV("OUT6 Volume", CS530X_OUT_VOL_CTRL3_1, 0, 255, 1, 343 snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv), 344 SOC_SINGLE_EXT_TLV("OUT7 Volume", CS530X_OUT_VOL_CTRL4_0, 0, 255, 1, 345 snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv), 346 SOC_SINGLE_EXT_TLV("OUT8 Volume", CS530X_OUT_VOL_CTRL4_1, 0, 255, 1, 347 snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv), 348 349 SOC_SINGLE("DAC5 Invert Switch", CS530X_OUT_INV, CS530X_INOUT5_INV_SHIFT, 1, 0), 350 SOC_SINGLE("DAC6 Invert Switch", CS530X_OUT_INV, CS530X_INOUT6_INV_SHIFT, 1, 0), 351 SOC_SINGLE("DAC7 Invert Switch", CS530X_OUT_INV, CS530X_INOUT7_INV_SHIFT, 1, 0), 352 SOC_SINGLE("DAC8 Invert Switch", CS530X_OUT_INV, CS530X_INOUT8_INV_SHIFT, 1, 0), 353 }; 354 355 static int cs530x_dac_event(struct snd_soc_dapm_widget *w, 356 struct snd_kcontrol *kcontrol, int event) 357 { 358 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 359 struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component); 360 struct regmap *regmap = cs530x->regmap; 361 362 switch (event) { 363 case SND_SOC_DAPM_PRE_PMU: 364 cs530x->dac_pairs_count++; 365 break; 366 case SND_SOC_DAPM_POST_PMU: 367 regmap_clear_bits(regmap, CS530X_OUT_VOL_CTRL1_0 + 368 (w->shift * 2), CS530X_INOUT_MUTE); 369 regmap_clear_bits(regmap, CS530X_OUT_VOL_CTRL1_0 + 370 ((w->shift + 1) * 2), CS530X_INOUT_MUTE); 371 372 cs530x->dac_pairs_count--; 373 if (!cs530x->dac_pairs_count) { 374 usleep_range(1000, 1100); 375 return regmap_write(regmap, CS530X_OUT_VOL_CTRL5, 376 CS530X_INOUT_VU); 377 } 378 break; 379 case SND_SOC_DAPM_PRE_PMD: 380 regmap_set_bits(regmap, CS530X_OUT_VOL_CTRL1_0 + 381 (w->shift * 2), CS530X_INOUT_MUTE); 382 regmap_set_bits(regmap, CS530X_OUT_VOL_CTRL1_0 + 383 ((w->shift + 1) * 2), CS530X_INOUT_MUTE); 384 return regmap_write(regmap, CS530X_OUT_VOL_CTRL5, 385 CS530X_INOUT_VU); 386 default: 387 return -EINVAL; 388 } 389 390 return 0; 391 } 392 393 static const struct snd_kcontrol_new adc12_ctrl = 394 SOC_DAPM_SINGLE_VIRT("Switch", 1); 395 static const struct snd_kcontrol_new adc34_ctrl = 396 SOC_DAPM_SINGLE_VIRT("Switch", 1); 397 static const struct snd_kcontrol_new adc56_ctrl = 398 SOC_DAPM_SINGLE_VIRT("Switch", 1); 399 static const struct snd_kcontrol_new adc78_ctrl = 400 SOC_DAPM_SINGLE_VIRT("Switch", 1); 401 static const struct snd_kcontrol_new dac12_ctrl = 402 SOC_DAPM_SINGLE_VIRT("Switch", 1); 403 static const struct snd_kcontrol_new dac34_ctrl = 404 SOC_DAPM_SINGLE_VIRT("Switch", 1); 405 static const struct snd_kcontrol_new dac56_ctrl = 406 SOC_DAPM_SINGLE_VIRT("Switch", 1); 407 static const struct snd_kcontrol_new dac78_ctrl = 408 SOC_DAPM_SINGLE_VIRT("Switch", 1); 409 static const struct snd_kcontrol_new in_hpf_ctrl = 410 SOC_DAPM_SINGLE_VIRT("Switch", 1); 411 static const struct snd_kcontrol_new out_hpf_ctrl = 412 SOC_DAPM_SINGLE_VIRT("Switch", 1); 413 414 /* General DAPM widgets for all devices */ 415 static const struct snd_soc_dapm_widget cs530x_gen_dapm_widgets[] = { 416 SND_SOC_DAPM_SUPPLY("Global Enable", CS530X_CHIP_ENABLE, 0, 0, NULL, 0), 417 }; 418 419 /* ADC's Channels 1 and 2 plus generic ADC DAPM events */ 420 static const struct snd_soc_dapm_widget cs530x_adc_ch12_dapm_widgets[] = { 421 SND_SOC_DAPM_INPUT("IN1"), 422 SND_SOC_DAPM_INPUT("IN2"), 423 SND_SOC_DAPM_ADC_E("ADC1", NULL, CS530X_IN_ENABLES, 0, 0, 424 cs530x_adc_event, 425 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU | 426 SND_SOC_DAPM_PRE_PMU), 427 SND_SOC_DAPM_ADC("ADC2", NULL, CS530X_IN_ENABLES, 1, 0), 428 SND_SOC_DAPM_SWITCH("ADC12 Enable", SND_SOC_NOPM, 0, 0, &adc12_ctrl), 429 SND_SOC_DAPM_SWITCH("IN HPF", CS530X_IN_FILTER, CS530X_INOUT_HPF_EN_SHIFT, 430 0, &in_hpf_ctrl), 431 }; 432 433 /* ADC's Channels 3 and 4 */ 434 static const struct snd_soc_dapm_widget cs530x_adc_ch34_dapm_widgets[] = { 435 SND_SOC_DAPM_INPUT("IN3"), 436 SND_SOC_DAPM_INPUT("IN4"), 437 SND_SOC_DAPM_ADC_E("ADC3", NULL, CS530X_IN_ENABLES, 2, 0, 438 cs530x_adc_event, 439 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU | 440 SND_SOC_DAPM_PRE_PMU), 441 SND_SOC_DAPM_ADC("ADC4", NULL, CS530X_IN_ENABLES, 3, 0), 442 SND_SOC_DAPM_SWITCH("ADC34 Enable", SND_SOC_NOPM, 0, 0, &adc34_ctrl), 443 }; 444 445 /* ADC's Channels 5 to 8 */ 446 static const struct snd_soc_dapm_widget cs530x_adc_ch58_dapm_widgets[] = { 447 SND_SOC_DAPM_INPUT("IN5"), 448 SND_SOC_DAPM_INPUT("IN6"), 449 SND_SOC_DAPM_INPUT("IN7"), 450 SND_SOC_DAPM_INPUT("IN8"), 451 SND_SOC_DAPM_ADC_E("ADC5", NULL, CS530X_IN_ENABLES, 4, 0, 452 cs530x_adc_event, 453 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU | 454 SND_SOC_DAPM_PRE_PMU), 455 SND_SOC_DAPM_ADC("ADC6", NULL, CS530X_IN_ENABLES, 5, 0), 456 SND_SOC_DAPM_SWITCH("ADC56 Enable", SND_SOC_NOPM, 0, 0, &adc56_ctrl), 457 SND_SOC_DAPM_ADC_E("ADC7", NULL, CS530X_IN_ENABLES, 6, 0, 458 cs530x_adc_event, 459 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU | 460 SND_SOC_DAPM_PRE_PMU), 461 SND_SOC_DAPM_ADC("ADC8", NULL, CS530X_IN_ENABLES, 7, 0), 462 SND_SOC_DAPM_SWITCH("ADC78 Enable", SND_SOC_NOPM, 0, 0, &adc78_ctrl), 463 }; 464 465 static const struct snd_soc_dapm_route adc_ch1_2_routes[] = { 466 { "ADC1", NULL, "Global Enable" }, 467 { "ADC2", NULL, "Global Enable" }, 468 469 { "ADC12 Enable", "Switch", "IN1" }, 470 { "ADC12 Enable", "Switch", "IN2" }, 471 { "ADC1", NULL, "ADC12 Enable" }, 472 { "ADC2", NULL, "ADC12 Enable" }, 473 { "IN HPF", "Switch", "ADC1" }, 474 { "IN HPF", "Switch", "ADC2" }, 475 476 { "AIF Capture", NULL, "IN HPF" }, 477 { "AIF Capture", NULL, "ADC1" }, 478 { "AIF Capture", NULL, "ADC2" }, 479 }; 480 481 static const struct snd_soc_dapm_route adc_ch3_4_routes[] = { 482 { "ADC3", NULL, "Global Enable" }, 483 { "ADC4", NULL, "Global Enable" }, 484 485 { "ADC34 Enable", "Switch", "IN3" }, 486 { "ADC34 Enable", "Switch", "IN4" }, 487 { "ADC3", NULL, "ADC34 Enable" }, 488 { "ADC4", NULL, "ADC34 Enable" }, 489 { "IN HPF", "Switch", "ADC3" }, 490 { "IN HPF", "Switch", "ADC4" }, 491 492 { "AIF Capture", NULL, "ADC3" }, 493 { "AIF Capture", NULL, "ADC4" }, 494 }; 495 496 static const struct snd_soc_dapm_route adc_ch5_8_routes[] = { 497 { "ADC5", NULL, "Global Enable" }, 498 { "ADC6", NULL, "Global Enable" }, 499 { "ADC7", NULL, "Global Enable" }, 500 { "ADC8", NULL, "Global Enable" }, 501 502 { "ADC56 Enable", "Switch", "IN5" }, 503 { "ADC56 Enable", "Switch", "IN6" }, 504 { "ADC5", NULL, "ADC56 Enable" }, 505 { "ADC6", NULL, "ADC56 Enable" }, 506 { "IN HPF", "Switch", "ADC5" }, 507 { "IN HPF", "Switch", "ADC6" }, 508 509 { "AIF Capture", NULL, "ADC5" }, 510 { "AIF Capture", NULL, "ADC6" }, 511 512 { "ADC78 Enable", "Switch", "IN7" }, 513 { "ADC78 Enable", "Switch", "IN8" }, 514 { "ADC7", NULL, "ADC78 Enable" }, 515 { "ADC8", NULL, "ADC78 Enable" }, 516 { "IN HPF", "Switch", "ADC7" }, 517 { "IN HPF", "Switch", "ADC8" }, 518 519 { "AIF Capture", NULL, "ADC7" }, 520 { "AIF Capture", NULL, "ADC8" }, 521 }; 522 523 static void cs530x_add_12_adc_widgets(struct snd_soc_component *component) 524 { 525 struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component); 526 527 snd_soc_add_component_controls(component, 528 cs530x_in_1_to_2_controls, 529 ARRAY_SIZE(cs530x_in_1_to_2_controls)); 530 531 snd_soc_dapm_new_controls(dapm, cs530x_adc_ch12_dapm_widgets, 532 ARRAY_SIZE(cs530x_adc_ch12_dapm_widgets)); 533 534 snd_soc_dapm_add_routes(dapm, adc_ch1_2_routes, 535 ARRAY_SIZE(adc_ch1_2_routes)); 536 } 537 538 static void cs530x_add_34_adc_widgets(struct snd_soc_component *component) 539 { 540 struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component); 541 542 snd_soc_add_component_controls(component, 543 cs530x_in_3_to_4_controls, 544 ARRAY_SIZE(cs530x_in_3_to_4_controls)); 545 546 snd_soc_dapm_new_controls(dapm, cs530x_adc_ch34_dapm_widgets, 547 ARRAY_SIZE(cs530x_adc_ch34_dapm_widgets)); 548 549 snd_soc_dapm_add_routes(dapm, adc_ch3_4_routes, 550 ARRAY_SIZE(adc_ch3_4_routes)); 551 } 552 553 /* DAC's Channels 1 and 2 plus generic DAC DAPM events */ 554 static const struct snd_soc_dapm_widget cs530x_dac_ch12_dapm_widgets[] = { 555 SND_SOC_DAPM_OUTPUT("OUT1"), 556 SND_SOC_DAPM_OUTPUT("OUT2"), 557 SND_SOC_DAPM_DAC_E("DAC1", NULL, CS530X_OUT_ENABLES, 0, 0, 558 cs530x_dac_event, 559 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU | 560 SND_SOC_DAPM_PRE_PMU), 561 SND_SOC_DAPM_DAC("DAC2", NULL, CS530X_OUT_ENABLES, 1, 0), 562 SND_SOC_DAPM_SWITCH("DAC12 Enable", SND_SOC_NOPM, 0, 0, &dac12_ctrl), 563 SND_SOC_DAPM_SWITCH("OUT HPF", CS530X_OUT_FILTER, CS530X_INOUT_HPF_EN_SHIFT, 564 0, &out_hpf_ctrl), 565 }; 566 567 /* DAC's Channels 3 and 4 */ 568 static const struct snd_soc_dapm_widget cs530x_dac_ch34_dapm_widgets[] = { 569 SND_SOC_DAPM_OUTPUT("OUT3"), 570 SND_SOC_DAPM_OUTPUT("OUT4"), 571 SND_SOC_DAPM_DAC_E("DAC3", NULL, CS530X_OUT_ENABLES, 2, 0, 572 cs530x_dac_event, 573 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU | 574 SND_SOC_DAPM_PRE_PMU), 575 SND_SOC_DAPM_DAC("DAC4", NULL, CS530X_OUT_ENABLES, 3, 0), 576 SND_SOC_DAPM_SWITCH("DAC34 Enable", SND_SOC_NOPM, 0, 0, &dac34_ctrl), 577 }; 578 579 /* DAC's Channels 5 to 8 */ 580 static const struct snd_soc_dapm_widget cs530x_dac_ch58_dapm_widgets[] = { 581 SND_SOC_DAPM_OUTPUT("OUT5"), 582 SND_SOC_DAPM_OUTPUT("OUT6"), 583 SND_SOC_DAPM_OUTPUT("OUT7"), 584 SND_SOC_DAPM_OUTPUT("OUT8"), 585 SND_SOC_DAPM_DAC_E("DAC5", NULL, CS530X_OUT_ENABLES, 4, 0, 586 cs530x_dac_event, 587 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU | 588 SND_SOC_DAPM_PRE_PMU), 589 SND_SOC_DAPM_DAC("DAC6", NULL, CS530X_OUT_ENABLES, 5, 0), 590 SND_SOC_DAPM_SWITCH("DAC56 Enable", SND_SOC_NOPM, 0, 0, &dac56_ctrl), 591 SND_SOC_DAPM_DAC_E("DAC7", NULL, CS530X_OUT_ENABLES, 6, 0, 592 cs530x_dac_event, 593 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU | 594 SND_SOC_DAPM_PRE_PMU), 595 SND_SOC_DAPM_DAC("DAC8", NULL, CS530X_OUT_ENABLES, 7, 0), 596 SND_SOC_DAPM_SWITCH("DAC78 Enable", SND_SOC_NOPM, 0, 0, &dac78_ctrl), 597 }; 598 599 static const struct snd_soc_dapm_route dac_ch1_2_routes[] = { 600 { "DAC1", NULL, "Global Enable" }, 601 { "DAC2", NULL, "Global Enable" }, 602 603 { "DAC12 Enable", "Switch", "OUT1" }, 604 { "DAC12 Enable", "Switch", "OUT2" }, 605 { "DAC1", NULL, "DAC12 Enable" }, 606 { "DAC2", NULL, "DAC12 Enable" }, 607 { "OUT HPF", "Switch", "DAC1" }, 608 { "OUT HPF", "Switch", "DAC2" }, 609 610 { "OUT HPF", NULL, "AIF Playback" }, 611 { "DAC1", NULL, "AIF Playback" }, 612 { "DAC2", NULL, "AIF Playback" }, 613 614 { "OUT1", NULL, "DAC1" }, 615 { "OUT2", NULL, "DAC2" }, 616 }; 617 618 static const struct snd_soc_dapm_route dac_ch3_4_routes[] = { 619 { "DAC3", NULL, "Global Enable" }, 620 { "DAC4", NULL, "Global Enable" }, 621 622 { "DAC34 Enable", "Switch", "OUT3" }, 623 { "DAC34 Enable", "Switch", "OUT4" }, 624 { "DAC3", NULL, "DAC34 Enable" }, 625 { "DAC4", NULL, "DAC34 Enable" }, 626 { "OUT HPF", "Switch", "DAC3" }, 627 { "OUT HPF", "Switch", "DAC4" }, 628 629 { "DAC3", NULL, "AIF Playback" }, 630 { "DAC4", NULL, "AIF Playback" }, 631 632 { "OUT3", NULL, "DAC3" }, 633 { "OUT4", NULL, "DAC4" }, 634 }; 635 636 static const struct snd_soc_dapm_route dac_ch5_8_routes[] = { 637 { "DAC5", NULL, "Global Enable" }, 638 { "DAC6", NULL, "Global Enable" }, 639 640 { "DAC56 Enable", "Switch", "OUT5" }, 641 { "DAC56 Enable", "Switch", "OUT6" }, 642 { "DAC5", NULL, "DAC56 Enable" }, 643 { "DAC6", NULL, "DAC56 Enable" }, 644 { "OUT HPF", "Switch", "DAC5" }, 645 { "OUT HPF", "Switch", "DAC6" }, 646 647 { "DAC5", NULL, "AIF Playback" }, 648 { "DAC6", NULL, "AIF Playback" }, 649 650 { "OUT5", NULL, "DAC5" }, 651 { "OUT6", NULL, "DAC6" }, 652 653 { "DAC7", NULL, "Global Enable" }, 654 { "DAC8", NULL, "Global Enable" }, 655 656 { "DAC78 Enable", "Switch", "OUT7" }, 657 { "DAC78 Enable", "Switch", "OUT8" }, 658 { "DAC7", NULL, "DAC78 Enable" }, 659 { "DAC8", NULL, "DAC78 Enable" }, 660 { "OUT HPF", "Switch", "DAC7" }, 661 { "OUT HPF", "Switch", "DAC8" }, 662 663 { "DAC7", NULL, "AIF Playback" }, 664 { "DAC8", NULL, "AIF Playback" }, 665 666 { "OUT7", NULL, "DAC7" }, 667 { "OUT8", NULL, "DAC8" }, 668 }; 669 670 static void cs530x_add_12_dac_widgets(struct snd_soc_component *component) 671 { 672 struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component); 673 674 snd_soc_add_component_controls(component, 675 cs530x_out_1_to_2_controls, 676 ARRAY_SIZE(cs530x_out_1_to_2_controls)); 677 678 snd_soc_dapm_new_controls(dapm, cs530x_dac_ch12_dapm_widgets, 679 ARRAY_SIZE(cs530x_dac_ch12_dapm_widgets)); 680 681 snd_soc_dapm_add_routes(dapm, dac_ch1_2_routes, 682 ARRAY_SIZE(dac_ch1_2_routes)); 683 } 684 685 static void cs530x_add_34_dac_widgets(struct snd_soc_component *component) 686 { 687 struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component); 688 689 snd_soc_add_component_controls(component, 690 cs530x_out_3_to_4_controls, 691 ARRAY_SIZE(cs530x_out_3_to_4_controls)); 692 693 snd_soc_dapm_new_controls(dapm, cs530x_dac_ch34_dapm_widgets, 694 ARRAY_SIZE(cs530x_dac_ch34_dapm_widgets)); 695 696 snd_soc_dapm_add_routes(dapm, dac_ch3_4_routes, 697 ARRAY_SIZE(dac_ch3_4_routes)); 698 } 699 700 static int cs530x_set_bclk(struct snd_soc_component *component, const int freq) 701 { 702 struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component); 703 struct regmap *regmap = cs530x->regmap; 704 unsigned int bclk_val; 705 706 switch (freq) { 707 case 2822400: 708 case 3072000: 709 bclk_val = CS530X_BCLK_2P822_3P072; 710 break; 711 case 5644800: 712 case 6144000: 713 bclk_val = CS530X_BCLK_5P6448_6P144; 714 break; 715 case 11289600: 716 case 12288000: 717 bclk_val = CS530X_BCLK_11P2896_12P288; 718 break; 719 case 22579200: 720 case 24576000: 721 bclk_val = CS530X_BCLK_24P5792_24P576; 722 break; 723 default: 724 dev_err(component->dev, "Invalid BCLK frequency %d\n", freq); 725 return -EINVAL; 726 } 727 728 dev_dbg(component->dev, "BCLK frequency is %d\n", freq); 729 730 return regmap_update_bits(regmap, CS530X_ASP_CFG, 731 CS530X_ASP_BCLK_FREQ_MASK, bclk_val); 732 } 733 734 static int cs530x_set_pll_refclk(struct snd_soc_component *component, 735 const unsigned int freq) 736 { 737 struct cs530x_priv *priv = snd_soc_component_get_drvdata(component); 738 struct regmap *regmap = priv->regmap; 739 unsigned int refclk; 740 741 switch (freq) { 742 case 2822400: 743 case 3072000: 744 refclk = CS530X_REFCLK_2P822_3P072; 745 break; 746 case 5644800: 747 case 6144000: 748 refclk = CS530X_REFCLK_5P6448_6P144; 749 break; 750 case 11289600: 751 case 12288000: 752 refclk = CS530X_REFCLK_11P2896_12P288; 753 break; 754 case 22579200: 755 case 24576000: 756 refclk = CS530X_REFCLK_24P5792_24P576; 757 break; 758 default: 759 dev_err(component->dev, "Invalid PLL refclk %d\n", freq); 760 return -EINVAL; 761 } 762 763 return regmap_update_bits(regmap, CS530X_CLK_CFG_0, 764 CS530X_PLL_REFCLK_FREQ_MASK, refclk); 765 } 766 767 static int cs530x_hw_params(struct snd_pcm_substream *substream, 768 struct snd_pcm_hw_params *params, 769 struct snd_soc_dai *dai) 770 { 771 struct snd_soc_component *component = dai->component; 772 struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component); 773 struct regmap *regmap = cs530x->regmap; 774 int ret = 0, fs = params_rate(params), bclk; 775 unsigned int fs_val; 776 777 switch (fs) { 778 case 32000: 779 fs_val = CS530X_FS_32K; 780 break; 781 case 44100: 782 case 48000: 783 fs_val = CS530X_FS_44P1K_48K; 784 break; 785 case 88200: 786 case 96000: 787 fs_val = CS530X_FS_88P2K_96K; 788 break; 789 case 176400: 790 case 192000: 791 fs_val = CS530X_FS_176P4K_192K; 792 break; 793 case 356800: 794 case 384000: 795 fs_val = CS530X_FS_356P8K_384K; 796 break; 797 case 705600: 798 case 768000: 799 fs_val = CS530X_FS_705P6K_768K; 800 break; 801 default: 802 dev_err(component->dev, "Invalid sample rate %d\n", fs); 803 return -EINVAL; 804 } 805 806 regmap_update_bits(regmap, CS530X_CLK_CFG_1, 807 CS530X_SAMPLE_RATE_MASK, fs_val); 808 809 810 if (regmap_test_bits(regmap, CS530X_SIGNAL_PATH_CFG, 811 CS530X_TDM_EN_MASK)) { 812 dev_dbg(component->dev, "Configuring for %d %d bit TDM slots\n", 813 cs530x->tdm_slots, cs530x->tdm_width); 814 bclk = snd_soc_tdm_params_to_bclk(params, 815 cs530x->tdm_width, 816 cs530x->tdm_slots, 817 1); 818 } else { 819 bclk = snd_soc_params_to_bclk(params); 820 } 821 822 if (!regmap_test_bits(regmap, CS530X_CLK_CFG_0, 823 CS530X_PLL_REFCLK_SRC_MASK)) { 824 ret = cs530x_set_pll_refclk(component, bclk); 825 if (ret) 826 return ret; 827 } 828 829 return cs530x_set_bclk(component, bclk); 830 } 831 832 static int cs530x_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 833 { 834 struct snd_soc_component *component = dai->component; 835 struct cs530x_priv *priv = snd_soc_component_get_drvdata(component); 836 struct regmap *regmap = priv->regmap; 837 unsigned int asp_fmt, asp_cfg = 0; 838 839 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 840 case SND_SOC_DAIFMT_CBC_CFC: 841 break; 842 case SND_SOC_DAIFMT_CBP_CFP: 843 asp_cfg = CS530X_ASP_PRIMARY; 844 break; 845 default: 846 return -EINVAL; 847 } 848 849 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 850 case SND_SOC_DAIFMT_DSP_A: 851 asp_fmt = CS530X_ASP_FMT_DSP_A; 852 break; 853 case SND_SOC_DAIFMT_I2S: 854 asp_fmt = CS530X_ASP_FMT_I2S; 855 break; 856 case SND_SOC_DAIFMT_LEFT_J: 857 asp_fmt = CS530X_ASP_FMT_LJ; 858 break; 859 default: 860 return -EINVAL; 861 } 862 863 switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 864 case SND_SOC_DAIFMT_NB_NF: 865 break; 866 case SND_SOC_DAIFMT_IB_IF: 867 asp_cfg |= CS530X_ASP_BCLK_INV; 868 break; 869 default: 870 return -EINVAL; 871 } 872 873 regmap_update_bits(regmap, CS530X_ASP_CFG, 874 CS530X_ASP_PRIMARY | CS530X_ASP_BCLK_INV, 875 asp_cfg); 876 877 return regmap_update_bits(regmap, CS530X_SIGNAL_PATH_CFG, 878 CS530X_ASP_FMT_MASK, asp_fmt); 879 } 880 881 static bool cs530x_check_mclk_freq(struct snd_soc_component *component, 882 const unsigned int freq) 883 { 884 switch (freq) { 885 case 24576000: 886 case 22579200: 887 case 12288000: 888 case 11289600: 889 return true; 890 default: 891 dev_err(component->dev, "Invalid MCLK %d\n", freq); 892 return false; 893 } 894 } 895 896 static int cs530x_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, 897 unsigned int rx_mask, int slots, int slot_width) 898 { 899 struct snd_soc_component *component = dai->component; 900 struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component); 901 struct regmap *regmap = cs530x->regmap; 902 unsigned int val; 903 904 switch (tx_mask) { 905 case CS530X_0_1_TDM_SLOT_MASK: 906 case CS530X_0_3_TDM_SLOT_MASK: 907 case CS530X_0_7_TDM_SLOT_MASK: 908 val = CS530X_0_7_TDM_SLOT_VAL; 909 break; 910 case CS530X_2_3_TDM_SLOT_MASK: 911 val = CS530X_2_3_TDM_SLOT_VAL; 912 break; 913 case CS530X_4_5_TDM_SLOT_MASK: 914 case CS530X_4_7_TDM_SLOT_MASK: 915 val = CS530X_4_7_TDM_SLOT_VAL; 916 break; 917 case CS530X_6_7_TDM_SLOT_MASK: 918 val = CS530X_6_7_TDM_SLOT_VAL; 919 break; 920 case CS530X_8_9_TDM_SLOT_MASK: 921 case CS530X_8_11_TDM_SLOT_MASK: 922 case CS530X_8_15_TDM_SLOT_MASK: 923 val = CS530X_8_15_TDM_SLOT_VAL; 924 break; 925 case CS530X_10_11_TDM_SLOT_MASK: 926 val = CS530X_10_11_TDM_SLOT_VAL; 927 break; 928 case CS530X_12_13_TDM_SLOT_MASK: 929 case CS530X_12_15_TDM_SLOT_MASK: 930 val = CS530X_12_15_TDM_SLOT_VAL; 931 break; 932 case CS530X_14_15_TDM_SLOT_MASK: 933 val = CS530X_14_15_TDM_SLOT_VAL; 934 break; 935 default: 936 dev_err(component->dev, "Invalid TX slot(s) 0x%x\n", tx_mask); 937 return -EINVAL; 938 } 939 940 cs530x->tdm_width = slot_width; 941 cs530x->tdm_slots = slots; 942 943 return regmap_update_bits(regmap, CS530X_SIGNAL_PATH_CFG, 944 CS530X_ASP_TDM_SLOT_MASK, 945 val << CS530X_ASP_TDM_SLOT_SHIFT); 946 } 947 948 static const struct snd_soc_dai_ops cs530x_dai_ops = { 949 .set_fmt = cs530x_set_fmt, 950 .hw_params = cs530x_hw_params, 951 .set_tdm_slot = cs530x_set_tdm_slot, 952 }; 953 954 static const struct snd_soc_dai_driver cs530x_dai = { 955 .name = "cs530x-dai", 956 .capture = { 957 .stream_name = "AIF Capture", 958 .rates = SNDRV_PCM_RATE_KNOT, 959 .formats = SNDRV_PCM_FMTBIT_S32_LE, 960 }, 961 .playback = { 962 .stream_name = "AIF Playback", 963 .rates = SNDRV_PCM_RATE_KNOT, 964 .formats = SNDRV_PCM_FMTBIT_S32_LE, 965 }, 966 .ops = &cs530x_dai_ops, 967 .symmetric_rate = 1, 968 .symmetric_sample_bits = 1, 969 }; 970 971 static int cs530x_set_pll(struct snd_soc_component *component, int pll_id, 972 int source, unsigned int freq_in, 973 unsigned int freq_out) 974 { 975 struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component); 976 struct regmap *regmap = cs530x->regmap; 977 unsigned int sysclk_src; 978 int ret; 979 980 regmap_read(regmap, CS530X_CLK_CFG_0, &sysclk_src); 981 982 /* Check if the source is the PLL */ 983 if ((sysclk_src & CS530X_SYSCLK_SRC_MASK) == 0) 984 return 0; 985 986 switch (source) { 987 case CS530X_PLL_SRC_MCLK: 988 if (!cs530x_check_mclk_freq(component, freq_in)) 989 return -EINVAL; 990 991 ret = cs530x_set_pll_refclk(component, freq_in); 992 if (ret) 993 return ret; 994 995 break; 996 case CS530X_PLL_SRC_BCLK: 997 break; 998 default: 999 dev_err(component->dev, "Invalid PLL source %d\n", source); 1000 return -EINVAL; 1001 } 1002 1003 return regmap_update_bits(regmap, CS530X_CLK_CFG_0, 1004 CS530X_PLL_REFCLK_SRC_MASK, source); 1005 } 1006 1007 static int cs530x_component_probe(struct snd_soc_component *component) 1008 { 1009 struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component); 1010 struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component); 1011 int num_widgets; 1012 1013 snd_soc_dapm_new_controls(dapm, cs530x_gen_dapm_widgets, 1014 ARRAY_SIZE(cs530x_gen_dapm_widgets)); 1015 1016 switch (cs530x->devtype) { 1017 case CS4282: 1018 cs530x_add_12_adc_widgets(component); 1019 cs530x_add_12_dac_widgets(component); 1020 break; 1021 case CS4302: 1022 cs530x_add_12_dac_widgets(component); 1023 break; 1024 case CS4304: 1025 cs530x_add_12_dac_widgets(component); 1026 cs530x_add_34_dac_widgets(component); 1027 1028 num_widgets = ARRAY_SIZE(cs530x_out_sum_4ch_controls); 1029 snd_soc_add_component_controls(component, 1030 cs530x_out_sum_4ch_controls, 1031 num_widgets); 1032 break; 1033 case CS4308: 1034 cs530x_add_12_dac_widgets(component); 1035 cs530x_add_34_dac_widgets(component); 1036 1037 num_widgets = ARRAY_SIZE(cs530x_out_5_to_8_controls); 1038 snd_soc_add_component_controls(component, 1039 cs530x_out_5_to_8_controls, 1040 num_widgets); 1041 1042 num_widgets = ARRAY_SIZE(cs530x_out_sum_8ch_controls); 1043 snd_soc_add_component_controls(component, 1044 cs530x_out_sum_8ch_controls, 1045 num_widgets); 1046 1047 num_widgets = ARRAY_SIZE(cs530x_dac_ch58_dapm_widgets); 1048 snd_soc_dapm_new_controls(dapm, cs530x_dac_ch58_dapm_widgets, 1049 num_widgets); 1050 1051 snd_soc_dapm_add_routes(dapm, dac_ch5_8_routes, 1052 ARRAY_SIZE(dac_ch5_8_routes)); 1053 break; 1054 case CS5302: 1055 cs530x_add_12_adc_widgets(component); 1056 break; 1057 case CS5304: 1058 cs530x_add_12_adc_widgets(component); 1059 cs530x_add_34_adc_widgets(component); 1060 1061 num_widgets = ARRAY_SIZE(cs530x_in_sum_4ch_controls); 1062 snd_soc_add_component_controls(component, 1063 cs530x_in_sum_4ch_controls, 1064 num_widgets); 1065 break; 1066 case CS5308: 1067 cs530x_add_12_adc_widgets(component); 1068 cs530x_add_34_adc_widgets(component); 1069 1070 num_widgets = ARRAY_SIZE(cs530x_in_5_to_8_controls); 1071 snd_soc_add_component_controls(component, 1072 cs530x_in_5_to_8_controls, 1073 num_widgets); 1074 1075 num_widgets = ARRAY_SIZE(cs530x_in_sum_8ch_controls); 1076 snd_soc_add_component_controls(component, 1077 cs530x_in_sum_8ch_controls, 1078 num_widgets); 1079 1080 num_widgets = ARRAY_SIZE(cs530x_adc_ch58_dapm_widgets); 1081 snd_soc_dapm_new_controls(dapm, cs530x_adc_ch58_dapm_widgets, 1082 num_widgets); 1083 1084 snd_soc_dapm_add_routes(dapm, adc_ch5_8_routes, 1085 ARRAY_SIZE(adc_ch5_8_routes)); 1086 break; 1087 default: 1088 dev_err(component->dev, "Invalid device type %d\n", 1089 cs530x->devtype); 1090 return -EINVAL; 1091 } 1092 1093 return 0; 1094 } 1095 1096 static int cs530x_set_sysclk(struct snd_soc_component *component, int clk_id, 1097 int source, unsigned int freq, int dir) 1098 { 1099 struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component); 1100 struct regmap *regmap = cs530x->regmap; 1101 1102 switch (source) { 1103 case CS530X_SYSCLK_SRC_MCLK: 1104 switch (freq) { 1105 case CS530X_SYSCLK_REF_45_1MHZ: 1106 case CS530X_SYSCLK_REF_49_1MHZ: 1107 break; 1108 default: 1109 dev_err(component->dev, "Invalid MCLK source rate %d\n", freq); 1110 return -EINVAL; 1111 } 1112 break; 1113 case CS530X_SYSCLK_SRC_PLL: 1114 break; 1115 default: 1116 dev_err(component->dev, "Invalid sysclk source: %d\n", source); 1117 return -EINVAL; 1118 } 1119 1120 return regmap_update_bits(regmap, CS530X_CLK_CFG_0, 1121 CS530X_SYSCLK_SRC_MASK, 1122 source << CS530X_SYSCLK_SRC_SHIFT); 1123 } 1124 1125 static const struct snd_soc_component_driver soc_component_dev_cs530x = { 1126 .probe = cs530x_component_probe, 1127 .set_sysclk = cs530x_set_sysclk, 1128 .set_pll = cs530x_set_pll, 1129 .endianness = 1, 1130 }; 1131 1132 const struct regmap_config cs530x_regmap_i2c = { 1133 .reg_bits = 16, 1134 .val_bits = 16, 1135 1136 .max_register = CS530X_MAX_REGISTER, 1137 .readable_reg = cs530x_readable_register, 1138 .writeable_reg = cs530x_writeable_register, 1139 1140 .cache_type = REGCACHE_MAPLE, 1141 .reg_defaults = cs530x_reg_defaults, 1142 .num_reg_defaults = ARRAY_SIZE(cs530x_reg_defaults), 1143 }; 1144 EXPORT_SYMBOL_NS_GPL(cs530x_regmap_i2c, "SND_SOC_CS530X"); 1145 1146 const struct regmap_config cs530x_regmap_spi = { 1147 .reg_bits = 16, 1148 .pad_bits = 16, 1149 .val_bits = 16, 1150 1151 .reg_stride = 2, 1152 1153 .reg_format_endian = REGMAP_ENDIAN_BIG, 1154 .val_format_endian = REGMAP_ENDIAN_BIG, 1155 1156 .max_register = CS530X_MAX_REGISTER, 1157 .writeable_reg = cs530x_writeable_register, 1158 .readable_reg = cs530x_readable_register, 1159 1160 .cache_type = REGCACHE_MAPLE, 1161 .reg_defaults = cs530x_reg_defaults, 1162 .num_reg_defaults = ARRAY_SIZE(cs530x_reg_defaults), 1163 }; 1164 EXPORT_SYMBOL_NS_GPL(cs530x_regmap_spi, "SND_SOC_CS530X"); 1165 1166 static int cs530x_check_device_id(struct cs530x_priv *cs530x) 1167 { 1168 struct device *dev = cs530x->dev; 1169 unsigned int dev_id, rev; 1170 int ret; 1171 1172 ret = regmap_read(cs530x->regmap, CS530X_DEVID, &dev_id); 1173 if (ret) 1174 return dev_err_probe(dev, ret, "Can't read device ID\n"); 1175 1176 ret = regmap_read(cs530x->regmap, CS530X_REVID, &rev); 1177 if (ret) 1178 return dev_err_probe(dev, ret, "Can't read REV ID\n"); 1179 1180 switch (dev_id) { 1181 case CS530X_2CH_CODEC_DEV_ID: 1182 cs530x->num_dacs = 2; 1183 cs530x->num_adcs = 2; 1184 break; 1185 case CS530X_2CH_DAC_DEV_ID: 1186 cs530x->num_dacs = 2; 1187 break; 1188 case CS530X_4CH_DAC_DEV_ID: 1189 cs530x->num_dacs = 4; 1190 break; 1191 case CS530X_8CH_DAC_DEV_ID: 1192 cs530x->num_dacs = 8; 1193 break; 1194 case CS530X_2CH_ADC_DEV_ID: 1195 cs530x->num_adcs = 2; 1196 break; 1197 case CS530X_4CH_ADC_DEV_ID: 1198 cs530x->num_adcs = 4; 1199 break; 1200 case CS530X_8CH_ADC_DEV_ID: 1201 cs530x->num_adcs = 8; 1202 break; 1203 default: 1204 return dev_err_probe(dev, -EINVAL, "Invalid device ID 0x%x\n", 1205 dev_id); 1206 } 1207 1208 if (cs530x->devtype != dev_id) { 1209 dev_err(dev, "Read device ID 0x%x is not the expected devtype 0x%x\n", 1210 dev_id, cs530x->devtype); 1211 return -EINVAL; 1212 } 1213 1214 dev_dbg(dev, "Device ID 0x%x Rev ID 0x%x (%d in %d out)\n", dev_id, rev, 1215 cs530x->num_adcs, cs530x->num_dacs); 1216 1217 return 0; 1218 } 1219 1220 static int cs530x_parse_device_properties(struct cs530x_priv *cs530x) 1221 { 1222 struct regmap *regmap = cs530x->regmap; 1223 struct device *dev = cs530x->dev; 1224 unsigned int val = 0; 1225 1226 switch (cs530x->num_adcs) { 1227 case 8: 1228 if (device_property_read_bool(dev, "cirrus,in-hiz-pin78")) 1229 val = CS530X_IN78_HIZ; 1230 1231 if (device_property_read_bool(dev, "cirrus,in-hiz-pin56")) 1232 val |= CS530X_IN56_HIZ; 1233 1234 fallthrough; 1235 case 4: 1236 if (device_property_read_bool(dev, "cirrus,in-hiz-pin34")) 1237 val |= CS530X_IN34_HIZ; 1238 1239 fallthrough; 1240 case 2: 1241 if (device_property_read_bool(dev, "cirrus,in-hiz-pin12")) 1242 val |= CS530X_IN12_HIZ; 1243 1244 return regmap_set_bits(regmap, CS530X_IN_HIZ, val); 1245 case 0: 1246 /* No ADCs */ 1247 return 0; 1248 default: 1249 return dev_err_probe(dev, -EINVAL, 1250 "Invalid number of adcs %d\n", 1251 cs530x->num_adcs); 1252 } 1253 } 1254 1255 int cs530x_probe(struct cs530x_priv *cs530x) 1256 { 1257 struct device *dev = cs530x->dev; 1258 int ret, i; 1259 1260 cs530x->dev_dai = devm_kmemdup(dev, &cs530x_dai, 1261 sizeof(*(cs530x->dev_dai)), 1262 GFP_KERNEL); 1263 if (!cs530x->dev_dai) 1264 return -ENOMEM; 1265 1266 for (i = 0; i < ARRAY_SIZE(cs530x->supplies); i++) 1267 cs530x->supplies[i].supply = cs530x_supply_names[i]; 1268 1269 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(cs530x->supplies), 1270 cs530x->supplies); 1271 if (ret != 0) 1272 return dev_err_probe(dev, ret, "Failed to request supplies"); 1273 1274 ret = regulator_bulk_enable(ARRAY_SIZE(cs530x->supplies), 1275 cs530x->supplies); 1276 if (ret != 0) 1277 return dev_err_probe(dev, ret, "Failed to enable supplies"); 1278 1279 cs530x->reset_gpio = devm_gpiod_get_optional(dev, "reset", 1280 GPIOD_OUT_HIGH); 1281 if (IS_ERR(cs530x->reset_gpio)) { 1282 ret = dev_err_probe(dev, PTR_ERR(cs530x->reset_gpio), 1283 "Reset gpio not available\n"); 1284 goto err_regulator; 1285 } 1286 1287 if (cs530x->reset_gpio) { 1288 usleep_range(2000, 2100); 1289 gpiod_set_value_cansleep(cs530x->reset_gpio, 0); 1290 } 1291 1292 usleep_range(5000, 5100); 1293 ret = cs530x_check_device_id(cs530x); 1294 if (ret) 1295 goto err_reset; 1296 1297 if (!cs530x->reset_gpio) { 1298 ret = regmap_write(cs530x->regmap, CS530X_SW_RESET, 1299 CS530X_SW_RST_VAL); 1300 if (ret) { 1301 dev_err_probe(dev, ret, "Soft Reset Failed\n"); 1302 goto err_reset; 1303 } 1304 } 1305 1306 ret = cs530x_parse_device_properties(cs530x); 1307 if (ret) 1308 goto err_reset; 1309 1310 if (cs530x->num_adcs) { 1311 cs530x->dev_dai->capture.channels_min = 2; 1312 cs530x->dev_dai->capture.channels_max = cs530x->num_adcs; 1313 } 1314 1315 if (cs530x->num_dacs) { 1316 cs530x->dev_dai->playback.channels_min = 2; 1317 cs530x->dev_dai->playback.channels_max = cs530x->num_dacs; 1318 } 1319 1320 ret = devm_snd_soc_register_component(dev, 1321 &soc_component_dev_cs530x, 1322 cs530x->dev_dai, 1); 1323 if (ret) { 1324 dev_err_probe(dev, ret, "Can't register cs530x component\n"); 1325 goto err_reset; 1326 } 1327 1328 return 0; 1329 1330 err_reset: 1331 gpiod_set_value_cansleep(cs530x->reset_gpio, 1); 1332 1333 err_regulator: 1334 regulator_bulk_disable(ARRAY_SIZE(cs530x->supplies), 1335 cs530x->supplies); 1336 1337 return ret; 1338 } 1339 EXPORT_SYMBOL_NS_GPL(cs530x_probe, "SND_SOC_CS530X"); 1340 1341 MODULE_DESCRIPTION("CS530X CODEC Driver"); 1342 MODULE_AUTHOR("Paul Handrigan <paulha@opensource.cirrus.com>"); 1343 MODULE_LICENSE("GPL"); 1344