0001
0002
0003
0004
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");