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