mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-24 03:24:55 +08:00
ASoC: cs35l41: Support external boost
Add support for external boost voltage, where GPIO1 must control a switch to isolate CS35L41 from the external Boost Voltage Signed-off-by: Lucas Tanure <tanureal@opensource.cirrus.com> Acked-by: Charles Keepax <ckeepax@opensource.cirrus.com> Acked-by: Mark Brown <broonie@kernel.org> Link: https://lore.kernel.org/r/20220413083728.10730-17-tanureal@opensource.cirrus.com Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
4b047ec3a1
commit
bb06c203f8
@ -701,6 +701,8 @@
|
||||
#define CS35L41_GPIO1_CTRL_SHIFT 16
|
||||
#define CS35L41_GPIO2_CTRL_MASK 0x07000000
|
||||
#define CS35L41_GPIO2_CTRL_SHIFT 24
|
||||
#define CS35L41_GPIO_LVL_SHIFT 15
|
||||
#define CS35L41_GPIO_LVL_MASK BIT(CS35L41_GPIO_LVL_SHIFT)
|
||||
#define CS35L41_GPIO_POL_MASK 0x1000
|
||||
#define CS35L41_GPIO_POL_SHIFT 12
|
||||
|
||||
@ -802,8 +804,6 @@ int cs35l41_register_errata_patch(struct device *dev, struct regmap *reg, unsign
|
||||
int cs35l41_set_channels(struct device *dev, struct regmap *reg,
|
||||
unsigned int tx_num, unsigned int *tx_slot,
|
||||
unsigned int rx_num, unsigned int *rx_slot);
|
||||
int cs35l41_boost_config(struct device *dev, struct regmap *regmap, int boost_ind, int boost_cap,
|
||||
int boost_ipk);
|
||||
int cs35l41_gpio_config(struct regmap *regmap, struct cs35l41_hw_cfg *hw_cfg);
|
||||
int cs35l41_init_boost(struct device *dev, struct regmap *regmap,
|
||||
struct cs35l41_hw_cfg *hw_cfg);
|
||||
|
@ -954,8 +954,8 @@ static const unsigned char cs35l41_bst_slope_table[4] = {
|
||||
0x75, 0x6B, 0x3B, 0x28
|
||||
};
|
||||
|
||||
int cs35l41_boost_config(struct device *dev, struct regmap *regmap, int boost_ind,
|
||||
int boost_cap, int boost_ipk)
|
||||
static int cs35l41_boost_config(struct device *dev, struct regmap *regmap, int boost_ind,
|
||||
int boost_cap, int boost_ipk)
|
||||
{
|
||||
unsigned char bst_lbst_val, bst_cbst_range, bst_ipk_scaled;
|
||||
int ret;
|
||||
@ -1040,7 +1040,6 @@ int cs35l41_boost_config(struct device *dev, struct regmap *regmap, int boost_in
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cs35l41_boost_config);
|
||||
|
||||
static const struct reg_sequence cs35l41_safe_to_reset[] = {
|
||||
{ 0x00000040, 0x00000055 },
|
||||
|
@ -578,15 +578,10 @@ static int cs35l41_main_amp_event(struct snd_soc_dapm_widget *w,
|
||||
cs35l41_pup_patch,
|
||||
ARRAY_SIZE(cs35l41_pup_patch));
|
||||
|
||||
regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL1,
|
||||
CS35L41_GLOBAL_EN_MASK,
|
||||
1 << CS35L41_GLOBAL_EN_SHIFT);
|
||||
|
||||
usleep_range(1000, 1100);
|
||||
cs35l41_global_enable(cs35l41->regmap, cs35l41->hw_cfg.bst_type, 1);
|
||||
break;
|
||||
case SND_SOC_DAPM_POST_PMD:
|
||||
regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL1,
|
||||
CS35L41_GLOBAL_EN_MASK, 0);
|
||||
cs35l41_global_enable(cs35l41->regmap, cs35l41->hw_cfg.bst_type, 0);
|
||||
|
||||
ret = regmap_read_poll_timeout(cs35l41->regmap, CS35L41_IRQ1_STATUS1,
|
||||
val, val & CS35L41_PDN_DONE_MASK,
|
||||
@ -1001,13 +996,13 @@ static int cs35l41_set_pdata(struct cs35l41_private *cs35l41)
|
||||
if (!hw_cfg->valid)
|
||||
return -EINVAL;
|
||||
|
||||
if (hw_cfg->bst_type == CS35L41_EXT_BOOST_NO_VSPK_SWITCH)
|
||||
return -EINVAL;
|
||||
|
||||
/* Required */
|
||||
ret = cs35l41_boost_config(cs35l41->dev, cs35l41->regmap,
|
||||
hw_cfg->bst_ind, hw_cfg->bst_cap, hw_cfg->bst_ipk);
|
||||
if (ret) {
|
||||
dev_err(cs35l41->dev, "Error in Boost DT config: %d\n", ret);
|
||||
ret = cs35l41_init_boost(cs35l41->dev, cs35l41->regmap, hw_cfg);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Optional */
|
||||
if (hw_cfg->dout_hiz <= CS35L41_ASP_DOUT_HIZ_MASK && hw_cfg->dout_hiz >= 0)
|
||||
@ -1017,9 +1012,31 @@ static int cs35l41_set_pdata(struct cs35l41_private *cs35l41)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_soc_dapm_route cs35l41_ext_bst_routes[] = {
|
||||
{"Main AMP", NULL, "VSPK"},
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_widget cs35l41_ext_bst_widget[] = {
|
||||
SND_SOC_DAPM_SUPPLY("VSPK", CS35L41_GPIO1_CTRL1, CS35L41_GPIO_LVL_SHIFT, 0, NULL, 0),
|
||||
};
|
||||
|
||||
static int cs35l41_component_probe(struct snd_soc_component *component)
|
||||
{
|
||||
struct cs35l41_private *cs35l41 = snd_soc_component_get_drvdata(component);
|
||||
struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
|
||||
int ret;
|
||||
|
||||
if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST) {
|
||||
ret = snd_soc_dapm_new_controls(dapm, cs35l41_ext_bst_widget,
|
||||
ARRAY_SIZE(cs35l41_ext_bst_widget));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = snd_soc_dapm_add_routes(dapm, cs35l41_ext_bst_routes,
|
||||
ARRAY_SIZE(cs35l41_ext_bst_routes));
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return wm_adsp2_component_probe(&cs35l41->dsp, component);
|
||||
}
|
||||
@ -1084,6 +1101,10 @@ static int cs35l41_handle_pdata(struct device *dev, struct cs35l41_hw_cfg *hw_cf
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
ret = device_property_read_u32(dev, "cirrus,boost-type", &val);
|
||||
if (ret >= 0)
|
||||
hw_cfg->bst_type = val;
|
||||
|
||||
ret = device_property_read_u32(dev, "cirrus,boost-peak-milliamp", &val);
|
||||
if (ret >= 0)
|
||||
hw_cfg->bst_ipk = val;
|
||||
@ -1376,6 +1397,7 @@ err_pm:
|
||||
|
||||
wm_adsp2_remove(&cs35l41->dsp);
|
||||
err:
|
||||
cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type);
|
||||
regulator_bulk_disable(CS35L41_NUM_SUPPLIES, cs35l41->supplies);
|
||||
gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
|
||||
|
||||
@ -1390,6 +1412,7 @@ void cs35l41_remove(struct cs35l41_private *cs35l41)
|
||||
|
||||
regmap_write(cs35l41->regmap, CS35L41_IRQ1_MASK1, 0xFFFFFFFF);
|
||||
wm_adsp2_remove(&cs35l41->dsp);
|
||||
cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type);
|
||||
|
||||
pm_runtime_put_noidle(cs35l41->dev);
|
||||
|
||||
@ -1409,6 +1432,7 @@ static int __maybe_unused cs35l41_runtime_suspend(struct device *dev)
|
||||
|
||||
dev_dbg(cs35l41->dev, "Enter hibernate\n");
|
||||
|
||||
cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type);
|
||||
regmap_write(cs35l41->regmap, CS35L41_WAKESRC_CTL, 0x0088);
|
||||
regmap_write(cs35l41->regmap, CS35L41_WAKESRC_CTL, 0x0188);
|
||||
|
||||
@ -1505,6 +1529,7 @@ static int __maybe_unused cs35l41_runtime_resume(struct device *dev)
|
||||
dev_err(cs35l41->dev, "Failed to restore register cache: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
cs35l41_init_boost(cs35l41->dev, cs35l41->regmap, &cs35l41->hw_cfg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user