linux/sound/soc/codecs/tas2770.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2//
   3// ALSA SoC Texas Instruments TAS2770 20-W Digital Input Mono Class-D
   4// Audio Amplifier with Speaker I/V Sense
   5//
   6// Copyright (C) 2016-2017 Texas Instruments Incorporated - https://www.ti.com/
   7//      Author: Tracy Yi <tracy-yi@ti.com>
   8//      Frank Shi <shifu0704@thundersoft.com>
   9
  10#include <linux/module.h>
  11#include <linux/moduleparam.h>
  12#include <linux/err.h>
  13#include <linux/init.h>
  14#include <linux/delay.h>
  15#include <linux/pm.h>
  16#include <linux/i2c.h>
  17#include <linux/gpio.h>
  18#include <linux/gpio/consumer.h>
  19#include <linux/regulator/consumer.h>
  20#include <linux/firmware.h>
  21#include <linux/regmap.h>
  22#include <linux/of.h>
  23#include <linux/of_gpio.h>
  24#include <linux/slab.h>
  25#include <sound/soc.h>
  26#include <sound/pcm.h>
  27#include <sound/pcm_params.h>
  28#include <sound/initval.h>
  29#include <sound/tlv.h>
  30
  31#include "tas2770.h"
  32
  33#define TAS2770_MDELAY 0xFFFFFFFE
  34
  35static void tas2770_reset(struct tas2770_priv *tas2770)
  36{
  37        if (tas2770->reset_gpio) {
  38                gpiod_set_value_cansleep(tas2770->reset_gpio, 0);
  39                msleep(20);
  40                gpiod_set_value_cansleep(tas2770->reset_gpio, 1);
  41        }
  42
  43        snd_soc_component_write(tas2770->component, TAS2770_SW_RST,
  44                TAS2770_RST);
  45}
  46
  47static int tas2770_set_bias_level(struct snd_soc_component *component,
  48                                 enum snd_soc_bias_level level)
  49{
  50        struct tas2770_priv *tas2770 =
  51                        snd_soc_component_get_drvdata(component);
  52
  53        switch (level) {
  54        case SND_SOC_BIAS_ON:
  55                snd_soc_component_update_bits(component, TAS2770_PWR_CTRL,
  56                                              TAS2770_PWR_CTRL_MASK,
  57                                              TAS2770_PWR_CTRL_ACTIVE);
  58                break;
  59        case SND_SOC_BIAS_STANDBY:
  60        case SND_SOC_BIAS_PREPARE:
  61                snd_soc_component_update_bits(component, TAS2770_PWR_CTRL,
  62                                              TAS2770_PWR_CTRL_MASK,
  63                                              TAS2770_PWR_CTRL_MUTE);
  64                break;
  65        case SND_SOC_BIAS_OFF:
  66                snd_soc_component_update_bits(component, TAS2770_PWR_CTRL,
  67                                              TAS2770_PWR_CTRL_MASK,
  68                                              TAS2770_PWR_CTRL_SHUTDOWN);
  69                break;
  70
  71        default:
  72                dev_err(tas2770->dev, "wrong power level setting %d\n", level);
  73                return -EINVAL;
  74        }
  75
  76        return 0;
  77}
  78
  79#ifdef CONFIG_PM
  80static int tas2770_codec_suspend(struct snd_soc_component *component)
  81{
  82        struct tas2770_priv *tas2770 = snd_soc_component_get_drvdata(component);
  83        int ret = 0;
  84
  85        regcache_cache_only(tas2770->regmap, true);
  86        regcache_mark_dirty(tas2770->regmap);
  87
  88        if (tas2770->sdz_gpio) {
  89                gpiod_set_value_cansleep(tas2770->sdz_gpio, 0);
  90        } else {
  91                ret = snd_soc_component_update_bits(component, TAS2770_PWR_CTRL,
  92                                                    TAS2770_PWR_CTRL_MASK,
  93                                                    TAS2770_PWR_CTRL_SHUTDOWN);
  94                if (ret < 0) {
  95                        regcache_cache_only(tas2770->regmap, false);
  96                        regcache_sync(tas2770->regmap);
  97                        return ret;
  98                }
  99
 100                ret = 0;
 101        }
 102
 103        return ret;
 104}
 105
 106static int tas2770_codec_resume(struct snd_soc_component *component)
 107{
 108        struct tas2770_priv *tas2770 = snd_soc_component_get_drvdata(component);
 109        int ret = 0;
 110
 111        if (tas2770->sdz_gpio) {
 112                gpiod_set_value_cansleep(tas2770->sdz_gpio, 1);
 113        } else {
 114                ret = snd_soc_component_update_bits(component, TAS2770_PWR_CTRL,
 115                                                    TAS2770_PWR_CTRL_MASK,
 116                                                    TAS2770_PWR_CTRL_ACTIVE);
 117                if (ret < 0)
 118                        return ret;
 119        }
 120
 121        regcache_cache_only(tas2770->regmap, false);
 122
 123        return regcache_sync(tas2770->regmap);
 124}
 125#else
 126#define tas2770_codec_suspend NULL
 127#define tas2770_codec_resume NULL
 128#endif
 129
 130static const char * const tas2770_ASI1_src[] = {
 131        "I2C offset", "Left", "Right", "LeftRightDiv2",
 132};
 133
 134static SOC_ENUM_SINGLE_DECL(
 135        tas2770_ASI1_src_enum, TAS2770_TDM_CFG_REG2,
 136        4, tas2770_ASI1_src);
 137
 138static const struct snd_kcontrol_new tas2770_asi1_mux =
 139        SOC_DAPM_ENUM("ASI1 Source", tas2770_ASI1_src_enum);
 140
 141static int tas2770_dac_event(struct snd_soc_dapm_widget *w,
 142                             struct snd_kcontrol *kcontrol, int event)
 143{
 144        struct snd_soc_component *component =
 145                        snd_soc_dapm_to_component(w->dapm);
 146        struct tas2770_priv *tas2770 =
 147                        snd_soc_component_get_drvdata(component);
 148        int ret;
 149
 150        switch (event) {
 151        case SND_SOC_DAPM_POST_PMU:
 152                ret = snd_soc_component_update_bits(component, TAS2770_PWR_CTRL,
 153                                                    TAS2770_PWR_CTRL_MASK,
 154                                                    TAS2770_PWR_CTRL_MUTE);
 155                break;
 156        case SND_SOC_DAPM_PRE_PMD:
 157                ret = snd_soc_component_update_bits(component, TAS2770_PWR_CTRL,
 158                                                    TAS2770_PWR_CTRL_MASK,
 159                                                    TAS2770_PWR_CTRL_SHUTDOWN);
 160                break;
 161        default:
 162                dev_err(tas2770->dev, "Not supported evevt\n");
 163                return -EINVAL;
 164        }
 165
 166        if (ret < 0)
 167                return ret;
 168
 169        return 0;
 170}
 171
 172static const struct snd_kcontrol_new isense_switch =
 173        SOC_DAPM_SINGLE("Switch", TAS2770_PWR_CTRL, 3, 1, 1);
 174static const struct snd_kcontrol_new vsense_switch =
 175        SOC_DAPM_SINGLE("Switch", TAS2770_PWR_CTRL, 2, 1, 1);
 176
 177static const struct snd_soc_dapm_widget tas2770_dapm_widgets[] = {
 178        SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0),
 179        SND_SOC_DAPM_MUX("ASI1 Sel", SND_SOC_NOPM, 0, 0, &tas2770_asi1_mux),
 180        SND_SOC_DAPM_SWITCH("ISENSE", TAS2770_PWR_CTRL, 3, 1, &isense_switch),
 181        SND_SOC_DAPM_SWITCH("VSENSE", TAS2770_PWR_CTRL, 2, 1, &vsense_switch),
 182        SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas2770_dac_event,
 183                           SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
 184        SND_SOC_DAPM_OUTPUT("OUT"),
 185        SND_SOC_DAPM_SIGGEN("VMON"),
 186        SND_SOC_DAPM_SIGGEN("IMON")
 187};
 188
 189static const struct snd_soc_dapm_route tas2770_audio_map[] = {
 190        {"ASI1 Sel", "I2C offset", "ASI1"},
 191        {"ASI1 Sel", "Left", "ASI1"},
 192        {"ASI1 Sel", "Right", "ASI1"},
 193        {"ASI1 Sel", "LeftRightDiv2", "ASI1"},
 194        {"DAC", NULL, "ASI1 Sel"},
 195        {"OUT", NULL, "DAC"},
 196        {"ISENSE", "Switch", "IMON"},
 197        {"VSENSE", "Switch", "VMON"},
 198};
 199
 200static int tas2770_mute(struct snd_soc_dai *dai, int mute, int direction)
 201{
 202        struct snd_soc_component *component = dai->component;
 203        int ret;
 204
 205        if (mute)
 206                ret = snd_soc_component_update_bits(component, TAS2770_PWR_CTRL,
 207                                                    TAS2770_PWR_CTRL_MASK,
 208                                                    TAS2770_PWR_CTRL_MUTE);
 209        else
 210                ret = snd_soc_component_update_bits(component, TAS2770_PWR_CTRL,
 211                                                    TAS2770_PWR_CTRL_MASK,
 212                                                    TAS2770_PWR_CTRL_ACTIVE);
 213
 214        if (ret < 0)
 215                return ret;
 216
 217        return 0;
 218}
 219
 220static int tas2770_set_bitwidth(struct tas2770_priv *tas2770, int bitwidth)
 221{
 222        int ret;
 223        struct snd_soc_component *component = tas2770->component;
 224
 225        switch (bitwidth) {
 226        case SNDRV_PCM_FORMAT_S16_LE:
 227                ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG2,
 228                                                    TAS2770_TDM_CFG_REG2_RXW_MASK,
 229                                                    TAS2770_TDM_CFG_REG2_RXW_16BITS);
 230                tas2770->v_sense_slot = tas2770->i_sense_slot + 2;
 231                break;
 232        case SNDRV_PCM_FORMAT_S24_LE:
 233                ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG2,
 234                                                    TAS2770_TDM_CFG_REG2_RXW_MASK,
 235                                                    TAS2770_TDM_CFG_REG2_RXW_24BITS);
 236                tas2770->v_sense_slot = tas2770->i_sense_slot + 4;
 237                break;
 238        case SNDRV_PCM_FORMAT_S32_LE:
 239                ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG2,
 240                                                    TAS2770_TDM_CFG_REG2_RXW_MASK,
 241                                                    TAS2770_TDM_CFG_REG2_RXW_32BITS);
 242                tas2770->v_sense_slot = tas2770->i_sense_slot + 4;
 243                break;
 244
 245        default:
 246                return -EINVAL;
 247        }
 248
 249        if (ret < 0)
 250                return ret;
 251
 252        ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG5,
 253                                            TAS2770_TDM_CFG_REG5_VSNS_MASK |
 254                                            TAS2770_TDM_CFG_REG5_50_MASK,
 255                                            TAS2770_TDM_CFG_REG5_VSNS_ENABLE |
 256                tas2770->v_sense_slot);
 257        if (ret < 0)
 258                return ret;
 259
 260        ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG6,
 261                                            TAS2770_TDM_CFG_REG6_ISNS_MASK |
 262                                            TAS2770_TDM_CFG_REG6_50_MASK,
 263                                            TAS2770_TDM_CFG_REG6_ISNS_ENABLE |
 264                                            tas2770->i_sense_slot);
 265        if (ret < 0)
 266                return ret;
 267
 268        return 0;
 269}
 270
 271static int tas2770_set_samplerate(struct tas2770_priv *tas2770, int samplerate)
 272{
 273        struct snd_soc_component *component = tas2770->component;
 274        int ramp_rate_val;
 275        int ret;
 276
 277        switch (samplerate) {
 278        case 48000:
 279                ramp_rate_val = TAS2770_TDM_CFG_REG0_SMP_48KHZ |
 280                                TAS2770_TDM_CFG_REG0_31_44_1_48KHZ;
 281                break;
 282        case 44100:
 283                ramp_rate_val = TAS2770_TDM_CFG_REG0_SMP_44_1KHZ |
 284                                TAS2770_TDM_CFG_REG0_31_44_1_48KHZ;
 285                break;
 286        case 96000:
 287                ramp_rate_val = TAS2770_TDM_CFG_REG0_SMP_48KHZ |
 288                                TAS2770_TDM_CFG_REG0_31_88_2_96KHZ;
 289                break;
 290        case 88200:
 291                ramp_rate_val = TAS2770_TDM_CFG_REG0_SMP_44_1KHZ |
 292                                TAS2770_TDM_CFG_REG0_31_88_2_96KHZ;
 293                break;
 294        case 19200:
 295                ramp_rate_val = TAS2770_TDM_CFG_REG0_SMP_48KHZ |
 296                                TAS2770_TDM_CFG_REG0_31_176_4_192KHZ;
 297                break;
 298        case 17640:
 299                ramp_rate_val = TAS2770_TDM_CFG_REG0_SMP_44_1KHZ |
 300                                TAS2770_TDM_CFG_REG0_31_176_4_192KHZ;
 301                break;
 302        default:
 303                return -EINVAL;
 304        }
 305
 306        ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG0,
 307                                            TAS2770_TDM_CFG_REG0_SMP_MASK |
 308                                            TAS2770_TDM_CFG_REG0_31_MASK,
 309                                            ramp_rate_val);
 310        if (ret < 0)
 311                return ret;
 312
 313        return 0;
 314}
 315
 316static int tas2770_hw_params(struct snd_pcm_substream *substream,
 317                             struct snd_pcm_hw_params *params,
 318                             struct snd_soc_dai *dai)
 319{
 320        struct snd_soc_component *component = dai->component;
 321        struct tas2770_priv *tas2770 =
 322                        snd_soc_component_get_drvdata(component);
 323        int ret;
 324
 325        ret = tas2770_set_bitwidth(tas2770, params_format(params));
 326        if (ret)
 327                return ret;
 328
 329        return tas2770_set_samplerate(tas2770, params_rate(params));
 330}
 331
 332static int tas2770_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 333{
 334        struct snd_soc_component *component = dai->component;
 335        struct tas2770_priv *tas2770 =
 336                        snd_soc_component_get_drvdata(component);
 337        u8 tdm_rx_start_slot = 0, asi_cfg_1 = 0;
 338        int ret;
 339
 340        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
 341        case SND_SOC_DAIFMT_CBS_CFS:
 342                break;
 343        default:
 344                dev_err(tas2770->dev, "ASI format master is not found\n");
 345                return -EINVAL;
 346        }
 347
 348        switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
 349        case SND_SOC_DAIFMT_NB_NF:
 350                asi_cfg_1 |= TAS2770_TDM_CFG_REG1_RX_RSING;
 351                break;
 352        case SND_SOC_DAIFMT_IB_NF:
 353                asi_cfg_1 |= TAS2770_TDM_CFG_REG1_RX_FALING;
 354                break;
 355        default:
 356                dev_err(tas2770->dev, "ASI format Inverse is not found\n");
 357                return -EINVAL;
 358        }
 359
 360        ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG1,
 361                                            TAS2770_TDM_CFG_REG1_RX_MASK,
 362                                            asi_cfg_1);
 363        if (ret < 0)
 364                return ret;
 365
 366        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
 367        case SND_SOC_DAIFMT_I2S:
 368                tdm_rx_start_slot = 1;
 369                break;
 370        case SND_SOC_DAIFMT_DSP_A:
 371                tdm_rx_start_slot = 0;
 372                break;
 373        case SND_SOC_DAIFMT_DSP_B:
 374                tdm_rx_start_slot = 1;
 375                break;
 376        case SND_SOC_DAIFMT_LEFT_J:
 377                tdm_rx_start_slot = 0;
 378                break;
 379        default:
 380                dev_err(tas2770->dev,
 381                        "DAI Format is not found, fmt=0x%x\n", fmt);
 382                return -EINVAL;
 383        }
 384
 385        ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG1,
 386                                            TAS2770_TDM_CFG_REG1_MASK,
 387                                            (tdm_rx_start_slot << TAS2770_TDM_CFG_REG1_51_SHIFT));
 388        if (ret < 0)
 389                return ret;
 390
 391        return 0;
 392}
 393
 394static int tas2770_set_dai_tdm_slot(struct snd_soc_dai *dai,
 395                                unsigned int tx_mask,
 396                                unsigned int rx_mask,
 397                                int slots, int slot_width)
 398{
 399        struct snd_soc_component *component = dai->component;
 400        int left_slot, right_slot;
 401        int ret;
 402
 403        if (tx_mask == 0 || rx_mask != 0)
 404                return -EINVAL;
 405
 406        if (slots == 1) {
 407                if (tx_mask != 1)
 408                        return -EINVAL;
 409
 410                left_slot = 0;
 411                right_slot = 0;
 412        } else {
 413                left_slot = __ffs(tx_mask);
 414                tx_mask &= ~(1 << left_slot);
 415                if (tx_mask == 0) {
 416                        right_slot = left_slot;
 417                } else {
 418                        right_slot = __ffs(tx_mask);
 419                        tx_mask &= ~(1 << right_slot);
 420                }
 421        }
 422
 423        if (tx_mask != 0 || left_slot >= slots || right_slot >= slots)
 424                return -EINVAL;
 425
 426        ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG3,
 427                                            TAS2770_TDM_CFG_REG3_30_MASK,
 428                                            (left_slot << TAS2770_TDM_CFG_REG3_30_SHIFT));
 429        if (ret < 0)
 430                return ret;
 431        ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG3,
 432                                            TAS2770_TDM_CFG_REG3_RXS_MASK,
 433                                            (right_slot << TAS2770_TDM_CFG_REG3_RXS_SHIFT));
 434        if (ret < 0)
 435                return ret;
 436
 437        switch (slot_width) {
 438        case 16:
 439                ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG2,
 440                                                    TAS2770_TDM_CFG_REG2_RXS_MASK,
 441                                                    TAS2770_TDM_CFG_REG2_RXS_16BITS);
 442                break;
 443        case 24:
 444                ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG2,
 445                                                    TAS2770_TDM_CFG_REG2_RXS_MASK,
 446                                                    TAS2770_TDM_CFG_REG2_RXS_24BITS);
 447                break;
 448        case 32:
 449                ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG2,
 450                                                    TAS2770_TDM_CFG_REG2_RXS_MASK,
 451                                                    TAS2770_TDM_CFG_REG2_RXS_32BITS);
 452                break;
 453        case 0:
 454                /* Do not change slot width */
 455                ret = 0;
 456                break;
 457        default:
 458                ret = -EINVAL;
 459        }
 460
 461        if (ret < 0)
 462                return ret;
 463
 464        return 0;
 465}
 466
 467static struct snd_soc_dai_ops tas2770_dai_ops = {
 468        .mute_stream = tas2770_mute,
 469        .hw_params  = tas2770_hw_params,
 470        .set_fmt    = tas2770_set_fmt,
 471        .set_tdm_slot = tas2770_set_dai_tdm_slot,
 472        .no_capture_mute = 1,
 473};
 474
 475#define TAS2770_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
 476                SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 477
 478#define TAS2770_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\
 479                                           SNDRV_PCM_RATE_96000 |\
 480                                            SNDRV_PCM_RATE_192000\
 481                                          )
 482
 483static struct snd_soc_dai_driver tas2770_dai_driver[] = {
 484        {
 485                .name = "tas2770 ASI1",
 486                .id = 0,
 487                .playback = {
 488                        .stream_name    = "ASI1 Playback",
 489                        .channels_min   = 2,
 490                        .channels_max   = 2,
 491                        .rates      = TAS2770_RATES,
 492                        .formats    = TAS2770_FORMATS,
 493                },
 494                .capture = {
 495                        .stream_name    = "ASI1 Capture",
 496                        .channels_min   = 0,
 497                        .channels_max   = 2,
 498                        .rates          = TAS2770_RATES,
 499                        .formats    = TAS2770_FORMATS,
 500                },
 501                .ops = &tas2770_dai_ops,
 502                .symmetric_rate = 1,
 503        },
 504};
 505
 506static int tas2770_codec_probe(struct snd_soc_component *component)
 507{
 508        struct tas2770_priv *tas2770 =
 509                        snd_soc_component_get_drvdata(component);
 510
 511        tas2770->component = component;
 512
 513        if (tas2770->sdz_gpio)
 514                gpiod_set_value_cansleep(tas2770->sdz_gpio, 1);
 515
 516        tas2770_reset(tas2770);
 517
 518        return 0;
 519}
 520
 521static DECLARE_TLV_DB_SCALE(tas2770_digital_tlv, 1100, 50, 0);
 522static DECLARE_TLV_DB_SCALE(tas2770_playback_volume, -12750, 50, 0);
 523
 524static const struct snd_kcontrol_new tas2770_snd_controls[] = {
 525        SOC_SINGLE_TLV("Speaker Playback Volume", TAS2770_PLAY_CFG_REG2,
 526                       0, TAS2770_PLAY_CFG_REG2_VMAX, 1, tas2770_playback_volume),
 527        SOC_SINGLE_TLV("Amp Gain Volume", TAS2770_PLAY_CFG_REG0, 0, 0x14, 0,
 528                       tas2770_digital_tlv),
 529};
 530
 531static const struct snd_soc_component_driver soc_component_driver_tas2770 = {
 532        .probe                  = tas2770_codec_probe,
 533        .suspend                = tas2770_codec_suspend,
 534        .resume                 = tas2770_codec_resume,
 535        .set_bias_level = tas2770_set_bias_level,
 536        .controls               = tas2770_snd_controls,
 537        .num_controls           = ARRAY_SIZE(tas2770_snd_controls),
 538        .dapm_widgets           = tas2770_dapm_widgets,
 539        .num_dapm_widgets       = ARRAY_SIZE(tas2770_dapm_widgets),
 540        .dapm_routes            = tas2770_audio_map,
 541        .num_dapm_routes        = ARRAY_SIZE(tas2770_audio_map),
 542        .idle_bias_on           = 1,
 543        .endianness             = 1,
 544        .non_legacy_dai_naming  = 1,
 545};
 546
 547static int tas2770_register_codec(struct tas2770_priv *tas2770)
 548{
 549        return devm_snd_soc_register_component(tas2770->dev,
 550                &soc_component_driver_tas2770,
 551                tas2770_dai_driver, ARRAY_SIZE(tas2770_dai_driver));
 552}
 553
 554static const struct reg_default tas2770_reg_defaults[] = {
 555        { TAS2770_PAGE, 0x00 },
 556        { TAS2770_SW_RST, 0x00 },
 557        { TAS2770_PWR_CTRL, 0x0e },
 558        { TAS2770_PLAY_CFG_REG0, 0x10 },
 559        { TAS2770_PLAY_CFG_REG1, 0x01 },
 560        { TAS2770_PLAY_CFG_REG2, 0x00 },
 561        { TAS2770_MSC_CFG_REG0, 0x07 },
 562        { TAS2770_TDM_CFG_REG1, 0x02 },
 563        { TAS2770_TDM_CFG_REG2, 0x0a },
 564        { TAS2770_TDM_CFG_REG3, 0x10 },
 565        { TAS2770_INT_MASK_REG0, 0xfc },
 566        { TAS2770_INT_MASK_REG1, 0xb1 },
 567        { TAS2770_INT_CFG, 0x05 },
 568        { TAS2770_MISC_IRQ, 0x81 },
 569        { TAS2770_CLK_CGF, 0x0c },
 570
 571};
 572
 573static bool tas2770_volatile(struct device *dev, unsigned int reg)
 574{
 575        switch (reg) {
 576        case TAS2770_PAGE: /* regmap implementation requires this */
 577        case TAS2770_SW_RST: /* always clears after write */
 578        case TAS2770_BO_PRV_REG0:/* has a self clearing bit */
 579        case TAS2770_LVE_INT_REG0:
 580        case TAS2770_LVE_INT_REG1:
 581        case TAS2770_LAT_INT_REG0:/* Sticky interrupt flags */
 582        case TAS2770_LAT_INT_REG1:/* Sticky interrupt flags */
 583        case TAS2770_VBAT_MSB:
 584        case TAS2770_VBAT_LSB:
 585        case TAS2770_TEMP_MSB:
 586        case TAS2770_TEMP_LSB:
 587                return true;
 588        }
 589
 590        return false;
 591}
 592
 593static bool tas2770_writeable(struct device *dev, unsigned int reg)
 594{
 595        switch (reg) {
 596        case TAS2770_LVE_INT_REG0:
 597        case TAS2770_LVE_INT_REG1:
 598        case TAS2770_LAT_INT_REG0:
 599        case TAS2770_LAT_INT_REG1:
 600        case TAS2770_VBAT_MSB:
 601        case TAS2770_VBAT_LSB:
 602        case TAS2770_TEMP_MSB:
 603        case TAS2770_TEMP_LSB:
 604        case TAS2770_TDM_CLK_DETC:
 605        case TAS2770_REV_AND_GPID:
 606                return false;
 607        }
 608
 609        return true;
 610}
 611
 612static const struct regmap_range_cfg tas2770_regmap_ranges[] = {
 613        {
 614                .range_min = 0,
 615                .range_max = 1 * 128,
 616                .selector_reg = TAS2770_PAGE,
 617                .selector_mask = 0xff,
 618                .selector_shift = 0,
 619                .window_start = 0,
 620                .window_len = 128,
 621        },
 622};
 623
 624static const struct regmap_config tas2770_i2c_regmap = {
 625        .reg_bits = 8,
 626        .val_bits = 8,
 627        .writeable_reg = tas2770_writeable,
 628        .volatile_reg = tas2770_volatile,
 629        .reg_defaults = tas2770_reg_defaults,
 630        .num_reg_defaults = ARRAY_SIZE(tas2770_reg_defaults),
 631        .cache_type = REGCACHE_RBTREE,
 632        .ranges = tas2770_regmap_ranges,
 633        .num_ranges = ARRAY_SIZE(tas2770_regmap_ranges),
 634        .max_register = 1 * 128,
 635};
 636
 637static int tas2770_parse_dt(struct device *dev, struct tas2770_priv *tas2770)
 638{
 639        int rc = 0;
 640
 641        rc = fwnode_property_read_u32(dev->fwnode, "ti,imon-slot-no",
 642                                      &tas2770->i_sense_slot);
 643        if (rc) {
 644                dev_info(tas2770->dev, "Property %s is missing setting default slot\n",
 645                         "ti,imon-slot-no");
 646
 647                tas2770->i_sense_slot = 0;
 648        }
 649
 650        rc = fwnode_property_read_u32(dev->fwnode, "ti,vmon-slot-no",
 651                                      &tas2770->v_sense_slot);
 652        if (rc) {
 653                dev_info(tas2770->dev, "Property %s is missing setting default slot\n",
 654                         "ti,vmon-slot-no");
 655
 656                tas2770->v_sense_slot = 2;
 657        }
 658
 659        tas2770->sdz_gpio = devm_gpiod_get_optional(dev, "shutdown", GPIOD_OUT_HIGH);
 660        if (IS_ERR(tas2770->sdz_gpio)) {
 661                if (PTR_ERR(tas2770->sdz_gpio) == -EPROBE_DEFER)
 662                        return -EPROBE_DEFER;
 663
 664                tas2770->sdz_gpio = NULL;
 665        }
 666
 667        return 0;
 668}
 669
 670static int tas2770_i2c_probe(struct i2c_client *client,
 671                        const struct i2c_device_id *id)
 672{
 673        struct tas2770_priv *tas2770;
 674        int result;
 675
 676        tas2770 = devm_kzalloc(&client->dev, sizeof(struct tas2770_priv),
 677                               GFP_KERNEL);
 678        if (!tas2770)
 679                return -ENOMEM;
 680
 681        tas2770->dev = &client->dev;
 682        i2c_set_clientdata(client, tas2770);
 683        dev_set_drvdata(&client->dev, tas2770);
 684
 685        tas2770->regmap = devm_regmap_init_i2c(client, &tas2770_i2c_regmap);
 686        if (IS_ERR(tas2770->regmap)) {
 687                result = PTR_ERR(tas2770->regmap);
 688                dev_err(&client->dev, "Failed to allocate register map: %d\n",
 689                        result);
 690                return result;
 691        }
 692
 693        if (client->dev.of_node) {
 694                result = tas2770_parse_dt(&client->dev, tas2770);
 695                if (result) {
 696                        dev_err(tas2770->dev, "%s: Failed to parse devicetree\n",
 697                                __func__);
 698                        return result;
 699                }
 700        }
 701
 702        tas2770->reset_gpio = devm_gpiod_get_optional(tas2770->dev, "reset",
 703                                                      GPIOD_OUT_HIGH);
 704        if (IS_ERR(tas2770->reset_gpio)) {
 705                if (PTR_ERR(tas2770->reset_gpio) == -EPROBE_DEFER) {
 706                        tas2770->reset_gpio = NULL;
 707                        return -EPROBE_DEFER;
 708                }
 709        }
 710
 711        result = tas2770_register_codec(tas2770);
 712        if (result)
 713                dev_err(tas2770->dev, "Register codec failed.\n");
 714
 715        return result;
 716}
 717
 718static const struct i2c_device_id tas2770_i2c_id[] = {
 719        { "tas2770", 0},
 720        { }
 721};
 722MODULE_DEVICE_TABLE(i2c, tas2770_i2c_id);
 723
 724#if defined(CONFIG_OF)
 725static const struct of_device_id tas2770_of_match[] = {
 726        { .compatible = "ti,tas2770" },
 727        {},
 728};
 729MODULE_DEVICE_TABLE(of, tas2770_of_match);
 730#endif
 731
 732static struct i2c_driver tas2770_i2c_driver = {
 733        .driver = {
 734                .name   = "tas2770",
 735                .of_match_table = of_match_ptr(tas2770_of_match),
 736        },
 737        .probe      = tas2770_i2c_probe,
 738        .id_table   = tas2770_i2c_id,
 739};
 740module_i2c_driver(tas2770_i2c_driver);
 741
 742MODULE_AUTHOR("Shi Fu <shifu0704@thundersoft.com>");
 743MODULE_DESCRIPTION("TAS2770 I2C Smart Amplifier driver");
 744MODULE_LICENSE("GPL v2");
 745