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