2 * tas2552.c - ALSA SoC Texas Instruments TAS2552 Mono Audio Amplifier
4 * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com
6 * Author: Dan Murphy <dmurphy@ti.com>
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
18 #include <linux/module.h>
19 #include <linux/errno.h>
20 #include <linux/device.h>
21 #include <linux/i2c.h>
22 #include <linux/gpio.h>
23 #include <linux/of_gpio.h>
24 #include <linux/pm_runtime.h>
25 #include <linux/regmap.h>
26 #include <linux/slab.h>
28 #include <linux/gpio/consumer.h>
29 #include <linux/regulator/consumer.h>
31 #include <sound/pcm.h>
32 #include <sound/pcm_params.h>
33 #include <sound/soc.h>
34 #include <sound/soc-dapm.h>
35 #include <sound/tlv.h>
36 #include <sound/tas2552-plat.h>
37 #include <dt-bindings/sound/tas2552.h>
41 static const struct reg_default tas2552_reg_defs
[] = {
42 {TAS2552_CFG_1
, 0x22},
43 {TAS2552_CFG_3
, 0x80},
45 {TAS2552_OUTPUT_DATA
, 0xc0},
46 {TAS2552_PDM_CFG
, 0x01},
47 {TAS2552_PGA_GAIN
, 0x00},
48 {TAS2552_BOOST_APT_CTRL
, 0x0f},
49 {TAS2552_RESERVED_0D
, 0xbe},
50 {TAS2552_LIMIT_RATE_HYS
, 0x08},
51 {TAS2552_CFG_2
, 0xef},
52 {TAS2552_SER_CTRL_1
, 0x00},
53 {TAS2552_SER_CTRL_2
, 0x00},
54 {TAS2552_PLL_CTRL_1
, 0x10},
55 {TAS2552_PLL_CTRL_2
, 0x00},
56 {TAS2552_PLL_CTRL_3
, 0x00},
58 {TAS2552_BTS_CTRL
, 0x80},
59 {TAS2552_LIMIT_RELEASE
, 0x04},
60 {TAS2552_LIMIT_INT_COUNT
, 0x00},
61 {TAS2552_EDGE_RATE_CTRL
, 0x40},
62 {TAS2552_VBAT_DATA
, 0x00},
65 #define TAS2552_NUM_SUPPLIES 3
66 static const char *tas2552_supply_names
[TAS2552_NUM_SUPPLIES
] = {
67 "vbat", /* vbat voltage */
68 "iovdd", /* I/O Voltage */
69 "avdd", /* Analog DAC Voltage */
73 struct snd_soc_codec
*codec
;
74 struct regmap
*regmap
;
75 struct i2c_client
*tas2552_client
;
76 struct regulator_bulk_data supplies
[TAS2552_NUM_SUPPLIES
];
77 struct gpio_desc
*enable_gpio
;
78 unsigned char regs
[TAS2552_VBAT_DATA
];
79 unsigned int pll_clkin
;
85 unsigned int tdm_delay
;
88 static int tas2552_post_event(struct snd_soc_dapm_widget
*w
,
89 struct snd_kcontrol
*kcontrol
, int event
)
91 struct snd_soc_codec
*codec
= snd_soc_dapm_to_codec(w
->dapm
);
94 case SND_SOC_DAPM_POST_PMU
:
95 snd_soc_write(codec
, TAS2552_RESERVED_0D
, 0xc0);
96 snd_soc_update_bits(codec
, TAS2552_LIMIT_RATE_HYS
, (1 << 5),
98 snd_soc_update_bits(codec
, TAS2552_CFG_2
, 1, 0);
99 snd_soc_update_bits(codec
, TAS2552_CFG_1
, TAS2552_SWS
, 0);
101 case SND_SOC_DAPM_POST_PMD
:
102 snd_soc_update_bits(codec
, TAS2552_CFG_1
, TAS2552_SWS
,
104 snd_soc_update_bits(codec
, TAS2552_CFG_2
, 1, 1);
105 snd_soc_update_bits(codec
, TAS2552_LIMIT_RATE_HYS
, (1 << 5), 0);
106 snd_soc_write(codec
, TAS2552_RESERVED_0D
, 0xbe);
112 /* Input mux controls */
113 static const char * const tas2552_input_texts
[] = {
114 "Digital", "Analog" };
115 static SOC_ENUM_SINGLE_DECL(tas2552_input_mux_enum
, TAS2552_CFG_3
, 7,
116 tas2552_input_texts
);
118 static const struct snd_kcontrol_new tas2552_input_mux_control
=
119 SOC_DAPM_ENUM("Route", tas2552_input_mux_enum
);
121 static const struct snd_soc_dapm_widget tas2552_dapm_widgets
[] =
123 SND_SOC_DAPM_INPUT("IN"),
126 SND_SOC_DAPM_MUX("Input selection", SND_SOC_NOPM
, 0, 0,
127 &tas2552_input_mux_control
),
129 SND_SOC_DAPM_AIF_IN("DAC IN", "DAC Playback", 0, SND_SOC_NOPM
, 0, 0),
130 SND_SOC_DAPM_DAC("DAC", NULL
, SND_SOC_NOPM
, 0, 0),
131 SND_SOC_DAPM_OUT_DRV("ClassD", TAS2552_CFG_2
, 7, 0, NULL
, 0),
132 SND_SOC_DAPM_SUPPLY("PLL", TAS2552_CFG_2
, 3, 0, NULL
, 0),
133 SND_SOC_DAPM_POST("Post Event", tas2552_post_event
),
135 SND_SOC_DAPM_OUTPUT("OUT")
138 static const struct snd_soc_dapm_route tas2552_audio_map
[] = {
139 {"DAC", NULL
, "DAC IN"},
140 {"Input selection", "Digital", "DAC"},
141 {"Input selection", "Analog", "IN"},
142 {"ClassD", NULL
, "Input selection"},
143 {"OUT", NULL
, "ClassD"},
144 {"ClassD", NULL
, "PLL"},
148 static void tas2552_sw_shutdown(struct tas2552_data
*tas2552
, int sw_shutdown
)
156 cfg1_reg
= TAS2552_SWS
;
158 snd_soc_update_bits(tas2552
->codec
, TAS2552_CFG_1
, TAS2552_SWS
,
163 static int tas2552_setup_pll(struct snd_soc_codec
*codec
,
164 struct snd_pcm_hw_params
*params
)
166 struct tas2552_data
*tas2552
= dev_get_drvdata(codec
->dev
);
167 bool bypass_pll
= false;
168 unsigned int pll_clk
= params_rate(params
) * 512;
169 unsigned int pll_clkin
= tas2552
->pll_clkin
;
173 if (tas2552
->pll_clk_id
!= TAS2552_PLL_CLKIN_BCLK
)
176 pll_clkin
= snd_soc_params_to_bclk(params
);
177 pll_clkin
+= tas2552
->tdm_delay
;
180 pll_enable
= snd_soc_read(codec
, TAS2552_CFG_2
) & TAS2552_PLL_ENABLE
;
181 snd_soc_update_bits(codec
, TAS2552_CFG_2
, TAS2552_PLL_ENABLE
, 0);
183 if (pll_clkin
== pll_clk
)
187 /* By pass the PLL configuration */
188 snd_soc_update_bits(codec
, TAS2552_PLL_CTRL_2
,
189 TAS2552_PLL_BYPASS
, TAS2552_PLL_BYPASS
);
191 /* Fill in the PLL control registers for J & D
192 * pll_clk = (.5 * pll_clkin * J.D) / 2^p
193 * Need to fill in J and D here based on incoming freq
197 u8 pll_sel
= (tas2552
->pll_clk_id
<< 3) & TAS2552_PLL_SRC_MASK
;
198 u8 p
= snd_soc_read(codec
, TAS2552_PLL_CTRL_1
);
203 j
= (pll_clk
* 2 * (1 << p
)) / pll_clkin
;
204 d
= (pll_clk
* 2 * (1 << p
)) % pll_clkin
;
205 d
/= (pll_clkin
/ 10000);
207 if (d
&& (pll_clkin
< 512000 || pll_clkin
> 9200000)) {
208 if (tas2552
->pll_clk_id
== TAS2552_PLL_CLKIN_BCLK
) {
210 pll_sel
= (TAS2552_PLL_CLKIN_1_8_FIXED
<< 3) &
211 TAS2552_PLL_SRC_MASK
;
213 pll_clkin
= snd_soc_params_to_bclk(params
);
214 pll_clkin
+= tas2552
->tdm_delay
;
215 pll_sel
= (TAS2552_PLL_CLKIN_BCLK
<< 3) &
216 TAS2552_PLL_SRC_MASK
;
221 snd_soc_update_bits(codec
, TAS2552_CFG_1
, TAS2552_PLL_SRC_MASK
,
224 snd_soc_update_bits(codec
, TAS2552_PLL_CTRL_1
,
225 TAS2552_PLL_J_MASK
, j
);
226 /* Will clear the PLL_BYPASS bit */
227 snd_soc_write(codec
, TAS2552_PLL_CTRL_2
,
228 TAS2552_PLL_D_UPPER(d
));
229 snd_soc_write(codec
, TAS2552_PLL_CTRL_3
,
230 TAS2552_PLL_D_LOWER(d
));
233 /* Restore PLL status */
234 snd_soc_update_bits(codec
, TAS2552_CFG_2
, TAS2552_PLL_ENABLE
,
240 static int tas2552_hw_params(struct snd_pcm_substream
*substream
,
241 struct snd_pcm_hw_params
*params
,
242 struct snd_soc_dai
*dai
)
244 struct snd_soc_codec
*codec
= dai
->codec
;
245 struct tas2552_data
*tas2552
= dev_get_drvdata(codec
->dev
);
247 u8 ser_ctrl1_reg
, wclk_rate
;
249 switch (params_width(params
)) {
251 ser_ctrl1_reg
= TAS2552_WORDLENGTH_16BIT
;
252 cpf
= 32 + tas2552
->tdm_delay
;
255 ser_ctrl1_reg
= TAS2552_WORDLENGTH_20BIT
;
256 cpf
= 64 + tas2552
->tdm_delay
;
259 ser_ctrl1_reg
= TAS2552_WORDLENGTH_24BIT
;
260 cpf
= 64 + tas2552
->tdm_delay
;
263 ser_ctrl1_reg
= TAS2552_WORDLENGTH_32BIT
;
264 cpf
= 64 + tas2552
->tdm_delay
;
267 dev_err(codec
->dev
, "Not supported sample size: %d\n",
268 params_width(params
));
273 ser_ctrl1_reg
|= TAS2552_CLKSPERFRAME_32
;
275 ser_ctrl1_reg
|= TAS2552_CLKSPERFRAME_64
;
277 ser_ctrl1_reg
|= TAS2552_CLKSPERFRAME_128
;
279 ser_ctrl1_reg
|= TAS2552_CLKSPERFRAME_256
;
281 snd_soc_update_bits(codec
, TAS2552_SER_CTRL_1
,
282 TAS2552_WORDLENGTH_MASK
| TAS2552_CLKSPERFRAME_MASK
,
285 switch (params_rate(params
)) {
287 wclk_rate
= TAS2552_WCLK_FREQ_8KHZ
;
291 wclk_rate
= TAS2552_WCLK_FREQ_11_12KHZ
;
294 wclk_rate
= TAS2552_WCLK_FREQ_16KHZ
;
298 wclk_rate
= TAS2552_WCLK_FREQ_22_24KHZ
;
301 wclk_rate
= TAS2552_WCLK_FREQ_32KHZ
;
305 wclk_rate
= TAS2552_WCLK_FREQ_44_48KHZ
;
309 wclk_rate
= TAS2552_WCLK_FREQ_88_96KHZ
;
313 wclk_rate
= TAS2552_WCLK_FREQ_176_192KHZ
;
316 dev_err(codec
->dev
, "Not supported sample rate: %d\n",
317 params_rate(params
));
321 snd_soc_update_bits(codec
, TAS2552_CFG_3
, TAS2552_WCLK_FREQ_MASK
,
324 return tas2552_setup_pll(codec
, params
);
327 #define TAS2552_DAI_FMT_MASK (TAS2552_BCLKDIR | \
329 TAS2552_DATAFORMAT_MASK)
330 static int tas2552_prepare(struct snd_pcm_substream
*substream
,
331 struct snd_soc_dai
*dai
)
333 struct snd_soc_codec
*codec
= dai
->codec
;
334 struct tas2552_data
*tas2552
= snd_soc_codec_get_drvdata(codec
);
337 /* TDM slot selection only valid in DSP_A/_B mode */
338 if (tas2552
->dai_fmt
== SND_SOC_DAIFMT_DSP_A
)
339 delay
+= (tas2552
->tdm_delay
+ 1);
340 else if (tas2552
->dai_fmt
== SND_SOC_DAIFMT_DSP_B
)
341 delay
+= tas2552
->tdm_delay
;
343 /* Configure data delay */
344 snd_soc_write(codec
, TAS2552_SER_CTRL_2
, delay
);
349 static int tas2552_set_dai_fmt(struct snd_soc_dai
*dai
, unsigned int fmt
)
351 struct snd_soc_codec
*codec
= dai
->codec
;
352 struct tas2552_data
*tas2552
= dev_get_drvdata(codec
->dev
);
355 switch (fmt
& SND_SOC_DAIFMT_MASTER_MASK
) {
356 case SND_SOC_DAIFMT_CBS_CFS
:
357 serial_format
= 0x00;
359 case SND_SOC_DAIFMT_CBS_CFM
:
360 serial_format
= TAS2552_WCLKDIR
;
362 case SND_SOC_DAIFMT_CBM_CFS
:
363 serial_format
= TAS2552_BCLKDIR
;
365 case SND_SOC_DAIFMT_CBM_CFM
:
366 serial_format
= (TAS2552_BCLKDIR
| TAS2552_WCLKDIR
);
369 dev_vdbg(codec
->dev
, "DAI Format master is not found\n");
373 switch (fmt
& (SND_SOC_DAIFMT_FORMAT_MASK
|
374 SND_SOC_DAIFMT_INV_MASK
)) {
375 case (SND_SOC_DAIFMT_I2S
| SND_SOC_DAIFMT_NB_NF
):
377 case (SND_SOC_DAIFMT_DSP_A
| SND_SOC_DAIFMT_IB_NF
):
378 case (SND_SOC_DAIFMT_DSP_B
| SND_SOC_DAIFMT_IB_NF
):
379 serial_format
|= TAS2552_DATAFORMAT_DSP
;
381 case (SND_SOC_DAIFMT_RIGHT_J
| SND_SOC_DAIFMT_NB_NF
):
382 serial_format
|= TAS2552_DATAFORMAT_RIGHT_J
;
384 case (SND_SOC_DAIFMT_LEFT_J
| SND_SOC_DAIFMT_NB_NF
):
385 serial_format
|= TAS2552_DATAFORMAT_LEFT_J
;
388 dev_vdbg(codec
->dev
, "DAI Format is not found\n");
391 tas2552
->dai_fmt
= fmt
& SND_SOC_DAIFMT_FORMAT_MASK
;
393 snd_soc_update_bits(codec
, TAS2552_SER_CTRL_1
, TAS2552_DAI_FMT_MASK
,
398 static int tas2552_set_dai_sysclk(struct snd_soc_dai
*dai
, int clk_id
,
399 unsigned int freq
, int dir
)
401 struct snd_soc_codec
*codec
= dai
->codec
;
402 struct tas2552_data
*tas2552
= dev_get_drvdata(codec
->dev
);
406 case TAS2552_PLL_CLKIN_MCLK
:
407 case TAS2552_PLL_CLKIN_IVCLKIN
:
408 if (freq
< 512000 || freq
> 24576000) {
409 /* out of range PLL_CLKIN, fall back to use BCLK */
410 dev_warn(codec
->dev
, "Out of range PLL_CLKIN: %u\n",
412 clk_id
= TAS2552_PLL_CLKIN_BCLK
;
416 case TAS2552_PLL_CLKIN_BCLK
:
417 case TAS2552_PLL_CLKIN_1_8_FIXED
:
418 mask
= TAS2552_PLL_SRC_MASK
;
419 val
= (clk_id
<< 3) & mask
; /* bit 4:5 in the register */
421 tas2552
->pll_clk_id
= clk_id
;
422 tas2552
->pll_clkin
= freq
;
424 case TAS2552_PDM_CLK_PLL
:
425 case TAS2552_PDM_CLK_IVCLKIN
:
426 case TAS2552_PDM_CLK_BCLK
:
427 case TAS2552_PDM_CLK_MCLK
:
428 mask
= TAS2552_PDM_CLK_SEL_MASK
;
429 val
= (clk_id
>> 1) & mask
; /* bit 0:1 in the register */
430 reg
= TAS2552_PDM_CFG
;
431 tas2552
->pdm_clk_id
= clk_id
;
432 tas2552
->pdm_clk
= freq
;
435 dev_err(codec
->dev
, "Invalid clk id: %d\n", clk_id
);
439 snd_soc_update_bits(codec
, reg
, mask
, val
);
444 static int tas2552_set_dai_tdm_slot(struct snd_soc_dai
*dai
,
445 unsigned int tx_mask
, unsigned int rx_mask
,
446 int slots
, int slot_width
)
448 struct snd_soc_codec
*codec
= dai
->codec
;
449 struct tas2552_data
*tas2552
= snd_soc_codec_get_drvdata(codec
);
452 if (unlikely(!tx_mask
)) {
453 dev_err(codec
->dev
, "tx masks need to be non 0\n");
457 /* TDM based on DSP mode requires slots to be adjacent */
458 lsb
= __ffs(tx_mask
);
459 if ((lsb
+ 1) != __fls(tx_mask
)) {
460 dev_err(codec
->dev
, "Invalid mask, slots must be adjacent\n");
464 tas2552
->tdm_delay
= lsb
* slot_width
;
466 /* DOUT in high-impedance on inactive bit clocks */
467 snd_soc_update_bits(codec
, TAS2552_DOUT
,
468 TAS2552_SDOUT_TRISTATE
, TAS2552_SDOUT_TRISTATE
);
473 static int tas2552_mute(struct snd_soc_dai
*dai
, int mute
)
476 struct snd_soc_codec
*codec
= dai
->codec
;
479 cfg1_reg
|= TAS2552_MUTE
;
481 snd_soc_update_bits(codec
, TAS2552_CFG_1
, TAS2552_MUTE
, cfg1_reg
);
487 static int tas2552_runtime_suspend(struct device
*dev
)
489 struct tas2552_data
*tas2552
= dev_get_drvdata(dev
);
491 tas2552_sw_shutdown(tas2552
, 1);
493 regcache_cache_only(tas2552
->regmap
, true);
494 regcache_mark_dirty(tas2552
->regmap
);
496 gpiod_set_value(tas2552
->enable_gpio
, 0);
501 static int tas2552_runtime_resume(struct device
*dev
)
503 struct tas2552_data
*tas2552
= dev_get_drvdata(dev
);
505 gpiod_set_value(tas2552
->enable_gpio
, 1);
507 tas2552_sw_shutdown(tas2552
, 0);
509 regcache_cache_only(tas2552
->regmap
, false);
510 regcache_sync(tas2552
->regmap
);
516 static const struct dev_pm_ops tas2552_pm
= {
517 SET_RUNTIME_PM_OPS(tas2552_runtime_suspend
, tas2552_runtime_resume
,
521 static const struct snd_soc_dai_ops tas2552_speaker_dai_ops
= {
522 .hw_params
= tas2552_hw_params
,
523 .prepare
= tas2552_prepare
,
524 .set_sysclk
= tas2552_set_dai_sysclk
,
525 .set_fmt
= tas2552_set_dai_fmt
,
526 .set_tdm_slot
= tas2552_set_dai_tdm_slot
,
527 .digital_mute
= tas2552_mute
,
530 /* Formats supported by TAS2552 driver. */
531 #define TAS2552_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
532 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
534 /* TAS2552 dai structure. */
535 static struct snd_soc_dai_driver tas2552_dai
[] = {
537 .name
= "tas2552-amplifier",
539 .stream_name
= "Playback",
542 .rates
= SNDRV_PCM_RATE_8000_192000
,
543 .formats
= TAS2552_FORMATS
,
545 .ops
= &tas2552_speaker_dai_ops
,
550 * DAC digital volumes. From -7 to 24 dB in 1 dB steps
552 static DECLARE_TLV_DB_SCALE(dac_tlv
, -700, 100, 0);
554 static const char * const tas2552_din_source_select
[] = {
558 "Left + Right average",
560 static SOC_ENUM_SINGLE_DECL(tas2552_din_source_enum
,
562 tas2552_din_source_select
);
564 static const struct snd_kcontrol_new tas2552_snd_controls
[] = {
565 SOC_SINGLE_TLV("Speaker Driver Playback Volume",
566 TAS2552_PGA_GAIN
, 0, 0x1f, 0, dac_tlv
),
567 SOC_ENUM("DIN source", tas2552_din_source_enum
),
570 static int tas2552_codec_probe(struct snd_soc_codec
*codec
)
572 struct tas2552_data
*tas2552
= snd_soc_codec_get_drvdata(codec
);
575 tas2552
->codec
= codec
;
577 ret
= regulator_bulk_enable(ARRAY_SIZE(tas2552
->supplies
),
581 dev_err(codec
->dev
, "Failed to enable supplies: %d\n",
586 gpiod_set_value(tas2552
->enable_gpio
, 1);
588 ret
= pm_runtime_get_sync(codec
->dev
);
590 dev_err(codec
->dev
, "Enabling device failed: %d\n",
595 snd_soc_update_bits(codec
, TAS2552_CFG_1
, TAS2552_MUTE
, TAS2552_MUTE
);
596 snd_soc_write(codec
, TAS2552_CFG_3
, TAS2552_I2S_OUT_SEL
|
597 TAS2552_DIN_SRC_SEL_AVG_L_R
);
598 snd_soc_write(codec
, TAS2552_OUTPUT_DATA
,
599 TAS2552_PDM_DATA_SEL_V_I
|
600 TAS2552_R_DATA_OUT(TAS2552_DATA_OUT_V_DATA
));
601 snd_soc_write(codec
, TAS2552_BOOST_APT_CTRL
, TAS2552_APT_DELAY_200
|
602 TAS2552_APT_THRESH_20_17
);
604 snd_soc_write(codec
, TAS2552_CFG_2
, TAS2552_BOOST_EN
| TAS2552_APT_EN
|
610 gpiod_set_value(tas2552
->enable_gpio
, 0);
612 regulator_bulk_disable(ARRAY_SIZE(tas2552
->supplies
),
617 static int tas2552_codec_remove(struct snd_soc_codec
*codec
)
619 struct tas2552_data
*tas2552
= snd_soc_codec_get_drvdata(codec
);
621 pm_runtime_put(codec
->dev
);
623 gpiod_set_value(tas2552
->enable_gpio
, 0);
629 static int tas2552_suspend(struct snd_soc_codec
*codec
)
631 struct tas2552_data
*tas2552
= snd_soc_codec_get_drvdata(codec
);
634 ret
= regulator_bulk_disable(ARRAY_SIZE(tas2552
->supplies
),
638 dev_err(codec
->dev
, "Failed to disable supplies: %d\n",
643 static int tas2552_resume(struct snd_soc_codec
*codec
)
645 struct tas2552_data
*tas2552
= snd_soc_codec_get_drvdata(codec
);
648 ret
= regulator_bulk_enable(ARRAY_SIZE(tas2552
->supplies
),
652 dev_err(codec
->dev
, "Failed to enable supplies: %d\n",
659 #define tas2552_suspend NULL
660 #define tas2552_resume NULL
663 static struct snd_soc_codec_driver soc_codec_dev_tas2552
= {
664 .probe
= tas2552_codec_probe
,
665 .remove
= tas2552_codec_remove
,
666 .suspend
= tas2552_suspend
,
667 .resume
= tas2552_resume
,
668 .ignore_pmdown_time
= true,
670 .component_driver
= {
671 .controls
= tas2552_snd_controls
,
672 .num_controls
= ARRAY_SIZE(tas2552_snd_controls
),
673 .dapm_widgets
= tas2552_dapm_widgets
,
674 .num_dapm_widgets
= ARRAY_SIZE(tas2552_dapm_widgets
),
675 .dapm_routes
= tas2552_audio_map
,
676 .num_dapm_routes
= ARRAY_SIZE(tas2552_audio_map
),
680 static const struct regmap_config tas2552_regmap_config
= {
684 .max_register
= TAS2552_MAX_REG
,
685 .reg_defaults
= tas2552_reg_defs
,
686 .num_reg_defaults
= ARRAY_SIZE(tas2552_reg_defs
),
687 .cache_type
= REGCACHE_RBTREE
,
690 static int tas2552_probe(struct i2c_client
*client
,
691 const struct i2c_device_id
*id
)
694 struct tas2552_data
*data
;
699 data
= devm_kzalloc(&client
->dev
, sizeof(*data
), GFP_KERNEL
);
703 data
->enable_gpio
= devm_gpiod_get_optional(dev
, "enable",
705 if (IS_ERR(data
->enable_gpio
))
706 return PTR_ERR(data
->enable_gpio
);
708 data
->tas2552_client
= client
;
709 data
->regmap
= devm_regmap_init_i2c(client
, &tas2552_regmap_config
);
710 if (IS_ERR(data
->regmap
)) {
711 ret
= PTR_ERR(data
->regmap
);
712 dev_err(&client
->dev
, "Failed to allocate register map: %d\n",
717 for (i
= 0; i
< ARRAY_SIZE(data
->supplies
); i
++)
718 data
->supplies
[i
].supply
= tas2552_supply_names
[i
];
720 ret
= devm_regulator_bulk_get(dev
, ARRAY_SIZE(data
->supplies
),
723 dev_err(dev
, "Failed to request supplies: %d\n", ret
);
727 pm_runtime_set_active(&client
->dev
);
728 pm_runtime_set_autosuspend_delay(&client
->dev
, 1000);
729 pm_runtime_use_autosuspend(&client
->dev
);
730 pm_runtime_enable(&client
->dev
);
731 pm_runtime_mark_last_busy(&client
->dev
);
732 pm_runtime_put_sync_autosuspend(&client
->dev
);
734 dev_set_drvdata(&client
->dev
, data
);
736 ret
= snd_soc_register_codec(&client
->dev
,
737 &soc_codec_dev_tas2552
,
738 tas2552_dai
, ARRAY_SIZE(tas2552_dai
));
740 dev_err(&client
->dev
, "Failed to register codec: %d\n", ret
);
745 static int tas2552_i2c_remove(struct i2c_client
*client
)
747 snd_soc_unregister_codec(&client
->dev
);
748 pm_runtime_disable(&client
->dev
);
752 static const struct i2c_device_id tas2552_id
[] = {
756 MODULE_DEVICE_TABLE(i2c
, tas2552_id
);
758 #if IS_ENABLED(CONFIG_OF)
759 static const struct of_device_id tas2552_of_match
[] = {
760 { .compatible
= "ti,tas2552", },
763 MODULE_DEVICE_TABLE(of
, tas2552_of_match
);
766 static struct i2c_driver tas2552_i2c_driver
= {
769 .of_match_table
= of_match_ptr(tas2552_of_match
),
772 .probe
= tas2552_probe
,
773 .remove
= tas2552_i2c_remove
,
774 .id_table
= tas2552_id
,
777 module_i2c_driver(tas2552_i2c_driver
);
779 MODULE_AUTHOR("Dan Muprhy <dmurphy@ti.com>");
780 MODULE_DESCRIPTION("TAS2552 Audio amplifier driver");
781 MODULE_LICENSE("GPL");