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