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_component
*component
;
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_component
*component
= snd_soc_dapm_to_component(w
->dapm
);
94 case SND_SOC_DAPM_POST_PMU
:
95 snd_soc_component_write(component
, TAS2552_RESERVED_0D
, 0xc0);
96 snd_soc_component_update_bits(component
, TAS2552_LIMIT_RATE_HYS
, (1 << 5),
98 snd_soc_component_update_bits(component
, TAS2552_CFG_2
, 1, 0);
99 snd_soc_component_update_bits(component
, TAS2552_CFG_1
, TAS2552_SWS
, 0);
101 case SND_SOC_DAPM_POST_PMD
:
102 snd_soc_component_update_bits(component
, TAS2552_CFG_1
, TAS2552_SWS
,
104 snd_soc_component_update_bits(component
, TAS2552_CFG_2
, 1, 1);
105 snd_soc_component_update_bits(component
, TAS2552_LIMIT_RATE_HYS
, (1 << 5), 0);
106 snd_soc_component_write(component
, 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
)
152 if (!tas2552
->component
)
156 cfg1_reg
= TAS2552_SWS
;
158 snd_soc_component_update_bits(tas2552
->component
, TAS2552_CFG_1
, TAS2552_SWS
,
163 static int tas2552_setup_pll(struct snd_soc_component
*component
,
164 struct snd_pcm_hw_params
*params
)
166 struct tas2552_data
*tas2552
= dev_get_drvdata(component
->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_component_read32(component
, TAS2552_CFG_2
) & TAS2552_PLL_ENABLE
;
181 snd_soc_component_update_bits(component
, TAS2552_CFG_2
, TAS2552_PLL_ENABLE
, 0);
183 if (pll_clkin
== pll_clk
)
187 /* By pass the PLL configuration */
188 snd_soc_component_update_bits(component
, 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
195 unsigned int d
, q
, t
;
197 u8 pll_sel
= (tas2552
->pll_clk_id
<< 3) & TAS2552_PLL_SRC_MASK
;
198 u8 p
= snd_soc_component_read32(component
, TAS2552_PLL_CTRL_1
);
203 t
= (pll_clk
* 2) << p
;
206 t
= pll_clkin
/ 10000;
208 d
= q
+ ((9999 - pll_clkin
% 10000) * (d
/ t
- q
)) / 10000;
210 if (d
&& (pll_clkin
< 512000 || pll_clkin
> 9200000)) {
211 if (tas2552
->pll_clk_id
== TAS2552_PLL_CLKIN_BCLK
) {
213 pll_sel
= (TAS2552_PLL_CLKIN_1_8_FIXED
<< 3) &
214 TAS2552_PLL_SRC_MASK
;
216 pll_clkin
= snd_soc_params_to_bclk(params
);
217 pll_clkin
+= tas2552
->tdm_delay
;
218 pll_sel
= (TAS2552_PLL_CLKIN_BCLK
<< 3) &
219 TAS2552_PLL_SRC_MASK
;
224 snd_soc_component_update_bits(component
, TAS2552_CFG_1
, TAS2552_PLL_SRC_MASK
,
227 snd_soc_component_update_bits(component
, TAS2552_PLL_CTRL_1
,
228 TAS2552_PLL_J_MASK
, j
);
229 /* Will clear the PLL_BYPASS bit */
230 snd_soc_component_write(component
, TAS2552_PLL_CTRL_2
,
231 TAS2552_PLL_D_UPPER(d
));
232 snd_soc_component_write(component
, TAS2552_PLL_CTRL_3
,
233 TAS2552_PLL_D_LOWER(d
));
236 /* Restore PLL status */
237 snd_soc_component_update_bits(component
, TAS2552_CFG_2
, TAS2552_PLL_ENABLE
,
243 static int tas2552_hw_params(struct snd_pcm_substream
*substream
,
244 struct snd_pcm_hw_params
*params
,
245 struct snd_soc_dai
*dai
)
247 struct snd_soc_component
*component
= dai
->component
;
248 struct tas2552_data
*tas2552
= dev_get_drvdata(component
->dev
);
250 u8 ser_ctrl1_reg
, wclk_rate
;
252 switch (params_width(params
)) {
254 ser_ctrl1_reg
= TAS2552_WORDLENGTH_16BIT
;
255 cpf
= 32 + tas2552
->tdm_delay
;
258 ser_ctrl1_reg
= TAS2552_WORDLENGTH_20BIT
;
259 cpf
= 64 + tas2552
->tdm_delay
;
262 ser_ctrl1_reg
= TAS2552_WORDLENGTH_24BIT
;
263 cpf
= 64 + tas2552
->tdm_delay
;
266 ser_ctrl1_reg
= TAS2552_WORDLENGTH_32BIT
;
267 cpf
= 64 + tas2552
->tdm_delay
;
270 dev_err(component
->dev
, "Not supported sample size: %d\n",
271 params_width(params
));
276 ser_ctrl1_reg
|= TAS2552_CLKSPERFRAME_32
;
278 ser_ctrl1_reg
|= TAS2552_CLKSPERFRAME_64
;
280 ser_ctrl1_reg
|= TAS2552_CLKSPERFRAME_128
;
282 ser_ctrl1_reg
|= TAS2552_CLKSPERFRAME_256
;
284 snd_soc_component_update_bits(component
, TAS2552_SER_CTRL_1
,
285 TAS2552_WORDLENGTH_MASK
| TAS2552_CLKSPERFRAME_MASK
,
288 switch (params_rate(params
)) {
290 wclk_rate
= TAS2552_WCLK_FREQ_8KHZ
;
294 wclk_rate
= TAS2552_WCLK_FREQ_11_12KHZ
;
297 wclk_rate
= TAS2552_WCLK_FREQ_16KHZ
;
301 wclk_rate
= TAS2552_WCLK_FREQ_22_24KHZ
;
304 wclk_rate
= TAS2552_WCLK_FREQ_32KHZ
;
308 wclk_rate
= TAS2552_WCLK_FREQ_44_48KHZ
;
312 wclk_rate
= TAS2552_WCLK_FREQ_88_96KHZ
;
316 wclk_rate
= TAS2552_WCLK_FREQ_176_192KHZ
;
319 dev_err(component
->dev
, "Not supported sample rate: %d\n",
320 params_rate(params
));
324 snd_soc_component_update_bits(component
, TAS2552_CFG_3
, TAS2552_WCLK_FREQ_MASK
,
327 return tas2552_setup_pll(component
, params
);
330 #define TAS2552_DAI_FMT_MASK (TAS2552_BCLKDIR | \
332 TAS2552_DATAFORMAT_MASK)
333 static int tas2552_prepare(struct snd_pcm_substream
*substream
,
334 struct snd_soc_dai
*dai
)
336 struct snd_soc_component
*component
= dai
->component
;
337 struct tas2552_data
*tas2552
= snd_soc_component_get_drvdata(component
);
340 /* TDM slot selection only valid in DSP_A/_B mode */
341 if (tas2552
->dai_fmt
== SND_SOC_DAIFMT_DSP_A
)
342 delay
+= (tas2552
->tdm_delay
+ 1);
343 else if (tas2552
->dai_fmt
== SND_SOC_DAIFMT_DSP_B
)
344 delay
+= tas2552
->tdm_delay
;
346 /* Configure data delay */
347 snd_soc_component_write(component
, TAS2552_SER_CTRL_2
, delay
);
352 static int tas2552_set_dai_fmt(struct snd_soc_dai
*dai
, unsigned int fmt
)
354 struct snd_soc_component
*component
= dai
->component
;
355 struct tas2552_data
*tas2552
= dev_get_drvdata(component
->dev
);
358 switch (fmt
& SND_SOC_DAIFMT_MASTER_MASK
) {
359 case SND_SOC_DAIFMT_CBS_CFS
:
360 serial_format
= 0x00;
362 case SND_SOC_DAIFMT_CBS_CFM
:
363 serial_format
= TAS2552_WCLKDIR
;
365 case SND_SOC_DAIFMT_CBM_CFS
:
366 serial_format
= TAS2552_BCLKDIR
;
368 case SND_SOC_DAIFMT_CBM_CFM
:
369 serial_format
= (TAS2552_BCLKDIR
| TAS2552_WCLKDIR
);
372 dev_vdbg(component
->dev
, "DAI Format master is not found\n");
376 switch (fmt
& (SND_SOC_DAIFMT_FORMAT_MASK
|
377 SND_SOC_DAIFMT_INV_MASK
)) {
378 case (SND_SOC_DAIFMT_I2S
| SND_SOC_DAIFMT_NB_NF
):
380 case (SND_SOC_DAIFMT_DSP_A
| SND_SOC_DAIFMT_IB_NF
):
381 case (SND_SOC_DAIFMT_DSP_B
| SND_SOC_DAIFMT_IB_NF
):
382 serial_format
|= TAS2552_DATAFORMAT_DSP
;
384 case (SND_SOC_DAIFMT_RIGHT_J
| SND_SOC_DAIFMT_NB_NF
):
385 serial_format
|= TAS2552_DATAFORMAT_RIGHT_J
;
387 case (SND_SOC_DAIFMT_LEFT_J
| SND_SOC_DAIFMT_NB_NF
):
388 serial_format
|= TAS2552_DATAFORMAT_LEFT_J
;
391 dev_vdbg(component
->dev
, "DAI Format is not found\n");
394 tas2552
->dai_fmt
= fmt
& SND_SOC_DAIFMT_FORMAT_MASK
;
396 snd_soc_component_update_bits(component
, TAS2552_SER_CTRL_1
, TAS2552_DAI_FMT_MASK
,
401 static int tas2552_set_dai_sysclk(struct snd_soc_dai
*dai
, int clk_id
,
402 unsigned int freq
, int dir
)
404 struct snd_soc_component
*component
= dai
->component
;
405 struct tas2552_data
*tas2552
= dev_get_drvdata(component
->dev
);
409 case TAS2552_PLL_CLKIN_MCLK
:
410 case TAS2552_PLL_CLKIN_IVCLKIN
:
411 if (freq
< 512000 || freq
> 24576000) {
412 /* out of range PLL_CLKIN, fall back to use BCLK */
413 dev_warn(component
->dev
, "Out of range PLL_CLKIN: %u\n",
415 clk_id
= TAS2552_PLL_CLKIN_BCLK
;
419 case TAS2552_PLL_CLKIN_BCLK
:
420 case TAS2552_PLL_CLKIN_1_8_FIXED
:
421 mask
= TAS2552_PLL_SRC_MASK
;
422 val
= (clk_id
<< 3) & mask
; /* bit 4:5 in the register */
424 tas2552
->pll_clk_id
= clk_id
;
425 tas2552
->pll_clkin
= freq
;
427 case TAS2552_PDM_CLK_PLL
:
428 case TAS2552_PDM_CLK_IVCLKIN
:
429 case TAS2552_PDM_CLK_BCLK
:
430 case TAS2552_PDM_CLK_MCLK
:
431 mask
= TAS2552_PDM_CLK_SEL_MASK
;
432 val
= (clk_id
>> 1) & mask
; /* bit 0:1 in the register */
433 reg
= TAS2552_PDM_CFG
;
434 tas2552
->pdm_clk_id
= clk_id
;
435 tas2552
->pdm_clk
= freq
;
438 dev_err(component
->dev
, "Invalid clk id: %d\n", clk_id
);
442 snd_soc_component_update_bits(component
, reg
, mask
, val
);
447 static int tas2552_set_dai_tdm_slot(struct snd_soc_dai
*dai
,
448 unsigned int tx_mask
, unsigned int rx_mask
,
449 int slots
, int slot_width
)
451 struct snd_soc_component
*component
= dai
->component
;
452 struct tas2552_data
*tas2552
= snd_soc_component_get_drvdata(component
);
455 if (unlikely(!tx_mask
)) {
456 dev_err(component
->dev
, "tx masks need to be non 0\n");
460 /* TDM based on DSP mode requires slots to be adjacent */
461 lsb
= __ffs(tx_mask
);
462 if ((lsb
+ 1) != __fls(tx_mask
)) {
463 dev_err(component
->dev
, "Invalid mask, slots must be adjacent\n");
467 tas2552
->tdm_delay
= lsb
* slot_width
;
469 /* DOUT in high-impedance on inactive bit clocks */
470 snd_soc_component_update_bits(component
, TAS2552_DOUT
,
471 TAS2552_SDOUT_TRISTATE
, TAS2552_SDOUT_TRISTATE
);
476 static int tas2552_mute(struct snd_soc_dai
*dai
, int mute
)
479 struct snd_soc_component
*component
= dai
->component
;
482 cfg1_reg
|= TAS2552_MUTE
;
484 snd_soc_component_update_bits(component
, TAS2552_CFG_1
, TAS2552_MUTE
, cfg1_reg
);
490 static int tas2552_runtime_suspend(struct device
*dev
)
492 struct tas2552_data
*tas2552
= dev_get_drvdata(dev
);
494 tas2552_sw_shutdown(tas2552
, 1);
496 regcache_cache_only(tas2552
->regmap
, true);
497 regcache_mark_dirty(tas2552
->regmap
);
499 gpiod_set_value(tas2552
->enable_gpio
, 0);
504 static int tas2552_runtime_resume(struct device
*dev
)
506 struct tas2552_data
*tas2552
= dev_get_drvdata(dev
);
508 gpiod_set_value(tas2552
->enable_gpio
, 1);
510 tas2552_sw_shutdown(tas2552
, 0);
512 regcache_cache_only(tas2552
->regmap
, false);
513 regcache_sync(tas2552
->regmap
);
519 static const struct dev_pm_ops tas2552_pm
= {
520 SET_RUNTIME_PM_OPS(tas2552_runtime_suspend
, tas2552_runtime_resume
,
524 static const struct snd_soc_dai_ops tas2552_speaker_dai_ops
= {
525 .hw_params
= tas2552_hw_params
,
526 .prepare
= tas2552_prepare
,
527 .set_sysclk
= tas2552_set_dai_sysclk
,
528 .set_fmt
= tas2552_set_dai_fmt
,
529 .set_tdm_slot
= tas2552_set_dai_tdm_slot
,
530 .digital_mute
= tas2552_mute
,
533 /* Formats supported by TAS2552 driver. */
534 #define TAS2552_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
535 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
537 /* TAS2552 dai structure. */
538 static struct snd_soc_dai_driver tas2552_dai
[] = {
540 .name
= "tas2552-amplifier",
542 .stream_name
= "Playback",
545 .rates
= SNDRV_PCM_RATE_8000_192000
,
546 .formats
= TAS2552_FORMATS
,
548 .ops
= &tas2552_speaker_dai_ops
,
553 * DAC digital volumes. From -7 to 24 dB in 1 dB steps
555 static DECLARE_TLV_DB_SCALE(dac_tlv
, -700, 100, 0);
557 static const char * const tas2552_din_source_select
[] = {
561 "Left + Right average",
563 static SOC_ENUM_SINGLE_DECL(tas2552_din_source_enum
,
565 tas2552_din_source_select
);
567 static const struct snd_kcontrol_new tas2552_snd_controls
[] = {
568 SOC_SINGLE_TLV("Speaker Driver Playback Volume",
569 TAS2552_PGA_GAIN
, 0, 0x1f, 0, dac_tlv
),
570 SOC_ENUM("DIN source", tas2552_din_source_enum
),
573 static int tas2552_component_probe(struct snd_soc_component
*component
)
575 struct tas2552_data
*tas2552
= snd_soc_component_get_drvdata(component
);
578 tas2552
->component
= component
;
580 ret
= regulator_bulk_enable(ARRAY_SIZE(tas2552
->supplies
),
584 dev_err(component
->dev
, "Failed to enable supplies: %d\n",
589 gpiod_set_value(tas2552
->enable_gpio
, 1);
591 ret
= pm_runtime_get_sync(component
->dev
);
593 dev_err(component
->dev
, "Enabling device failed: %d\n",
598 snd_soc_component_update_bits(component
, TAS2552_CFG_1
, TAS2552_MUTE
, TAS2552_MUTE
);
599 snd_soc_component_write(component
, TAS2552_CFG_3
, TAS2552_I2S_OUT_SEL
|
600 TAS2552_DIN_SRC_SEL_AVG_L_R
);
601 snd_soc_component_write(component
, TAS2552_OUTPUT_DATA
,
602 TAS2552_PDM_DATA_SEL_V_I
|
603 TAS2552_R_DATA_OUT(TAS2552_DATA_OUT_V_DATA
));
604 snd_soc_component_write(component
, TAS2552_BOOST_APT_CTRL
, TAS2552_APT_DELAY_200
|
605 TAS2552_APT_THRESH_20_17
);
607 snd_soc_component_write(component
, TAS2552_CFG_2
, TAS2552_BOOST_EN
| TAS2552_APT_EN
|
613 gpiod_set_value(tas2552
->enable_gpio
, 0);
615 regulator_bulk_disable(ARRAY_SIZE(tas2552
->supplies
),
620 static void tas2552_component_remove(struct snd_soc_component
*component
)
622 struct tas2552_data
*tas2552
= snd_soc_component_get_drvdata(component
);
624 pm_runtime_put(component
->dev
);
626 gpiod_set_value(tas2552
->enable_gpio
, 0);
630 static int tas2552_suspend(struct snd_soc_component
*component
)
632 struct tas2552_data
*tas2552
= snd_soc_component_get_drvdata(component
);
635 ret
= regulator_bulk_disable(ARRAY_SIZE(tas2552
->supplies
),
639 dev_err(component
->dev
, "Failed to disable supplies: %d\n",
644 static int tas2552_resume(struct snd_soc_component
*component
)
646 struct tas2552_data
*tas2552
= snd_soc_component_get_drvdata(component
);
649 ret
= regulator_bulk_enable(ARRAY_SIZE(tas2552
->supplies
),
653 dev_err(component
->dev
, "Failed to enable supplies: %d\n",
660 #define tas2552_suspend NULL
661 #define tas2552_resume NULL
664 static const struct snd_soc_component_driver soc_component_dev_tas2552
= {
665 .probe
= tas2552_component_probe
,
666 .remove
= tas2552_component_remove
,
667 .suspend
= tas2552_suspend
,
668 .resume
= tas2552_resume
,
669 .controls
= tas2552_snd_controls
,
670 .num_controls
= ARRAY_SIZE(tas2552_snd_controls
),
671 .dapm_widgets
= tas2552_dapm_widgets
,
672 .num_dapm_widgets
= ARRAY_SIZE(tas2552_dapm_widgets
),
673 .dapm_routes
= tas2552_audio_map
,
674 .num_dapm_routes
= ARRAY_SIZE(tas2552_audio_map
),
677 .non_legacy_dai_naming
= 1,
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
= devm_snd_soc_register_component(&client
->dev
,
737 &soc_component_dev_tas2552
,
738 tas2552_dai
, ARRAY_SIZE(tas2552_dai
));
740 dev_err(&client
->dev
, "Failed to register component: %d\n", ret
);
745 static int tas2552_i2c_remove(struct i2c_client
*client
)
747 pm_runtime_disable(&client
->dev
);
751 static const struct i2c_device_id tas2552_id
[] = {
755 MODULE_DEVICE_TABLE(i2c
, tas2552_id
);
757 #if IS_ENABLED(CONFIG_OF)
758 static const struct of_device_id tas2552_of_match
[] = {
759 { .compatible
= "ti,tas2552", },
762 MODULE_DEVICE_TABLE(of
, tas2552_of_match
);
765 static struct i2c_driver tas2552_i2c_driver
= {
768 .of_match_table
= of_match_ptr(tas2552_of_match
),
771 .probe
= tas2552_probe
,
772 .remove
= tas2552_i2c_remove
,
773 .id_table
= tas2552_id
,
776 module_i2c_driver(tas2552_i2c_driver
);
778 MODULE_AUTHOR("Dan Muprhy <dmurphy@ti.com>");
779 MODULE_DESCRIPTION("TAS2552 Audio amplifier driver");
780 MODULE_LICENSE("GPL");