ASoC: max98090: Add extcon support for jack detection notification 58/93258/5
authorDongwoo Lee <dwoo08.lee@samsung.com>
Fri, 21 Oct 2016 02:51:46 +0000 (11:51 +0900)
committerSeung-Woo Kim <sw0312.kim@samsung.com>
Mon, 24 Oct 2016 06:55:34 +0000 (23:55 -0700)
This patch applies extcon for jack detection notification.
Changes in jack state is reported to input driver with snd-soc
framework, as well as to extcon framework.

Change-Id: Id46f10320b18258472521fad57cbbfc98547bb6d
Signed-off-by: Dongwoo Lee <dwoo08.lee@samsung.com>
sound/soc/codecs/max98090.c
sound/soc/codecs/max98090.h

index 9f9f5ee42d6e8ed4a0b47ebf70a8ce6260c80599..b3dce978666589bc1b29e8cdc3bcd144fe56fab4 100644 (file)
 #include <sound/soc.h>
 #include <sound/tlv.h>
 #include <sound/max98090.h>
+#include <linux/extcon.h>
 #include "max98090.h"
 
+const char *max98090_extcon_cable[] = {
+       "Microphone",
+       "Headphone",
+       NULL,
+};
+
+static void max98090_extcon_jack_report(struct max98090_priv *max98090,
+                                       int prev_state, int status)
+{
+       struct extcon_dev *edev = max98090->edev;
+       int mic_state = status & SND_JACK_MICROPHONE;
+
+       /* report mic state if it is available, or connected previously */
+       if (mic_state || prev_state == M98090_JACK_STATE_HEADSET)
+               extcon_set_cable_state(edev, "Microphone", mic_state);
+
+       extcon_set_cable_state(edev, "Headphone", status & SND_JACK_HEADPHONE);
+}
+
 /* Allows for sparsely populated register maps */
 static struct reg_default max98090_reg[] = {
        { 0x00, 0x00 }, /* 00 Software Reset */
@@ -2188,7 +2208,7 @@ static void max98090_jack_work(struct work_struct *work)
                jack_work.work);
        struct snd_soc_codec *codec = max98090->codec;
        struct snd_soc_dapm_context *dapm = &codec->dapm;
-       int status = 0;
+       int prev_state, status = 0;
        int reg;
 
        /* Read a second time */
@@ -2209,6 +2229,8 @@ static void max98090_jack_work(struct work_struct *work)
                reg = snd_soc_read(codec, M98090_REG_JACK_STATUS);
        }
 
+       prev_state = max98090->jack_state;
+
        reg = snd_soc_read(codec, M98090_REG_JACK_STATUS);
 
        switch (reg & (M98090_LSNS_MASK | M98090_JKSNS_MASK)) {
@@ -2267,6 +2289,10 @@ static void max98090_jack_work(struct work_struct *work)
        snd_soc_jack_report(max98090->jack, status,
                            SND_JACK_HEADSET | SND_JACK_BTN_0);
 
+       /* only reports jack connection state with extcon */
+       if (!(status & SND_JACK_BTN_0))
+               max98090_extcon_jack_report(max98090, prev_state, status);
+
        snd_soc_dapm_sync(dapm);
 }
 
@@ -2654,6 +2680,19 @@ static int max98090_i2c_probe(struct i2c_client *i2c,
                return ret;
        }
 
+       max98090->edev = devm_extcon_dev_allocate(&i2c->dev,
+                                                       max98090_extcon_cable);
+       if (IS_ERR(max98090->edev))
+               return PTR_ERR(max98090->edev);
+
+       max98090->edev->name = "Headset Jack";
+
+       ret = devm_extcon_dev_register(&i2c->dev, max98090->edev);
+       if (ret < 0) {
+               dev_err(&i2c->dev, "extcon_dev_register() failed: %d\n", ret);
+               return ret;
+       }
+
        ret = snd_soc_register_codec(&i2c->dev,
                        &soc_codec_dev_max98090, max98090_dai,
                        ARRAY_SIZE(max98090_dai));
index 21ff743f5af28d07bdc6ec4209b84b6ca2e77929..189447963e0c950ba4373a5b677747b7af526af4 100644 (file)
@@ -1543,6 +1543,7 @@ struct max98090_priv {
        unsigned int pa2en;
        unsigned int sidetone;
        bool master;
+       struct extcon_dev *edev;
 };
 
 int max98090_mic_detect(struct snd_soc_codec *codec,