ALSA: hda: cs35l41: Move external boost handling to lib for ASoC use
To add support for external boost for ASoC move the HDA external boost implementation to the shared lib. Signed-off-by: Lucas Tanure <tanureal@opensource.cirrus.com> Link: https://lore.kernel.org/r/20220413083728.10730-15-tanureal@opensource.cirrus.com Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
734b965e67
commit
5577dd2329
@ -805,5 +805,9 @@ int cs35l41_set_channels(struct device *dev, struct regmap *reg,
|
||||
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);
|
||||
bool cs35l41_safe_reset(struct regmap *regmap, enum cs35l41_boost_type b_type);
|
||||
int cs35l41_global_enable(struct regmap *regmap, enum cs35l41_boost_type b_type, int enable);
|
||||
|
||||
#endif /* __CS35L41_H */
|
||||
|
@ -32,94 +32,6 @@ static const struct reg_sequence cs35l41_hda_mute[] = {
|
||||
{ CS35L41_AMP_DIG_VOL_CTRL, 0x0000A678 }, // AMP_VOL_PCM Mute
|
||||
};
|
||||
|
||||
static const struct reg_sequence cs35l41_safe_to_reset[] = {
|
||||
{ 0x00000040, 0x00000055 },
|
||||
{ 0x00000040, 0x000000AA },
|
||||
{ 0x0000393C, 0x000000C0, 6000},
|
||||
{ 0x0000393C, 0x00000000 },
|
||||
{ 0x00007414, 0x00C82222 },
|
||||
{ 0x0000742C, 0x00000000 },
|
||||
{ 0x00000040, 0x000000CC },
|
||||
{ 0x00000040, 0x00000033 },
|
||||
};
|
||||
|
||||
static const struct reg_sequence cs35l41_safe_to_active[] = {
|
||||
{ 0x00000040, 0x00000055 },
|
||||
{ 0x00000040, 0x000000AA },
|
||||
{ 0x0000742C, 0x0000000F },
|
||||
{ 0x0000742C, 0x00000079 },
|
||||
{ 0x00007438, 0x00585941 },
|
||||
{ CS35L41_PWR_CTRL1, 0x00000001, 3000 }, // GLOBAL_EN = 1
|
||||
{ 0x0000742C, 0x000000F9 },
|
||||
{ 0x00007438, 0x00580941 },
|
||||
{ 0x00000040, 0x000000CC },
|
||||
{ 0x00000040, 0x00000033 },
|
||||
};
|
||||
|
||||
static const struct reg_sequence cs35l41_active_to_safe[] = {
|
||||
{ 0x00000040, 0x00000055 },
|
||||
{ 0x00000040, 0x000000AA },
|
||||
{ 0x00007438, 0x00585941 },
|
||||
{ CS35L41_PWR_CTRL1, 0x00000000 },
|
||||
{ 0x0000742C, 0x00000009, 3000 },
|
||||
{ 0x00007438, 0x00580941 },
|
||||
{ 0x00000040, 0x000000CC },
|
||||
{ 0x00000040, 0x00000033 },
|
||||
};
|
||||
|
||||
static const struct reg_sequence cs35l41_reset_to_safe[] = {
|
||||
{ 0x00000040, 0x00000055 },
|
||||
{ 0x00000040, 0x000000AA },
|
||||
{ 0x00007438, 0x00585941 },
|
||||
{ 0x00007414, 0x08C82222 },
|
||||
{ 0x0000742C, 0x00000009 },
|
||||
{ 0x00000040, 0x000000CC },
|
||||
{ 0x00000040, 0x00000033 },
|
||||
};
|
||||
|
||||
static bool cs35l41_hda_safe_reset(struct cs35l41_hda *cs35l41)
|
||||
{
|
||||
switch (cs35l41->hw_cfg.bst_type) {
|
||||
case CS35L41_EXT_BOOST:
|
||||
regmap_write(cs35l41->regmap, CS35L41_GPIO1_CTRL1, 0x00000001);
|
||||
regmap_multi_reg_write(cs35l41->regmap, cs35l41_safe_to_reset,
|
||||
ARRAY_SIZE(cs35l41_safe_to_reset));
|
||||
return true;
|
||||
case CS35L41_EXT_BOOST_NO_VSPK_SWITCH:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
static int cs35l41_hda_global_enable(struct cs35l41_hda *cs35l41, int enable)
|
||||
{
|
||||
int ret;
|
||||
|
||||
switch (cs35l41->hw_cfg.bst_type) {
|
||||
case CS35L41_INT_BOOST:
|
||||
ret = regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL1,
|
||||
CS35L41_GLOBAL_EN_MASK,
|
||||
enable << CS35L41_GLOBAL_EN_SHIFT);
|
||||
usleep_range(3000, 3100);
|
||||
break;
|
||||
case CS35L41_EXT_BOOST:
|
||||
case CS35L41_EXT_BOOST_NO_VSPK_SWITCH:
|
||||
if (enable)
|
||||
ret = regmap_multi_reg_write(cs35l41->regmap, cs35l41_safe_to_active,
|
||||
ARRAY_SIZE(cs35l41_safe_to_active));
|
||||
else
|
||||
ret = regmap_multi_reg_write(cs35l41->regmap, cs35l41_active_to_safe,
|
||||
ARRAY_SIZE(cs35l41_active_to_safe));
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
static void cs35l41_hda_playback_hook(struct device *dev, int action)
|
||||
{
|
||||
struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
|
||||
@ -135,11 +47,11 @@ static void cs35l41_hda_playback_hook(struct device *dev, int action)
|
||||
regmap_write(reg, CS35L41_GPIO1_CTRL1, 0x00008001);
|
||||
break;
|
||||
case HDA_GEN_PCM_ACT_PREPARE:
|
||||
ret = cs35l41_hda_global_enable(cs35l41, 1);
|
||||
ret = cs35l41_global_enable(reg, cs35l41->hw_cfg.bst_type, 1);
|
||||
break;
|
||||
case HDA_GEN_PCM_ACT_CLEANUP:
|
||||
regmap_multi_reg_write(reg, cs35l41_hda_mute, ARRAY_SIZE(cs35l41_hda_mute));
|
||||
ret = cs35l41_hda_global_enable(cs35l41, 0);
|
||||
ret = cs35l41_global_enable(reg, cs35l41->hw_cfg.bst_type, 0);
|
||||
break;
|
||||
case HDA_GEN_PCM_ACT_CLOSE:
|
||||
ret = regmap_update_bits(reg, CS35L41_PWR_CTRL2,
|
||||
@ -207,26 +119,9 @@ static int cs35l41_hda_apply_properties(struct cs35l41_hda *cs35l41)
|
||||
if (!cs35l41->hw_cfg.valid)
|
||||
return -EINVAL;
|
||||
|
||||
switch (hw_cfg->bst_type) {
|
||||
case CS35L41_INT_BOOST:
|
||||
ret = cs35l41_boost_config(cs35l41->dev, cs35l41->regmap,
|
||||
hw_cfg->bst_ind, hw_cfg->bst_cap, hw_cfg->bst_ipk);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
case CS35L41_EXT_BOOST:
|
||||
case CS35L41_EXT_BOOST_NO_VSPK_SWITCH:
|
||||
regmap_multi_reg_write(cs35l41->regmap, cs35l41_reset_to_safe,
|
||||
ARRAY_SIZE(cs35l41_reset_to_safe));
|
||||
ret = regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2, CS35L41_BST_EN_MASK,
|
||||
CS35L41_BST_DIS_FET_OFF << CS35L41_BST_EN_SHIFT);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
default:
|
||||
dev_err(cs35l41->dev, "Boost type %d not supported\n", hw_cfg->bst_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = cs35l41_init_boost(cs35l41->dev, cs35l41->regmap, hw_cfg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (hw_cfg->gpio1.valid) {
|
||||
switch (hw_cfg->gpio1.func) {
|
||||
@ -505,7 +400,7 @@ int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int i
|
||||
return 0;
|
||||
|
||||
err:
|
||||
if (cs35l41_hda_safe_reset(cs35l41))
|
||||
if (cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type))
|
||||
gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
|
||||
gpiod_put(cs35l41->reset_gpio);
|
||||
|
||||
@ -519,7 +414,7 @@ void cs35l41_hda_remove(struct device *dev)
|
||||
|
||||
component_del(cs35l41->dev, &cs35l41_hda_comp_ops);
|
||||
|
||||
if (cs35l41_hda_safe_reset(cs35l41))
|
||||
if (cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type))
|
||||
gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
|
||||
gpiod_put(cs35l41->reset_gpio);
|
||||
}
|
||||
|
@ -954,9 +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)
|
||||
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;
|
||||
@ -1043,6 +1042,130 @@ int cs35l41_boost_config(struct device *dev, struct regmap *regmap, int boost_in
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cs35l41_boost_config);
|
||||
|
||||
static const struct reg_sequence cs35l41_safe_to_reset[] = {
|
||||
{ 0x00000040, 0x00000055 },
|
||||
{ 0x00000040, 0x000000AA },
|
||||
{ 0x0000393C, 0x000000C0, 6000},
|
||||
{ 0x0000393C, 0x00000000 },
|
||||
{ 0x00007414, 0x00C82222 },
|
||||
{ 0x0000742C, 0x00000000 },
|
||||
{ 0x00000040, 0x000000CC },
|
||||
{ 0x00000040, 0x00000033 },
|
||||
};
|
||||
|
||||
static const struct reg_sequence cs35l41_active_to_safe[] = {
|
||||
{ 0x00000040, 0x00000055 },
|
||||
{ 0x00000040, 0x000000AA },
|
||||
{ 0x00007438, 0x00585941 },
|
||||
{ CS35L41_PWR_CTRL1, 0x00000000 },
|
||||
{ 0x0000742C, 0x00000009, 3000 },
|
||||
{ 0x00007438, 0x00580941 },
|
||||
{ 0x00000040, 0x000000CC },
|
||||
{ 0x00000040, 0x00000033 },
|
||||
};
|
||||
|
||||
static const struct reg_sequence cs35l41_safe_to_active[] = {
|
||||
{ 0x00000040, 0x00000055 },
|
||||
{ 0x00000040, 0x000000AA },
|
||||
{ 0x0000742C, 0x0000000F },
|
||||
{ 0x0000742C, 0x00000079 },
|
||||
{ 0x00007438, 0x00585941 },
|
||||
{ CS35L41_PWR_CTRL1, 0x00000001, 3000 }, // GLOBAL_EN = 1
|
||||
{ 0x0000742C, 0x000000F9 },
|
||||
{ 0x00007438, 0x00580941 },
|
||||
{ 0x00000040, 0x000000CC },
|
||||
{ 0x00000040, 0x00000033 },
|
||||
};
|
||||
|
||||
static const struct reg_sequence cs35l41_reset_to_safe[] = {
|
||||
{ 0x00000040, 0x00000055 },
|
||||
{ 0x00000040, 0x000000AA },
|
||||
{ 0x00007438, 0x00585941 },
|
||||
{ 0x00007414, 0x08C82222 },
|
||||
{ 0x0000742C, 0x00000009 },
|
||||
{ 0x00000040, 0x000000CC },
|
||||
{ 0x00000040, 0x00000033 },
|
||||
};
|
||||
|
||||
int cs35l41_init_boost(struct device *dev, struct regmap *regmap,
|
||||
struct cs35l41_hw_cfg *hw_cfg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
switch (hw_cfg->bst_type) {
|
||||
case CS35L41_INT_BOOST:
|
||||
ret = cs35l41_boost_config(dev, regmap, hw_cfg->bst_ind,
|
||||
hw_cfg->bst_cap, hw_cfg->bst_ipk);
|
||||
if (ret)
|
||||
dev_err(dev, "Error in Boost DT config: %d\n", ret);
|
||||
break;
|
||||
case CS35L41_EXT_BOOST:
|
||||
case CS35L41_EXT_BOOST_NO_VSPK_SWITCH:
|
||||
/* Only CLSA0100 doesn't use GPIO as VSPK switch, but even on that laptop we can
|
||||
* toggle GPIO1 as is not connected to anything.
|
||||
* There will be no other device without VSPK switch.
|
||||
*/
|
||||
regmap_write(regmap, CS35L41_GPIO1_CTRL1, 0x00000001);
|
||||
regmap_multi_reg_write(regmap, cs35l41_reset_to_safe,
|
||||
ARRAY_SIZE(cs35l41_reset_to_safe));
|
||||
ret = regmap_update_bits(regmap, CS35L41_PWR_CTRL2, CS35L41_BST_EN_MASK,
|
||||
CS35L41_BST_DIS_FET_OFF << CS35L41_BST_EN_SHIFT);
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "Boost type %d not supported\n", hw_cfg->bst_type);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cs35l41_init_boost);
|
||||
|
||||
bool cs35l41_safe_reset(struct regmap *regmap, enum cs35l41_boost_type b_type)
|
||||
{
|
||||
switch (b_type) {
|
||||
/* There is only one laptop that doesn't have VSPK switch. */
|
||||
case CS35L41_EXT_BOOST_NO_VSPK_SWITCH:
|
||||
return false;
|
||||
case CS35L41_EXT_BOOST:
|
||||
regmap_write(regmap, CS35L41_GPIO1_CTRL1, 0x00000001);
|
||||
regmap_multi_reg_write(regmap, cs35l41_safe_to_reset,
|
||||
ARRAY_SIZE(cs35l41_safe_to_reset));
|
||||
return true;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cs35l41_safe_reset);
|
||||
|
||||
int cs35l41_global_enable(struct regmap *regmap, enum cs35l41_boost_type b_type, int enable)
|
||||
{
|
||||
int ret;
|
||||
|
||||
switch (b_type) {
|
||||
case CS35L41_INT_BOOST:
|
||||
ret = regmap_update_bits(regmap, CS35L41_PWR_CTRL1, CS35L41_GLOBAL_EN_MASK,
|
||||
enable << CS35L41_GLOBAL_EN_SHIFT);
|
||||
usleep_range(3000, 3100);
|
||||
break;
|
||||
case CS35L41_EXT_BOOST:
|
||||
case CS35L41_EXT_BOOST_NO_VSPK_SWITCH:
|
||||
if (enable)
|
||||
ret = regmap_multi_reg_write(regmap, cs35l41_safe_to_active,
|
||||
ARRAY_SIZE(cs35l41_safe_to_active));
|
||||
else
|
||||
ret = regmap_multi_reg_write(regmap, cs35l41_active_to_safe,
|
||||
ARRAY_SIZE(cs35l41_active_to_safe));
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cs35l41_global_enable);
|
||||
|
||||
int cs35l41_gpio_config(struct regmap *regmap, struct cs35l41_hw_cfg *hw_cfg)
|
||||
{
|
||||
struct cs35l41_gpio_cfg *gpio1 = &hw_cfg->gpio1;
|
||||
|
Loading…
Reference in New Issue
Block a user