summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDongwoo Lee <dwoo08.lee@samsung.com>2016-10-21 11:51:46 +0900
committerSeung-Woo Kim <sw0312.kim@samsung.com>2016-12-14 13:54:36 +0900
commit0e82e9072af96d58e85122296c074a37085879e7 (patch)
tree835c40b4c0a21dbfc7f40036ff54c6f61b6c7e80
parent287de690cbe05fa894e510b9482f47943227f259 (diff)
ASoC: max98090: Add extcon support for jack detection notification
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>
-rw-r--r--sound/soc/codecs/max98090.c41
-rw-r--r--sound/soc/codecs/max98090.h1
2 files changed, 41 insertions, 1 deletions
diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c
index 9f9f5ee42d6e..b3dce9786665 100644
--- a/sound/soc/codecs/max98090.c
+++ b/sound/soc/codecs/max98090.c
@@ -24,8 +24,28 @@
#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));
diff --git a/sound/soc/codecs/max98090.h b/sound/soc/codecs/max98090.h
index 21ff743f5af2..189447963e0c 100644
--- a/sound/soc/codecs/max98090.h
+++ b/sound/soc/codecs/max98090.h
@@ -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,