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                        tx_mask &= ~(1 << right_slot);
 204                }
 205        }
 206
 207        slots_cfg = (right_slot << TAS2562_RIGHT_SLOT_SHIFT) | left_slot;
 208
 209        ret = snd_soc_component_write(component, TAS2562_TDM_CFG3, slots_cfg);
 210        if (ret < 0)
 211                return ret;
 212
 213        switch (slot_width) {
 214        case 16:
 215                ret = snd_soc_component_update_bits(component,
 216                                                    TAS2562_TDM_CFG2,
 217                                                    TAS2562_TDM_CFG2_RXLEN_MASK,
 218                                                    TAS2562_TDM_CFG2_RXLEN_16B);
 219                break;
 220        case 24:
 221                ret = snd_soc_component_update_bits(component,
 222                                                    TAS2562_TDM_CFG2,
 223                                                    TAS2562_TDM_CFG2_RXLEN_MASK,
 224                                                    TAS2562_TDM_CFG2_RXLEN_24B);
 225                break;
 226        case 32:
 227                ret = snd_soc_component_update_bits(component,
 228                                                    TAS2562_TDM_CFG2,
 229                                                    TAS2562_TDM_CFG2_RXLEN_MASK,
 230                                                    TAS2562_TDM_CFG2_RXLEN_32B);
 231                break;
 232
 233        case 0:
 234                /* Do not change slot width */
 235                break;
 236        default:
 237                dev_err(tas2562->dev, "slot width not supported");
 238                ret = -EINVAL;
 239        }
 240
 241        if (ret < 0)
 242                return ret;
 243
 244        ret = snd_soc_component_update_bits(component, TAS2562_TDM_CFG5,
 245                                            TAS2562_TDM_CFG5_VSNS_SLOT_MASK,
 246                                            tas2562->v_sense_slot);
 247        if (ret < 0)
 248                return ret;
 249
 250        ret = snd_soc_component_update_bits(component, TAS2562_TDM_CFG6,
 251                                            TAS2562_TDM_CFG6_ISNS_SLOT_MASK,
 252                                            tas2562->i_sense_slot);
 253        if (ret < 0)
 254                return ret;
 255
 256        return 0;
 257}
 258
 259static int tas2562_set_bitwidth(struct tas2562_data *tas2562, int bitwidth)
 260{
 261        int ret;
 262        int val;
 263        int sense_en;
 264
 265        switch (bitwidth) {
 266        case SNDRV_PCM_FORMAT_S16_LE:
 267                snd_soc_component_update_bits(tas2562->component,
 268                                              TAS2562_TDM_CFG2,
 269                                              TAS2562_TDM_CFG2_RXWLEN_MASK,
 270                                              TAS2562_TDM_CFG2_RXWLEN_16B);
 271                break;
 272        case SNDRV_PCM_FORMAT_S24_LE:
 273                snd_soc_component_update_bits(tas2562->component,
 274                                              TAS2562_TDM_CFG2,
 275                                              TAS2562_TDM_CFG2_RXWLEN_MASK,
 276                                              TAS2562_TDM_CFG2_RXWLEN_24B);
 277                break;
 278        case SNDRV_PCM_FORMAT_S32_LE:
 279                snd_soc_component_update_bits(tas2562->component,
 280                                              TAS2562_TDM_CFG2,
 281                                              TAS2562_TDM_CFG2_RXWLEN_MASK,
 282                                              TAS2562_TDM_CFG2_RXWLEN_32B);
 283                break;
 284
 285        default:
 286                dev_info(tas2562->dev, "Unsupported bitwidth format\n");
 287                return -EINVAL;
 288        }
 289
 290        val = snd_soc_component_read(tas2562->component, TAS2562_PWR_CTRL);
 291        if (val < 0)
 292                return val;
 293
 294        if (val & (1 << TAS2562_VSENSE_POWER_EN))
 295                sense_en = 0;
 296        else
 297                sense_en = TAS2562_TDM_CFG5_VSNS_EN;
 298
 299        ret = snd_soc_component_update_bits(tas2562->component, TAS2562_TDM_CFG5,
 300                TAS2562_TDM_CFG5_VSNS_EN, sense_en);
 301        if (ret < 0)
 302                return ret;
 303
 304        if (val & (1 << TAS2562_ISENSE_POWER_EN))
 305                sense_en = 0;
 306        else
 307                sense_en = TAS2562_TDM_CFG6_ISNS_EN;
 308
 309        ret = snd_soc_component_update_bits(tas2562->component, TAS2562_TDM_CFG6,
 310                TAS2562_TDM_CFG6_ISNS_EN, sense_en);
 311        if (ret < 0)
 312                return ret;
 313
 314        return 0;
 315}
 316
 317static int tas2562_hw_params(struct snd_pcm_substream *substream,
 318                             struct snd_pcm_hw_params *params,
 319                             struct snd_soc_dai *dai)
 320{
 321        struct snd_soc_component *component = dai->component;
 322        struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component);
 323        int ret;
 324
 325        ret = tas2562_set_bitwidth(tas2562, params_format(params));
 326        if (ret) {
 327                dev_err(tas2562->dev, "set bitwidth failed, %d\n", ret);
 328                return ret;
 329        }
 330
 331        ret = tas2562_set_samplerate(tas2562, params_rate(params));
 332        if (ret)
 333                dev_err(tas2562->dev, "set sample rate failed, %d\n", ret);
 334
 335        return ret;
 336}
 337
 338static int tas2562_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 339{
 340        struct snd_soc_component *component = dai->component;
 341        struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component);
 342        u8 asi_cfg_1 = 0;
 343        u8 tdm_rx_start_slot = 0;
 344        int ret;
 345
 346        switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
 347        case SND_SOC_DAIFMT_NB_NF:
 348                asi_cfg_1 = 0;
 349                break;
 350        case SND_SOC_DAIFMT_IB_NF:
 351                asi_cfg_1 |= TAS2562_TDM_CFG1_RX_FALLING;
 352                break;
 353        default:
 354                dev_err(tas2562->dev, "ASI format Inverse is not found\n");
 355                return -EINVAL;
 356        }
 357
 358        ret = snd_soc_component_update_bits(component, TAS2562_TDM_CFG1,
 359                                            TAS2562_TDM_CFG1_RX_EDGE_MASK,
 360                                            asi_cfg_1);
 361        if (ret < 0) {
 362                dev_err(tas2562->dev, "Failed to set RX edge\n");
 363                return ret;
 364        }
 365        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
 366        case SND_SOC_DAIFMT_LEFT_J:
 367        case SND_SOC_DAIFMT_DSP_B:
 368                tdm_rx_start_slot = 0;
 369                break;
 370        case SND_SOC_DAIFMT_I2S:
 371        case SND_SOC_DAIFMT_DSP_A:
 372                tdm_rx_start_slot = 1;
 373                break;
 374        default:
 375                dev_err(tas2562->dev,
 376                        "DAI Format is not found, fmt=0x%x\n", fmt);
 377                return -EINVAL;
 378        }
 379
 380        ret = snd_soc_component_update_bits(component, TAS2562_TDM_CFG1,
 381                                TAS2562_RX_OFF_MASK, (tdm_rx_start_slot << 1));
 382        if (ret < 0)
 383                return ret;
 384
 385        return 0;
 386}
 387
 388static int tas2562_mute(struct snd_soc_dai *dai, int mute, int direction)
 389{
 390        struct snd_soc_component *component = dai->component;
 391
 392        return snd_soc_component_update_bits(component, TAS2562_PWR_CTRL,
 393                                             TAS2562_MODE_MASK,
 394                                             mute ? TAS2562_MUTE : 0);
 395}
 396
 397static int tas2562_codec_probe(struct snd_soc_component *component)
 398{
 399        struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component);
 400        int ret;
 401
 402        tas2562->component = component;
 403
 404        if (tas2562->sdz_gpio)
 405                gpiod_set_value_cansleep(tas2562->sdz_gpio, 1);
 406
 407        ret = snd_soc_component_update_bits(component, TAS2562_PWR_CTRL,
 408                                            TAS2562_MODE_MASK, TAS2562_MUTE);
 409        if (ret < 0)
 410                return ret;
 411
 412        return 0;
 413}
 414
 415#ifdef CONFIG_PM
 416static int tas2562_suspend(struct snd_soc_component *component)
 417{
 418        struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component);
 419
 420        regcache_cache_only(tas2562->regmap, true);
 421        regcache_mark_dirty(tas2562->regmap);
 422
 423        if (tas2562->sdz_gpio)
 424                gpiod_set_value_cansleep(tas2562->sdz_gpio, 0);
 425
 426        return 0;
 427}
 428
 429static int tas2562_resume(struct snd_soc_component *component)
 430{
 431        struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component);
 432
 433        if (tas2562->sdz_gpio)
 434                gpiod_set_value_cansleep(tas2562->sdz_gpio, 1);
 435
 436        regcache_cache_only(tas2562->regmap, false);
 437
 438        return regcache_sync(tas2562->regmap);
 439}
 440#else
 441#define tas2562_suspend NULL
 442#define tas2562_resume NULL
 443#endif
 444
 445static const char * const tas2562_ASI1_src[] = {
 446        "I2C offset", "Left", "Right", "LeftRightDiv2",
 447};
 448
 449static SOC_ENUM_SINGLE_DECL(tas2562_ASI1_src_enum, TAS2562_TDM_CFG2, 4,
 450                            tas2562_ASI1_src);
 451
 452static const struct snd_kcontrol_new tas2562_asi1_mux =
 453        SOC_DAPM_ENUM("ASI1 Source", tas2562_ASI1_src_enum);
 454
 455static int tas2562_dac_event(struct snd_soc_dapm_widget *w,
 456                             struct snd_kcontrol *kcontrol, int event)
 457{
 458        struct snd_soc_component *component =
 459                                        snd_soc_dapm_to_component(w->dapm);
 460        struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component);
 461        int ret;
 462
 463        switch (event) {
 464        case SND_SOC_DAPM_POST_PMU:
 465                ret = snd_soc_component_update_bits(component,
 466                        TAS2562_PWR_CTRL,
 467                        TAS2562_MODE_MASK,
 468                        TAS2562_MUTE);
 469                if (ret)
 470                        goto end;
 471                break;
 472        case SND_SOC_DAPM_PRE_PMD:
 473                ret = snd_soc_component_update_bits(component,
 474                        TAS2562_PWR_CTRL,
 475                        TAS2562_MODE_MASK,
 476                        TAS2562_SHUTDOWN);
 477                if (ret)
 478                        goto end;
 479                break;
 480        default:
 481                dev_err(tas2562->dev, "Not supported evevt\n");
 482                return -EINVAL;
 483        }
 484
 485end:
 486        if (ret < 0)
 487                return ret;
 488
 489        return 0;
 490}
 491
 492static int tas2562_volume_control_get(struct snd_kcontrol *kcontrol,
 493                                      struct snd_ctl_elem_value *ucontrol)
 494{
 495        struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
 496        struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component);
 497
 498        ucontrol->value.integer.value[0] = tas2562->volume_lvl;
 499        return 0;
 500}
 501
 502static int tas2562_volume_control_put(struct snd_kcontrol *kcontrol,
 503                                      struct snd_ctl_elem_value *ucontrol)
 504{
 505        struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
 506        struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component);
 507        int ret;
 508        u32 reg_val;
 509
 510        reg_val = float_vol_db_lookup[ucontrol->value.integer.value[0]/2];
 511        ret = snd_soc_component_write(component, TAS2562_DVC_CFG4,
 512                                      (reg_val & 0xff));
 513        if (ret)
 514                return ret;
 515        ret = snd_soc_component_write(component, TAS2562_DVC_CFG3,
 516                                      ((reg_val >> 8) & 0xff));
 517        if (ret)
 518                return ret;
 519        ret = snd_soc_component_write(component, TAS2562_DVC_CFG2,
 520                                      ((reg_val >> 16) & 0xff));
 521        if (ret)
 522                return ret;
 523        ret = snd_soc_component_write(component, TAS2562_DVC_CFG1,
 524                                      ((reg_val >> 24) & 0xff));
 525        if (ret)
 526                return ret;
 527
 528        tas2562->volume_lvl = ucontrol->value.integer.value[0];
 529
 530        return ret;
 531}
 532
 533/* Digital Volume Control. From 0 dB to -110 dB in 1 dB steps */
 534static const DECLARE_TLV_DB_SCALE(dvc_tlv, -11000, 100, 0);
 535
 536static DECLARE_TLV_DB_SCALE(tas2562_dac_tlv, 850, 50, 0);
 537
 538static const struct snd_kcontrol_new isense_switch =
 539        SOC_DAPM_SINGLE("Switch", TAS2562_PWR_CTRL, TAS2562_ISENSE_POWER_EN,
 540                        1, 1);
 541
 542static const struct snd_kcontrol_new vsense_switch =
 543        SOC_DAPM_SINGLE("Switch", TAS2562_PWR_CTRL, TAS2562_VSENSE_POWER_EN,
 544                        1, 1);
 545
 546static const struct snd_kcontrol_new tas2562_snd_controls[] = {
 547        SOC_SINGLE_TLV("Amp Gain Volume", TAS2562_PB_CFG1, 1, 0x1c, 0,
 548                       tas2562_dac_tlv),
 549        {
 550                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 551                .name = "Digital Volume Control",
 552                .index = 0,
 553                .tlv.p = dvc_tlv,
 554                .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,
 555                .info = snd_soc_info_volsw,
 556                .get = tas2562_volume_control_get,
 557                .put = tas2562_volume_control_put,
 558                .private_value = SOC_SINGLE_VALUE(TAS2562_DVC_CFG1, 0, 110, 0, 0),
 559        },
 560};
 561
 562static const struct snd_soc_dapm_widget tas2110_dapm_widgets[] = {
 563        SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0),
 564        SND_SOC_DAPM_MUX("ASI1 Sel", SND_SOC_NOPM, 0, 0, &tas2562_asi1_mux),
 565        SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas2562_dac_event,
 566                           SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
 567        SND_SOC_DAPM_OUTPUT("OUT"),
 568};
 569
 570static const struct snd_soc_dapm_route tas2110_audio_map[] = {
 571        {"ASI1 Sel", "I2C offset", "ASI1"},
 572        {"ASI1 Sel", "Left", "ASI1"},
 573        {"ASI1 Sel", "Right", "ASI1"},
 574        {"ASI1 Sel", "LeftRightDiv2", "ASI1"},
 575        { "DAC", NULL, "ASI1 Sel" },
 576        { "OUT", NULL, "DAC" },
 577};
 578
 579static const struct snd_soc_component_driver soc_component_dev_tas2110 = {
 580        .probe                  = tas2562_codec_probe,
 581        .suspend                = tas2562_suspend,
 582        .resume                 = tas2562_resume,
 583        .set_bias_level         = tas2562_set_bias_level,
 584        .controls               = tas2562_snd_controls,
 585        .num_controls           = ARRAY_SIZE(tas2562_snd_controls),
 586        .dapm_widgets           = tas2110_dapm_widgets,
 587        .num_dapm_widgets       = ARRAY_SIZE(tas2110_dapm_widgets),
 588        .dapm_routes            = tas2110_audio_map,
 589        .num_dapm_routes        = ARRAY_SIZE(tas2110_audio_map),
 590        .idle_bias_on           = 1,
 591        .use_pmdown_time        = 1,
 592        .endianness             = 1,
 593        .non_legacy_dai_naming  = 1,
 594};
 595
 596static const struct snd_soc_dapm_widget tas2562_dapm_widgets[] = {
 597        SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0),
 598        SND_SOC_DAPM_MUX("ASI1 Sel", SND_SOC_NOPM, 0, 0, &tas2562_asi1_mux),
 599        SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas2562_dac_event,
 600                           SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
 601        SND_SOC_DAPM_SWITCH("ISENSE", TAS2562_PWR_CTRL, 3, 1, &isense_switch),
 602        SND_SOC_DAPM_SWITCH("VSENSE", TAS2562_PWR_CTRL, 2, 1, &vsense_switch),
 603        SND_SOC_DAPM_SIGGEN("VMON"),
 604        SND_SOC_DAPM_SIGGEN("IMON"),
 605        SND_SOC_DAPM_OUTPUT("OUT"),
 606};
 607
 608static const struct snd_soc_dapm_route tas2562_audio_map[] = {
 609        {"ASI1 Sel", "I2C offset", "ASI1"},
 610        {"ASI1 Sel", "Left", "ASI1"},
 611        {"ASI1 Sel", "Right", "ASI1"},
 612        {"ASI1 Sel", "LeftRightDiv2", "ASI1"},
 613        { "DAC", NULL, "ASI1 Sel" },
 614        { "OUT", NULL, "DAC" },
 615        {"ISENSE", "Switch", "IMON"},
 616        {"VSENSE", "Switch", "VMON"},
 617};
 618
 619static const struct snd_soc_component_driver soc_component_dev_tas2562 = {
 620        .probe                  = tas2562_codec_probe,
 621        .suspend                = tas2562_suspend,
 622        .resume                 = tas2562_resume,
 623        .set_bias_level         = tas2562_set_bias_level,
 624        .controls               = tas2562_snd_controls,
 625        .num_controls           = ARRAY_SIZE(tas2562_snd_controls),
 626        .dapm_widgets           = tas2562_dapm_widgets,
 627        .num_dapm_widgets       = ARRAY_SIZE(tas2562_dapm_widgets),
 628        .dapm_routes            = tas2562_audio_map,
 629        .num_dapm_routes        = ARRAY_SIZE(tas2562_audio_map),
 630        .idle_bias_on           = 1,
 631        .use_pmdown_time        = 1,
 632        .endianness             = 1,
 633        .non_legacy_dai_naming  = 1,
 634};
 635
 636static const struct snd_soc_dai_ops tas2562_speaker_dai_ops = {
 637        .hw_params      = tas2562_hw_params,
 638        .set_fmt        = tas2562_set_dai_fmt,
 639        .set_tdm_slot   = tas2562_set_dai_tdm_slot,
 640        .mute_stream    = tas2562_mute,
 641        .no_capture_mute = 1,
 642};
 643
 644static struct snd_soc_dai_driver tas2562_dai[] = {
 645        {
 646                .name = "tas2562-amplifier",
 647                .id = 0,
 648                .playback = {
 649                        .stream_name    = "ASI1 Playback",
 650                        .channels_min   = 2,
 651                        .channels_max   = 2,
 652                        .rates      = SNDRV_PCM_RATE_8000_192000,
 653                        .formats    = TAS2562_FORMATS,
 654                },
 655                .capture = {
 656                        .stream_name    = "ASI1 Capture",
 657                        .channels_min   = 0,
 658                        .channels_max   = 2,
 659                        .rates          = SNDRV_PCM_RATE_8000_192000,
 660                        .formats        = TAS2562_FORMATS,
 661                },
 662                .ops = &tas2562_speaker_dai_ops,
 663        },
 664};
 665
 666static const struct regmap_range_cfg tas2562_ranges[] = {
 667        {
 668                .range_min = 0,
 669                .range_max = 5 * 128,
 670                .selector_reg = TAS2562_PAGE_CTRL,
 671                .selector_mask = 0xff,
 672                .selector_shift = 0,
 673                .window_start = 0,
 674                .window_len = 128,
 675        },
 676};
 677
 678static const struct reg_default tas2562_reg_defaults[] = {
 679        { TAS2562_PAGE_CTRL, 0x00 },
 680        { TAS2562_SW_RESET, 0x00 },
 681        { TAS2562_PWR_CTRL, 0x0e },
 682        { TAS2562_PB_CFG1, 0x20 },
 683        { TAS2562_TDM_CFG0, 0x09 },
 684        { TAS2562_TDM_CFG1, 0x02 },
 685        { TAS2562_DVC_CFG1, 0x40 },
 686        { TAS2562_DVC_CFG2, 0x40 },
 687        { TAS2562_DVC_CFG3, 0x00 },
 688        { TAS2562_DVC_CFG4, 0x00 },
 689};
 690
 691static const struct regmap_config tas2562_regmap_config = {
 692        .reg_bits = 8,
 693        .val_bits = 8,
 694
 695        .max_register = 5 * 128,
 696        .cache_type = REGCACHE_RBTREE,
 697        .reg_defaults = tas2562_reg_defaults,
 698        .num_reg_defaults = ARRAY_SIZE(tas2562_reg_defaults),
 699        .ranges = tas2562_ranges,
 700        .num_ranges = ARRAY_SIZE(tas2562_ranges),
 701};
 702
 703static int tas2562_parse_dt(struct tas2562_data *tas2562)
 704{
 705        struct device *dev = tas2562->dev;
 706        int ret = 0;
 707
 708        tas2562->sdz_gpio = devm_gpiod_get_optional(dev, "shutdown", GPIOD_OUT_HIGH);
 709        if (IS_ERR(tas2562->sdz_gpio)) {
 710                if (PTR_ERR(tas2562->sdz_gpio) == -EPROBE_DEFER)
 711                        return -EPROBE_DEFER;
 712
 713                tas2562->sdz_gpio = NULL;
 714        }
 715
 716        /*
 717         * The shut-down property is deprecated but needs to be checked for
 718         * backwards compatibility.
 719         */
 720        if (tas2562->sdz_gpio == NULL) {
 721                tas2562->sdz_gpio = devm_gpiod_get_optional(dev, "shut-down",
 722                                                              GPIOD_OUT_HIGH);
 723                if (IS_ERR(tas2562->sdz_gpio))
 724                        if (PTR_ERR(tas2562->sdz_gpio) == -EPROBE_DEFER)
 725                                return -EPROBE_DEFER;
 726
 727                tas2562->sdz_gpio = NULL;
 728        }
 729
 730        if (tas2562->model_id == TAS2110)
 731                return ret;
 732
 733        ret = fwnode_property_read_u32(dev->fwnode, "ti,imon-slot-no",
 734                        &tas2562->i_sense_slot);
 735        if (ret) {
 736                dev_err(dev, "Property %s is missing setting default slot\n",
 737                        "ti,imon-slot-no");
 738                tas2562->i_sense_slot = 0;
 739        }
 740
 741
 742        ret = fwnode_property_read_u32(dev->fwnode, "ti,vmon-slot-no",
 743                        &tas2562->v_sense_slot);
 744        if (ret) {
 745                dev_info(dev, "Property %s is missing setting default slot\n",
 746                        "ti,vmon-slot-no");
 747                tas2562->v_sense_slot = 2;
 748        }
 749
 750        if (tas2562->v_sense_slot < tas2562->i_sense_slot) {
 751                dev_err(dev, "Vsense slot must be greater than Isense slot\n");
 752                return -EINVAL;
 753        }
 754
 755        return ret;
 756}
 757
 758static int tas2562_probe(struct i2c_client *client,
 759                         const struct i2c_device_id *id)
 760{
 761        struct device *dev = &client->dev;
 762        struct tas2562_data *data;
 763        int ret;
 764
 765        data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
 766        if (!data)
 767                return -ENOMEM;
 768
 769        data->client = client;
 770        data->dev = &client->dev;
 771        data->model_id = id->driver_data;
 772
 773        tas2562_parse_dt(data);
 774
 775        data->regmap = devm_regmap_init_i2c(client, &tas2562_regmap_config);
 776        if (IS_ERR(data->regmap)) {
 777                ret = PTR_ERR(data->regmap);
 778                dev_err(dev, "failed to allocate register map: %d\n", ret);
 779                return ret;
 780        }
 781
 782        dev_set_drvdata(&client->dev, data);
 783
 784        if (data->model_id == TAS2110)
 785                return devm_snd_soc_register_component(dev,
 786                                                       &soc_component_dev_tas2110,
 787                                                       tas2562_dai,
 788                                                       ARRAY_SIZE(tas2562_dai));
 789
 790        return devm_snd_soc_register_component(dev, &soc_component_dev_tas2562,
 791                                               tas2562_dai,
 792                                               ARRAY_SIZE(tas2562_dai));
 793
 794}
 795
 796static const struct i2c_device_id tas2562_id[] = {
 797        { "tas2562", TAS2562 },
 798        { "tas2563", TAS2563 },
 799        { "tas2564", TAS2564 },
 800        { "tas2110", TAS2110 },
 801        { }
 802};
 803MODULE_DEVICE_TABLE(i2c, tas2562_id);
 804
 805#ifdef CONFIG_OF
 806static const struct of_device_id tas2562_of_match[] = {
 807        { .compatible = "ti,tas2562", },
 808        { .compatible = "ti,tas2563", },
 809        { .compatible = "ti,tas2564", },
 810        { .compatible = "ti,tas2110", },
 811        { },
 812};
 813MODULE_DEVICE_TABLE(of, tas2562_of_match);
 814#endif
 815
 816static struct i2c_driver tas2562_i2c_driver = {
 817        .driver = {
 818                .name = "tas2562",
 819                .of_match_table = of_match_ptr(tas2562_of_match),
 820        },
 821        .probe = tas2562_probe,
 822        .id_table = tas2562_id,
 823};
 824
 825module_i2c_driver(tas2562_i2c_driver);
 826
 827MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
 828MODULE_DESCRIPTION("TAS2562 Audio amplifier driver");
 829MODULE_LICENSE("GPL");
 830