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