Audio: Add different handler for button_press GPIO
authorVaibhav Agarwal <vaibhav.agarwal@intel.com>
Tue, 20 Mar 2012 19:24:45 +0000 (00:54 +0530)
committerbuildbot <buildbot@intel.com>
Fri, 30 Mar 2012 14:51:29 +0000 (07:51 -0700)
BZ: 26377

Currently, only single handler is used for HP_DET,
BUTTON_PRESS interrupt line. However, it should be handled
differently. Thus, no interrupts are reported for button
press event(s).

The solution is to register seperate handlers for different
GPIO lines and handle each event appropriately.

Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@intel.com>
Change-Id: I8262487d423a10f49d93ca24be7a43cbac894738
Reviewed-on: http://android.intel.com:8080/39834
Reviewed-by: Kp, Jeeja <jeeja.kp@intel.com>
Reviewed-by: Koul, Vinod <vinod.koul@intel.com>
Reviewed-by: M, Arulselvan <arulselvan.m@intel.com>
Tested-by: M, Arulselvan <arulselvan.m@intel.com>
Reviewed-by: buildbot <buildbot@intel.com>
Tested-by: buildbot <buildbot@intel.com>
sound/soc/codecs/cs42l73.c
sound/soc/codecs/cs42l73.h
sound/soc/mid-x86/clv_machine.c

index 64dc63b..1557305 100644 (file)
@@ -1131,18 +1131,44 @@ static int cs42l73_set_mic_bias(struct snd_soc_codec *codec, int state)
        return 0;
 }
 
