/* * Update the DC servo calibration on gain changes */ static int wm8993_put_dc_servo(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); int ret; ret = snd_soc_put_volsw_2r(kcontrol, ucontrol); /* Updating the analogue gains invalidates the DC servo cache */ hubs->class_w_dcs = 0; /* If we're applying an offset correction then updating the * callibration would be likely to introduce further offsets. */ if (hubs->dcs_codes || hubs->no_series_update) return ret; /* Only need to do this if the outputs are active */ if (snd_soc_read(codec, WM8993_POWER_MANAGEMENT_1) & (WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA)) snd_soc_update_bits(codec, WM8993_DC_SERVO_0, WM8993_DCS_TRIG_SINGLE_0 | WM8993_DCS_TRIG_SINGLE_1, WM8993_DCS_TRIG_SINGLE_0 | WM8993_DCS_TRIG_SINGLE_1); return ret; }
static int wm8350_put_volsw_2r_vu(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct wm8350_out_ramp *or = codec->private_data; struct wm8350_output *out1 = &or->out1, *out2 = &or->out2; int ret, reg = kcontrol->private_value & 0xff; u16 val; /* we cache the OUT1/2 volumes when the codec is inactive to keep * pops to a low during ramping */ if (reg == WM8350_LOUT1_VOLUME) { out1->left_vol = ucontrol->value.integer.value[0]; out1->right_vol = ucontrol->value.integer.value[1]; if (!codec->active) return 1; } else if (reg == WM8350_LOUT2_VOLUME) { out2->left_vol = ucontrol->value.integer.value[0]; out2->right_vol = ucontrol->value.integer.value[1]; if (!codec->active) return 1; } ret = snd_soc_put_volsw_2r(kcontrol, ucontrol); if (ret < 0) return ret; /* now hit the volume update bits (always bit 8) */ val = wm8350_codec_read(codec, reg); wm8350_codec_write(codec, reg, val | WM8350_OUT1_VU); return 1; }
static int wm8350_put_volsw_2r_vu(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct wm8350_data *wm8350_priv = codec->private_data; struct wm8350_output *out = NULL; struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; int ret; unsigned int reg = mc->reg; u16 val; /* For OUT1 and OUT2 we shadow the values and only actually write * them out when active in order to ensure the amplifier comes on * as quietly as possible. */ switch (reg) { case WM8350_LOUT1_VOLUME: out = &wm8350_priv->out1; break; case WM8350_LOUT2_VOLUME: out = &wm8350_priv->out2; break; default: break; } if (out) { out->left_vol = ucontrol->value.integer.value[0]; out->right_vol = ucontrol->value.integer.value[1]; if (!out->active) return 1; } ret = snd_soc_put_volsw_2r(kcontrol, ucontrol); if (ret < 0) return ret; /* now hit the volume update bits (always bit 8) */ val = wm8350_codec_read(codec, reg); wm8350_codec_write(codec, reg, val | WM8350_OUT1_VU); return 1; }
/* * Update the DC servo calibration on gain changes */ static int wm8993_put_dc_servo(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); int ret; ret = snd_soc_put_volsw_2r(kcontrol, ucontrol); /* Only need to do this if the outputs are active */ if (snd_soc_read(codec, WM8993_POWER_MANAGEMENT_1) & (WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA)) snd_soc_update_bits(codec, WM8993_DC_SERVO_0, WM8993_DCS_TRIG_SINGLE_0 | WM8993_DCS_TRIG_SINGLE_1, WM8993_DCS_TRIG_SINGLE_0 | WM8993_DCS_TRIG_SINGLE_1); return ret; }
static int cs42888_out_vu(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); unsigned int reg = mc->reg; unsigned int reg2 = mc->rreg; int ret; u16 val; ret = snd_soc_put_volsw_2r(kcontrol, ucontrol); if (ret < 0) return ret; /* Now write again with the volume update bit set */ val = cs42888_read_reg_cache(codec, reg); ret = cs42888_i2c_write(codec, reg, val); val = cs42888_read_reg_cache(codec, reg2); ret = cs42888_i2c_write(codec, reg2, val); return 0; }