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>
40 static struct reg_default tas2552_reg_defs
[] = {
41 {TAS2552_CFG_1
, 0x22},
42 {TAS2552_CFG_3
, 0x80},
44 {TAS2552_OUTPUT_DATA
, 0xc0},
45 {TAS2552_PDM_CFG
, 0x01},
46 {TAS2552_PGA_GAIN
, 0x00},
47 {TAS2552_BOOST_PT_CTRL
, 0x0f},
48 {TAS2552_RESERVED_0D
, 0x00},
49 {TAS2552_LIMIT_RATE_HYS
, 0x08},
50 {TAS2552_CFG_2
, 0xef},
51 {TAS2552_SER_CTRL_1
, 0x00},
52 {TAS2552_SER_CTRL_2
, 0x00},
53 {TAS2552_PLL_CTRL_1
, 0x10},
54 {TAS2552_PLL_CTRL_2
, 0x00},
55 {TAS2552_PLL_CTRL_3
, 0x00},
57 {TAS2552_BTS_CTRL
, 0x80},
58 {TAS2552_LIMIT_RELEASE
, 0x04},
59 {TAS2552_LIMIT_INT_COUNT
, 0x00},
60 {TAS2552_EDGE_RATE_CTRL
, 0x40},
61 {TAS2552_VBAT_DATA
, 0x00},
64 #define TAS2552_NUM_SUPPLIES 3
65 static const char *tas2552_supply_names
[TAS2552_NUM_SUPPLIES
] = {
66 "vbat", /* vbat voltage */
67 "iovdd", /* I/O Voltage */
68 "avdd", /* Analog DAC Voltage */
72 struct snd_soc_codec
*codec
;
73 struct regmap
*regmap
;
74 struct i2c_client
*tas2552_client
;
75 struct regulator_bulk_data supplies
[TAS2552_NUM_SUPPLIES
];
76 struct gpio_desc
*enable_gpio
;
77 unsigned char regs
[TAS2552_VBAT_DATA
];
81 static void tas2552_sw_shutdown(struct tas2552_data
*tas_data
, int sw_shutdown
)
88 cfg1_reg
= TAS2552_SWS_MASK
;
90 snd_soc_update_bits(tas_data
->codec
, TAS2552_CFG_1
,
91 TAS2552_SWS_MASK
, cfg1_reg
);
94 static int tas2552_hw_params(struct snd_pcm_substream
*substream
,
95 struct snd_pcm_hw_params
*params
,
96 struct snd_soc_dai
*dai
)
98 struct snd_soc_codec
*codec
= dai
->codec
;
99 struct tas2552_data
*tas2552
= dev_get_drvdata(codec
->dev
);
100 int sample_rate
, pll_clk
;
104 /* Turn on Class D amplifier */
105 snd_soc_update_bits(codec
, TAS2552_CFG_2
, TAS2552_CLASSD_EN_MASK
,
111 snd_soc_update_bits(codec
, TAS2552_CFG_2
, TAS2552_PLL_ENABLE
, 0);
113 if (tas2552
->mclk
== TAS2552_245MHZ_CLK
||
114 tas2552
->mclk
== TAS2552_225MHZ_CLK
) {
115 /* By pass the PLL configuration */
116 snd_soc_update_bits(codec
, TAS2552_PLL_CTRL_2
,
117 TAS2552_PLL_BYPASS_MASK
,
120 /* Fill in the PLL control registers for J & D
121 * PLL_CLK = (.5 * freq * J.D) / 2^p
122 * Need to fill in J and D here based on incoming freq
124 p
= snd_soc_read(codec
, TAS2552_PLL_CTRL_1
);
126 sample_rate
= params_rate(params
);
128 if (sample_rate
== 48000)
129 pll_clk
= TAS2552_245MHZ_CLK
;
130 else if (sample_rate
== 44100)
131 pll_clk
= TAS2552_225MHZ_CLK
;
133 dev_vdbg(codec
->dev
, "Substream sample rate is not found %i\n",
134 params_rate(params
));
138 j
= (pll_clk
* 2 * (1 << p
)) / tas2552
->mclk
;
139 d
= (pll_clk
* 2 * (1 << p
)) % tas2552
->mclk
;
141 snd_soc_update_bits(codec
, TAS2552_PLL_CTRL_1
,
142 TAS2552_PLL_J_MASK
, j
);
143 snd_soc_write(codec
, TAS2552_PLL_CTRL_2
,
144 (d
>> 7) & TAS2552_PLL_D_UPPER_MASK
);
145 snd_soc_write(codec
, TAS2552_PLL_CTRL_3
,
146 d
& TAS2552_PLL_D_LOWER_MASK
);
150 snd_soc_update_bits(codec
, TAS2552_CFG_2
, TAS2552_PLL_ENABLE
,
156 static int tas2552_set_dai_fmt(struct snd_soc_dai
*dai
, unsigned int fmt
)
158 struct snd_soc_codec
*codec
= dai
->codec
;
160 u8 serial_control_mask
;
162 switch (fmt
& SND_SOC_DAIFMT_MASTER_MASK
) {
163 case SND_SOC_DAIFMT_CBS_CFS
:
164 serial_format
= 0x00;
166 case SND_SOC_DAIFMT_CBS_CFM
:
167 serial_format
= TAS2552_WORD_CLK_MASK
;
169 case SND_SOC_DAIFMT_CBM_CFS
:
170 serial_format
= TAS2552_BIT_CLK_MASK
;
172 case SND_SOC_DAIFMT_CBM_CFM
:
173 serial_format
= (TAS2552_BIT_CLK_MASK
| TAS2552_WORD_CLK_MASK
);
176 dev_vdbg(codec
->dev
, "DAI Format master is not found\n");
180 serial_control_mask
= TAS2552_BIT_CLK_MASK
| TAS2552_WORD_CLK_MASK
;
182 switch (fmt
& SND_SOC_DAIFMT_FORMAT_MASK
) {
183 case SND_SOC_DAIFMT_I2S
:
184 serial_format
&= TAS2552_DAIFMT_I2S_MASK
;
186 case SND_SOC_DAIFMT_DSP_A
:
187 serial_format
|= TAS2552_DAIFMT_DSP
;
189 case SND_SOC_DAIFMT_RIGHT_J
:
190 serial_format
|= TAS2552_DAIFMT_RIGHT_J
;
192 case SND_SOC_DAIFMT_LEFT_J
:
193 serial_format
|= TAS2552_DAIFMT_LEFT_J
;
196 dev_vdbg(codec
->dev
, "DAI Format is not found\n");
200 if (fmt
& SND_SOC_DAIFMT_FORMAT_MASK
)
201 serial_control_mask
|= TAS2552_DATA_FORMAT_MASK
;
203 snd_soc_update_bits(codec
, TAS2552_SER_CTRL_1
, serial_control_mask
,
209 static int tas2552_set_dai_sysclk(struct snd_soc_dai
*dai
, int clk_id
,
210 unsigned int freq
, int dir
)
212 struct snd_soc_codec
*codec
= dai
->codec
;
213 struct tas2552_data
*tas2552
= dev_get_drvdata(codec
->dev
);
215 tas2552
->mclk
= freq
;
220 static int tas2552_mute(struct snd_soc_dai
*dai
, int mute
)
223 struct snd_soc_codec
*codec
= dai
->codec
;
226 cfg1_reg
= TAS2552_MUTE_MASK
;
228 cfg1_reg
= ~TAS2552_MUTE_MASK
;
230 snd_soc_update_bits(codec
, TAS2552_CFG_1
, TAS2552_MUTE_MASK
, cfg1_reg
);
235 #ifdef CONFIG_PM_RUNTIME
236 static int tas2552_runtime_suspend(struct device
*dev
)
238 struct tas2552_data
*tas2552
= dev_get_drvdata(dev
);
240 tas2552_sw_shutdown(tas2552
, 0);
242 if (tas2552
->enable_gpio
)
243 gpiod_set_value(tas2552
->enable_gpio
, 0);
245 regcache_cache_only(tas2552
->regmap
, true);
246 regcache_mark_dirty(tas2552
->regmap
);
251 static int tas2552_runtime_resume(struct device
*dev
)
253 struct tas2552_data
*tas2552
= dev_get_drvdata(dev
);
255 if (tas2552
->enable_gpio
)
256 gpiod_set_value(tas2552
->enable_gpio
, 1);
258 tas2552_sw_shutdown(tas2552
, 1);
260 regcache_cache_only(tas2552
->regmap
, false);
261 regcache_sync(tas2552
->regmap
);
267 static const struct dev_pm_ops tas2552_pm
= {
268 SET_RUNTIME_PM_OPS(tas2552_runtime_suspend
, tas2552_runtime_resume
,
272 static void tas2552_shutdown(struct snd_pcm_substream
*substream
,
273 struct snd_soc_dai
*dai
)
275 struct snd_soc_codec
*codec
= dai
->codec
;
277 snd_soc_update_bits(codec
, TAS2552_CFG_2
, TAS2552_PLL_ENABLE
, 0);
280 static struct snd_soc_dai_ops tas2552_speaker_dai_ops
= {
281 .hw_params
= tas2552_hw_params
,
282 .set_sysclk
= tas2552_set_dai_sysclk
,
283 .set_fmt
= tas2552_set_dai_fmt
,
284 .shutdown
= tas2552_shutdown
,
285 .digital_mute
= tas2552_mute
,
288 /* Formats supported by TAS2552 driver. */
289 #define TAS2552_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
290 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
292 /* TAS2552 dai structure. */
293 static struct snd_soc_dai_driver tas2552_dai
[] = {
295 .name
= "tas2552-amplifier",
297 .stream_name
= "Speaker",
300 .rates
= SNDRV_PCM_RATE_8000_192000
,
301 .formats
= TAS2552_FORMATS
,
303 .ops
= &tas2552_speaker_dai_ops
,
308 * DAC digital volumes. From -7 to 24 dB in 1 dB steps
310 static DECLARE_TLV_DB_SCALE(dac_tlv
, -7, 100, 24);
312 static const struct snd_kcontrol_new tas2552_snd_controls
[] = {
313 SOC_SINGLE_TLV("Speaker Driver Playback Volume",
314 TAS2552_PGA_GAIN
, 0, 0x1f, 1, dac_tlv
),
317 static const struct reg_default tas2552_init_regs
[] = {
318 { TAS2552_RESERVED_0D
, 0xc0 },
321 static int tas2552_codec_probe(struct snd_soc_codec
*codec
)
323 struct tas2552_data
*tas2552
= snd_soc_codec_get_drvdata(codec
);
326 tas2552
->codec
= codec
;
328 ret
= regulator_bulk_enable(ARRAY_SIZE(tas2552
->supplies
),
332 dev_err(codec
->dev
, "Failed to enable supplies: %d\n",
337 if (tas2552
->enable_gpio
)
338 gpiod_set_value(tas2552
->enable_gpio
, 1);
340 ret
= pm_runtime_get_sync(codec
->dev
);
342 dev_err(codec
->dev
, "Enabling device failed: %d\n",
347 snd_soc_write(codec
, TAS2552_CFG_1
, TAS2552_MUTE_MASK
|
348 TAS2552_PLL_SRC_BCLK
);
349 snd_soc_write(codec
, TAS2552_CFG_3
, TAS2552_I2S_OUT_SEL
|
350 TAS2552_DIN_SRC_SEL_AVG_L_R
| TAS2552_88_96KHZ
);
351 snd_soc_write(codec
, TAS2552_DOUT
, TAS2552_PDM_DATA_I
);
352 snd_soc_write(codec
, TAS2552_OUTPUT_DATA
, TAS2552_PDM_DATA_V_I
| 0x8);
353 snd_soc_write(codec
, TAS2552_PDM_CFG
, TAS2552_PDM_BCLK_SEL
);
354 snd_soc_write(codec
, TAS2552_BOOST_PT_CTRL
, TAS2552_APT_DELAY_200
|
355 TAS2552_APT_THRESH_2_1_7
);
357 ret
= regmap_register_patch(tas2552
->regmap
, tas2552_init_regs
,
358 ARRAY_SIZE(tas2552_init_regs
));
360 dev_err(codec
->dev
, "Failed to write init registers: %d\n",
365 snd_soc_write(codec
, TAS2552_CFG_2
, TAS2552_CLASSD_EN
|
366 TAS2552_BOOST_EN
| TAS2552_APT_EN
|
371 pm_runtime_put(codec
->dev
);
373 if (tas2552
->enable_gpio
)
374 gpiod_set_value(tas2552
->enable_gpio
, 0);
376 regulator_bulk_disable(ARRAY_SIZE(tas2552
->supplies
),
381 static int tas2552_codec_remove(struct snd_soc_codec
*codec
)
383 struct tas2552_data
*tas2552
= snd_soc_codec_get_drvdata(codec
);
385 if (tas2552
->enable_gpio
)
386 gpiod_set_value(tas2552
->enable_gpio
, 0);
392 static int tas2552_suspend(struct snd_soc_codec
*codec
)
394 struct tas2552_data
*tas2552
= snd_soc_codec_get_drvdata(codec
);
397 ret
= regulator_bulk_disable(ARRAY_SIZE(tas2552
->supplies
),
401 dev_err(codec
->dev
, "Failed to disable supplies: %d\n",
406 static int tas2552_resume(struct snd_soc_codec
*codec
)
408 struct tas2552_data
*tas2552
= snd_soc_codec_get_drvdata(codec
);
411 ret
= regulator_bulk_enable(ARRAY_SIZE(tas2552
->supplies
),
415 dev_err(codec
->dev
, "Failed to enable supplies: %d\n",
422 #define tas2552_suspend NULL
423 #define tas2552_resume NULL
426 static struct snd_soc_codec_driver soc_codec_dev_tas2552
= {
427 .probe
= tas2552_codec_probe
,
428 .remove
= tas2552_codec_remove
,
429 .suspend
= tas2552_suspend
,
430 .resume
= tas2552_resume
,
431 .controls
= tas2552_snd_controls
,
432 .num_controls
= ARRAY_SIZE(tas2552_snd_controls
),
435 static const struct regmap_config tas2552_regmap_config
= {
439 .max_register
= TAS2552_MAX_REG
,
440 .reg_defaults
= tas2552_reg_defs
,
441 .num_reg_defaults
= ARRAY_SIZE(tas2552_reg_defs
),
442 .cache_type
= REGCACHE_RBTREE
,
445 static int tas2552_probe(struct i2c_client
*client
,
446 const struct i2c_device_id
*id
)
449 struct tas2552_data
*data
;
454 data
= devm_kzalloc(&client
->dev
, sizeof(*data
), GFP_KERNEL
);
458 data
->enable_gpio
= devm_gpiod_get(dev
, "enable");
459 if (IS_ERR(data
->enable_gpio
)) {
460 ret
= PTR_ERR(data
->enable_gpio
);
461 if (ret
!= -ENOENT
&& ret
!= -ENOSYS
)
464 data
->enable_gpio
= NULL
;
466 gpiod_direction_output(data
->enable_gpio
, 0);
469 data
->tas2552_client
= client
;
470 data
->regmap
= devm_regmap_init_i2c(client
, &tas2552_regmap_config
);
471 if (IS_ERR(data
->regmap
)) {
472 ret
= PTR_ERR(data
->regmap
);
473 dev_err(&client
->dev
, "Failed to allocate register map: %d\n",
478 for (i
= 0; i
< ARRAY_SIZE(data
->supplies
); i
++)
479 data
->supplies
[i
].supply
= tas2552_supply_names
[i
];
481 ret
= devm_regulator_bulk_get(dev
, ARRAY_SIZE(data
->supplies
),
484 dev_err(dev
, "Failed to request supplies: %d\n", ret
);
486 pm_runtime_set_active(&client
->dev
);
487 pm_runtime_set_autosuspend_delay(&client
->dev
, 1000);
488 pm_runtime_use_autosuspend(&client
->dev
);
489 pm_runtime_enable(&client
->dev
);
490 pm_runtime_mark_last_busy(&client
->dev
);
491 pm_runtime_put_sync_autosuspend(&client
->dev
);
493 dev_set_drvdata(&client
->dev
, data
);
495 ret
= snd_soc_register_codec(&client
->dev
,
496 &soc_codec_dev_tas2552
,
497 tas2552_dai
, ARRAY_SIZE(tas2552_dai
));
499 dev_err(&client
->dev
, "Failed to register codec: %d\n", ret
);
504 static int tas2552_i2c_remove(struct i2c_client
*client
)
506 snd_soc_unregister_codec(&client
->dev
);
510 static const struct i2c_device_id tas2552_id
[] = {
514 MODULE_DEVICE_TABLE(i2c
, tas2552_id
);
516 #if IS_ENABLED(CONFIG_OF)
517 static const struct of_device_id tas2552_of_match
[] = {
518 { .compatible
= "ti,tas2552", },
521 MODULE_DEVICE_TABLE(of
, tas2552_of_match
);
524 static struct i2c_driver tas2552_i2c_driver
= {
527 .owner
= THIS_MODULE
,
528 .of_match_table
= of_match_ptr(tas2552_of_match
),
531 .probe
= tas2552_probe
,
532 .remove
= tas2552_i2c_remove
,
533 .id_table
= tas2552_id
,
536 module_i2c_driver(tas2552_i2c_driver
);
538 MODULE_AUTHOR("Dan Muprhy <dmurphy@ti.com>");
539 MODULE_DESCRIPTION("TAS2552 Audio amplifier driver");
540 MODULE_LICENSE("GPL");