linux/sound/soc/codecs/tas2562.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2//
   3// Driver for the Texas Instruments TAS2562 CODEC
   4// Copyright (C) 2019 Texas Instruments Inc.
   5
   6
   7#include <linux/module.h>
   8#include <linux/errno.h>
   9#include <linux/device.h>
  10#include <linux/i2c.h>
  11#include <linux/pm_runtime.h>
  12#include <linux/regmap.h>
  13#include <linux/slab.h>
  14#include <linux/gpio/consumer.h>
  15#include <linux/regulator/consumer.h>
  16#include <linux/delay.h>
  17
  18#include <sound/pcm.h>
  19#include <sound/pcm_params.h>
  20#include <sound/soc.h>
  21#include <sound/soc-dapm.h>
  22#include <sound/tlv.h>
  23
  24#include "tas2562.h"
  25
  26#define TAS2562_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |\
  27                         SNDRV_PCM_FORMAT_S32_LE)
  28
  29/* DVC equation involves floating point math
  30 * round(10^(volume in dB/20)*2^30)
  31 * so create a lookup table for 2dB step
  32 */
  33static const unsigned int float_vol_db_lookup[] = {
  340x00000d43, 0x000010b2, 0x00001505, 0x00001a67, 0x00002151,
  350x000029f1, 0x000034cd, 0x00004279, 0x000053af, 0x0000695b,
  360x0000695b, 0x0000a6fa, 0x0000d236, 0x000108a4, 0x00014d2a,
  370x0001a36e, 0x00021008, 0x000298c0, 0x000344df, 0x00041d8f,
  380x00052e5a, 0x000685c8, 0x00083621, 0x000a566d, 0x000d03a7,
  390x0010624d, 0x0014a050, 0x0019f786, 0x0020b0bc, 0x0029279d,
  400x0033cf8d, 0x004139d3, 0x00521d50, 0x00676044, 0x0082248a,
  410x00a3d70a, 0x00ce4328, 0x0103ab3d, 0x0146e75d, 0x019b8c27,
  420x02061b89, 0x028c423f, 0x03352529, 0x0409c2b0, 0x05156d68,
  430x080e9f96, 0x0a24b062, 0x0cc509ab, 0x10137987, 0x143d1362,
  440x197a967f, 0x2013739e, 0x28619ae9, 0x32d64617, 0x40000000
  45};
  46
  47struct tas2562_data {
  48        struct snd_soc_component *component;
  49        struct gpio_desc *sdz_gpio;
  50        struct regmap *regmap;
  51        struct device *dev;
  52        struct i2c_client *client;
  53        int v_sense_slot;
  54        int i_sense_slot;
  55        int volume_lvl;
  56        int model_id;
  57};
  58
  59enum tas256x_model {
  60        TAS2562,
  61        TAS2563,
  62        TAS2564,
  63        TAS2110,
  64};
  65
  66static int tas2562_set_bias_level(struct snd_soc_component *component,
  67                                 enum snd_soc_bias_level level)
  68{
  69        struct tas2562_data *tas2562 =
  70                        snd_soc_component_get_drvdata(component);
  71
  72        switch (level) {
  73        case SND_SOC_BIAS_ON:
  74                snd_soc_component_update_bits(component,
  75                        TAS2562_PWR_CTRL,
  76                        TAS2562_MODE_MASK, TAS2562_ACTIVE);
  77                break;
  78        case SND_SOC_BIAS_STANDBY:
  79        case SND_SOC_BIAS_PREPARE:
  80                snd_soc_component_update_bits(component,
  81                        TAS2562_PWR_CTRL,
  82                        TAS2562_MODE_MASK, TAS2562_MUTE);
  83                break;
  84        case SND_SOC_BIAS_OFF:
  85                snd_soc_component_update_bits(component,
  86                        TAS2562_PWR_CTRL,
  87                        TAS2562_MODE_MASK, TAS2562_SHUTDOWN);
  88                break;
  89
  90        default:
  91                dev_err(tas2562->dev,
  92                                "wrong power level setting %d\n", level);
  93                return -EINVAL;
  94        }
  95
  96        return 0;
  97}
  98
  99static int tas2562_set_samplerate(struct tas2562_data *tas2562, int samplerate)
 100{
 101        int samp_rate;
 102        int ramp_rate;
 103
 104        switch (samplerate) {
 105        case 7350:
 106                ramp_rate = TAS2562_TDM_CFG0_RAMPRATE_44_1;
 107                samp_rate = TAS2562_TDM_CFG0_SAMPRATE_7305_8KHZ;
 108                break;
 109        case 8000:
 110                ramp_rate = 0;
 111                samp_rate = TAS2562_TDM_CFG0_SAMPRATE_7305_8KHZ;
 112                break;
 113        case 14700:
 114                ramp_rate = TAS2562_TDM_CFG0_RAMPRATE_44_1;
 115                samp_rate = TAS2562_TDM_CFG0_SAMPRATE_14_7_16KHZ;
 116                break;
 117        case 16000:
 118                ramp_rate = 0;
 119                samp_rate = TAS2562_TDM_CFG0_SAMPRATE_14_7_16KHZ;
 120                break;
 121        case 22050:
 122                ramp_rate = TAS2562_TDM_CFG0_RAMPRATE_44_1;
 123                samp_rate = TAS2562_TDM_CFG0_SAMPRATE_22_05_24KHZ;
 124                break;
 125        case 24000:
 126                ramp_rate = 0;
 127                samp_rate = TAS2562_TDM_CFG0_SAMPRATE_22_05_24KHZ;
 128                break;
 129        case 29400:
 130                ramp_rate = TAS2562_TDM_CFG0_RAMPRATE_44_1;
 131                samp_rate = TAS2562_TDM_CFG0_SAMPRATE_29_4_32KHZ;
 132                break;
 133        case 32000:
 134                ramp_rate = 0;
 135                samp_rate = TAS2562_TDM_CFG0_SAMPRATE_29_4_32KHZ;
 136                break;
 137        case 44100:
 138                ramp_rate = TAS2562_TDM_CFG0_RAMPRATE_44_1;
 139                samp_rate = TAS2562_TDM_CFG0_SAMPRATE_44_1_48KHZ;
 140                break;
 141        case 48000:
 142                ramp_rate = 0;
 143                samp_rate = TAS2562_TDM_CFG0_SAMPRATE_44_1_48KHZ;
 144                break;
 145        case 88200:
 146                ramp_rate = TAS2562_TDM_CFG0_RAMPRATE_44_1;
 147                samp_rate = TAS2562_TDM_CFG0_SAMPRATE_88_2_96KHZ;
 148                break;
 149        case 96000:
 150                ramp_rate = 0;
 151                samp_rate = TAS2562_TDM_CFG0_SAMPRATE_88_2_96KHZ;
 152                break;
 153        case 176400:
 154                ramp_rate = TAS2562_TDM_CFG0_RAMPRATE_44_1;
 155                samp_rate = TAS2562_TDM_CFG0_SAMPRATE_176_4_192KHZ;
 156                break;
 157        case 192000:
 158                ramp_rate = 0;
 159                samp_rate = TAS2562_TDM_CFG0_SAMPRATE_176_4_192KHZ;
 160                break;
 161        default:
 162                dev_info(tas2562->dev, "%s, unsupported sample rate, %d\n",
 163                        __func__, samplerate);
 164                return -EINVAL;
 165        }
 166
 167        snd_soc_component_update_bits(tas2562->component, TAS2562_TDM_CFG0,
 168                TAS2562_TDM_CFG0_RAMPRATE_MASK, ramp_rate);
 169        snd_soc_component_update_bits(tas2562->component, TAS2562_TDM_CFG0,
 170                TAS2562_TDM_CFG0_SAMPRATE_MASK, samp_rate);
 171
 172        return 0;
 173}
 174
 175static int tas2562_set_dai_tdm_slot(struct snd_soc_dai *dai,
 176                unsigned int tx_mask, unsigned int rx_mask,
 177                int slots, int slot_width)
 178{
 179        struct snd_soc_component *component = dai->component;
 180        struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component);
 181        int left_slot, right_slot;
 182        int slots_cfg;
 183        int ret;
 184
 185        if (!tx_mask) {
 186                dev_err(component->dev, "tx masks must not be 0\n");
 187                return -EINVAL;
 188        }
 189
 190        if (slots == 1) {
 191                if (tx_mask != 1)
 192                        return -EINVAL;
 193
 194                left_slot = 0;
 195                right_slot = 0;
 196        } else {
 197                left_slot = __ffs(tx_mask);
 198                tx_mask &= ~(1 << left_slot);
 199                if (tx_mask == 0) {
 200                        right_slot = left_slot;
 201                } else {
 202                        right_slot = __ffs(tx_mask);
 203                }
 204        }
 205
 206        slots_cfg = (right_slot << TAS2562_RIGHT_SLOT_SHIFT) | left_slot;
 207
 208        ret = snd_soc_component_write(component, TAS2562_TDM_CFG3, slots_cfg);
 209        if (ret < 0)
 210                return ret;
 211
 212        switch (slot_width) {
 213        case 16:
 214                ret = snd_soc_component_update_bits(component,
 215                                                    TAS2562_TDM_CFG2,
 216                                                    TAS2562_TDM_CFG2_RXLEN_MASK,
 217                                                    TAS2562_TDM_CFG2_RXLEN_16B);
 218                break;
 219        case 24:
 220                ret = snd_soc_component_update_bits(component,
 221                                                    TAS2562_TDM_CFG2,
 222                                                    TAS2562_TDM_CFG2_RXLEN_MASK,
 223                                                    TAS2562_TDM_CFG2_RXLEN_24B);
 224                break;
 225        case 32:
 226                ret = snd_soc_component_update_bits(component,
 227                                                    TAS2562_TDM_CFG2,
 228                                                    TAS2562_TDM_CFG2_RXLEN_MASK,
 229                                                    TAS2562_TDM_CFG2_RXLEN_32B);
 230                break;
 231
 232        case 0:
 233                /* Do not change slot width */
 234                break;
 235        default:
 236                dev_err(tas2562->dev, "slot width not supported");
 237                ret = -EINVAL;
 238        }
 239
 240        if (ret < 0)
 241                return ret;
 242
 243        ret = snd_soc_component_update_bits(component, TAS2562_TDM_CFG5,
 244                                            TAS2562_TDM_CFG5_VSNS_SLOT_MASK,
 245                                            tas2562->v_sense_slot);
 246        if (ret < 0)
 247                return ret;
 248
 249        ret = snd_soc_component_update_bits(component, TAS2562_TDM_CFG6,
 250                                            TAS2562_TDM_CFG6_ISNS_SLOT_MASK,
 251                                            tas2562->i_sense_slot);
 252        if (ret < 0)
 253                return ret;
 254
 255        return 0;
 256}
 257
 258static int tas2562_set_bitwidth(struct tas2562_data *tas2562, int bitwidth)
 259{
 260        int ret;
 261        int val;
 262        int sense_en;
 263
 264        switch (bitwidth) {
 265        case SNDRV_PCM_FORMAT_S16_LE:
 266                snd_soc_component_update_bits(tas2562->component,
 267                                              TAS2562_TDM_CFG2,
 268                                              TAS2562_TDM_CFG2_RXWLEN_MASK,
 269                                              TAS2562_TDM_CFG2_RXWLEN_16B);
 270                break;
 271        case SNDRV_PCM_FORMAT_S24_LE:
 272                snd_soc_component_update_bits(tas2562->component,
 273                                              TAS2562_TDM_CFG2,
 274                                              TAS2562_TDM_CFG2_RXWLEN_MASK,
 275                                              TAS2562_TDM_CFG2_RXWLEN_24B);
 276                break;
 277        case SNDRV_PCM_FORMAT_S32_LE:
 278                snd_soc_component_update_bits(tas2562->component,
 279                                              TAS2562_TDM_CFG2,
 280                                              TAS2562_TDM_CFG2_RXWLEN_MASK,
 281                                              TAS2562_TDM_CFG2_RXWLEN_32B);
 282                break;
 283
 284        default:
 285                dev_info(tas2562->dev, "Unsupported bitwidth format\n");
 286                return -EINVAL;
 287        }
 288
 289        val = snd_soc_component_read(tas2562->component, TAS2562_PWR_CTRL);
 290        if (val < 0)
 291                return val;
 292
 293        if (val & (1 << TAS2562_VSENSE_POWER_EN))
 294                sense_en = 0;
 295        else
 296                sense_en = TAS2562_TDM_CFG5_VSNS_EN;
 297
 298        ret = snd_soc_component_update_bits(tas2562->component, TAS2562_TDM_CFG5,
 299                TAS2562_TDM_CFG5_VSNS_EN, sense_en);
 300        if (ret < 0)
 301                return ret;
 302
 303        if (val & (1 << TAS2562_ISENSE_POWER_EN))
 304                sense_en = 0;
 305        else
 306                sense_en = TAS2562_TDM_CFG6_ISNS_EN;
 307
 308        ret = snd_soc_component_update_bits(tas2562->component, TAS2562_TDM_CFG6,
 309                TAS2562_TDM_CFG6_ISNS_EN, sense_en);
 310        if (ret < 0)
 311                return ret;
 312
 313        return 0;
 314}
 315
 316static int tas2562_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 tas2562_data *tas2562 = snd_soc_component_get_drvdata(component);
 322        int ret;
 323
 324        ret = tas2562_set_bitwidth(tas2562, params_format(params));
 325        if (ret) {
 326                dev_err(tas2562->dev, "set bitwidth failed, %d\n", ret);
 327                return ret;
 328        }
 329
 330        ret = tas2562_set_samplerate(tas2562, params_rate(params));
 331        if (ret)
 332                dev_err(tas2562->dev, "set sample rate failed, %d\n", ret);
 333
 334        return ret;
 335}
 336
 337static int tas2562_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 338{
 339        struct snd_soc_component *component = dai->component;
 340        struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component);
 341        u8 asi_cfg_1 = 0;
 342        u8 tdm_rx_start_slot = 0;
 343        int ret;
 344
 345        switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
 346        case SND_SOC_DAIFMT_NB_NF:
 347                asi_cfg_1 = 0;
 348                break;
 349        case SND_SOC_DAIFMT_IB_NF:
 350                asi_cfg_1 |= TAS2562_TDM_CFG1_RX_FALLING;
 351                break;
 352        default:
 353                dev_err(tas2562->dev, "ASI format Inverse is not found\n");
 354                return -EINVAL;
 355        }
 356
 357        ret = snd_soc_component_update_bits(component, TAS2562_TDM_CFG1,
 358                                            TAS2562_TDM_CFG1_RX_EDGE_MASK,
 359                                            asi_cfg_1);
 360        if (ret < 0) {
 361                dev_err(tas2562->dev, "Failed to set RX edge\n");
 362                return ret;
 363        }
 364        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
 365        case SND_SOC_DAIFMT_LEFT_J:
 366        case SND_SOC_DAIFMT_DSP_B:
 367                tdm_rx_start_slot = 0;
 368                break;
 369        case SND_SOC_DAIFMT_I2S:
 370        case SND_SOC_DAIFMT_DSP_A:
 371                tdm_rx_start_slot = 1;
 372                break;
 373        default:
 374                dev_err(tas2562->dev,
 375                        "DAI Format is not found, fmt=0x%x\n", fmt);
 376                return -EINVAL;
 377        }
 378
 379        ret = snd_soc_component_update_bits(component, TAS2562_TDM_CFG1,
 380                                TAS2562_RX_OFF_MASK, (tdm_rx_start_slot << 1));
 381        if (ret < 0)
 382                return ret;
 383
 384        return 0;
 385}
 386
 387static int tas2562_mute(struct snd_soc_dai *dai, int mute, int direction)
 388{
 389        struct snd_soc_component *component = dai->component;
 390
 391        return snd_soc_component_update_bits(component, TAS2562_PWR_CTRL,
 392                                             TAS2562_MODE_MASK,
 393                                             mute ? TAS2562_MUTE : 0);
 394}
 395
 396static int tas2562_codec_probe(struct snd_soc_component *component)
 397{
 398        struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component);
 399        int ret;
 400
 401        tas2562->component = component;
 402
 403        if (tas2562->sdz_gpio)
 404                gpiod_set_value_cansleep(tas2562->sdz_gpio, 1);
 405
 406        ret = snd_soc_component_update_bits(component, TAS2562_PWR_CTRL,
 407                                            TAS2562_MODE_MASK, TAS2562_MUTE);
 408        if (ret < 0)
 409                return ret;
 410
 411        return 0;
 412}
 413
 414#ifdef CONFIG_PM
 415static int tas2562_suspend(struct snd_soc_component *component)
 416{
 417        struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component);
 418
 419        regcache_cache_only(tas2562->regmap, true);
 420        regcache_mark_dirty(tas2562->regmap);
 421
 422        if (tas2562->sdz_gpio)
 423                gpiod_set_value_cansleep(tas2562->sdz_gpio, 0);
 424
 425        return 0;
 426}
 427
 428static int tas2562_resume(struct snd_soc_component *component)
 429{
 430        struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component);
 431
 432        if (tas2562->sdz_gpio)
 433                gpiod_set_value_cansleep(tas2562->sdz_gpio, 1);
 434
 435        regcache_cache_only(tas2562->regmap, false);
 436
 437        return regcache_sync(tas2562->regmap);
 438}
 439#else
 440#define tas2562_suspend NULL
 441#define tas2562_resume NULL
 442#endif
 443
 444static const char * const tas2562_ASI1_src[] = {
 445        "I2C offset", "Left", "Right", "LeftRightDiv2",
 446};
 447
 448static SOC_ENUM_SINGLE_DECL(tas2562_ASI1_src_enum, TAS2562_TDM_CFG2, 4,
 449                            tas2562_ASI1_src);
 450
 451static const struct snd_kcontrol_new tas2562_asi1_mux =
 452        SOC_DAPM_ENUM("ASI1 Source", tas2562_ASI1_src_enum);
 453
 454static int tas2562_dac_event(struct snd_soc_dapm_widget *w,
 455                             struct snd_kcontrol *kcontrol, int event)
 456{
 457        struct snd_soc_component *component =
 458                                        snd_soc_dapm_to_component(w->dapm);
 459        struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component);
 460        int ret;
 461
 462        switch (event) {
 463        case SND_SOC_DAPM_POST_PMU:
 464                ret = snd_soc_component_update_bits(component,
 465                        TAS2562_PWR_CTRL,
 466                        TAS2562_MODE_MASK,
 467                        TAS2562_MUTE);
 468                if (ret)
 469                        goto end;
 470                break;
 471        case SND_SOC_DAPM_PRE_PMD:
 472                ret = snd_soc_component_update_bits(component,
 473                        TAS2562_PWR_CTRL,
 474                        TAS2562_MODE_MASK,
 475                        TAS2562_SHUTDOWN);
 476                if (ret)
 477                        goto end;
 478                break;
 479        default:
 480                dev_err(tas2562->dev, "Not supported evevt\n");
 481                return -EINVAL;
 482        }
 483
 484end:
 485        if (ret < 0)
 486                return ret;
 487
 488        return 0;
 489}
 490
 491static int tas2562_volume_control_get(struct snd_kcontrol *kcontrol,
 492                                      struct snd_ctl_elem_value *ucontrol)
 493{
 494        struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
 495        struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component);
 496
 497        ucontrol->value.integer.value[0] = tas2562->volume_lvl;
 498        return 0;
 499}
 500
 501static int tas2562_volume_control_put(struct snd_kcontrol *kcontrol,
 502                                      struct snd_ctl_elem_value *ucontrol)
 503{
 504        struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
 505        struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component);
 506        int ret;
 507        u32 reg_val;
 508
 509        reg_val = float_vol_db_lookup[ucontrol->value.integer.value[0]/2];
 510        ret = snd_soc_component_write(component, TAS2562_DVC_CFG4,
 511                                      (reg_val & 0xff));
 512        if (ret)
 513                return ret;
 514        ret = snd_soc_component_write(component, TAS2562_DVC_CFG3,
 515                                      ((reg_val >> 8) & 0xff));
 516        if (ret)
 517                return ret;
 518        ret = snd_soc_component_write(component, TAS2562_DVC_CFG2,
 519                                      ((reg_val >> 16) & 0xff));
 520        if (ret)
 521                return ret;
 522        ret = snd_soc_component_write(component, TAS2562_DVC_CFG1,
 523                                      ((reg_val >> 24) & 0xff));
 524        if (ret)
 525                return ret;
 526
 527        tas2562->volume_lvl = ucontrol->value.integer.value[0];
 528
 529        return 0;
 530}
 531
 532/* Digital Volume Control. From 0 dB to -110 dB in 1 dB steps */
 533static const DECLARE_TLV_DB_SCALE(dvc_tlv, -11000, 100, 0);
 534
 535static DECLARE_TLV_DB_SCALE(tas2562_dac_tlv, 850, 50, 0);
 536
 537static const struct snd_kcontrol_new isense_switch =
 538        SOC_DAPM_SINGLE("Switch", TAS2562_PWR_CTRL, TAS2562_ISENSE_POWER_EN,
 539                        1, 1);
 540
 541static const struct snd_kcontrol_new vsense_switch =
 542        SOC_DAPM_SINGLE("Switch", TAS2562_PWR_CTRL, TAS2562_VSENSE_POWER_EN,
 543                        1, 1);
 544
 545static const struct snd_kcontrol_new tas2562_snd_controls[] = {
 546        SOC_SINGLE_TLV("Amp Gain Volume", TAS2562_PB_CFG1, 1, 0x1c, 0,
 547                       tas2562_dac_tlv),
 548        {
 549                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 550                .name = "Digital Volume Control",
 551                .index = 0,
 552                .tlv.p = dvc_tlv,
 553                .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,
 554                .info = snd_soc_info_volsw,
 555                .get = tas2562_volume_control_get,
 556                .put = tas2562_volume_control_put,
 557                .private_value = SOC_SINGLE_VALUE(TAS2562_DVC_CFG1, 0, 110, 0, 0),
 558        },
 559};
 560
 561static const struct snd_soc_dapm_widget tas2110_dapm_widgets[] = {
 562        SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0),
 563        SND_SOC_DAPM_MUX("ASI1 Sel", SND_SOC_NOPM, 0, 0, &tas2562_asi1_mux),
 564        SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas2562_dac_event,
 565                           SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
 566        SND_SOC_DAPM_OUTPUT("OUT"),
 567};
 568
 569static const struct snd_soc_dapm_route tas2110_audio_map[] = {
 570        {"ASI1 Sel", "I2C offset", "ASI1"},
 571        {"ASI1 Sel", "Left", "ASI1"},
 572        {"ASI1 Sel", "Right", "ASI1"},
 573        {"ASI1 Sel", "LeftRightDiv2", "ASI1"},
 574        { "DAC", NULL, "ASI1 Sel" },
 575        { "OUT", NULL, "DAC" },
 576};
 577
 578static const struct snd_soc_component_driver soc_component_dev_tas2110 = {
 579        .probe                  = tas2562_codec_probe,
 580        .suspend                = tas2562_suspend,
 581        .resume                 = tas2562_resume,
 582        .set_bias_level         = tas2562_set_bias_level,
 583        .controls               = tas2562_snd_controls,
 584        .num_controls           = ARRAY_SIZE(tas2562_snd_controls),
 585        .dapm_widgets           = tas2110_dapm_widgets,
 586        .num_dapm_widgets       = ARRAY_SIZE(tas2110_dapm_widgets),
 587        .dapm_routes            = tas2110_audio_map,
 588        .num_dapm_routes        = ARRAY_SIZE(tas2110_audio_map),
 589        .idle_bias_on           = 1,
 590        .use_pmdown_time        = 1,
 591        .endianness             = 1,
 592        .non_legacy_dai_naming  = 1,
 593};
 594
 595static const struct snd_soc_dapm_widget tas2562_dapm_widgets[] = {
 596        SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0),
 597        SND_SOC_DAPM_MUX("ASI1 Sel", SND_SOC_NOPM, 0, 0, &tas2562_asi1_mux),
 598        SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas2562_dac_event,
 599                           SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
 600        SND_SOC_DAPM_SWITCH("ISENSE", TAS2562_PWR_CTRL, 3, 1, &isense_switch),
 601        SND_SOC_DAPM_SWITCH("VSENSE", TAS2562_PWR_CTRL, 2, 1, &vsense_switch),
 602        SND_SOC_DAPM_SIGGEN("VMON"),
 603        SND_SOC_DAPM_SIGGEN("IMON"),
 604        SND_SOC_DAPM_OUTPUT("OUT"),
 605};
 606
 607static const struct snd_soc_dapm_route tas2562_audio_map[] = {
 608        {"ASI1 Sel", "I2C offset", "ASI1"},
 609        {"ASI1 Sel", "Left", "ASI1"},
 610        {"ASI1 Sel", "Right", "ASI1"},
 611        {"ASI1 Sel", "LeftRightDiv2", "ASI1"},
 612        { "DAC", NULL, "ASI1 Sel" },
 613        { "OUT", NULL, "DAC" },
 614        {"ISENSE", "Switch", "IMON"},
 615        {"VSENSE", "Switch", "VMON"},
 616};
 617
 618static const struct snd_soc_component_driver soc_component_dev_tas2562 = {
 619        .probe                  = tas2562_codec_probe,
 620        .suspend                = tas2562_suspend,
 621        .resume                 = tas2562_resume,
 622        .set_bias_level         = tas2562_set_bias_level,
 623        .controls               = tas2562_snd_controls,
 624        .num_controls           = ARRAY_SIZE(tas2562_snd_controls),
 625        .dapm_widgets           = tas2562_dapm_widgets,
 626        .num_dapm_widgets       = ARRAY_SIZE(tas2562_dapm_widgets),
 627        .dapm_routes            = tas2562_audio_map,
 628        .num_dapm_routes        = ARRAY_SIZE(tas2562_audio_map),
 629        .idle_bias_on           = 1,
 630        .use_pmdown_time        = 1,
 631        .endianness             = 1,
 632        .non_legacy_dai_naming  = 1,
 633};
 634
 635static const struct snd_soc_dai_ops tas2562_speaker_dai_ops = {
 636        .hw_params      = tas2562_hw_params,
 637        .set_fmt        = tas2562_set_dai_fmt,
 638        .set_tdm_slot   = tas2562_set_dai_tdm_slot,
 639        .mute_stream    = tas2562_mute,
 640        .no_capture_mute = 1,
 641};
 642
 643static struct snd_soc_dai_driver tas2562_dai[] = {
 644        {
 645                .name = "tas2562-amplifier",
 646                .id = 0,
 647                .playback = {
 648                        .stream_name    = "ASI1 Playback",
 649                        .channels_min   = 2,
 650                        .channels_max   = 2,
 651                        .rates      = SNDRV_PCM_RATE_8000_192000,
 652                        .formats    = TAS2562_FORMATS,
 653                },
 654                .capture = {
 655                        .stream_name    = "ASI1 Capture",
 656                        .channels_min   = 0,
 657                        .channels_max   = 2,
 658                        .rates          = SNDRV_PCM_RATE_8000_192000,
 659                        .formats        = TAS2562_FORMATS,
 660                },
 661                .ops = &tas2562_speaker_dai_ops,
 662        },
 663};
 664
 665static const struct regmap_range_cfg tas2562_ranges[] = {
 666        {
 667                .range_min = 0,
 668                .range_max = 5 * 128,
 669                .selector_reg = TAS2562_PAGE_CTRL,
 670                .selector_mask = 0xff,
 671                .selector_shift = 0,
 672                .window_start = 0,
 673                .window_len = 128,
 674        },
 675};
 676
 677static const struct reg_default tas2562_reg_defaults[] = {
 678        { TAS2562_PAGE_CTRL, 0x00 },
 679        { TAS2562_SW_RESET, 0x00 },
 680        { TAS2562_PWR_CTRL, 0x0e },
 681        { TAS2562_PB_CFG1, 0x20 },
 682        { TAS2562_TDM_CFG0, 0x09 },
 683        { TAS2562_TDM_CFG1, 0x02 },
 684        { TAS2562_DVC_CFG1, 0x40 },
 685        { TAS2562_DVC_CFG2, 0x40 },
 686        { TAS2562_DVC_CFG3, 0x00 },
 687        { TAS2562_DVC_CFG4, 0x00 },
 688};
 689
 690static const struct regmap_config tas2562_regmap_config = {
 691        .reg_bits = 8,
 692        .val_bits = 8,
 693
 694        .max_register = 5 * 128,
 695        .cache_type = REGCACHE_RBTREE,
 696        .reg_defaults = tas2562_reg_defaults,
 697        .num_reg_defaults = ARRAY_SIZE(tas2562_reg_defaults),
 698        .ranges = tas2562_ranges,
 699        .num_ranges = ARRAY_SIZE(tas2562_ranges),
 700};
 701
 702static int tas2562_parse_dt(struct tas2562_data *tas2562)
 703{
 704        struct device *dev = tas2562->dev;
 705        int ret = 0;
 706
 707        tas2562->sdz_gpio = devm_gpiod_get_optional(dev, "shutdown", GPIOD_OUT_HIGH);
 708        if (IS_ERR(tas2562->sdz_gpio)) {
 709                if (PTR_ERR(tas2562->sdz_gpio) == -EPROBE_DEFER)
 710                        return -EPROBE_DEFER;
 711
 712                tas2562->sdz_gpio = NULL;
 713        }
 714
 715        /*
 716         * The shut-down property is deprecated but needs to be checked for
 717         * backwards compatibility.
 718         */
 719        if (tas2562->sdz_gpio == NULL) {
 720                tas2562->sdz_gpio = devm_gpiod_get_optional(dev, "shut-down",
 721                                                              GPIOD_OUT_HIGH);
 722                if (IS_ERR(tas2562->sdz_gpio))
 723                        if (PTR_ERR(tas2562->sdz_gpio) == -EPROBE_DEFER)
 724                                return -EPROBE_DEFER;
 725
 726                tas2562->sdz_gpio = NULL;
 727        }
 728
 729        if (tas2562->model_id == TAS2110)
 730                return ret;
 731
 732        ret = fwnode_property_read_u32(dev->fwnode, "ti,imon-slot-no",
 733                        &tas2562->i_sense_slot);
 734        if (ret) {
 735                dev_err(dev, "Property %s is missing setting default slot\n",
 736                        "ti,imon-slot-no");
 737                tas2562->i_sense_slot = 0;
 738        }
 739
 740
 741        ret = fwnode_property_read_u32(dev->fwnode, "ti,vmon-slot-no",
 742                        &tas2562->v_sense_slot);
 743        if (ret) {
 744                dev_info(dev, "Property %s is missing setting default slot\n",
 745                        "ti,vmon-slot-no");
 746                tas2562->v_sense_slot = 2;
 747        }
 748
 749        if (tas2562->v_sense_slot < tas2562->i_sense_slot) {
 750                dev_err(dev, "Vsense slot must be greater than Isense slot\n");
 751                return -EINVAL;
 752        }
 753
 754        return ret;
 755}
 756
 757static int tas2562_probe(struct i2c_client *client,
 758                         const struct i2c_device_id *id)
 759{
 760        struct device *dev = &client->dev;
 761        struct tas2562_data *data;
 762        int ret;
 763
 764        data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
 765        if (!data)
 766                return -ENOMEM;
 767
 768        data->client = client;
 769        data->dev = &client->dev;
 770        data->model_id = id->driver_data;
 771
 772        tas2562_parse_dt(data);
 773
 774        data->regmap = devm_regmap_init_i2c(client, &tas2562_regmap_config);
 775        if (IS_ERR(data->regmap)) {
 776                ret = PTR_ERR(data->regmap);
 777                dev_err(dev, "failed to allocate register map: %d\n", ret);
 778                return ret;
 779        }
 780
 781        dev_set_drvdata(&client->dev, data);
 782
 783        if (data->model_id == TAS2110)
 784                return devm_snd_soc_register_component(dev,
 785                                                       &soc_component_dev_tas2110,
 786                                                       tas2562_dai,
 787                                                       ARRAY_SIZE(tas2562_dai));
 788
 789        return devm_snd_soc_register_component(dev, &soc_component_dev_tas2562,
 790                                               tas2562_dai,
 791                                               ARRAY_SIZE(tas2562_dai));
 792
 793}
 794
 795static const struct i2c_device_id tas2562_id[] = {
 796        { "tas2562", TAS2562 },
 797        { "tas2563", TAS2563 },
 798        { "tas2564", TAS2564 },
 799        { "tas2110", TAS2110 },
 800        { }
 801};
 802MODULE_DEVICE_TABLE(i2c, tas2562_id);
 803
 804#ifdef CONFIG_OF
 805static const struct of_device_id tas2562_of_match[] = {
 806        { .compatible = "ti,tas2562", },
 807        { .compatible = "ti,tas2563", },
 808        { .compatible = "ti,tas2564", },
 809        { .compatible = "ti,tas2110", },
 810        { },
 811};
 812MODULE_DEVICE_TABLE(of, tas2562_of_match);
 813#endif
 814
 815static struct i2c_driver tas2562_i2c_driver = {
 816        .driver = {
 817                .name = "tas2562",
 818                .of_match_table = of_match_ptr(tas2562_of_match),
 819        },
 820        .probe = tas2562_probe,
 821        .id_table = tas2562_id,
 822};
 823
 824module_i2c_driver(tas2562_i2c_driver);
 825
 826MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
 827MODULE_DESCRIPTION("TAS2562 Audio amplifier driver");
 828MODULE_LICENSE("GPL");
 829