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