1// SPDX-License-Identifier: GPL-2.0 2// 3// Driver for the Texas Instruments TAS2764 CODEC 4// Copyright (C) 2020 Texas Instruments Inc. 5 6#include <linux/module.h> 7#include <linux/moduleparam.h> 8#include <linux/err.h> 9#include <linux/init.h> 10#include <linux/delay.h> 11#include <linux/pm.h> 12#include <linux/i2c.h> 13#include <linux/gpio.h> 14#include <linux/gpio/consumer.h> 15#include <linux/regulator/consumer.h> 16#include <linux/regmap.h> 17#include <linux/of.h> 18#include <linux/of_gpio.h> 19#include <linux/slab.h> 20#include <sound/soc.h> 21#include <sound/pcm.h> 22#include <sound/pcm_params.h> 23#include <sound/initval.h> 24#include <sound/tlv.h> 25 26#include "tas2764.h" 27 28struct tas2764_priv { 29 struct snd_soc_component *component; 30 struct gpio_desc *reset_gpio; 31 struct gpio_desc *sdz_gpio; 32 struct regmap *regmap; 33 struct device *dev; 34 35 int v_sense_slot; 36 int i_sense_slot; 37 38 bool dac_powered; 39 bool unmuted; 40}; 41 42static void tas2764_reset(struct tas2764_priv *tas2764) 43{ 44 if (tas2764->reset_gpio) { 45 gpiod_set_value_cansleep(tas2764->reset_gpio, 0); 46 msleep(20); 47 gpiod_set_value_cansleep(tas2764->reset_gpio, 1); 48 usleep_range(1000, 2000); 49 } 50 51 snd_soc_component_write(tas2764->component, TAS2764_SW_RST, 52 TAS2764_RST); 53 usleep_range(1000, 2000); 54} 55 56static int tas2764_update_pwr_ctrl(struct tas2764_priv *tas2764) 57{ 58 struct snd_soc_component *component = tas2764->component; 59 unsigned int val; 60 int ret; 61 62 if (tas2764->dac_powered) 63 val = tas2764->unmuted ? 64 TAS2764_PWR_CTRL_ACTIVE : TAS2764_PWR_CTRL_MUTE; 65 else 66 val = TAS2764_PWR_CTRL_SHUTDOWN; 67 68 ret = snd_soc_component_update_bits(component, TAS2764_PWR_CTRL, 69 TAS2764_PWR_CTRL_MASK, val); 70 if (ret < 0) 71 return ret; 72 73 return 0; 74} 75 76#ifdef CONFIG_PM 77static int tas2764_codec_suspend(struct snd_soc_component *component) 78{ 79 struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component); 80 int ret; 81 82 ret = snd_soc_component_update_bits(component, TAS2764_PWR_CTRL, 83 TAS2764_PWR_CTRL_MASK, 84 TAS2764_PWR_CTRL_SHUTDOWN); 85 86 if (ret < 0) 87 return ret; 88 89 if (tas2764->sdz_gpio) 90 gpiod_set_value_cansleep(tas2764->sdz_gpio, 0); 91 92 regcache_cache_only(tas2764->regmap, true); 93 regcache_mark_dirty(tas2764->regmap); 94 95 return 0; 96} 97 98static int tas2764_codec_resume(struct snd_soc_component *component) 99{ 100 struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component); 101 int ret; 102 103 if (tas2764->sdz_gpio) { 104 gpiod_set_value_cansleep(tas2764->sdz_gpio, 1); 105 usleep_range(1000, 2000); 106 } 107 108 ret = tas2764_update_pwr_ctrl(tas2764); 109 110 if (ret < 0) 111 return ret; 112 113 regcache_cache_only(tas2764->regmap, false); 114 115 return regcache_sync(tas2764->regmap); 116} 117#else 118#define tas2764_codec_suspend NULL 119#define tas2764_codec_resume NULL 120#endif 121 122static const char * const tas2764_ASI1_src[] = { 123 "I2C offset", "Left", "Right", "LeftRightDiv2", 124}; 125 126static SOC_ENUM_SINGLE_DECL( 127 tas2764_ASI1_src_enum, TAS2764_TDM_CFG2, TAS2764_TDM_CFG2_SCFG_SHIFT, 128 tas2764_ASI1_src); 129 130static const struct snd_kcontrol_new tas2764_asi1_mux = 131 SOC_DAPM_ENUM("ASI1 Source", tas2764_ASI1_src_enum); 132 133static int tas2764_dac_event(struct snd_soc_dapm_widget *w, 134 struct snd_kcontrol *kcontrol, int event) 135{ 136 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 137 struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component); 138 int ret; 139 140 switch (event) { 141 case SND_SOC_DAPM_POST_PMU: 142 tas2764->dac_powered = true; 143 ret = tas2764_update_pwr_ctrl(tas2764); 144 break; 145 case SND_SOC_DAPM_PRE_PMD: 146 tas2764->dac_powered = false; 147 ret = tas2764_update_pwr_ctrl(tas2764); 148 break; 149 default: 150 dev_err(tas2764->dev, "Unsupported event\n"); 151 return -EINVAL; 152 } 153 154 if (ret < 0) 155 return ret; 156 157 return 0; 158} 159 160static const struct snd_kcontrol_new isense_switch = 161 SOC_DAPM_SINGLE("Switch", TAS2764_PWR_CTRL, TAS2764_ISENSE_POWER_EN, 1, 1); 162static const struct snd_kcontrol_new vsense_switch = 163 SOC_DAPM_SINGLE("Switch", TAS2764_PWR_CTRL, TAS2764_VSENSE_POWER_EN, 1, 1); 164 165static const struct snd_soc_dapm_widget tas2764_dapm_widgets[] = { 166 SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0), 167 SND_SOC_DAPM_MUX("ASI1 Sel", SND_SOC_NOPM, 0, 0, &tas2764_asi1_mux), 168 SND_SOC_DAPM_SWITCH("ISENSE", TAS2764_PWR_CTRL, TAS2764_ISENSE_POWER_EN, 169 1, &isense_switch), 170 SND_SOC_DAPM_SWITCH("VSENSE", TAS2764_PWR_CTRL, TAS2764_VSENSE_POWER_EN, 171 1, &vsense_switch), 172 SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas2764_dac_event, 173 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), 174 SND_SOC_DAPM_OUTPUT("OUT"), 175 SND_SOC_DAPM_SIGGEN("VMON"), 176 SND_SOC_DAPM_SIGGEN("IMON") 177}; 178 179static const struct snd_soc_dapm_route tas2764_audio_map[] = { 180 {"ASI1 Sel", "I2C offset", "ASI1"}, 181 {"ASI1 Sel", "Left", "ASI1"}, 182 {"ASI1 Sel", "Right", "ASI1"}, 183 {"ASI1 Sel", "LeftRightDiv2", "ASI1"}, 184 {"DAC", NULL, "ASI1 Sel"}, 185 {"OUT", NULL, "DAC"}, 186 {"ISENSE", "Switch", "IMON"}, 187 {"VSENSE", "Switch", "VMON"}, 188}; 189 190static int tas2764_mute(struct snd_soc_dai *dai, int mute, int direction) 191{ 192 struct tas2764_priv *tas2764 = 193 snd_soc_component_get_drvdata(dai->component); 194 195 tas2764->unmuted = !mute; 196 return tas2764_update_pwr_ctrl(tas2764); 197} 198 199static int tas2764_set_bitwidth(struct tas2764_priv *tas2764, int bitwidth) 200{ 201 struct snd_soc_component *component = tas2764->component; 202 int sense_en; 203 int val; 204 int ret; 205 206 switch (bitwidth) { 207 case SNDRV_PCM_FORMAT_S16_LE: 208 ret = snd_soc_component_update_bits(component, 209 TAS2764_TDM_CFG2, 210 TAS2764_TDM_CFG2_RXW_MASK, 211 TAS2764_TDM_CFG2_RXW_16BITS); 212 break; 213 case SNDRV_PCM_FORMAT_S24_LE: 214 ret = snd_soc_component_update_bits(component, 215 TAS2764_TDM_CFG2, 216 TAS2764_TDM_CFG2_RXW_MASK, 217 TAS2764_TDM_CFG2_RXW_24BITS); 218 break; 219 case SNDRV_PCM_FORMAT_S32_LE: 220 ret = snd_soc_component_update_bits(component, 221 TAS2764_TDM_CFG2, 222 TAS2764_TDM_CFG2_RXW_MASK, 223 TAS2764_TDM_CFG2_RXW_32BITS); 224 break; 225 226 default: 227 return -EINVAL; 228 } 229 230 if (ret < 0) 231 return ret; 232 233 val = snd_soc_component_read(tas2764->component, TAS2764_PWR_CTRL); 234 if (val < 0) 235 return val; 236 237 if (val & (1 << TAS2764_VSENSE_POWER_EN)) 238 sense_en = 0; 239 else 240 sense_en = TAS2764_TDM_CFG5_VSNS_ENABLE; 241 242 ret = snd_soc_component_update_bits(tas2764->component, TAS2764_TDM_CFG5, 243 TAS2764_TDM_CFG5_VSNS_ENABLE, 244 sense_en); 245 if (ret < 0) 246 return ret; 247 248 if (val & (1 << TAS2764_ISENSE_POWER_EN)) 249 sense_en = 0; 250 else 251 sense_en = TAS2764_TDM_CFG6_ISNS_ENABLE; 252 253 ret = snd_soc_component_update_bits(tas2764->component, TAS2764_TDM_CFG6, 254 TAS2764_TDM_CFG6_ISNS_ENABLE, 255 sense_en); 256 if (ret < 0) 257 return ret; 258 259 return 0; 260} 261 262static int tas2764_set_samplerate(struct tas2764_priv *tas2764, int samplerate) 263{ 264 struct snd_soc_component *component = tas2764->component; 265 int ramp_rate_val; 266 int ret; 267 268 switch (samplerate) { 269 case 48000: 270 ramp_rate_val = TAS2764_TDM_CFG0_SMP_48KHZ | 271 TAS2764_TDM_CFG0_44_1_48KHZ; 272 break; 273 case 44100: 274 ramp_rate_val = TAS2764_TDM_CFG0_SMP_44_1KHZ | 275 TAS2764_TDM_CFG0_44_1_48KHZ; 276 break; 277 case 96000: 278 ramp_rate_val = TAS2764_TDM_CFG0_SMP_48KHZ | 279 TAS2764_TDM_CFG0_88_2_96KHZ; 280 break; 281 case 88200: 282 ramp_rate_val = TAS2764_TDM_CFG0_SMP_44_1KHZ | 283 TAS2764_TDM_CFG0_88_2_96KHZ; 284 break; 285 default: 286 return -EINVAL; 287 } 288 289 ret = snd_soc_component_update_bits(component, TAS2764_TDM_CFG0, 290 TAS2764_TDM_CFG0_SMP_MASK | 291 TAS2764_TDM_CFG0_MASK, 292 ramp_rate_val); 293 if (ret < 0) 294 return ret; 295 296 return 0; 297} 298 299static int tas2764_hw_params(struct snd_pcm_substream *substream, 300 struct snd_pcm_hw_params *params, 301 struct snd_soc_dai *dai) 302{ 303 struct snd_soc_component *component = dai->component; 304 struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component); 305 int ret; 306 307 ret = tas2764_set_bitwidth(tas2764, params_format(params)); 308 if (ret < 0) 309 return ret; 310 311 return tas2764_set_samplerate(tas2764, params_rate(params)); 312} 313 314static int tas2764_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 315{ 316 struct snd_soc_component *component = dai->component; 317 struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component); 318 u8 tdm_rx_start_slot = 0, asi_cfg_0 = 0, asi_cfg_1 = 0; 319 int ret; 320 321 switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 322 case SND_SOC_DAIFMT_NB_IF: 323 asi_cfg_0 ^= TAS2764_TDM_CFG0_FRAME_START; 324 fallthrough; 325 case SND_SOC_DAIFMT_NB_NF: 326 asi_cfg_1 = TAS2764_TDM_CFG1_RX_RISING; 327 break; 328 case SND_SOC_DAIFMT_IB_IF: 329 asi_cfg_0 ^= TAS2764_TDM_CFG0_FRAME_START; 330 fallthrough; 331 case SND_SOC_DAIFMT_IB_NF: 332 asi_cfg_1 = TAS2764_TDM_CFG1_RX_FALLING; 333 break; 334 } 335 336 ret = snd_soc_component_update_bits(component, TAS2764_TDM_CFG1, 337 TAS2764_TDM_CFG1_RX_MASK, 338 asi_cfg_1); 339 if (ret < 0) 340 return ret; 341 342 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 343 case SND_SOC_DAIFMT_I2S: 344 asi_cfg_0 ^= TAS2764_TDM_CFG0_FRAME_START; 345 fallthrough; 346 case SND_SOC_DAIFMT_DSP_A: 347 tdm_rx_start_slot = 1; 348 break; 349 case SND_SOC_DAIFMT_DSP_B: 350 case SND_SOC_DAIFMT_LEFT_J: 351 tdm_rx_start_slot = 0; 352 break; 353 default: 354 dev_err(tas2764->dev, 355 "DAI Format is not found, fmt=0x%x\n", fmt); 356 return -EINVAL; 357 } 358 359 ret = snd_soc_component_update_bits(component, TAS2764_TDM_CFG0, 360 TAS2764_TDM_CFG0_FRAME_START, 361 asi_cfg_0); 362 if (ret < 0) 363 return ret; 364 365 ret = snd_soc_component_update_bits(component, TAS2764_TDM_CFG1, 366 TAS2764_TDM_CFG1_MASK, 367 (tdm_rx_start_slot << TAS2764_TDM_CFG1_51_SHIFT)); 368 if (ret < 0) 369 return ret; 370 371 return 0; 372} 373 374static int tas2764_set_dai_tdm_slot(struct snd_soc_dai *dai, 375 unsigned int tx_mask, 376 unsigned int rx_mask, 377 int slots, int slot_width) 378{ 379 struct snd_soc_component *component = dai->component; 380 struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component); 381 int left_slot, right_slot; 382 int slots_cfg; 383 int slot_size; 384 int ret; 385 386 if (tx_mask == 0 || rx_mask != 0) 387 return -EINVAL; 388 389 left_slot = __ffs(tx_mask); 390 tx_mask &= ~(1 << left_slot); 391 if (tx_mask == 0) { 392 right_slot = left_slot; 393 } else { 394 right_slot = __ffs(tx_mask); 395 tx_mask &= ~(1 << right_slot); 396 } 397 398 if (tx_mask != 0 || left_slot >= slots || right_slot >= slots) 399 return -EINVAL; 400 401 slots_cfg = (right_slot << TAS2764_TDM_CFG3_RXS_SHIFT) | left_slot; 402 403 ret = snd_soc_component_write(component, TAS2764_TDM_CFG3, slots_cfg); 404 if (ret) 405 return ret; 406 407 switch (slot_width) { 408 case 16: 409 slot_size = TAS2764_TDM_CFG2_RXS_16BITS; 410 break; 411 case 24: 412 slot_size = TAS2764_TDM_CFG2_RXS_24BITS; 413 break; 414 case 32: 415 slot_size = TAS2764_TDM_CFG2_RXS_32BITS; 416 break; 417 default: 418 return -EINVAL; 419 } 420 421 ret = snd_soc_component_update_bits(component, TAS2764_TDM_CFG2, 422 TAS2764_TDM_CFG2_RXS_MASK, 423 slot_size); 424 if (ret < 0) 425 return ret; 426 427 ret = snd_soc_component_update_bits(component, TAS2764_TDM_CFG5, 428 TAS2764_TDM_CFG5_50_MASK, 429 tas2764->v_sense_slot); 430 if (ret < 0) 431 return ret; 432 433 ret = snd_soc_component_update_bits(component, TAS2764_TDM_CFG6, 434 TAS2764_TDM_CFG6_50_MASK, 435 tas2764->i_sense_slot); 436 if (ret < 0) 437 return ret; 438 439 return 0; 440} 441 442static struct snd_soc_dai_ops tas2764_dai_ops = { 443 .mute_stream = tas2764_mute, 444 .hw_params = tas2764_hw_params, 445 .set_fmt = tas2764_set_fmt, 446 .set_tdm_slot = tas2764_set_dai_tdm_slot, 447 .no_capture_mute = 1, 448}; 449 450#define TAS2764_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ 451 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) 452 453#define TAS2764_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\ 454 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_88200) 455 456static struct snd_soc_dai_driver tas2764_dai_driver[] = { 457 { 458 .name = "tas2764 ASI1", 459 .id = 0, 460 .playback = { 461 .stream_name = "ASI1 Playback", 462 .channels_min = 1, 463 .channels_max = 2, 464 .rates = TAS2764_RATES, 465 .formats = TAS2764_FORMATS, 466 }, 467 .capture = { 468 .stream_name = "ASI1 Capture", 469 .channels_min = 0, 470 .channels_max = 2, 471 .rates = TAS2764_RATES, 472 .formats = TAS2764_FORMATS, 473 }, 474 .ops = &tas2764_dai_ops, 475 .symmetric_rates = 1, 476 }, 477}; 478 479static int tas2764_codec_probe(struct snd_soc_component *component) 480{ 481 struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component); 482 int ret; 483 484 tas2764->component = component; 485 486 if (tas2764->sdz_gpio) { 487 gpiod_set_value_cansleep(tas2764->sdz_gpio, 1); 488 usleep_range(1000, 2000); 489 } 490 491 tas2764_reset(tas2764); 492 493 ret = snd_soc_component_update_bits(tas2764->component, TAS2764_TDM_CFG5, 494 TAS2764_TDM_CFG5_VSNS_ENABLE, 0); 495 if (ret < 0) 496 return ret; 497 498 ret = snd_soc_component_update_bits(tas2764->component, TAS2764_TDM_CFG6, 499 TAS2764_TDM_CFG6_ISNS_ENABLE, 0); 500 if (ret < 0) 501 return ret; 502 503 return 0; 504} 505 506static DECLARE_TLV_DB_SCALE(tas2764_digital_tlv, 1100, 50, 0); 507static DECLARE_TLV_DB_SCALE(tas2764_playback_volume, -10050, 50, 1); 508 509static const struct snd_kcontrol_new tas2764_snd_controls[] = { 510 SOC_SINGLE_TLV("Speaker Volume", TAS2764_DVC, 0, 511 TAS2764_DVC_MAX, 1, tas2764_playback_volume), 512 SOC_SINGLE_TLV("Amp Gain Volume", TAS2764_CHNL_0, 1, 0x14, 0, 513 tas2764_digital_tlv), 514}; 515 516static const struct snd_soc_component_driver soc_component_driver_tas2764 = { 517 .probe = tas2764_codec_probe, 518 .suspend = tas2764_codec_suspend, 519 .resume = tas2764_codec_resume, 520 .controls = tas2764_snd_controls, 521 .num_controls = ARRAY_SIZE(tas2764_snd_controls), 522 .dapm_widgets = tas2764_dapm_widgets, 523 .num_dapm_widgets = ARRAY_SIZE(tas2764_dapm_widgets), 524 .dapm_routes = tas2764_audio_map, 525 .num_dapm_routes = ARRAY_SIZE(tas2764_audio_map), 526 .idle_bias_on = 1, 527 .endianness = 1, 528 .non_legacy_dai_naming = 1, 529}; 530 531static const struct reg_default tas2764_reg_defaults[] = { 532 { TAS2764_PAGE, 0x00 }, 533 { TAS2764_SW_RST, 0x00 }, 534 { TAS2764_PWR_CTRL, 0x1a }, 535 { TAS2764_DVC, 0x00 }, 536 { TAS2764_CHNL_0, 0x28 }, 537 { TAS2764_TDM_CFG0, 0x09 }, 538 { TAS2764_TDM_CFG1, 0x02 }, 539 { TAS2764_TDM_CFG2, 0x0a }, 540 { TAS2764_TDM_CFG3, 0x10 }, 541 { TAS2764_TDM_CFG5, 0x42 }, 542}; 543 544static const struct regmap_range_cfg tas2764_regmap_ranges[] = { 545 { 546 .range_min = 0, 547 .range_max = 1 * 128, 548 .selector_reg = TAS2764_PAGE, 549 .selector_mask = 0xff, 550 .selector_shift = 0, 551 .window_start = 0, 552 .window_len = 128, 553 }, 554}; 555 556static const struct regmap_config tas2764_i2c_regmap = { 557 .reg_bits = 8, 558 .val_bits = 8, 559 .reg_defaults = tas2764_reg_defaults, 560 .num_reg_defaults = ARRAY_SIZE(tas2764_reg_defaults), 561 .cache_type = REGCACHE_RBTREE, 562 .ranges = tas2764_regmap_ranges, 563 .num_ranges = ARRAY_SIZE(tas2764_regmap_ranges), 564 .max_register = 1 * 128, 565}; 566 567static int tas2764_parse_dt(struct device *dev, struct tas2764_priv *tas2764) 568{ 569 int ret = 0; 570 571 tas2764->reset_gpio = devm_gpiod_get_optional(tas2764->dev, "reset", 572 GPIOD_OUT_HIGH); 573 if (IS_ERR(tas2764->reset_gpio)) { 574 if (PTR_ERR(tas2764->reset_gpio) == -EPROBE_DEFER) { 575 tas2764->reset_gpio = NULL; 576 return -EPROBE_DEFER; 577 } 578 } 579 580 tas2764->sdz_gpio = devm_gpiod_get_optional(dev, "shutdown", GPIOD_OUT_HIGH); 581 if (IS_ERR(tas2764->sdz_gpio)) { 582 if (PTR_ERR(tas2764->sdz_gpio) == -EPROBE_DEFER) 583 return -EPROBE_DEFER; 584 585 tas2764->sdz_gpio = NULL; 586 } 587 588 ret = fwnode_property_read_u32(dev->fwnode, "ti,imon-slot-no", 589 &tas2764->i_sense_slot); 590 if (ret) 591 tas2764->i_sense_slot = 0; 592 593 ret = fwnode_property_read_u32(dev->fwnode, "ti,vmon-slot-no", 594 &tas2764->v_sense_slot); 595 if (ret) 596 tas2764->v_sense_slot = 2; 597 598 return 0; 599} 600 601static int tas2764_i2c_probe(struct i2c_client *client, 602 const struct i2c_device_id *id) 603{ 604 struct tas2764_priv *tas2764; 605 int result; 606 607 tas2764 = devm_kzalloc(&client->dev, sizeof(struct tas2764_priv), 608 GFP_KERNEL); 609 if (!tas2764) 610 return -ENOMEM; 611 612 tas2764->dev = &client->dev; 613 i2c_set_clientdata(client, tas2764); 614 dev_set_drvdata(&client->dev, tas2764); 615 616 tas2764->regmap = devm_regmap_init_i2c(client, &tas2764_i2c_regmap); 617 if (IS_ERR(tas2764->regmap)) { 618 result = PTR_ERR(tas2764->regmap); 619 dev_err(&client->dev, "Failed to allocate register map: %d\n", 620 result); 621 return result; 622 } 623 624 if (client->dev.of_node) { 625 result = tas2764_parse_dt(&client->dev, tas2764); 626 if (result) { 627 dev_err(tas2764->dev, "%s: Failed to parse devicetree\n", 628 __func__); 629 return result; 630 } 631 } 632 633 return devm_snd_soc_register_component(tas2764->dev, 634 &soc_component_driver_tas2764, 635 tas2764_dai_driver, 636 ARRAY_SIZE(tas2764_dai_driver)); 637} 638 639static const struct i2c_device_id tas2764_i2c_id[] = { 640 { "tas2764", 0}, 641 { } 642}; 643MODULE_DEVICE_TABLE(i2c, tas2764_i2c_id); 644 645#if defined(CONFIG_OF) 646static const struct of_device_id tas2764_of_match[] = { 647 { .compatible = "ti,tas2764" }, 648 {}, 649}; 650MODULE_DEVICE_TABLE(of, tas2764_of_match); 651#endif 652 653static struct i2c_driver tas2764_i2c_driver = { 654 .driver = { 655 .name = "tas2764", 656 .of_match_table = of_match_ptr(tas2764_of_match), 657 }, 658 .probe = tas2764_i2c_probe, 659 .id_table = tas2764_i2c_id, 660}; 661module_i2c_driver(tas2764_i2c_driver); 662 663MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>"); 664MODULE_DESCRIPTION("TAS2764 I2C Smart Amplifier driver"); 665MODULE_LICENSE("GPL v2"); 666