Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.10.11.
  1// SPDX-License-Identifier: GPL-2.0
  2// Driver for the Texas Instruments TAS2780 Mono
  3//		Audio amplifier
  4// Copyright (C) 2022 Texas Instruments Inc.
  5
  6#include <linux/module.h>
  7#include <linux/err.h>
  8#include <linux/pm.h>
  9#include <linux/i2c.h>
 10#include <linux/gpio/consumer.h>
 11#include <linux/regmap.h>
 12#include <linux/of.h>
 13#include <sound/soc.h>
 14#include <sound/pcm.h>
 15#include <sound/pcm_params.h>
 16#include <sound/tlv.h>
 17
 18#include "tas2780.h"
 19
 20struct tas2780_priv {
 21	struct snd_soc_component *component;
 22	struct gpio_desc *reset_gpio;
 23	struct regmap *regmap;
 24	struct device *dev;
 25	int v_sense_slot;
 26	int i_sense_slot;
 27};
 28
 29static void tas2780_reset(struct tas2780_priv *tas2780)
 30{
 31	int ret = 0;
 32
 33	if (tas2780->reset_gpio) {
 34		gpiod_set_value_cansleep(tas2780->reset_gpio, 0);
 35		usleep_range(2000, 2050);
 36		gpiod_set_value_cansleep(tas2780->reset_gpio, 1);
 37		usleep_range(2000, 2050);
 38	}
 39
 40	ret = snd_soc_component_write(tas2780->component, TAS2780_SW_RST,
 41				TAS2780_RST);
 42	if (ret)
 43		dev_err(tas2780->dev, "%s:errCode:0x%x Reset error!\n",
 44			__func__, ret);
 45}
 46
 47#ifdef CONFIG_PM
 48static int tas2780_codec_suspend(struct snd_soc_component *component)
 49{
 50	struct tas2780_priv *tas2780 =
 51		snd_soc_component_get_drvdata(component);
 52	int ret = 0;
 53
 54	ret = snd_soc_component_update_bits(component, TAS2780_PWR_CTRL,
 55		TAS2780_PWR_CTRL_MASK, TAS2780_PWR_CTRL_SHUTDOWN);
 56	if (ret < 0) {
 57		dev_err(tas2780->dev, "%s:errCode:0x%0x:power down error\n",
 58			__func__, ret);
 59		goto err;
 60	}
 61	ret = 0;
 62	regcache_cache_only(tas2780->regmap, true);
 63	regcache_mark_dirty(tas2780->regmap);
 64err:
 65	return ret;
 66}
 67
 68static int tas2780_codec_resume(struct snd_soc_component *component)
 69{
 70	struct tas2780_priv *tas2780 =
 71		snd_soc_component_get_drvdata(component);
 72	int ret;
 73
 74	ret = snd_soc_component_update_bits(component, TAS2780_PWR_CTRL,
 75		TAS2780_PWR_CTRL_MASK, TAS2780_PWR_CTRL_ACTIVE);
 76
 77	if (ret < 0) {
 78		dev_err(tas2780->dev, "%s:errCode:0x%0x:power down error\n",
 79			__func__, ret);
 80		goto err;
 81	}
 82	regcache_cache_only(tas2780->regmap, false);
 83	ret = regcache_sync(tas2780->regmap);
 84err:
 85	return ret;
 86}
 87#endif
 88
 89static const char * const tas2780_ASI1_src[] = {
 90	"I2C offset", "Left", "Right", "LeftRightDiv2",
 91};
 92
 93static SOC_ENUM_SINGLE_DECL(
 94	tas2780_ASI1_src_enum, TAS2780_TDM_CFG2, 4, tas2780_ASI1_src);
 95
 96static const struct snd_kcontrol_new tas2780_asi1_mux =
 97	SOC_DAPM_ENUM("ASI1 Source", tas2780_ASI1_src_enum);
 98
 99static const struct snd_kcontrol_new isense_switch =
