summaryrefslogtreecommitdiff
path: root/sound/soc/codecs/cs35l41.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/cs35l41.c')
-rw-r--r--sound/soc/codecs/cs35l41.c166
1 files changed, 79 insertions, 87 deletions
diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c
index 6b784a62df0c..912196f45648 100644
--- a/sound/soc/codecs/cs35l41.c
+++ b/sound/soc/codecs/cs35l41.c
@@ -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,
@@ -995,69 +990,53 @@ static int cs35l41_dai_set_sysclk(struct snd_soc_dai *dai,
static int cs35l41_set_pdata(struct cs35l41_private *cs35l41)
{
+ struct cs35l41_hw_cfg *hw_cfg = &cs35l41->hw_cfg;
int ret;
- /* Set Platform Data */
- /* Required */
- if (cs35l41->pdata.bst_ipk &&
- cs35l41->pdata.bst_ind && cs35l41->pdata.bst_cap) {
- ret = cs35l41_boost_config(cs35l41->dev, cs35l41->regmap, cs35l41->pdata.bst_ind,
- cs35l41->pdata.bst_cap, cs35l41->pdata.bst_ipk);
- if (ret) {
- dev_err(cs35l41->dev, "Error in Boost DT config: %d\n", ret);
- return ret;
- }
- } else {
- dev_err(cs35l41->dev, "Incomplete Boost component DT config\n");
+ if (!hw_cfg->valid)
+ return -EINVAL;
+
+ if (hw_cfg->bst_type == CS35L41_EXT_BOOST_NO_VSPK_SWITCH)
return -EINVAL;
- }
+
+ /* Required */
+ ret = cs35l41_init_boost(cs35l41->dev, cs35l41->regmap, hw_cfg);
+ if (ret)
+ return ret;
/* Optional */
- if (cs35l41->pdata.dout_hiz <= CS35L41_ASP_DOUT_HIZ_MASK &&
- cs35l41->pdata.dout_hiz >= 0)
- regmap_update_bits(cs35l41->regmap, CS35L41_SP_HIZ_CTRL,
- CS35L41_ASP_DOUT_HIZ_MASK,
- cs35l41->pdata.dout_hiz);
+ if (hw_cfg->dout_hiz <= CS35L41_ASP_DOUT_HIZ_MASK && hw_cfg->dout_hiz >= 0)
+ regmap_update_bits(cs35l41->regmap, CS35L41_SP_HIZ_CTRL, CS35L41_ASP_DOUT_HIZ_MASK,
+ hw_cfg->dout_hiz);
return 0;
}
-static int cs35l41_irq_gpio_config(struct cs35l41_private *cs35l41)
-{
- struct cs35l41_irq_cfg *irq_gpio_cfg1 = &cs35l41->pdata.irq_config1;
- struct cs35l41_irq_cfg *irq_gpio_cfg2 = &cs35l41->pdata.irq_config2;
- int irq_pol = IRQF_TRIGGER_NONE;
-
- regmap_update_bits(cs35l41->regmap, CS35L41_GPIO1_CTRL1,
- CS35L41_GPIO_POL_MASK | CS35L41_GPIO_DIR_MASK,
- irq_gpio_cfg1->irq_pol_inv << CS35L41_GPIO_POL_SHIFT |
- !irq_gpio_cfg1->irq_out_en << CS35L41_GPIO_DIR_SHIFT);
-
- regmap_update_bits(cs35l41->regmap, CS35L41_GPIO2_CTRL1,
- CS35L41_GPIO_POL_MASK | CS35L41_GPIO_DIR_MASK,
- irq_gpio_cfg2->irq_pol_inv << CS35L41_GPIO_POL_SHIFT |
- !irq_gpio_cfg2->irq_out_en << CS35L41_GPIO_DIR_SHIFT);
-
- regmap_update_bits(cs35l41->regmap, CS35L41_GPIO_PAD_CONTROL,
- CS35L41_GPIO1_CTRL_MASK | CS35L41_GPIO2_CTRL_MASK,
- irq_gpio_cfg1->irq_src_sel << CS35L41_GPIO1_CTRL_SHIFT |
- irq_gpio_cfg2->irq_src_sel << CS35L41_GPIO2_CTRL_SHIFT);
-
- if ((irq_gpio_cfg2->irq_src_sel ==
- (CS35L41_GPIO_CTRL_ACTV_LO | CS35L41_VALID_PDATA)) ||
- (irq_gpio_cfg2->irq_src_sel ==
- (CS35L41_GPIO_CTRL_OPEN_INT | CS35L41_VALID_PDATA)))
- irq_pol = IRQF_TRIGGER_LOW;
- else if (irq_gpio_cfg2->irq_src_sel ==
- (CS35L41_GPIO_CTRL_ACTV_HI | CS35L41_VALID_PDATA))
- irq_pol = IRQF_TRIGGER_HIGH;
-
- return irq_pol;
-}
+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);
}
@@ -1115,50 +1094,60 @@ static const struct snd_soc_component_driver soc_component_dev_cs35l41 = {
.set_sysclk = cs35l41_component_set_sysclk,
};
-static int cs35l41_handle_pdata(struct device *dev, struct cs35l41_platform_data *pdata)
+static int cs35l41_handle_pdata(struct device *dev, struct cs35l41_hw_cfg *hw_cfg)
{
- struct cs35l41_irq_cfg *irq_gpio1_config = &pdata->irq_config1;
- struct cs35l41_irq_cfg *irq_gpio2_config = &pdata->irq_config2;
+ struct cs35l41_gpio_cfg *gpio1 = &hw_cfg->gpio1;
+ struct cs35l41_gpio_cfg *gpio2 = &hw_cfg->gpio2;
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)
- pdata->bst_ipk = val;
+ hw_cfg->bst_ipk = val;
+ else
+ hw_cfg->bst_ipk = -1;
ret = device_property_read_u32(dev, "cirrus,boost-ind-nanohenry", &val);
if (ret >= 0)
- pdata->bst_ind = val;
+ hw_cfg->bst_ind = val;
+ else
+ hw_cfg->bst_ind = -1;
ret = device_property_read_u32(dev, "cirrus,boost-cap-microfarad", &val);
if (ret >= 0)
- pdata->bst_cap = val;
+ hw_cfg->bst_cap = val;
+ else
+ hw_cfg->bst_cap = -1;
ret = device_property_read_u32(dev, "cirrus,asp-sdout-hiz", &val);
if (ret >= 0)
- pdata->dout_hiz = val;
+ hw_cfg->dout_hiz = val;
else
- pdata->dout_hiz = -1;
+ hw_cfg->dout_hiz = -1;
/* GPIO1 Pin Config */
- irq_gpio1_config->irq_pol_inv = device_property_read_bool(dev,
- "cirrus,gpio1-polarity-invert");
- irq_gpio1_config->irq_out_en = device_property_read_bool(dev,
- "cirrus,gpio1-output-enable");
- ret = device_property_read_u32(dev, "cirrus,gpio1-src-select",
- &val);
- if (ret >= 0)
- irq_gpio1_config->irq_src_sel = val | CS35L41_VALID_PDATA;
+ gpio1->pol_inv = device_property_read_bool(dev, "cirrus,gpio1-polarity-invert");
+ gpio1->out_en = device_property_read_bool(dev, "cirrus,gpio1-output-enable");
+ ret = device_property_read_u32(dev, "cirrus,gpio1-src-select", &val);
+ if (ret >= 0) {
+ gpio1->func = val;
+ gpio1->valid = true;
+ }
/* GPIO2 Pin Config */
- irq_gpio2_config->irq_pol_inv = device_property_read_bool(dev,
- "cirrus,gpio2-polarity-invert");
- irq_gpio2_config->irq_out_en = device_property_read_bool(dev,
- "cirrus,gpio2-output-enable");
- ret = device_property_read_u32(dev, "cirrus,gpio2-src-select",
- &val);
- if (ret >= 0)
- irq_gpio2_config->irq_src_sel = val | CS35L41_VALID_PDATA;
+ gpio2->pol_inv = device_property_read_bool(dev, "cirrus,gpio2-polarity-invert");
+ gpio2->out_en = device_property_read_bool(dev, "cirrus,gpio2-output-enable");
+ ret = device_property_read_u32(dev, "cirrus,gpio2-src-select", &val);
+ if (ret >= 0) {
+ gpio2->func = val;
+ gpio2->valid = true;
+ }
+
+ hw_cfg->valid = true;
return 0;
}
@@ -1248,17 +1237,16 @@ err_dsp:
return ret;
}
-int cs35l41_probe(struct cs35l41_private *cs35l41,
- struct cs35l41_platform_data *pdata)
+int cs35l41_probe(struct cs35l41_private *cs35l41, const struct cs35l41_hw_cfg *hw_cfg)
{
u32 regid, reg_revid, i, mtl_revid, int_status, chipid_match;
int irq_pol = 0;
int ret;
- if (pdata) {
- cs35l41->pdata = *pdata;
+ if (hw_cfg) {
+ cs35l41->hw_cfg = *hw_cfg;
} else {
- ret = cs35l41_handle_pdata(cs35l41->dev, &cs35l41->pdata);
+ ret = cs35l41_handle_pdata(cs35l41->dev, &cs35l41->hw_cfg);
if (ret != 0)
return ret;
}
@@ -1357,7 +1345,7 @@ int cs35l41_probe(struct cs35l41_private *cs35l41,
cs35l41_test_key_lock(cs35l41->dev, cs35l41->regmap);
- irq_pol = cs35l41_irq_gpio_config(cs35l41);
+ irq_pol = cs35l41_gpio_config(cs35l41->regmap, &cs35l41->hw_cfg);
/* Set interrupt masks for critical errors */
regmap_write(cs35l41->regmap, CS35L41_IRQ1_MASK1,
@@ -1409,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);
@@ -1423,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);
@@ -1442,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);
@@ -1538,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;
}