linux/sound/soc/codecs/tas2552.c
<<
>>
Prefs
   1/*
   2 * tas2552.c - ALSA SoC Texas Instruments TAS2552 Mono Audio Amplifier
   3 *
   4 * Copyright (C) 2014 Texas Instruments Incorporated -  http://www.ti.com
   5 *
   6 * Author: Dan Murphy <dmurphy@ti.com>
   7 *
   8 * This program is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU General Public License
  10 * version 2 as published by the Free Software Foundation.
  11 *
  12 * This program is distributed in the hope that it will be useful, but
  13 * WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15 * General Public License for more details.
  16 */
  17
  18#include <linux/module.h>
  19#include <linux/errno.h>
  20#include <linux/device.h>
  21#include <linux/i2c.h>
  22#include <linux/gpio.h>
  23#include <linux/of_gpio.h>
  24#include <linux/pm_runtime.h>
  25#include <linux/regmap.h>
  26#include <linux/slab.h>
  27
  28#include <linux/gpio/consumer.h>
  29#include <linux/regulator/consumer.h>
  30
  31#include <sound/pcm.h>
  32#include <sound/pcm_params.h>
  33#include <sound/soc.h>
  34#include <sound/soc-dapm.h>
  35#include <sound/tlv.h>
  36#include <sound/tas2552-plat.h>
  37#include <dt-bindings/sound/tas2552.h>
  38
  39#include "tas2552.h"
  40
  41static const struct reg_default tas2552_reg_defs[] = {
  42        {TAS2552_CFG_1, 0x22},
  43        {TAS2552_CFG_3, 0x80},
  44        {TAS2552_DOUT, 0x00},
  45        {TAS2552_OUTPUT_DATA, 0xc0},
  46        {TAS2552_PDM_CFG, 0x01},
  47        {TAS2552_PGA_GAIN, 0x00},
  48        {TAS2552_BOOST_APT_CTRL, 0x0f},
  49        {TAS2552_RESERVED_0D, 0xbe},
  50        {TAS2552_LIMIT_RATE_HYS, 0x08},
  51        {TAS2552_CFG_2, 0xef},
  52        {TAS2552_SER_CTRL_1, 0x00},
  53        {TAS2552_SER_CTRL_2, 0x00},
  54        {TAS2552_PLL_CTRL_1, 0x10},
  55        {TAS2552_PLL_CTRL_2, 0x00},
  56        {TAS2552_PLL_CTRL_3, 0x00},
  57        {TAS2552_BTIP, 0x8f},
  58        {TAS2552_BTS_CTRL, 0x80},
  59        {TAS2552_LIMIT_RELEASE, 0x04},
  60        {TAS2552_LIMIT_INT_COUNT, 0x00},
  61        {TAS2552_EDGE_RATE_CTRL, 0x40},
  62        {TAS2552_VBAT_DATA, 0x00},
  63};
  64
  65#define TAS2552_NUM_SUPPLIES    3
  66static const char *tas2552_supply_names[TAS2552_NUM_SUPPLIES] = {
  67        "vbat",         /* vbat voltage */
  68        "iovdd",        /* I/O Voltage */
  69        "avdd",         /* Analog DAC Voltage */
  70};
  71
  72struct tas2552_data {
  73        struct snd_soc_codec *codec;
  74        struct regmap *regmap;
  75        struct i2c_client *tas2552_client;
  76        struct regulator_bulk_data supplies[TAS2552_NUM_SUPPLIES];
  77        struct gpio_desc *enable_gpio;
  78        unsigned char regs[TAS2552_VBAT_DATA];
  79        unsigned int pll_clkin;
  80        int pll_clk_id;
  81        unsigned int pdm_clk;
  82        int pdm_clk_id;
  83
  84        unsigned int dai_fmt;
  85        unsigned int tdm_delay;
  86};
  87
  88static int tas2552_post_event(struct snd_soc_dapm_widget *w,
  89                              struct snd_kcontrol *kcontrol, int event)
  90{
  91        struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
  92
  93        switch (event) {
  94        case SND_SOC_DAPM_POST_PMU:
  95                snd_soc_write(codec, TAS2552_RESERVED_0D, 0xc0);
  96                snd_soc_update_bits(codec, TAS2552_LIMIT_RATE_HYS, (1 << 5),
  97                                    (1 << 5));
  98                snd_soc_update_bits(codec, TAS2552_CFG_2, 1, 0);
  99                snd_soc_update_bits(codec, TAS2552_CFG_1, TAS2552_SWS, 0);
 100                break;
 101        case SND_SOC_DAPM_POST_PMD:
 102                snd_soc_update_bits(codec, TAS2552_CFG_1, TAS2552_SWS,
 103                                    TAS2552_SWS);
 104                snd_soc_update_bits(codec, TAS2552_CFG_2, 1, 1);
 105                snd_soc_update_bits(codec, TAS2552_LIMIT_RATE_HYS, (1 << 5), 0);
 106                snd_soc_write(codec, TAS2552_RESERVED_0D, 0xbe);
 107                break;
 108        }
 109        return 0;
 110}
 111
 112/* Input mux controls */
 113static const char * const tas2552_input_texts[] = {
 114        "Digital", "Analog" };
 115static SOC_ENUM_SINGLE_DECL(tas2552_input_mux_enum, TAS2552_CFG_3, 7,
 116                            tas2552_input_texts);
 117
 118static const struct snd_kcontrol_new tas2552_input_mux_control =
 119        SOC_DAPM_ENUM("Route", tas2552_input_mux_enum);
 120
 121static const struct snd_soc_dapm_widget tas2552_dapm_widgets[] =
 122{
 123        SND_SOC_DAPM_INPUT("IN"),
 124
 125        /* MUX Controls */
 126        SND_SOC_DAPM_MUX("Input selection", SND_SOC_NOPM, 0, 0,
 127                         &tas2552_input_mux_control),
 128
 129        SND_SOC_DAPM_AIF_IN("DAC IN", "DAC Playback", 0, SND_SOC_NOPM, 0, 0),
 130        SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0),
 131        SND_SOC_DAPM_OUT_DRV("ClassD", TAS2552_CFG_2, 7, 0, NULL, 0),
 132        SND_SOC_DAPM_SUPPLY("PLL", TAS2552_CFG_2, 3, 0, NULL, 0),
 133        SND_SOC_DAPM_POST("Post Event", tas2552_post_event),
 134
 135        SND_SOC_DAPM_OUTPUT("OUT")
 136};
 137
 138static const struct snd_soc_dapm_route tas2552_audio_map[] = {
 139        {"DAC", NULL, "DAC IN"},
 140        {"Input selection", "Digital", "DAC"},
 141        {"Input selection", "Analog", "IN"},
 142        {"ClassD", NULL, "Input selection"},
 143        {"OUT", NULL, "ClassD"},
 144        {"ClassD", NULL, "PLL"},
 145};
 146
 147#ifdef CONFIG_PM
 148static void tas2552_sw_shutdown(struct tas2552_data *tas2552, int sw_shutdown)
 149{
 150        u8 cfg1_reg = 0;
 151
 152        if (!tas2552->codec)
 153                return;
 154
 155        if (sw_shutdown)
 156                cfg1_reg = TAS2552_SWS;
 157
 158        snd_soc_update_bits(tas2552->codec, TAS2552_CFG_1, TAS2552_SWS,
 159                            cfg1_reg);
 160}
 161#endif
 162
 163static int tas2552_setup_pll(struct snd_soc_codec *codec,
 164                             struct snd_pcm_hw_params *params)
 165{
 166        struct tas2552_data *tas2552 = dev_get_drvdata(codec->dev);
 167        bool bypass_pll = false;
 168        unsigned int pll_clk = params_rate(params) * 512;
 169        unsigned int pll_clkin = tas2552->pll_clkin;
 170        u8 pll_enable;
 171
 172        if (!pll_clkin) {
 173                if (tas2552->pll_clk_id != TAS2552_PLL_CLKIN_BCLK)
 174                        return -EINVAL;
 175
 176                pll_clkin = snd_soc_params_to_bclk(params);
 177                pll_clkin += tas2552->tdm_delay;
 178        }
 179
 180        pll_enable = snd_soc_read(codec, TAS2552_CFG_2) & TAS2552_PLL_ENABLE;
 181        snd_soc_update_bits(codec, TAS2552_CFG_2, TAS2552_PLL_ENABLE, 0);
 182
 183        if (pll_clkin == pll_clk)
 184                bypass_pll = true;
 185
 186        if (bypass_pll) {
 187                /* By pass the PLL configuration */
 188                snd_soc_update_bits(codec, TAS2552_PLL_CTRL_2,
 189                                    TAS2552_PLL_BYPASS, TAS2552_PLL_BYPASS);
 190        } else {
 191                /* Fill in the PLL control registers for J & D
 192                 * pll_clk = (.5 * pll_clkin * J.D) / 2^p
 193                 * Need to fill in J and D here based on incoming freq
 194                 */
 195                unsigned int d;
 196                u8 j;
 197                u8 pll_sel = (tas2552->pll_clk_id << 3) & TAS2552_PLL_SRC_MASK;
 198                u8 p = snd_soc_read(codec, TAS2552_PLL_CTRL_1);
 199
 200                p = (p >> 7);
 201
 202recalc:
 203                j = (pll_clk * 2 * (1 << p)) / pll_clkin;
 204                d = (pll_clk * 2 * (1 << p)) % pll_clkin;
 205                d /= (pll_clkin / 10000);
 206
 207                if (d && (pll_clkin < 512000 || pll_clkin > 9200000)) {
 208                        if (tas2552->pll_clk_id == TAS2552_PLL_CLKIN_BCLK) {
 209                                pll_clkin = 1800000;
 210                                pll_sel = (TAS2552_PLL_CLKIN_1_8_FIXED << 3) &
 211                                                        TAS2552_PLL_SRC_MASK;
 212                        } else {
 213                                pll_clkin = snd_soc_params_to_bclk(params);
 214                                pll_clkin += tas2552->tdm_delay;
 215                                pll_sel = (TAS2552_PLL_CLKIN_BCLK << 3) &
 216                                                        TAS2552_PLL_SRC_MASK;
 217                        }
 218                        goto recalc;
 219                }
 220
 221                snd_soc_update_bits(codec, TAS2552_CFG_1, TAS2552_PLL_SRC_MASK,
 222                                    pll_sel);
 223
 224                snd_soc_update_bits(codec, TAS2552_PLL_CTRL_1,
 225                                    TAS2552_PLL_J_MASK, j);
 226                /* Will clear the PLL_BYPASS bit */
 227                snd_soc_write(codec, TAS2552_PLL_CTRL_2,
 228                              TAS2552_PLL_D_UPPER(d));
 229                snd_soc_write(codec, TAS2552_PLL_CTRL_3,
 230                              TAS2552_PLL_D_LOWER(d));
 231        }
 232
 233        /* Restore PLL status */
 234        snd_soc_update_bits(codec, TAS2552_CFG_2, TAS2552_PLL_ENABLE,
 235                            pll_enable);
 236
 237        return 0;
 238}
 239
 240static int tas2552_hw_params(struct snd_pcm_substream *substream,
 241                             struct snd_pcm_hw_params *params,
 242                             struct snd_soc_dai *dai)
 243{
 244        struct snd_soc_codec *codec = dai->codec;
 245        struct tas2552_data *tas2552 = dev_get_drvdata(codec->dev);
 246        int cpf;
 247        u8 ser_ctrl1_reg, wclk_rate;
 248
 249        switch (params_width(params)) {
 250        case 16:
 251                ser_ctrl1_reg = TAS2552_WORDLENGTH_16BIT;
 252                cpf = 32 + tas2552->tdm_delay;
 253                break;
 254        case 20:
 255                ser_ctrl1_reg = TAS2552_WORDLENGTH_20BIT;
 256                cpf = 64 + tas2552->tdm_delay;
 257                break;
 258        case 24:
 259                ser_ctrl1_reg = TAS2552_WORDLENGTH_24BIT;
 260                cpf = 64 + tas2552->tdm_delay;
 261                break;
 262        case 32:
 263                ser_ctrl1_reg = TAS2552_WORDLENGTH_32BIT;
 264                cpf = 64 + tas2552->tdm_delay;
 265                break;
 266        default:
 267                dev_err(codec->dev, "Not supported sample size: %d\n",
 268                        params_width(params));
 269                return -EINVAL;
 270        }
 271
 272        if (cpf <= 32)
 273                ser_ctrl1_reg |= TAS2552_CLKSPERFRAME_32;
 274        else if (cpf <= 64)
 275                ser_ctrl1_reg |= TAS2552_CLKSPERFRAME_64;
 276        else if (cpf <= 128)
 277                ser_ctrl1_reg |= TAS2552_CLKSPERFRAME_128;
 278        else
 279                ser_ctrl1_reg |= TAS2552_CLKSPERFRAME_256;
 280
 281        snd_soc_update_bits(codec, TAS2552_SER_CTRL_1,
 282                            TAS2552_WORDLENGTH_MASK | TAS2552_CLKSPERFRAME_MASK,
 283                            ser_ctrl1_reg);
 284
 285        switch (params_rate(params)) {
 286        case 8000:
 287                wclk_rate = TAS2552_WCLK_FREQ_8KHZ;
 288                break;
 289        case 11025:
 290        case 12000:
 291                wclk_rate = TAS2552_WCLK_FREQ_11_12KHZ;
 292                break;
 293        case 16000:
 294                wclk_rate = TAS2552_WCLK_FREQ_16KHZ;
 295                break;
 296        case 22050:
 297        case 24000:
 298                wclk_rate = TAS2552_WCLK_FREQ_22_24KHZ;
 299                break;
 300        case 32000:
 301                wclk_rate = TAS2552_WCLK_FREQ_32KHZ;
 302                break;
 303        case 44100:
 304        case 48000:
 305                wclk_rate = TAS2552_WCLK_FREQ_44_48KHZ;
 306                break;
 307        case 88200:
 308        case 96000:
 309                wclk_rate = TAS2552_WCLK_FREQ_88_96KHZ;
 310                break;
 311        case 176400:
 312        case 192000:
 313                wclk_rate = TAS2552_WCLK_FREQ_176_192KHZ;
 314                break;
 315        default:
 316                dev_err(codec->dev, "Not supported sample rate: %d\n",
 317                        params_rate(params));
 318                return -EINVAL;
 319        }
 320
 321        snd_soc_update_bits(codec, TAS2552_CFG_3, TAS2552_WCLK_FREQ_MASK,
 322                            wclk_rate);
 323
 324        return tas2552_setup_pll(codec, params);
 325}
 326
 327#define TAS2552_DAI_FMT_MASK    (TAS2552_BCLKDIR | \
 328                                 TAS2552_WCLKDIR | \
 329                                 TAS2552_DATAFORMAT_MASK)
 330static int tas2552_prepare(struct snd_pcm_substream *substream,
 331                           struct snd_soc_dai *dai)
 332{
 333        struct snd_soc_codec *codec = dai->codec;
 334        struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec);
 335        int delay = 0;
 336
 337        /* TDM slot selection only valid in DSP_A/_B mode */
 338        if (tas2552->dai_fmt == SND_SOC_DAIFMT_DSP_A)
 339                delay += (tas2552->tdm_delay + 1);
 340        else if (tas2552->dai_fmt == SND_SOC_DAIFMT_DSP_B)
 341                delay += tas2552->tdm_delay;
 342
 343        /* Configure data delay */
 344        snd_soc_write(codec, TAS2552_SER_CTRL_2, delay);
 345
 346        return 0;
 347}
 348
 349static int tas2552_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 350{
 351        struct snd_soc_codec *codec = dai->codec;
 352        struct tas2552_data *tas2552 = dev_get_drvdata(codec->dev);
 353        u8 serial_format;
 354
 355        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
 356        case SND_SOC_DAIFMT_CBS_CFS:
 357                serial_format = 0x00;
 358                break;
 359        case SND_SOC_DAIFMT_CBS_CFM:
 360                serial_format = TAS2552_WCLKDIR;
 361                break;
 362        case SND_SOC_DAIFMT_CBM_CFS:
 363                serial_format = TAS2552_BCLKDIR;
 364                break;
 365        case SND_SOC_DAIFMT_CBM_CFM:
 366                serial_format = (TAS2552_BCLKDIR | TAS2552_WCLKDIR);
 367                break;
 368        default:
 369                dev_vdbg(codec->dev, "DAI Format master is not found\n");
 370                return -EINVAL;
 371        }
 372
 373        switch (fmt & (SND_SOC_DAIFMT_FORMAT_MASK |
 374                       SND_SOC_DAIFMT_INV_MASK)) {
 375        case (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF):
 376                break;
 377        case (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF):
 378        case (SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF):
 379                serial_format |= TAS2552_DATAFORMAT_DSP;
 380                break;
 381        case (SND_SOC_DAIFMT_RIGHT_J | SND_SOC_DAIFMT_NB_NF):
 382                serial_format |= TAS2552_DATAFORMAT_RIGHT_J;
 383                break;
 384        case (SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF):
 385                serial_format |= TAS2552_DATAFORMAT_LEFT_J;
 386                break;
 387        default:
 388                dev_vdbg(codec->dev, "DAI Format is not found\n");
 389                return -EINVAL;
 390        }
 391        tas2552->dai_fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
 392
 393        snd_soc_update_bits(codec, TAS2552_SER_CTRL_1, TAS2552_DAI_FMT_MASK,
 394                            serial_format);
 395        return 0;
 396}
 397
 398static int tas2552_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
 399                                  unsigned int freq, int dir)
 400{
 401        struct snd_soc_codec *codec = dai->codec;
 402        struct tas2552_data *tas2552 = dev_get_drvdata(codec->dev);
 403        u8 reg, mask, val;
 404
 405        switch (clk_id) {
 406        case TAS2552_PLL_CLKIN_MCLK:
 407        case TAS2552_PLL_CLKIN_IVCLKIN:
 408                if (freq < 512000 || freq > 24576000) {
 409                        /* out of range PLL_CLKIN, fall back to use BCLK */
 410                        dev_warn(codec->dev, "Out of range PLL_CLKIN: %u\n",
 411                                 freq);
 412                        clk_id = TAS2552_PLL_CLKIN_BCLK;
 413                        freq = 0;
 414                }
 415                /* fall through */
 416        case TAS2552_PLL_CLKIN_BCLK:
 417        case TAS2552_PLL_CLKIN_1_8_FIXED:
 418                mask = TAS2552_PLL_SRC_MASK;
 419                val = (clk_id << 3) & mask; /* bit 4:5 in the register */
 420                reg = TAS2552_CFG_1;
 421                tas2552->pll_clk_id = clk_id;
 422                tas2552->pll_clkin = freq;
 423                break;
 424        case TAS2552_PDM_CLK_PLL:
 425        case TAS2552_PDM_CLK_IVCLKIN:
 426        case TAS2552_PDM_CLK_BCLK:
 427        case TAS2552_PDM_CLK_MCLK:
 428                mask = TAS2552_PDM_CLK_SEL_MASK;
 429                val = (clk_id >> 1) & mask; /* bit 0:1 in the register */
 430                reg = TAS2552_PDM_CFG;
 431                tas2552->pdm_clk_id = clk_id;
 432                tas2552->pdm_clk = freq;
 433                break;
 434        default:
 435                dev_err(codec->dev, "Invalid clk id: %d\n", clk_id);
 436                return -EINVAL;
 437        }
 438
 439        snd_soc_update_bits(codec, reg, mask, val);
 440
 441        return 0;
 442}
 443
 444static int tas2552_set_dai_tdm_slot(struct snd_soc_dai *dai,
 445                                    unsigned int tx_mask, unsigned int rx_mask,
 446                                    int slots, int slot_width)
 447{
 448        struct snd_soc_codec *codec = dai->codec;
 449        struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec);
 450        unsigned int lsb;
 451
 452        if (unlikely(!tx_mask)) {
 453                dev_err(codec->dev, "tx masks need to be non 0\n");
 454                return -EINVAL;
 455        }
 456
 457        /* TDM based on DSP mode requires slots to be adjacent */
 458        lsb = __ffs(tx_mask);
 459        if ((lsb + 1) != __fls(tx_mask)) {
 460                dev_err(codec->dev, "Invalid mask, slots must be adjacent\n");
 461                return -EINVAL;
 462        }
 463
 464        tas2552->tdm_delay = lsb * slot_width;
 465
 466        /* DOUT in high-impedance on inactive bit clocks */
 467        snd_soc_update_bits(codec, TAS2552_DOUT,
 468                            TAS2552_SDOUT_TRISTATE, TAS2552_SDOUT_TRISTATE);
 469
 470        return 0;
 471}
 472
 473static int tas2552_mute(struct snd_soc_dai *dai, int mute)
 474{
 475        u8 cfg1_reg = 0;
 476        struct snd_soc_codec *codec = dai->codec;
 477
 478        if (mute)
 479                cfg1_reg |= TAS2552_MUTE;
 480
 481        snd_soc_update_bits(codec, TAS2552_CFG_1, TAS2552_MUTE, cfg1_reg);
 482
 483        return 0;
 484}
 485
 486#ifdef CONFIG_PM
 487static int tas2552_runtime_suspend(struct device *dev)
 488{
 489        struct tas2552_data *tas2552 = dev_get_drvdata(dev);
 490
 491        tas2552_sw_shutdown(tas2552, 1);
 492
 493        regcache_cache_only(tas2552->regmap, true);
 494        regcache_mark_dirty(tas2552->regmap);
 495
 496        gpiod_set_value(tas2552->enable_gpio, 0);
 497
 498        return 0;
 499}
 500
 501static int tas2552_runtime_resume(struct device *dev)
 502{
 503        struct tas2552_data *tas2552 = dev_get_drvdata(dev);
 504
 505        gpiod_set_value(tas2552->enable_gpio, 1);
 506
 507        tas2552_sw_shutdown(tas2552, 0);
 508
 509        regcache_cache_only(tas2552->regmap, false);
 510        regcache_sync(tas2552->regmap);
 511
 512        return 0;
 513}
 514#endif
 515
 516static const struct dev_pm_ops tas2552_pm = {
 517        SET_RUNTIME_PM_OPS(tas2552_runtime_suspend, tas2552_runtime_resume,
 518                           NULL)
 519};
 520
 521static const struct snd_soc_dai_ops tas2552_speaker_dai_ops = {
 522        .hw_params      = tas2552_hw_params,
 523        .prepare        = tas2552_prepare,
 524        .set_sysclk     = tas2552_set_dai_sysclk,
 525        .set_fmt        = tas2552_set_dai_fmt,
 526        .set_tdm_slot   = tas2552_set_dai_tdm_slot,
 527        .digital_mute = tas2552_mute,
 528};
 529
 530/* Formats supported by TAS2552 driver. */
 531#define TAS2552_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
 532                         SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 533
 534/* TAS2552 dai structure. */
 535static struct snd_soc_dai_driver tas2552_dai[] = {
 536        {
 537                .name = "tas2552-amplifier",
 538                .playback = {
 539                        .stream_name = "Playback",
 540                        .channels_min = 2,
 541                        .channels_max = 2,
 542                        .rates = SNDRV_PCM_RATE_8000_192000,
 543                        .formats = TAS2552_FORMATS,
 544                },
 545                .ops = &tas2552_speaker_dai_ops,
 546        },
 547};
 548
 549/*
 550 * DAC digital volumes. From -7 to 24 dB in 1 dB steps
 551 */
 552static DECLARE_TLV_DB_SCALE(dac_tlv, -700, 100, 0);
 553
 554static const char * const tas2552_din_source_select[] = {
 555        "Muted",
 556        "Left",
 557        "Right",
 558        "Left + Right average",
 559};
 560static SOC_ENUM_SINGLE_DECL(tas2552_din_source_enum,
 561                            TAS2552_CFG_3, 3,
 562                            tas2552_din_source_select);
 563
 564static const struct snd_kcontrol_new tas2552_snd_controls[] = {
 565        SOC_SINGLE_TLV("Speaker Driver Playback Volume",
 566                         TAS2552_PGA_GAIN, 0, 0x1f, 0, dac_tlv),
 567        SOC_ENUM("DIN source", tas2552_din_source_enum),
 568};
 569
 570static int tas2552_codec_probe(struct snd_soc_codec *codec)
 571{
 572        struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec);
 573        int ret;
 574
 575        tas2552->codec = codec;
 576
 577        ret = regulator_bulk_enable(ARRAY_SIZE(tas2552->supplies),
 578                                    tas2552->supplies);
 579
 580        if (ret != 0) {
 581                dev_err(codec->dev, "Failed to enable supplies: %d\n",
 582                        ret);
 583                return ret;
 584        }
 585
 586        gpiod_set_value(tas2552->enable_gpio, 1);
 587
 588        ret = pm_runtime_get_sync(codec->dev);
 589        if (ret < 0) {
 590                dev_err(codec->dev, "Enabling device failed: %d\n",
 591                        ret);
 592                goto probe_fail;
 593        }
 594
 595        snd_soc_update_bits(codec, TAS2552_CFG_1, TAS2552_MUTE, TAS2552_MUTE);
 596        snd_soc_write(codec, TAS2552_CFG_3, TAS2552_I2S_OUT_SEL |
 597                                            TAS2552_DIN_SRC_SEL_AVG_L_R);
 598        snd_soc_write(codec, TAS2552_OUTPUT_DATA,
 599                      TAS2552_PDM_DATA_SEL_V_I |
 600                      TAS2552_R_DATA_OUT(TAS2552_DATA_OUT_V_DATA));
 601        snd_soc_write(codec, TAS2552_BOOST_APT_CTRL, TAS2552_APT_DELAY_200 |
 602                                                     TAS2552_APT_THRESH_20_17);
 603
 604        snd_soc_write(codec, TAS2552_CFG_2, TAS2552_BOOST_EN | TAS2552_APT_EN |
 605                                            TAS2552_LIM_EN);
 606
 607        return 0;
 608
 609probe_fail:
 610        gpiod_set_value(tas2552->enable_gpio, 0);
 611
 612        regulator_bulk_disable(ARRAY_SIZE(tas2552->supplies),
 613                                        tas2552->supplies);
 614        return -EIO;
 615}
 616
 617static int tas2552_codec_remove(struct snd_soc_codec *codec)
 618{
 619        struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec);
 620
 621        pm_runtime_put(codec->dev);
 622
 623        gpiod_set_value(tas2552->enable_gpio, 0);
 624
 625        return 0;
 626};
 627
 628#ifdef CONFIG_PM
 629static int tas2552_suspend(struct snd_soc_codec *codec)
 630{
 631        struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec);
 632        int ret;
 633
 634        ret = regulator_bulk_disable(ARRAY_SIZE(tas2552->supplies),
 635                                        tas2552->supplies);
 636
 637        if (ret != 0)
 638                dev_err(codec->dev, "Failed to disable supplies: %d\n",
 639                        ret);
 640        return 0;
 641}
 642
 643static int tas2552_resume(struct snd_soc_codec *codec)
 644{
 645        struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec);
 646        int ret;
 647
 648        ret = regulator_bulk_enable(ARRAY_SIZE(tas2552->supplies),
 649                                    tas2552->supplies);
 650
 651        if (ret != 0) {
 652                dev_err(codec->dev, "Failed to enable supplies: %d\n",
 653                        ret);
 654        }
 655
 656        return 0;
 657}
 658#else
 659#define tas2552_suspend NULL
 660#define tas2552_resume NULL
 661#endif
 662
 663static struct snd_soc_codec_driver soc_codec_dev_tas2552 = {
 664        .probe = tas2552_codec_probe,
 665        .remove = tas2552_codec_remove,
 666        .suspend =      tas2552_suspend,
 667        .resume = tas2552_resume,
 668        .ignore_pmdown_time = true,
 669
 670        .controls = tas2552_snd_controls,
 671        .num_controls = ARRAY_SIZE(tas2552_snd_controls),
 672        .dapm_widgets = tas2552_dapm_widgets,
 673        .num_dapm_widgets = ARRAY_SIZE(tas2552_dapm_widgets),
 674        .dapm_routes = tas2552_audio_map,
 675        .num_dapm_routes = ARRAY_SIZE(tas2552_audio_map),
 676};
 677
 678static const struct regmap_config tas2552_regmap_config = {
 679        .reg_bits = 8,
 680        .val_bits = 8,
 681
 682        .max_register = TAS2552_MAX_REG,
 683        .reg_defaults = tas2552_reg_defs,
 684        .num_reg_defaults = ARRAY_SIZE(tas2552_reg_defs),
 685        .cache_type = REGCACHE_RBTREE,
 686};
 687
 688static int tas2552_probe(struct i2c_client *client,
 689                           const struct i2c_device_id *id)
 690{
 691        struct device *dev;
 692        struct tas2552_data *data;
 693        int ret;
 694        int i;
 695
 696        dev = &client->dev;
 697        data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
 698        if (data == NULL)
 699                return -ENOMEM;
 700
 701        data->enable_gpio = devm_gpiod_get_optional(dev, "enable",
 702                                                    GPIOD_OUT_LOW);
 703        if (IS_ERR(data->enable_gpio))
 704                return PTR_ERR(data->enable_gpio);
 705
 706        data->tas2552_client = client;
 707        data->regmap = devm_regmap_init_i2c(client, &tas2552_regmap_config);
 708        if (IS_ERR(data->regmap)) {
 709                ret = PTR_ERR(data->regmap);
 710                dev_err(&client->dev, "Failed to allocate register map: %d\n",
 711                        ret);
 712                return ret;
 713        }
 714
 715        for (i = 0; i < ARRAY_SIZE(data->supplies); i++)
 716                data->supplies[i].supply = tas2552_supply_names[i];
 717
 718        ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(data->supplies),
 719                                      data->supplies);
 720        if (ret != 0) {
 721                dev_err(dev, "Failed to request supplies: %d\n", ret);
 722                return ret;
 723        }
 724
 725        pm_runtime_set_active(&client->dev);
 726        pm_runtime_set_autosuspend_delay(&client->dev, 1000);
 727        pm_runtime_use_autosuspend(&client->dev);
 728        pm_runtime_enable(&client->dev);
 729        pm_runtime_mark_last_busy(&client->dev);
 730        pm_runtime_put_sync_autosuspend(&client->dev);
 731
 732        dev_set_drvdata(&client->dev, data);
 733
 734        ret = snd_soc_register_codec(&client->dev,
 735                                      &soc_codec_dev_tas2552,
 736                                      tas2552_dai, ARRAY_SIZE(tas2552_dai));
 737        if (ret < 0)
 738                dev_err(&client->dev, "Failed to register codec: %d\n", ret);
 739
 740        return ret;
 741}
 742
 743static int tas2552_i2c_remove(struct i2c_client *client)
 744{
 745        snd_soc_unregister_codec(&client->dev);
 746        pm_runtime_disable(&client->dev);
 747        return 0;
 748}
 749
 750static const struct i2c_device_id tas2552_id[] = {
 751        { "tas2552", 0 },
 752        { }
 753};
 754MODULE_DEVICE_TABLE(i2c, tas2552_id);
 755
 756#if IS_ENABLED(CONFIG_OF)
 757static const struct of_device_id tas2552_of_match[] = {
 758        { .compatible = "ti,tas2552", },
 759        {},
 760};
 761MODULE_DEVICE_TABLE(of, tas2552_of_match);
 762#endif
 763
 764static struct i2c_driver tas2552_i2c_driver = {
 765        .driver = {
 766                .name = "tas2552",
 767                .of_match_table = of_match_ptr(tas2552_of_match),
 768                .pm = &tas2552_pm,
 769        },
 770        .probe = tas2552_probe,
 771        .remove = tas2552_i2c_remove,
 772        .id_table = tas2552_id,
 773};
 774
 775module_i2c_driver(tas2552_i2c_driver);
 776
 777MODULE_AUTHOR("Dan Muprhy <dmurphy@ti.com>");
 778MODULE_DESCRIPTION("TAS2552 Audio amplifier driver");
 779MODULE_LICENSE("GPL");
 780