Skip to content

Commit 40fb0b2

Browse files
marcanjannau
authored andcommitted
ASoC: tas2770: Add SDZ regulator
Multiple amps can be connected to the same SDZ GPIO. Using raw GPIOs for this breaks, as there is no concept of refcounting/sharing. In order to model these platforms, introduce support for an SDZ "regulator". This allows us to represent the SDZ GPIO as a simple regulator-fixed, and then the regulator core takes care of refcounting so that all codecs are only powered down once all the driver instances are in the suspend state. This also reworks the sleep/resume logic to copy what tas2764 does, which makes more sense. Signed-off-by: Hector Martin <marcan@marcan.st>
1 parent e78fb97 commit 40fb0b2

2 files changed

Lines changed: 50 additions & 23 deletions

File tree

sound/soc/codecs/tas2770.c

Lines changed: 49 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -71,23 +71,21 @@ static int tas2770_codec_suspend(struct snd_soc_component *component)
7171
struct tas2770_priv *tas2770 = snd_soc_component_get_drvdata(component);
7272
int ret = 0;
7373

74-
regcache_cache_only(tas2770->regmap, true);
75-
regcache_mark_dirty(tas2770->regmap);
74+
ret = snd_soc_component_update_bits(component, TAS2770_PWR_CTRL,
75+
TAS2770_PWR_CTRL_MASK,
76+
TAS2770_PWR_CTRL_SHUTDOWN);
77+
if (ret < 0)
78+
return ret;
7679

77-
if (tas2770->sdz_gpio) {
80+
if (tas2770->sdz_gpio)
7881
gpiod_set_value_cansleep(tas2770->sdz_gpio, 0);
79-
} else {
80-
ret = snd_soc_component_update_bits(component, TAS2770_PWR_CTRL,
81-
TAS2770_PWR_CTRL_MASK,
82-
TAS2770_PWR_CTRL_SHUTDOWN);
83-
if (ret < 0) {
84-
regcache_cache_only(tas2770->regmap, false);
85-
regcache_sync(tas2770->regmap);
86-
return ret;
87-
}
8882

89-
ret = 0;
90-
}
83+
regulator_disable(tas2770->sdz_reg);
84+
85+
regcache_cache_only(tas2770->regmap, true);
86+
regcache_mark_dirty(tas2770->regmap);
87+
88+
usleep_range(6000, 7000);
9189

9290
return ret;
9391
}
@@ -97,18 +95,26 @@ static int tas2770_codec_resume(struct snd_soc_component *component)
9795
struct tas2770_priv *tas2770 = snd_soc_component_get_drvdata(component);
9896
int ret;
9997

100-
if (tas2770->sdz_gpio) {
101-
gpiod_set_value_cansleep(tas2770->sdz_gpio, 1);
102-
usleep_range(1000, 2000);
103-
} else {
104-
ret = tas2770_update_pwr_ctrl(tas2770);
105-
if (ret < 0)
106-
return ret;
98+
ret = regulator_enable(tas2770->sdz_reg);
99+
100+
if (ret) {
101+
dev_err(tas2770->dev, "Failed to enable regulator\n");
102+
return ret;
107103
}
108104

105+
if (tas2770->sdz_gpio)
106+
gpiod_set_value_cansleep(tas2770->sdz_gpio, 1);
107+
108+
109+
usleep_range(1000, 2000);
110+
109111
regcache_cache_only(tas2770->regmap, false);
110112

111-
return regcache_sync(tas2770->regmap);
113+
ret = regcache_sync(tas2770->regmap);
114+
if (ret < 0)
115+
return ret;
116+
117+
return tas2770_update_pwr_ctrl(tas2770);
112118
}
113119
#else
114120
#define tas2770_codec_suspend NULL
@@ -623,11 +629,18 @@ static int tas2770_codec_probe(struct snd_soc_component *component)
623629

624630
tas2770->component = component;
625631

632+
ret = regulator_enable(tas2770->sdz_reg);
633+
if (ret != 0) {
634+
dev_err(tas2770->dev, "Failed to enable regulator: %d\n", ret);
635+
return ret;
636+
}
637+
626638
if (tas2770->sdz_gpio) {
627639
gpiod_set_value_cansleep(tas2770->sdz_gpio, 1);
628-
usleep_range(1000, 2000);
629640
}
630641

642+
usleep_range(1000, 2000);
643+
631644
tas2770_reset(tas2770);
632645
regmap_reinit_cache(tas2770->regmap, &tas2770_i2c_regmap);
633646

@@ -649,6 +662,13 @@ static int tas2770_codec_probe(struct snd_soc_component *component)
649662
return 0;
650663
}
651664

665+
static void tas2770_codec_remove(struct snd_soc_component *component)
666+
{
667+
struct tas2770_priv *tas2770 = snd_soc_component_get_drvdata(component);
668+
669+
regulator_disable(tas2770->sdz_reg);
670+
}
671+
652672
static DECLARE_TLV_DB_SCALE(tas2770_digital_tlv, 1100, 50, 0);
653673
static DECLARE_TLV_DB_SCALE(tas2770_playback_volume, -10050, 50, 0);
654674

@@ -661,6 +681,7 @@ static const struct snd_kcontrol_new tas2770_snd_controls[] = {
661681

662682
static const struct snd_soc_component_driver soc_component_driver_tas2770 = {
663683
.probe = tas2770_codec_probe,
684+
.remove = tas2770_codec_remove,
664685
.suspend = tas2770_codec_suspend,
665686
.resume = tas2770_codec_resume,
666687
.controls = tas2770_snd_controls,
@@ -790,6 +811,11 @@ static int tas2770_parse_dt(struct device *dev, struct tas2770_priv *tas2770)
790811
if (rc)
791812
tas2770->pdm_slot = -1;
792813

814+
tas2770->sdz_reg = devm_regulator_get(dev, "SDZ");
815+
if (IS_ERR(tas2770->sdz_reg))
816+
return dev_err_probe(dev, PTR_ERR(tas2770->sdz_reg),
817+
"Failed to get SDZ supply\n");
818+
793819
tas2770->sdz_gpio = devm_gpiod_get_optional(dev, "shutdown", GPIOD_OUT_HIGH);
794820
if (IS_ERR(tas2770->sdz_gpio)) {
795821
if (PTR_ERR(tas2770->sdz_gpio) == -EPROBE_DEFER)

sound/soc/codecs/tas2770.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ struct tas2770_priv {
139139
struct snd_soc_component *component;
140140
struct gpio_desc *reset_gpio;
141141
struct gpio_desc *sdz_gpio;
142+
struct regulator *sdz_reg;
142143
struct regmap *regmap;
143144
struct device *dev;
144145
int v_sense_slot;

0 commit comments

Comments
 (0)