From 0e82e9072af96d58e85122296c074a37085879e7 Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Fri, 21 Oct 2016 11:51:46 +0900 Subject: 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 --- sound/soc/codecs/max98090.c | 41 ++++++++++++++++++++++++++++++++++++++++- sound/soc/codecs/max98090.h | 1 + 2 files changed, 41 insertions(+), 1 deletion(-) 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 #include #include +#include #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, -- cgit v1.2.3