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