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_codec *codec; 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_codec *codec = dai->codec; 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(codec->dev, "unsupported sample rate: %u\n", rate); 81 return -EINVAL; 82 } 83 84 ret = snd_soc_update_bits(codec, TAS5720_DIGITAL_CTRL1_REG, 85 TAS5720_SSZ_DS, ssz_ds); 86 if (ret < 0) { 87 dev_err(codec->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_codec *codec = dai->codec; 97 u8 serial_format; 98 int ret; 99 100 if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) { 101 dev_vdbg(codec->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(codec->dev, "DAI Format is not found\n"); 136 return -EINVAL; 137 } 138 139 ret = snd_soc_update_bits(codec, TAS5720_DIGITAL_CTRL1_REG, 140 TAS5720_SAIF_FORMAT_MASK, 141 serial_format); 142 if (ret < 0) { 143 dev_err(codec->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_codec *codec = dai->codec; 155 unsigned int first_slot; 156 int ret; 157 158 if (!tx_mask) { 159 dev_err(codec->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(codec->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_update_bits(codec, TAS5720_DIGITAL_CTRL1_REG, 178 TAS5720_TDM_CFG_SRC, TAS5720_TDM_CFG_SRC); 179 if (ret < 0) 180 goto error_snd_soc_update_bits; 181 182 /* Configure the TDM slot to process audio from */ 183 ret = snd_soc_update_bits(codec, TAS5720_DIGITAL_CTRL2_REG, 184 TAS5720_TDM_SLOT_SEL_MASK, first_slot); 185 if (ret < 0) 186 goto error_snd_soc_update_bits; 187 188 return 0; 189 190 error_snd_soc_update_bits: 191 dev_err(codec->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_codec *codec = dai->codec; 198 int ret; 199 200 ret = snd_soc_update_bits(codec, TAS5720_DIGITAL_CTRL2_REG, 201 TAS5720_MUTE, mute ? TAS5720_MUTE : 0); 202 if (ret < 0) { 203 dev_err(codec->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->codec->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_codec *codec) 271 { 272 struct tas5720_data *tas5720 = snd_soc_codec_get_drvdata(codec); 273 unsigned int device_id, expected_device_id; 274 int ret; 275 276 tas5720->codec = codec; 277 278 ret = regulator_bulk_enable(ARRAY_SIZE(tas5720->supplies), 279 tas5720->supplies); 280 if (ret != 0) { 281 dev_err(codec->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(codec->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(codec->dev, "unexpected private driver data\n"); 306 return -EINVAL; 307 } 308 309 if (device_id != expected_device_id) 310 dev_warn(codec->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_update_bits(codec, TAS5720_DIGITAL_CTRL2_REG, 315 TAS5720_MUTE, TAS5720_MUTE); 316 if (ret < 0) 317 goto error_snd_soc_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_update_bits(codec, TAS5720_POWER_CTRL_REG, 326 TAS5720_SDZ, 0); 327 if (ret < 0) 328 goto error_snd_soc_update_bits; 329 330 INIT_DELAYED_WORK(&tas5720->fault_check_work, tas5720_fault_check_work); 331 332 return 0; 333 334 error_snd_soc_update_bits: 335 dev_err(codec->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 int tas5720_codec_remove(struct snd_soc_codec *codec) 344 { 345 struct tas5720_data *tas5720 = snd_soc_codec_get_drvdata(codec); 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(codec->dev, "failed to disable supplies: %d\n", ret); 354 355 return ret; 356 }; 357 358 static int tas5720_dac_event(struct snd_soc_dapm_widget *w, 359 struct snd_kcontrol *kcontrol, int event) 360 { 361 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); 362 struct tas5720_data *tas5720 = snd_soc_codec_get_drvdata(codec); 363 int ret; 364 365 if (event & SND_SOC_DAPM_POST_PMU) { 366 /* Take TAS5720 out of shutdown mode */ 367 ret = snd_soc_update_bits(codec, TAS5720_POWER_CTRL_REG, 368 TAS5720_SDZ, TAS5720_SDZ); 369 if (ret < 0) { 370 dev_err(codec->dev, "error waking codec: %d\n", ret); 371 return ret; 372 } 373 374 /* 375 * Observe codec shutdown-to-active time. The datasheet only 376 * lists a nominal value however just use-it as-is without 377 * additional padding to minimize the delay introduced in 378 * starting to play audio (actually there is other setup done 379 * by the ASoC framework that will provide additional delays, 380 * so we should always be safe). 381 */ 382 msleep(25); 383 384 /* Turn on TAS5720 periodic fault checking/handling */ 385 tas5720->last_fault = 0; 386 schedule_delayed_work(&tas5720->fault_check_work, 387 msecs_to_jiffies(TAS5720_FAULT_CHECK_INTERVAL)); 388 } else if (event & SND_SOC_DAPM_PRE_PMD) { 389 /* Disable TAS5720 periodic fault checking/handling */ 390 cancel_delayed_work_sync(&tas5720->fault_check_work); 391 392 /* Place TAS5720 in shutdown mode to minimize current draw */ 393 ret = snd_soc_update_bits(codec, TAS5720_POWER_CTRL_REG, 394 TAS5720_SDZ, 0); 395 if (ret < 0) { 396 dev_err(codec->dev, "error shutting down codec: %d\n", 397 ret); 398 return ret; 399 } 400 } 401 402 return 0; 403 } 404 405 #ifdef CONFIG_PM 406 static int tas5720_suspend(struct snd_soc_codec *codec) 407 { 408 struct tas5720_data *tas5720 = snd_soc_codec_get_drvdata(codec); 409 int ret; 410 411 regcache_cache_only(tas5720->regmap, true); 412 regcache_mark_dirty(tas5720->regmap); 413 414 ret = regulator_bulk_disable(ARRAY_SIZE(tas5720->supplies), 415 tas5720->supplies); 416 if (ret < 0) 417 dev_err(codec->dev, "failed to disable supplies: %d\n", ret); 418 419 return ret; 420 } 421 422 static int tas5720_resume(struct snd_soc_codec *codec) 423 { 424 struct tas5720_data *tas5720 = snd_soc_codec_get_drvdata(codec); 425 int ret; 426 427 ret = regulator_bulk_enable(ARRAY_SIZE(tas5720->supplies), 428 tas5720->supplies); 429 if (ret < 0) { 430 dev_err(codec->dev, "failed to enable supplies: %d\n", ret); 431 return ret; 432 } 433 434 regcache_cache_only(tas5720->regmap, false); 435 436 ret = regcache_sync(tas5720->regmap); 437 if (ret < 0) { 438 dev_err(codec->dev, "failed to sync regcache: %d\n", ret); 439 return ret; 440 } 441 442 return 0; 443 } 444 #else 445 #define tas5720_suspend NULL 446 #define tas5720_resume NULL 447 #endif 448 449 static bool tas5720_is_volatile_reg(struct device *dev, unsigned int reg) 450 { 451 switch (reg) { 452 case TAS5720_DEVICE_ID_REG: 453 case TAS5720_FAULT_REG: 454 return true; 455 default: 456 return false; 457 } 458 } 459 460 static const struct regmap_config tas5720_regmap_config = { 461 .reg_bits = 8, 462 .val_bits = 8, 463 464 .max_register = TAS5720_MAX_REG, 465 .cache_type = REGCACHE_RBTREE, 466 .volatile_reg = tas5720_is_volatile_reg, 467 }; 468 469 /* 470 * DAC analog gain. There are four discrete values to select from, ranging 471 * from 19.2 dB to 26.3dB. 472 */ 473 static const DECLARE_TLV_DB_RANGE(dac_analog_tlv, 474 0x0, 0x0, TLV_DB_SCALE_ITEM(1920, 0, 0), 475 0x1, 0x1, TLV_DB_SCALE_ITEM(2070, 0, 0), 476 0x2, 0x2, TLV_DB_SCALE_ITEM(2350, 0, 0), 477 0x3, 0x3, TLV_DB_SCALE_ITEM(2630, 0, 0), 478 ); 479 480 /* 481 * DAC digital volumes. From -103.5 to 24 dB in 0.5 dB steps. Note that 482 * setting the gain below -100 dB (register value <0x7) is effectively a MUTE 483 * as per device datasheet. 484 */ 485 static DECLARE_TLV_DB_SCALE(dac_tlv, -10350, 50, 0); 486 487 static const struct snd_kcontrol_new tas5720_snd_controls[] = { 488 SOC_SINGLE_TLV("Speaker Driver Playback Volume", 489 TAS5720_VOLUME_CTRL_REG, 0, 0xff, 0, dac_tlv), 490 SOC_SINGLE_TLV("Speaker Driver Analog Gain", TAS5720_ANALOG_CTRL_REG, 491 TAS5720_ANALOG_GAIN_SHIFT, 3, 0, dac_analog_tlv), 492 }; 493 494 static const struct snd_soc_dapm_widget tas5720_dapm_widgets[] = { 495 SND_SOC_DAPM_AIF_IN("DAC IN", "Playback", 0, SND_SOC_NOPM, 0, 0), 496 SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas5720_dac_event, 497 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), 498 SND_SOC_DAPM_OUTPUT("OUT") 499 }; 500 501 static const struct snd_soc_dapm_route tas5720_audio_map[] = { 502 { "DAC", NULL, "DAC IN" }, 503 { "OUT", NULL, "DAC" }, 504 }; 505 506 static const struct snd_soc_codec_driver soc_codec_dev_tas5720 = { 507 .probe = tas5720_codec_probe, 508 .remove = tas5720_codec_remove, 509 .suspend = tas5720_suspend, 510 .resume = tas5720_resume, 511 512 .component_driver = { 513 .controls = tas5720_snd_controls, 514 .num_controls = ARRAY_SIZE(tas5720_snd_controls), 515 .dapm_widgets = tas5720_dapm_widgets, 516 .num_dapm_widgets = ARRAY_SIZE(tas5720_dapm_widgets), 517 .dapm_routes = tas5720_audio_map, 518 .num_dapm_routes = ARRAY_SIZE(tas5720_audio_map), 519 }, 520 }; 521 522 /* PCM rates supported by the TAS5720 driver */ 523 #define TAS5720_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\ 524 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) 525 526 /* Formats supported by TAS5720 driver */ 527 #define TAS5720_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE |\ 528 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE) 529 530 static const struct snd_soc_dai_ops tas5720_speaker_dai_ops = { 531 .hw_params = tas5720_hw_params, 532 .set_fmt = tas5720_set_dai_fmt, 533 .set_tdm_slot = tas5720_set_dai_tdm_slot, 534 .digital_mute = tas5720_mute, 535 }; 536 537 /* 538 * TAS5720 DAI structure 539 * 540 * Note that were are advertising .playback.channels_max = 2 despite this being 541 * a mono amplifier. The reason for that is that some serial ports such as TI's 542 * McASP module have a minimum number of channels (2) that they can output. 543 * Advertising more channels than we have will allow us to interface with such 544 * a serial port without really any negative side effects as the TAS5720 will 545 * simply ignore any extra channel(s) asides from the one channel that is 546 * configured to be played back. 547 */ 548 static struct snd_soc_dai_driver tas5720_dai[] = { 549 { 550 .name = "tas5720-amplifier", 551 .playback = { 552 .stream_name = "Playback", 553 .channels_min = 1, 554 .channels_max = 2, 555 .rates = TAS5720_RATES, 556 .formats = TAS5720_FORMATS, 557 }, 558 .ops = &tas5720_speaker_dai_ops, 559 }, 560 }; 561 562 static int tas5720_probe(struct i2c_client *client, 563 const struct i2c_device_id *id) 564 { 565 struct device *dev = &client->dev; 566 struct tas5720_data *data; 567 int ret; 568 int i; 569 570 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 571 if (!data) 572 return -ENOMEM; 573 574 data->tas5720_client = client; 575 data->devtype = id->driver_data; 576 577 data->regmap = devm_regmap_init_i2c(client, &tas5720_regmap_config); 578 if (IS_ERR(data->regmap)) { 579 ret = PTR_ERR(data->regmap); 580 dev_err(dev, "failed to allocate register map: %d\n", ret); 581 return ret; 582 } 583 584 for (i = 0; i < ARRAY_SIZE(data->supplies); i++) 585 data->supplies[i].supply = tas5720_supply_names[i]; 586 587 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(data->supplies), 588 data->supplies); 589 if (ret != 0) { 590 dev_err(dev, "failed to request supplies: %d\n", ret); 591 return ret; 592 } 593 594 dev_set_drvdata(dev, data); 595 596 ret = snd_soc_register_codec(&client->dev, 597 &soc_codec_dev_tas5720, 598 tas5720_dai, ARRAY_SIZE(tas5720_dai)); 599 if (ret < 0) { 600 dev_err(dev, "failed to register codec: %d\n", ret); 601 return ret; 602 } 603 604 return 0; 605 } 606 607 static int tas5720_remove(struct i2c_client *client) 608 { 609 struct device *dev = &client->dev; 610 611 snd_soc_unregister_codec(dev); 612 613 return 0; 614 } 615 616 static const struct i2c_device_id tas5720_id[] = { 617 { "tas5720", TAS5720 }, 618 { "tas5722", TAS5722 }, 619 { } 620 }; 621 MODULE_DEVICE_TABLE(i2c, tas5720_id); 622 623 #if IS_ENABLED(CONFIG_OF) 624 static const struct of_device_id tas5720_of_match[] = { 625 { .compatible = "ti,tas5720", }, 626 { .compatible = "ti,tas5722", }, 627 { }, 628 }; 629 MODULE_DEVICE_TABLE(of, tas5720_of_match); 630 #endif 631 632 static struct i2c_driver tas5720_i2c_driver = { 633 .driver = { 634 .name = "tas5720", 635 .of_match_table = of_match_ptr(tas5720_of_match), 636 }, 637 .probe = tas5720_probe, 638 .remove = tas5720_remove, 639 .id_table = tas5720_id, 640 }; 641 642 module_i2c_driver(tas5720_i2c_driver); 643 644 MODULE_AUTHOR("Andreas Dannenberg <dannenberg@ti.com>"); 645 MODULE_DESCRIPTION("TAS5720 Audio amplifier driver"); 646 MODULE_LICENSE("GPL"); 647