Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ASoC: add tas2780 driver

1.update Kconfig and Makefile 2.add tas2780.c and tas2780.h

Signed-off-by: Raphael-Xu <13691752556@139.com>
Link: https://lore.kernel.org/r/20220707123343.2403-1-13691752556@139.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Raphael-Xu and committed by
Mark Brown
eae9f9ce 0de876c1

+774
+8
sound/soc/codecs/Kconfig
··· 219 219 imply SND_SOC_TAS2562 220 220 imply SND_SOC_TAS2764 221 221 imply SND_SOC_TAS2770 222 + imply SND_SOC_TAS2780 222 223 imply SND_SOC_TAS5086 223 224 imply SND_SOC_TAS571X 224 225 imply SND_SOC_TAS5720 ··· 1535 1534 config SND_SOC_TAS2770 1536 1535 tristate "Texas Instruments TAS2770 speaker amplifier" 1537 1536 depends on I2C 1537 + 1538 + config SND_SOC_TAS2780 1539 + tristate "Texas Instruments TAS2780 Mono Audio amplifier" 1540 + depends on I2C 1541 + help 1542 + Enable support for Texas Instruments TAS2780 high-efficiency 1543 + digital input mono Class-D audio power amplifiers. 1538 1544 1539 1545 config SND_SOC_TAS5086 1540 1546 tristate "Texas Instruments TAS5086 speaker amplifier"
+2
sound/soc/codecs/Makefile
··· 348 348 snd-soc-tas2552-objs := tas2552.o 349 349 snd-soc-tas2562-objs := tas2562.o 350 350 snd-soc-tas2764-objs := tas2764.o 351 + snd-soc-tas2780-objs := tas2780.o 351 352 # Mux 352 353 snd-soc-simple-mux-objs := simple-mux.o 353 354 ··· 593 592 obj-$(CONFIG_SND_SOC_TAS2552) += snd-soc-tas2552.o 594 593 obj-$(CONFIG_SND_SOC_TAS2562) += snd-soc-tas2562.o 595 594 obj-$(CONFIG_SND_SOC_TAS2764) += snd-soc-tas2764.o 595 + obj-$(CONFIG_SND_SOC_TAS2780) += snd-soc-tas2780.o 596 596 obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o 597 597 obj-$(CONFIG_SND_SOC_TAS571X) += snd-soc-tas571x.o 598 598 obj-$(CONFIG_SND_SOC_TAS5720) += snd-soc-tas5720.o
+663
sound/soc/codecs/tas2780.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Driver for the Texas Instruments TAS2780 Mono 3 + // Audio amplifier 4 + // Copyright (C) 2022 Texas Instruments Inc. 5 + 6 + #include <linux/module.h> 7 + #include <linux/err.h> 8 + #include <linux/pm.h> 9 + #include <linux/i2c.h> 10 + #include <linux/gpio.h> 11 + #include <linux/gpio/consumer.h> 12 + #include <linux/regmap.h> 13 + #include <linux/of.h> 14 + #include <linux/of_gpio.h> 15 + #include <sound/soc.h> 16 + #include <sound/pcm.h> 17 + #include <sound/pcm_params.h> 18 + #include <sound/tlv.h> 19 + 20 + #include "tas2780.h" 21 + 22 + struct tas2780_priv { 23 + struct snd_soc_component *component; 24 + struct gpio_desc *reset_gpio; 25 + struct regmap *regmap; 26 + struct device *dev; 27 + int v_sense_slot; 28 + int i_sense_slot; 29 + }; 30 + 31 + static void tas2780_reset(struct tas2780_priv *tas2780) 32 + { 33 + int ret = 0; 34 + 35 + if (tas2780->reset_gpio) { 36 + gpiod_set_value_cansleep(tas2780->reset_gpio, 0); 37 + usleep_range(2000, 2050); 38 + gpiod_set_value_cansleep(tas2780->reset_gpio, 1); 39 + usleep_range(2000, 2050); 40 + } 41 + 42 + snd_soc_component_write(tas2780->component, TAS2780_SW_RST, 43 + TAS2780_RST); 44 + if (ret) 45 + dev_err(tas2780->dev, "%s:errCode:0x%x Reset error!\n", 46 + __func__, ret); 47 + } 48 + 49 + #ifdef CONFIG_PM 50 + static int tas2780_codec_suspend(struct snd_soc_component *component) 51 + { 52 + struct tas2780_priv *tas2780 = 53 + snd_soc_component_get_drvdata(component); 54 + int ret = 0; 55 + 56 + ret = snd_soc_component_update_bits(component, TAS2780_PWR_CTRL, 57 + TAS2780_PWR_CTRL_MASK, TAS2780_PWR_CTRL_SHUTDOWN); 58 + if (ret < 0) { 59 + dev_err(tas2780->dev, "%s:errCode:0x%0x:power down error\n", 60 + __func__, ret); 61 + goto err; 62 + } 63 + ret = 0; 64 + regcache_cache_only(tas2780->regmap, true); 65 + regcache_mark_dirty(tas2780->regmap); 66 + err: 67 + return ret; 68 + } 69 + 70 + static int tas2780_codec_resume(struct snd_soc_component *component) 71 + { 72 + struct tas2780_priv *tas2780 = 73 + snd_soc_component_get_drvdata(component); 74 + int ret = 0; 75 + 76 + ret = snd_soc_component_update_bits(component, TAS2780_PWR_CTRL, 77 + TAS2780_PWR_CTRL_MASK, TAS2780_PWR_CTRL_ACTIVE); 78 + 79 + if (ret < 0) { 80 + dev_err(tas2780->dev, "%s:errCode:0x%0x:power down error\n", 81 + __func__, ret); 82 + goto err; 83 + } 84 + ret = 0; 85 + regcache_cache_only(tas2780->regmap, false); 86 + ret = regcache_sync(tas2780->regmap); 87 + err: 88 + return ret; 89 + } 90 + #endif 91 + 92 + static const char * const tas2780_ASI1_src[] = { 93 + "I2C offset", "Left", "Right", "LeftRightDiv2", 94 + }; 95 + 96 + static SOC_ENUM_SINGLE_DECL( 97 + tas2780_ASI1_src_enum, TAS2780_TDM_CFG2, 4, tas2780_ASI1_src); 98 + 99 + static const struct snd_kcontrol_new tas2780_asi1_mux = 100 + SOC_DAPM_ENUM("ASI1 Source", tas2780_ASI1_src_enum); 101 + 102 + static const struct snd_kcontrol_new isense_switch = 103 + SOC_DAPM_SINGLE("Switch", TAS2780_PWR_CTRL, 104 + TAS2780_ISENSE_POWER_EN, 1, 1); 105 + static const struct snd_kcontrol_new vsense_switch = 106 + SOC_DAPM_SINGLE("Switch", TAS2780_PWR_CTRL, 107 + TAS2780_VSENSE_POWER_EN, 1, 1); 108 + 109 + static const struct snd_soc_dapm_widget tas2780_dapm_widgets[] = { 110 + SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0), 111 + SND_SOC_DAPM_MUX("ASI1 Sel", SND_SOC_NOPM, 0, 0, &tas2780_asi1_mux), 112 + SND_SOC_DAPM_SWITCH("ISENSE", TAS2780_PWR_CTRL, 113 + TAS2780_ISENSE_POWER_EN, 1, &isense_switch), 114 + SND_SOC_DAPM_SWITCH("VSENSE", TAS2780_PWR_CTRL, 115 + TAS2780_VSENSE_POWER_EN, 1, &vsense_switch), 116 + SND_SOC_DAPM_OUTPUT("OUT"), 117 + SND_SOC_DAPM_SIGGEN("VMON"), 118 + SND_SOC_DAPM_SIGGEN("IMON") 119 + }; 120 + 121 + static const struct snd_soc_dapm_route tas2780_audio_map[] = { 122 + {"ASI1 Sel", "I2C offset", "ASI1"}, 123 + {"ASI1 Sel", "Left", "ASI1"}, 124 + {"ASI1 Sel", "Right", "ASI1"}, 125 + {"ASI1 Sel", "LeftRightDiv2", "ASI1"}, 126 + {"OUT", NULL, "ASI1 Sel"}, 127 + {"ISENSE", "Switch", "IMON"}, 128 + {"VSENSE", "Switch", "VMON"}, 129 + }; 130 + 131 + static int tas2780_mute(struct snd_soc_dai *dai, int mute, int direction) 132 + { 133 + struct snd_soc_component *component = dai->component; 134 + struct tas2780_priv *tas2780 = 135 + snd_soc_component_get_drvdata(component); 136 + int ret = 0; 137 + 138 + ret = snd_soc_component_update_bits(component, TAS2780_PWR_CTRL, 139 + TAS2780_PWR_CTRL_MASK, 140 + mute ? TAS2780_PWR_CTRL_MUTE : 0); 141 + if (ret < 0) { 142 + dev_err(tas2780->dev, "%s: Failed to set powercontrol\n", 143 + __func__); 144 + goto err; 145 + } 146 + ret = 0; 147 + err: 148 + return ret; 149 + } 150 + 151 + static int tas2780_set_bitwidth(struct tas2780_priv *tas2780, int bitwidth) 152 + { 153 + struct snd_soc_component *component = tas2780->component; 154 + int sense_en; 155 + int val; 156 + int ret; 157 + int slot_size; 158 + 159 + switch (bitwidth) { 160 + case SNDRV_PCM_FORMAT_S16_LE: 161 + ret = snd_soc_component_update_bits(component, 162 + TAS2780_TDM_CFG2, 163 + TAS2780_TDM_CFG2_RXW_MASK, 164 + TAS2780_TDM_CFG2_RXW_16BITS); 165 + slot_size = TAS2780_TDM_CFG2_RXS_16BITS; 166 + break; 167 + case SNDRV_PCM_FORMAT_S24_LE: 168 + ret = snd_soc_component_update_bits(component, 169 + TAS2780_TDM_CFG2, 170 + TAS2780_TDM_CFG2_RXW_MASK, 171 + TAS2780_TDM_CFG2_RXW_24BITS); 172 + slot_size = TAS2780_TDM_CFG2_RXS_24BITS; 173 + break; 174 + case SNDRV_PCM_FORMAT_S32_LE: 175 + ret = snd_soc_component_update_bits(component, 176 + TAS2780_TDM_CFG2, 177 + TAS2780_TDM_CFG2_RXW_MASK, 178 + TAS2780_TDM_CFG2_RXW_32BITS); 179 + slot_size = TAS2780_TDM_CFG2_RXS_32BITS; 180 + break; 181 + 182 + default: 183 + ret = -EINVAL; 184 + } 185 + 186 + if (ret < 0) { 187 + dev_err(tas2780->dev, "%s:errCode:0x%x set bitwidth error\n", 188 + __func__, ret); 189 + goto err; 190 + } 191 + 192 + ret = snd_soc_component_update_bits(component, TAS2780_TDM_CFG2, 193 + TAS2780_TDM_CFG2_RXS_MASK, slot_size); 194 + if (ret < 0) { 195 + dev_err(tas2780->dev, 196 + "%s:errCode:0x%x set RX slot size error\n", 197 + __func__, ret); 198 + goto err; 199 + } 200 + 201 + val = snd_soc_component_read(tas2780->component, TAS2780_PWR_CTRL); 202 + if (val < 0) { 203 + dev_err(tas2780->dev, "%s:errCode:0x%x read PWR_CTRL error\n", 204 + __func__, val); 205 + ret = val; 206 + goto err; 207 + } 208 + 209 + if (val & (1 << TAS2780_VSENSE_POWER_EN)) 210 + sense_en = 0; 211 + else 212 + sense_en = TAS2780_TDM_CFG5_VSNS_ENABLE; 213 + 214 + ret = snd_soc_component_update_bits(tas2780->component, 215 + TAS2780_TDM_CFG5, TAS2780_TDM_CFG5_VSNS_ENABLE, sense_en); 216 + if (ret < 0) { 217 + dev_err(tas2780->dev, "%s:errCode:0x%x enable vSNS error\n", 218 + __func__, ret); 219 + goto err; 220 + } 221 + 222 + if (val & (1 << TAS2780_ISENSE_POWER_EN)) 223 + sense_en = 0; 224 + else 225 + sense_en = TAS2780_TDM_CFG6_ISNS_ENABLE; 226 + 227 + ret = snd_soc_component_update_bits(tas2780->component, 228 + TAS2780_TDM_CFG6, TAS2780_TDM_CFG6_ISNS_ENABLE, sense_en); 229 + if (ret < 0) { 230 + dev_err(tas2780->dev, "%s:errCode:0x%x enable iSNS error\n", 231 + __func__, ret); 232 + goto err; 233 + } 234 + ret = 0; 235 + err: 236 + return ret; 237 + } 238 + 239 + static int tas2780_set_samplerate( 240 + struct tas2780_priv *tas2780, int samplerate) 241 + { 242 + struct snd_soc_component *component = tas2780->component; 243 + int ramp_rate_val; 244 + int ret; 245 + 246 + switch (samplerate) { 247 + case 48000: 248 + ramp_rate_val = TAS2780_TDM_CFG0_SMP_48KHZ | 249 + TAS2780_TDM_CFG0_44_1_48KHZ; 250 + break; 251 + case 44100: 252 + ramp_rate_val = TAS2780_TDM_CFG0_SMP_44_1KHZ | 253 + TAS2780_TDM_CFG0_44_1_48KHZ; 254 + break; 255 + case 96000: 256 + ramp_rate_val = TAS2780_TDM_CFG0_SMP_48KHZ | 257 + TAS2780_TDM_CFG0_88_2_96KHZ; 258 + break; 259 + case 88200: 260 + ramp_rate_val = TAS2780_TDM_CFG0_SMP_44_1KHZ | 261 + TAS2780_TDM_CFG0_88_2_96KHZ; 262 + break; 263 + default: 264 + return -EINVAL; 265 + } 266 + ret = snd_soc_component_update_bits(component, TAS2780_TDM_CFG0, 267 + TAS2780_TDM_CFG0_SMP_MASK | TAS2780_TDM_CFG0_MASK, 268 + ramp_rate_val); 269 + if (ret < 0) { 270 + dev_err(tas2780->dev, 271 + "%s:errCode:0x%x Failed to set ramp_rate_val\n", 272 + __func__, ret); 273 + goto err; 274 + } 275 + ret = 0; 276 + err: 277 + return ret; 278 + } 279 + 280 + static int tas2780_hw_params(struct snd_pcm_substream *substream, 281 + struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) 282 + { 283 + struct snd_soc_component *component = dai->component; 284 + struct tas2780_priv *tas2780 = 285 + snd_soc_component_get_drvdata(component); 286 + int ret; 287 + 288 + ret = tas2780_set_bitwidth(tas2780, params_format(params)); 289 + if (ret < 0) 290 + return ret; 291 + 292 + return tas2780_set_samplerate(tas2780, params_rate(params)); 293 + } 294 + 295 + static int tas2780_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 296 + { 297 + struct snd_soc_component *component = dai->component; 298 + struct tas2780_priv *tas2780 = 299 + snd_soc_component_get_drvdata(component); 300 + u8 tdm_rx_start_slot = 0, asi_cfg_1 = 0; 301 + int iface; 302 + int ret = 0; 303 + 304 + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 305 + case SND_SOC_DAIFMT_NB_NF: 306 + asi_cfg_1 = TAS2780_TDM_CFG1_RX_RISING; 307 + break; 308 + case SND_SOC_DAIFMT_IB_NF: 309 + asi_cfg_1 = TAS2780_TDM_CFG1_RX_FALLING; 310 + break; 311 + default: 312 + dev_err(tas2780->dev, "ASI format Inverse is not found\n"); 313 + return -EINVAL; 314 + } 315 + 316 + ret = snd_soc_component_update_bits(component, TAS2780_TDM_CFG1, 317 + TAS2780_TDM_CFG1_RX_MASK, asi_cfg_1); 318 + if (ret < 0) { 319 + dev_err(tas2780->dev, 320 + "%s:errCode:0x%x Failed to set asi_cfg_1\n", 321 + __func__, ret); 322 + goto err; 323 + } 324 + 325 + if (((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S) 326 + || ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) 327 + == SND_SOC_DAIFMT_DSP_A)){ 328 + iface = TAS2780_TDM_CFG2_SCFG_I2S; 329 + tdm_rx_start_slot = 1; 330 + } else { 331 + if (((fmt & SND_SOC_DAIFMT_FORMAT_MASK) 332 + == SND_SOC_DAIFMT_DSP_B) 333 + || ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) 334 + == SND_SOC_DAIFMT_LEFT_J)) { 335 + iface = TAS2780_TDM_CFG2_SCFG_LEFT_J; 336 + tdm_rx_start_slot = 0; 337 + } else { 338 + dev_err(tas2780->dev, 339 + "%s:DAI Format is not found, fmt=0x%x\n", 340 + __func__, fmt); 341 + ret = -EINVAL; 342 + goto err; 343 + } 344 + } 345 + ret = snd_soc_component_update_bits(component, TAS2780_TDM_CFG1, 346 + TAS2780_TDM_CFG1_MASK, 347 + (tdm_rx_start_slot << TAS2780_TDM_CFG1_51_SHIFT)); 348 + if (ret < 0) { 349 + dev_err(tas2780->dev, 350 + "%s:errCode:0x%x Failed to set tdm_rx_start_slot\n", 351 + __func__, ret); 352 + goto err; 353 + } 354 + 355 + ret = snd_soc_component_update_bits(component, TAS2780_TDM_CFG2, 356 + TAS2780_TDM_CFG2_SCFG_MASK, iface); 357 + if (ret < 0) { 358 + dev_err(tas2780->dev, "%s:errCode:0x%x Failed to set iface\n", 359 + __func__, ret); 360 + goto err; 361 + } 362 + ret = 0; 363 + err: 364 + return ret; 365 + } 366 + 367 + static int tas2780_set_dai_tdm_slot(struct snd_soc_dai *dai, 368 + unsigned int tx_mask, 369 + unsigned int rx_mask, 370 + int slots, int slot_width) 371 + { 372 + struct snd_soc_component *component = dai->component; 373 + struct tas2780_priv *tas2780 = 374 + snd_soc_component_get_drvdata(component); 375 + int left_slot, right_slot; 376 + int slots_cfg; 377 + int slot_size; 378 + int ret = 0; 379 + 380 + if (tx_mask == 0 || rx_mask != 0) 381 + return -EINVAL; 382 + 383 + if (slots == 1) { 384 + if (tx_mask != 1) 385 + return -EINVAL; 386 + left_slot = 0; 387 + right_slot = 0; 388 + } else { 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 + 399 + if (tx_mask != 0 || left_slot >= slots || right_slot >= slots) 400 + return -EINVAL; 401 + 402 + slots_cfg = (right_slot << TAS2780_TDM_CFG3_RXS_SHIFT) | left_slot; 403 + ret = snd_soc_component_write(component, TAS2780_TDM_CFG3, slots_cfg); 404 + if (ret) { 405 + dev_err(tas2780->dev, 406 + "%s:errCode:0x%x Failed to set slots_cfg\n", 407 + __func__, ret); 408 + goto err; 409 + } 410 + 411 + switch (slot_width) { 412 + case 16: 413 + slot_size = TAS2780_TDM_CFG2_RXS_16BITS; 414 + break; 415 + case 24: 416 + slot_size = TAS2780_TDM_CFG2_RXS_24BITS; 417 + break; 418 + case 32: 419 + slot_size = TAS2780_TDM_CFG2_RXS_32BITS; 420 + break; 421 + default: 422 + ret = -EINVAL; 423 + goto err; 424 + } 425 + 426 + ret = snd_soc_component_update_bits(component, TAS2780_TDM_CFG2, 427 + TAS2780_TDM_CFG2_RXS_MASK, slot_size); 428 + if (ret < 0) { 429 + dev_err(tas2780->dev, 430 + "%s:errCode:0x%x Failed to set slot_size\n", 431 + __func__, ret); 432 + goto err; 433 + } 434 + 435 + ret = snd_soc_component_update_bits(component, TAS2780_TDM_CFG5, 436 + TAS2780_TDM_CFG5_50_MASK, tas2780->v_sense_slot); 437 + if (ret < 0) { 438 + dev_err(tas2780->dev, 439 + "%s:errCode:0x%x Failed to set v_sense_slot\n", 440 + __func__, ret); 441 + goto err; 442 + } 443 + 444 + ret = snd_soc_component_update_bits(component, TAS2780_TDM_CFG6, 445 + TAS2780_TDM_CFG6_50_MASK, tas2780->i_sense_slot); 446 + if (ret < 0) { 447 + dev_err(tas2780->dev, 448 + "%s:errCode:0x%x Failed to set i_sense_slot\n", 449 + __func__, ret); 450 + goto err; 451 + } 452 + ret = 0; 453 + err: 454 + return ret; 455 + } 456 + 457 + static const struct snd_soc_dai_ops tas2780_dai_ops = { 458 + .mute_stream = tas2780_mute, 459 + .hw_params = tas2780_hw_params, 460 + .set_fmt = tas2780_set_fmt, 461 + .set_tdm_slot = tas2780_set_dai_tdm_slot, 462 + .no_capture_mute = 1, 463 + }; 464 + 465 + #define TAS2780_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ 466 + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) 467 + 468 + #define TAS2780_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\ 469 + SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_88200) 470 + 471 + static struct snd_soc_dai_driver tas2780_dai_driver[] = { 472 + { 473 + .name = "tas2780 ASI1", 474 + .id = 0, 475 + .playback = { 476 + .stream_name = "ASI1 Playback", 477 + .channels_min = 2, 478 + .channels_max = 2, 479 + .rates = TAS2780_RATES, 480 + .formats = TAS2780_FORMATS, 481 + }, 482 + .capture = { 483 + .stream_name = "ASI1 Capture", 484 + .channels_min = 1, 485 + .channels_max = 2, 486 + .rates = TAS2780_RATES, 487 + .formats = TAS2780_FORMATS, 488 + }, 489 + .ops = &tas2780_dai_ops, 490 + .symmetric_rate = 1, 491 + }, 492 + }; 493 + 494 + static int tas2780_codec_probe(struct snd_soc_component *component) 495 + { 496 + struct tas2780_priv *tas2780 = 497 + snd_soc_component_get_drvdata(component); 498 + int ret = 0; 499 + 500 + tas2780->component = component; 501 + 502 + tas2780_reset(tas2780); 503 + ret = snd_soc_component_update_bits(component, 504 + TAS2780_IC_CFG, TAS2780_IC_CFG_MASK, 505 + TAS2780_IC_CFG_ENABLE); 506 + if (ret < 0) 507 + dev_err(tas2780->dev, "%s:errCode:0x%0x\n", 508 + __func__, ret); 509 + 510 + return ret; 511 + } 512 + 513 + static DECLARE_TLV_DB_SCALE(tas2780_digital_tlv, 1100, 50, 0); 514 + static DECLARE_TLV_DB_SCALE(tas2780_playback_volume, -10000, 50, 0); 515 + 516 + static const struct snd_kcontrol_new tas2780_snd_controls[] = { 517 + SOC_SINGLE_TLV("Speaker Volume", TAS2780_DVC, 0, 518 + TAS2780_DVC_MAX, 1, tas2780_playback_volume), 519 + SOC_SINGLE_TLV("Amp Gain Volume", TAS2780_CHNL_0, 0, 0x14, 0, 520 + tas2780_digital_tlv), 521 + }; 522 + 523 + static const struct snd_soc_component_driver soc_component_driver_tas2780 = { 524 + .probe = tas2780_codec_probe, 525 + #ifdef CONFIG_PM 526 + .suspend = tas2780_codec_suspend, 527 + .resume = tas2780_codec_resume, 528 + #endif 529 + .controls = tas2780_snd_controls, 530 + .num_controls = ARRAY_SIZE(tas2780_snd_controls), 531 + .dapm_widgets = tas2780_dapm_widgets, 532 + .num_dapm_widgets = ARRAY_SIZE(tas2780_dapm_widgets), 533 + .dapm_routes = tas2780_audio_map, 534 + .num_dapm_routes = ARRAY_SIZE(tas2780_audio_map), 535 + .idle_bias_on = 1, 536 + .endianness = 1, 537 + }; 538 + 539 + static const struct reg_default tas2780_reg_defaults[] = { 540 + { TAS2780_PAGE, 0x00 }, 541 + { TAS2780_SW_RST, 0x00 }, 542 + { TAS2780_PWR_CTRL, 0x1a }, 543 + { TAS2780_DVC, 0x00 }, 544 + { TAS2780_CHNL_0, 0x00 }, 545 + { TAS2780_TDM_CFG0, 0x09 }, 546 + { TAS2780_TDM_CFG1, 0x02 }, 547 + { TAS2780_TDM_CFG2, 0x0a }, 548 + { TAS2780_TDM_CFG3, 0x10 }, 549 + { TAS2780_TDM_CFG5, 0x42 }, 550 + }; 551 + 552 + static const struct regmap_range_cfg tas2780_regmap_ranges[] = { 553 + { 554 + .range_min = 0, 555 + .range_max = 1 * 128, 556 + .selector_reg = TAS2780_PAGE, 557 + .selector_mask = 0xff, 558 + .selector_shift = 0, 559 + .window_start = 0, 560 + .window_len = 128, 561 + }, 562 + }; 563 + 564 + static const struct regmap_config tas2780_i2c_regmap = { 565 + .reg_bits = 8, 566 + .val_bits = 8, 567 + .reg_defaults = tas2780_reg_defaults, 568 + .num_reg_defaults = ARRAY_SIZE(tas2780_reg_defaults), 569 + .cache_type = REGCACHE_RBTREE, 570 + .ranges = tas2780_regmap_ranges, 571 + .num_ranges = ARRAY_SIZE(tas2780_regmap_ranges), 572 + .max_register = 1 * 128, 573 + }; 574 + 575 + static int tas2780_parse_dt(struct device *dev, struct tas2780_priv *tas2780) 576 + { 577 + int ret = 0; 578 + 579 + tas2780->reset_gpio = devm_gpiod_get_optional(tas2780->dev, "reset", 580 + GPIOD_OUT_HIGH); 581 + if (IS_ERR(tas2780->reset_gpio)) { 582 + if (PTR_ERR(tas2780->reset_gpio) == -EPROBE_DEFER) { 583 + tas2780->reset_gpio = NULL; 584 + return -EPROBE_DEFER; 585 + } 586 + } 587 + 588 + ret = fwnode_property_read_u32(dev->fwnode, "ti,imon-slot-no", 589 + &tas2780->i_sense_slot); 590 + if (ret) 591 + tas2780->i_sense_slot = 0; 592 + 593 + ret = fwnode_property_read_u32(dev->fwnode, "ti,vmon-slot-no", 594 + &tas2780->v_sense_slot); 595 + if (ret) 596 + tas2780->v_sense_slot = 2; 597 + 598 + return 0; 599 + } 600 + 601 + static int tas2780_i2c_probe(struct i2c_client *client, 602 + const struct i2c_device_id *id) 603 + { 604 + struct tas2780_priv *tas2780; 605 + int result; 606 + 607 + tas2780 = devm_kzalloc(&client->dev, sizeof(struct tas2780_priv), 608 + GFP_KERNEL); 609 + if (!tas2780) 610 + return -ENOMEM; 611 + tas2780->dev = &client->dev; 612 + i2c_set_clientdata(client, tas2780); 613 + dev_set_drvdata(&client->dev, tas2780); 614 + 615 + tas2780->regmap = devm_regmap_init_i2c(client, &tas2780_i2c_regmap); 616 + if (IS_ERR(tas2780->regmap)) { 617 + result = PTR_ERR(tas2780->regmap); 618 + dev_err(&client->dev, "Failed to allocate register map: %d\n", 619 + result); 620 + return result; 621 + } 622 + 623 + if (client->dev.of_node) { 624 + result = tas2780_parse_dt(&client->dev, tas2780); 625 + if (result) { 626 + dev_err(tas2780->dev, 627 + "%s: Failed to parse devicetree\n", __func__); 628 + return result; 629 + } 630 + } 631 + 632 + return devm_snd_soc_register_component(tas2780->dev, 633 + &soc_component_driver_tas2780, tas2780_dai_driver, 634 + ARRAY_SIZE(tas2780_dai_driver)); 635 + } 636 + 637 + static const struct i2c_device_id tas2780_i2c_id[] = { 638 + { "tas2780", 0}, 639 + { } 640 + }; 641 + MODULE_DEVICE_TABLE(i2c, tas2780_i2c_id); 642 + 643 + #if defined(CONFIG_OF) 644 + static const struct of_device_id tas2780_of_match[] = { 645 + { .compatible = "ti,tas2780" }, 646 + {}, 647 + }; 648 + MODULE_DEVICE_TABLE(of, tas2780_of_match); 649 + #endif 650 + 651 + static struct i2c_driver tas2780_i2c_driver = { 652 + .driver = { 653 + .name = "tas2780", 654 + .of_match_table = of_match_ptr(tas2780_of_match), 655 + }, 656 + .probe = tas2780_i2c_probe, 657 + .id_table = tas2780_i2c_id, 658 + }; 659 + module_i2c_driver(tas2780_i2c_driver); 660 + 661 + MODULE_AUTHOR("Raphael Xu <raphael-xu@ti.com>"); 662 + MODULE_DESCRIPTION("TAS2780 I2C Smart Amplifier driver"); 663 + MODULE_LICENSE("GPL");
+101
sound/soc/codecs/tas2780.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * TAS2780.h - ALSA SoC Texas Instruments TAS2780 Mono Audio Amplifier 4 + * 5 + * Copyright (C) 2020-2022 Texas Instruments Incorporated - https://www.ti.com 6 + * 7 + * Author: Raphael Xu <raphael-xu@ti.com> 8 + */ 9 + 10 + #ifndef __TAS2780_H__ 11 + #define __TAS2780_H__ 12 + 13 + /* Book Control Register */ 14 + #define TAS2780_BOOKCTL_PAGE 0 15 + #define TAS2780_BOOKCTL_REG 127 16 + #define TAS2780_REG(page, reg) ((page * 128) + reg) 17 + 18 + /* Page */ 19 + #define TAS2780_PAGE TAS2780_REG(0X0, 0x00) 20 + #define TAS2780_PAGE_PAGE_MASK 255 21 + 22 + /* Software Reset */ 23 + #define TAS2780_SW_RST TAS2780_REG(0X0, 0x01) 24 + #define TAS2780_RST BIT(0) 25 + 26 + /* Power Control */ 27 + #define TAS2780_PWR_CTRL TAS2780_REG(0X0, 0x02) 28 + #define TAS2780_PWR_CTRL_MASK GENMASK(1, 0) 29 + #define TAS2780_PWR_CTRL_ACTIVE 0x0 30 + #define TAS2780_PWR_CTRL_MUTE BIT(0) 31 + #define TAS2780_PWR_CTRL_SHUTDOWN BIT(1) 32 + 33 + #define TAS2780_VSENSE_POWER_EN 3 34 + #define TAS2780_ISENSE_POWER_EN 4 35 + 36 + /* Digital Volume Control */ 37 + #define TAS2780_DVC TAS2780_REG(0X0, 0x1a) 38 + #define TAS2780_DVC_MAX 0xc9 39 + 40 + #define TAS2780_CHNL_0 TAS2780_REG(0X0, 0x03) 41 + 42 + /* TDM Configuration Reg0 */ 43 + #define TAS2780_TDM_CFG0 TAS2780_REG(0X0, 0x08) 44 + #define TAS2780_TDM_CFG0_SMP_MASK BIT(5) 45 + #define TAS2780_TDM_CFG0_SMP_48KHZ 0x0 46 + #define TAS2780_TDM_CFG0_SMP_44_1KHZ BIT(5) 47 + #define TAS2780_TDM_CFG0_MASK GENMASK(3, 1) 48 + #define TAS2780_TDM_CFG0_44_1_48KHZ BIT(3) 49 + #define TAS2780_TDM_CFG0_88_2_96KHZ (BIT(3) | BIT(1)) 50 + 51 + /* TDM Configuration Reg1 */ 52 + #define TAS2780_TDM_CFG1 TAS2780_REG(0X0, 0x09) 53 + #define TAS2780_TDM_CFG1_MASK GENMASK(5, 1) 54 + #define TAS2780_TDM_CFG1_51_SHIFT 1 55 + #define TAS2780_TDM_CFG1_RX_MASK BIT(0) 56 + #define TAS2780_TDM_CFG1_RX_RISING 0x0 57 + #define TAS2780_TDM_CFG1_RX_FALLING BIT(0) 58 + 59 + /* TDM Configuration Reg2 */ 60 + #define TAS2780_TDM_CFG2 TAS2780_REG(0X0, 0x0a) 61 + #define TAS2780_TDM_CFG2_RXW_MASK GENMASK(3, 2) 62 + #define TAS2780_TDM_CFG2_RXW_16BITS 0x0 63 + #define TAS2780_TDM_CFG2_RXW_24BITS BIT(3) 64 + #define TAS2780_TDM_CFG2_RXW_32BITS (BIT(3) | BIT(2)) 65 + #define TAS2780_TDM_CFG2_RXS_MASK GENMASK(1, 0) 66 + #define TAS2780_TDM_CFG2_RXS_16BITS 0x0 67 + #define TAS2780_TDM_CFG2_RXS_24BITS BIT(0) 68 + #define TAS2780_TDM_CFG2_RXS_32BITS BIT(1) 69 + #define TAS2780_TDM_CFG2_SCFG_MASK GENMASK(5, 4) 70 + #define TAS2780_TDM_CFG2_SCFG_I2S 0x0 71 + #define TAS2780_TDM_CFG2_SCFG_LEFT_J BIT(4) 72 + #define TAS2780_TDM_CFG2_SCFG_RIGHT_J BIT(5) 73 + 74 + /* TDM Configuration Reg3 */ 75 + #define TAS2780_TDM_CFG3 TAS2780_REG(0X0, 0x0c) 76 + #define TAS2780_TDM_CFG3_RXS_MASK GENMASK(7, 4) 77 + #define TAS2780_TDM_CFG3_RXS_SHIFT 0x4 78 + #define TAS2780_TDM_CFG3_MASK GENMASK(3, 0) 79 + 80 + /* TDM Configuration Reg4 */ 81 + #define TAS2780_TDM_CFG4 TAS2780_REG(0X0, 0x0d) 82 + #define TAS2780_TDM_CFG4_TX_OFFSET_MASK GENMASK(3, 1) 83 + 84 + /* TDM Configuration Reg5 */ 85 + #define TAS2780_TDM_CFG5 TAS2780_REG(0X0, 0x0e) 86 + #define TAS2780_TDM_CFG5_VSNS_MASK BIT(6) 87 + #define TAS2780_TDM_CFG5_VSNS_ENABLE BIT(6) 88 + #define TAS2780_TDM_CFG5_50_MASK GENMASK(5, 0) 89 + 90 + /* TDM Configuration Reg6 */ 91 + #define TAS2780_TDM_CFG6 TAS2780_REG(0X0, 0x0f) 92 + #define TAS2780_TDM_CFG6_ISNS_MASK BIT(6) 93 + #define TAS2780_TDM_CFG6_ISNS_ENABLE BIT(6) 94 + #define TAS2780_TDM_CFG6_50_MASK GENMASK(5, 0) 95 + 96 + /* IC CFG */ 97 + #define TAS2780_IC_CFG TAS2780_REG(0X0, 0x5c) 98 + #define TAS2780_IC_CFG_MASK GENMASK(7, 6) 99 + #define TAS2780_IC_CFG_ENABLE (BIT(7) | BIT(6)) 100 + 101 + #endif /* __TAS2780_H__ */