1 // SPDX-License-Identifier: GPL-2.0
3 // Driver for the Texas Instruments TAS2562 CODEC
4 // Copyright (C) 2019 Texas Instruments Inc.
7 #include <linux/module.h>
8 #include <linux/errno.h>
9 #include <linux/device.h>
10 #include <linux/i2c.h>
11 #include <linux/pm_runtime.h>
12 #include <linux/regmap.h>
13 #include <linux/slab.h>
14 #include <linux/gpio/consumer.h>
15 #include <linux/regulator/consumer.h>
16 #include <linux/delay.h>
18 #include <sound/pcm.h>
19 #include <sound/pcm_params.h>
20 #include <sound/soc.h>
21 #include <sound/soc-dapm.h>
22 #include <sound/tlv.h>
26 #define TAS2562_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |\
27 SNDRV_PCM_FORMAT_S32_LE)
30 struct snd_soc_component
*component
;
31 struct gpio_desc
*sdz_gpio
;
32 struct regmap
*regmap
;
34 struct i2c_client
*client
;
39 static int tas2562_set_bias_level(struct snd_soc_component
*component
,
40 enum snd_soc_bias_level level
)
42 struct tas2562_data
*tas2562
=
43 snd_soc_component_get_drvdata(component
);
47 snd_soc_component_update_bits(component
,
49 TAS2562_MODE_MASK
, TAS2562_ACTIVE
);
51 case SND_SOC_BIAS_STANDBY
:
52 case SND_SOC_BIAS_PREPARE
:
53 snd_soc_component_update_bits(component
,
55 TAS2562_MODE_MASK
, TAS2562_MUTE
);
57 case SND_SOC_BIAS_OFF
:
58 snd_soc_component_update_bits(component
,
60 TAS2562_MODE_MASK
, TAS2562_SHUTDOWN
);
65 "wrong power level setting %d\n", level
);
72 static int tas2562_set_samplerate(struct tas2562_data
*tas2562
, int samplerate
)
79 ramp_rate
= TAS2562_TDM_CFG0_RAMPRATE_44_1
;
80 samp_rate
= TAS2562_TDM_CFG0_SAMPRATE_7305_8KHZ
;
84 samp_rate
= TAS2562_TDM_CFG0_SAMPRATE_7305_8KHZ
;
87 ramp_rate
= TAS2562_TDM_CFG0_RAMPRATE_44_1
;
88 samp_rate
= TAS2562_TDM_CFG0_SAMPRATE_14_7_16KHZ
;
92 samp_rate
= TAS2562_TDM_CFG0_SAMPRATE_14_7_16KHZ
;
95 ramp_rate
= TAS2562_TDM_CFG0_RAMPRATE_44_1
;
96 samp_rate
= TAS2562_TDM_CFG0_SAMPRATE_22_05_24KHZ
;
100 samp_rate
= TAS2562_TDM_CFG0_SAMPRATE_22_05_24KHZ
;
103 ramp_rate
= TAS2562_TDM_CFG0_RAMPRATE_44_1
;
104 samp_rate
= TAS2562_TDM_CFG0_SAMPRATE_29_4_32KHZ
;
108 samp_rate
= TAS2562_TDM_CFG0_SAMPRATE_29_4_32KHZ
;
111 ramp_rate
= TAS2562_TDM_CFG0_RAMPRATE_44_1
;
112 samp_rate
= TAS2562_TDM_CFG0_SAMPRATE_44_1_48KHZ
;
116 samp_rate
= TAS2562_TDM_CFG0_SAMPRATE_44_1_48KHZ
;
119 ramp_rate
= TAS2562_TDM_CFG0_RAMPRATE_44_1
;
120 samp_rate
= TAS2562_TDM_CFG0_SAMPRATE_88_2_96KHZ
;
124 samp_rate
= TAS2562_TDM_CFG0_SAMPRATE_88_2_96KHZ
;
127 ramp_rate
= TAS2562_TDM_CFG0_RAMPRATE_44_1
;
128 samp_rate
= TAS2562_TDM_CFG0_SAMPRATE_176_4_192KHZ
;
132 samp_rate
= TAS2562_TDM_CFG0_SAMPRATE_176_4_192KHZ
;
135 dev_info(tas2562
->dev
, "%s, unsupported sample rate, %d\n",
136 __func__
, samplerate
);
140 snd_soc_component_update_bits(tas2562
->component
, TAS2562_TDM_CFG0
,
141 TAS2562_TDM_CFG0_RAMPRATE_MASK
, ramp_rate
);
142 snd_soc_component_update_bits(tas2562
->component
, TAS2562_TDM_CFG0
,
143 TAS2562_TDM_CFG0_SAMPRATE_MASK
, samp_rate
);
148 static int tas2562_set_dai_tdm_slot(struct snd_soc_dai
*dai
,
149 unsigned int tx_mask
, unsigned int rx_mask
,
150 int slots
, int slot_width
)
152 struct snd_soc_component
*component
= dai
->component
;
153 struct tas2562_data
*tas2562
= snd_soc_component_get_drvdata(component
);
156 switch (slot_width
) {
158 ret
= snd_soc_component_update_bits(component
,
160 TAS2562_TDM_CFG2_RXLEN_MASK
,
161 TAS2562_TDM_CFG2_RXLEN_16B
);
164 ret
= snd_soc_component_update_bits(component
,
166 TAS2562_TDM_CFG2_RXLEN_MASK
,
167 TAS2562_TDM_CFG2_RXLEN_24B
);
170 ret
= snd_soc_component_update_bits(component
,
172 TAS2562_TDM_CFG2_RXLEN_MASK
,
173 TAS2562_TDM_CFG2_RXLEN_32B
);
177 /* Do not change slot width */
180 dev_err(tas2562
->dev
, "slot width not supported");
190 static int tas2562_set_bitwidth(struct tas2562_data
*tas2562
, int bitwidth
)
195 case SNDRV_PCM_FORMAT_S16_LE
:
196 snd_soc_component_update_bits(tas2562
->component
,
198 TAS2562_TDM_CFG2_RXWLEN_MASK
,
199 TAS2562_TDM_CFG2_RXWLEN_16B
);
200 tas2562
->v_sense_slot
= tas2562
->i_sense_slot
+ 2;
202 case SNDRV_PCM_FORMAT_S24_LE
:
203 snd_soc_component_update_bits(tas2562
->component
,
205 TAS2562_TDM_CFG2_RXWLEN_MASK
,
206 TAS2562_TDM_CFG2_RXWLEN_24B
);
207 tas2562
->v_sense_slot
= tas2562
->i_sense_slot
+ 4;
209 case SNDRV_PCM_FORMAT_S32_LE
:
210 snd_soc_component_update_bits(tas2562
->component
,
212 TAS2562_TDM_CFG2_RXWLEN_MASK
,
213 TAS2562_TDM_CFG2_RXWLEN_32B
);
214 tas2562
->v_sense_slot
= tas2562
->i_sense_slot
+ 4;
218 dev_info(tas2562
->dev
, "Not supported params format\n");
221 ret
= snd_soc_component_update_bits(tas2562
->component
,
223 TAS2562_TDM_CFG5_VSNS_EN
| TAS2562_TDM_CFG5_VSNS_SLOT_MASK
,
224 TAS2562_TDM_CFG5_VSNS_EN
| tas2562
->v_sense_slot
);
228 ret
= snd_soc_component_update_bits(tas2562
->component
,
230 TAS2562_TDM_CFG6_ISNS_EN
| TAS2562_TDM_CFG6_ISNS_SLOT_MASK
,
231 TAS2562_TDM_CFG6_ISNS_EN
| tas2562
->i_sense_slot
);
238 static int tas2562_hw_params(struct snd_pcm_substream
*substream
,
239 struct snd_pcm_hw_params
*params
,
240 struct snd_soc_dai
*dai
)
242 struct snd_soc_component
*component
= dai
->component
;
243 struct tas2562_data
*tas2562
= snd_soc_component_get_drvdata(component
);
246 ret
= tas2562_set_bitwidth(tas2562
, params_format(params
));
248 dev_err(tas2562
->dev
, "set bitwidth failed, %d\n", ret
);
252 ret
= tas2562_set_samplerate(tas2562
, params_rate(params
));
254 dev_err(tas2562
->dev
, "set bitwidth failed, %d\n", ret
);
259 static int tas2562_set_dai_fmt(struct snd_soc_dai
*dai
, unsigned int fmt
)
261 struct snd_soc_component
*component
= dai
->component
;
262 struct tas2562_data
*tas2562
= snd_soc_component_get_drvdata(component
);
263 u8 tdm_rx_start_slot
= 0, asi_cfg_1
= 0;
266 switch (fmt
& SND_SOC_DAIFMT_INV_MASK
) {
267 case SND_SOC_DAIFMT_NB_NF
:
270 case SND_SOC_DAIFMT_IB_NF
:
271 asi_cfg_1
|= TAS2562_TDM_CFG1_RX_FALLING
;
274 dev_err(tas2562
->dev
, "ASI format Inverse is not found\n");
278 ret
= snd_soc_component_update_bits(component
, TAS2562_TDM_CFG1
,
279 TAS2562_TDM_CFG1_RX_EDGE_MASK
,
282 dev_err(tas2562
->dev
, "Failed to set RX edge\n");
286 switch (fmt
& SND_SOC_DAIFMT_FORMAT_MASK
) {
287 case (SND_SOC_DAIFMT_I2S
):
288 case (SND_SOC_DAIFMT_DSP_A
):
289 case (SND_SOC_DAIFMT_DSP_B
):
290 tdm_rx_start_slot
= BIT(1);
292 case (SND_SOC_DAIFMT_LEFT_J
):
293 tdm_rx_start_slot
= 0;
296 dev_err(tas2562
->dev
, "DAI Format is not found, fmt=0x%x\n",
302 ret
= snd_soc_component_update_bits(component
, TAS2562_TDM_CFG1
,
303 TAS2562_TDM_CFG1_RX_OFFSET_MASK
,
312 static int tas2562_mute(struct snd_soc_dai
*dai
, int mute
)
314 struct snd_soc_component
*component
= dai
->component
;
316 return snd_soc_component_update_bits(component
, TAS2562_PWR_CTRL
,
318 mute
? TAS2562_MUTE
: 0);
321 static int tas2562_codec_probe(struct snd_soc_component
*component
)
323 struct tas2562_data
*tas2562
= snd_soc_component_get_drvdata(component
);
326 tas2562
->component
= component
;
328 if (tas2562
->sdz_gpio
)
329 gpiod_set_value_cansleep(tas2562
->sdz_gpio
, 1);
331 ret
= snd_soc_component_update_bits(component
, TAS2562_PWR_CTRL
,
332 TAS2562_MODE_MASK
, TAS2562_MUTE
);
340 static int tas2562_suspend(struct snd_soc_component
*component
)
342 struct tas2562_data
*tas2562
= snd_soc_component_get_drvdata(component
);
344 regcache_cache_only(tas2562
->regmap
, true);
345 regcache_mark_dirty(tas2562
->regmap
);
347 if (tas2562
->sdz_gpio
)
348 gpiod_set_value_cansleep(tas2562
->sdz_gpio
, 0);
353 static int tas2562_resume(struct snd_soc_component
*component
)
355 struct tas2562_data
*tas2562
= snd_soc_component_get_drvdata(component
);
357 if (tas2562
->sdz_gpio
)
358 gpiod_set_value_cansleep(tas2562
->sdz_gpio
, 1);
360 regcache_cache_only(tas2562
->regmap
, false);
362 return regcache_sync(tas2562
->regmap
);
365 #define tas2562_suspend NULL
366 #define tas2562_resume NULL
369 static const char * const tas2562_ASI1_src
[] = {
370 "I2C offset", "Left", "Right", "LeftRightDiv2",
373 static SOC_ENUM_SINGLE_DECL(tas2562_ASI1_src_enum
, TAS2562_TDM_CFG2
, 4,
376 static const struct snd_kcontrol_new tas2562_asi1_mux
=
377 SOC_DAPM_ENUM("ASI1 Source", tas2562_ASI1_src_enum
);
379 static int tas2562_dac_event(struct snd_soc_dapm_widget
*w
,
380 struct snd_kcontrol
*kcontrol
, int event
)
382 struct snd_soc_component
*component
=
383 snd_soc_dapm_to_component(w
->dapm
);
384 struct tas2562_data
*tas2562
= snd_soc_component_get_drvdata(component
);
387 case SND_SOC_DAPM_POST_PMU
:
388 dev_info(tas2562
->dev
, "SND_SOC_DAPM_POST_PMU\n");
390 case SND_SOC_DAPM_PRE_PMD
:
391 dev_info(tas2562
->dev
, "SND_SOC_DAPM_PRE_PMD\n");
400 static DECLARE_TLV_DB_SCALE(tas2562_dac_tlv
, 850, 50, 0);
402 static const struct snd_kcontrol_new isense_switch
=
403 SOC_DAPM_SINGLE("Switch", TAS2562_PWR_CTRL
, TAS2562_ISENSE_POWER_EN
,
406 static const struct snd_kcontrol_new vsense_switch
=
407 SOC_DAPM_SINGLE("Switch", TAS2562_PWR_CTRL
, TAS2562_VSENSE_POWER_EN
,
410 static const struct snd_kcontrol_new tas2562_snd_controls
[] = {
411 SOC_SINGLE_TLV("Amp Gain Volume", TAS2562_PB_CFG1
, 0, 0x1c, 0,
415 static const struct snd_soc_dapm_widget tas2562_dapm_widgets
[] = {
416 SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM
, 0, 0),
417 SND_SOC_DAPM_MUX("ASI1 Sel", SND_SOC_NOPM
, 0, 0, &tas2562_asi1_mux
),
418 SND_SOC_DAPM_AIF_IN("DAC IN", "Playback", 0, SND_SOC_NOPM
, 0, 0),
419 SND_SOC_DAPM_DAC_E("DAC", NULL
, SND_SOC_NOPM
, 0, 0, tas2562_dac_event
,
420 SND_SOC_DAPM_POST_PMU
| SND_SOC_DAPM_PRE_PMD
),
421 SND_SOC_DAPM_SWITCH("ISENSE", TAS2562_PWR_CTRL
, 3, 1, &isense_switch
),
422 SND_SOC_DAPM_SWITCH("VSENSE", TAS2562_PWR_CTRL
, 2, 1, &vsense_switch
),
423 SND_SOC_DAPM_SIGGEN("VMON"),
424 SND_SOC_DAPM_SIGGEN("IMON"),
425 SND_SOC_DAPM_OUTPUT("OUT"),
428 static const struct snd_soc_dapm_route tas2562_audio_map
[] = {
429 {"ASI1 Sel", "I2C offset", "ASI1"},
430 {"ASI1 Sel", "Left", "ASI1"},
431 {"ASI1 Sel", "Right", "ASI1"},
432 {"ASI1 Sel", "LeftRightDiv2", "ASI1"},
433 { "DAC", NULL
, "DAC IN" },
434 { "OUT", NULL
, "DAC" },
435 {"ISENSE", "Switch", "IMON"},
436 {"VSENSE", "Switch", "VMON"},
439 static const struct snd_soc_component_driver soc_component_dev_tas2562
= {
440 .probe
= tas2562_codec_probe
,
441 .suspend
= tas2562_suspend
,
442 .resume
= tas2562_resume
,
443 .set_bias_level
= tas2562_set_bias_level
,
444 .controls
= tas2562_snd_controls
,
445 .num_controls
= ARRAY_SIZE(tas2562_snd_controls
),
446 .dapm_widgets
= tas2562_dapm_widgets
,
447 .num_dapm_widgets
= ARRAY_SIZE(tas2562_dapm_widgets
),
448 .dapm_routes
= tas2562_audio_map
,
449 .num_dapm_routes
= ARRAY_SIZE(tas2562_audio_map
),
451 .use_pmdown_time
= 1,
453 .non_legacy_dai_naming
= 1,
456 static const struct snd_soc_dai_ops tas2562_speaker_dai_ops
= {
457 .hw_params
= tas2562_hw_params
,
458 .set_fmt
= tas2562_set_dai_fmt
,
459 .set_tdm_slot
= tas2562_set_dai_tdm_slot
,
460 .digital_mute
= tas2562_mute
,
463 static struct snd_soc_dai_driver tas2562_dai
[] = {
465 .name
= "tas2562-amplifier",
468 .stream_name
= "ASI1 Playback",
471 .rates
= SNDRV_PCM_RATE_8000_192000
,
472 .formats
= TAS2562_FORMATS
,
474 .ops
= &tas2562_speaker_dai_ops
,
478 static const struct regmap_range_cfg tas2562_ranges
[] = {
481 .range_max
= 5 * 128,
482 .selector_reg
= TAS2562_PAGE_CTRL
,
483 .selector_mask
= 0xff,
490 static const struct reg_default tas2562_reg_defaults
[] = {
491 { TAS2562_PAGE_CTRL
, 0x00 },
492 { TAS2562_SW_RESET
, 0x00 },
493 { TAS2562_PWR_CTRL
, 0x0e },
494 { TAS2562_PB_CFG1
, 0x20 },
495 { TAS2562_TDM_CFG0
, 0x09 },
496 { TAS2562_TDM_CFG1
, 0x02 },
499 static const struct regmap_config tas2562_regmap_config
= {
503 .max_register
= 5 * 128,
504 .cache_type
= REGCACHE_RBTREE
,
505 .reg_defaults
= tas2562_reg_defaults
,
506 .num_reg_defaults
= ARRAY_SIZE(tas2562_reg_defaults
),
507 .ranges
= tas2562_ranges
,
508 .num_ranges
= ARRAY_SIZE(tas2562_ranges
),
511 static int tas2562_parse_dt(struct tas2562_data
*tas2562
)
513 struct device
*dev
= tas2562
->dev
;
516 tas2562
->sdz_gpio
= devm_gpiod_get_optional(dev
, "shut-down-gpio",
518 if (IS_ERR(tas2562
->sdz_gpio
)) {
519 if (PTR_ERR(tas2562
->sdz_gpio
) == -EPROBE_DEFER
) {
520 tas2562
->sdz_gpio
= NULL
;
521 return -EPROBE_DEFER
;
525 ret
= fwnode_property_read_u32(dev
->fwnode
, "ti,imon-slot-no",
526 &tas2562
->i_sense_slot
);
528 dev_err(dev
, "Looking up %s property failed %d\n",
529 "ti,imon-slot-no", ret
);
534 static int tas2562_probe(struct i2c_client
*client
,
535 const struct i2c_device_id
*id
)
537 struct device
*dev
= &client
->dev
;
538 struct tas2562_data
*data
;
541 data
= devm_kzalloc(dev
, sizeof(*data
), GFP_KERNEL
);
545 data
->client
= client
;
546 data
->dev
= &client
->dev
;
548 tas2562_parse_dt(data
);
550 data
->regmap
= devm_regmap_init_i2c(client
, &tas2562_regmap_config
);
551 if (IS_ERR(data
->regmap
)) {
552 ret
= PTR_ERR(data
->regmap
);
553 dev_err(dev
, "failed to allocate register map: %d\n", ret
);
557 dev_set_drvdata(&client
->dev
, data
);
559 return devm_snd_soc_register_component(dev
, &soc_component_dev_tas2562
,
561 ARRAY_SIZE(tas2562_dai
));
565 static const struct i2c_device_id tas2562_id
[] = {
569 MODULE_DEVICE_TABLE(i2c
, tas2562_id
);
571 static const struct of_device_id tas2562_of_match
[] = {
572 { .compatible
= "ti,tas2562", },
575 MODULE_DEVICE_TABLE(of
, tas2562_of_match
);
577 static struct i2c_driver tas2562_i2c_driver
= {
580 .of_match_table
= of_match_ptr(tas2562_of_match
),
582 .probe
= tas2562_probe
,
583 .id_table
= tas2562_id
,
586 module_i2c_driver(tas2562_i2c_driver
);
588 MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
589 MODULE_DESCRIPTION("TAS2562 Audio amplifier driver");
590 MODULE_LICENSE("GPL");