]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
ASoC: twl6040: Remove HS/HF gain ramp feature
authorPeter Ujfalusi <peter.ujfalusi@ti.com>
Fri, 4 May 2012 12:17:20 +0000 (15:17 +0300)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Mon, 7 May 2012 17:27:36 +0000 (18:27 +0100)
None of the machines uses the gain ramp possibility for HS/HF.
This code path is mostly unused and it does not reduces the pop
noise on the output (it alters it to sound a bit different).
The preferred method to reduce pop noise is to use ABE.
Remove the gain ramp, and related features form the driver.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
sound/soc/codecs/twl6040.c

index ccbc88aa84977d755213bbdb7c314a2cf40b1c6b..d3807a3549419b31ff8eb4b429c6cdb341d425ff 100644 (file)
 #define TWL6040_OUTHF_0dB 0x03
 #define TWL6040_OUTHF_M52dB 0x1D
 
-#define TWL6040_RAMP_NONE      0
-#define TWL6040_RAMP_UP                1
-#define TWL6040_RAMP_DOWN      2
-
-#define TWL6040_HSL_VOL_MASK   0x0F
-#define TWL6040_HSL_VOL_SHIFT  0
-#define TWL6040_HSR_VOL_MASK   0xF0
-#define TWL6040_HSR_VOL_SHIFT  4
-#define TWL6040_HF_VOL_MASK    0x1F
-#define TWL6040_HF_VOL_SHIFT   0
-
 /* Shadow register used by the driver */
 #define TWL6040_REG_SW_SHADOW  0x2F
 #define TWL6040_CACHEREGNUM    (TWL6040_REG_SW_SHADOW + 1)
 /* TWL6040_REG_SW_SHADOW (0x2F) fields */
 #define TWL6040_EAR_PATH_ENABLE        0x01
 