100	SOC_DAPM_SINGLE("Switch", TAS2780_PWR_CTRL,
101			TAS2780_ISENSE_POWER_EN, 1, 1);
102static const struct snd_kcontrol_new vsense_switch =
103	SOC_DAPM_SINGLE("Switch", TAS2780_PWR_CTRL,
104			TAS2780_VSENSE_POWER_EN, 1, 1);
105
106static const struct snd_soc_dapm_widget tas2780_dapm_widgets[] = {
107	SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0),
108	SND_SOC_DAPM_MUX("ASI1 Sel", SND_SOC_NOPM, 0, 0, &tas2780_asi1_mux),
109	SND_SOC_DAPM_SWITCH("ISENSE", TAS2780_PWR_CTRL,
110		TAS2780_ISENSE_POWER_EN, 1, &isense_switch),
111	SND_SOC_DAPM_SWITCH("VSENSE", TAS2780_PWR_CTRL,
112		TAS2780_VSENSE_POWER_EN, 1, &vsense_switch),
113	SND_SOC_DAPM_OUTPUT("OUT"),
114	SND_SOC_DAPM_SIGGEN("VMON"),
115	SND_SOC_DAPM_SIGGEN("IMON")
116};
117
118static const struct snd_soc_dapm_route tas2780_audio_map[] = {
119	{"ASI1 Sel", "I2C offset", "ASI1"},
120	{"ASI1 Sel", "Left", "ASI1"},
121	{"ASI1 Sel", "Right", "ASI1"},
122	{"ASI1 Sel", "LeftRightDiv2", "ASI1"},
123	{"OUT", NULL, "ASI1 Sel"},
124	{"ISENSE", "Switch", "IMON"},
125	{"VSENSE", "Switch", "VMON"},
126};
127
128static int tas2780_mute(struct snd_soc_dai *dai, int mute, int direction)
129{
130	struct snd_soc_component *component = dai->component;
131	struct tas2780_priv *tas2780 =
132		snd_soc_component_get_drvdata(component);
133	int ret = 0;
134
135	ret = snd_soc_component_update_bits(component, TAS2780_PWR_CTRL,
136		TAS2780_PWR_CTRL_MASK,
137		mute ? TAS2780_PWR_CTRL_MUTE : 0);
138	if (ret < 0) {
139		dev_err(tas2780->dev, "%s: Failed to set powercontrol\n",
140			__func__);
141		goto err;
142	}
143	ret = 0;
144err:
145	return ret;
146}
147
148static int tas2780_set_bitwidth(struct tas2780_priv *tas2780, int bitwidth)
149{
150	struct snd_soc_component *component = tas2780->component;
151	int sense_en;
152	int val;
153	int ret;
154	int slot_size;
155
156	switch (bitwidth) {
157	case SNDRV_PCM_FORMAT_S16_LE:
158		ret = snd_soc_component_update_bits(component,
159			TAS2780_TDM_CFG2,
160			TAS2780_TDM_CFG2_RXW_MASK,
161			TAS2780_TDM_CFG2_RXW_16BITS);
162		slot_size = TAS2780_TDM_CFG2_RXS_16BITS;
163		break;
164	case SNDRV_PCM_FORMAT_S24_LE:
165		ret = snd_soc_component_update_bits(component,
166			TAS2780_TDM_CFG2,
167			TAS2780_TDM_CFG2_RXW_MASK,
168			TAS2780_TDM_CFG2_RXW_24BITS);
169		slot_size = TAS2780_TDM_CFG2_RXS_24BITS;
170		break;
171	case SNDRV_PCM_FORMAT_S32_LE:
172		ret = snd_soc_component_update_bits(component,
173			TAS2780_TDM_CFG2,
174			TAS2780_TDM_CFG2_RXW_MASK,
175			TAS2780_TDM_CFG2_RXW_32BITS);
176		slot_size = TAS2780_TDM_CFG2_RXS_32BITS;
177		break;
178
179	default:
180		ret = -EINVAL;
181	}
182
183	if (ret < 0) {
184		dev_err(tas2780->dev, "%s:errCode:0x%x set bitwidth error\n",
185			__func__, ret);
186		goto err;
187	}
188
189	ret = snd_soc_component_update_bits(component, TAS2780_TDM_CFG2,
190		TAS2780_TDM_CFG2_RXS_MASK, slot_size);
191	if (ret < 0) {
192		dev_err(tas2780->dev,
193			"%s:errCode:0x%x set RX slot size error\n",
194			__func__, ret);
195		goto err;
196	}
197
198	val = snd_soc_component_read(tas2780->component, TAS2780_PWR_CTRL);
199	if (val < 0) {
200		dev_err(tas2780->dev, "%s:errCode:0x%x read PWR_CTRL error\n",
201			__func__, val);
202		ret = val;
203		goto err;
204	}
205
206	if (val & (1 << TAS2780_VSENSE_POWER_EN))
207		sense_en = 0;
208	else
209		sense_en = TAS2780_TDM_CFG5_VSNS_ENABLE;
210
211	ret = snd_soc_component_update_bits(tas2780->component,
212		TAS2780_TDM_CFG5, TAS2780_TDM_CFG5_VSNS_ENABLE, sense_en);
213	if (ret < 0) {
214		dev_err(tas2780->dev, "%s:errCode:0x%x enable vSNS error\n",
215			__func__, ret);
216		goto err;
217	}
218
219	if (val & (1 << TAS2780_ISENSE_POWER_EN))
220		sense_en = 0;
221	else
222		sense_en = TAS2780_TDM_CFG6_ISNS_ENABLE;
223
224	ret = snd_soc_component_update_bits(tas2780->component,
225		TAS2780_TDM_CFG6, TAS2780_TDM_CFG6_ISNS_ENABLE, sense_en);
226	if (ret < 0) {
227		dev_err(tas2780->dev, "%s:errCode:0x%x enable iSNS error\n",
228			__func__, ret);
229		goto err;
230	}
231	ret = 0;
232err:
233	return ret;
234}
235
236static int tas2780_set_samplerate(
237	struct tas2780_priv *tas2780, int samplerate)
238{
239	struct snd_soc_component *component = tas2780->component;
240	int ramp_rate_val;
241	int ret;
242
243	switch (samplerate) {
244	case 48000:
245		ramp_rate_val = TAS2780_TDM_CFG0_SMP_48KHZ |
246				TAS2780_TDM_CFG0_44_1_48KHZ;
247		break;
248	case 44100:
249		ramp_rate_val = TAS2780_TDM_CFG0_SMP_44_1KHZ |
250				TAS2780_TDM_CFG0_44_1_48KHZ;
251		break;
252	case 96000:
253		ramp_rate_val = TAS2780_TDM_CFG0_SMP_48KHZ |
254				TAS2780_TDM_CFG0_88_2_96KHZ;
255		break;
256	case 88200:
257		ramp_rate_val = TAS2780_TDM_CFG0_SMP_44_1KHZ |
258				TAS2780_TDM_CFG0_88_2_96KHZ;
259		break;
260	default:
261		return -EINVAL;
262	}
263	ret = snd_soc_component_update_bits(component, TAS2780_TDM_CFG0,
264		TAS2780_TDM_CFG0_SMP_MASK | TAS2780_TDM_CFG0_MASK,
265		ramp_rate_val);
266	if (ret < 0) {
267		dev_err(tas2780->dev,
268			"%s:errCode:0x%x Failed to set ramp_rate_val\n",
269			__func__, ret);
270		goto err;
271	}
272	ret = 0;
273err:
274	return ret;
275}
276
277static int tas2780_hw_params(struct snd_pcm_substream *substream,
278	struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
279{
280	struct snd_soc_component *component = dai->component;
281	struct tas2780_priv *tas2780 =
282		snd_soc_component_get_drvdata(component);
283	int ret;
284
285	ret = tas2780_set_bitwidth(tas2780, params_format(params));
286	if (ret < 0)
287		return ret;
288
289	return tas2780_set_samplerate(tas2780, params_rate(params));
290}
291
292static int tas2780_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
293{
294	struct snd_soc_component *component = dai->component;
295	struct tas2780_priv *tas2780 =
296		snd_soc_component_get_drvdata(component);
297	u8 tdm_rx_start_slot = 0, asi_cfg_1 = 0;
298	int iface;
299	int ret = 0;
300
301	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
302	case SND_SOC_DAIFMT_NB_NF:
303		asi_cfg_1 = TAS2780_TDM_CFG1_RX_RISING;
304		break;
305	case SND_SOC_DAIFMT_IB_NF:
306		asi_cfg_1 = TAS2780_TDM_CFG1_RX_FALLING;
307		break;
308	default:
309		dev_err(tas2780->dev, "ASI format Inverse is not found\n");
310		return -EINVAL;
311	}
312
313	ret = snd_soc_component_update_bits(component, TAS2780_TDM_CFG1,
314		TAS2780_TDM_CFG1_RX_MASK, asi_cfg_1);
315	if (ret < 0) {
316		dev_err(tas2780->dev,
317			"%s:errCode:0x%x Failed to set asi_cfg_1\n",
318			__func__, ret);
319		goto err;
320	}
321
322	if (((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S)
323		|| ((fmt & SND_SOC_DAIFMT_FORMAT_MASK)
324		== SND_SOC_DAIFMT_DSP_A)){
325		iface = TAS2780_TDM_CFG2_SCFG_I2S;
326		tdm_rx_start_slot = 1;
327	} else {
328		if (((fmt & SND_SOC_DAIFMT_FORMAT_MASK)
329			== SND_SOC_DAIFMT_DSP_B)
330			|| ((fmt & SND_SOC_DAIFMT_FORMAT_MASK)
331			== SND_SOC_DAIFMT_LEFT_J)) {
332			iface = TAS2780_TDM_CFG2_SCFG_LEFT_J;
333			tdm_rx_start_slot = 0;
334		} else {
335			dev_err(tas2780->dev,
336				"%s:DAI Format is not found, fmt=0x%x\n",
337				__func__, fmt);
338			ret = -EINVAL;
339			goto err;
340		}
341	}
342	ret = snd_soc_component_update_bits(component, TAS2780_TDM_CFG1,
343		TAS2780_TDM_CFG1_MASK,
344		(tdm_rx_start_slot << TAS2780_TDM_CFG1_51_SHIFT));
345	if (ret < 0) {
346		dev_err(tas2780->dev,
347			"%s:errCode:0x%x Failed to set tdm_rx_start_slot\n",
348			__func__, ret);
349		goto err;
350	}
351
352	ret = snd_soc_component_update_bits(component, TAS2780_TDM_CFG2,
353		TAS2780_TDM_CFG2_SCFG_MASK, iface);
354	if (ret < 0) {
355		dev_err(tas2780->dev, "%s:errCode:0x%x Failed to set iface\n",
356			__func__, ret);
357		goto err;
358	}
359	ret = 0;
360err:
361	return ret;
362}
363
364static int tas2780_set_dai_tdm_slot(struct snd_soc_dai *dai,
365				unsigned int tx_mask,
366				unsigned int rx_mask,
367				int slots, int slot_width)
368{
369	struct snd_soc_component *component = dai->component;
370	struct tas2780_priv *tas2780 =
371		snd_soc_component_get_drvdata(component);
372	int left_slot, right_slot;
373	int slots_cfg;
374	int slot_size;
375	int ret = 0;
376
377	if (tx_mask == 0 || rx_mask != 0)
378		return -EINVAL;
379
380	left_slot = __ffs(tx_mask);
381	tx_mask &= ~(1 << left_slot);
382	if (tx_mask == 0) {
383		right_slot = left_slot;
384	} else {
385		right_slot = __ffs(tx_mask);
386		tx_mask &= ~(1 << right_slot);
387	}
388
389	if (tx_mask != 0 || left_slot >= slots || right_slot >= slots)
390		return -EINVAL;
391
392	slots_cfg = (right_slot << TAS2780_TDM_CFG3_RXS_SHIFT) | left_slot;
393	ret = snd_soc_component_write(component, TAS2780_TDM_CFG3, slots_cfg);
394	if (ret) {
395		dev_err(tas2780->dev,
396			"%s:errCode:0x%x Failed to set slots_cfg\n",
397			__func__, ret);
398		goto err;
399	}
400
401	switch (slot_width) {
402	case 16:
403		slot_size = TAS2780_TDM_CFG2_RXS_16BITS;
404		break;
405	case 24:
406		slot_size = TAS2780_TDM_CFG2_RXS_24BITS;
407		break;
408	case 32:
409		slot_size = TAS2780_TDM_CFG2_RXS_32BITS;
410		break;
411	default:
412		ret = -EINVAL;
413		goto err;
414	}
415
416	ret = snd_soc_component_update_bits(component, TAS2780_TDM_CFG2,
417		TAS2780_TDM_CFG2_RXS_MASK, slot_size);
418	if (ret < 0) {
419		dev_err(tas2780->dev,
420			"%s:errCode:0x%x Failed to set slot_size\n",
421			__func__, ret);
422		goto err;
423	}
424
425	ret = snd_soc_component_update_bits(component, TAS2780_TDM_CFG5,
426		TAS2780_TDM_CFG5_50_MASK, tas2780->v_sense_slot);
427	if (ret < 0) {
428		dev_err(tas2780->dev,
429			"%s:errCode:0x%x Failed to set v_sense_slot\n",
430			__func__, ret);
431		goto err;
432	}
433
434	ret = snd_soc_component_update_bits(component, TAS2780_TDM_CFG6,
435		TAS2780_TDM_CFG6_50_MASK, tas2780->i_sense_slot);
436	if (ret < 0) {
437		dev_err(tas2780->dev,
438			"%s:errCode:0x%x Failed to set i_sense_slot\n",
439			__func__, ret);
440		goto err;
441	}
442	ret = 0;
443err:
444	return ret;
445}
446
447static const struct snd_soc_dai_ops tas2780_dai_ops = {
448	.mute_stream = tas2780_mute,
449	.hw_params  = tas2780_hw_params,
450	.set_fmt    = tas2780_set_fmt,
451	.set_tdm_slot = tas2780_set_dai_tdm_slot,
452	.no_capture_mute = 1,
453};
454
455#define TAS2780_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
456			 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
457
458#define TAS2780_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\
459		       SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_88200)
460
461static struct snd_soc_dai_driver tas2780_dai_driver[] = {
462	{
463		.name = "tas2780 ASI1",
464		.id = 0,
465		.playback = {
466			.stream_name    = "ASI1 Playback",
467			.channels_min   = 2,
468			.channels_max   = 2,
469			.rates      = TAS2780_RATES,
470			.formats    = TAS2780_FORMATS,
471		},
472		.capture = {
473			.stream_name    = "ASI1 Capture",
474			.channels_min   = 1,
475			.channels_max   = 2,
476			.rates = TAS2780_RATES,
477			.formats = TAS2780_FORMATS,
478		},
479		.ops = &tas2780_dai_ops,
480		.symmetric_rate = 1,
481	},
482};
483
484static int tas2780_codec_probe(struct snd_soc_component *component)
485{
486	struct tas2780_priv *tas2780 =
487		snd_soc_component_get_drvdata(component);
488	int ret = 0;
489
490	tas2780->component = component;
491
492	tas2780_reset(tas2780);
493	ret = snd_soc_component_update_bits(component,
494			TAS2780_IC_CFG, TAS2780_IC_CFG_MASK,
495			TAS2780_IC_CFG_ENABLE);
496	if (ret < 0)
497		dev_err(tas2780->dev, "%s:errCode:0x%0x\n",
498			__func__, ret);
499
500	return ret;
501}
502
503static DECLARE_TLV_DB_SCALE(tas2780_digital_tlv, 1100, 50, 0);
504static DECLARE_TLV_DB_SCALE(tas2780_playback_volume, -10000, 50, 0);
505
506static const struct snd_kcontrol_new tas2780_snd_controls[] = {
507	SOC_SINGLE_TLV("Speaker Volume", TAS2780_DVC, 0,
508		       TAS2780_DVC_MAX, 1, tas2780_playback_volume),
509	SOC_SINGLE_TLV("Amp Gain Volume", TAS2780_CHNL_0, 0, 0x14, 0,
510		       tas2780_digital_tlv),
511};
512
513static const struct snd_soc_component_driver soc_component_driver_tas2780 = {
514	.probe			= tas2780_codec_probe,
515#ifdef CONFIG_PM
516	.suspend		= tas2780_codec_suspend,
517	.resume			= tas2780_codec_resume,
518#endif
519	.controls		= tas2780_snd_controls,
520	.num_controls		= ARRAY_SIZE(tas2780_snd_controls),
521	.dapm_widgets		= tas2780_dapm_widgets,
522	.num_dapm_widgets	= ARRAY_SIZE(tas2780_dapm_widgets),
523	.dapm_routes		= tas2780_audio_map,
524	.num_dapm_routes	= ARRAY_SIZE(tas2780_audio_map),
525	.idle_bias_on		= 1,
526	.endianness		= 1,
527};
528
529static const struct reg_default tas2780_reg_defaults[] = {
530	{ TAS2780_PAGE, 0x00 },
531	{ TAS2780_SW_RST, 0x00 },
532	{ TAS2780_PWR_CTRL, 0x1a },
533	{ TAS2780_DVC, 0x00 },
534	{ TAS2780_CHNL_0, 0x00 },
535	{ TAS2780_TDM_CFG0, 0x09 },
536	{ TAS2780_TDM_CFG1, 0x02 },
537	{ TAS2780_TDM_CFG2, 0x0a },
538	{ TAS2780_TDM_CFG3, 0x10 },
539	{ TAS2780_TDM_CFG5, 0x42 },
540};
541
542static const struct regmap_range_cfg tas2780_regmap_ranges[] = {
543	{
544		.range_min = 0,
545		.range_max = 1 * 128,
546		.selector_reg = TAS2780_PAGE,
547		.selector_mask = 0xff,
548		.selector_shift = 0,
549		.window_start = 0,
550		.window_len = 128,
551	},
552};
553
554static const struct regmap_config tas2780_i2c_regmap = {
555	.reg_bits = 8,
556	.val_bits = 8,
557	.reg_defaults = tas2780_reg_defaults,
558	.num_reg_defaults = ARRAY_SIZE(tas2780_reg_defaults),
559	.cache_type = REGCACHE_RBTREE,
560	.ranges = tas2780_regmap_ranges,
561	.num_ranges = ARRAY_SIZE(tas2780_regmap_ranges),
562	.max_register = 1 * 128,
563};
564
565static int tas2780_parse_dt(struct device *dev, struct tas2780_priv *tas2780)
566{
567	int ret = 0;
568
569	tas2780->reset_gpio = devm_gpiod_get_optional(tas2780->dev, "reset",
570		GPIOD_OUT_HIGH);
571	if (IS_ERR(tas2780->reset_gpio)) {
572		if (PTR_ERR(tas2780->reset_gpio) == -EPROBE_DEFER) {
573			tas2780->reset_gpio = NULL;
574			return -EPROBE_DEFER;
575		}
576	}
577
578	ret = fwnode_property_read_u32(dev->fwnode, "ti,imon-slot-no",
579		&tas2780->i_sense_slot);
580	if (ret)
581		tas2780->i_sense_slot = 0;
582
583	ret = fwnode_property_read_u32(dev->fwnode, "ti,vmon-slot-no",
584		&tas2780->v_sense_slot);
585	if (ret)
586		tas2780->v_sense_slot = 2;
587
588	return 0;
589}
590
591static int tas2780_i2c_probe(struct i2c_client *client)
592{
593	struct tas2780_priv *tas2780;
594	int result;
595
596	tas2780 = devm_kzalloc(&client->dev, sizeof(struct tas2780_priv),
597		GFP_KERNEL);
598	if (!tas2780)
599		return -ENOMEM;
600	tas2780->dev = &client->dev;
601	i2c_set_clientdata(client, tas2780);
602	dev_set_drvdata(&client->dev, tas2780);
603
604	tas2780->regmap = devm_regmap_init_i2c(client, &tas2780_i2c_regmap);
605	if (IS_ERR(tas2780->regmap)) {
606		result = PTR_ERR(tas2780->regmap);
607		dev_err(&client->dev, "Failed to allocate register map: %d\n",
608			result);
609		return result;
610	}
611
612	if (client->dev.of_node) {
613		result = tas2780_parse_dt(&client->dev, tas2780);
614		if (result) {
615			dev_err(tas2780->dev,
616				"%s: Failed to parse devicetree\n", __func__);
617			return result;
618		}
619	}
620
621	return devm_snd_soc_register_component(tas2780->dev,
622		&soc_component_driver_tas2780, tas2780_dai_driver,
623		ARRAY_SIZE(tas2780_dai_driver));
624}
625
626static const struct i2c_device_id tas2780_i2c_id[] = {
627	{ "tas2780"},
628	{ }
629};
630MODULE_DEVICE_TABLE(i2c, tas2780_i2c_id);
631
632#if defined(CONFIG_OF)
633static const struct of_device_id tas2780_of_match[] = {
634	{ .compatible = "ti,tas2780" },
635	{},
636};
637MODULE_DEVICE_TABLE(of, tas2780_of_match);
638#endif
639
640static struct i2c_driver tas2780_i2c_driver = {
641	.driver = {
642		.name   = "tas2780",
643		.of_match_table = of_match_ptr(tas2780_of_match),
644	},
645	.probe      = tas2780_i2c_probe,
646	.id_table   = tas2780_i2c_id,
647};
648module_i2c_driver(tas2780_i2c_driver);
649
650MODULE_AUTHOR("Raphael Xu <raphael-xu@ti.com>");
651MODULE_DESCRIPTION("TAS2780 I2C Smart Amplifier driver");
652MODULE_LICENSE("GPL");