~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/soc/codecs/tas2780.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php