-struct twl6040_output {
-       u16 active;
-       u16 left_vol;
-       u16 right_vol;
-       u16 left_step;
-       u16 right_step;
-       unsigned int step_delay;
-       u16 ramp;
-       struct delayed_work work;
-       struct completion ramp_done;
-};
-
 struct twl6040_jack_data {
        struct snd_soc_jack *jack;
        struct delayed_work work;
@@ -101,8 +78,6 @@ struct twl6040_data {
        struct snd_soc_codec *codec;
        struct workqueue_struct *workqueue;
        struct mutex mutex;
-       struct twl6040_output headset;
-       struct twl6040_output handsfree;
 };
 
 /*
@@ -312,318 +287,6 @@ static void twl6040_restore_regs(struct snd_soc_codec *codec)
        }
 }
 
-/*
- * Ramp HS PGA volume to minimise pops at stream startup and shutdown.
- */
-static inline int twl6040_hs_ramp_step(struct snd_soc_codec *codec,
-                       unsigned int left_step, unsigned int right_step)
-{
-
-       struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
-       struct twl6040_output *headset = &priv->headset;
-       int left_complete = 0, right_complete = 0;
-       u8 reg, val;
-
-       /* left channel */
-       left_step = (left_step > 0xF) ? 0xF : left_step;
-       reg = twl6040_read_reg_cache(codec, TWL6040_REG_HSGAIN);
-       val = (~reg & TWL6040_HSL_VOL_MASK);
-
-       if (headset->ramp == TWL6040_RAMP_UP) {
-               /* ramp step up */
-               if (val < headset->left_vol) {
-                       if (val + left_step > headset->left_vol)
-                               val = headset->left_vol;
-                       else
-                               val += left_step;
-
-                       reg &= ~TWL6040_HSL_VOL_MASK;
-                       twl6040_write(codec, TWL6040_REG_HSGAIN,
-                                       (reg | (~val & TWL6040_HSL_VOL_MASK)));
-               } else {
-                       left_complete = 1;
-               }
-       } else if (headset->ramp == TWL6040_RAMP_DOWN) {
-               /* ramp step down */
-               if (val > 0x0) {
-                       if ((int)val - (int)left_step < 0)
-                               val = 0;
-                       else
-                               val -= left_step;
-
-                       reg &= ~TWL6040_HSL_VOL_MASK;
-                       twl6040_write(codec, TWL6040_REG_HSGAIN, reg |
-                                               (~val & TWL6040_HSL_VOL_MASK));
-               } else {
-                       left_complete = 1;
-               }
-       }
-
-       /* right channel */
-       right_step = (right_step > 0xF) ? 0xF : right_step;
-       reg = twl6040_read_reg_cache(codec, TWL6040_REG_HSGAIN);
-       val = (~reg & TWL6040_HSR_VOL_MASK) >> TWL6040_HSR_VOL_SHIFT;
-
-       if (headset->ramp == TWL6040_RAMP_UP) {
-               /* ramp step up */
-               if (val < headset->right_vol) {
-                       if (val + right_step > headset->right_vol)
-                               val = headset->right_vol;
-                       else
-                               val += right_step;
-
-                       reg &= ~TWL6040_HSR_VOL_MASK;
-                       twl6040_write(codec, TWL6040_REG_HSGAIN,
-                               (reg | (~val << TWL6040_HSR_VOL_SHIFT)));
-               } else {
-                       right_complete = 1;
-               }
-       } else if (headset->ramp == TWL6040_RAMP_DOWN) {
-               /* ramp step down */
-               if (val > 0x0) {
-                       if ((int)val - (int)right_step < 0)
-                               val = 0;
-                       else
-                               val -= right_step;
-
-                       reg &= ~TWL6040_HSR_VOL_MASK;
-                       twl6040_write(codec, TWL6040_REG_HSGAIN,
-                                        reg | (~val << TWL6040_HSR_VOL_SHIFT));
-               } else {
-                       right_complete = 1;
-               }
-       }
-
-       return left_complete & right_complete;
-}
-
-/*
- * Ramp HF PGA volume to minimise pops at stream startup and shutdown.
- */
-static inline int twl6040_hf_ramp_step(struct snd_soc_codec *codec,
-                       unsigned int left_step, unsigned int right_step)
-{
-       struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
-       struct twl6040_output *handsfree = &priv->handsfree;
-       int left_complete = 0, right_complete = 0;
-       u16 reg, val;
-
-       /* left channel */
-       left_step = (left_step > 0x1D) ? 0x1D : left_step;
-       reg = twl6040_read_reg_cache(codec, TWL6040_REG_HFLGAIN);
-       reg = 0x1D - reg;
-       val = (reg & TWL6040_HF_VOL_MASK);
-       if (handsfree->ramp == TWL6040_RAMP_UP) {
-               /* ramp step up */
-               if (val < handsfree->left_vol) {
-                       if (val + left_step > handsfree->left_vol)
-                               val = handsfree->left_vol;
-                       else
-                               val += left_step;
-
-                       reg &= ~TWL6040_HF_VOL_MASK;
-                       twl6040_write(codec, TWL6040_REG_HFLGAIN,
-                                               reg | (0x1D - val));
-               } else {
-                       left_complete = 1;
-               }
-       } else if (handsfree->ramp == TWL6040_RAMP_DOWN) {
-               /* ramp step down */
-               if (val > 0) {
-                       if ((int)val - (int)left_step < 0)
-                               val = 0;
-                       else
-                               val -= left_step;
-
-                       reg &= ~TWL6040_HF_VOL_MASK;
-                       twl6040_write(codec, TWL6040_REG_HFLGAIN,
-                                               reg | (0x1D - val));
-               } else {
-                       left_complete = 1;
-               }
-       }
-
-       /* right channel */
-       right_step = (right_step > 0x1D) ? 0x1D : right_step;
-       reg = twl6040_read_reg_cache(codec, TWL6040_REG_HFRGAIN);
-       reg = 0x1D - reg;
-       val = (reg & TWL6040_HF_VOL_MASK);
-       if (handsfree->ramp == TWL6040_RAMP_UP) {
-               /* ramp step up */
-               if (val < handsfree->right_vol) {
-                       if (val + right_step > handsfree->right_vol)
-                               val = handsfree->right_vol;
-                       else
-                               val += right_step;
-
-                       reg &= ~TWL6040_HF_VOL_MASK;
-                       twl6040_write(codec, TWL6040_REG_HFRGAIN,
-                                               reg | (0x1D - val));
-               } else {
-                       right_complete = 1;
-               }
-       } else if (handsfree->ramp == TWL6040_RAMP_DOWN) {
-               /* ramp step down */
-               if (val > 0) {
-                       if ((int)val - (int)right_step < 0)
-                               val = 0;
-                       else
-                               val -= right_step;
-
-                       reg &= ~TWL6040_HF_VOL_MASK;
-                       twl6040_write(codec, TWL6040_REG_HFRGAIN,
-                                               reg | (0x1D - val));
-               }
-       }
-
-       return left_complete & right_complete;
-}
-
-/*
- * This work ramps both output PGAs at stream start/stop time to
- * minimise pop associated with DAPM power switching.
- */
-static void twl6040_pga_hs_work(struct work_struct *work)
-{
-       struct twl6040_data *priv =
-               container_of(work, struct twl6040_data, headset.work.work);
-       struct snd_soc_codec *codec = priv->codec;
-       struct twl6040_output *headset = &priv->headset;
-       int i, headset_complete;
-
-       /* do we need to ramp at all ? */
-       if (headset->ramp == TWL6040_RAMP_NONE)
-               return;
-
-       /* HS PGA gain range: 0x0 - 0xf (0 - 15) */
-       for (i = 0; i < 16; i++) {
-               headset_complete = twl6040_hs_ramp_step(codec,
-                                               headset->left_step,
-                                               headset->right_step);
-
-               /* ramp finished ? */
-               if (headset_complete)
-                       break;
-
-               schedule_timeout_interruptible(
-                               msecs_to_jiffies(headset->step_delay));
-       }
-
-       if (headset->ramp == TWL6040_RAMP_DOWN) {
-               headset->active = 0;
-               complete(&headset->ramp_done);
-       } else {
-               headset->active = 1;
-       }
-       headset->ramp = TWL6040_RAMP_NONE;
-}
-
-static void twl6040_pga_hf_work(struct work_struct *work)
-{
-       struct twl6040_data *priv =
-               container_of(work, struct twl6040_data, handsfree.work.work);
-       struct snd_soc_codec *codec = priv->codec;
-       struct twl6040_output *handsfree = &priv->handsfree;
-       int i, handsfree_complete;
-
-       /* do we need to ramp at all ? */
-       if (handsfree->ramp == TWL6040_RAMP_NONE)
-               return;
-
-       /*
-        * HF PGA gain range: 0x00 - 0x1d (0 - 29) */
-       for (i = 0; i < 30; i++) {
-               handsfree_complete = twl6040_hf_ramp_step(codec,
-                                               handsfree->left_step,
-                                               handsfree->right_step);
-
-               /* ramp finished ? */
-               if (handsfree_complete)
-                       break;
-
-               schedule_timeout_interruptible(
-                               msecs_to_jiffies(handsfree->step_delay));
-       }
-
-
-       if (handsfree->ramp == TWL6040_RAMP_DOWN) {
-               handsfree->active = 0;
-               complete(&handsfree->ramp_done);
-       } else
-               handsfree->active = 1;
-       handsfree->ramp = TWL6040_RAMP_NONE;
-}
-
-static int out_drv_event(struct snd_soc_dapm_widget *w,
-                       struct snd_kcontrol *kcontrol, int event)
-{
-       struct snd_soc_codec *codec = w->codec;
-       struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
-       struct twl6040_output *out;
-       struct delayed_work *work;
-
-       switch (w->shift) {
-       case 2: /* Headset output driver */
-               out = &priv->headset;
-               work = &out->work;
-               /*
-                * Make sure, that we do not mess up variables for already
-                * executing work.
-                */
-               cancel_delayed_work_sync(work);
-
-               out->left_step = priv->hs_left_step;
-               out->right_step = priv->hs_right_step;
-               out->step_delay = 5;    /* 5 ms between volume ramp steps */
-               break;
-       case 4: /* Handsfree output driver */
-               out = &priv->handsfree;
-               work = &out->work;
-               /*
-                * Make sure, that we do not mess up variables for already
-                * executing work.
-                */
-               cancel_delayed_work_sync(work);
-
-               out->left_step = priv->hf_left_step;
-               out->right_step = priv->hf_right_step;
-               out->step_delay = 5;    /* 5 ms between volume ramp steps */
-               break;
-       default:
-               return -1;
-       }
-
-       switch (event) {
-       case SND_SOC_DAPM_POST_PMU:
-               if (out->active)
-                       break;
-
-               /* don't use volume ramp for power-up */
-               out->ramp = TWL6040_RAMP_UP;
-               out->left_step = out->left_vol;
-               out->right_step = out->right_vol;
-
-               queue_delayed_work(priv->workqueue, work, msecs_to_jiffies(1));
-               break;
-
-       case SND_SOC_DAPM_PRE_PMD:
-               if (!out->active)
-                       break;
-
-               /* use volume ramp for power-down */
-               out->ramp = TWL6040_RAMP_DOWN;
-               INIT_COMPLETION(out->ramp_done);
-
-               queue_delayed_work(priv->workqueue, work, msecs_to_jiffies(1));
-
-               wait_for_completion_timeout(&out->ramp_done,
-                                           msecs_to_jiffies(2000));
-               break;
-       }
-
-       return 0;
-}
-
 /* set headset dac and driver power mode */
 static int headset_power_mode(struct snd_soc_codec *codec, int high_perf)
 {
@@ -748,71 +411,6 @@ static irqreturn_t twl6040_audio_handler(int irq, void *data)
        return IRQ_HANDLED;
 }
 
-static int twl6040_put_volsw(struct snd_kcontrol *kcontrol,
-                                 struct snd_ctl_elem_value *ucontrol)
-{
-       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct twl6040_data *twl6040_priv = snd_soc_codec_get_drvdata(codec);
-       struct twl6040_output *out = NULL;
-       struct soc_mixer_control *mc =
-               (struct soc_mixer_control *)kcontrol->private_value;
-       int ret;
-
-       /* For HS and HF 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 (mc->reg) {
-       case TWL6040_REG_HSGAIN:
-               out = &twl6040_priv->headset;
-               break;
-       case TWL6040_REG_HFLGAIN:
-               out = &twl6040_priv->handsfree;
-               break;
-       default:
-               dev_warn(codec->dev, "%s: Unexpected register: 0x%02x\n",
-                                       __func__, mc->reg);
-               return -EINVAL;
-       }
-
-       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(kcontrol, ucontrol);
-       if (ret < 0)
-               return ret;
-
-       return 1;
-}
-
-static int twl6040_get_volsw(struct snd_kcontrol *kcontrol,
-                               struct snd_ctl_elem_value *ucontrol)
-{
-       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct twl6040_data *twl6040_priv = snd_soc_codec_get_drvdata(codec);
-       struct twl6040_output *out = &twl6040_priv->headset;
-       struct soc_mixer_control *mc =
-               (struct soc_mixer_control *)kcontrol->private_value;
-
-       switch (mc->reg) {
-       case TWL6040_REG_HSGAIN:
-               out = &twl6040_priv->headset;
-               break;
-       case TWL6040_REG_HFLGAIN:
-               out = &twl6040_priv->handsfree;
-               break;
-       default:
-               dev_warn(codec->dev, "%s: Unexpected register: 0x%02x\n",
-                                       __func__, mc->reg);
-               return -EINVAL;
-       }
-
-       ucontrol->value.integer.value[0] = out->left_vol;
-       ucontrol->value.integer.value[1] = out->right_vol;
-       return 0;
-}
-
 static int twl6040_soc_dapm_put_vibra_enum(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol)
 {
@@ -1077,12 +675,10 @@ static const struct snd_kcontrol_new twl6040_snd_controls[] = {
                TWL6040_REG_LINEGAIN, 0, 3, 7, 0, afm_amp_tlv),
 
        /* Playback gains */
-       SOC_DOUBLE_EXT_TLV("Headset Playback Volume",
-               TWL6040_REG_HSGAIN, 0, 4, 0xF, 1, twl6040_get_volsw,
-               twl6040_put_volsw, hs_tlv),
-       SOC_DOUBLE_R_EXT_TLV("Handsfree Playback Volume",
-               TWL6040_REG_HFLGAIN, TWL6040_REG_HFRGAIN, 0, 0x1D, 1,
-               twl6040_get_volsw, twl6040_put_volsw, hf_tlv),
+       SOC_DOUBLE_TLV("Headset Playback Volume",
+               TWL6040_REG_HSGAIN, 0, 4, 0xF, 1, hs_tlv),
+       SOC_DOUBLE_R_TLV("Handsfree Playback Volume",
+               TWL6040_REG_HFLGAIN, TWL6040_REG_HFRGAIN, 0, 0x1D, 1, hf_tlv),
        SOC_SINGLE_TLV("Earphone Playback Volume",
                TWL6040_REG_EARCTL, 1, 0xF, 1, ep_tlv),
 
@@ -1181,22 +777,14 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = {
                        &auxr_switch_control),
 
        /* Analog playback drivers */
-       SND_SOC_DAPM_OUT_DRV_E("HF Left Driver",
-                       TWL6040_REG_HFLCTL, 4, 0, NULL, 0,
-                       out_drv_event,
-                       SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
-       SND_SOC_DAPM_OUT_DRV_E("HF Right Driver",
-                       TWL6040_REG_HFRCTL, 4, 0, NULL, 0,
-                       out_drv_event,
-                       SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
-       SND_SOC_DAPM_OUT_DRV_E("HS Left Driver",
-                       TWL6040_REG_HSLCTL, 2, 0, NULL, 0,
-                       out_drv_event,
-                       SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
-       SND_SOC_DAPM_OUT_DRV_E("HS Right Driver",
-                       TWL6040_REG_HSRCTL, 2, 0, NULL, 0,
-                       out_drv_event,
-                       SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+       SND_SOC_DAPM_OUT_DRV("HF Left Driver",
+                       TWL6040_REG_HFLCTL, 4, 0, NULL, 0),
+       SND_SOC_DAPM_OUT_DRV("HF Right Driver",
+                       TWL6040_REG_HFRCTL, 4, 0, NULL, 0),
+       SND_SOC_DAPM_OUT_DRV("HS Left Driver",
+                       TWL6040_REG_HSLCTL, 2, 0, NULL, 0),
+       SND_SOC_DAPM_OUT_DRV("HS Right Driver",
+                       TWL6040_REG_HSRCTL, 2, 0, NULL, 0),
        SND_SOC_DAPM_OUT_DRV_E("Earphone Driver",
                        TWL6040_REG_EARCTL, 0, 0, NULL, 0,
                        twl6040_ep_drv_event,
@@ -1568,14 +1156,9 @@ static int twl6040_probe(struct snd_soc_codec *codec)
        }
 
        INIT_DELAYED_WORK(&priv->hs_jack.work, twl6040_accessory_work);
-       INIT_DELAYED_WORK(&priv->headset.work, twl6040_pga_hs_work);
-       INIT_DELAYED_WORK(&priv->handsfree.work, twl6040_pga_hf_work);
 
        mutex_init(&priv->mutex);
 
-       init_completion(&priv->headset.ramp_done);
-       init_completion(&priv->handsfree.ramp_done);
-
        ret = request_threaded_irq(priv->plug_irq, NULL, twl6040_audio_handler,
                                   0, "twl6040_irq_plug", codec);
        if (ret) {