Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ASoC: cs530x: Add CODEC and DAC support

- Added DAC register address constants
- Add the new registers to the regmap config
- Renamed constants that are shared between the DACs and ADCs
- Add the device IDs and device names of the CODEC and DACs along with
their different capabilities
- Add DAPM widgets, ALSA controls and event handling for the DAC
functionality
- Add Playback DAI support

Signed-off-by: Simon Trimmer <simont@opensource.cirrus.com>
Signed-off-by: Vitaly Rodionov <vitalyr@opensource.cirrus.com>
Link: https://patch.msgid.link/20251023090327.58275-7-vitalyr@opensource.cirrus.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Simon Trimmer and committed by
Mark Brown
c63b2315 9957614d

+440 -45
+16
sound/soc/codecs/cs530x-i2c.c
··· 14 14 15 15 static const struct of_device_id cs530x_of_match[] = { 16 16 { 17 + .compatible = "cirrus,cs4282", 18 + .data = (void *)CS4282, 19 + }, { 20 + .compatible = "cirrus,cs4302", 21 + .data = (void *)CS4302, 22 + }, { 23 + .compatible = "cirrus,cs4304", 24 + .data = (void *)CS4304, 25 + }, { 26 + .compatible = "cirrus,cs4308", 27 + .data = (void *)CS4308, 28 + }, { 17 29 .compatible = "cirrus,cs5302", 18 30 .data = (void *)CS5302, 19 31 }, { ··· 40 28 MODULE_DEVICE_TABLE(of, cs530x_of_match); 41 29 42 30 static const struct i2c_device_id cs530x_i2c_id[] = { 31 + { "cs4282", CS4282 }, 32 + { "cs4302", CS4302 }, 33 + { "cs4304", CS4304 }, 34 + { "cs4308", CS4308 }, 43 35 { "cs5302", CS5302 }, 44 36 { "cs5304", CS5304 }, 45 37 { "cs5308", CS5308 },
+382 -29
sound/soc/codecs/cs530x.c
··· 45 45 { CS530X_IN_VOL_CTRL3_1, 0x8000 }, 46 46 { CS530X_IN_VOL_CTRL4_0, 0x8000 }, 47 47 { CS530X_IN_VOL_CTRL4_1, 0x8000 }, 48 + { CS530X_OUT_ENABLES, 0 }, 49 + { CS530X_OUT_RAMP_SUM, 0x0022 }, 50 + { CS530X_OUT_FILTER, 0 }, 51 + { CS530X_OUT_INV, 0 }, 52 + { CS530X_OUT_VOL_CTRL1_0, 0x8000 }, 53 + { CS530X_OUT_VOL_CTRL1_1, 0x8000 }, 54 + { CS530X_OUT_VOL_CTRL2_0, 0x8000 }, 55 + { CS530X_OUT_VOL_CTRL2_1, 0x8000 }, 56 + { CS530X_OUT_VOL_CTRL3_0, 0x8000 }, 57 + { CS530X_OUT_VOL_CTRL3_1, 0x8000 }, 58 + { CS530X_OUT_VOL_CTRL4_0, 0x8000 }, 59 + { CS530X_OUT_VOL_CTRL4_1, 0x8000 }, 48 60 { CS530X_PAD_FN, 0 }, 49 61 { CS530X_PAD_LVL, 0 }, 50 62 }; ··· 82 70 case CS530X_IN_VOL_CTRL3_1: 83 71 case CS530X_IN_VOL_CTRL4_0: 84 72 case CS530X_IN_VOL_CTRL4_1: 73 + case CS530X_OUT_ENABLES: 74 + case CS530X_OUT_RAMP_SUM: 75 + case CS530X_OUT_DEEMPH: 76 + case CS530X_OUT_FILTER: 77 + case CS530X_OUT_INV: 78 + case CS530X_OUT_VOL_CTRL1_0: 79 + case CS530X_OUT_VOL_CTRL1_1: 80 + case CS530X_OUT_VOL_CTRL2_0: 81 + case CS530X_OUT_VOL_CTRL2_1: 82 + case CS530X_OUT_VOL_CTRL3_0: 83 + case CS530X_OUT_VOL_CTRL3_1: 84 + case CS530X_OUT_VOL_CTRL4_0: 85 + case CS530X_OUT_VOL_CTRL4_1: 85 86 case CS530X_PAD_FN: 86 87 case CS530X_PAD_LVL: 87 88 return true; ··· 119 94 switch (reg) { 120 95 case CS530X_SW_RESET: 121 96 case CS530X_IN_VOL_CTRL5: 97 + case CS530X_OUT_VOL_CTRL5: 122 98 return true; 123 99 default: 124 100 return cs530x_read_and_write_regs(reg); ··· 152 126 153 127 static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -1270, 50, 0); 154 128 155 - static const char * const cs530x_in_filter_text[] = { 129 + static const char * const cs530x_inout_filter_text[] = { 156 130 "Min Phase Slow Roll-off", 157 131 "Min Phase Fast Roll-off", 158 132 "Linear Phase Slow Roll-off", ··· 160 134 }; 161 135 162 136 static SOC_ENUM_SINGLE_DECL(cs530x_in_filter_enum, CS530X_IN_FILTER, 163 - CS530X_IN_FILTER_SHIFT, 164 - cs530x_in_filter_text); 137 + CS530X_INOUT_FILTER_SHIFT, 138 + cs530x_inout_filter_text); 165 139 166 - static const char * const cs530x_in_4ch_sum_text[] = { 140 + static SOC_ENUM_SINGLE_DECL(cs530x_out_filter_enum, CS530X_OUT_FILTER, 141 + CS530X_INOUT_FILTER_SHIFT, 142 + cs530x_inout_filter_text); 143 + 144 + static const char * const cs530x_4ch_sum_text[] = { 167 145 "None", 168 146 "Groups of 2", 169 147 "Groups of 4", 170 148 }; 171 149 172 150 static SOC_ENUM_SINGLE_DECL(cs530x_in_sum_ch4_enum, CS530X_IN_RAMP_SUM, 173 - CS530X_IN_SUM_MODE_SHIFT, 174 - cs530x_in_4ch_sum_text); 151 + CS530X_INOUT_SUM_MODE_SHIFT, 152 + cs530x_4ch_sum_text); 175 153 176 154 static const struct snd_kcontrol_new cs530x_in_sum_4ch_controls[] = { 177 155 SOC_ENUM("IN Sum Select", cs530x_in_sum_ch4_enum), 178 156 }; 179 157 180 - static const char * const cs530x_in_8ch_sum_text[] = { 158 + static SOC_ENUM_SINGLE_DECL(cs530x_out_sum_ch4_enum, CS530X_OUT_RAMP_SUM, 159 + CS530X_INOUT_SUM_MODE_SHIFT, 160 + cs530x_4ch_sum_text); 161 + 162 + static const struct snd_kcontrol_new cs530x_out_sum_4ch_controls[] = { 163 + SOC_ENUM("OUT Sum Select", cs530x_out_sum_ch4_enum), 164 + }; 165 + 166 + static const char * const cs530x_8ch_sum_text[] = { 181 167 "None", 182 168 "Groups of 2", 183 169 "Groups of 4", ··· 197 159 }; 198 160 199 161 static SOC_ENUM_SINGLE_DECL(cs530x_in_sum_ch8_enum, CS530X_IN_RAMP_SUM, 200 - CS530X_IN_SUM_MODE_SHIFT, 201 - cs530x_in_8ch_sum_text); 162 + CS530X_INOUT_SUM_MODE_SHIFT, 163 + cs530x_8ch_sum_text); 202 164 203 165 static const struct snd_kcontrol_new cs530x_in_sum_8ch_controls[] = { 204 166 SOC_ENUM("IN Sum Select", cs530x_in_sum_ch8_enum), 205 167 }; 206 168 169 + static SOC_ENUM_SINGLE_DECL(cs530x_out_sum_ch8_enum, CS530X_OUT_RAMP_SUM, 170 + CS530X_INOUT_SUM_MODE_SHIFT, 171 + cs530x_8ch_sum_text); 172 + 173 + static const struct snd_kcontrol_new cs530x_out_sum_8ch_controls[] = { 174 + SOC_ENUM("OUT Sum Select", cs530x_out_sum_ch8_enum), 175 + }; 207 176 208 177 static const char * const cs530x_vol_ramp_text[] = { 209 178 "0ms/6dB", "0.5ms/6dB", "1ms/6dB", "2ms/6dB", "4ms/6dB", "8ms/6dB", ··· 235 190 SOC_ENUM("Input Ramp Up", cs530x_ramp_inc_enum), 236 191 SOC_ENUM("Input Ramp Down", cs530x_ramp_dec_enum), 237 192 238 - SOC_SINGLE("ADC1 Invert Switch", CS530X_IN_INV, CS530X_IN1_INV_SHIFT, 1, 0), 239 - SOC_SINGLE("ADC2 Invert Switch", CS530X_IN_INV, CS530X_IN2_INV_SHIFT, 1, 0), 193 + SOC_SINGLE("ADC1 Invert Switch", CS530X_IN_INV, CS530X_INOUT1_INV_SHIFT, 1, 0), 194 + SOC_SINGLE("ADC2 Invert Switch", CS530X_IN_INV, CS530X_INOUT2_INV_SHIFT, 1, 0), 240 195 }; 241 196 242 197 static const struct snd_kcontrol_new cs530x_in_3_to_4_controls[] = { ··· 245 200 SOC_SINGLE_EXT_TLV("IN4 Volume", CS530X_IN_VOL_CTRL2_1, 0, 255, 1, 246 201 snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv), 247 202 248 - SOC_SINGLE("ADC3 Invert Switch", CS530X_IN_INV, CS530X_IN3_INV_SHIFT, 1, 0), 249 - SOC_SINGLE("ADC4 Invert Switch", CS530X_IN_INV, CS530X_IN4_INV_SHIFT, 1, 0), 203 + SOC_SINGLE("ADC3 Invert Switch", CS530X_IN_INV, CS530X_INOUT3_INV_SHIFT, 1, 0), 204 + SOC_SINGLE("ADC4 Invert Switch", CS530X_IN_INV, CS530X_INOUT4_INV_SHIFT, 1, 0), 250 205 }; 251 206 252 207 static const struct snd_kcontrol_new cs530x_in_5_to_8_controls[] = { ··· 259 214 SOC_SINGLE_EXT_TLV("IN8 Volume", CS530X_IN_VOL_CTRL4_1, 0, 255, 1, 260 215 snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv), 261 216 262 - SOC_SINGLE("ADC5 Invert Switch", CS530X_IN_INV, CS530X_IN5_INV_SHIFT, 1, 0), 263 - SOC_SINGLE("ADC6 Invert Switch", CS530X_IN_INV, CS530X_IN6_INV_SHIFT, 1, 0), 264 - SOC_SINGLE("ADC7 Invert Switch", CS530X_IN_INV, CS530X_IN7_INV_SHIFT, 1, 0), 265 - SOC_SINGLE("ADC8 Invert Switch", CS530X_IN_INV, CS530X_IN8_INV_SHIFT, 1, 0), 217 + SOC_SINGLE("ADC5 Invert Switch", CS530X_IN_INV, CS530X_INOUT5_INV_SHIFT, 1, 0), 218 + SOC_SINGLE("ADC6 Invert Switch", CS530X_IN_INV, CS530X_INOUT6_INV_SHIFT, 1, 0), 219 + SOC_SINGLE("ADC7 Invert Switch", CS530X_IN_INV, CS530X_INOUT7_INV_SHIFT, 1, 0), 220 + SOC_SINGLE("ADC8 Invert Switch", CS530X_IN_INV, CS530X_INOUT8_INV_SHIFT, 1, 0), 266 221 }; 267 222 268 223 static int cs530x_adc_event(struct snd_soc_dapm_widget *w, ··· 278 233 break; 279 234 case SND_SOC_DAPM_POST_PMU: 280 235 regmap_clear_bits(regmap, CS530X_IN_VOL_CTRL1_0 + 281 - (w->shift * 2), CS530X_IN_MUTE); 236 + (w->shift * 2), CS530X_INOUT_MUTE); 282 237 regmap_clear_bits(regmap, CS530X_IN_VOL_CTRL1_0 + 283 - ((w->shift + 1) * 2), CS530X_IN_MUTE); 238 + ((w->shift + 1) * 2), CS530X_INOUT_MUTE); 284 239 285 240 cs530x->adc_pairs_count--; 286 241 if (!cs530x->adc_pairs_count) { 287 242 usleep_range(1000, 1100); 288 243 return regmap_write(regmap, CS530X_IN_VOL_CTRL5, 289 - CS530X_IN_VU); 244 + CS530X_INOUT_VU); 290 245 } 291 246 break; 292 247 case SND_SOC_DAPM_PRE_PMD: 293 248 regmap_set_bits(regmap, CS530X_IN_VOL_CTRL1_0 + 294 - (w->shift * 2), CS530X_IN_MUTE); 249 + (w->shift * 2), CS530X_INOUT_MUTE); 295 250 regmap_set_bits(regmap, CS530X_IN_VOL_CTRL1_0 + 296 - ((w->shift + 1) * 2), CS530X_IN_MUTE); 251 + ((w->shift + 1) * 2), CS530X_INOUT_MUTE); 297 252 return regmap_write(regmap, CS530X_IN_VOL_CTRL5, 298 - CS530X_IN_VU); 253 + CS530X_INOUT_VU); 254 + default: 255 + return -EINVAL; 256 + } 257 + 258 + return 0; 259 + } 260 + 261 + static SOC_ENUM_SINGLE_DECL(cs530x_ramp_out_inc_enum, CS530X_OUT_RAMP_SUM, 262 + CS530X_RAMP_RATE_INC_SHIFT, 263 + cs530x_vol_ramp_text); 264 + 265 + static SOC_ENUM_SINGLE_DECL(cs530x_ramp_out_dec_enum, CS530X_OUT_RAMP_SUM, 266 + CS530X_RAMP_RATE_DEC_SHIFT, 267 + cs530x_vol_ramp_text); 268 + 269 + static const struct snd_kcontrol_new cs530x_out_1_to_2_controls[] = { 270 + SOC_SINGLE_EXT_TLV("OUT1 Volume", CS530X_OUT_VOL_CTRL1_0, 0, 255, 1, 271 + snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv), 272 + SOC_SINGLE_EXT_TLV("OUT2 Volume", CS530X_OUT_VOL_CTRL1_1, 0, 255, 1, 273 + snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv), 274 + 275 + SOC_ENUM("OUT DEC Filter Select", cs530x_out_filter_enum), 276 + SOC_ENUM("Output Ramp Up", cs530x_ramp_out_inc_enum), 277 + SOC_ENUM("Output Ramp Down", cs530x_ramp_out_dec_enum), 278 + 279 + SOC_SINGLE("DAC1 Invert Switch", CS530X_OUT_INV, CS530X_INOUT1_INV_SHIFT, 1, 0), 280 + SOC_SINGLE("DAC2 Invert Switch", CS530X_OUT_INV, CS530X_INOUT2_INV_SHIFT, 1, 0), 281 + }; 282 + 283 + static const struct snd_kcontrol_new cs530x_out_3_to_4_controls[] = { 284 + SOC_SINGLE_EXT_TLV("OUT3 Volume", CS530X_OUT_VOL_CTRL2_0, 0, 255, 1, 285 + snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv), 286 + SOC_SINGLE_EXT_TLV("OUT4 Volume", CS530X_OUT_VOL_CTRL2_1, 0, 255, 1, 287 + snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv), 288 + 289 + SOC_SINGLE("DAC3 Invert Switch", CS530X_OUT_INV, CS530X_INOUT3_INV_SHIFT, 1, 0), 290 + SOC_SINGLE("DAC4 Invert Switch", CS530X_OUT_INV, CS530X_INOUT4_INV_SHIFT, 1, 0), 291 + }; 292 + 293 + static const struct snd_kcontrol_new cs530x_out_5_to_8_controls[] = { 294 + SOC_SINGLE_EXT_TLV("OUT5 Volume", CS530X_OUT_VOL_CTRL3_0, 0, 255, 1, 295 + snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv), 296 + SOC_SINGLE_EXT_TLV("OUT6 Volume", CS530X_OUT_VOL_CTRL3_1, 0, 255, 1, 297 + snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv), 298 + SOC_SINGLE_EXT_TLV("OUT7 Volume", CS530X_OUT_VOL_CTRL4_0, 0, 255, 1, 299 + snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv), 300 + SOC_SINGLE_EXT_TLV("OUT8 Volume", CS530X_OUT_VOL_CTRL4_1, 0, 255, 1, 301 + snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv), 302 + 303 + SOC_SINGLE("DAC5 Invert Switch", CS530X_OUT_INV, CS530X_INOUT5_INV_SHIFT, 1, 0), 304 + SOC_SINGLE("DAC6 Invert Switch", CS530X_OUT_INV, CS530X_INOUT6_INV_SHIFT, 1, 0), 305 + SOC_SINGLE("DAC7 Invert Switch", CS530X_OUT_INV, CS530X_INOUT7_INV_SHIFT, 1, 0), 306 + SOC_SINGLE("DAC8 Invert Switch", CS530X_OUT_INV, CS530X_INOUT8_INV_SHIFT, 1, 0), 307 + }; 308 + 309 + static int cs530x_dac_event(struct snd_soc_dapm_widget *w, 310 + struct snd_kcontrol *kcontrol, int event) 311 + { 312 + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 313 + struct cs530x_priv *cs530x = snd_soc_component_get_drvdata(component); 314 + struct regmap *regmap = cs530x->regmap; 315 + 316 + switch (event) { 317 + case SND_SOC_DAPM_PRE_PMU: 318 + cs530x->dac_pairs_count++; 319 + break; 320 + case SND_SOC_DAPM_POST_PMU: 321 + regmap_clear_bits(regmap, CS530X_OUT_VOL_CTRL1_0 + 322 + (w->shift * 2), CS530X_INOUT_MUTE); 323 + regmap_clear_bits(regmap, CS530X_OUT_VOL_CTRL1_0 + 324 + ((w->shift + 1) * 2), CS530X_INOUT_MUTE); 325 + 326 + cs530x->dac_pairs_count--; 327 + if (!cs530x->dac_pairs_count) { 328 + usleep_range(1000, 1100); 329 + return regmap_write(regmap, CS530X_OUT_VOL_CTRL5, 330 + CS530X_INOUT_VU); 331 + } 332 + break; 333 + case SND_SOC_DAPM_PRE_PMD: 334 + regmap_set_bits(regmap, CS530X_OUT_VOL_CTRL1_0 + 335 + (w->shift * 2), CS530X_INOUT_MUTE); 336 + regmap_set_bits(regmap, CS530X_OUT_VOL_CTRL1_0 + 337 + ((w->shift + 1) * 2), CS530X_INOUT_MUTE); 338 + return regmap_write(regmap, CS530X_OUT_VOL_CTRL5, 339 + CS530X_INOUT_VU); 299 340 default: 300 341 return -EINVAL; 301 342 } ··· 397 266 SOC_DAPM_SINGLE_VIRT("Switch", 1); 398 267 static const struct snd_kcontrol_new adc78_ctrl = 399 268 SOC_DAPM_SINGLE_VIRT("Switch", 1); 269 + static const struct snd_kcontrol_new dac12_ctrl = 270 + SOC_DAPM_SINGLE_VIRT("Switch", 1); 271 + static const struct snd_kcontrol_new dac34_ctrl = 272 + SOC_DAPM_SINGLE_VIRT("Switch", 1); 273 + static const struct snd_kcontrol_new dac56_ctrl = 274 + SOC_DAPM_SINGLE_VIRT("Switch", 1); 275 + static const struct snd_kcontrol_new dac78_ctrl = 276 + SOC_DAPM_SINGLE_VIRT("Switch", 1); 400 277 static const struct snd_kcontrol_new in_hpf_ctrl = 278 + SOC_DAPM_SINGLE_VIRT("Switch", 1); 279 + static const struct snd_kcontrol_new out_hpf_ctrl = 401 280 SOC_DAPM_SINGLE_VIRT("Switch", 1); 402 281 403 282 /* General DAPM widgets for all devices */ ··· 425 284 SND_SOC_DAPM_PRE_PMU), 426 285 SND_SOC_DAPM_ADC("ADC2", NULL, CS530X_IN_ENABLES, 1, 0), 427 286 SND_SOC_DAPM_SWITCH("ADC12 Enable", SND_SOC_NOPM, 0, 0, &adc12_ctrl), 428 - SND_SOC_DAPM_SWITCH("IN HPF", CS530X_IN_FILTER, CS530X_IN_HPF_EN_SHIFT, 287 + SND_SOC_DAPM_SWITCH("IN HPF", CS530X_IN_FILTER, CS530X_INOUT_HPF_EN_SHIFT, 429 288 0, &in_hpf_ctrl), 430 289 }; 431 290 ··· 547 406 548 407 snd_soc_dapm_add_routes(dapm, adc_ch3_4_routes, 549 408 ARRAY_SIZE(adc_ch3_4_routes)); 409 + } 410 + 411 + /* DAC's Channels 1 and 2 plus generic DAC DAPM events */ 412 + static const struct snd_soc_dapm_widget cs530x_dac_ch12_dapm_widgets[] = { 413 + SND_SOC_DAPM_OUTPUT("OUT1"), 414 + SND_SOC_DAPM_OUTPUT("OUT2"), 415 + SND_SOC_DAPM_DAC_E("DAC1", NULL, CS530X_OUT_ENABLES, 0, 0, 416 + cs530x_dac_event, 417 + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU | 418 + SND_SOC_DAPM_PRE_PMU), 419 + SND_SOC_DAPM_DAC("DAC2", NULL, CS530X_OUT_ENABLES, 1, 0), 420 + SND_SOC_DAPM_SWITCH("DAC12 Enable", SND_SOC_NOPM, 0, 0, &dac12_ctrl), 421 + SND_SOC_DAPM_SWITCH("OUT HPF", CS530X_OUT_FILTER, CS530X_INOUT_HPF_EN_SHIFT, 422 + 0, &out_hpf_ctrl), 423 + }; 424 + 425 + /* DAC's Channels 3 and 4 */ 426 + static const struct snd_soc_dapm_widget cs530x_dac_ch34_dapm_widgets[] = { 427 + SND_SOC_DAPM_OUTPUT("OUT3"), 428 + SND_SOC_DAPM_OUTPUT("OUT4"), 429 + SND_SOC_DAPM_DAC_E("DAC3", NULL, CS530X_OUT_ENABLES, 2, 0, 430 + cs530x_dac_event, 431 + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU | 432 + SND_SOC_DAPM_PRE_PMU), 433 + SND_SOC_DAPM_DAC("DAC4", NULL, CS530X_OUT_ENABLES, 3, 0), 434 + SND_SOC_DAPM_SWITCH("DAC34 Enable", SND_SOC_NOPM, 0, 0, &dac34_ctrl), 435 + }; 436 + 437 + /* DAC's Channels 5 to 8 */ 438 + static const struct snd_soc_dapm_widget cs530x_dac_ch58_dapm_widgets[] = { 439 + SND_SOC_DAPM_OUTPUT("OUT5"), 440 + SND_SOC_DAPM_OUTPUT("OUT6"), 441 + SND_SOC_DAPM_OUTPUT("OUT7"), 442 + SND_SOC_DAPM_OUTPUT("OUT8"), 443 + SND_SOC_DAPM_DAC_E("DAC5", NULL, CS530X_OUT_ENABLES, 4, 0, 444 + cs530x_dac_event, 445 + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU | 446 + SND_SOC_DAPM_PRE_PMU), 447 + SND_SOC_DAPM_DAC("DAC6", NULL, CS530X_OUT_ENABLES, 5, 0), 448 + SND_SOC_DAPM_SWITCH("DAC56 Enable", SND_SOC_NOPM, 0, 0, &dac56_ctrl), 449 + SND_SOC_DAPM_DAC_E("DAC7", NULL, CS530X_OUT_ENABLES, 6, 0, 450 + cs530x_dac_event, 451 + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU | 452 + SND_SOC_DAPM_PRE_PMU), 453 + SND_SOC_DAPM_DAC("DAC8", NULL, CS530X_OUT_ENABLES, 7, 0), 454 + SND_SOC_DAPM_SWITCH("DAC78 Enable", SND_SOC_NOPM, 0, 0, &dac78_ctrl), 455 + }; 456 + 457 + static const struct snd_soc_dapm_route dac_ch1_2_routes[] = { 458 + { "DAC1", NULL, "Global Enable" }, 459 + { "DAC2", NULL, "Global Enable" }, 460 + 461 + { "DAC12 Enable", "Switch", "OUT1" }, 462 + { "DAC12 Enable", "Switch", "OUT2" }, 463 + { "DAC1", NULL, "DAC12 Enable" }, 464 + { "DAC2", NULL, "DAC12 Enable" }, 465 + { "OUT HPF", "Switch", "DAC1" }, 466 + { "OUT HPF", "Switch", "DAC2" }, 467 + 468 + { "OUT HPF", NULL, "AIF Playback" }, 469 + { "DAC1", NULL, "AIF Playback" }, 470 + { "DAC2", NULL, "AIF Playback" }, 471 + 472 + { "OUT1", NULL, "DAC1" }, 473 + { "OUT2", NULL, "DAC2" }, 474 + }; 475 + 476 + static const struct snd_soc_dapm_route dac_ch3_4_routes[] = { 477 + { "DAC3", NULL, "Global Enable" }, 478 + { "DAC4", NULL, "Global Enable" }, 479 + 480 + { "DAC34 Enable", "Switch", "OUT3" }, 481 + { "DAC34 Enable", "Switch", "OUT4" }, 482 + { "DAC3", NULL, "DAC34 Enable" }, 483 + { "DAC4", NULL, "DAC34 Enable" }, 484 + { "OUT HPF", "Switch", "DAC3" }, 485 + { "OUT HPF", "Switch", "DAC4" }, 486 + 487 + { "DAC3", NULL, "AIF Playback" }, 488 + { "DAC4", NULL, "AIF Playback" }, 489 + 490 + { "OUT3", NULL, "DAC3" }, 491 + { "OUT4", NULL, "DAC4" }, 492 + }; 493 + 494 + static const struct snd_soc_dapm_route dac_ch5_8_routes[] = { 495 + { "DAC5", NULL, "Global Enable" }, 496 + { "DAC6", NULL, "Global Enable" }, 497 + 498 + { "DAC56 Enable", "Switch", "OUT5" }, 499 + { "DAC56 Enable", "Switch", "OUT6" }, 500 + { "DAC5", NULL, "DAC56 Enable" }, 501 + { "DAC6", NULL, "DAC56 Enable" }, 502 + { "OUT HPF", "Switch", "DAC5" }, 503 + { "OUT HPF", "Switch", "DAC6" }, 504 + 505 + { "DAC5", NULL, "AIF Playback" }, 506 + { "DAC6", NULL, "AIF Playback" }, 507 + 508 + { "OUT5", NULL, "DAC5" }, 509 + { "OUT6", NULL, "DAC6" }, 510 + 511 + { "DAC7", NULL, "Global Enable" }, 512 + { "DAC8", NULL, "Global Enable" }, 513 + 514 + { "DAC78 Enable", "Switch", "OUT7" }, 515 + { "DAC78 Enable", "Switch", "OUT8" }, 516 + { "DAC7", NULL, "DAC78 Enable" }, 517 + { "DAC8", NULL, "DAC78 Enable" }, 518 + { "OUT HPF", "Switch", "DAC7" }, 519 + { "OUT HPF", "Switch", "DAC8" }, 520 + 521 + { "DAC7", NULL, "AIF Playback" }, 522 + { "DAC8", NULL, "AIF Playback" }, 523 + 524 + { "OUT7", NULL, "DAC7" }, 525 + { "OUT8", NULL, "DAC8" }, 526 + }; 527 + 528 + static void cs530x_add_12_dac_widgets(struct snd_soc_component *component) 529 + { 530 + struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); 531 + 532 + snd_soc_add_component_controls(component, 533 + cs530x_out_1_to_2_controls, 534 + ARRAY_SIZE(cs530x_out_1_to_2_controls)); 535 + 536 + snd_soc_dapm_new_controls(dapm, cs530x_dac_ch12_dapm_widgets, 537 + ARRAY_SIZE(cs530x_dac_ch12_dapm_widgets)); 538 + 539 + snd_soc_dapm_add_routes(dapm, dac_ch1_2_routes, 540 + ARRAY_SIZE(dac_ch1_2_routes)); 541 + } 542 + 543 + static void cs530x_add_34_dac_widgets(struct snd_soc_component *component) 544 + { 545 + struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); 546 + 547 + snd_soc_add_component_controls(component, 548 + cs530x_out_3_to_4_controls, 549 + ARRAY_SIZE(cs530x_out_3_to_4_controls)); 550 + 551 + snd_soc_dapm_new_controls(dapm, cs530x_dac_ch34_dapm_widgets, 552 + ARRAY_SIZE(cs530x_dac_ch34_dapm_widgets)); 553 + 554 + snd_soc_dapm_add_routes(dapm, dac_ch3_4_routes, 555 + ARRAY_SIZE(dac_ch3_4_routes)); 550 556 } 551 557 552 558 static int cs530x_set_bclk(struct snd_soc_component *component, const int freq) ··· 954 666 .name = "cs530x-dai", 955 667 .capture = { 956 668 .stream_name = "AIF Capture", 957 - .channels_min = 2, 958 - .channels_max = 8, 669 + .rates = SNDRV_PCM_RATE_KNOT, 670 + .formats = SNDRV_PCM_FMTBIT_S32_LE, 671 + }, 672 + .playback = { 673 + .stream_name = "AIF Playback", 959 674 .rates = SNDRV_PCM_RATE_KNOT, 960 675 .formats = SNDRV_PCM_FMTBIT_S32_LE, 961 676 }, ··· 1013 722 ARRAY_SIZE(cs530x_gen_dapm_widgets)); 1014 723 1015 724 switch (cs530x->devtype) { 725 + case CS4282: 726 + cs530x_add_12_adc_widgets(component); 727 + cs530x_add_12_dac_widgets(component); 728 + break; 729 + case CS4302: 730 + cs530x_add_12_dac_widgets(component); 731 + break; 732 + case CS4304: 733 + cs530x_add_12_dac_widgets(component); 734 + cs530x_add_34_dac_widgets(component); 735 + 736 + num_widgets = ARRAY_SIZE(cs530x_out_sum_4ch_controls); 737 + snd_soc_add_component_controls(component, 738 + cs530x_out_sum_4ch_controls, 739 + num_widgets); 740 + break; 741 + case CS4308: 742 + cs530x_add_12_dac_widgets(component); 743 + cs530x_add_34_dac_widgets(component); 744 + 745 + num_widgets = ARRAY_SIZE(cs530x_out_5_to_8_controls); 746 + snd_soc_add_component_controls(component, 747 + cs530x_out_5_to_8_controls, 748 + num_widgets); 749 + 750 + num_widgets = ARRAY_SIZE(cs530x_out_sum_8ch_controls); 751 + snd_soc_add_component_controls(component, 752 + cs530x_out_sum_8ch_controls, 753 + num_widgets); 754 + 755 + num_widgets = ARRAY_SIZE(cs530x_dac_ch58_dapm_widgets); 756 + snd_soc_dapm_new_controls(dapm, cs530x_dac_ch58_dapm_widgets, 757 + num_widgets); 758 + 759 + snd_soc_dapm_add_routes(dapm, dac_ch5_8_routes, 760 + ARRAY_SIZE(dac_ch5_8_routes)); 761 + break; 1016 762 case CS5302: 1017 763 cs530x_add_12_adc_widgets(component); 1018 764 break; ··· 1153 825 if (ret) 1154 826 return dev_err_probe(dev, ret, "Can't read REV ID\n"); 1155 827 1156 - dev_dbg(dev, "Device ID 0x%x Rev ID 0x%x\n", dev_id, rev); 1157 - 1158 828 switch (dev_id) { 829 + case CS530X_2CH_CODEC_DEV_ID: 830 + cs530x->num_dacs = 2; 831 + cs530x->num_adcs = 2; 832 + break; 833 + case CS530X_2CH_DAC_DEV_ID: 834 + cs530x->num_dacs = 2; 835 + break; 836 + case CS530X_4CH_DAC_DEV_ID: 837 + cs530x->num_dacs = 4; 838 + break; 839 + case CS530X_8CH_DAC_DEV_ID: 840 + cs530x->num_dacs = 8; 841 + break; 1159 842 case CS530X_2CH_ADC_DEV_ID: 1160 843 cs530x->num_adcs = 2; 1161 844 break; ··· 1180 841 return dev_err_probe(dev, -EINVAL, "Invalid device ID 0x%x\n", 1181 842 dev_id); 1182 843 } 844 + 845 + dev_dbg(dev, "Device ID 0x%x Rev ID 0x%x (%d in %d out)\n", dev_id, rev, 846 + cs530x->num_adcs, cs530x->num_dacs); 1183 847 1184 848 return 0; 1185 849 } ··· 1212 870 val |= CS530X_IN12_HIZ; 1213 871 1214 872 return regmap_set_bits(regmap, CS530X_IN_HIZ, val); 873 + case 0: 874 + /* No ADCs */ 875 + return 0; 1215 876 default: 1216 877 return dev_err_probe(dev, -EINVAL, 1217 878 "Invalid number of adcs %d\n", ··· 1277 932 if (ret) 1278 933 goto err_reset; 1279 934 1280 - cs530x->dev_dai->capture.channels_max = cs530x->num_adcs; 935 + if (cs530x->num_adcs) { 936 + cs530x->dev_dai->capture.channels_min = 2; 937 + cs530x->dev_dai->capture.channels_max = cs530x->num_adcs; 938 + } 939 + 940 + if (cs530x->num_dacs) { 941 + cs530x->dev_dai->playback.channels_min = 2; 942 + cs530x->dev_dai->playback.channels_max = cs530x->num_dacs; 943 + } 1281 944 1282 945 ret = devm_snd_soc_register_component(dev, 1283 946 &soc_component_dev_cs530x,
+42 -16
sound/soc/codecs/cs530x.h
··· 15 15 #include <linux/regulator/consumer.h> 16 16 17 17 /* Devices */ 18 + #define CS530X_2CH_CODEC_DEV_ID 0x4282 19 + #define CS530X_2CH_DAC_DEV_ID 0x4302 20 + #define CS530X_4CH_DAC_DEV_ID 0x4304 21 + #define CS530X_8CH_DAC_DEV_ID 0x4308 18 22 #define CS530X_2CH_ADC_DEV_ID 0x5302 19 23 #define CS530X_4CH_ADC_DEV_ID 0x5304 20 24 #define CS530X_8CH_ADC_DEV_ID 0x5308 ··· 48 44 #define CS530X_IN_VOL_CTRL4_0 0x000009C 49 45 #define CS530X_IN_VOL_CTRL4_1 0x000009E 50 46 #define CS530X_IN_VOL_CTRL5 0x00000A0 47 + 48 + #define CS530X_OUT_ENABLES 0x00000C0 49 + #define CS530X_OUT_RAMP_SUM 0x00000C2 50 + #define CS530X_OUT_DEEMPH 0x00000C4 51 + #define CS530X_OUT_FILTER 0x00000C6 52 + #define CS530X_OUT_INV 0x00000CA 53 + #define CS530X_OUT_VOL_CTRL1_0 0x00000D0 54 + #define CS530X_OUT_VOL_CTRL1_1 0x00000D2 55 + #define CS530X_OUT_VOL_CTRL2_0 0x00000D4 56 + #define CS530X_OUT_VOL_CTRL2_1 0x00000D6 57 + #define CS530X_OUT_VOL_CTRL3_0 0x00000D8 58 + #define CS530X_OUT_VOL_CTRL3_1 0x00000DA 59 + #define CS530X_OUT_VOL_CTRL4_0 0x00000DC 60 + #define CS530X_OUT_VOL_CTRL4_1 0x00000DE 61 + #define CS530X_OUT_VOL_CTRL5 0x00000E0 51 62 52 63 #define CS530X_PAD_FN 0x0003D24 53 64 #define CS530X_PAD_LVL 0x0003D28 ··· 151 132 #define CS530X_14_15_TDM_SLOT_MASK GENMASK(15, 14) 152 133 #define CS530X_14_15_TDM_SLOT_VAL 7 153 134 154 - /* IN_RAMP_SUM */ 135 + /* IN_RAMP_SUM and OUT_RAMP_SUM */ 155 136 #define CS530X_RAMP_RATE_INC_SHIFT 0 156 137 #define CS530X_RAMP_RATE_DEC_SHIFT 4 157 - #define CS530X_IN_SUM_MODE_SHIFT 13 138 + #define CS530X_INOUT_SUM_MODE_SHIFT 13 158 139 159 - /* IN_FILTER */ 160 - #define CS530X_IN_FILTER_SHIFT 8 161 - #define CS530X_IN_HPF_EN_SHIFT 12 140 + /* IN_FILTER and OUT_FILTER */ 141 + #define CS530X_INOUT_FILTER_SHIFT 8 142 + #define CS530X_INOUT_HPF_EN_SHIFT 12 162 143 163 144 /* IN_HIZ */ 164 145 #define CS530X_IN12_HIZ BIT(0) ··· 166 147 #define CS530X_IN56_HIZ BIT(2) 167 148 #define CS530X_IN78_HIZ BIT(3) 168 149 169 - /* IN_INV */ 170 - #define CS530X_IN1_INV_SHIFT 0 171 - #define CS530X_IN2_INV_SHIFT 1 172 - #define CS530X_IN3_INV_SHIFT 2 173 - #define CS530X_IN4_INV_SHIFT 3 174 - #define CS530X_IN5_INV_SHIFT 4 175 - #define CS530X_IN6_INV_SHIFT 5 176 - #define CS530X_IN7_INV_SHIFT 6 177 - #define CS530X_IN8_INV_SHIFT 7 150 + /* IN_INV and OUT_INV */ 151 + #define CS530X_INOUT1_INV_SHIFT 0 152 + #define CS530X_INOUT2_INV_SHIFT 1 153 + #define CS530X_INOUT3_INV_SHIFT 2 154 + #define CS530X_INOUT4_INV_SHIFT 3 155 + #define CS530X_INOUT5_INV_SHIFT 4 156 + #define CS530X_INOUT6_INV_SHIFT 5 157 + #define CS530X_INOUT7_INV_SHIFT 6 158 + #define CS530X_INOUT8_INV_SHIFT 7 178 159 179 - /* IN_VOL_CTLy_z */ 180 - #define CS530X_IN_MUTE BIT(15) 160 + /* IN_VOL_CTLy_z and OUT_VOL_CTLy_z */ 161 + #define CS530X_INOUT_MUTE BIT(15) 181 162 182 163 /* IN_VOL_CTL5 */ 183 164 #define CS530X_IN_VU BIT(0) ··· 197 178 #define CS530X_CONFIG3_LVL BIT(7) 198 179 #define CS530X_CONFIG4_LVL BIT(8) 199 180 #define CS530X_CONFIG5_LVL BIT(9) 181 + /* IN_VOL_CTL5 and OUT_VOL_CTL5 */ 182 + #define CS530X_INOUT_VU BIT(0) 200 183 201 184 /* System Clock Source */ 202 185 #define CS530X_SYSCLK_SRC_MCLK 0 ··· 211 190 #define CS530X_NUM_SUPPLIES 2 212 191 213 192 enum cs530x_type { 193 + CS4282, 194 + CS4302, 195 + CS4304, 196 + CS4308, 214 197 CS5302, 215 198 CS5304, 216 199 CS5308, ··· 235 210 int tdm_width; 236 211 int tdm_slots; 237 212 int adc_pairs_count; 213 + int dac_pairs_count; 238 214 239 215 struct gpio_desc *reset_gpio; 240 216 };