xref: /openbmc/linux/sound/soc/codecs/tas2764.c (revision 8ffdff6a)
1 // SPDX-License-Identifier: GPL-2.0
2 //
3 // Driver for the Texas Instruments TAS2764 CODEC
4 // Copyright (C) 2020 Texas Instruments Inc.
5 
6 #include <linux/module.h>
7 #include <linux/moduleparam.h>
8 #include <linux/err.h>
9 #include <linux/init.h>
10 #include <linux/delay.h>
11 #include <linux/pm.h>
12 #include <linux/i2c.h>
13 #include <linux/gpio.h>
14 #include <linux/gpio/consumer.h>
15 #include <linux/regulator/consumer.h>
16 #include <linux/regmap.h>
17 #include <linux/of.h>
18 #include <linux/of_gpio.h>
19 #include <linux/slab.h>
20 #include <sound/soc.h>
21 #include <sound/pcm.h>
22 #include <sound/pcm_params.h>
23 #include <sound/initval.h>
24 #include <sound/tlv.h>
25 
26 #include "tas2764.h"
27 
28 struct tas2764_priv {
29 	struct snd_soc_component *component;
30 	struct gpio_desc *reset_gpio;
31 	struct gpio_desc *sdz_gpio;
32 	struct regmap *regmap;
33 	struct device *dev;
34 
35 	int v_sense_slot;
36 	int i_sense_slot;
37 };
38 
39 static void tas2764_reset(struct tas2764_priv *tas2764)
40 {
41 	if (tas2764->reset_gpio) {
42 		gpiod_set_value_cansleep(tas2764->reset_gpio, 0);
43 		msleep(20);
44 		gpiod_set_value_cansleep(tas2764->reset_gpio, 1);
45 	}
46 
47 	snd_soc_component_write(tas2764->component, TAS2764_SW_RST,
48 				TAS2764_RST);
49 }
50 
51 static int tas2764_set_bias_level(struct snd_soc_component *component,
52 				 enum snd_soc_bias_level level)
53 {
54 	struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component);
55 
56 	switch (level) {
57 	case SND_SOC_BIAS_ON:
58 		snd_soc_component_update_bits(component, TAS2764_PWR_CTRL,
59 					      TAS2764_PWR_CTRL_MASK,
60 					      TAS2764_PWR_CTRL_ACTIVE);
61 		break;
62 	case SND_SOC_BIAS_STANDBY:
63 	case SND_SOC_BIAS_PREPARE:
64 		snd_soc_component_update_bits(component, TAS2764_PWR_CTRL,
65 					      TAS2764_PWR_CTRL_MASK,
66 					      TAS2764_PWR_CTRL_MUTE);
67 		break;
68 	case SND_SOC_BIAS_OFF:
69 		snd_soc_component_update_bits(component, TAS2764_PWR_CTRL,
70 					      TAS2764_PWR_CTRL_MASK,
71 					      TAS2764_PWR_CTRL_SHUTDOWN);
72 		break;
73 
74 	default:
75 		dev_err(tas2764->dev,
76 				"wrong power level setting %d\n", level);
77 		return -EINVAL;
78 	}
79 
80 	return 0;
81 }
82 
83 #ifdef CONFIG_PM
84 static int tas2764_codec_suspend(struct snd_soc_component *component)
85 {
86 	struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component);
87 	int ret;
88 
89 	ret = snd_soc_component_update_bits(component, TAS2764_PWR_CTRL,
90 					    TAS2764_PWR_CTRL_MASK,
91 					    TAS2764_PWR_CTRL_SHUTDOWN);
92 
93 	if (ret < 0)
94 		return ret;
95 
96 	if (tas2764->sdz_gpio)
97 		gpiod_set_value_cansleep(tas2764->sdz_gpio, 0);
98 
99 	regcache_cache_only(tas2764->regmap, true);
100 	regcache_mark_dirty(tas2764->regmap);
101 
102 	return 0;
103 }
104 
105 static int tas2764_codec_resume(struct snd_soc_component *component)
106 {
107 	struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component);
108 	int ret;
109 
110 	if (tas2764->sdz_gpio)
111 		gpiod_set_value_cansleep(tas2764->sdz_gpio, 1);
112 
113 	ret = snd_soc_component_update_bits(component, TAS2764_PWR_CTRL,
114 					    TAS2764_PWR_CTRL_MASK,
115 					    TAS2764_PWR_CTRL_ACTIVE);
116 
117 	if (ret < 0)
118 		return ret;
119 
120 	regcache_cache_only(tas2764->regmap, false);
121 
122 	return regcache_sync(tas2764->regmap);
123 }
124 #else
125 #define tas2764_codec_suspend NULL
126 #define tas2764_codec_resume NULL
127 #endif
128 
129 static const char * const tas2764_ASI1_src[] = {
130 	"I2C offset", "Left", "Right", "LeftRightDiv2",
131 };
132 
133 static SOC_ENUM_SINGLE_DECL(
134 	tas2764_ASI1_src_enum, TAS2764_TDM_CFG2, 4, tas2764_ASI1_src);
135 
136 static const struct snd_kcontrol_new tas2764_asi1_mux =
137 	SOC_DAPM_ENUM("ASI1 Source", tas2764_ASI1_src_enum);
138 
139 static int tas2764_dac_event(struct snd_soc_dapm_widget *w,
140 			     struct snd_kcontrol *kcontrol, int event)
141 {
142 	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
143 	struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component);
144 	int ret;
145 
146 	switch (event) {
147 	case SND_SOC_DAPM_POST_PMU:
148 		ret = snd_soc_component_update_bits(component, TAS2764_PWR_CTRL,
149 						    TAS2764_PWR_CTRL_MASK,
150 						    TAS2764_PWR_CTRL_MUTE);
151 		break;
152 	case SND_SOC_DAPM_PRE_PMD:
153 		ret = snd_soc_component_update_bits(component, TAS2764_PWR_CTRL,
154 						    TAS2764_PWR_CTRL_MASK,
155 						    TAS2764_PWR_CTRL_SHUTDOWN);
156 		break;
157 	default:
158 		dev_err(tas2764->dev, "Unsupported event\n");
159 		return -EINVAL;
160 	}
161 
162 	if (ret < 0)
163 		return ret;
164 
165 	return 0;
166 }
167 
168 static const struct snd_kcontrol_new isense_switch =
169 	SOC_DAPM_SINGLE("Switch", TAS2764_PWR_CTRL, TAS2764_ISENSE_POWER_EN, 1, 1);
170 static const struct snd_kcontrol_new vsense_switch =
171 	SOC_DAPM_SINGLE("Switch", TAS2764_PWR_CTRL, TAS2764_VSENSE_POWER_EN, 1, 1);
172 
173 static const struct snd_soc_dapm_widget tas2764_dapm_widgets[] = {
174 	SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0),
175 	SND_SOC_DAPM_MUX("ASI1 Sel", SND_SOC_NOPM, 0, 0, &tas2764_asi1_mux),
176 	SND_SOC_DAPM_SWITCH("ISENSE", TAS2764_PWR_CTRL, TAS2764_ISENSE_POWER_EN,
177 			    1, &isense_switch),
178 	SND_SOC_DAPM_SWITCH("VSENSE", TAS2764_PWR_CTRL, TAS2764_VSENSE_POWER_EN,
179 			    1, &vsense_switch),
180 	SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas2764_dac_event,
181 			   SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
182 	SND_SOC_DAPM_OUTPUT("OUT"),
183 	SND_SOC_DAPM_SIGGEN("VMON"),
184 	SND_SOC_DAPM_SIGGEN("IMON")
185 };
186 
187 static const struct snd_soc_dapm_route tas2764_audio_map[] = {
188 	{"ASI1 Sel", "I2C offset", "ASI1"},
189 	{"ASI1 Sel", "Left", "ASI1"},
190 	{"ASI1 Sel", "Right", "ASI1"},
191 	{"ASI1 Sel", "LeftRightDiv2", "ASI1"},
192 	{"DAC", NULL, "ASI1 Sel"},
193 	{"OUT", NULL, "DAC"},
194 	{"ISENSE", "Switch", "IMON"},
195 	{"VSENSE", "Switch", "VMON"},
196 };
197 
198 static int tas2764_mute(struct snd_soc_dai *dai, int mute, int direction)
199 {
200 	struct snd_soc_component *component = dai->component;
201 	int ret;
202 
203 	ret = snd_soc_component_update_bits(component, TAS2764_PWR_CTRL,
204 					    TAS2764_PWR_CTRL_MASK,
205 					    mute ? TAS2764_PWR_CTRL_MUTE : 0);
206 
207 	if (ret < 0)
208 		return ret;
209 
210 	return 0;
211 }
212 
213 static int tas2764_set_bitwidth(struct tas2764_priv *tas2764, int bitwidth)
214 {
215 	struct snd_soc_component *component = tas2764->component;
216 	int sense_en;
217 	int val;
218 	int ret;
219 
220 	switch (bitwidth) {
221 	case SNDRV_PCM_FORMAT_S16_LE:
222 		ret = snd_soc_component_update_bits(component,
223 						    TAS2764_TDM_CFG2,
224 						    TAS2764_TDM_CFG2_RXW_MASK,
225 						    TAS2764_TDM_CFG2_RXW_16BITS);
226 		break;
227 	case SNDRV_PCM_FORMAT_S24_LE:
228 		ret = snd_soc_component_update_bits(component,
229 						    TAS2764_TDM_CFG2,
230 						    TAS2764_TDM_CFG2_RXW_MASK,
231 						    TAS2764_TDM_CFG2_RXW_24BITS);
232 		break;
233 	case SNDRV_PCM_FORMAT_S32_LE:
234 		ret = snd_soc_component_update_bits(component,
235 						    TAS2764_TDM_CFG2,
236 						    TAS2764_TDM_CFG2_RXW_MASK,
237 						    TAS2764_TDM_CFG2_RXW_32BITS);
238 		break;
239 
240 	default:
241 		return -EINVAL;
242 	}
243 
244 	if (ret < 0)
245 		return ret;
246 
247 	val = snd_soc_component_read(tas2764->component, TAS2764_PWR_CTRL);
248 	if (val < 0)
249 		return val;
250 
251 	if (val & (1 << TAS2764_VSENSE_POWER_EN))
252 		sense_en = 0;
253 	else
254 		sense_en = TAS2764_TDM_CFG5_VSNS_ENABLE;
255 
256 	ret = snd_soc_component_update_bits(tas2764->component, TAS2764_TDM_CFG5,
257 					    TAS2764_TDM_CFG5_VSNS_ENABLE,
258 					    sense_en);
259 	if (ret < 0)
260 		return ret;
261 
262 	if (val & (1 << TAS2764_ISENSE_POWER_EN))
263 		sense_en = 0;
264 	else
265 		sense_en = TAS2764_TDM_CFG6_ISNS_ENABLE;
266 
267 	ret = snd_soc_component_update_bits(tas2764->component, TAS2764_TDM_CFG6,
268 					    TAS2764_TDM_CFG6_ISNS_ENABLE,
269 					    sense_en);
270 	if (ret < 0)
271 		return ret;
272 
273 	return 0;
274 }
275 
276 static int tas2764_set_samplerate(struct tas2764_priv *tas2764, int samplerate)
277 {
278 	struct snd_soc_component *component = tas2764->component;
279 	int ramp_rate_val;
280 	int ret;
281 
282 	switch (samplerate) {
283 	case 48000:
284 		ramp_rate_val = TAS2764_TDM_CFG0_SMP_48KHZ |
285 				TAS2764_TDM_CFG0_44_1_48KHZ;
286 		break;
287 	case 44100:
288 		ramp_rate_val = TAS2764_TDM_CFG0_SMP_44_1KHZ |
289 				TAS2764_TDM_CFG0_44_1_48KHZ;
290 		break;
291 	case 96000:
292 		ramp_rate_val = TAS2764_TDM_CFG0_SMP_48KHZ |
293 				TAS2764_TDM_CFG0_88_2_96KHZ;
294 		break;
295 	case 88200:
296 		ramp_rate_val = TAS2764_TDM_CFG0_SMP_44_1KHZ |
297 				TAS2764_TDM_CFG0_88_2_96KHZ;
298 		break;
299 	default:
300 		return -EINVAL;
301 	}
302 
303 	ret = snd_soc_component_update_bits(component, TAS2764_TDM_CFG0,
304 					    TAS2764_TDM_CFG0_SMP_MASK |
305 					    TAS2764_TDM_CFG0_MASK,
306 					    ramp_rate_val);
307 	if (ret < 0)
308 		return ret;
309 
310 	return 0;
311 }
312 
313 static int tas2764_hw_params(struct snd_pcm_substream *substream,
314 			     struct snd_pcm_hw_params *params,
315 			     struct snd_soc_dai *dai)
316 {
317 	struct snd_soc_component *component = dai->component;
318 	struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component);
319 	int ret;
320 
321 	ret = tas2764_set_bitwidth(tas2764, params_format(params));
322 	if (ret < 0)
323 		return ret;
324 
325 	return tas2764_set_samplerate(tas2764, params_rate(params));
326 }
327 
328 static int tas2764_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
329 {
330 	struct snd_soc_component *component = dai->component;
331 	struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component);
332 	u8 tdm_rx_start_slot = 0, asi_cfg_1 = 0;
333 	int iface;
334 	int ret;
335 
336 	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
337 	case SND_SOC_DAIFMT_NB_NF:
338 		asi_cfg_1 = TAS2764_TDM_CFG1_RX_RISING;
339 		break;
340 	case SND_SOC_DAIFMT_IB_NF:
341 		asi_cfg_1 = TAS2764_TDM_CFG1_RX_FALLING;
342 		break;
343 	default:
344 		dev_err(tas2764->dev, "ASI format Inverse is not found\n");
345 		return -EINVAL;
346 	}
347 
348 	ret = snd_soc_component_update_bits(component, TAS2764_TDM_CFG1,
349 					    TAS2764_TDM_CFG1_RX_MASK,
350 					    asi_cfg_1);
351 	if (ret < 0)
352 		return ret;
353 
354 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
355 	case SND_SOC_DAIFMT_I2S:
356 	case SND_SOC_DAIFMT_DSP_A:
357 		iface = TAS2764_TDM_CFG2_SCFG_I2S;
358 		tdm_rx_start_slot = 1;
359 		break;
360 	case SND_SOC_DAIFMT_DSP_B:
361 	case SND_SOC_DAIFMT_LEFT_J:
362 		iface = TAS2764_TDM_CFG2_SCFG_LEFT_J;
363 		tdm_rx_start_slot = 0;
364 		break;
365 	default:
366 		dev_err(tas2764->dev,
367 			"DAI Format is not found, fmt=0x%x\n", fmt);
368 		return -EINVAL;
369 	}
370 
371 	ret = snd_soc_component_update_bits(component, TAS2764_TDM_CFG1,
372 					    TAS2764_TDM_CFG1_MASK,
373 					    (tdm_rx_start_slot << TAS2764_TDM_CFG1_51_SHIFT));
374 	if (ret < 0)
375 		return ret;
376 
377 	ret = snd_soc_component_update_bits(component, TAS2764_TDM_CFG2,
378 					    TAS2764_TDM_CFG2_SCFG_MASK, iface);
379 	if (ret < 0)
380 		return ret;
381 
382 	return 0;
383 }
384 
385 static int tas2764_set_dai_tdm_slot(struct snd_soc_dai *dai,
386 				unsigned int tx_mask,
387 				unsigned int rx_mask,
388 				int slots, int slot_width)
389 {
390 	struct snd_soc_component *component = dai->component;
391 	struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component);
392 	int left_slot, right_slot;
393 	int slots_cfg;
394 	int slot_size;
395 	int ret;
396 
397 	if (tx_mask == 0 || rx_mask != 0)
398 		return -EINVAL;
399 
400 	if (slots == 1) {
401 		if (tx_mask != 1)
402 			return -EINVAL;
403 		left_slot = 0;
404 		right_slot = 0;
405 	} else {
406 		left_slot = __ffs(tx_mask);
407 		tx_mask &= ~(1 << left_slot);
408 		if (tx_mask == 0) {
409 			right_slot = left_slot;
410 		} else {
411 			right_slot = __ffs(tx_mask);
412 			tx_mask &= ~(1 << right_slot);
413 		}
414 	}
415 
416 	if (tx_mask != 0 || left_slot >= slots || right_slot >= slots)
417 		return -EINVAL;
418 
419 	slots_cfg = (right_slot << TAS2764_TDM_CFG3_RXS_SHIFT) | left_slot;
420 
421 	ret = snd_soc_component_write(component, TAS2764_TDM_CFG3, slots_cfg);
422 	if (ret)
423 		return ret;
424 
425 	switch (slot_width) {
426 	case 16:
427 		slot_size = TAS2764_TDM_CFG2_RXS_16BITS;
428 		break;
429 	case 24:
430 		slot_size = TAS2764_TDM_CFG2_RXS_24BITS;
431 		break;
432 	case 32:
433 		slot_size = TAS2764_TDM_CFG2_RXS_32BITS;
434 		break;
435 	default:
436 		return -EINVAL;
437 	}
438 
439 	ret = snd_soc_component_update_bits(component, TAS2764_TDM_CFG2,
440 					    TAS2764_TDM_CFG2_RXS_MASK,
441 					    slot_size);
442 	if (ret < 0)
443 		return ret;
444 
445 	ret = snd_soc_component_update_bits(component, TAS2764_TDM_CFG5,
446 					    TAS2764_TDM_CFG5_50_MASK,
447 					    tas2764->v_sense_slot);
448 	if (ret < 0)
449 		return ret;
450 
451 	ret = snd_soc_component_update_bits(component, TAS2764_TDM_CFG6,
452 					    TAS2764_TDM_CFG6_50_MASK,
453 					    tas2764->i_sense_slot);
454 	if (ret < 0)
455 		return ret;
456 
457 	return 0;
458 }
459 
460 static struct snd_soc_dai_ops tas2764_dai_ops = {
461 	.mute_stream = tas2764_mute,
462 	.hw_params  = tas2764_hw_params,
463 	.set_fmt    = tas2764_set_fmt,
464 	.set_tdm_slot = tas2764_set_dai_tdm_slot,
465 	.no_capture_mute = 1,
466 };
467 
468 #define TAS2764_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
469 			 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
470 
471 #define TAS2764_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\
472 		       SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_88200)
473 
474 static struct snd_soc_dai_driver tas2764_dai_driver[] = {
475 	{
476 		.name = "tas2764 ASI1",
477 		.id = 0,
478 		.playback = {
479 			.stream_name    = "ASI1 Playback",
480 			.channels_min   = 2,
481 			.channels_max   = 2,
482 			.rates      = TAS2764_RATES,
483 			.formats    = TAS2764_FORMATS,
484 		},
485 		.capture = {
486 			.stream_name    = "ASI1 Capture",
487 			.channels_min   = 0,
488 			.channels_max   = 2,
489 			.rates = TAS2764_RATES,
490 			.formats = TAS2764_FORMATS,
491 		},
492 		.ops = &tas2764_dai_ops,
493 		.symmetric_rate = 1,
494 	},
495 };
496 
497 static int tas2764_codec_probe(struct snd_soc_component *component)
498 {
499 	struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component);
500 	int ret;
501 
502 	tas2764->component = component;
503 
504 	if (tas2764->sdz_gpio)
505 		gpiod_set_value_cansleep(tas2764->sdz_gpio, 1);
506 
507 	tas2764_reset(tas2764);
508 
509 	ret = snd_soc_component_update_bits(tas2764->component, TAS2764_TDM_CFG5,
510 					    TAS2764_TDM_CFG5_VSNS_ENABLE, 0);
511 	if (ret < 0)
512 		return ret;
513 
514 	ret = snd_soc_component_update_bits(tas2764->component, TAS2764_TDM_CFG6,
515 					    TAS2764_TDM_CFG6_ISNS_ENABLE, 0);
516 	if (ret < 0)
517 		return ret;
518 
519 	ret = snd_soc_component_update_bits(component, TAS2764_PWR_CTRL,
520 					    TAS2764_PWR_CTRL_MASK,
521 					    TAS2764_PWR_CTRL_MUTE);
522 	if (ret < 0)
523 		return ret;
524 
525 	return 0;
526 }
527 
528 static DECLARE_TLV_DB_SCALE(tas2764_digital_tlv, 1100, 50, 0);
529 static DECLARE_TLV_DB_SCALE(tas2764_playback_volume, -10000, 50, 0);
530 
531 static const struct snd_kcontrol_new tas2764_snd_controls[] = {
532 	SOC_SINGLE_TLV("Speaker Volume", TAS2764_DVC, 0,
533 		       TAS2764_DVC_MAX, 1, tas2764_playback_volume),
534 	SOC_SINGLE_TLV("Amp Gain Volume", TAS2764_CHNL_0, 0, 0x14, 0,
535 		       tas2764_digital_tlv),
536 };
537 
538 static const struct snd_soc_component_driver soc_component_driver_tas2764 = {
539 	.probe			= tas2764_codec_probe,
540 	.suspend		= tas2764_codec_suspend,
541 	.resume			= tas2764_codec_resume,
542 	.set_bias_level		= tas2764_set_bias_level,
543 	.controls		= tas2764_snd_controls,
544 	.num_controls		= ARRAY_SIZE(tas2764_snd_controls),
545 	.dapm_widgets		= tas2764_dapm_widgets,
546 	.num_dapm_widgets	= ARRAY_SIZE(tas2764_dapm_widgets),
547 	.dapm_routes		= tas2764_audio_map,
548 	.num_dapm_routes	= ARRAY_SIZE(tas2764_audio_map),
549 	.idle_bias_on		= 1,
550 	.endianness		= 1,
551 	.non_legacy_dai_naming	= 1,
552 };
553 
554 static const struct reg_default tas2764_reg_defaults[] = {
555 	{ TAS2764_PAGE, 0x00 },
556 	{ TAS2764_SW_RST, 0x00 },
557 	{ TAS2764_PWR_CTRL, 0x1a },
558 	{ TAS2764_DVC, 0x00 },
559 	{ TAS2764_CHNL_0, 0x00 },
560 	{ TAS2764_TDM_CFG0, 0x09 },
561 	{ TAS2764_TDM_CFG1, 0x02 },
562 	{ TAS2764_TDM_CFG2, 0x0a },
563 	{ TAS2764_TDM_CFG3, 0x10 },
564 	{ TAS2764_TDM_CFG5, 0x42 },
565 };
566 
567 static const struct regmap_range_cfg tas2764_regmap_ranges[] = {
568 	{
569 		.range_min = 0,
570 		.range_max = 1 * 128,
571 		.selector_reg = TAS2764_PAGE,
572 		.selector_mask = 0xff,
573 		.selector_shift = 0,
574 		.window_start = 0,
575 		.window_len = 128,
576 	},
577 };
578 
579 static const struct regmap_config tas2764_i2c_regmap = {
580 	.reg_bits = 8,
581 	.val_bits = 8,
582 	.reg_defaults = tas2764_reg_defaults,
583 	.num_reg_defaults = ARRAY_SIZE(tas2764_reg_defaults),
584 	.cache_type = REGCACHE_RBTREE,
585 	.ranges = tas2764_regmap_ranges,
586 	.num_ranges = ARRAY_SIZE(tas2764_regmap_ranges),
587 	.max_register = 1 * 128,
588 };
589 
590 static int tas2764_parse_dt(struct device *dev, struct tas2764_priv *tas2764)
591 {
592 	int ret = 0;
593 
594 	tas2764->reset_gpio = devm_gpiod_get_optional(tas2764->dev, "reset",
595 						      GPIOD_OUT_HIGH);
596 	if (IS_ERR(tas2764->reset_gpio)) {
597 		if (PTR_ERR(tas2764->reset_gpio) == -EPROBE_DEFER) {
598 			tas2764->reset_gpio = NULL;
599 			return -EPROBE_DEFER;
600 		}
601 	}
602 
603 	tas2764->sdz_gpio = devm_gpiod_get_optional(dev, "shutdown", GPIOD_OUT_HIGH);
604 	if (IS_ERR(tas2764->sdz_gpio)) {
605 		if (PTR_ERR(tas2764->sdz_gpio) == -EPROBE_DEFER)
606 			return -EPROBE_DEFER;
607 
608 		tas2764->sdz_gpio = NULL;
609 	}
610 
611 	ret = fwnode_property_read_u32(dev->fwnode, "ti,imon-slot-no",
612 				       &tas2764->i_sense_slot);
613 	if (ret)
614 		tas2764->i_sense_slot = 0;
615 
616 	ret = fwnode_property_read_u32(dev->fwnode, "ti,vmon-slot-no",
617 				       &tas2764->v_sense_slot);
618 	if (ret)
619 		tas2764->v_sense_slot = 2;
620 
621 	return 0;
622 }
623 
624 static int tas2764_i2c_probe(struct i2c_client *client,
625 			const struct i2c_device_id *id)
626 {
627 	struct tas2764_priv *tas2764;
628 	int result;
629 
630 	tas2764 = devm_kzalloc(&client->dev, sizeof(struct tas2764_priv),
631 			       GFP_KERNEL);
632 	if (!tas2764)
633 		return -ENOMEM;
634 
635 	tas2764->dev = &client->dev;
636 	i2c_set_clientdata(client, tas2764);
637 	dev_set_drvdata(&client->dev, tas2764);
638 
639 	tas2764->regmap = devm_regmap_init_i2c(client, &tas2764_i2c_regmap);
640 	if (IS_ERR(tas2764->regmap)) {
641 		result = PTR_ERR(tas2764->regmap);
642 		dev_err(&client->dev, "Failed to allocate register map: %d\n",
643 					result);
644 		return result;
645 	}
646 
647 	if (client->dev.of_node) {
648 		result = tas2764_parse_dt(&client->dev, tas2764);
649 		if (result) {
650 			dev_err(tas2764->dev, "%s: Failed to parse devicetree\n",
651 				__func__);
652 			return result;
653 		}
654 	}
655 
656 	return devm_snd_soc_register_component(tas2764->dev,
657 					       &soc_component_driver_tas2764,
658 					       tas2764_dai_driver,
659 					       ARRAY_SIZE(tas2764_dai_driver));
660 }
661 
662 static const struct i2c_device_id tas2764_i2c_id[] = {
663 	{ "tas2764", 0},
664 	{ }
665 };
666 MODULE_DEVICE_TABLE(i2c, tas2764_i2c_id);
667 
668 #if defined(CONFIG_OF)
669 static const struct of_device_id tas2764_of_match[] = {
670 	{ .compatible = "ti,tas2764" },
671 	{},
672 };
673 MODULE_DEVICE_TABLE(of, tas2764_of_match);
674 #endif
675 
676 static struct i2c_driver tas2764_i2c_driver = {
677 	.driver = {
678 		.name   = "tas2764",
679 		.of_match_table = of_match_ptr(tas2764_of_match),
680 	},
681 	.probe      = tas2764_i2c_probe,
682 	.id_table   = tas2764_i2c_id,
683 };
684 module_i2c_driver(tas2764_i2c_driver);
685 
686 MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
687 MODULE_DESCRIPTION("TAS2764 I2C Smart Amplifier driver");
688 MODULE_LICENSE("GPL v2");
689