diff options
author | Dongwoo Lee <dwoo08.lee@samsung.com> | 2016-10-21 11:51:46 +0900 |
---|---|---|
committer | Seung-Woo Kim <sw0312.kim@samsung.com> | 2016-12-14 13:54:36 +0900 |
commit | 0e82e9072af96d58e85122296c074a37085879e7 (patch) | |
tree | 835c40b4c0a21dbfc7f40036ff54c6f61b6c7e80 | |
parent | 287de690cbe05fa894e510b9482f47943227f259 (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.c | 41 | ||||
-rw-r--r-- | sound/soc/codecs/max98090.h | 1 |
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, |