-void cs42l73_hp_detection(struct snd_soc_codec *codec,
+void cs42l73_bp_detection(struct snd_soc_codec *codec,
                           struct snd_soc_jack *jack,
                           int plug_status)
 {
        unsigned int status;
+       unsigned int reg;
+       unsigned int mask = SND_JACK_BTN_0 | SND_JACK_HEADSET;
+
+       if (plug_status) {
+               pr_err("%s: Invalid interrupt\n", __func__);
+               return;
+       } else {
+               snd_soc_update_bits(codec, CS42L73_IM1, MIC2_SDET, MIC2_SDET);
+               reg = snd_soc_read(codec, CS42L73_IS1);
+               if (reg & MIC2_SDET) { /*button pressed */
+                       pr_debug("%s:Button Pressed\n", __func__);
+                       status = SND_JACK_HEADSET | SND_JACK_BTN_0;
+               } else {
+                       pr_debug("%s:Button Released\n", __func__);
+                       status = SND_JACK_HEADSET;
+               }
+       }
+       snd_soc_jack_report(jack, status, mask);
+}
+EXPORT_SYMBOL_GPL(cs42l73_bp_detection);
+
+void cs42l73_hp_detection(struct snd_soc_codec *codec,
+                          struct snd_soc_jack *jack,
+                          int plug_status)
+{
+       unsigned int status = 0;
        unsigned int micbias = 0;
        int hs_status = 0;
        unsigned int reg;
        unsigned int mask = SND_JACK_BTN_0 | SND_JACK_HEADSET;
 
        if (plug_status) {
-               pr_debug("In cs42l73_hp_detection disable micbias\n");
+               pr_debug("%s: Jack removed - disable micbias\n", __func__);
                cs42l73_set_mic_bias(codec, MIC_BIAS_DISABLE);
        } else {
                micbias = snd_soc_read(codec, CS42L73_PWRCTL2);
@@ -1153,7 +1179,6 @@ void cs42l73_hp_detection(struct snd_soc_codec *codec,
                }
 
                snd_soc_update_bits(codec, CS42L73_IM1, MIC2_SDET, MIC2_SDET);
-               mdelay(1000);
                reg = snd_soc_read(codec, CS42L73_IS1);
 
                pr_debug("Mic detect = %x ISI =%x\n", micbias, reg);
@@ -1166,11 +1191,6 @@ void cs42l73_hp_detection(struct snd_soc_codec *codec,
                                status = SND_JACK_HEADSET;
                                pr_debug("Headset detected\n");
                        }
-               } else {
-                       if (reg & MIC2_SDET)  /*button pressed */
-                               status = SND_JACK_HEADSET | SND_JACK_BTN_0;
-                       else
-                               status = SND_JACK_HEADSET;
                }
        }
        snd_soc_jack_report(jack, status, mask);
@@ -1286,8 +1306,6 @@ static __devinit int cs42l73_i2c_probe(struct i2c_client *i2c_client,
 
 static __devexit int cs42l73_i2c_remove(struct i2c_client *client)
 {
-       struct cs42l73_private *cs42l73 = i2c_get_clientdata(client);
-
        snd_soc_unregister_codec(&client->dev);
 
        /* No need for kfree(cs42l73), as it'll be automatically freed
index 0e844d5..cd31959 100644 (file)
 #define CS42L73_MMCC(id)       (CS42L73_XSPMMCC + (id << 1))
 #define CS42L73_SPFS(id) ((id == CS42L73_ASP) ? CS42L73_ASPC : CS42L73_VXSPFS)
 
+extern void cs42l73_bp_detection(struct snd_soc_codec *codec,
+                                 struct snd_soc_jack *jack, int plug_status);
 extern void cs42l73_hp_detection(struct snd_soc_codec *codec,
                                  struct snd_soc_jack *jack, int plug_status);
 
index 7297cf0..ca9c80c 100644 (file)
@@ -162,6 +162,40 @@ static struct snd_soc_jack_gpio hs_button_gpio = {
        .report = SND_JACK_BTN_0,
        .debounce_time = 100,
 };
+
+static void clv_soc_jack_gpio_detect_bp(struct snd_soc_jack_gpio *gpio)
+{
+       int enable;
+       struct snd_soc_jack *jack = gpio->jack;
+       struct snd_soc_codec *codec = jack->codec;
+
+       enable = gpio_get_value(gpio->gpio);
+       if (gpio->invert)
+               enable = !enable;
+       pr_debug("%s: gpio->%d=0x%x\n", __func__, gpio->gpio, enable);
+       cs42l73_bp_detection(codec, jack, enable);
+}
+
+/* irq handler for button_press gpio pin */
+static irqreturn_t clv_gpio_handler_bp(int irq, void *data)
+{
+       struct snd_soc_jack_gpio *gpio = data;
+
+       schedule_delayed_work(&gpio->work,
+                               msecs_to_jiffies(gpio->debounce_time));
+
+       return IRQ_HANDLED;
+}
+
+/* gpio work */
+static void clv_gpio_work_bp(struct work_struct *work)
+{
+       struct snd_soc_jack_gpio *gpio;
+
+       gpio = container_of(work, struct snd_soc_jack_gpio, work.work);
+       clv_soc_jack_gpio_detect_bp(gpio);
+}
+
 static void clv_soc_jack_gpio_detect(struct snd_soc_jack_gpio *gpio)
 {
        int enable;
@@ -170,6 +204,7 @@ static void clv_soc_jack_gpio_detect(struct snd_soc_jack_gpio *gpio)
        enable = gpio_get_value(gpio->gpio);
        if (gpio->invert)
                enable = !enable;
+       pr_debug("%s:gpio->%d=0x%d\n", __func__, gpio->gpio, enable);
        cs42l73_hp_detection(codec, jack, enable);
 }
 
@@ -224,11 +259,21 @@ int clv_soc_jack_add_gpio(struct snd_soc_jack *jack,
        if (ret)
                goto err;
 
-       INIT_DELAYED_WORK(&gpio->work, clv_gpio_work);
-       gpio->jack = jack;
+       if (gpio->gpio == CS42L73_HPSENSE_GPIO) {
+
+               INIT_DELAYED_WORK(&gpio->work, clv_gpio_work);
+               gpio->jack = jack;
+
+               ret = request_irq(gpio_to_irq(gpio->gpio), clv_gpio_handler,
+                               IRQF_TRIGGER_FALLING, codec->name, gpio);
+       } else {
+               INIT_DELAYED_WORK(&gpio->work, clv_gpio_work_bp);
+               gpio->jack = jack;
+
+               ret = request_irq(gpio_to_irq(gpio->gpio), clv_gpio_handler_bp,
+                               IRQF_TRIGGER_FALLING, codec->name, gpio);
 
-       ret = request_irq(gpio_to_irq(gpio->gpio), clv_gpio_handler,
-                                IRQF_TRIGGER_FALLING, codec->name, gpio);
+       }
        if (ret)
                goto err;
 
@@ -239,6 +284,7 @@ int clv_soc_jack_add_gpio(struct snd_soc_jack *jack,
        /* Update initial jack status */
        if (gpio->gpio == CS42L73_HPSENSE_GPIO)
                clv_soc_jack_gpio_detect(gpio);
+
        return 0;
 
 err: