Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 //
0003 // Driver for the Texas Instruments TAS2764 CODEC
0004 // Copyright (C) 2020 Texas Instruments Inc.
0005 
0006 #include <linux/module.h>
0007 #include <linux/moduleparam.h>
0008 #include <linux/err.h>
0009 #include <linux/init.h>
0010 #include <linux/delay.h>
0011 #include <linux/pm.h>
0012 #include <linux/i2c.h>
0013 #include <linux/gpio.h>
0014 #include <linux/gpio/consumer.h>
0015 #include <linux/regulator/consumer.h>
0016 #include <linux/regmap.h>
0017 #include <linux/of.h>
0018 #include <linux/of_gpio.h>
0019 #include <linux/slab.h>
0020 #include <sound/soc.h>
0021 #include <sound/pcm.h>
0022 #include <sound/pcm_params.h>
0023 #include <sound/initval.h>
0024 #include <sound/tlv.h>
0025 
0026 #include "tas2764.h"
0027 
0028 struct tas2764_priv {
0029     struct snd_soc_component *component;
0030     struct gpio_desc *reset_gpio;
0031     struct gpio_desc *sdz_gpio;
0032     struct regmap *regmap;
0033     struct device *dev;
0034     
0035     int v_sense_slot;
0036     int i_sense_slot;
0037 };
0038 
0039 static void tas2764_reset(struct tas2764_priv *tas2764)
0040 {
0041     if (tas2764->reset_gpio) {
0042         gpiod_set_value_cansleep(tas2764->reset_gpio, 0);
0043         msleep(20);
0044         gpiod_set_value_cansleep(tas2764->reset_gpio, 1);
0045         usleep_range(1000, 2000);
0046     }
0047 
0048     snd_soc_component_write(tas2764->component, TAS2764_SW_RST,
0049                 TAS2764_RST);
0050     usleep_range(1000, 2000);
0051 }
0052 
0053 static int tas2764_set_bias_level(struct snd_soc_component *component,
0054                  enum snd_soc_bias_level level)
0055 {
0056     struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component);
0057 
0058     switch (level) {
0059     case SND_SOC_BIAS_ON:
0060         snd_soc_component_update_bits(component, TAS2764_PWR_CTRL,
0061                           TAS2764_PWR_CTRL_MASK,
0062                           TAS2764_PWR_CTRL_ACTIVE);
0063         break;
0064     case SND_SOC_BIAS_STANDBY:
0065     case SND_SOC_BIAS_PREPARE:
0066         snd_soc_component_update_bits(component, TAS2764_PWR_CTRL,
0067                           TAS2764_PWR_CTRL_MASK,
0068                           TAS2764_PWR_CTRL_MUTE);
0069         break;
0070     case SND_SOC_BIAS_OFF:
0071         snd_soc_component_update_bits(component, TAS2764_PWR_CTRL,
0072                           TAS2764_PWR_CTRL_MASK,
0073                           TAS2764_PWR_CTRL_SHUTDOWN);
0074         break;
0075 
0076     default:
0077         dev_err(tas2764->dev,
0078                 "wrong power level setting %d\n", level);
0079         return -EINVAL;
0080     }
0081 
0082     return 0;
0083 }
0084 
0085 #ifdef CONFIG_PM
0086 static int tas2764_codec_suspend(struct snd_soc_component *component)
0087 {
0088     struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component);
0089     int ret;
0090 
0091     ret = snd_soc_component_update_bits(component, TAS2764_PWR_CTRL,
0092                         TAS2764_PWR_CTRL_MASK,
0093                         TAS2764_PWR_CTRL_SHUTDOWN);
0094 
0095     if (ret < 0)
0096         return ret;
0097 
0098     if (tas2764->sdz_gpio)
0099         gpiod_set_value_cansleep(tas2764->sdz_gpio, 0);
0100 
0101     regcache_cache_only(tas2764->regmap, true);
0102     regcache_mark_dirty(tas2764->regmap);
0103 
0104     return 0;
0105 }
0106 
0107 static int tas2764_codec_resume(struct snd_soc_component *component)
0108 {
0109     struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component);
0110     int ret;
0111 
0112     if (tas2764->sdz_gpio) {
0113         gpiod_set_value_cansleep(tas2764->sdz_gpio, 1);
0114         usleep_range(1000, 2000);
0115     }
0116 
0117     ret = snd_soc_component_update_bits(component, TAS2764_PWR_CTRL,
0118                         TAS2764_PWR_CTRL_MASK,
0119                         TAS2764_PWR_CTRL_ACTIVE);
0120 
0121     if (ret < 0)
0122         return ret;
0123 
0124     regcache_cache_only(tas2764->regmap, false);
0125 
0126     return regcache_sync(tas2764->regmap);
0127 }
0128 #else
0129 #define tas2764_codec_suspend NULL
0130 #define tas2764_codec_resume NULL
0131 #endif
0132 
0133 static const char * const tas2764_ASI1_src[] = {
0134     "I2C offset", "Left", "Right", "LeftRightDiv2",
0135 };
0136 
0137 static SOC_ENUM_SINGLE_DECL(
0138     tas2764_ASI1_src_enum, TAS2764_TDM_CFG2, TAS2764_TDM_CFG2_SCFG_SHIFT,
0139     tas2764_ASI1_src);
0140 
0141 static const struct snd_kcontrol_new tas2764_asi1_mux =
0142     SOC_DAPM_ENUM("ASI1 Source", tas2764_ASI1_src_enum);
0143 
0144 static int tas2764_dac_event(struct snd_soc_dapm_widget *w,
0145                  struct snd_kcontrol *kcontrol, int event)
0146 {
0147     struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
0148     struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component);
0149     int ret;
0150 
0151     switch (event) {
0152     case SND_SOC_DAPM_POST_PMU:
0153         ret = snd_soc_component_update_bits(component, TAS2764_PWR_CTRL,
0154                             TAS2764_PWR_CTRL_MASK,
0155                             TAS2764_PWR_CTRL_MUTE);
0156         break;
0157     case SND_SOC_DAPM_PRE_PMD:
0158         ret = snd_soc_component_update_bits(component, TAS2764_PWR_CTRL,
0159                             TAS2764_PWR_CTRL_MASK,
0160                             TAS2764_PWR_CTRL_SHUTDOWN);
0161         break;
0162     default:
0163         dev_err(tas2764->dev, "Unsupported event\n");
0164         return -EINVAL;
0165     }
0166 
0167     if (ret < 0)
0168         return ret;
0169 
0170     return 0;
0171 }
0172 
0173 static const struct snd_kcontrol_new isense_switch =
0174     SOC_DAPM_SINGLE("Switch", TAS2764_PWR_CTRL, TAS2764_ISENSE_POWER_EN, 1, 1);
0175 static const struct snd_kcontrol_new vsense_switch =
0176     SOC_DAPM_SINGLE("Switch", TAS2764_PWR_CTRL, TAS2764_VSENSE_POWER_EN, 1, 1);
0177 
0178 static const struct snd_soc_dapm_widget tas2764_dapm_widgets[] = {
0179     SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0),
0180     SND_SOC_DAPM_MUX("ASI1 Sel", SND_SOC_NOPM, 0, 0, &tas2764_asi1_mux),
0181     SND_SOC_DAPM_SWITCH("ISENSE", TAS2764_PWR_CTRL, TAS2764_ISENSE_POWER_EN,
0182                 1, &isense_switch),
0183     SND_SOC_DAPM_SWITCH("VSENSE", TAS2764_PWR_CTRL, TAS2764_VSENSE_POWER_EN,
0184                 1, &vsense_switch),
0185     SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas2764_dac_event,
0186                SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
0187     SND_SOC_DAPM_OUTPUT("OUT"),
0188     SND_SOC_DAPM_SIGGEN("VMON"),
0189     SND_SOC_DAPM_SIGGEN("IMON")
0190 };
0191 
0192 static const struct snd_soc_dapm_route tas2764_audio_map[] = {
0193     {"ASI1 Sel", "I2C offset", "ASI1"},
0194     {"ASI1 Sel", "Left", "ASI1"},
0195     {"ASI1 Sel", "Right", "ASI1"},
0196     {"ASI1 Sel", "LeftRightDiv2", "ASI1"},
0197     {"DAC", NULL, "ASI1 Sel"},
0198     {"OUT", NULL, "DAC"},
0199     {"ISENSE", "Switch", "IMON"},
0200     {"VSENSE", "Switch", "VMON"},
0201 };
0202 
0203 static int tas2764_mute(struct snd_soc_dai *dai, int mute, int direction)
0204 {
0205     struct snd_soc_component *component = dai->component;
0206     int ret;
0207 
0208     ret = snd_soc_component_update_bits(component, TAS2764_PWR_CTRL,
0209                         TAS2764_PWR_CTRL_MASK,
0210                         mute ? TAS2764_PWR_CTRL_MUTE : 0);
0211 
0212     if (ret < 0)
0213         return ret;
0214 
0215     return 0;
0216 }
0217 
0218 static int tas2764_set_bitwidth(struct tas2764_priv *tas2764, int bitwidth)
0219 {
0220     struct snd_soc_component *component = tas2764->component;
0221     int sense_en;
0222     int val;
0223     int ret;
0224 
0225     switch (bitwidth) {
0226     case SNDRV_PCM_FORMAT_S16_LE:
0227         ret = snd_soc_component_update_bits(component,
0228                             TAS2764_TDM_CFG2,
0229                             TAS2764_TDM_CFG2_RXW_MASK,
0230                             TAS2764_TDM_CFG2_RXW_16BITS);
0231         break;
0232     case SNDRV_PCM_FORMAT_S24_LE:
0233         ret = snd_soc_component_update_bits(component,
0234                             TAS2764_TDM_CFG2,
0235                             TAS2764_TDM_CFG2_RXW_MASK,
0236                             TAS2764_TDM_CFG2_RXW_24BITS);
0237         break;
0238     case SNDRV_PCM_FORMAT_S32_LE:
0239         ret = snd_soc_component_update_bits(component,
0240                             TAS2764_TDM_CFG2,
0241                             TAS2764_TDM_CFG2_RXW_MASK,
0242                             TAS2764_TDM_CFG2_RXW_32BITS);
0243         break;
0244 
0245     default:
0246         return -EINVAL;
0247     }
0248 
0249     if (ret < 0)
0250         return ret;
0251 
0252     val = snd_soc_component_read(tas2764->component, TAS2764_PWR_CTRL);
0253     if (val < 0)
0254         return val;
0255 
0256     if (val & (1 << TAS2764_VSENSE_POWER_EN))
0257         sense_en = 0;
0258     else
0259         sense_en = TAS2764_TDM_CFG5_VSNS_ENABLE;
0260 
0261     ret = snd_soc_component_update_bits(tas2764->component, TAS2764_TDM_CFG5,
0262                         TAS2764_TDM_CFG5_VSNS_ENABLE,
0263                         sense_en);
0264     if (ret < 0)
0265         return ret;
0266 
0267     if (val & (1 << TAS2764_ISENSE_POWER_EN))
0268         sense_en = 0;
0269     else
0270         sense_en = TAS2764_TDM_CFG6_ISNS_ENABLE;
0271 
0272     ret = snd_soc_component_update_bits(tas2764->component, TAS2764_TDM_CFG6,
0273                         TAS2764_TDM_CFG6_ISNS_ENABLE,
0274                         sense_en);
0275     if (ret < 0)
0276         return ret;
0277 
0278     return 0;
0279 }
0280 
0281 static int tas2764_set_samplerate(struct tas2764_priv *tas2764, int samplerate)
0282 {
0283     struct snd_soc_component *component = tas2764->component;
0284     int ramp_rate_val;
0285     int ret;
0286 
0287     switch (samplerate) {
0288     case 48000:
0289         ramp_rate_val = TAS2764_TDM_CFG0_SMP_48KHZ |
0290                 TAS2764_TDM_CFG0_44_1_48KHZ;
0291         break;
0292     case 44100:
0293         ramp_rate_val = TAS2764_TDM_CFG0_SMP_44_1KHZ |
0294                 TAS2764_TDM_CFG0_44_1_48KHZ;
0295         break;
0296     case 96000:
0297         ramp_rate_val = TAS2764_TDM_CFG0_SMP_48KHZ |
0298                 TAS2764_TDM_CFG0_88_2_96KHZ;
0299         break;
0300     case 88200:
0301         ramp_rate_val = TAS2764_TDM_CFG0_SMP_44_1KHZ |
0302                 TAS2764_TDM_CFG0_88_2_96KHZ;
0303         break;
0304     default:
0305         return -EINVAL;
0306     }
0307 
0308     ret = snd_soc_component_update_bits(component, TAS2764_TDM_CFG0,
0309                         TAS2764_TDM_CFG0_SMP_MASK |
0310                         TAS2764_TDM_CFG0_MASK,
0311                         ramp_rate_val);
0312     if (ret < 0)
0313         return ret;
0314 
0315     return 0;
0316 }
0317 
0318 static int tas2764_hw_params(struct snd_pcm_substream *substream,
0319                  struct snd_pcm_hw_params *params,
0320                  struct snd_soc_dai *dai)
0321 {
0322     struct snd_soc_component *component = dai->component;
0323     struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component);
0324     int ret;
0325 
0326     ret = tas2764_set_bitwidth(tas2764, params_format(params));
0327     if (ret < 0)
0328         return ret;
0329 
0330     return tas2764_set_samplerate(tas2764, params_rate(params));
0331 }
0332 
0333 static int tas2764_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
0334 {
0335     struct snd_soc_component *component = dai->component;
0336     struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component);
0337     u8 tdm_rx_start_slot = 0, asi_cfg_0 = 0, asi_cfg_1 = 0;
0338     int ret;
0339 
0340     switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
0341     case SND_SOC_DAIFMT_NB_IF:
0342         asi_cfg_0 ^= TAS2764_TDM_CFG0_FRAME_START;
0343         fallthrough;
0344     case SND_SOC_DAIFMT_NB_NF:
0345         asi_cfg_1 = TAS2764_TDM_CFG1_RX_RISING;
0346         break;
0347     case SND_SOC_DAIFMT_IB_IF:
0348         asi_cfg_0 ^= TAS2764_TDM_CFG0_FRAME_START;
0349         fallthrough;
0350     case SND_SOC_DAIFMT_IB_NF:
0351         asi_cfg_1 = TAS2764_TDM_CFG1_RX_FALLING;
0352         break;
0353     }
0354 
0355     ret = snd_soc_component_update_bits(component, TAS2764_TDM_CFG1,
0356                         TAS2764_TDM_CFG1_RX_MASK,
0357                         asi_cfg_1);
0358     if (ret < 0)
0359         return ret;
0360 
0361     switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
0362     case SND_SOC_DAIFMT_I2S:
0363         asi_cfg_0 ^= TAS2764_TDM_CFG0_FRAME_START;
0364         fallthrough;
0365     case SND_SOC_DAIFMT_DSP_A:
0366         tdm_rx_start_slot = 1;
0367         break;
0368     case SND_SOC_DAIFMT_DSP_B:
0369     case SND_SOC_DAIFMT_LEFT_J:
0370         tdm_rx_start_slot = 0;
0371         break;
0372     default:
0373         dev_err(tas2764->dev,
0374             "DAI Format is not found, fmt=0x%x\n", fmt);
0375         return -EINVAL;
0376     }
0377 
0378     ret = snd_soc_component_update_bits(component, TAS2764_TDM_CFG0,
0379                         TAS2764_TDM_CFG0_FRAME_START,
0380                         asi_cfg_0);
0381     if (ret < 0)
0382         return ret;
0383 
0384     ret = snd_soc_component_update_bits(component, TAS2764_TDM_CFG1,
0385                         TAS2764_TDM_CFG1_MASK,
0386                         (tdm_rx_start_slot << TAS2764_TDM_CFG1_51_SHIFT));
0387     if (ret < 0)
0388         return ret;
0389 
0390     return 0;
0391 }
0392 
0393 static int tas2764_set_dai_tdm_slot(struct snd_soc_dai *dai,
0394                 unsigned int tx_mask,
0395                 unsigned int rx_mask,
0396                 int slots, int slot_width)
0397 {
0398     struct snd_soc_component *component = dai->component;
0399     struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component);
0400     int left_slot, right_slot;
0401     int slots_cfg;
0402     int slot_size;
0403     int ret;
0404 
0405     if (tx_mask == 0 || rx_mask != 0)
0406         return -EINVAL;
0407 
0408     if (slots == 1) {
0409         if (tx_mask != 1)
0410             return -EINVAL;
0411         left_slot = 0;
0412         right_slot = 0;
0413     } else {
0414         left_slot = __ffs(tx_mask);
0415         tx_mask &= ~(1 << left_slot);
0416         if (tx_mask == 0) {
0417             right_slot = left_slot;
0418         } else {
0419             right_slot = __ffs(tx_mask);
0420             tx_mask &= ~(1 << right_slot);
0421         }
0422     }
0423 
0424     if (tx_mask != 0 || left_slot >= slots || right_slot >= slots)
0425         return -EINVAL;
0426 
0427     slots_cfg = (right_slot << TAS2764_TDM_CFG3_RXS_SHIFT) | left_slot;
0428 
0429     ret = snd_soc_component_write(component, TAS2764_TDM_CFG3, slots_cfg);
0430     if (ret)
0431         return ret;
0432 
0433     switch (slot_width) {
0434     case 16:
0435         slot_size = TAS2764_TDM_CFG2_RXS_16BITS;
0436         break;
0437     case 24:
0438         slot_size = TAS2764_TDM_CFG2_RXS_24BITS;
0439         break;
0440     case 32:
0441         slot_size = TAS2764_TDM_CFG2_RXS_32BITS;
0442         break;
0443     default:
0444         return -EINVAL;
0445     }
0446 
0447     ret = snd_soc_component_update_bits(component, TAS2764_TDM_CFG2,
0448                         TAS2764_TDM_CFG2_RXS_MASK,
0449                         slot_size);
0450     if (ret < 0)
0451         return ret;
0452 
0453     ret = snd_soc_component_update_bits(component, TAS2764_TDM_CFG5,
0454                         TAS2764_TDM_CFG5_50_MASK,
0455                         tas2764->v_sense_slot);
0456     if (ret < 0)
0457         return ret;
0458 
0459     ret = snd_soc_component_update_bits(component, TAS2764_TDM_CFG6,
0460                         TAS2764_TDM_CFG6_50_MASK,
0461                         tas2764->i_sense_slot);
0462     if (ret < 0)
0463         return ret;
0464 
0465     return 0;
0466 }
0467 
0468 static const struct snd_soc_dai_ops tas2764_dai_ops = {
0469     .mute_stream = tas2764_mute,
0470     .hw_params  = tas2764_hw_params,
0471     .set_fmt    = tas2764_set_fmt,
0472     .set_tdm_slot = tas2764_set_dai_tdm_slot,
0473     .no_capture_mute = 1,
0474 };
0475 
0476 #define TAS2764_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
0477              SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
0478 
0479 #define TAS2764_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\
0480                SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_88200)
0481 
0482 static struct snd_soc_dai_driver tas2764_dai_driver[] = {
0483     {
0484         .name = "tas2764 ASI1",
0485         .id = 0,
0486         .playback = {
0487             .stream_name    = "ASI1 Playback",
0488             .channels_min   = 2,
0489             .channels_max   = 2,
0490             .rates      = TAS2764_RATES,
0491             .formats    = TAS2764_FORMATS,
0492         },
0493         .capture = {
0494             .stream_name    = "ASI1 Capture",
0495             .channels_min   = 0,
0496             .channels_max   = 2,
0497             .rates = TAS2764_RATES,
0498             .formats = TAS2764_FORMATS,
0499         },
0500         .ops = &tas2764_dai_ops,
0501         .symmetric_rate = 1,
0502     },
0503 };
0504 
0505 static int tas2764_codec_probe(struct snd_soc_component *component)
0506 {
0507     struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component);
0508     int ret;
0509 
0510     tas2764->component = component;
0511 
0512     if (tas2764->sdz_gpio) {
0513         gpiod_set_value_cansleep(tas2764->sdz_gpio, 1);
0514         usleep_range(1000, 2000);
0515     }
0516 
0517     tas2764_reset(tas2764);
0518 
0519     ret = snd_soc_component_update_bits(tas2764->component, TAS2764_TDM_CFG5,
0520                         TAS2764_TDM_CFG5_VSNS_ENABLE, 0);
0521     if (ret < 0)
0522         return ret;
0523 
0524     ret = snd_soc_component_update_bits(tas2764->component, TAS2764_TDM_CFG6,
0525                         TAS2764_TDM_CFG6_ISNS_ENABLE, 0);
0526     if (ret < 0)
0527         return ret;
0528 
0529     ret = snd_soc_component_update_bits(component, TAS2764_PWR_CTRL,
0530                         TAS2764_PWR_CTRL_MASK,
0531                         TAS2764_PWR_CTRL_MUTE);
0532     if (ret < 0)
0533         return ret;
0534 
0535     return 0;
0536 }
0537 
0538 static DECLARE_TLV_DB_SCALE(tas2764_digital_tlv, 1100, 50, 0);
0539 static DECLARE_TLV_DB_SCALE(tas2764_playback_volume, -10050, 50, 1);
0540 
0541 static const struct snd_kcontrol_new tas2764_snd_controls[] = {
0542     SOC_SINGLE_TLV("Speaker Volume", TAS2764_DVC, 0,
0543                TAS2764_DVC_MAX, 1, tas2764_playback_volume),
0544     SOC_SINGLE_TLV("Amp Gain Volume", TAS2764_CHNL_0, 1, 0x14, 0,
0545                tas2764_digital_tlv),
0546 };
0547 
0548 static const struct snd_soc_component_driver soc_component_driver_tas2764 = {
0549     .probe          = tas2764_codec_probe,
0550     .suspend        = tas2764_codec_suspend,
0551     .resume         = tas2764_codec_resume,
0552     .set_bias_level     = tas2764_set_bias_level,
0553     .controls       = tas2764_snd_controls,
0554     .num_controls       = ARRAY_SIZE(tas2764_snd_controls),
0555     .dapm_widgets       = tas2764_dapm_widgets,
0556     .num_dapm_widgets   = ARRAY_SIZE(tas2764_dapm_widgets),
0557     .dapm_routes        = tas2764_audio_map,
0558     .num_dapm_routes    = ARRAY_SIZE(tas2764_audio_map),
0559     .idle_bias_on       = 1,
0560     .endianness     = 1,
0561 };
0562 
0563 static const struct reg_default tas2764_reg_defaults[] = {
0564     { TAS2764_PAGE, 0x00 },
0565     { TAS2764_SW_RST, 0x00 },
0566     { TAS2764_PWR_CTRL, 0x1a },
0567     { TAS2764_DVC, 0x00 },
0568     { TAS2764_CHNL_0, 0x28 },
0569     { TAS2764_TDM_CFG0, 0x09 },
0570     { TAS2764_TDM_CFG1, 0x02 },
0571     { TAS2764_TDM_CFG2, 0x0a },
0572     { TAS2764_TDM_CFG3, 0x10 },
0573     { TAS2764_TDM_CFG5, 0x42 },
0574 };
0575 
0576 static const struct regmap_range_cfg tas2764_regmap_ranges[] = {
0577     {
0578         .range_min = 0,
0579         .range_max = 1 * 128,
0580         .selector_reg = TAS2764_PAGE,
0581         .selector_mask = 0xff,
0582         .selector_shift = 0,
0583         .window_start = 0,
0584         .window_len = 128,
0585     },
0586 };
0587 
0588 static const struct regmap_config tas2764_i2c_regmap = {
0589     .reg_bits = 8,
0590     .val_bits = 8,
0591     .reg_defaults = tas2764_reg_defaults,
0592     .num_reg_defaults = ARRAY_SIZE(tas2764_reg_defaults),
0593     .cache_type = REGCACHE_RBTREE,
0594     .ranges = tas2764_regmap_ranges,
0595     .num_ranges = ARRAY_SIZE(tas2764_regmap_ranges),
0596     .max_register = 1 * 128,
0597 };
0598 
0599 static int tas2764_parse_dt(struct device *dev, struct tas2764_priv *tas2764)
0600 {
0601     int ret = 0;
0602 
0603     tas2764->reset_gpio = devm_gpiod_get_optional(tas2764->dev, "reset",
0604                               GPIOD_OUT_HIGH);
0605     if (IS_ERR(tas2764->reset_gpio)) {
0606         if (PTR_ERR(tas2764->reset_gpio) == -EPROBE_DEFER) {
0607             tas2764->reset_gpio = NULL;
0608             return -EPROBE_DEFER;
0609         }
0610     }
0611 
0612     tas2764->sdz_gpio = devm_gpiod_get_optional(dev, "shutdown", GPIOD_OUT_HIGH);
0613     if (IS_ERR(tas2764->sdz_gpio)) {
0614         if (PTR_ERR(tas2764->sdz_gpio) == -EPROBE_DEFER)
0615             return -EPROBE_DEFER;
0616 
0617         tas2764->sdz_gpio = NULL;
0618     }
0619 
0620     ret = fwnode_property_read_u32(dev->fwnode, "ti,imon-slot-no",
0621                        &tas2764->i_sense_slot);
0622     if (ret)
0623         tas2764->i_sense_slot = 0;
0624 
0625     ret = fwnode_property_read_u32(dev->fwnode, "ti,vmon-slot-no",
0626                        &tas2764->v_sense_slot);
0627     if (ret)
0628         tas2764->v_sense_slot = 2;
0629 
0630     return 0;
0631 }
0632 
0633 static int tas2764_i2c_probe(struct i2c_client *client)
0634 {
0635     struct tas2764_priv *tas2764;
0636     int result;
0637 
0638     tas2764 = devm_kzalloc(&client->dev, sizeof(struct tas2764_priv),
0639                    GFP_KERNEL);
0640     if (!tas2764)
0641         return -ENOMEM;
0642 
0643     tas2764->dev = &client->dev;
0644     i2c_set_clientdata(client, tas2764);
0645     dev_set_drvdata(&client->dev, tas2764);
0646 
0647     tas2764->regmap = devm_regmap_init_i2c(client, &tas2764_i2c_regmap);
0648     if (IS_ERR(tas2764->regmap)) {
0649         result = PTR_ERR(tas2764->regmap);
0650         dev_err(&client->dev, "Failed to allocate register map: %d\n",
0651                     result);
0652         return result;
0653     }
0654 
0655     if (client->dev.of_node) {
0656         result = tas2764_parse_dt(&client->dev, tas2764);
0657         if (result) {
0658             dev_err(tas2764->dev, "%s: Failed to parse devicetree\n",
0659                 __func__);
0660             return result;
0661         }
0662     }
0663 
0664     return devm_snd_soc_register_component(tas2764->dev,
0665                            &soc_component_driver_tas2764,
0666                            tas2764_dai_driver,
0667                            ARRAY_SIZE(tas2764_dai_driver));
0668 }
0669 
0670 static const struct i2c_device_id tas2764_i2c_id[] = {
0671     { "tas2764", 0},
0672     { }
0673 };
0674 MODULE_DEVICE_TABLE(i2c, tas2764_i2c_id);
0675 
0676 #if defined(CONFIG_OF)
0677 static const struct of_device_id tas2764_of_match[] = {
0678     { .compatible = "ti,tas2764" },
0679     {},
0680 };
0681 MODULE_DEVICE_TABLE(of, tas2764_of_match);
0682 #endif
0683 
0684 static struct i2c_driver tas2764_i2c_driver = {
0685     .driver = {
0686         .name   = "tas2764",
0687         .of_match_table = of_match_ptr(tas2764_of_match),
0688     },
0689     .probe_new  = tas2764_i2c_probe,
0690     .id_table   = tas2764_i2c_id,
0691 };
0692 module_i2c_driver(tas2764_i2c_driver);
0693 
0694 MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
0695 MODULE_DESCRIPTION("TAS2764 I2C Smart Amplifier driver");
0696 MODULE_LICENSE("GPL v2");