static void madera_extcon_hp_clamp(struct madera_extcon *info, bool clamp)
{
struct madera *madera = info->madera;
- unsigned int mask = 0, val = 0;
- unsigned int edre_reg = 0, edre_val = 0;
- unsigned int ep_sel = 0;
+ unsigned int mask = 0, ep_mask = 0, val = 0;
int ret;
snd_soc_dapm_mutex_lock(madera->dapm);
switch (madera->type) {
case CS47L15:
case CS47L35:
- case CS47L92:
- case CS47L93:
- /*
- * check whether audio is routed to EPOUT, do not disable OUT1
- * in that case
- */
- regmap_read(madera->regmap, MADERA_OUTPUT_ENABLES_1, &ep_sel);
- ep_sel &= MADERA_EP_SEL_MASK;
- break;
- default:
- break;
- };
-
- switch (madera->type) {
- case CS47L35:
+ ep_mask = MADERA_EP_SEL_MASK;
break;
case CS47L85:
case WM1840:
- edre_reg = MADERA_EDRE_MANUAL;
- mask = MADERA_HP1L_SHRTO | MADERA_HP1L_FLWR | MADERA_HP1L_SHRTI;
- if (clamp) {
- val = MADERA_HP1L_SHRTO;
- edre_val = MADERA_EDRE_OUT1L_MANUAL |
- MADERA_EDRE_OUT1R_MANUAL;
- } else {
- val = MADERA_HP1L_FLWR | MADERA_HP1L_SHRTI;
- edre_val = 0;
- }
break;
default:
mask = MADERA_HPD_OVD_ENA_SEL_MASK;
- if (clamp)
+ if (!clamp)
val = MADERA_HPD_OVD_ENA_SEL_MASK;
else
val = 0;
madera->out_clamp[0] = clamp;
- /* Keep the HP output stages disabled while doing the clamp */
- if (clamp && !ep_sel) {
+ /* Keep the HP output stages disabled while disabling the clamp */
+ if (!clamp) {
ret = regmap_update_bits(madera->regmap,
MADERA_OUTPUT_ENABLES_1,
- (MADERA_OUT1L_ENA |
+ ep_mask |
+ ((MADERA_OUT1L_ENA |
MADERA_OUT1R_ENA) <<
- (2 * (info->pdata->output - 1)),
+ (2 * (info->pdata->output - 1))),
0);
if (ret)
dev_warn(info->dev,
ret);
}
- if (edre_reg && !ep_sel) {
- ret = regmap_update_bits(madera->regmap, edre_reg,
- MADERA_EDRE_OUT1L_MANUAL_MASK |
- MADERA_EDRE_OUT1R_MANUAL_MASK,
- edre_val);
- if (ret)
- dev_warn(info->dev,
- "Failed to set EDRE Manual: %d\n", ret);
- }
-
- dev_warn(info->dev, "%s clamp mask=0x%x val=0x%x\n",
+ dev_dbg(info->dev, "%s clamp mask=0x%x val=0x%x\n",
clamp ? "Setting" : "Clearing", mask, val);
switch (madera->type) {
case CS47L35:
- break;
case CS47L85:
case WM1840:
- ret = regmap_update_bits(madera->regmap,
- MADERA_HP_CTRL_1L, mask, val);
- if (ret)
- dev_warn(info->dev, "Failed to do clamp: %d\n", ret);
-
- ret = regmap_update_bits(madera->regmap,
- MADERA_HP_CTRL_1R, mask, val);
- if (ret)
- dev_warn(info->dev, "Failed to do clamp: %d\n", ret);
break;
default:
ret = regmap_update_bits(madera->regmap,
break;
}
- /* Restore the desired state while not doing the clamp */
- if (!clamp) {
+ /* Restore the desired state when restoring the clamp */
+ if (clamp) {
+ if (ep_mask) {
+ ret = regmap_update_bits(madera->regmap,
+ MADERA_OUTPUT_ENABLES_1,
+ ep_mask, madera->ep_sel);
+ if (ret)
+ dev_warn(info->dev,
+ "Failed to restore output demux: %d\n",
+ ret);
+ }
+
madera->out_shorted[0] = (madera->hp_impedance_x100[0] <=
info->hpdet_short_x100);
- if (!madera->out_shorted[0] && !ep_sel) {
+ if (!madera->out_shorted[0]) {
ret = regmap_update_bits(madera->regmap,
MADERA_OUTPUT_ENABLES_1,
(MADERA_OUT1L_ENA |
snd_soc_dapm_kcontrol_dapm(kcontrol);
struct madera *madera = dev_get_drvdata(codec->dev->parent);
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
- unsigned int ep_sel, mux, change;
- int ret, demux_change_ret;
+ unsigned int mux, change;
+ int ret, demux_change_ret = 0;
bool out_mono, restore_out = true;
if (ucontrol->value.enumerated.item[0] > e->items - 1)
return -EINVAL;
mux = ucontrol->value.enumerated.item[0];
- ep_sel = mux << MADERA_EP_SEL_SHIFT;
snd_soc_dapm_mutex_lock(dapm);
+ madera->ep_sel = mux << MADERA_EP_SEL_SHIFT;
+
change = snd_soc_test_bits(codec, MADERA_OUTPUT_ENABLES_1,
- MADERA_EP_SEL_MASK, ep_sel);
+ MADERA_EP_SEL_MASK, madera->ep_sel);
if (!change)
goto end;
usleep_range(2000, 3000); /* wait for wseq to complete */
/*
- * if HP detection clamp is applied while switching to HPOUT
- * OUT1 should remain disabled and EDRE should be set to manual
+ * if HPDET has disabled the clamp while switching to HPOUT
+ * OUT1 should remain disabled
*/
- if (!ep_sel &&
- (madera->out_clamp[0] || madera->out_shorted[0]))
+ if (!madera->ep_sel &&
+ (!madera->out_clamp[0] || madera->out_shorted[0]))
restore_out = false;
/* change demux setting */
- demux_change_ret = regmap_update_bits(madera->regmap,
- MADERA_OUTPUT_ENABLES_1,
- MADERA_EP_SEL_MASK, ep_sel);
+ if (madera->out_clamp[0])
+ demux_change_ret = regmap_update_bits(madera->regmap,
+ MADERA_OUTPUT_ENABLES_1,
+ MADERA_EP_SEL_MASK,
+ madera->ep_sel);
if (demux_change_ret) {
dev_err(madera->dev, "Failed to set OUT1 demux: %d\n",
demux_change_ret);
} else {
/* apply correct setting for mono mode */
- if (!ep_sel && !madera->pdata.codec.out_mono[0])
+ if (!madera->ep_sel && !madera->pdata.codec.out_mono[0])
out_mono = false; /* stereo HP */
else
out_mono = true; /* EP or mono HP */
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
- unsigned int val;
- val = snd_soc_read(codec, MADERA_OUTPUT_ENABLES_1);
- val &= MADERA_EP_SEL_MASK;
- val >>= MADERA_EP_SEL_SHIFT;
- ucontrol->value.enumerated.item[0] = val;
+ struct snd_soc_dapm_context *dapm =
+ snd_soc_dapm_kcontrol_dapm(kcontrol);
+ struct madera *madera = dev_get_drvdata(codec->dev->parent);
+
+ snd_soc_dapm_mutex_lock(dapm);
+ ucontrol->value.enumerated.item[0] = madera->ep_sel >> MADERA_EP_SEL_SHIFT;
+ snd_soc_dapm_mutex_unlock(dapm);
+
return 0;
}
EXPORT_SYMBOL_GPL(madera_out1_demux_get);