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 static const struct regmap_config tas5722_regmap_config = { 470 .reg_bits = 8, 471 .val_bits = 8, 472 473 .max_register = TAS5722_MAX_REG, 474 .cache_type = REGCACHE_RBTREE, 475 .volatile_reg = tas5720_is_volatile_reg, 476 }; 477 478 /* 479 * DAC analog gain. There are four discrete values to select from, ranging 480 * from 19.2 dB to 26.3dB. 481 */ 482 static const DECLARE_TLV_DB_RANGE(dac_analog_tlv, 483 0x0, 0x0, TLV_DB_SCALE_ITEM(1920, 0, 0), 484 0x1, 0x1, TLV_DB_SCALE_ITEM(2070, 0, 0), 485 0x2, 0x2, TLV_DB_SCALE_ITEM(2350, 0, 0), 486 0x3, 0x3, TLV_DB_SCALE_ITEM(2630, 0, 0), 487 ); 488 489 /* 490 * DAC digital volumes. From -103.5 to 24 dB in 0.5 dB steps. Note that 491 * setting the gain below -100 dB (register value <0x7) is effectively a MUTE 492 * as per device datasheet. 493 */ 494 static DECLARE_TLV_DB_SCALE(dac_tlv, -10350, 50, 0); 495 496 static const struct snd_kcontrol_new tas5720_snd_controls[] = { 497 SOC_SINGLE_TLV("Speaker Driver Playback Volume", 498 TAS5720_VOLUME_CTRL_REG, 0, 0xff, 0, dac_tlv), 499 SOC_SINGLE_TLV("Speaker Driver Analog Gain", TAS5720_ANALOG_CTRL_REG, 500 TAS5720_ANALOG_GAIN_SHIFT, 3, 0, dac_analog_tlv), 501 }; 502 503 static const struct snd_soc_dapm_widget tas5720_dapm_widgets[] = { 504 SND_SOC_DAPM_AIF_IN("DAC IN", "Playback", 0, SND_SOC_NOPM, 0, 0), 505 SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas5720_dac_event, 506 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), 507 SND_SOC_DAPM_OUTPUT("OUT") 508 }; 509 510 static const struct snd_soc_dapm_route tas5720_audio_map[] = { 511 { "DAC", NULL, "DAC IN" }, 512 { "OUT", NULL, "DAC" }, 513 }; 514 515 static const struct snd_soc_codec_driver soc_codec_dev_tas5720 = { 516 .probe = tas5720_codec_probe, 517 .remove = tas5720_codec_remove, 518 .suspend = tas5720_suspend, 519 .resume = tas5720_resume, 520 521 .component_driver = { 522 .controls = tas5720_snd_controls, 523 .num_controls = ARRAY_SIZE(tas5720_snd_controls), 524 .dapm_widgets = tas5720_dapm_widgets, 525 .num_dapm_widgets = ARRAY_SIZE(tas5720_dapm_widgets), 526 .dapm_routes = tas5720_audio_map, 527 .num_dapm_routes = ARRAY_SIZE(tas5720_audio_map), 528 }, 529 }; 530 531 /* PCM rates supported by the TAS5720 driver */ 532 #define TAS5720_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\ 533 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) 534 535 /* Formats supported by TAS5720 driver */ 536 #define TAS5720_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE |\ 537 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE) 538 539 static const struct snd_soc_dai_ops tas5720_speaker_dai_ops = { 540 .hw_params = tas5720_hw_params, 541 .set_fmt = tas5720_set_dai_fmt, 542 .set_tdm_slot = tas5720_set_dai_tdm_slot, 543 .digital_mute = tas5720_mute, 544 }; 545 546 /* 547 * TAS5720 DAI structure 548 * 549 * Note that were are advertising .playback.channels_max = 2 despite this being 550 * a mono amplifier. The reason for that is that some serial ports such as TI's 551 * McASP module have a minimum number of channels (2) that they can output. 552 * Advertising more channels than we have will allow us to interface with such 553 * a serial port without really any negative side effects as the TAS5720 will 554 * simply ignore any extra channel(s) asides from the one channel that is 555 * configured to be played back. 556 */ 557 static struct snd_soc_dai_driver tas5720_dai[] = { 558 { 559 .name = "tas5720-amplifier", 560 .playback = { 561 .stream_name = "Playback", 562 .channels_min = 1, 563 .channels_max = 2, 564 .rates = TAS5720_RATES, 565 .formats = TAS5720_FORMATS, 566 }, 567 .ops = &tas5720_speaker_dai_ops, 568 }, 569 }; 570 571 static int tas5720_probe(struct i2c_client *client, 572 const struct i2c_device_id *id) 573 { 574 struct device *dev = &client->dev; 575 struct tas5720_data *data; 576 const struct regmap_config *regmap_config; 577 int ret; 578 int i; 579 580 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 581 if (!data) 582 return -ENOMEM; 583 584 data->tas5720_client = client; 585 data->devtype = id->driver_data; 586 587 switch (id->driver_data) { 588 case TAS5720: 589 regmap_config = &tas5720_regmap_config; 590 break; 591 case TAS5722: 592 regmap_config = &tas5722_regmap_config; 593 break; 594 default: 595 dev_err(dev, "unexpected private driver data\n"); 596 return -EINVAL; 597 } 598 data->regmap = devm_regmap_init_i2c(client, regmap_config); 599 if (IS_ERR(data->regmap)) { 600 ret = PTR_ERR(data->regmap); 601 dev_err(dev, "failed to allocate register map: %d\n", ret); 602 return ret; 603 } 604 605 for (i = 0; i < ARRAY_SIZE(data->supplies); i++) 606 data->supplies[i].supply = tas5720_supply_names[i]; 607 608 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(data->supplies), 609 data->supplies); 610 if (ret != 0) { 611 dev_err(dev, "failed to request supplies: %d\n", ret); 612 return ret; 613 } 614 615 dev_set_drvdata(dev, data); 616 617 ret = snd_soc_register_codec(&client->dev, 618 &soc_codec_dev_tas5720, 619 tas5720_dai, ARRAY_SIZE(tas5720_dai)); 620 if (ret < 0) { 621 dev_err(dev, "failed to register codec: %d\n", ret); 622 return ret; 623 } 624 625 return 0; 626 } 627 628 static int tas5720_remove(struct i2c_client *client) 629 { 630 struct device *dev = &client->dev; 631 632 snd_soc_unregister_codec(dev); 633 634 return 0; 635 } 636 637 static const struct i2c_device_id tas5720_id[] = { 638 { "tas5720", TAS5720 }, 639 { "tas5722", TAS5722 }, 640 { } 641 }; 642 MODULE_DEVICE_TABLE(i2c, tas5720_id); 643 644 #if IS_ENABLED(CONFIG_OF) 645 static const struct of_device_id tas5720_of_match[] = { 646 { .compatible = "ti,tas5720", }, 647 { .compatible = "ti,tas5722", }, 648 { }, 649 }; 650 MODULE_DEVICE_TABLE(of, tas5720_of_match); 651 #endif 652 653 static struct i2c_driver tas5720_i2c_driver = { 654 .driver = { 655 .name = "tas5720", 656 .of_match_table = of_match_ptr(tas5720_of_match), 657 }, 658 .probe = tas5720_probe, 659 .remove = tas5720_remove, 660 .id_table = tas5720_id, 661 }; 662 663 module_i2c_driver(tas5720_i2c_driver); 664 665 MODULE_AUTHOR("Andreas Dannenberg <dannenberg@ti.com>"); 666 MODULE_DESCRIPTION("TAS5720 Audio amplifier driver"); 667 MODULE_LICENSE("GPL"); 668