tas2562.c (21924B)
1// SPDX-License-Identifier: GPL-2.0 2// 3// Driver for the Texas Instruments TAS2562 CODEC 4// Copyright (C) 2019 Texas Instruments Inc. 5 6 7#include <linux/module.h> 8#include <linux/errno.h> 9#include <linux/device.h> 10#include <linux/i2c.h> 11#include <linux/pm_runtime.h> 12#include <linux/regmap.h> 13#include <linux/slab.h> 14#include <linux/gpio/consumer.h> 15#include <linux/regulator/consumer.h> 16#include <linux/delay.h> 17 18#include <sound/pcm.h> 19#include <sound/pcm_params.h> 20#include <sound/soc.h> 21#include <sound/soc-dapm.h> 22#include <sound/tlv.h> 23 24#include "tas2562.h" 25 26#define TAS2562_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |\ 27 SNDRV_PCM_FORMAT_S32_LE) 28 29/* DVC equation involves floating point math 30 * round(10^(volume in dB/20)*2^30) 31 * so create a lookup table for 2dB step 32 */ 33static const unsigned int float_vol_db_lookup[] = { 340x00000d43, 0x000010b2, 0x00001505, 0x00001a67, 0x00002151, 350x000029f1, 0x000034cd, 0x00004279, 0x000053af, 0x0000695b, 360x0000695b, 0x0000a6fa, 0x0000d236, 0x000108a4, 0x00014d2a, 370x0001a36e, 0x00021008, 0x000298c0, 0x000344df, 0x00041d8f, 380x00052e5a, 0x000685c8, 0x00083621, 0x000a566d, 0x000d03a7, 390x0010624d, 0x0014a050, 0x0019f786, 0x0020b0bc, 0x0029279d, 400x0033cf8d, 0x004139d3, 0x00521d50, 0x00676044, 0x0082248a, 410x00a3d70a, 0x00ce4328, 0x0103ab3d, 0x0146e75d, 0x019b8c27, 420x02061b89, 0x028c423f, 0x03352529, 0x0409c2b0, 0x05156d68, 430x080e9f96, 0x0a24b062, 0x0cc509ab, 0x10137987, 0x143d1362, 440x197a967f, 0x2013739e, 0x28619ae9, 0x32d64617, 0x40000000 45}; 46 47struct tas2562_data { 48 struct snd_soc_component *component; 49 struct gpio_desc *sdz_gpio; 50 struct regmap *regmap; 51 struct device *dev; 52 struct i2c_client *client; 53 int v_sense_slot; 54 int i_sense_slot; 55 int volume_lvl; 56 int model_id; 57}; 58 59enum tas256x_model { 60 TAS2562, 61 TAS2563, 62 TAS2564, 63 TAS2110, 64}; 65 66static int tas2562_set_bias_level(struct snd_soc_component *component, 67 enum snd_soc_bias_level level) 68{ 69 struct tas2562_data *tas2562 = 70 snd_soc_component_get_drvdata(component); 71 72 switch (level) { 73 case SND_SOC_BIAS_ON: 74 snd_soc_component_update_bits(component, 75 TAS2562_PWR_CTRL, 76 TAS2562_MODE_MASK, TAS2562_ACTIVE); 77 break; 78 case SND_SOC_BIAS_STANDBY: 79 case SND_SOC_BIAS_PREPARE: 80 snd_soc_component_update_bits(component, 81 TAS2562_PWR_CTRL, 82 TAS2562_MODE_MASK, TAS2562_MUTE); 83 break; 84 case SND_SOC_BIAS_OFF: 85 snd_soc_component_update_bits(component, 86 TAS2562_PWR_CTRL, 87 TAS2562_MODE_MASK, TAS2562_SHUTDOWN); 88 break; 89 90 default: 91 dev_err(tas2562->dev, 92 "wrong power level setting %d\n", level); 93 return -EINVAL; 94 } 95 96 return 0; 97} 98 99static int tas2562_set_samplerate(struct tas2562_data *tas2562, int samplerate) 100{ 101 int samp_rate; 102 int ramp_rate; 103 104 switch (samplerate) { 105 case 7350: 106 ramp_rate = TAS2562_TDM_CFG0_RAMPRATE_44_1; 107 samp_rate = TAS2562_TDM_CFG0_SAMPRATE_7305_8KHZ; 108 break; 109 case 8000: 110 ramp_rate = 0; 111 samp_rate = TAS2562_TDM_CFG0_SAMPRATE_7305_8KHZ; 112 break; 113 case 14700: 114 ramp_rate = TAS2562_TDM_CFG0_RAMPRATE_44_1; 115 samp_rate = TAS2562_TDM_CFG0_SAMPRATE_14_7_16KHZ; 116 break; 117 case 16000: 118 ramp_rate = 0; 119 samp_rate = TAS2562_TDM_CFG0_SAMPRATE_14_7_16KHZ; 120 break; 121 case 22050: 122 ramp_rate = TAS2562_TDM_CFG0_RAMPRATE_44_1; 123 samp_rate = TAS2562_TDM_CFG0_SAMPRATE_22_05_24KHZ; 124 break; 125 case 24000: 126 ramp_rate = 0; 127 samp_rate = TAS2562_TDM_CFG0_SAMPRATE_22_05_24KHZ; 128 break; 129 case 29400: 130 ramp_rate = TAS2562_TDM_CFG0_RAMPRATE_44_1; 131 samp_rate = TAS2562_TDM_CFG0_SAMPRATE_29_4_32KHZ; 132 break; 133 case 32000: 134 ramp_rate = 0; 135 samp_rate = TAS2562_TDM_CFG0_SAMPRATE_29_4_32KHZ; 136 break; 137 case 44100: 138 ramp_rate = TAS2562_TDM_CFG0_RAMPRATE_44_1; 139 samp_rate = TAS2562_TDM_CFG0_SAMPRATE_44_1_48KHZ; 140 break; 141 case 48000: 142 ramp_rate = 0; 143 samp_rate = TAS2562_TDM_CFG0_SAMPRATE_44_1_48KHZ; 144 break; 145 case 88200: 146 ramp_rate = TAS2562_TDM_CFG0_RAMPRATE_44_1; 147 samp_rate = TAS2562_TDM_CFG0_SAMPRATE_88_2_96KHZ; 148 break; 149 case 96000: 150 ramp_rate = 0; 151 samp_rate = TAS2562_TDM_CFG0_SAMPRATE_88_2_96KHZ; 152 break; 153 case 176400: 154 ramp_rate = TAS2562_TDM_CFG0_RAMPRATE_44_1; 155 samp_rate = TAS2562_TDM_CFG0_SAMPRATE_176_4_192KHZ; 156 break; 157 case 192000: 158 ramp_rate = 0; 159 samp_rate = TAS2562_TDM_CFG0_SAMPRATE_176_4_192KHZ; 160 break; 161 default: 162 dev_info(tas2562->dev, "%s, unsupported sample rate, %d\n", 163 __func__, samplerate); 164 return -EINVAL; 165 } 166 167 snd_soc_component_update_bits(tas2562->component, TAS2562_TDM_CFG0, 168 TAS2562_TDM_CFG0_RAMPRATE_MASK, ramp_rate); 169 snd_soc_component_update_bits(tas2562->component, TAS2562_TDM_CFG0, 170 TAS2562_TDM_CFG0_SAMPRATE_MASK, samp_rate); 171 172 return 0; 173} 174 175static int tas2562_set_dai_tdm_slot(struct snd_soc_dai *dai, 176 unsigned int tx_mask, unsigned int rx_mask, 177 int slots, int slot_width) 178{ 179 struct snd_soc_component *component = dai->component; 180 struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component); 181 int left_slot, right_slot; 182 int slots_cfg; 183 int ret; 184 185 if (!tx_mask) { 186 dev_err(component->dev, "tx masks must not be 0\n"); 187 return -EINVAL; 188 } 189 190 if (slots == 1) { 191 if (tx_mask != 1) 192 return -EINVAL; 193 194 left_slot = 0; 195 right_slot = 0; 196 } else { 197 left_slot = __ffs(tx_mask); 198 tx_mask &= ~(1 << left_slot); 199 if (tx_mask == 0) { 200 right_slot = left_slot; 201 } else { 202 right_slot = __ffs(tx_mask); 203 } 204 } 205 206 slots_cfg = (right_slot << TAS2562_RIGHT_SLOT_SHIFT) | left_slot; 207 208 ret = snd_soc_component_write(component, TAS2562_TDM_CFG3, slots_cfg); 209 if (ret < 0) 210 return ret; 211 212 switch (slot_width) { 213 case 16: 214 ret = snd_soc_component_update_bits(component, 215 TAS2562_TDM_CFG2, 216 TAS2562_TDM_CFG2_RXLEN_MASK, 217 TAS2562_TDM_CFG2_RXLEN_16B); 218 break; 219 case 24: 220 ret = snd_soc_component_update_bits(component, 221 TAS2562_TDM_CFG2, 222 TAS2562_TDM_CFG2_RXLEN_MASK, 223 TAS2562_TDM_CFG2_RXLEN_24B); 224 break; 225 case 32: 226 ret = snd_soc_component_update_bits(component, 227 TAS2562_TDM_CFG2, 228 TAS2562_TDM_CFG2_RXLEN_MASK, 229 TAS2562_TDM_CFG2_RXLEN_32B); 230 break; 231 232 case 0: 233 /* Do not change slot width */ 234 break; 235 default: 236 dev_err(tas2562->dev, "slot width not supported"); 237 ret = -EINVAL; 238 } 239 240 if (ret < 0) 241 return ret; 242 243 ret = snd_soc_component_update_bits(component, TAS2562_TDM_CFG5, 244 TAS2562_TDM_CFG5_VSNS_SLOT_MASK, 245 tas2562->v_sense_slot); 246 if (ret < 0) 247 return ret; 248 249 ret = snd_soc_component_update_bits(component, TAS2562_TDM_CFG6, 250 TAS2562_TDM_CFG6_ISNS_SLOT_MASK, 251 tas2562->i_sense_slot); 252 if (ret < 0) 253 return ret; 254 255 return 0; 256} 257 258static int tas2562_set_bitwidth(struct tas2562_data *tas2562, int bitwidth) 259{ 260 int ret; 261 int val; 262 int sense_en; 263 264 switch (bitwidth) { 265 case SNDRV_PCM_FORMAT_S16_LE: 266 snd_soc_component_update_bits(tas2562->component, 267 TAS2562_TDM_CFG2, 268 TAS2562_TDM_CFG2_RXWLEN_MASK, 269 TAS2562_TDM_CFG2_RXWLEN_16B); 270 break; 271 case SNDRV_PCM_FORMAT_S24_LE: 272 snd_soc_component_update_bits(tas2562->component, 273 TAS2562_TDM_CFG2, 274 TAS2562_TDM_CFG2_RXWLEN_MASK, 275 TAS2562_TDM_CFG2_RXWLEN_24B); 276 break; 277 case SNDRV_PCM_FORMAT_S32_LE: 278 snd_soc_component_update_bits(tas2562->component, 279 TAS2562_TDM_CFG2, 280 TAS2562_TDM_CFG2_RXWLEN_MASK, 281 TAS2562_TDM_CFG2_RXWLEN_32B); 282 break; 283 284 default: 285 dev_info(tas2562->dev, "Unsupported bitwidth format\n"); 286 return -EINVAL; 287 } 288 289 val = snd_soc_component_read(tas2562->component, TAS2562_PWR_CTRL); 290 if (val < 0) 291 return val; 292 293 if (val & (1 << TAS2562_VSENSE_POWER_EN)) 294 sense_en = 0; 295 else 296 sense_en = TAS2562_TDM_CFG5_VSNS_EN; 297 298 ret = snd_soc_component_update_bits(tas2562->component, TAS2562_TDM_CFG5, 299 TAS2562_TDM_CFG5_VSNS_EN, sense_en); 300 if (ret < 0) 301 return ret; 302 303 if (val & (1 << TAS2562_ISENSE_POWER_EN)) 304 sense_en = 0; 305 else 306 sense_en = TAS2562_TDM_CFG6_ISNS_EN; 307 308 ret = snd_soc_component_update_bits(tas2562->component, TAS2562_TDM_CFG6, 309 TAS2562_TDM_CFG6_ISNS_EN, sense_en); 310 if (ret < 0) 311 return ret; 312 313 return 0; 314} 315 316static int tas2562_hw_params(struct snd_pcm_substream *substream, 317 struct snd_pcm_hw_params *params, 318 struct snd_soc_dai *dai) 319{ 320 struct snd_soc_component *component = dai->component; 321 struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component); 322 int ret; 323 324 ret = tas2562_set_bitwidth(tas2562, params_format(params)); 325 if (ret) { 326 dev_err(tas2562->dev, "set bitwidth failed, %d\n", ret); 327 return ret; 328 } 329 330 ret = tas2562_set_samplerate(tas2562, params_rate(params)); 331 if (ret) 332 dev_err(tas2562->dev, "set sample rate failed, %d\n", ret); 333 334 return ret; 335} 336 337static int tas2562_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) 338{ 339 struct snd_soc_component *component = dai->component; 340 struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component); 341 u8 asi_cfg_1 = 0; 342 u8 tdm_rx_start_slot = 0; 343 int ret; 344 345 switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 346 case SND_SOC_DAIFMT_NB_NF: 347 asi_cfg_1 = 0; 348 break; 349 case SND_SOC_DAIFMT_IB_NF: 350 asi_cfg_1 |= TAS2562_TDM_CFG1_RX_FALLING; 351 break; 352 default: 353 dev_err(tas2562->dev, "ASI format Inverse is not found\n"); 354 return -EINVAL; 355 } 356 357 ret = snd_soc_component_update_bits(component, TAS2562_TDM_CFG1, 358 TAS2562_TDM_CFG1_RX_EDGE_MASK, 359 asi_cfg_1); 360 if (ret < 0) { 361 dev_err(tas2562->dev, "Failed to set RX edge\n"); 362 return ret; 363 } 364 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 365 case SND_SOC_DAIFMT_LEFT_J: 366 case SND_SOC_DAIFMT_DSP_B: 367 tdm_rx_start_slot = 0; 368 break; 369 case SND_SOC_DAIFMT_I2S: 370 case SND_SOC_DAIFMT_DSP_A: 371 tdm_rx_start_slot = 1; 372 break; 373 default: 374 dev_err(tas2562->dev, 375 "DAI Format is not found, fmt=0x%x\n", fmt); 376 return -EINVAL; 377 } 378 379 ret = snd_soc_component_update_bits(component, TAS2562_TDM_CFG1, 380 TAS2562_RX_OFF_MASK, (tdm_rx_start_slot << 1)); 381 if (ret < 0) 382 return ret; 383 384 return 0; 385} 386 387static int tas2562_mute(struct snd_soc_dai *dai, int mute, int direction) 388{ 389 struct snd_soc_component *component = dai->component; 390 391 return snd_soc_component_update_bits(component, TAS2562_PWR_CTRL, 392 TAS2562_MODE_MASK, 393 mute ? TAS2562_MUTE : 0); 394} 395 396static int tas2562_codec_probe(struct snd_soc_component *component) 397{ 398 struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component); 399 int ret; 400 401 tas2562->component = component; 402 403 if (tas2562->sdz_gpio) 404 gpiod_set_value_cansleep(tas2562->sdz_gpio, 1); 405 406 ret = snd_soc_component_update_bits(component, TAS2562_PWR_CTRL, 407 TAS2562_MODE_MASK, TAS2562_MUTE); 408 if (ret < 0) 409 return ret; 410 411 return 0; 412} 413 414#ifdef CONFIG_PM 415static int tas2562_suspend(struct snd_soc_component *component) 416{ 417 struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component); 418 419 regcache_cache_only(tas2562->regmap, true); 420 regcache_mark_dirty(tas2562->regmap); 421 422 if (tas2562->sdz_gpio) 423 gpiod_set_value_cansleep(tas2562->sdz_gpio, 0); 424 425 return 0; 426} 427 428static int tas2562_resume(struct snd_soc_component *component) 429{ 430 struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component); 431 432 if (tas2562->sdz_gpio) 433 gpiod_set_value_cansleep(tas2562->sdz_gpio, 1); 434 435 regcache_cache_only(tas2562->regmap, false); 436 437 return regcache_sync(tas2562->regmap); 438} 439#else 440#define tas2562_suspend NULL 441#define tas2562_resume NULL 442#endif 443 444static const char * const tas2562_ASI1_src[] = { 445 "I2C offset", "Left", "Right", "LeftRightDiv2", 446}; 447 448static SOC_ENUM_SINGLE_DECL(tas2562_ASI1_src_enum, TAS2562_TDM_CFG2, 4, 449 tas2562_ASI1_src); 450 451static const struct snd_kcontrol_new tas2562_asi1_mux = 452 SOC_DAPM_ENUM("ASI1 Source", tas2562_ASI1_src_enum); 453 454static int tas2562_dac_event(struct snd_soc_dapm_widget *w, 455 struct snd_kcontrol *kcontrol, int event) 456{ 457 struct snd_soc_component *component = 458 snd_soc_dapm_to_component(w->dapm); 459 struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component); 460 int ret; 461 462 switch (event) { 463 case SND_SOC_DAPM_POST_PMU: 464 ret = snd_soc_component_update_bits(component, 465 TAS2562_PWR_CTRL, 466 TAS2562_MODE_MASK, 467 TAS2562_MUTE); 468 if (ret) 469 goto end; 470 break; 471 case SND_SOC_DAPM_PRE_PMD: 472 ret = snd_soc_component_update_bits(component, 473 TAS2562_PWR_CTRL, 474 TAS2562_MODE_MASK, 475 TAS2562_SHUTDOWN); 476 if (ret) 477 goto end; 478 break; 479 default: 480 dev_err(tas2562->dev, "Not supported evevt\n"); 481 return -EINVAL; 482 } 483 484end: 485 if (ret < 0) 486 return ret; 487 488 return 0; 489} 490 491static int tas2562_volume_control_get(struct snd_kcontrol *kcontrol, 492 struct snd_ctl_elem_value *ucontrol) 493{ 494 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 495 struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component); 496 497 ucontrol->value.integer.value[0] = tas2562->volume_lvl; 498 return 0; 499} 500 501static int tas2562_volume_control_put(struct snd_kcontrol *kcontrol, 502 struct snd_ctl_elem_value *ucontrol) 503{ 504 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 505 struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component); 506 int ret; 507 u32 reg_val; 508 509 reg_val = float_vol_db_lookup[ucontrol->value.integer.value[0]/2]; 510 ret = snd_soc_component_write(component, TAS2562_DVC_CFG4, 511 (reg_val & 0xff)); 512 if (ret) 513 return ret; 514 ret = snd_soc_component_write(component, TAS2562_DVC_CFG3, 515 ((reg_val >> 8) & 0xff)); 516 if (ret) 517 return ret; 518 ret = snd_soc_component_write(component, TAS2562_DVC_CFG2, 519 ((reg_val >> 16) & 0xff)); 520 if (ret) 521 return ret; 522 ret = snd_soc_component_write(component, TAS2562_DVC_CFG1, 523 ((reg_val >> 24) & 0xff)); 524 if (ret) 525 return ret; 526 527 tas2562->volume_lvl = ucontrol->value.integer.value[0]; 528 529 return 0; 530} 531 532/* Digital Volume Control. From 0 dB to -110 dB in 1 dB steps */ 533static const DECLARE_TLV_DB_SCALE(dvc_tlv, -11000, 100, 0); 534 535static DECLARE_TLV_DB_SCALE(tas2562_dac_tlv, 850, 50, 0); 536 537static const struct snd_kcontrol_new isense_switch = 538 SOC_DAPM_SINGLE("Switch", TAS2562_PWR_CTRL, TAS2562_ISENSE_POWER_EN, 539 1, 1); 540 541static const struct snd_kcontrol_new vsense_switch = 542 SOC_DAPM_SINGLE("Switch", TAS2562_PWR_CTRL, TAS2562_VSENSE_POWER_EN, 543 1, 1); 544 545static const struct snd_kcontrol_new tas2562_snd_controls[] = { 546 SOC_SINGLE_TLV("Amp Gain Volume", TAS2562_PB_CFG1, 1, 0x1c, 0, 547 tas2562_dac_tlv), 548 { 549 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 550 .name = "Digital Volume Control", 551 .index = 0, 552 .tlv.p = dvc_tlv, 553 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE, 554 .info = snd_soc_info_volsw, 555 .get = tas2562_volume_control_get, 556 .put = tas2562_volume_control_put, 557 .private_value = SOC_SINGLE_VALUE(TAS2562_DVC_CFG1, 0, 110, 0, 0), 558 }, 559}; 560 561static const struct snd_soc_dapm_widget tas2110_dapm_widgets[] = { 562 SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0), 563 SND_SOC_DAPM_MUX("ASI1 Sel", SND_SOC_NOPM, 0, 0, &tas2562_asi1_mux), 564 SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas2562_dac_event, 565 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), 566 SND_SOC_DAPM_OUTPUT("OUT"), 567}; 568 569static const struct snd_soc_dapm_route tas2110_audio_map[] = { 570 {"ASI1 Sel", "I2C offset", "ASI1"}, 571 {"ASI1 Sel", "Left", "ASI1"}, 572 {"ASI1 Sel", "Right", "ASI1"}, 573 {"ASI1 Sel", "LeftRightDiv2", "ASI1"}, 574 { "DAC", NULL, "ASI1 Sel" }, 575 { "OUT", NULL, "DAC" }, 576}; 577 578static const struct snd_soc_component_driver soc_component_dev_tas2110 = { 579 .probe = tas2562_codec_probe, 580 .suspend = tas2562_suspend, 581 .resume = tas2562_resume, 582 .set_bias_level = tas2562_set_bias_level, 583 .controls = tas2562_snd_controls, 584 .num_controls = ARRAY_SIZE(tas2562_snd_controls), 585 .dapm_widgets = tas2110_dapm_widgets, 586 .num_dapm_widgets = ARRAY_SIZE(tas2110_dapm_widgets), 587 .dapm_routes = tas2110_audio_map, 588 .num_dapm_routes = ARRAY_SIZE(tas2110_audio_map), 589 .idle_bias_on = 1, 590 .use_pmdown_time = 1, 591 .endianness = 1, 592 .non_legacy_dai_naming = 1, 593}; 594 595static const struct snd_soc_dapm_widget tas2562_dapm_widgets[] = { 596 SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0), 597 SND_SOC_DAPM_MUX("ASI1 Sel", SND_SOC_NOPM, 0, 0, &tas2562_asi1_mux), 598 SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas2562_dac_event, 599 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), 600 SND_SOC_DAPM_SWITCH("ISENSE", TAS2562_PWR_CTRL, 3, 1, &isense_switch), 601 SND_SOC_DAPM_SWITCH("VSENSE", TAS2562_PWR_CTRL, 2, 1, &vsense_switch), 602 SND_SOC_DAPM_SIGGEN("VMON"), 603 SND_SOC_DAPM_SIGGEN("IMON"), 604 SND_SOC_DAPM_OUTPUT("OUT"), 605}; 606 607static const struct snd_soc_dapm_route tas2562_audio_map[] = { 608 {"ASI1 Sel", "I2C offset", "ASI1"}, 609 {"ASI1 Sel", "Left", "ASI1"}, 610 {"ASI1 Sel", "Right", "ASI1"}, 611 {"ASI1 Sel", "LeftRightDiv2", "ASI1"}, 612 { "DAC", NULL, "ASI1 Sel" }, 613 { "OUT", NULL, "DAC" }, 614 {"ISENSE", "Switch", "IMON"}, 615 {"VSENSE", "Switch", "VMON"}, 616}; 617 618static const struct snd_soc_component_driver soc_component_dev_tas2562 = { 619 .probe = tas2562_codec_probe, 620 .suspend = tas2562_suspend, 621 .resume = tas2562_resume, 622 .set_bias_level = tas2562_set_bias_level, 623 .controls = tas2562_snd_controls, 624 .num_controls = ARRAY_SIZE(tas2562_snd_controls), 625 .dapm_widgets = tas2562_dapm_widgets, 626 .num_dapm_widgets = ARRAY_SIZE(tas2562_dapm_widgets), 627 .dapm_routes = tas2562_audio_map, 628 .num_dapm_routes = ARRAY_SIZE(tas2562_audio_map), 629 .idle_bias_on = 1, 630 .use_pmdown_time = 1, 631 .endianness = 1, 632 .non_legacy_dai_naming = 1, 633}; 634 635static const struct snd_soc_dai_ops tas2562_speaker_dai_ops = { 636 .hw_params = tas2562_hw_params, 637 .set_fmt = tas2562_set_dai_fmt, 638 .set_tdm_slot = tas2562_set_dai_tdm_slot, 639 .mute_stream = tas2562_mute, 640 .no_capture_mute = 1, 641}; 642 643static struct snd_soc_dai_driver tas2562_dai[] = { 644 { 645 .name = "tas2562-amplifier", 646 .id = 0, 647 .playback = { 648 .stream_name = "ASI1 Playback", 649 .channels_min = 2, 650 .channels_max = 2, 651 .rates = SNDRV_PCM_RATE_8000_192000, 652 .formats = TAS2562_FORMATS, 653 }, 654 .capture = { 655 .stream_name = "ASI1 Capture", 656 .channels_min = 0, 657 .channels_max = 2, 658 .rates = SNDRV_PCM_RATE_8000_192000, 659 .formats = TAS2562_FORMATS, 660 }, 661 .ops = &tas2562_speaker_dai_ops, 662 }, 663}; 664 665static const struct regmap_range_cfg tas2562_ranges[] = { 666 { 667 .range_min = 0, 668 .range_max = 5 * 128, 669 .selector_reg = TAS2562_PAGE_CTRL, 670 .selector_mask = 0xff, 671 .selector_shift = 0, 672 .window_start = 0, 673 .window_len = 128, 674 }, 675}; 676 677static const struct reg_default tas2562_reg_defaults[] = { 678 { TAS2562_PAGE_CTRL, 0x00 }, 679 { TAS2562_SW_RESET, 0x00 }, 680 { TAS2562_PWR_CTRL, 0x0e }, 681 { TAS2562_PB_CFG1, 0x20 }, 682 { TAS2562_TDM_CFG0, 0x09 }, 683 { TAS2562_TDM_CFG1, 0x02 }, 684 { TAS2562_DVC_CFG1, 0x40 }, 685 { TAS2562_DVC_CFG2, 0x40 }, 686 { TAS2562_DVC_CFG3, 0x00 }, 687 { TAS2562_DVC_CFG4, 0x00 }, 688}; 689 690static const struct regmap_config tas2562_regmap_config = { 691 .reg_bits = 8, 692 .val_bits = 8, 693 694 .max_register = 5 * 128, 695 .cache_type = REGCACHE_RBTREE, 696 .reg_defaults = tas2562_reg_defaults, 697 .num_reg_defaults = ARRAY_SIZE(tas2562_reg_defaults), 698 .ranges = tas2562_ranges, 699 .num_ranges = ARRAY_SIZE(tas2562_ranges), 700}; 701 702static int tas2562_parse_dt(struct tas2562_data *tas2562) 703{ 704 struct device *dev = tas2562->dev; 705 int ret = 0; 706 707 tas2562->sdz_gpio = devm_gpiod_get_optional(dev, "shutdown", GPIOD_OUT_HIGH); 708 if (IS_ERR(tas2562->sdz_gpio)) { 709 if (PTR_ERR(tas2562->sdz_gpio) == -EPROBE_DEFER) 710 return -EPROBE_DEFER; 711 712 tas2562->sdz_gpio = NULL; 713 } 714 715 /* 716 * The shut-down property is deprecated but needs to be checked for 717 * backwards compatibility. 718 */ 719 if (tas2562->sdz_gpio == NULL) { 720 tas2562->sdz_gpio = devm_gpiod_get_optional(dev, "shut-down", 721 GPIOD_OUT_HIGH); 722 if (IS_ERR(tas2562->sdz_gpio)) 723 if (PTR_ERR(tas2562->sdz_gpio) == -EPROBE_DEFER) 724 return -EPROBE_DEFER; 725 726 tas2562->sdz_gpio = NULL; 727 } 728 729 if (tas2562->model_id == TAS2110) 730 return ret; 731 732 ret = fwnode_property_read_u32(dev->fwnode, "ti,imon-slot-no", 733 &tas2562->i_sense_slot); 734 if (ret) { 735 dev_err(dev, "Property %s is missing setting default slot\n", 736 "ti,imon-slot-no"); 737 tas2562->i_sense_slot = 0; 738 } 739 740 741 ret = fwnode_property_read_u32(dev->fwnode, "ti,vmon-slot-no", 742 &tas2562->v_sense_slot); 743 if (ret) { 744 dev_info(dev, "Property %s is missing setting default slot\n", 745 "ti,vmon-slot-no"); 746 tas2562->v_sense_slot = 2; 747 } 748 749 if (tas2562->v_sense_slot < tas2562->i_sense_slot) { 750 dev_err(dev, "Vsense slot must be greater than Isense slot\n"); 751 return -EINVAL; 752 } 753 754 return ret; 755} 756 757static const struct i2c_device_id tas2562_id[] = { 758 { "tas2562", TAS2562 }, 759 { "tas2563", TAS2563 }, 760 { "tas2564", TAS2564 }, 761 { "tas2110", TAS2110 }, 762 { } 763}; 764MODULE_DEVICE_TABLE(i2c, tas2562_id); 765 766static int tas2562_probe(struct i2c_client *client) 767{ 768 struct device *dev = &client->dev; 769 struct tas2562_data *data; 770 int ret; 771 const struct i2c_device_id *id; 772 773 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 774 if (!data) 775 return -ENOMEM; 776 777 id = i2c_match_id(tas2562_id, client); 778 data->client = client; 779 data->dev = &client->dev; 780 data->model_id = id->driver_data; 781 782 tas2562_parse_dt(data); 783 784 data->regmap = devm_regmap_init_i2c(client, &tas2562_regmap_config); 785 if (IS_ERR(data->regmap)) { 786 ret = PTR_ERR(data->regmap); 787 dev_err(dev, "failed to allocate register map: %d\n", ret); 788 return ret; 789 } 790 791 dev_set_drvdata(&client->dev, data); 792 793 if (data->model_id == TAS2110) 794 return devm_snd_soc_register_component(dev, 795 &soc_component_dev_tas2110, 796 tas2562_dai, 797 ARRAY_SIZE(tas2562_dai)); 798 799 return devm_snd_soc_register_component(dev, &soc_component_dev_tas2562, 800 tas2562_dai, 801 ARRAY_SIZE(tas2562_dai)); 802 803} 804 805#ifdef CONFIG_OF 806static const struct of_device_id tas2562_of_match[] = { 807 { .compatible = "ti,tas2562", }, 808 { .compatible = "ti,tas2563", }, 809 { .compatible = "ti,tas2564", }, 810 { .compatible = "ti,tas2110", }, 811 { }, 812}; 813MODULE_DEVICE_TABLE(of, tas2562_of_match); 814#endif 815 816static struct i2c_driver tas2562_i2c_driver = { 817 .driver = { 818 .name = "tas2562", 819 .of_match_table = of_match_ptr(tas2562_of_match), 820 }, 821 .probe_new = tas2562_probe, 822 .id_table = tas2562_id, 823}; 824 825module_i2c_driver(tas2562_i2c_driver); 826 827MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>"); 828MODULE_DESCRIPTION("TAS2562 Audio amplifier driver"); 829MODULE_LICENSE("GPL");