1 // SPDX-License-Identifier: GPL-2.0-only OR MIT 2 // 3 // Analog Devices' SSM3515 audio amp driver 4 // 5 // Copyright (C) The Asahi Linux Contributors 6 7 #include <linux/bits.h> 8 #include <linux/bitfield.h> 9 #include <linux/device.h> 10 #include <linux/i2c.h> 11 #include <linux/module.h> 12 #include <linux/of.h> 13 #include <linux/regmap.h> 14 15 #include <sound/pcm.h> 16 #include <sound/pcm_params.h> 17 #include <sound/soc.h> 18 #include <sound/tlv.h> 19 20 21 #define SSM3515_PWR 0x00 22 #define SSM3515_PWR_APWDN_EN BIT(7) 23 #define SSM3515_PWR_BSNS_PWDN BIT(6) 24 #define SSM3515_PWR_S_RST BIT(1) 25 #define SSM3515_PWR_SPWDN BIT(0) 26 27 #define SSM3515_GEC 0x01 28 #define SSM3515_GEC_EDGE BIT(4) 29 #define SSM3515_GEC_EDGE_SHIFT 4 30 #define SSM3515_GEC_ANA_GAIN GENMASK(1, 0) 31 32 #define SSM3515_DAC 0x02 33 #define SSM3515_DAC_HV BIT(7) 34 #define SSM3515_DAC_MUTE BIT(6) 35 #define SSM3515_DAC_HPF BIT(5) 36 #define SSM3515_DAC_LPM BIT(4) 37 #define SSM3515_DAC_FS GENMASK(2, 0) 38 39 #define SSM3515_DAC_VOL 0x03 40 41 #define SSM3515_SAI1 0x04 42 #define SSM3515_SAI1_DAC_POL BIT(7) 43 #define SSM3515_SAI1_BCLK_POL BIT(6) 44 #define SSM3515_SAI1_TDM_BCLKS GENMASK(5, 3) 45 #define SSM3515_SAI1_FSYNC_MODE BIT(2) 46 #define SSM3515_SAI1_SDATA_FMT BIT(1) 47 #define SSM3515_SAI1_SAI_MODE BIT(0) 48 49 #define SSM3515_SAI2 0x05 50 #define SSM3515_SAI2_DATA_WIDTH BIT(7) 51 #define SSM3515_SAI2_AUTO_SLOT BIT(4) 52 #define SSM3515_SAI2_TDM_SLOT GENMASK(3, 0) 53 54 #define SSM3515_VBAT_OUT 0x06 55 56 #define SSM3515_STATUS 0x0a 57 #define SSM3515_STATUS_UVLO_REG BIT(6) 58 #define SSM3515_STATUS_LIM_EG BIT(5) 59 #define SSM3515_STATUS_CLIP BIT(4) 60 #define SSM3515_STATUS_AMP_OC BIT(3) 61 #define SSM3515_STATUS_OTF BIT(2) 62 #define SSM3515_STATUS_OTW BIT(1) 63 #define SSM3515_STATUS_BAT_WARN BIT(0) 64 65 static bool ssm3515_volatile_reg(struct device *dev, unsigned int reg) 66 { 67 switch (reg) { 68 case SSM3515_STATUS: 69 case SSM3515_VBAT_OUT: 70 return true; 71 72 default: 73 return false; 74 } 75 } 76 77 static const struct reg_default ssm3515_reg_defaults[] = { 78 { SSM3515_PWR, 0x81 }, 79 { SSM3515_GEC, 0x01 }, 80 { SSM3515_DAC, 0x32 }, 81 { SSM3515_DAC_VOL, 0x40 }, 82 { SSM3515_SAI1, 0x11 }, 83 { SSM3515_SAI2, 0x00 }, 84 }; 85 86 static const struct regmap_config ssm3515_i2c_regmap = { 87 .reg_bits = 8, 88 .val_bits = 8, 89 .volatile_reg = ssm3515_volatile_reg, 90 .max_register = 0xb, 91 .reg_defaults = ssm3515_reg_defaults, 92 .num_reg_defaults = ARRAY_SIZE(ssm3515_reg_defaults), 93 .cache_type = REGCACHE_FLAT, 94 }; 95 96 struct ssm3515_data { 97 struct device *dev; 98 struct regmap *regmap; 99 }; 100 101 // The specced range is -71.25...24.00 dB with step size of 0.375 dB, 102 // and a mute item below that. This is represented by -71.62...24.00 dB 103 // with the mute item mapped onto the low end. 104 static DECLARE_TLV_DB_MINMAX_MUTE(ssm3515_dac_volume, -7162, 2400); 105 106 static const char * const ssm3515_ana_gain_text[] = { 107 "8.4 V Span", "12.6 V Span", "14 V Span", "15 V Span", 108 }; 109 110 static SOC_ENUM_SINGLE_DECL(ssm3515_ana_gain_enum, SSM3515_GEC, 111 __bf_shf(SSM3515_GEC_ANA_GAIN), 112 ssm3515_ana_gain_text); 113 114 static const struct snd_kcontrol_new ssm3515_snd_controls[] = { 115 SOC_SINGLE_TLV("DAC Playback Volume", SSM3515_DAC_VOL, 116 0, 255, 1, ssm3515_dac_volume), 117 SOC_SINGLE("Low EMI Mode Switch", SSM3515_GEC, 118 __bf_shf(SSM3515_GEC_EDGE), 1, 0), 119 SOC_SINGLE("Soft Volume Ramping Switch", SSM3515_DAC, 120 __bf_shf(SSM3515_DAC_HV), 1, 1), 121 SOC_SINGLE("HPF Switch", SSM3515_DAC, 122 __bf_shf(SSM3515_DAC_HPF), 1, 0), 123 SOC_SINGLE("DAC Invert Switch", SSM3515_SAI1, 124 __bf_shf(SSM3515_SAI1_DAC_POL), 1, 0), 125 SOC_ENUM("DAC Analog Gain Select", ssm3515_ana_gain_enum), 126 }; 127 128 static void ssm3515_read_faults(struct snd_soc_component *component) 129 { 130 int ret; 131 132 ret = snd_soc_component_read(component, SSM3515_STATUS); 133 if (ret <= 0) { 134 /* 135 * If the read was erroneous, ASoC core has printed a message, 136 * and that's all that's appropriate in handling the error here. 137 */ 138 return; 139 } 140 141 dev_err(component->dev, "device reports:%s%s%s%s%s%s%s\n", 142 FIELD_GET(SSM3515_STATUS_UVLO_REG, ret) ? " voltage regulator fault" : "", 143 FIELD_GET(SSM3515_STATUS_LIM_EG, ret) ? " limiter engaged" : "", 144 FIELD_GET(SSM3515_STATUS_CLIP, ret) ? " clipping detected" : "", 145 FIELD_GET(SSM3515_STATUS_AMP_OC, ret) ? " amp over-current fault" : "", 146 FIELD_GET(SSM3515_STATUS_OTF, ret) ? " overtemperature fault" : "", 147 FIELD_GET(SSM3515_STATUS_OTW, ret) ? " overtemperature warning" : "", 148 FIELD_GET(SSM3515_STATUS_BAT_WARN, ret) ? " bat voltage low warning" : ""); 149 } 150 151 static int ssm3515_probe(struct snd_soc_component *component) 152 { 153 int ret; 154 155 /* Start out muted */ 156 ret = snd_soc_component_update_bits(component, SSM3515_DAC, 157 SSM3515_DAC_MUTE, SSM3515_DAC_MUTE); 158 if (ret < 0) 159 return ret; 160 161 /* Disable the 'master power-down' */ 162 ret = snd_soc_component_update_bits(component, SSM3515_PWR, 163 SSM3515_PWR_SPWDN, 0); 164 if (ret < 0) 165 return ret; 166 167 return 0; 168 } 169 170 static int ssm3515_mute(struct snd_soc_dai *dai, int mute, int direction) 171 { 172 int ret; 173 174 ret = snd_soc_component_update_bits(dai->component, 175 SSM3515_DAC, 176 SSM3515_DAC_MUTE, 177 FIELD_PREP(SSM3515_DAC_MUTE, mute)); 178 if (ret < 0) 179 return ret; 180 return 0; 181 } 182 183 static int ssm3515_hw_params(struct snd_pcm_substream *substream, 184 struct snd_pcm_hw_params *params, 185 struct snd_soc_dai *dai) 186 { 187 struct snd_soc_component *component = dai->component; 188 int ret, rateval; 189 190 switch (params_format(params)) { 191 case SNDRV_PCM_FORMAT_S16: 192 case SNDRV_PCM_FORMAT_S24: 193 ret = snd_soc_component_update_bits(component, 194 SSM3515_SAI2, SSM3515_SAI2_DATA_WIDTH, 195 FIELD_PREP(SSM3515_SAI2_DATA_WIDTH, 196 params_width(params) == 16)); 197 if (ret < 0) 198 return ret; 199 break; 200 201 default: 202 return -EINVAL; 203 } 204 205 switch (params_rate(params)) { 206 case 8000 ... 12000: 207 rateval = 0; 208 break; 209 case 16000 ... 24000: 210 rateval = 1; 211 break; 212 case 32000 ... 48000: 213 rateval = 2; 214 break; 215 case 64000 ... 96000: 216 rateval = 3; 217 break; 218 case 128000 ... 192000: 219 rateval = 4; 220 break; 221 case 48001 ... 63999: /* this is ...72000 but overlaps */ 222 rateval = 5; 223 break; 224 default: 225 return -EINVAL; 226 } 227 228 ret = snd_soc_component_update_bits(component, 229 SSM3515_DAC, SSM3515_DAC_FS, 230 FIELD_PREP(SSM3515_DAC_FS, rateval)); 231 if (ret < 0) 232 return ret; 233 234 return 0; 235 } 236 237 static int ssm3515_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 238 { 239 struct snd_soc_component *component = dai->component; 240 bool fpol_inv = false; /* non-inverted: frame starts with low-to-high FSYNC */ 241 int ret; 242 u8 sai1 = 0; 243 244 switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 245 case SND_SOC_DAIFMT_IB_NF: 246 case SND_SOC_DAIFMT_IB_IF: 247 sai1 |= SSM3515_SAI1_BCLK_POL; 248 break; 249 } 250 251 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 252 case SND_SOC_DAIFMT_I2S: 253 fpol_inv = 1; 254 sai1 &= ~SSM3515_SAI1_SDATA_FMT; /* 1 bit start delay */ 255 break; 256 case SND_SOC_DAIFMT_LEFT_J: 257 fpol_inv = 0; 258 sai1 |= SSM3515_SAI1_SDATA_FMT; /* no start delay */ 259 break; 260 default: 261 return -EINVAL; 262 } 263 264 switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 265 case SND_SOC_DAIFMT_NB_IF: 266 case SND_SOC_DAIFMT_IB_IF: 267 fpol_inv ^= 1; 268 break; 269 } 270 271 /* Set the serial input to 'TDM mode' */ 272 sai1 |= SSM3515_SAI1_SAI_MODE; 273 274 if (fpol_inv) { 275 /* 276 * We configure the codec in a 'TDM mode', in which the 277 * FSYNC_MODE bit of SAI1 is supposed to select between 278 * what the datasheet calls 'Pulsed FSYNC mode' and '50% 279 * FSYNC mode'. 280 * 281 * Experiments suggest that this bit in fact simply selects 282 * the FSYNC polarity, so go with that. 283 */ 284 sai1 |= SSM3515_SAI1_FSYNC_MODE; 285 } 286 287 ret = snd_soc_component_update_bits(component, SSM3515_SAI1, 288 SSM3515_SAI1_BCLK_POL | SSM3515_SAI1_SDATA_FMT | 289 SSM3515_SAI1_SAI_MODE | SSM3515_SAI1_FSYNC_MODE, sai1); 290 291 if (ret < 0) 292 return ret; 293 return 0; 294 } 295 296 static int ssm3515_set_tdm_slot(struct snd_soc_dai *dai, 297 unsigned int tx_mask, 298 unsigned int rx_mask, 299 int slots, int slot_width) 300 { 301 struct snd_soc_component *component = dai->component; 302 int slot, tdm_bclks_val, ret; 303 304 if (tx_mask == 0 || rx_mask != 0) 305 return -EINVAL; 306 307 slot = __ffs(tx_mask); 308 309 if (tx_mask & ~BIT(slot)) 310 return -EINVAL; 311 312 switch (slot_width) { 313 case 16: 314 tdm_bclks_val = 0; 315 break; 316 case 24: 317 tdm_bclks_val = 1; 318 break; 319 case 32: 320 tdm_bclks_val = 2; 321 break; 322 case 48: 323 tdm_bclks_val = 3; 324 break; 325 case 64: 326 tdm_bclks_val = 4; 327 break; 328 default: 329 return -EINVAL; 330 } 331 332 ret = snd_soc_component_update_bits(component, SSM3515_SAI1, 333 SSM3515_SAI1_TDM_BCLKS, 334 FIELD_PREP(SSM3515_SAI1_TDM_BCLKS, tdm_bclks_val)); 335 if (ret < 0) 336 return ret; 337 338 ret = snd_soc_component_update_bits(component, SSM3515_SAI2, 339 SSM3515_SAI2_TDM_SLOT, 340 FIELD_PREP(SSM3515_SAI2_TDM_SLOT, slot)); 341 if (ret < 0) 342 return ret; 343 344 return 0; 345 } 346 347 static int ssm3515_hw_free(struct snd_pcm_substream *substream, 348 struct snd_soc_dai *dai) 349 { 350 /* 351 * We don't get live notification of faults, so at least at 352 * this time, when playback is over, check if we have tripped 353 * over anything and if so, log it. 354 */ 355 ssm3515_read_faults(dai->component); 356 return 0; 357 } 358 359 static const struct snd_soc_dai_ops ssm3515_dai_ops = { 360 .mute_stream = ssm3515_mute, 361 .hw_params = ssm3515_hw_params, 362 .set_fmt = ssm3515_set_fmt, 363 .set_tdm_slot = ssm3515_set_tdm_slot, 364 .hw_free = ssm3515_hw_free, 365 }; 366 367 static struct snd_soc_dai_driver ssm3515_dai_driver = { 368 .name = "SSM3515 SAI", 369 .id = 0, 370 .playback = { 371 .stream_name = "Playback", 372 .channels_min = 1, 373 .channels_max = 1, 374 .rates = SNDRV_PCM_RATE_CONTINUOUS, 375 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, 376 }, 377 .ops = &ssm3515_dai_ops, 378 }; 379 380 static const struct snd_soc_dapm_widget ssm3515_dapm_widgets[] = { 381 SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0), 382 SND_SOC_DAPM_OUTPUT("OUT"), 383 }; 384 385 static const struct snd_soc_dapm_route ssm3515_dapm_routes[] = { 386 {"OUT", NULL, "DAC"}, 387 {"DAC", NULL, "Playback"}, 388 }; 389 390 static const struct snd_soc_component_driver ssm3515_asoc_component = { 391 .probe = ssm3515_probe, 392 .controls = ssm3515_snd_controls, 393 .num_controls = ARRAY_SIZE(ssm3515_snd_controls), 394 .dapm_widgets = ssm3515_dapm_widgets, 395 .num_dapm_widgets = ARRAY_SIZE(ssm3515_dapm_widgets), 396 .dapm_routes = ssm3515_dapm_routes, 397 .num_dapm_routes = ARRAY_SIZE(ssm3515_dapm_routes), 398 .endianness = 1, 399 }; 400 401 static int ssm3515_i2c_probe(struct i2c_client *client) 402 { 403 struct ssm3515_data *data; 404 int ret; 405 406 data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); 407 if (!data) 408 return -ENOMEM; 409 410 data->dev = &client->dev; 411 i2c_set_clientdata(client, data); 412 413 data->regmap = devm_regmap_init_i2c(client, &ssm3515_i2c_regmap); 414 if (IS_ERR(data->regmap)) 415 return dev_err_probe(data->dev, PTR_ERR(data->regmap), 416 "initializing register map\n"); 417 418 /* Perform a reset */ 419 ret = regmap_update_bits(data->regmap, SSM3515_PWR, 420 SSM3515_PWR_S_RST, SSM3515_PWR_S_RST); 421 if (ret < 0) 422 return dev_err_probe(data->dev, ret, 423 "performing software reset\n"); 424 regmap_reinit_cache(data->regmap, &ssm3515_i2c_regmap); 425 426 return devm_snd_soc_register_component(data->dev, 427 &ssm3515_asoc_component, 428 &ssm3515_dai_driver, 1); 429 } 430 431 static const struct of_device_id ssm3515_of_match[] = { 432 { .compatible = "adi,ssm3515" }, 433 {} 434 }; 435 MODULE_DEVICE_TABLE(of, ssm3515_of_match); 436 437 static struct i2c_driver ssm3515_i2c_driver = { 438 .driver = { 439 .name = "ssm3515", 440 .of_match_table = ssm3515_of_match, 441 }, 442 .probe = ssm3515_i2c_probe, 443 }; 444 module_i2c_driver(ssm3515_i2c_driver); 445 446 MODULE_AUTHOR("Martin PoviĊĦer <povik+lin@cutebit.org>"); 447 MODULE_DESCRIPTION("ASoC SSM3515 audio amp driver"); 448 MODULE_LICENSE("Dual MIT/GPL"); 449
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.