tas5720.c (21532B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * tas5720.c - ALSA SoC Texas Instruments TAS5720 Mono Audio Amplifier 4 * 5 * Copyright (C)2015-2016 Texas Instruments Incorporated - https://www.ti.com 6 * 7 * Author: Andreas Dannenberg <dannenberg@ti.com> 8 */ 9 10#include <linux/module.h> 11#include <linux/errno.h> 12#include <linux/device.h> 13#include <linux/i2c.h> 14#include <linux/pm_runtime.h> 15#include <linux/regmap.h> 16#include <linux/slab.h> 17#include <linux/regulator/consumer.h> 18#include <linux/delay.h> 19 20#include <sound/pcm.h> 21#include <sound/pcm_params.h> 22#include <sound/soc.h> 23#include <sound/soc-dapm.h> 24#include <sound/tlv.h> 25 26#include "tas5720.h" 27 28/* Define how often to check (and clear) the fault status register (in ms) */ 29#define TAS5720_FAULT_CHECK_INTERVAL 200 30 31enum tas572x_type { 32 TAS5720, 33 TAS5722, 34}; 35 36static const char * const tas5720_supply_names[] = { 37 "dvdd", /* Digital power supply. Connect to 3.3-V supply. */ 38 "pvdd", /* Class-D amp and analog power supply (connected). */ 39}; 40 41#define TAS5720_NUM_SUPPLIES ARRAY_SIZE(tas5720_supply_names) 42 43struct tas5720_data { 44 struct snd_soc_component *component; 45 struct regmap *regmap; 46 struct i2c_client *tas5720_client; 47 enum tas572x_type devtype; 48 struct regulator_bulk_data supplies[TAS5720_NUM_SUPPLIES]; 49 struct delayed_work fault_check_work; 50 unsigned int last_fault; 51}; 52 53static int tas5720_hw_params(struct snd_pcm_substream *substream, 54 struct snd_pcm_hw_params *params, 55 struct snd_soc_dai *dai) 56{ 57 struct snd_soc_component *component = dai->component; 58 unsigned int rate = params_rate(params); 59 bool ssz_ds; 60 int ret; 61 62 switch (rate) { 63 case 44100: 64 case 48000: 65 ssz_ds = false; 66 break; 67 case 88200: 68 case 96000: 69 ssz_ds = true; 70 break; 71 default: 72 dev_err(component->dev, "unsupported sample rate: %u\n", rate); 73 return -EINVAL; 74 } 75 76 ret = snd_soc_component_update_bits(component, TAS5720_DIGITAL_CTRL1_REG, 77 TAS5720_SSZ_DS, ssz_ds); 78 if (ret < 0) { 79 dev_err(component->dev, "error setting sample rate: %d\n", ret); 80 return ret; 81 } 82 83 return 0; 84} 85 86static int tas5720_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) 87{ 88 struct snd_soc_component *component = dai->component; 89 u8 serial_format; 90 int ret; 91 92 if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) { 93 dev_vdbg(component->dev, "DAI Format master is not found\n"); 94 return -EINVAL; 95 } 96 97 switch (fmt & (SND_SOC_DAIFMT_FORMAT_MASK | 98 SND_SOC_DAIFMT_INV_MASK)) { 99 case (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF): 100 /* 1st data bit occur one BCLK cycle after the frame sync */ 101 serial_format = TAS5720_SAIF_I2S; 102 break; 103 case (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF): 104 /* 105 * Note that although the TAS5720 does not have a dedicated DSP 106 * mode it doesn't care about the LRCLK duty cycle during TDM 107 * operation. Therefore we can use the device's I2S mode with 108 * its delaying of the 1st data bit to receive DSP_A formatted 109 * data. See device datasheet for additional details. 110 */ 111 serial_format = TAS5720_SAIF_I2S; 112 break; 113 case (SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF): 114 /* 115 * Similar to DSP_A, we can use the fact that the TAS5720 does 116 * not care about the LRCLK duty cycle during TDM to receive 117 * DSP_B formatted data in LEFTJ mode (no delaying of the 1st 118 * data bit). 119 */ 120 serial_format = TAS5720_SAIF_LEFTJ; 121 break; 122 case (SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF): 123 /* No delay after the frame sync */ 124 serial_format = TAS5720_SAIF_LEFTJ; 125 break; 126 default: 127 dev_vdbg(component->dev, "DAI Format is not found\n"); 128 return -EINVAL; 129 } 130 131 ret = snd_soc_component_update_bits(component, TAS5720_DIGITAL_CTRL1_REG, 132 TAS5720_SAIF_FORMAT_MASK, 133 serial_format); 134 if (ret < 0) { 135 dev_err(component->dev, "error setting SAIF format: %d\n", ret); 136 return ret; 137 } 138 139 return 0; 140} 141 142static int tas5720_set_dai_tdm_slot(struct snd_soc_dai *dai, 143 unsigned int tx_mask, unsigned int rx_mask, 144 int slots, int slot_width) 145{ 146 struct snd_soc_component *component = dai->component; 147 struct tas5720_data *tas5720 = snd_soc_component_get_drvdata(component); 148 unsigned int first_slot; 149 int ret; 150 151 if (!tx_mask) { 152 dev_err(component->dev, "tx masks must not be 0\n"); 153 return -EINVAL; 154 } 155 156 /* 157 * Determine the first slot that is being requested. We will only 158 * use the first slot that is found since the TAS5720 is a mono 159 * amplifier. 160 */ 161 first_slot = __ffs(tx_mask); 162 163 if (first_slot > 7) { 164 dev_err(component->dev, "slot selection out of bounds (%u)\n", 165 first_slot); 166 return -EINVAL; 167 } 168 169 /* Enable manual TDM slot selection (instead of I2C ID based) */ 170 ret = snd_soc_component_update_bits(component, TAS5720_DIGITAL_CTRL1_REG, 171 TAS5720_TDM_CFG_SRC, TAS5720_TDM_CFG_SRC); 172 if (ret < 0) 173 goto error_snd_soc_component_update_bits; 174 175 /* Configure the TDM slot to process audio from */ 176 ret = snd_soc_component_update_bits(component, TAS5720_DIGITAL_CTRL2_REG, 177 TAS5720_TDM_SLOT_SEL_MASK, first_slot); 178 if (ret < 0) 179 goto error_snd_soc_component_update_bits; 180 181 /* Configure TDM slot width. This is only applicable to TAS5722. */ 182 switch (tas5720->devtype) { 183 case TAS5722: 184 ret = snd_soc_component_update_bits(component, TAS5722_DIGITAL_CTRL2_REG, 185 TAS5722_TDM_SLOT_16B, 186 slot_width == 16 ? 187 TAS5722_TDM_SLOT_16B : 0); 188 if (ret < 0) 189 goto error_snd_soc_component_update_bits; 190 break; 191 default: 192 break; 193 } 194 195 return 0; 196 197error_snd_soc_component_update_bits: 198 dev_err(component->dev, "error configuring TDM mode: %d\n", ret); 199 return ret; 200} 201 202static int tas5720_mute(struct snd_soc_dai *dai, int mute, int direction) 203{ 204 struct snd_soc_component *component = dai->component; 205 int ret; 206 207 ret = snd_soc_component_update_bits(component, TAS5720_DIGITAL_CTRL2_REG, 208 TAS5720_MUTE, mute ? TAS5720_MUTE : 0); 209 if (ret < 0) { 210 dev_err(component->dev, "error (un-)muting device: %d\n", ret); 211 return ret; 212 } 213 214 return 0; 215} 216 217static void tas5720_fault_check_work(struct work_struct *work) 218{ 219 struct tas5720_data *tas5720 = container_of(work, struct tas5720_data, 220 fault_check_work.work); 221 struct device *dev = tas5720->component->dev; 222 unsigned int curr_fault; 223 int ret; 224 225 ret = regmap_read(tas5720->regmap, TAS5720_FAULT_REG, &curr_fault); 226 if (ret < 0) { 227 dev_err(dev, "failed to read FAULT register: %d\n", ret); 228 goto out; 229 } 230 231 /* Check/handle all errors except SAIF clock errors */ 232 curr_fault &= TAS5720_OCE | TAS5720_DCE | TAS5720_OTE; 233 234 /* 235 * Only flag errors once for a given occurrence. This is needed as 236 * the TAS5720 will take time clearing the fault condition internally 237 * during which we don't want to bombard the system with the same 238 * error message over and over. 239 */ 240 if ((curr_fault & TAS5720_OCE) && !(tas5720->last_fault & TAS5720_OCE)) 241 dev_crit(dev, "experienced an over current hardware fault\n"); 242 243 if ((curr_fault & TAS5720_DCE) && !(tas5720->last_fault & TAS5720_DCE)) 244 dev_crit(dev, "experienced a DC detection fault\n"); 245 246 if ((curr_fault & TAS5720_OTE) && !(tas5720->last_fault & TAS5720_OTE)) 247 dev_crit(dev, "experienced an over temperature fault\n"); 248 249 /* Store current fault value so we can detect any changes next time */ 250 tas5720->last_fault = curr_fault; 251 252 if (!curr_fault) 253 goto out; 254 255 /* 256 * Periodically toggle SDZ (shutdown bit) H->L->H to clear any latching 257 * faults as long as a fault condition persists. Always going through 258 * the full sequence no matter the first return value to minimizes 259 * chances for the device to end up in shutdown mode. 260 */ 261 ret = regmap_write_bits(tas5720->regmap, TAS5720_POWER_CTRL_REG, 262 TAS5720_SDZ, 0); 263 if (ret < 0) 264 dev_err(dev, "failed to write POWER_CTRL register: %d\n", ret); 265 266 ret = regmap_write_bits(tas5720->regmap, TAS5720_POWER_CTRL_REG, 267 TAS5720_SDZ, TAS5720_SDZ); 268 if (ret < 0) 269 dev_err(dev, "failed to write POWER_CTRL register: %d\n", ret); 270 271out: 272 /* Schedule the next fault check at the specified interval */ 273 schedule_delayed_work(&tas5720->fault_check_work, 274 msecs_to_jiffies(TAS5720_FAULT_CHECK_INTERVAL)); 275} 276 277static int tas5720_codec_probe(struct snd_soc_component *component) 278{ 279 struct tas5720_data *tas5720 = snd_soc_component_get_drvdata(component); 280 unsigned int device_id, expected_device_id; 281 int ret; 282 283 tas5720->component = component; 284 285 ret = regulator_bulk_enable(ARRAY_SIZE(tas5720->supplies), 286 tas5720->supplies); 287 if (ret != 0) { 288 dev_err(component->dev, "failed to enable supplies: %d\n", ret); 289 return ret; 290 } 291 292 /* 293 * Take a liberal approach to checking the device ID to allow the 294 * driver to be used even if the device ID does not match, however 295 * issue a warning if there is a mismatch. 296 */ 297 ret = regmap_read(tas5720->regmap, TAS5720_DEVICE_ID_REG, &device_id); 298 if (ret < 0) { 299 dev_err(component->dev, "failed to read device ID register: %d\n", 300 ret); 301 goto probe_fail; 302 } 303 304 switch (tas5720->devtype) { 305 case TAS5720: 306 expected_device_id = TAS5720_DEVICE_ID; 307 break; 308 case TAS5722: 309 expected_device_id = TAS5722_DEVICE_ID; 310 break; 311 default: 312 dev_err(component->dev, "unexpected private driver data\n"); 313 return -EINVAL; 314 } 315 316 if (device_id != expected_device_id) 317 dev_warn(component->dev, "wrong device ID. expected: %u read: %u\n", 318 expected_device_id, device_id); 319 320 /* Set device to mute */ 321 ret = snd_soc_component_update_bits(component, TAS5720_DIGITAL_CTRL2_REG, 322 TAS5720_MUTE, TAS5720_MUTE); 323 if (ret < 0) 324 goto error_snd_soc_component_update_bits; 325 326 /* 327 * Enter shutdown mode - our default when not playing audio - to 328 * minimize current consumption. On the TAS5720 there is no real down 329 * side doing so as all device registers are preserved and the wakeup 330 * of the codec is rather quick which we do using a dapm widget. 331 */ 332 ret = snd_soc_component_update_bits(component, TAS5720_POWER_CTRL_REG, 333 TAS5720_SDZ, 0); 334 if (ret < 0) 335 goto error_snd_soc_component_update_bits; 336 337 INIT_DELAYED_WORK(&tas5720->fault_check_work, tas5720_fault_check_work); 338 339 return 0; 340 341error_snd_soc_component_update_bits: 342 dev_err(component->dev, "error configuring device registers: %d\n", ret); 343 344probe_fail: 345 regulator_bulk_disable(ARRAY_SIZE(tas5720->supplies), 346 tas5720->supplies); 347 return ret; 348} 349 350static void tas5720_codec_remove(struct snd_soc_component *component) 351{ 352 struct tas5720_data *tas5720 = snd_soc_component_get_drvdata(component); 353 int ret; 354 355 cancel_delayed_work_sync(&tas5720->fault_check_work); 356 357 ret = regulator_bulk_disable(ARRAY_SIZE(tas5720->supplies), 358 tas5720->supplies); 359 if (ret < 0) 360 dev_err(component->dev, "failed to disable supplies: %d\n", ret); 361}; 362 363static int tas5720_dac_event(struct snd_soc_dapm_widget *w, 364 struct snd_kcontrol *kcontrol, int event) 365{ 366 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 367 struct tas5720_data *tas5720 = snd_soc_component_get_drvdata(component); 368 int ret; 369 370 if (event & SND_SOC_DAPM_POST_PMU) { 371 /* Take TAS5720 out of shutdown mode */ 372 ret = snd_soc_component_update_bits(component, TAS5720_POWER_CTRL_REG, 373 TAS5720_SDZ, TAS5720_SDZ); 374 if (ret < 0) { 375 dev_err(component->dev, "error waking component: %d\n", ret); 376 return ret; 377 } 378 379 /* 380 * Observe codec shutdown-to-active time. The datasheet only 381 * lists a nominal value however just use-it as-is without 382 * additional padding to minimize the delay introduced in 383 * starting to play audio (actually there is other setup done 384 * by the ASoC framework that will provide additional delays, 385 * so we should always be safe). 386 */ 387 msleep(25); 388 389 /* Turn on TAS5720 periodic fault checking/handling */ 390 tas5720->last_fault = 0; 391 schedule_delayed_work(&tas5720->fault_check_work, 392 msecs_to_jiffies(TAS5720_FAULT_CHECK_INTERVAL)); 393 } else if (event & SND_SOC_DAPM_PRE_PMD) { 394 /* Disable TAS5720 periodic fault checking/handling */ 395 cancel_delayed_work_sync(&tas5720->fault_check_work); 396 397 /* Place TAS5720 in shutdown mode to minimize current draw */ 398 ret = snd_soc_component_update_bits(component, TAS5720_POWER_CTRL_REG, 399 TAS5720_SDZ, 0); 400 if (ret < 0) { 401 dev_err(component->dev, "error shutting down component: %d\n", 402 ret); 403 return ret; 404 } 405 } 406 407 return 0; 408} 409 410#ifdef CONFIG_PM 411static int tas5720_suspend(struct snd_soc_component *component) 412{ 413 struct tas5720_data *tas5720 = snd_soc_component_get_drvdata(component); 414 int ret; 415 416 regcache_cache_only(tas5720->regmap, true); 417 regcache_mark_dirty(tas5720->regmap); 418 419 ret = regulator_bulk_disable(ARRAY_SIZE(tas5720->supplies), 420 tas5720->supplies); 421 if (ret < 0) 422 dev_err(component->dev, "failed to disable supplies: %d\n", ret); 423 424 return ret; 425} 426 427static int tas5720_resume(struct snd_soc_component *component) 428{ 429 struct tas5720_data *tas5720 = snd_soc_component_get_drvdata(component); 430 int ret; 431 432 ret = regulator_bulk_enable(ARRAY_SIZE(tas5720->supplies), 433 tas5720->supplies); 434 if (ret < 0) { 435 dev_err(component->dev, "failed to enable supplies: %d\n", ret); 436 return ret; 437 } 438 439 regcache_cache_only(tas5720->regmap, false); 440 441 ret = regcache_sync(tas5720->regmap); 442 if (ret < 0) { 443 dev_err(component->dev, "failed to sync regcache: %d\n", ret); 444 return ret; 445 } 446 447 return 0; 448} 449#else 450#define tas5720_suspend NULL 451#define tas5720_resume NULL 452#endif 453 454static bool tas5720_is_volatile_reg(struct device *dev, unsigned int reg) 455{ 456 switch (reg) { 457 case TAS5720_DEVICE_ID_REG: 458 case TAS5720_FAULT_REG: 459 return true; 460 default: 461 return false; 462 } 463} 464 465static const struct regmap_config tas5720_regmap_config = { 466 .reg_bits = 8, 467 .val_bits = 8, 468 469 .max_register = TAS5720_MAX_REG, 470 .cache_type = REGCACHE_RBTREE, 471 .volatile_reg = tas5720_is_volatile_reg, 472}; 473 474static const struct regmap_config tas5722_regmap_config = { 475 .reg_bits = 8, 476 .val_bits = 8, 477 478 .max_register = TAS5722_MAX_REG, 479 .cache_type = REGCACHE_RBTREE, 480 .volatile_reg = tas5720_is_volatile_reg, 481}; 482 483/* 484 * DAC analog gain. There are four discrete values to select from, ranging 485 * from 19.2 dB to 26.3dB. 486 */ 487static const DECLARE_TLV_DB_RANGE(dac_analog_tlv, 488 0x0, 0x0, TLV_DB_SCALE_ITEM(1920, 0, 0), 489 0x1, 0x1, TLV_DB_SCALE_ITEM(2070, 0, 0), 490 0x2, 0x2, TLV_DB_SCALE_ITEM(2350, 0, 0), 491 0x3, 0x3, TLV_DB_SCALE_ITEM(2630, 0, 0), 492); 493 494/* 495 * DAC digital volumes. From -103.5 to 24 dB in 0.5 dB or 0.25 dB steps 496 * depending on the device. Note that setting the gain below -100 dB 497 * (register value <0x7) is effectively a MUTE as per device datasheet. 498 * 499 * Note that for the TAS5722 the digital volume controls are actually split 500 * over two registers, so we need custom getters/setters for access. 501 */ 502static DECLARE_TLV_DB_SCALE(tas5720_dac_tlv, -10350, 50, 0); 503static DECLARE_TLV_DB_SCALE(tas5722_dac_tlv, -10350, 25, 0); 504 505static int tas5722_volume_get(struct snd_kcontrol *kcontrol, 506 struct snd_ctl_elem_value *ucontrol) 507{ 508 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 509 unsigned int val; 510 511 val = snd_soc_component_read(component, TAS5720_VOLUME_CTRL_REG); 512 ucontrol->value.integer.value[0] = val << 1; 513 514 val = snd_soc_component_read(component, TAS5722_DIGITAL_CTRL2_REG); 515 ucontrol->value.integer.value[0] |= val & TAS5722_VOL_CONTROL_LSB; 516 517 return 0; 518} 519 520static int tas5722_volume_set(struct snd_kcontrol *kcontrol, 521 struct snd_ctl_elem_value *ucontrol) 522{ 523 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); 524 unsigned int sel = ucontrol->value.integer.value[0]; 525 526 snd_soc_component_write(component, TAS5720_VOLUME_CTRL_REG, sel >> 1); 527 snd_soc_component_update_bits(component, TAS5722_DIGITAL_CTRL2_REG, 528 TAS5722_VOL_CONTROL_LSB, sel); 529 530 return 0; 531} 532 533static const struct snd_kcontrol_new tas5720_snd_controls[] = { 534 SOC_SINGLE_TLV("Speaker Driver Playback Volume", 535 TAS5720_VOLUME_CTRL_REG, 0, 0xff, 0, tas5720_dac_tlv), 536 SOC_SINGLE_TLV("Speaker Driver Analog Gain", TAS5720_ANALOG_CTRL_REG, 537 TAS5720_ANALOG_GAIN_SHIFT, 3, 0, dac_analog_tlv), 538}; 539 540static const struct snd_kcontrol_new tas5722_snd_controls[] = { 541 SOC_SINGLE_EXT_TLV("Speaker Driver Playback Volume", 542 0, 0, 511, 0, 543 tas5722_volume_get, tas5722_volume_set, 544 tas5722_dac_tlv), 545 SOC_SINGLE_TLV("Speaker Driver Analog Gain", TAS5720_ANALOG_CTRL_REG, 546 TAS5720_ANALOG_GAIN_SHIFT, 3, 0, dac_analog_tlv), 547}; 548 549static const struct snd_soc_dapm_widget tas5720_dapm_widgets[] = { 550 SND_SOC_DAPM_AIF_IN("DAC IN", "Playback", 0, SND_SOC_NOPM, 0, 0), 551 SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas5720_dac_event, 552 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), 553 SND_SOC_DAPM_OUTPUT("OUT") 554}; 555 556static const struct snd_soc_dapm_route tas5720_audio_map[] = { 557 { "DAC", NULL, "DAC IN" }, 558 { "OUT", NULL, "DAC" }, 559}; 560 561static const struct snd_soc_component_driver soc_component_dev_tas5720 = { 562 .probe = tas5720_codec_probe, 563 .remove = tas5720_codec_remove, 564 .suspend = tas5720_suspend, 565 .resume = tas5720_resume, 566 .controls = tas5720_snd_controls, 567 .num_controls = ARRAY_SIZE(tas5720_snd_controls), 568 .dapm_widgets = tas5720_dapm_widgets, 569 .num_dapm_widgets = ARRAY_SIZE(tas5720_dapm_widgets), 570 .dapm_routes = tas5720_audio_map, 571 .num_dapm_routes = ARRAY_SIZE(tas5720_audio_map), 572 .idle_bias_on = 1, 573 .use_pmdown_time = 1, 574 .endianness = 1, 575 .non_legacy_dai_naming = 1, 576}; 577 578static const struct snd_soc_component_driver soc_component_dev_tas5722 = { 579 .probe = tas5720_codec_probe, 580 .remove = tas5720_codec_remove, 581 .suspend = tas5720_suspend, 582 .resume = tas5720_resume, 583 .controls = tas5722_snd_controls, 584 .num_controls = ARRAY_SIZE(tas5722_snd_controls), 585 .dapm_widgets = tas5720_dapm_widgets, 586 .num_dapm_widgets = ARRAY_SIZE(tas5720_dapm_widgets), 587 .dapm_routes = tas5720_audio_map, 588 .num_dapm_routes = ARRAY_SIZE(tas5720_audio_map), 589 .idle_bias_on = 1, 590 .use_pmdown_time = 1, 591 .endianness = 1, 592 .non_legacy_dai_naming = 1, 593}; 594 595/* PCM rates supported by the TAS5720 driver */ 596#define TAS5720_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\ 597 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) 598 599/* Formats supported by TAS5720 driver */ 600#define TAS5720_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE |\ 601 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE) 602 603static const struct snd_soc_dai_ops tas5720_speaker_dai_ops = { 604 .hw_params = tas5720_hw_params, 605 .set_fmt = tas5720_set_dai_fmt, 606 .set_tdm_slot = tas5720_set_dai_tdm_slot, 607 .mute_stream = tas5720_mute, 608 .no_capture_mute = 1, 609}; 610 611/* 612 * TAS5720 DAI structure 613 * 614 * Note that were are advertising .playback.channels_max = 2 despite this being 615 * a mono amplifier. The reason for that is that some serial ports such as TI's 616 * McASP module have a minimum number of channels (2) that they can output. 617 * Advertising more channels than we have will allow us to interface with such 618 * a serial port without really any negative side effects as the TAS5720 will 619 * simply ignore any extra channel(s) asides from the one channel that is 620 * configured to be played back. 621 */ 622static struct snd_soc_dai_driver tas5720_dai[] = { 623 { 624 .name = "tas5720-amplifier", 625 .playback = { 626 .stream_name = "Playback", 627 .channels_min = 1, 628 .channels_max = 2, 629 .rates = TAS5720_RATES, 630 .formats = TAS5720_FORMATS, 631 }, 632 .ops = &tas5720_speaker_dai_ops, 633 }, 634}; 635 636static const struct i2c_device_id tas5720_id[] = { 637 { "tas5720", TAS5720 }, 638 { "tas5722", TAS5722 }, 639 { } 640}; 641MODULE_DEVICE_TABLE(i2c, tas5720_id); 642 643static int tas5720_probe(struct i2c_client *client) 644{ 645 struct device *dev = &client->dev; 646 struct tas5720_data *data; 647 const struct regmap_config *regmap_config; 648 const struct i2c_device_id *id; 649 int ret; 650 int i; 651 652 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 653 if (!data) 654 return -ENOMEM; 655 656 id = i2c_match_id(tas5720_id, client); 657 data->tas5720_client = client; 658 data->devtype = id->driver_data; 659 660 switch (id->driver_data) { 661 case TAS5720: 662 regmap_config = &tas5720_regmap_config; 663 break; 664 case TAS5722: 665 regmap_config = &tas5722_regmap_config; 666 break; 667 default: 668 dev_err(dev, "unexpected private driver data\n"); 669 return -EINVAL; 670 } 671 data->regmap = devm_regmap_init_i2c(client, regmap_config); 672 if (IS_ERR(data->regmap)) { 673 ret = PTR_ERR(data->regmap); 674 dev_err(dev, "failed to allocate register map: %d\n", ret); 675 return ret; 676 } 677 678 for (i = 0; i < ARRAY_SIZE(data->supplies); i++) 679 data->supplies[i].supply = tas5720_supply_names[i]; 680 681 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(data->supplies), 682 data->supplies); 683 if (ret != 0) { 684 dev_err(dev, "failed to request supplies: %d\n", ret); 685 return ret; 686 } 687 688 dev_set_drvdata(dev, data); 689 690 switch (id->driver_data) { 691 case TAS5720: 692 ret = devm_snd_soc_register_component(&client->dev, 693 &soc_component_dev_tas5720, 694 tas5720_dai, 695 ARRAY_SIZE(tas5720_dai)); 696 break; 697 case TAS5722: 698 ret = devm_snd_soc_register_component(&client->dev, 699 &soc_component_dev_tas5722, 700 tas5720_dai, 701 ARRAY_SIZE(tas5720_dai)); 702 break; 703 default: 704 dev_err(dev, "unexpected private driver data\n"); 705 return -EINVAL; 706 } 707 if (ret < 0) { 708 dev_err(dev, "failed to register component: %d\n", ret); 709 return ret; 710 } 711 712 return 0; 713} 714 715#if IS_ENABLED(CONFIG_OF) 716static const struct of_device_id tas5720_of_match[] = { 717 { .compatible = "ti,tas5720", }, 718 { .compatible = "ti,tas5722", }, 719 { }, 720}; 721MODULE_DEVICE_TABLE(of, tas5720_of_match); 722#endif 723 724static struct i2c_driver tas5720_i2c_driver = { 725 .driver = { 726 .name = "tas5720", 727 .of_match_table = of_match_ptr(tas5720_of_match), 728 }, 729 .probe_new = tas5720_probe, 730 .id_table = tas5720_id, 731}; 732 733module_i2c_driver(tas5720_i2c_driver); 734 735MODULE_AUTHOR("Andreas Dannenberg <dannenberg@ti.com>"); 736MODULE_DESCRIPTION("TAS5720 Audio amplifier driver"); 737MODULE_LICENSE("GPL");