All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/5] rt5651: Enable jack detection
@ 2017-10-20 11:18 Carlo Caione
  2017-10-20 11:18 ` [PATCH v2 1/5] ASoC: rt5651: Enable jack detection on JD* pins Carlo Caione
                   ` (4 more replies)
  0 siblings, 5 replies; 18+ messages in thread
From: Carlo Caione @ 2017-10-20 11:18 UTC (permalink / raw)
  To: linux, bardliao, oder_chiou, pierre-louis.bossart, broonie,
	alsa-devel, linux-kernel, tiwai, albertchen, edgar_shen
  Cc: Carlo Caione

From: Carlo Caione <carlo@endlessm.com>

Patchset to support jack detection for the rt5651 codec on the JD* pins
and enable it on the KIANO cherry-trail laptop.

Changelog:
v2:
 - Added quirks for the KIANO laptop
 - Extended support to JD1_2 and JD2 pins
 - Reworked quirk logic in the codec driver
 - Codec driver can now differentiate between headphone and headset
   (thank you Bard Liao)

Carlo Caione (5):
  ASoC: rt5651: Enable jack detection on JD* pins
  ASoC: intel: byt: Add headset jack
  ASoC: intel: byt: Enable IN2 map quirk for a KIANO laptop
  ASoC: rt5651: Rework quirk logic
  ASoC: rt5651: Enable JD1_1 quirk for KIANO laptopt

 include/sound/rt5651.h                |   8 ++
 sound/soc/codecs/rt5651.c             | 215 +++++++++++++++++++++++++++++++++-
 sound/soc/codecs/rt5651.h             |   4 +
 sound/soc/intel/boards/bytcr_rt5651.c |  31 +++++
 4 files changed, 252 insertions(+), 6 deletions(-)

-- 
2.14.2

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH v2 1/5] ASoC: rt5651: Enable jack detection on JD* pins
  2017-10-20 11:18 [PATCH v2 0/5] rt5651: Enable jack detection Carlo Caione
@ 2017-10-20 11:18 ` Carlo Caione
  2017-10-26 14:17     ` Mark Brown
  2017-10-26 14:17     ` Mark Brown
  2017-10-20 11:18 ` [PATCH v2 2/5] ASoC: intel: byt: Add headset jack Carlo Caione
                   ` (3 subsequent siblings)
  4 siblings, 2 replies; 18+ messages in thread
From: Carlo Caione @ 2017-10-20 11:18 UTC (permalink / raw)
  To: linux, bardliao, oder_chiou, pierre-louis.bossart, broonie,
	alsa-devel, linux-kernel, tiwai, albertchen, edgar_shen
  Cc: Carlo Caione

From: Carlo Caione <carlo@endlessm.com>

Enable jack detection for the RT5651 codec on the JD* pins.

Signed-off-by: Carlo Caione <carlo@endlessm.com>
---
 include/sound/rt5651.h    |   8 +++
 sound/soc/codecs/rt5651.c | 168 +++++++++++++++++++++++++++++++++++++++++++++-
 sound/soc/codecs/rt5651.h |   4 ++
 3 files changed, 178 insertions(+), 2 deletions(-)

diff --git a/include/sound/rt5651.h b/include/sound/rt5651.h
index d35de758dfb5..18b79a761f10 100644
--- a/include/sound/rt5651.h
+++ b/include/sound/rt5651.h
@@ -11,11 +11,19 @@
 #ifndef __LINUX_SND_RT5651_H
 #define __LINUX_SND_RT5651_H
 
+enum rt5651_jd_src {
+	RT5651_JD_NULL,
+	RT5651_JD1_1,
+	RT5651_JD1_2,
+	RT5651_JD2,
+};
+
 struct rt5651_platform_data {
 	/* IN2 can optionally be differential */
 	bool in2_diff;
 
 	bool dmic_en;
+	enum rt5651_jd_src jd_src;
 };
 
 #endif
diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c
index 28f7210cec91..91f254391452 100644
--- a/sound/soc/codecs/rt5651.c
+++ b/sound/soc/codecs/rt5651.c
@@ -26,6 +26,7 @@
 #include <sound/soc-dapm.h>
 #include <sound/initval.h>
 #include <sound/tlv.h>
+#include <sound/jack.h>
 
 #include "rl6231.h"
 #include "rt5651.h"
@@ -880,6 +881,9 @@ static const struct snd_soc_dapm_widget rt5651_dapm_widgets[] = {
 	SND_SOC_DAPM_SUPPLY("PLL1", RT5651_PWR_ANLG2,
 			RT5651_PWR_PLL_BIT, 0, NULL, 0),
 	/* Input Side */
+	SND_SOC_DAPM_SUPPLY("JD Power", RT5651_PWR_ANLG2,
+		RT5651_PWM_JD_M_BIT, 0, NULL, 0),
+
 	/* micbias */
 	SND_SOC_DAPM_SUPPLY("LDO", RT5651_PWR_ANLG1,
 			RT5651_PWR_LDO_BIT, 0, NULL, 0),
@@ -1528,6 +1532,8 @@ static int rt5651_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
 static int rt5651_set_bias_level(struct snd_soc_codec *codec,
 			enum snd_soc_bias_level level)
 {
+	struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
+
 	switch (level) {
 	case SND_SOC_BIAS_PREPARE:
 		if (SND_SOC_BIAS_STANDBY == snd_soc_codec_get_bias_level(codec)) {
@@ -1556,8 +1562,13 @@ static int rt5651_set_bias_level(struct snd_soc_codec *codec,
 		snd_soc_write(codec, RT5651_PWR_DIG2, 0x0000);
 		snd_soc_write(codec, RT5651_PWR_VOL, 0x0000);
 		snd_soc_write(codec, RT5651_PWR_MIXER, 0x0000);
-		snd_soc_write(codec, RT5651_PWR_ANLG1, 0x0000);
-		snd_soc_write(codec, RT5651_PWR_ANLG2, 0x0000);
+		if (rt5651->pdata.jd_src) {
+			snd_soc_write(codec, RT5651_PWR_ANLG2, 0x0204);
+			snd_soc_write(codec, RT5651_PWR_ANLG1, 0x0002);
+		} else {
+			snd_soc_write(codec, RT5651_PWR_ANLG1, 0x0000);
+			snd_soc_write(codec, RT5651_PWR_ANLG2, 0x0000);
+		}
 		break;
 
 	default:
@@ -1570,6 +1581,7 @@ static int rt5651_set_bias_level(struct snd_soc_codec *codec,
 static int rt5651_probe(struct snd_soc_codec *codec)
 {
 	struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
+	struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
 
 	rt5651->codec = codec;
 
@@ -1585,6 +1597,15 @@ static int rt5651_probe(struct snd_soc_codec *codec)
 
 	snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_OFF);
 
+	if (rt5651->pdata.jd_src) {
+		snd_soc_dapm_force_enable_pin(dapm, "JD Power");
+		snd_soc_dapm_force_enable_pin(dapm, "LDO");
+		snd_soc_dapm_sync(dapm);
+
+		regmap_update_bits(rt5651->regmap, RT5651_MICBIAS,
+				   0x38, 0x38);
+	}
+
 	return 0;
 }
 
@@ -1728,6 +1749,93 @@ static int rt5651_parse_dt(struct rt5651_priv *rt5651, struct device_node *np)
 	return 0;
 }
 
+static irqreturn_t rt5651_irq(int irq, void *data)
+{
+	struct rt5651_priv *rt5651 = data;
+
+	queue_delayed_work(system_power_efficient_wq,
+			   &rt5651->jack_detect_work, msecs_to_jiffies(250));
+
+	return IRQ_HANDLED;
+}
+
+static int rt5651_jack_detect(struct snd_soc_codec *codec, int jack_insert)
+{
+	struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
+	int jack_type;
+
+	if (jack_insert) {
+		snd_soc_dapm_force_enable_pin(dapm, "LDO");
+		snd_soc_dapm_sync(dapm);
+
+		snd_soc_update_bits(codec, RT5651_MICBIAS,
+				    RT5651_MIC1_OVCD_MASK |
+				    RT5651_MIC1_OVTH_MASK |
+				    RT5651_PWR_CLK12M_MASK |
+				    RT5651_PWR_MB_MASK,
+				    RT5651_MIC1_OVCD_EN |
+				    RT5651_MIC1_OVTH_600UA |
+				    RT5651_PWR_MB_PU |
+				    RT5651_PWR_CLK12M_PU);
+		msleep(100);
+		if (snd_soc_read(codec, RT5651_IRQ_CTRL2) & RT5651_MB1_OC_CLR)
+			jack_type = SND_JACK_HEADPHONE;
+		else
+			jack_type = SND_JACK_HEADSET;
+		snd_soc_update_bits(codec, RT5651_IRQ_CTRL2,
+				    RT5651_MB1_OC_CLR, 0);
+	} else { /* jack out */
+		jack_type = 0;
+
+		snd_soc_update_bits(codec, RT5651_MICBIAS,
+				    RT5651_MIC1_OVCD_MASK,
+				    RT5651_MIC1_OVCD_DIS);
+	}
+
+	return jack_type;
+}
+
+static void rt5651_jack_detect_work(struct work_struct *work)
+{
+	struct rt5651_priv *rt5651 =
+		container_of(work, struct rt5651_priv, jack_detect_work.work);
+
+	int report, val = 0;
+
+	if (!rt5651->codec)
+		return;
+
+	switch (rt5651->pdata.jd_src) {
+	case RT5651_JD1_1:
+		val = snd_soc_read(rt5651->codec, RT5651_INT_IRQ_ST) & 0x1000;
+		break;
+	case RT5651_JD1_2:
+		val = snd_soc_read(rt5651->codec, RT5651_INT_IRQ_ST) & 0x2000;
+		break;
+	case RT5651_JD2:
+		val = snd_soc_read(rt5651->codec, RT5651_INT_IRQ_ST) & 0x4000;
+		break;
+	default:
+		break;
+	}
+
+	report = rt5651_jack_detect(rt5651->codec, !val);
+
+	snd_soc_jack_report(rt5651->hp_jack, report, SND_JACK_HEADSET);
+}
+
+int rt5651_set_jack_detect(struct snd_soc_codec *codec,
+			   struct snd_soc_jack *hp_jack)
+{
+	struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
+
+	rt5651->hp_jack = hp_jack;
+	rt5651_irq(0, rt5651);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rt5651_set_jack_detect);
+
 static int rt5651_i2c_probe(struct i2c_client *i2c,
 		    const struct i2c_device_id *id)
 {
@@ -1779,6 +1887,59 @@ static int rt5651_i2c_probe(struct i2c_client *i2c,
 
 	rt5651->hp_mute = 1;
 
+	if (rt5651->pdata.jd_src) {
+
+		/* IRQ output on GPIO1 */
+		regmap_update_bits(rt5651->regmap, RT5651_GPIO_CTRL1,
+				   RT5651_GP1_PIN_MASK, RT5651_GP1_PIN_IRQ);
+
+		switch (rt5651->pdata.jd_src) {
+		case RT5651_JD1_1:
+			regmap_update_bits(rt5651->regmap, RT5651_JD_CTRL2,
+					   RT5651_JD_TRG_SEL_MASK,
+					   RT5651_JD_TRG_SEL_JD1_1);
+			regmap_update_bits(rt5651->regmap, RT5651_IRQ_CTRL1,
+					   RT5651_JD1_1_IRQ_EN,
+					   RT5651_JD1_1_IRQ_EN);
+			break;
+		case RT5651_JD1_2:
+			regmap_update_bits(rt5651->regmap, RT5651_JD_CTRL2,
+					   RT5651_JD_TRG_SEL_MASK,
+					   RT5651_JD_TRG_SEL_JD1_2);
+			regmap_update_bits(rt5651->regmap, RT5651_IRQ_CTRL1,
+					   RT5651_JD1_2_IRQ_EN,
+					   RT5651_JD1_2_IRQ_EN);
+			break;
+		case RT5651_JD2:
+			regmap_update_bits(rt5651->regmap, RT5651_JD_CTRL2,
+					   RT5651_JD_TRG_SEL_MASK,
+					   RT5651_JD_TRG_SEL_JD2);
+			regmap_update_bits(rt5651->regmap, RT5651_IRQ_CTRL1,
+					   RT5651_JD2_IRQ_EN,
+					   RT5651_JD2_IRQ_EN);
+			break;
+		case RT5651_JD_NULL:
+			break;
+		default:
+			dev_warn(&i2c->dev, "Currently only JD1_1 / JD1_2 / JD2 are supported\n");
+			break;
+		}
+	}
+
+	INIT_DELAYED_WORK(&rt5651->jack_detect_work, rt5651_jack_detect_work);
+
+	if (i2c->irq) {
+		ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL,
+						rt5651_irq,
+						IRQF_TRIGGER_RISING |
+						IRQF_TRIGGER_FALLING |
+						IRQF_ONESHOT, "rt5651", rt5651);
+		if (ret) {
+			dev_err(&i2c->dev, "Failed to reguest IRQ: %d\n", ret);
+			return ret;
+		}
+	}
+
 	ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5651,
 				rt5651_dai, ARRAY_SIZE(rt5651_dai));
 
@@ -1787,6 +1948,9 @@ static int rt5651_i2c_probe(struct i2c_client *i2c,
 
 static int rt5651_i2c_remove(struct i2c_client *i2c)
 {
+	struct rt5651_priv *rt5651 = i2c_get_clientdata(i2c);
+
+	cancel_delayed_work_sync(&rt5651->jack_detect_work);
 	snd_soc_unregister_codec(&i2c->dev);
 
 	return 0;
diff --git a/sound/soc/codecs/rt5651.h b/sound/soc/codecs/rt5651.h
index 1bd33cfa6411..4f8b202121d7 100644
--- a/sound/soc/codecs/rt5651.h
+++ b/sound/soc/codecs/rt5651.h
@@ -2062,6 +2062,8 @@ struct rt5651_priv {
 	struct snd_soc_codec *codec;
 	struct rt5651_platform_data pdata;
 	struct regmap *regmap;
+	struct snd_soc_jack *hp_jack;
+	struct delayed_work jack_detect_work;
 
 	int sysclk;
 	int sysclk_src;
@@ -2077,4 +2079,6 @@ struct rt5651_priv {
 	bool hp_mute;
 };
 
+int rt5651_set_jack_detect(struct snd_soc_codec *codec,
+			   struct snd_soc_jack *hp_jack);
 #endif /* __RT5651_H__ */
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 2/5] ASoC: intel: byt: Add headset jack
  2017-10-20 11:18 [PATCH v2 0/5] rt5651: Enable jack detection Carlo Caione
  2017-10-20 11:18 ` [PATCH v2 1/5] ASoC: rt5651: Enable jack detection on JD* pins Carlo Caione
@ 2017-10-20 11:18 ` Carlo Caione
  2017-10-26 14:16     ` Mark Brown
  2017-10-20 11:18 ` [PATCH v2 3/5] ASoC: intel: byt: Enable IN2 map quirk for a KIANO laptop Carlo Caione
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 18+ messages in thread
From: Carlo Caione @ 2017-10-20 11:18 UTC (permalink / raw)
  To: linux, bardliao, oder_chiou, pierre-louis.bossart, broonie,
	alsa-devel, linux-kernel, tiwai, albertchen, edgar_shen
  Cc: Carlo Caione

From: Carlo Caione <carlo@endlessm.com>

Introduce an headset jack in the machine driver and register it to the
codec driver.

Signed-off-by: Carlo Caione <carlo@endlessm.com>
---
 sound/soc/intel/boards/bytcr_rt5651.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c
index 1dad5c98c9ef..5aca55baccda 100644
--- a/sound/soc/intel/boards/bytcr_rt5651.c
+++ b/sound/soc/intel/boards/bytcr_rt5651.c
@@ -47,6 +47,7 @@ enum {
 
 struct byt_rt5651_private {
 	struct clk *mclk;
+	struct snd_soc_jack jack;
 };
 
 static unsigned long byt_rt5651_quirk = BYT_RT5651_DMIC_MAP |
@@ -177,6 +178,17 @@ static const struct snd_kcontrol_new byt_rt5651_controls[] = {
 	SOC_DAPM_PIN_SWITCH("Speaker"),
 };
 
+static struct snd_soc_jack_pin bytcr_jack_pins[] = {
+	{
+		.pin	= "Headphone",
+		.mask	= SND_JACK_HEADPHONE,
+	},
+	{
+		.pin	= "Headset Mic",
+		.mask	= SND_JACK_MICROPHONE,
+	},
+};
+
 static int byt_rt5651_aif1_hw_params(struct snd_pcm_substream *substream,
 					struct snd_pcm_hw_params *params)
 {
@@ -244,6 +256,7 @@ static const struct dmi_system_id byt_rt5651_quirk_table[] = {
 static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime)
 {
 	struct snd_soc_card *card = runtime->card;
+	struct snd_soc_codec *codec = runtime->codec;
 	struct byt_rt5651_private *priv = snd_soc_card_get_drvdata(card);
 	const struct snd_soc_dapm_route *custom_map;
 	int num_routes;
@@ -301,6 +314,16 @@ static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime)
 			dev_err(card->dev, "unable to set MCLK rate\n");
 	}
 
+	ret = snd_soc_card_jack_new(runtime->card, "Headset",
+				    SND_JACK_HEADSET, &priv->jack,
+				    bytcr_jack_pins, ARRAY_SIZE(bytcr_jack_pins));
+	if (ret) {
+		dev_err(runtime->dev, "Headset jack creation failed %d\n", ret);
+		return ret;
+	}
+
+	rt5651_set_jack_detect(codec, &priv->jack);
+
 	return ret;
 }
 
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 3/5] ASoC: intel: byt: Enable IN2 map quirk for a KIANO laptop
  2017-10-20 11:18 [PATCH v2 0/5] rt5651: Enable jack detection Carlo Caione
  2017-10-20 11:18 ` [PATCH v2 1/5] ASoC: rt5651: Enable jack detection on JD* pins Carlo Caione
  2017-10-20 11:18 ` [PATCH v2 2/5] ASoC: intel: byt: Add headset jack Carlo Caione
@ 2017-10-20 11:18 ` Carlo Caione
  2017-10-26 14:16     ` Mark Brown
  2017-10-20 11:18 ` [PATCH v2 4/5] ASoC: rt5651: Rework quirk logic Carlo Caione
  2017-10-20 11:18 ` [PATCH v2 5/5] ASoC: rt5651: Enable JD1_1 quirk for KIANO laptopt Carlo Caione
  4 siblings, 1 reply; 18+ messages in thread
From: Carlo Caione @ 2017-10-20 11:18 UTC (permalink / raw)
  To: linux, bardliao, oder_chiou, pierre-louis.bossart, broonie,
	alsa-devel, linux-kernel, tiwai, albertchen, edgar_shen
  Cc: Carlo Caione

From: Carlo Caione <carlo@endlessm.com>

This cherry-trails laptop has the internal mic connected to the IN2
input pins. Enable the quirk to correctly map the routes.

Signed-off-by: Carlo Caione <carlo@endlessm.com>
---
 sound/soc/intel/boards/bytcr_rt5651.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c
index 5aca55baccda..c7494f88ab81 100644
--- a/sound/soc/intel/boards/bytcr_rt5651.c
+++ b/sound/soc/intel/boards/bytcr_rt5651.c
@@ -250,6 +250,14 @@ static const struct dmi_system_id byt_rt5651_quirk_table[] = {
 		.driver_data = (void *)(BYT_RT5651_DMIC_MAP |
 					BYT_RT5651_DMIC_EN),
 	},
+	{
+		.callback = byt_rt5651_quirk_cb,
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "KIANO"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "KIANO SlimNote 14.2"),
+		},
+		.driver_data = (void *)(BYT_RT5651_IN2_MAP),
+	},
 	{}
 };
 
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 4/5] ASoC: rt5651: Rework quirk logic
  2017-10-20 11:18 [PATCH v2 0/5] rt5651: Enable jack detection Carlo Caione
                   ` (2 preceding siblings ...)
  2017-10-20 11:18 ` [PATCH v2 3/5] ASoC: intel: byt: Enable IN2 map quirk for a KIANO laptop Carlo Caione
@ 2017-10-20 11:18 ` Carlo Caione
  2017-10-26 14:16     ` Mark Brown
  2017-10-20 11:18 ` [PATCH v2 5/5] ASoC: rt5651: Enable JD1_1 quirk for KIANO laptopt Carlo Caione
  4 siblings, 1 reply; 18+ messages in thread
From: Carlo Caione @ 2017-10-20 11:18 UTC (permalink / raw)
  To: linux, bardliao, oder_chiou, pierre-louis.bossart, broonie,
	alsa-devel, linux-kernel, tiwai, albertchen, edgar_shen
  Cc: Carlo Caione

From: Carlo Caione <carlo@endlessm.com>

Rework a bit the quirk logic in the codec driver to simplify the
DMI-based quirk assignment for non-DT platforms.

Signed-off-by: Carlo Caione <carlo@endlessm.com>
---
 sound/soc/codecs/rt5651.c | 39 +++++++++++++++++++++++++++++++++++----
 1 file changed, 35 insertions(+), 4 deletions(-)

diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c
index 91f254391452..f01d41101631 100644
--- a/sound/soc/codecs/rt5651.c
+++ b/sound/soc/codecs/rt5651.c
@@ -19,6 +19,7 @@
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>
 #include <linux/acpi.h>
+#include <linux/dmi.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -31,6 +32,10 @@
 #include "rl6231.h"
 #include "rt5651.h"
 
+#define RT5651_JD_MAP(quirk)	((quirk) & GENMASK(7, 0))
+#define RT5651_IN2_DIFF		BIT(16)
+#define RT5651_DMIC_EN		BIT(17)
+
 #define RT5651_DEVICE_ID_VALUE 0x6281
 
 #define RT5651_PR_RANGE_BASE (0xff + 1)
@@ -38,6 +43,8 @@
 
 #define RT5651_PR_BASE (RT5651_PR_RANGE_BASE + (0 * RT5651_PR_SPACING))
 
+static unsigned long rt5651_quirk;
+
 static const struct regmap_range_cfg rt5651_ranges[] = {
 	{ .name = "PR", .range_min = RT5651_PR_BASE,
 	  .range_max = RT5651_PR_BASE + 0xb4,
@@ -1739,16 +1746,36 @@ static const struct i2c_device_id rt5651_i2c_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, rt5651_i2c_id);
 
+static int rt5651_quirk_cb(const struct dmi_system_id *id)
+{
+	rt5651_quirk = (unsigned long) id->driver_data;
+	return 1;
+}
+
+static const struct dmi_system_id rt5651_quirk_table[] = {
+	{}
+};
+
 static int rt5651_parse_dt(struct rt5651_priv *rt5651, struct device_node *np)
 {
-	rt5651->pdata.in2_diff = of_property_read_bool(np,
-		"realtek,in2-differential");
-	rt5651->pdata.dmic_en = of_property_read_bool(np,
-		"realtek,dmic-en");
+	if (of_property_read_bool(np, "realtek,in2-differential"))
+		rt5651_quirk |= RT5651_IN2_DIFF;
+	if (of_property_read_bool(np, "realtek,dmic-en"))
+		rt5651_quirk |= RT5651_DMIC_EN;
 
 	return 0;
 }
 
+static void rt5651_set_pdata(struct rt5651_priv *rt5651)
+{
+	if (rt5651_quirk & RT5651_IN2_DIFF)
+		rt5651->pdata.in2_diff = true;
+	if (rt5651_quirk & RT5651_DMIC_EN)
+		rt5651->pdata.dmic_en = true;
+	if (RT5651_JD_MAP(rt5651_quirk))
+		rt5651->pdata.jd_src = RT5651_JD_MAP(rt5651_quirk);
+}
+
 static irqreturn_t rt5651_irq(int irq, void *data)
 {
 	struct rt5651_priv *rt5651 = data;
@@ -1854,6 +1881,10 @@ static int rt5651_i2c_probe(struct i2c_client *i2c,
 		rt5651->pdata = *pdata;
 	else if (i2c->dev.of_node)
 		rt5651_parse_dt(rt5651, i2c->dev.of_node);
+	else
+		dmi_check_system(rt5651_quirk_table);
+
+	rt5651_set_pdata(rt5651);
 
 	rt5651->regmap = devm_regmap_init_i2c(i2c, &rt5651_regmap);
 	if (IS_ERR(rt5651->regmap)) {
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 5/5] ASoC: rt5651: Enable JD1_1 quirk for KIANO laptopt
  2017-10-20 11:18 [PATCH v2 0/5] rt5651: Enable jack detection Carlo Caione
                   ` (3 preceding siblings ...)
  2017-10-20 11:18 ` [PATCH v2 4/5] ASoC: rt5651: Rework quirk logic Carlo Caione
@ 2017-10-20 11:18 ` Carlo Caione
  2017-10-26 14:16     ` Mark Brown
  4 siblings, 1 reply; 18+ messages in thread
From: Carlo Caione @ 2017-10-20 11:18 UTC (permalink / raw)
  To: linux, bardliao, oder_chiou, pierre-louis.bossart, broonie,
	alsa-devel, linux-kernel, tiwai, albertchen, edgar_shen
  Cc: Carlo Caione

From: Carlo Caione <carlo@endlessm.com>

The KIANO SlimNote 14.2 laptop uses the JD1_1 input pin for jack
detection. Set the correct quirk in the codec driver.

Signed-off-by: Carlo Caione <carlo@endlessm.com>
---
 sound/soc/codecs/rt5651.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c
index f01d41101631..831b297978a4 100644
--- a/sound/soc/codecs/rt5651.c
+++ b/sound/soc/codecs/rt5651.c
@@ -1753,6 +1753,14 @@ static int rt5651_quirk_cb(const struct dmi_system_id *id)
 }
 
 static const struct dmi_system_id rt5651_quirk_table[] = {
+	{
+		.callback = rt5651_quirk_cb,
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "KIANO"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "KIANO SlimNote 14.2"),
+		},
+		.driver_data = (unsigned long *) RT5651_JD1_1,
+	},
 	{}
 };
 
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Applied "ASoC: intel: byt: Enable IN2 map quirk for a KIANO laptop" to the asoc tree
  2017-10-20 11:18 ` [PATCH v2 3/5] ASoC: intel: byt: Enable IN2 map quirk for a KIANO laptop Carlo Caione
@ 2017-10-26 14:16     ` Mark Brown
  0 siblings, 0 replies; 18+ messages in thread
From: Mark Brown @ 2017-10-26 14:16 UTC (permalink / raw)
  To: Carlo Caione
  Cc: Mark Brown, linux, bardliao, oder_chiou, pierre-louis.bossart,
	broonie, alsa-devel, linux-kernel, tiwai, albertchen, edgar_shen,
	alsa-devel

The patch

   ASoC: intel: byt: Enable IN2 map quirk for a KIANO laptop

has been applied to the asoc tree at

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 2fe30129b0a6a8ddf71c46c8fb4524cb89739bc0 Mon Sep 17 00:00:00 2001
From: Carlo Caione <carlo@endlessm.com>
Date: Fri, 20 Oct 2017 12:18:57 +0100
Subject: [PATCH] ASoC: intel: byt: Enable IN2 map quirk for a KIANO laptop

This cherry-trails laptop has the internal mic connected to the IN2
input pins. Enable the quirk to correctly map the routes.

Signed-off-by: Carlo Caione <carlo@endlessm.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 sound/soc/intel/boards/bytcr_rt5651.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c
index 0df9067e4382..d955836c6870 100644
--- a/sound/soc/intel/boards/bytcr_rt5651.c
+++ b/sound/soc/intel/boards/bytcr_rt5651.c
@@ -250,6 +250,14 @@ static const struct dmi_system_id byt_rt5651_quirk_table[] = {
 		.driver_data = (void *)(BYT_RT5651_DMIC_MAP |
 					BYT_RT5651_DMIC_EN),
 	},
+	{
+		.callback = byt_rt5651_quirk_cb,
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "KIANO"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "KIANO SlimNote 14.2"),
+		},
+		.driver_data = (void *)(BYT_RT5651_IN2_MAP),
+	},
 	{}
 };
 
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Applied "ASoC: intel: byt: Enable IN2 map quirk for a KIANO laptop" to the asoc tree
@ 2017-10-26 14:16     ` Mark Brown
  0 siblings, 0 replies; 18+ messages in thread
From: Mark Brown @ 2017-10-26 14:16 UTC (permalink / raw)
  To: Carlo Caione
  Cc: oder_chiou, alsa-devel, edgar_shen, tiwai, pierre-louis.bossart,
	linux-kernel, albertchen, broonie, bardliao, linux

The patch

   ASoC: intel: byt: Enable IN2 map quirk for a KIANO laptop

has been applied to the asoc tree at

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 2fe30129b0a6a8ddf71c46c8fb4524cb89739bc0 Mon Sep 17 00:00:00 2001
From: Carlo Caione <carlo@endlessm.com>
Date: Fri, 20 Oct 2017 12:18:57 +0100
Subject: [PATCH] ASoC: intel: byt: Enable IN2 map quirk for a KIANO laptop

This cherry-trails laptop has the internal mic connected to the IN2
input pins. Enable the quirk to correctly map the routes.

Signed-off-by: Carlo Caione <carlo@endlessm.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 sound/soc/intel/boards/bytcr_rt5651.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c
index 0df9067e4382..d955836c6870 100644
--- a/sound/soc/intel/boards/bytcr_rt5651.c
+++ b/sound/soc/intel/boards/bytcr_rt5651.c
@@ -250,6 +250,14 @@ static const struct dmi_system_id byt_rt5651_quirk_table[] = {
 		.driver_data = (void *)(BYT_RT5651_DMIC_MAP |
 					BYT_RT5651_DMIC_EN),
 	},
+	{
+		.callback = byt_rt5651_quirk_cb,
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "KIANO"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "KIANO SlimNote 14.2"),
+		},
+		.driver_data = (void *)(BYT_RT5651_IN2_MAP),
+	},
 	{}
 };
 
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Applied "ASoC: intel: byt: Add headset jack" to the asoc tree
  2017-10-20 11:18 ` [PATCH v2 2/5] ASoC: intel: byt: Add headset jack Carlo Caione
@ 2017-10-26 14:16     ` Mark Brown
  0 siblings, 0 replies; 18+ messages in thread
From: Mark Brown @ 2017-10-26 14:16 UTC (permalink / raw)
  To: Carlo Caione
  Cc: Mark Brown, linux, bardliao, oder_chiou, pierre-louis.bossart,
	broonie, alsa-devel, linux-kernel, tiwai, albertchen, edgar_shen,
	alsa-devel

The patch

   ASoC: intel: byt: Add headset jack

has been applied to the asoc tree at

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From d9f8f9b2f3e2b95875cd59ae5c3276e4662e7513 Mon Sep 17 00:00:00 2001
From: Carlo Caione <carlo@endlessm.com>
Date: Fri, 20 Oct 2017 12:18:56 +0100
Subject: [PATCH] ASoC: intel: byt: Add headset jack

Introduce an headset jack in the machine driver and register it to the
codec driver.

Signed-off-by: Carlo Caione <carlo@endlessm.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 sound/soc/intel/boards/bytcr_rt5651.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c
index 51de1bbe8ecd..0df9067e4382 100644
--- a/sound/soc/intel/boards/bytcr_rt5651.c
+++ b/sound/soc/intel/boards/bytcr_rt5651.c
@@ -47,6 +47,7 @@ enum {
 
 struct byt_rt5651_private {
 	struct clk *mclk;
+	struct snd_soc_jack jack;
 };
 
 static unsigned long byt_rt5651_quirk = BYT_RT5651_DMIC_MAP |
@@ -177,6 +178,17 @@ static const struct snd_kcontrol_new byt_rt5651_controls[] = {
 	SOC_DAPM_PIN_SWITCH("Speaker"),
 };
 
+static struct snd_soc_jack_pin bytcr_jack_pins[] = {
+	{
+		.pin	= "Headphone",
+		.mask	= SND_JACK_HEADPHONE,
+	},
+	{
+		.pin	= "Headset Mic",
+		.mask	= SND_JACK_MICROPHONE,
+	},
+};
+
 static int byt_rt5651_aif1_hw_params(struct snd_pcm_substream *substream,
 					struct snd_pcm_hw_params *params)
 {
@@ -244,6 +256,7 @@ static const struct dmi_system_id byt_rt5651_quirk_table[] = {
 static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime)
 {
 	struct snd_soc_card *card = runtime->card;
+	struct snd_soc_codec *codec = runtime->codec;
 	struct byt_rt5651_private *priv = snd_soc_card_get_drvdata(card);
 	const struct snd_soc_dapm_route *custom_map;
 	int num_routes;
@@ -301,6 +314,16 @@ static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime)
 			dev_err(card->dev, "unable to set MCLK rate\n");
 	}
 
+	ret = snd_soc_card_jack_new(runtime->card, "Headset",
+				    SND_JACK_HEADSET, &priv->jack,
+				    bytcr_jack_pins, ARRAY_SIZE(bytcr_jack_pins));
+	if (ret) {
+		dev_err(runtime->dev, "Headset jack creation failed %d\n", ret);
+		return ret;
+	}
+
+	rt5651_set_jack_detect(codec, &priv->jack);
+
 	return ret;
 }
 
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Applied "ASoC: intel: byt: Add headset jack" to the asoc tree
@ 2017-10-26 14:16     ` Mark Brown
  0 siblings, 0 replies; 18+ messages in thread
From: Mark Brown @ 2017-10-26 14:16 UTC (permalink / raw)
  To: Carlo Caione
  Cc: oder_chiou, alsa-devel, edgar_shen, tiwai, pierre-louis.bossart,
	linux-kernel, albertchen, broonie, bardliao, linux

The patch

   ASoC: intel: byt: Add headset jack

has been applied to the asoc tree at

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From d9f8f9b2f3e2b95875cd59ae5c3276e4662e7513 Mon Sep 17 00:00:00 2001
From: Carlo Caione <carlo@endlessm.com>
Date: Fri, 20 Oct 2017 12:18:56 +0100
Subject: [PATCH] ASoC: intel: byt: Add headset jack

Introduce an headset jack in the machine driver and register it to the
codec driver.

Signed-off-by: Carlo Caione <carlo@endlessm.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 sound/soc/intel/boards/bytcr_rt5651.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c
index 51de1bbe8ecd..0df9067e4382 100644
--- a/sound/soc/intel/boards/bytcr_rt5651.c
+++ b/sound/soc/intel/boards/bytcr_rt5651.c
@@ -47,6 +47,7 @@ enum {
 
 struct byt_rt5651_private {
 	struct clk *mclk;
+	struct snd_soc_jack jack;
 };
 
 static unsigned long byt_rt5651_quirk = BYT_RT5651_DMIC_MAP |
@@ -177,6 +178,17 @@ static const struct snd_kcontrol_new byt_rt5651_controls[] = {
 	SOC_DAPM_PIN_SWITCH("Speaker"),
 };
 
+static struct snd_soc_jack_pin bytcr_jack_pins[] = {
+	{
+		.pin	= "Headphone",
+		.mask	= SND_JACK_HEADPHONE,
+	},
+	{
+		.pin	= "Headset Mic",
+		.mask	= SND_JACK_MICROPHONE,
+	},
+};
+
 static int byt_rt5651_aif1_hw_params(struct snd_pcm_substream *substream,
 					struct snd_pcm_hw_params *params)
 {
@@ -244,6 +256,7 @@ static const struct dmi_system_id byt_rt5651_quirk_table[] = {
 static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime)
 {
 	struct snd_soc_card *card = runtime->card;
+	struct snd_soc_codec *codec = runtime->codec;
 	struct byt_rt5651_private *priv = snd_soc_card_get_drvdata(card);
 	const struct snd_soc_dapm_route *custom_map;
 	int num_routes;
@@ -301,6 +314,16 @@ static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime)
 			dev_err(card->dev, "unable to set MCLK rate\n");
 	}
 
+	ret = snd_soc_card_jack_new(runtime->card, "Headset",
+				    SND_JACK_HEADSET, &priv->jack,
+				    bytcr_jack_pins, ARRAY_SIZE(bytcr_jack_pins));
+	if (ret) {
+		dev_err(runtime->dev, "Headset jack creation failed %d\n", ret);
+		return ret;
+	}
+
+	rt5651_set_jack_detect(codec, &priv->jack);
+
 	return ret;
 }
 
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Applied "ASoC: rt5651: Enable JD1_1 quirk for KIANO laptopt" to the asoc tree
  2017-10-20 11:18 ` [PATCH v2 5/5] ASoC: rt5651: Enable JD1_1 quirk for KIANO laptopt Carlo Caione
@ 2017-10-26 14:16     ` Mark Brown
  0 siblings, 0 replies; 18+ messages in thread
From: Mark Brown @ 2017-10-26 14:16 UTC (permalink / raw)
  To: Carlo Caione
  Cc: Mark Brown, linux, bardliao, oder_chiou, pierre-louis.bossart,
	broonie, alsa-devel, linux-kernel, tiwai, albertchen, edgar_shen,
	alsa-devel

The patch

   ASoC: rt5651: Enable JD1_1 quirk for KIANO laptopt

has been applied to the asoc tree at

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From f85353fdd49fe0087438ef7d7475a832d16276c4 Mon Sep 17 00:00:00 2001
From: Carlo Caione <carlo@endlessm.com>
Date: Fri, 20 Oct 2017 12:18:59 +0100
Subject: [PATCH] ASoC: rt5651: Enable JD1_1 quirk for KIANO laptopt

The KIANO SlimNote 14.2 laptop uses the JD1_1 input pin for jack
detection. Set the correct quirk in the codec driver.

Signed-off-by: Carlo Caione <carlo@endlessm.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 sound/soc/codecs/rt5651.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c
index f01d41101631..831b297978a4 100644
--- a/sound/soc/codecs/rt5651.c
+++ b/sound/soc/codecs/rt5651.c
@@ -1753,6 +1753,14 @@ static int rt5651_quirk_cb(const struct dmi_system_id *id)
 }
 
 static const struct dmi_system_id rt5651_quirk_table[] = {
+	{
+		.callback = rt5651_quirk_cb,
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "KIANO"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "KIANO SlimNote 14.2"),
+		},
+		.driver_data = (unsigned long *) RT5651_JD1_1,
+	},
 	{}
 };
 
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Applied "ASoC: rt5651: Enable JD1_1 quirk for KIANO laptopt" to the asoc tree
@ 2017-10-26 14:16     ` Mark Brown
  0 siblings, 0 replies; 18+ messages in thread
From: Mark Brown @ 2017-10-26 14:16 UTC (permalink / raw)
  To: Carlo Caione
  Cc: Mark Brown, linux, bardliao, oder_chiou, pierre-louis.bossart

The patch

   ASoC: rt5651: Enable JD1_1 quirk for KIANO laptopt

has been applied to the asoc tree at

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From f85353fdd49fe0087438ef7d7475a832d16276c4 Mon Sep 17 00:00:00 2001
From: Carlo Caione <carlo@endlessm.com>
Date: Fri, 20 Oct 2017 12:18:59 +0100
Subject: [PATCH] ASoC: rt5651: Enable JD1_1 quirk for KIANO laptopt

The KIANO SlimNote 14.2 laptop uses the JD1_1 input pin for jack
detection. Set the correct quirk in the codec driver.

Signed-off-by: Carlo Caione <carlo@endlessm.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 sound/soc/codecs/rt5651.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c
index f01d41101631..831b297978a4 100644
--- a/sound/soc/codecs/rt5651.c
+++ b/sound/soc/codecs/rt5651.c
@@ -1753,6 +1753,14 @@ static int rt5651_quirk_cb(const struct dmi_system_id *id)
 }
 
 static const struct dmi_system_id rt5651_quirk_table[] = {
+	{
+		.callback = rt5651_quirk_cb,
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "KIANO"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "KIANO SlimNote 14.2"),
+		},
+		.driver_data = (unsigned long *) RT5651_JD1_1,
+	},
 	{}
 };
 
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Applied "ASoC: rt5651: Rework quirk logic" to the asoc tree
  2017-10-20 11:18 ` [PATCH v2 4/5] ASoC: rt5651: Rework quirk logic Carlo Caione
@ 2017-10-26 14:16     ` Mark Brown
  0 siblings, 0 replies; 18+ messages in thread
From: Mark Brown @ 2017-10-26 14:16 UTC (permalink / raw)
  To: Carlo Caione
  Cc: Mark Brown, linux, bardliao, oder_chiou, pierre-louis.bossart,
	broonie, alsa-devel, linux-kernel, tiwai, albertchen, edgar_shen,
	alsa-devel

The patch

   ASoC: rt5651: Rework quirk logic

has been applied to the asoc tree at

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From b4435130bc19cd54631588355b16326aeb760e34 Mon Sep 17 00:00:00 2001
From: Carlo Caione <carlo@endlessm.com>
Date: Fri, 20 Oct 2017 12:18:58 +0100
Subject: [PATCH] ASoC: rt5651: Rework quirk logic

Rework a bit the quirk logic in the codec driver to simplify the
DMI-based quirk assignment for non-DT platforms.

Signed-off-by: Carlo Caione <carlo@endlessm.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 sound/soc/codecs/rt5651.c | 39 +++++++++++++++++++++++++++++++++++----
 1 file changed, 35 insertions(+), 4 deletions(-)

diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c
index 91f254391452..f01d41101631 100644
--- a/sound/soc/codecs/rt5651.c
+++ b/sound/soc/codecs/rt5651.c
@@ -19,6 +19,7 @@
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>
 #include <linux/acpi.h>
+#include <linux/dmi.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -31,6 +32,10 @@
 #include "rl6231.h"
 #include "rt5651.h"
 
+#define RT5651_JD_MAP(quirk)	((quirk) & GENMASK(7, 0))
+#define RT5651_IN2_DIFF		BIT(16)
+#define RT5651_DMIC_EN		BIT(17)
+
 #define RT5651_DEVICE_ID_VALUE 0x6281
 
 #define RT5651_PR_RANGE_BASE (0xff + 1)
@@ -38,6 +43,8 @@
 
 #define RT5651_PR_BASE (RT5651_PR_RANGE_BASE + (0 * RT5651_PR_SPACING))
 
+static unsigned long rt5651_quirk;
+
 static const struct regmap_range_cfg rt5651_ranges[] = {
 	{ .name = "PR", .range_min = RT5651_PR_BASE,
 	  .range_max = RT5651_PR_BASE + 0xb4,
@@ -1739,16 +1746,36 @@ static const struct i2c_device_id rt5651_i2c_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, rt5651_i2c_id);
 
+static int rt5651_quirk_cb(const struct dmi_system_id *id)
+{
+	rt5651_quirk = (unsigned long) id->driver_data;
+	return 1;
+}
+
+static const struct dmi_system_id rt5651_quirk_table[] = {
+	{}
+};
+
 static int rt5651_parse_dt(struct rt5651_priv *rt5651, struct device_node *np)
 {
-	rt5651->pdata.in2_diff = of_property_read_bool(np,
-		"realtek,in2-differential");
-	rt5651->pdata.dmic_en = of_property_read_bool(np,
-		"realtek,dmic-en");
+	if (of_property_read_bool(np, "realtek,in2-differential"))
+		rt5651_quirk |= RT5651_IN2_DIFF;
+	if (of_property_read_bool(np, "realtek,dmic-en"))
+		rt5651_quirk |= RT5651_DMIC_EN;
 
 	return 0;
 }
 
+static void rt5651_set_pdata(struct rt5651_priv *rt5651)
+{
+	if (rt5651_quirk & RT5651_IN2_DIFF)
+		rt5651->pdata.in2_diff = true;
+	if (rt5651_quirk & RT5651_DMIC_EN)
+		rt5651->pdata.dmic_en = true;
+	if (RT5651_JD_MAP(rt5651_quirk))
+		rt5651->pdata.jd_src = RT5651_JD_MAP(rt5651_quirk);
+}
+
 static irqreturn_t rt5651_irq(int irq, void *data)
 {
 	struct rt5651_priv *rt5651 = data;
@@ -1854,6 +1881,10 @@ static int rt5651_i2c_probe(struct i2c_client *i2c,
 		rt5651->pdata = *pdata;
 	else if (i2c->dev.of_node)
 		rt5651_parse_dt(rt5651, i2c->dev.of_node);
+	else
+		dmi_check_system(rt5651_quirk_table);
+
+	rt5651_set_pdata(rt5651);
 
 	rt5651->regmap = devm_regmap_init_i2c(i2c, &rt5651_regmap);
 	if (IS_ERR(rt5651->regmap)) {
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Applied "ASoC: rt5651: Rework quirk logic" to the asoc tree
@ 2017-10-26 14:16     ` Mark Brown
  0 siblings, 0 replies; 18+ messages in thread
From: Mark Brown @ 2017-10-26 14:16 UTC (permalink / raw)
  To: Carlo Caione
  Cc: Mark Brown, linux, bardliao, oder_chiou, pierre-louis.bossart

The patch

   ASoC: rt5651: Rework quirk logic

has been applied to the asoc tree at

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From b4435130bc19cd54631588355b16326aeb760e34 Mon Sep 17 00:00:00 2001
From: Carlo Caione <carlo@endlessm.com>
Date: Fri, 20 Oct 2017 12:18:58 +0100
Subject: [PATCH] ASoC: rt5651: Rework quirk logic

Rework a bit the quirk logic in the codec driver to simplify the
DMI-based quirk assignment for non-DT platforms.

Signed-off-by: Carlo Caione <carlo@endlessm.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 sound/soc/codecs/rt5651.c | 39 +++++++++++++++++++++++++++++++++++----
 1 file changed, 35 insertions(+), 4 deletions(-)

diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c
index 91f254391452..f01d41101631 100644
--- a/sound/soc/codecs/rt5651.c
+++ b/sound/soc/codecs/rt5651.c
@@ -19,6 +19,7 @@
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>
 #include <linux/acpi.h>
+#include <linux/dmi.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -31,6 +32,10 @@
 #include "rl6231.h"
 #include "rt5651.h"
 
+#define RT5651_JD_MAP(quirk)	((quirk) & GENMASK(7, 0))
+#define RT5651_IN2_DIFF		BIT(16)
+#define RT5651_DMIC_EN		BIT(17)
+
 #define RT5651_DEVICE_ID_VALUE 0x6281
 
 #define RT5651_PR_RANGE_BASE (0xff + 1)
@@ -38,6 +43,8 @@
 
 #define RT5651_PR_BASE (RT5651_PR_RANGE_BASE + (0 * RT5651_PR_SPACING))
 
+static unsigned long rt5651_quirk;
+
 static const struct regmap_range_cfg rt5651_ranges[] = {
 	{ .name = "PR", .range_min = RT5651_PR_BASE,
 	  .range_max = RT5651_PR_BASE + 0xb4,
@@ -1739,16 +1746,36 @@ static const struct i2c_device_id rt5651_i2c_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, rt5651_i2c_id);
 
+static int rt5651_quirk_cb(const struct dmi_system_id *id)
+{
+	rt5651_quirk = (unsigned long) id->driver_data;
+	return 1;
+}
+
+static const struct dmi_system_id rt5651_quirk_table[] = {
+	{}
+};
+
 static int rt5651_parse_dt(struct rt5651_priv *rt5651, struct device_node *np)
 {
-	rt5651->pdata.in2_diff = of_property_read_bool(np,
-		"realtek,in2-differential");
-	rt5651->pdata.dmic_en = of_property_read_bool(np,
-		"realtek,dmic-en");
+	if (of_property_read_bool(np, "realtek,in2-differential"))
+		rt5651_quirk |= RT5651_IN2_DIFF;
+	if (of_property_read_bool(np, "realtek,dmic-en"))
+		rt5651_quirk |= RT5651_DMIC_EN;
 
 	return 0;
 }
 
+static void rt5651_set_pdata(struct rt5651_priv *rt5651)
+{
+	if (rt5651_quirk & RT5651_IN2_DIFF)
+		rt5651->pdata.in2_diff = true;
+	if (rt5651_quirk & RT5651_DMIC_EN)
+		rt5651->pdata.dmic_en = true;
+	if (RT5651_JD_MAP(rt5651_quirk))
+		rt5651->pdata.jd_src = RT5651_JD_MAP(rt5651_quirk);
+}
+
 static irqreturn_t rt5651_irq(int irq, void *data)
 {
 	struct rt5651_priv *rt5651 = data;
@@ -1854,6 +1881,10 @@ static int rt5651_i2c_probe(struct i2c_client *i2c,
 		rt5651->pdata = *pdata;
 	else if (i2c->dev.of_node)
 		rt5651_parse_dt(rt5651, i2c->dev.of_node);
+	else
+		dmi_check_system(rt5651_quirk_table);
+
+	rt5651_set_pdata(rt5651);
 
 	rt5651->regmap = devm_regmap_init_i2c(i2c, &rt5651_regmap);
 	if (IS_ERR(rt5651->regmap)) {
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Applied "ASoC: rt5651: Enable jack detection on JD* pins" to the asoc tree
  2017-10-20 11:18 ` [PATCH v2 1/5] ASoC: rt5651: Enable jack detection on JD* pins Carlo Caione
@ 2017-10-26 14:17     ` Mark Brown
  2017-10-26 14:17     ` Mark Brown
  1 sibling, 0 replies; 18+ messages in thread
From: Mark Brown @ 2017-10-26 14:17 UTC (permalink / raw)
  To: Carlo Caione
  Cc: Mark Brown, linux, bardliao, oder_chiou, pierre-louis.bossart,
	broonie, alsa-devel, linux-kernel, tiwai, albertchen, edgar_shen,
	alsa-devel

The patch

   ASoC: rt5651: Enable jack detection on JD* pins

has been applied to the asoc tree at

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 80bbe4a30bc6b119df86c280c91cde2034309bf1 Mon Sep 17 00:00:00 2001
From: Carlo Caione <carlo@endlessm.com>
Date: Fri, 20 Oct 2017 12:18:55 +0100
Subject: [PATCH] ASoC: rt5651: Enable jack detection on JD* pins

Enable jack detection for the RT5651 codec on the JD* pins.

Signed-off-by: Carlo Caione <carlo@endlessm.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 include/sound/rt5651.h    |   8 +++
 sound/soc/codecs/rt5651.c | 168 +++++++++++++++++++++++++++++++++++++++++++++-
 sound/soc/codecs/rt5651.h |   4 ++
 3 files changed, 178 insertions(+), 2 deletions(-)

diff --git a/include/sound/rt5651.h b/include/sound/rt5651.h
index d35de758dfb5..18b79a761f10 100644
--- a/include/sound/rt5651.h
+++ b/include/sound/rt5651.h
@@ -11,11 +11,19 @@
 #ifndef __LINUX_SND_RT5651_H
 #define __LINUX_SND_RT5651_H
 
+enum rt5651_jd_src {
+	RT5651_JD_NULL,
+	RT5651_JD1_1,
+	RT5651_JD1_2,
+	RT5651_JD2,
+};
+
 struct rt5651_platform_data {
 	/* IN2 can optionally be differential */
 	bool in2_diff;
 
 	bool dmic_en;
+	enum rt5651_jd_src jd_src;
 };
 
 #endif
diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c
index 28f7210cec91..91f254391452 100644
--- a/sound/soc/codecs/rt5651.c
+++ b/sound/soc/codecs/rt5651.c
@@ -26,6 +26,7 @@
 #include <sound/soc-dapm.h>
 #include <sound/initval.h>
 #include <sound/tlv.h>
+#include <sound/jack.h>
 
 #include "rl6231.h"
 #include "rt5651.h"
@@ -880,6 +881,9 @@ static const struct snd_soc_dapm_widget rt5651_dapm_widgets[] = {
 	SND_SOC_DAPM_SUPPLY("PLL1", RT5651_PWR_ANLG2,
 			RT5651_PWR_PLL_BIT, 0, NULL, 0),
 	/* Input Side */
+	SND_SOC_DAPM_SUPPLY("JD Power", RT5651_PWR_ANLG2,
+		RT5651_PWM_JD_M_BIT, 0, NULL, 0),
+
 	/* micbias */
 	SND_SOC_DAPM_SUPPLY("LDO", RT5651_PWR_ANLG1,
 			RT5651_PWR_LDO_BIT, 0, NULL, 0),
@@ -1528,6 +1532,8 @@ static int rt5651_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
 static int rt5651_set_bias_level(struct snd_soc_codec *codec,
 			enum snd_soc_bias_level level)
 {
+	struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
+
 	switch (level) {
 	case SND_SOC_BIAS_PREPARE:
 		if (SND_SOC_BIAS_STANDBY == snd_soc_codec_get_bias_level(codec)) {
@@ -1556,8 +1562,13 @@ static int rt5651_set_bias_level(struct snd_soc_codec *codec,
 		snd_soc_write(codec, RT5651_PWR_DIG2, 0x0000);
 		snd_soc_write(codec, RT5651_PWR_VOL, 0x0000);
 		snd_soc_write(codec, RT5651_PWR_MIXER, 0x0000);
-		snd_soc_write(codec, RT5651_PWR_ANLG1, 0x0000);
-		snd_soc_write(codec, RT5651_PWR_ANLG2, 0x0000);
+		if (rt5651->pdata.jd_src) {
+			snd_soc_write(codec, RT5651_PWR_ANLG2, 0x0204);
+			snd_soc_write(codec, RT5651_PWR_ANLG1, 0x0002);
+		} else {
+			snd_soc_write(codec, RT5651_PWR_ANLG1, 0x0000);
+			snd_soc_write(codec, RT5651_PWR_ANLG2, 0x0000);
+		}
 		break;
 
 	default:
@@ -1570,6 +1581,7 @@ static int rt5651_set_bias_level(struct snd_soc_codec *codec,
 static int rt5651_probe(struct snd_soc_codec *codec)
 {
 	struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
+	struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
 
 	rt5651->codec = codec;
 
@@ -1585,6 +1597,15 @@ static int rt5651_probe(struct snd_soc_codec *codec)
 
 	snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_OFF);
 
+	if (rt5651->pdata.jd_src) {
+		snd_soc_dapm_force_enable_pin(dapm, "JD Power");
+		snd_soc_dapm_force_enable_pin(dapm, "LDO");
+		snd_soc_dapm_sync(dapm);
+
+		regmap_update_bits(rt5651->regmap, RT5651_MICBIAS,
+				   0x38, 0x38);
+	}
+
 	return 0;
 }
 
@@ -1728,6 +1749,93 @@ static int rt5651_parse_dt(struct rt5651_priv *rt5651, struct device_node *np)
 	return 0;
 }
 
+static irqreturn_t rt5651_irq(int irq, void *data)
+{
+	struct rt5651_priv *rt5651 = data;
+
+	queue_delayed_work(system_power_efficient_wq,
+			   &rt5651->jack_detect_work, msecs_to_jiffies(250));
+
+	return IRQ_HANDLED;
+}
+
+static int rt5651_jack_detect(struct snd_soc_codec *codec, int jack_insert)
+{
+	struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
+	int jack_type;
+
+	if (jack_insert) {
+		snd_soc_dapm_force_enable_pin(dapm, "LDO");
+		snd_soc_dapm_sync(dapm);
+
+		snd_soc_update_bits(codec, RT5651_MICBIAS,
+				    RT5651_MIC1_OVCD_MASK |
+				    RT5651_MIC1_OVTH_MASK |
+				    RT5651_PWR_CLK12M_MASK |
+				    RT5651_PWR_MB_MASK,
+				    RT5651_MIC1_OVCD_EN |
+				    RT5651_MIC1_OVTH_600UA |
+				    RT5651_PWR_MB_PU |
+				    RT5651_PWR_CLK12M_PU);
+		msleep(100);
+		if (snd_soc_read(codec, RT5651_IRQ_CTRL2) & RT5651_MB1_OC_CLR)
+			jack_type = SND_JACK_HEADPHONE;
+		else
+			jack_type = SND_JACK_HEADSET;
+		snd_soc_update_bits(codec, RT5651_IRQ_CTRL2,
+				    RT5651_MB1_OC_CLR, 0);
+	} else { /* jack out */
+		jack_type = 0;
+
+		snd_soc_update_bits(codec, RT5651_MICBIAS,
+				    RT5651_MIC1_OVCD_MASK,
+				    RT5651_MIC1_OVCD_DIS);
+	}
+
+	return jack_type;
+}
+
+static void rt5651_jack_detect_work(struct work_struct *work)
+{
+	struct rt5651_priv *rt5651 =
+		container_of(work, struct rt5651_priv, jack_detect_work.work);
+
+	int report, val = 0;
+
+	if (!rt5651->codec)
+		return;
+
+	switch (rt5651->pdata.jd_src) {
+	case RT5651_JD1_1:
+		val = snd_soc_read(rt5651->codec, RT5651_INT_IRQ_ST) & 0x1000;
+		break;
+	case RT5651_JD1_2:
+		val = snd_soc_read(rt5651->codec, RT5651_INT_IRQ_ST) & 0x2000;
+		break;
+	case RT5651_JD2:
+		val = snd_soc_read(rt5651->codec, RT5651_INT_IRQ_ST) & 0x4000;
+		break;
+	default:
+		break;
+	}
+
+	report = rt5651_jack_detect(rt5651->codec, !val);
+
+	snd_soc_jack_report(rt5651->hp_jack, report, SND_JACK_HEADSET);
+}
+
+int rt5651_set_jack_detect(struct snd_soc_codec *codec,
+			   struct snd_soc_jack *hp_jack)
+{
+	struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
+
+	rt5651->hp_jack = hp_jack;
+	rt5651_irq(0, rt5651);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rt5651_set_jack_detect);
+
 static int rt5651_i2c_probe(struct i2c_client *i2c,
 		    const struct i2c_device_id *id)
 {
@@ -1779,6 +1887,59 @@ static int rt5651_i2c_probe(struct i2c_client *i2c,
 
 	rt5651->hp_mute = 1;
 
+	if (rt5651->pdata.jd_src) {
+
+		/* IRQ output on GPIO1 */
+		regmap_update_bits(rt5651->regmap, RT5651_GPIO_CTRL1,
+				   RT5651_GP1_PIN_MASK, RT5651_GP1_PIN_IRQ);
+
+		switch (rt5651->pdata.jd_src) {
+		case RT5651_JD1_1:
+			regmap_update_bits(rt5651->regmap, RT5651_JD_CTRL2,
+					   RT5651_JD_TRG_SEL_MASK,
+					   RT5651_JD_TRG_SEL_JD1_1);
+			regmap_update_bits(rt5651->regmap, RT5651_IRQ_CTRL1,
+					   RT5651_JD1_1_IRQ_EN,
+					   RT5651_JD1_1_IRQ_EN);
+			break;
+		case RT5651_JD1_2:
+			regmap_update_bits(rt5651->regmap, RT5651_JD_CTRL2,
+					   RT5651_JD_TRG_SEL_MASK,
+					   RT5651_JD_TRG_SEL_JD1_2);
+			regmap_update_bits(rt5651->regmap, RT5651_IRQ_CTRL1,
+					   RT5651_JD1_2_IRQ_EN,
+					   RT5651_JD1_2_IRQ_EN);
+			break;
+		case RT5651_JD2:
+			regmap_update_bits(rt5651->regmap, RT5651_JD_CTRL2,
+					   RT5651_JD_TRG_SEL_MASK,
+					   RT5651_JD_TRG_SEL_JD2);
+			regmap_update_bits(rt5651->regmap, RT5651_IRQ_CTRL1,
+					   RT5651_JD2_IRQ_EN,
+					   RT5651_JD2_IRQ_EN);
+			break;
+		case RT5651_JD_NULL:
+			break;
+		default:
+			dev_warn(&i2c->dev, "Currently only JD1_1 / JD1_2 / JD2 are supported\n");
+			break;
+		}
+	}
+
+	INIT_DELAYED_WORK(&rt5651->jack_detect_work, rt5651_jack_detect_work);
+
+	if (i2c->irq) {
+		ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL,
+						rt5651_irq,
+						IRQF_TRIGGER_RISING |
+						IRQF_TRIGGER_FALLING |
+						IRQF_ONESHOT, "rt5651", rt5651);
+		if (ret) {
+			dev_err(&i2c->dev, "Failed to reguest IRQ: %d\n", ret);
+			return ret;
+		}
+	}
+
 	ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5651,
 				rt5651_dai, ARRAY_SIZE(rt5651_dai));
 
@@ -1787,6 +1948,9 @@ static int rt5651_i2c_probe(struct i2c_client *i2c,
 
 static int rt5651_i2c_remove(struct i2c_client *i2c)
 {
+	struct rt5651_priv *rt5651 = i2c_get_clientdata(i2c);
+
+	cancel_delayed_work_sync(&rt5651->jack_detect_work);
 	snd_soc_unregister_codec(&i2c->dev);
 
 	return 0;
diff --git a/sound/soc/codecs/rt5651.h b/sound/soc/codecs/rt5651.h
index 1bd33cfa6411..4f8b202121d7 100644
--- a/sound/soc/codecs/rt5651.h
+++ b/sound/soc/codecs/rt5651.h
@@ -2062,6 +2062,8 @@ struct rt5651_priv {
 	struct snd_soc_codec *codec;
 	struct rt5651_platform_data pdata;
 	struct regmap *regmap;
+	struct snd_soc_jack *hp_jack;
+	struct delayed_work jack_detect_work;
 
 	int sysclk;
 	int sysclk_src;
@@ -2077,4 +2079,6 @@ struct rt5651_priv {
 	bool hp_mute;
 };
 
+int rt5651_set_jack_detect(struct snd_soc_codec *codec,
+			   struct snd_soc_jack *hp_jack);
 #endif /* __RT5651_H__ */
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Applied "ASoC: rt5651: Enable jack detection on JD* pins" to the asoc tree
@ 2017-10-26 14:17     ` Mark Brown
  0 siblings, 0 replies; 18+ messages in thread
From: Mark Brown @ 2017-10-26 14:17 UTC (permalink / raw)
  To: Carlo Caione
  Cc: Mark Brown, linux, bardliao, oder_chiou, pierre-louis.bossart

The patch

   ASoC: rt5651: Enable jack detection on JD* pins

has been applied to the asoc tree at

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 80bbe4a30bc6b119df86c280c91cde2034309bf1 Mon Sep 17 00:00:00 2001
From: Carlo Caione <carlo@endlessm.com>
Date: Fri, 20 Oct 2017 12:18:55 +0100
Subject: [PATCH] ASoC: rt5651: Enable jack detection on JD* pins

Enable jack detection for the RT5651 codec on the JD* pins.

Signed-off-by: Carlo Caione <carlo@endlessm.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 include/sound/rt5651.h    |   8 +++
 sound/soc/codecs/rt5651.c | 168 +++++++++++++++++++++++++++++++++++++++++++++-
 sound/soc/codecs/rt5651.h |   4 ++
 3 files changed, 178 insertions(+), 2 deletions(-)

diff --git a/include/sound/rt5651.h b/include/sound/rt5651.h
index d35de758dfb5..18b79a761f10 100644
--- a/include/sound/rt5651.h
+++ b/include/sound/rt5651.h
@@ -11,11 +11,19 @@
 #ifndef __LINUX_SND_RT5651_H
 #define __LINUX_SND_RT5651_H
 
+enum rt5651_jd_src {
+	RT5651_JD_NULL,
+	RT5651_JD1_1,
+	RT5651_JD1_2,
+	RT5651_JD2,
+};
+
 struct rt5651_platform_data {
 	/* IN2 can optionally be differential */
 	bool in2_diff;
 
 	bool dmic_en;
+	enum rt5651_jd_src jd_src;
 };
 
 #endif
diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c
index 28f7210cec91..91f254391452 100644
--- a/sound/soc/codecs/rt5651.c
+++ b/sound/soc/codecs/rt5651.c
@@ -26,6 +26,7 @@
 #include <sound/soc-dapm.h>
 #include <sound/initval.h>
 #include <sound/tlv.h>
+#include <sound/jack.h>
 
 #include "rl6231.h"
 #include "rt5651.h"
@@ -880,6 +881,9 @@ static const struct snd_soc_dapm_widget rt5651_dapm_widgets[] = {
 	SND_SOC_DAPM_SUPPLY("PLL1", RT5651_PWR_ANLG2,
 			RT5651_PWR_PLL_BIT, 0, NULL, 0),
 	/* Input Side */
+	SND_SOC_DAPM_SUPPLY("JD Power", RT5651_PWR_ANLG2,
+		RT5651_PWM_JD_M_BIT, 0, NULL, 0),
+
 	/* micbias */
 	SND_SOC_DAPM_SUPPLY("LDO", RT5651_PWR_ANLG1,
 			RT5651_PWR_LDO_BIT, 0, NULL, 0),
@@ -1528,6 +1532,8 @@ static int rt5651_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
 static int rt5651_set_bias_level(struct snd_soc_codec *codec,
 			enum snd_soc_bias_level level)
 {
+	struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
+
 	switch (level) {
 	case SND_SOC_BIAS_PREPARE:
 		if (SND_SOC_BIAS_STANDBY == snd_soc_codec_get_bias_level(codec)) {
@@ -1556,8 +1562,13 @@ static int rt5651_set_bias_level(struct snd_soc_codec *codec,
 		snd_soc_write(codec, RT5651_PWR_DIG2, 0x0000);
 		snd_soc_write(codec, RT5651_PWR_VOL, 0x0000);
 		snd_soc_write(codec, RT5651_PWR_MIXER, 0x0000);
-		snd_soc_write(codec, RT5651_PWR_ANLG1, 0x0000);
-		snd_soc_write(codec, RT5651_PWR_ANLG2, 0x0000);
+		if (rt5651->pdata.jd_src) {
+			snd_soc_write(codec, RT5651_PWR_ANLG2, 0x0204);
+			snd_soc_write(codec, RT5651_PWR_ANLG1, 0x0002);
+		} else {
+			snd_soc_write(codec, RT5651_PWR_ANLG1, 0x0000);
+			snd_soc_write(codec, RT5651_PWR_ANLG2, 0x0000);
+		}
 		break;
 
 	default:
@@ -1570,6 +1581,7 @@ static int rt5651_set_bias_level(struct snd_soc_codec *codec,
 static int rt5651_probe(struct snd_soc_codec *codec)
 {
 	struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
+	struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
 
 	rt5651->codec = codec;
 
@@ -1585,6 +1597,15 @@ static int rt5651_probe(struct snd_soc_codec *codec)
 
 	snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_OFF);
 
+	if (rt5651->pdata.jd_src) {
+		snd_soc_dapm_force_enable_pin(dapm, "JD Power");
+		snd_soc_dapm_force_enable_pin(dapm, "LDO");
+		snd_soc_dapm_sync(dapm);
+
+		regmap_update_bits(rt5651->regmap, RT5651_MICBIAS,
+				   0x38, 0x38);
+	}
+
 	return 0;
 }
 
@@ -1728,6 +1749,93 @@ static int rt5651_parse_dt(struct rt5651_priv *rt5651, struct device_node *np)
 	return 0;
 }
 
+static irqreturn_t rt5651_irq(int irq, void *data)
+{
+	struct rt5651_priv *rt5651 = data;
+
+	queue_delayed_work(system_power_efficient_wq,
+			   &rt5651->jack_detect_work, msecs_to_jiffies(250));
+
+	return IRQ_HANDLED;
+}
+
+static int rt5651_jack_detect(struct snd_soc_codec *codec, int jack_insert)
+{
+	struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
+	int jack_type;
+
+	if (jack_insert) {
+		snd_soc_dapm_force_enable_pin(dapm, "LDO");
+		snd_soc_dapm_sync(dapm);
+
+		snd_soc_update_bits(codec, RT5651_MICBIAS,
+				    RT5651_MIC1_OVCD_MASK |
+				    RT5651_MIC1_OVTH_MASK |
+				    RT5651_PWR_CLK12M_MASK |
+				    RT5651_PWR_MB_MASK,
+				    RT5651_MIC1_OVCD_EN |
+				    RT5651_MIC1_OVTH_600UA |
+				    RT5651_PWR_MB_PU |
+				    RT5651_PWR_CLK12M_PU);
+		msleep(100);
+		if (snd_soc_read(codec, RT5651_IRQ_CTRL2) & RT5651_MB1_OC_CLR)
+			jack_type = SND_JACK_HEADPHONE;
+		else
+			jack_type = SND_JACK_HEADSET;
+		snd_soc_update_bits(codec, RT5651_IRQ_CTRL2,
+				    RT5651_MB1_OC_CLR, 0);
+	} else { /* jack out */
+		jack_type = 0;
+
+		snd_soc_update_bits(codec, RT5651_MICBIAS,
+				    RT5651_MIC1_OVCD_MASK,
+				    RT5651_MIC1_OVCD_DIS);
+	}
+
+	return jack_type;
+}
+
+static void rt5651_jack_detect_work(struct work_struct *work)
+{
+	struct rt5651_priv *rt5651 =
+		container_of(work, struct rt5651_priv, jack_detect_work.work);
+
+	int report, val = 0;
+
+	if (!rt5651->codec)
+		return;
+
+	switch (rt5651->pdata.jd_src) {
+	case RT5651_JD1_1:
+		val = snd_soc_read(rt5651->codec, RT5651_INT_IRQ_ST) & 0x1000;
+		break;
+	case RT5651_JD1_2:
+		val = snd_soc_read(rt5651->codec, RT5651_INT_IRQ_ST) & 0x2000;
+		break;
+	case RT5651_JD2:
+		val = snd_soc_read(rt5651->codec, RT5651_INT_IRQ_ST) & 0x4000;
+		break;
+	default:
+		break;
+	}
+
+	report = rt5651_jack_detect(rt5651->codec, !val);
+
+	snd_soc_jack_report(rt5651->hp_jack, report, SND_JACK_HEADSET);
+}
+
+int rt5651_set_jack_detect(struct snd_soc_codec *codec,
+			   struct snd_soc_jack *hp_jack)
+{
+	struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
+
+	rt5651->hp_jack = hp_jack;
+	rt5651_irq(0, rt5651);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rt5651_set_jack_detect);
+
 static int rt5651_i2c_probe(struct i2c_client *i2c,
 		    const struct i2c_device_id *id)
 {
@@ -1779,6 +1887,59 @@ static int rt5651_i2c_probe(struct i2c_client *i2c,
 
 	rt5651->hp_mute = 1;
 
+	if (rt5651->pdata.jd_src) {
+
+		/* IRQ output on GPIO1 */
+		regmap_update_bits(rt5651->regmap, RT5651_GPIO_CTRL1,
+				   RT5651_GP1_PIN_MASK, RT5651_GP1_PIN_IRQ);
+
+		switch (rt5651->pdata.jd_src) {
+		case RT5651_JD1_1:
+			regmap_update_bits(rt5651->regmap, RT5651_JD_CTRL2,
+					   RT5651_JD_TRG_SEL_MASK,
+					   RT5651_JD_TRG_SEL_JD1_1);
+			regmap_update_bits(rt5651->regmap, RT5651_IRQ_CTRL1,
+					   RT5651_JD1_1_IRQ_EN,
+					   RT5651_JD1_1_IRQ_EN);
+			break;
+		case RT5651_JD1_2:
+			regmap_update_bits(rt5651->regmap, RT5651_JD_CTRL2,
+					   RT5651_JD_TRG_SEL_MASK,
+					   RT5651_JD_TRG_SEL_JD1_2);
+			regmap_update_bits(rt5651->regmap, RT5651_IRQ_CTRL1,
+					   RT5651_JD1_2_IRQ_EN,
+					   RT5651_JD1_2_IRQ_EN);
+			break;
+		case RT5651_JD2:
+			regmap_update_bits(rt5651->regmap, RT5651_JD_CTRL2,
+					   RT5651_JD_TRG_SEL_MASK,
+					   RT5651_JD_TRG_SEL_JD2);
+			regmap_update_bits(rt5651->regmap, RT5651_IRQ_CTRL1,
+					   RT5651_JD2_IRQ_EN,
+					   RT5651_JD2_IRQ_EN);
+			break;
+		case RT5651_JD_NULL:
+			break;
+		default:
+			dev_warn(&i2c->dev, "Currently only JD1_1 / JD1_2 / JD2 are supported\n");
+			break;
+		}
+	}
+
+	INIT_DELAYED_WORK(&rt5651->jack_detect_work, rt5651_jack_detect_work);
+
+	if (i2c->irq) {
+		ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL,
+						rt5651_irq,
+						IRQF_TRIGGER_RISING |
+						IRQF_TRIGGER_FALLING |
+						IRQF_ONESHOT, "rt5651", rt5651);
+		if (ret) {
+			dev_err(&i2c->dev, "Failed to reguest IRQ: %d\n", ret);
+			return ret;
+		}
+	}
+
 	ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5651,
 				rt5651_dai, ARRAY_SIZE(rt5651_dai));
 
@@ -1787,6 +1948,9 @@ static int rt5651_i2c_probe(struct i2c_client *i2c,
 
 static int rt5651_i2c_remove(struct i2c_client *i2c)
 {
+	struct rt5651_priv *rt5651 = i2c_get_clientdata(i2c);
+
+	cancel_delayed_work_sync(&rt5651->jack_detect_work);
 	snd_soc_unregister_codec(&i2c->dev);
 
 	return 0;
diff --git a/sound/soc/codecs/rt5651.h b/sound/soc/codecs/rt5651.h
index 1bd33cfa6411..4f8b202121d7 100644
--- a/sound/soc/codecs/rt5651.h
+++ b/sound/soc/codecs/rt5651.h
@@ -2062,6 +2062,8 @@ struct rt5651_priv {
 	struct snd_soc_codec *codec;
 	struct rt5651_platform_data pdata;
 	struct regmap *regmap;
+	struct snd_soc_jack *hp_jack;
+	struct delayed_work jack_detect_work;
 
 	int sysclk;
 	int sysclk_src;
@@ -2077,4 +2079,6 @@ struct rt5651_priv {
 	bool hp_mute;
 };
 
+int rt5651_set_jack_detect(struct snd_soc_codec *codec,
+			   struct snd_soc_jack *hp_jack);
 #endif /* __RT5651_H__ */
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Applied "ASoC: rt5651: Enable jack detection on JD* pins" to the asoc tree
  2017-10-20 11:18 ` [PATCH v2 1/5] ASoC: rt5651: Enable jack detection on JD* pins Carlo Caione
@ 2017-10-26 14:17     ` Mark Brown
  2017-10-26 14:17     ` Mark Brown
  1 sibling, 0 replies; 18+ messages in thread
From: Mark Brown @ 2017-10-26 14:17 UTC (permalink / raw)
  To: Carlo Caione
  Cc: Mark Brown, linux, bardliao, oder_chiou, pierre-louis.bossart,
	broonie, alsa-devel, linux-kernel, tiwai, albertchen, edgar_shen,
	alsa-devel

The patch

   ASoC: rt5651: Enable jack detection on JD* pins

has been applied to the asoc tree at

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 60d5a1a47b9a8381c08d2263b11ac9c757c87746 Mon Sep 17 00:00:00 2001
From: Carlo Caione <carlo@endlessm.com>
Date: Fri, 20 Oct 2017 12:18:55 +0100
Subject: [PATCH] ASoC: rt5651: Enable jack detection on JD* pins

Enable jack detection for the RT5651 codec on the JD* pins.

Signed-off-by: Carlo Caione <carlo@endlessm.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 include/sound/rt5651.h    |   8 +++
 sound/soc/codecs/rt5651.c | 168 +++++++++++++++++++++++++++++++++++++++++++++-
 sound/soc/codecs/rt5651.h |   4 ++
 3 files changed, 178 insertions(+), 2 deletions(-)

diff --git a/include/sound/rt5651.h b/include/sound/rt5651.h
index d35de758dfb5..18b79a761f10 100644
--- a/include/sound/rt5651.h
+++ b/include/sound/rt5651.h
@@ -11,11 +11,19 @@
 #ifndef __LINUX_SND_RT5651_H
 #define __LINUX_SND_RT5651_H
 
+enum rt5651_jd_src {
+	RT5651_JD_NULL,
+	RT5651_JD1_1,
+	RT5651_JD1_2,
+	RT5651_JD2,
+};
+
 struct rt5651_platform_data {
 	/* IN2 can optionally be differential */
 	bool in2_diff;
 
 	bool dmic_en;
+	enum rt5651_jd_src jd_src;
 };
 
 #endif
diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c
index da60b28ba3df..2f0d0055c72f 100644
--- a/sound/soc/codecs/rt5651.c
+++ b/sound/soc/codecs/rt5651.c
@@ -26,6 +26,7 @@
 #include <sound/soc-dapm.h>
 #include <sound/initval.h>
 #include <sound/tlv.h>
+#include <sound/jack.h>
 
 #include "rl6231.h"
 #include "rt5651.h"
@@ -880,6 +881,9 @@ static const struct snd_soc_dapm_widget rt5651_dapm_widgets[] = {
 	SND_SOC_DAPM_SUPPLY("PLL1", RT5651_PWR_ANLG2,
 			RT5651_PWR_PLL_BIT, 0, NULL, 0),
 	/* Input Side */
+	SND_SOC_DAPM_SUPPLY("JD Power", RT5651_PWR_ANLG2,
+		RT5651_PWM_JD_M_BIT, 0, NULL, 0),
+
 	/* micbias */
 	SND_SOC_DAPM_SUPPLY("LDO", RT5651_PWR_ANLG1,
 			RT5651_PWR_LDO_BIT, 0, NULL, 0),
@@ -1528,6 +1532,8 @@ static int rt5651_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
 static int rt5651_set_bias_level(struct snd_soc_codec *codec,
 			enum snd_soc_bias_level level)
 {
+	struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
+
 	switch (level) {
 	case SND_SOC_BIAS_PREPARE:
 		if (SND_SOC_BIAS_STANDBY == snd_soc_codec_get_bias_level(codec)) {
@@ -1556,8 +1562,13 @@ static int rt5651_set_bias_level(struct snd_soc_codec *codec,
 		snd_soc_write(codec, RT5651_PWR_DIG2, 0x0000);
 		snd_soc_write(codec, RT5651_PWR_VOL, 0x0000);
 		snd_soc_write(codec, RT5651_PWR_MIXER, 0x0000);
-		snd_soc_write(codec, RT5651_PWR_ANLG1, 0x0000);
-		snd_soc_write(codec, RT5651_PWR_ANLG2, 0x0000);
+		if (rt5651->pdata.jd_src) {
+			snd_soc_write(codec, RT5651_PWR_ANLG2, 0x0204);
+			snd_soc_write(codec, RT5651_PWR_ANLG1, 0x0002);
+		} else {
+			snd_soc_write(codec, RT5651_PWR_ANLG1, 0x0000);
+			snd_soc_write(codec, RT5651_PWR_ANLG2, 0x0000);
+		}
 		break;
 
 	default:
@@ -1570,6 +1581,7 @@ static int rt5651_set_bias_level(struct snd_soc_codec *codec,
 static int rt5651_probe(struct snd_soc_codec *codec)
 {
 	struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
+	struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
 
 	rt5651->codec = codec;
 
@@ -1585,6 +1597,15 @@ static int rt5651_probe(struct snd_soc_codec *codec)
 
 	snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_OFF);
 
+	if (rt5651->pdata.jd_src) {
+		snd_soc_dapm_force_enable_pin(dapm, "JD Power");
+		snd_soc_dapm_force_enable_pin(dapm, "LDO");
+		snd_soc_dapm_sync(dapm);
+
+		regmap_update_bits(rt5651->regmap, RT5651_MICBIAS,
+				   0x38, 0x38);
+	}
+
 	return 0;
 }
 
@@ -1728,6 +1749,93 @@ static int rt5651_parse_dt(struct rt5651_priv *rt5651, struct device_node *np)
 	return 0;
 }
 
+static irqreturn_t rt5651_irq(int irq, void *data)
+{
+	struct rt5651_priv *rt5651 = data;
+
+	queue_delayed_work(system_power_efficient_wq,
+			   &rt5651->jack_detect_work, msecs_to_jiffies(250));
+
+	return IRQ_HANDLED;
+}
+
+static int rt5651_jack_detect(struct snd_soc_codec *codec, int jack_insert)
+{
+	struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
+	int jack_type;
+
+	if (jack_insert) {
+		snd_soc_dapm_force_enable_pin(dapm, "LDO");
+		snd_soc_dapm_sync(dapm);
+
+		snd_soc_update_bits(codec, RT5651_MICBIAS,
+				    RT5651_MIC1_OVCD_MASK |
+				    RT5651_MIC1_OVTH_MASK |
+				    RT5651_PWR_CLK12M_MASK |
+				    RT5651_PWR_MB_MASK,
+				    RT5651_MIC1_OVCD_EN |
+				    RT5651_MIC1_OVTH_600UA |
+				    RT5651_PWR_MB_PU |
+				    RT5651_PWR_CLK12M_PU);
+		msleep(100);
+		if (snd_soc_read(codec, RT5651_IRQ_CTRL2) & RT5651_MB1_OC_CLR)
+			jack_type = SND_JACK_HEADPHONE;
+		else
+			jack_type = SND_JACK_HEADSET;
+		snd_soc_update_bits(codec, RT5651_IRQ_CTRL2,
+				    RT5651_MB1_OC_CLR, 0);
+	} else { /* jack out */
+		jack_type = 0;
+
+		snd_soc_update_bits(codec, RT5651_MICBIAS,
+				    RT5651_MIC1_OVCD_MASK,
+				    RT5651_MIC1_OVCD_DIS);
+	}
+
+	return jack_type;
+}
+
+static void rt5651_jack_detect_work(struct work_struct *work)
+{
+	struct rt5651_priv *rt5651 =
+		container_of(work, struct rt5651_priv, jack_detect_work.work);
+
+	int report, val = 0;
+
+	if (!rt5651->codec)
+		return;
+
+	switch (rt5651->pdata.jd_src) {
+	case RT5651_JD1_1:
+		val = snd_soc_read(rt5651->codec, RT5651_INT_IRQ_ST) & 0x1000;
+		break;
+	case RT5651_JD1_2:
+		val = snd_soc_read(rt5651->codec, RT5651_INT_IRQ_ST) & 0x2000;
+		break;
+	case RT5651_JD2:
+		val = snd_soc_read(rt5651->codec, RT5651_INT_IRQ_ST) & 0x4000;
+		break;
+	default:
+		break;
+	}
+
+	report = rt5651_jack_detect(rt5651->codec, !val);
+
+	snd_soc_jack_report(rt5651->hp_jack, report, SND_JACK_HEADSET);
+}
+
+int rt5651_set_jack_detect(struct snd_soc_codec *codec,
+			   struct snd_soc_jack *hp_jack)
+{
+	struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
+
+	rt5651->hp_jack = hp_jack;
+	rt5651_irq(0, rt5651);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rt5651_set_jack_detect);
+
 static int rt5651_i2c_probe(struct i2c_client *i2c,
 		    const struct i2c_device_id *id)
 {
@@ -1779,6 +1887,59 @@ static int rt5651_i2c_probe(struct i2c_client *i2c,
 
 	rt5651->hp_mute = 1;
 
+	if (rt5651->pdata.jd_src) {
+
+		/* IRQ output on GPIO1 */
+		regmap_update_bits(rt5651->regmap, RT5651_GPIO_CTRL1,
+				   RT5651_GP1_PIN_MASK, RT5651_GP1_PIN_IRQ);
+
+		switch (rt5651->pdata.jd_src) {
+		case RT5651_JD1_1:
+			regmap_update_bits(rt5651->regmap, RT5651_JD_CTRL2,
+					   RT5651_JD_TRG_SEL_MASK,
+					   RT5651_JD_TRG_SEL_JD1_1);
+			regmap_update_bits(rt5651->regmap, RT5651_IRQ_CTRL1,
+					   RT5651_JD1_1_IRQ_EN,
+					   RT5651_JD1_1_IRQ_EN);
+			break;
+		case RT5651_JD1_2:
+			regmap_update_bits(rt5651->regmap, RT5651_JD_CTRL2,
+					   RT5651_JD_TRG_SEL_MASK,
+					   RT5651_JD_TRG_SEL_JD1_2);
+			regmap_update_bits(rt5651->regmap, RT5651_IRQ_CTRL1,
+					   RT5651_JD1_2_IRQ_EN,
+					   RT5651_JD1_2_IRQ_EN);
+			break;
+		case RT5651_JD2:
+			regmap_update_bits(rt5651->regmap, RT5651_JD_CTRL2,
+					   RT5651_JD_TRG_SEL_MASK,
+					   RT5651_JD_TRG_SEL_JD2);
+			regmap_update_bits(rt5651->regmap, RT5651_IRQ_CTRL1,
+					   RT5651_JD2_IRQ_EN,
+					   RT5651_JD2_IRQ_EN);
+			break;
+		case RT5651_JD_NULL:
+			break;
+		default:
+			dev_warn(&i2c->dev, "Currently only JD1_1 / JD1_2 / JD2 are supported\n");
+			break;
+		}
+	}
+
+	INIT_DELAYED_WORK(&rt5651->jack_detect_work, rt5651_jack_detect_work);
+
+	if (i2c->irq) {
+		ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL,
+						rt5651_irq,
+						IRQF_TRIGGER_RISING |
+						IRQF_TRIGGER_FALLING |
+						IRQF_ONESHOT, "rt5651", rt5651);
+		if (ret) {
+			dev_err(&i2c->dev, "Failed to reguest IRQ: %d\n", ret);
+			return ret;
+		}
+	}
+
 	ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5651,
 				rt5651_dai, ARRAY_SIZE(rt5651_dai));
 
@@ -1787,6 +1948,9 @@ static int rt5651_i2c_probe(struct i2c_client *i2c,
 
 static int rt5651_i2c_remove(struct i2c_client *i2c)
 {
+	struct rt5651_priv *rt5651 = i2c_get_clientdata(i2c);
+
+	cancel_delayed_work_sync(&rt5651->jack_detect_work);
 	snd_soc_unregister_codec(&i2c->dev);
 
 	return 0;
diff --git a/sound/soc/codecs/rt5651.h b/sound/soc/codecs/rt5651.h
index 1bd33cfa6411..4f8b202121d7 100644
--- a/sound/soc/codecs/rt5651.h
+++ b/sound/soc/codecs/rt5651.h
@@ -2062,6 +2062,8 @@ struct rt5651_priv {
 	struct snd_soc_codec *codec;
 	struct rt5651_platform_data pdata;
 	struct regmap *regmap;
+	struct snd_soc_jack *hp_jack;
+	struct delayed_work jack_detect_work;
 
 	int sysclk;
 	int sysclk_src;
@@ -2077,4 +2079,6 @@ struct rt5651_priv {
 	bool hp_mute;
 };
 
+int rt5651_set_jack_detect(struct snd_soc_codec *codec,
+			   struct snd_soc_jack *hp_jack);
 #endif /* __RT5651_H__ */
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Applied "ASoC: rt5651: Enable jack detection on JD* pins" to the asoc tree
@ 2017-10-26 14:17     ` Mark Brown
  0 siblings, 0 replies; 18+ messages in thread
From: Mark Brown @ 2017-10-26 14:17 UTC (permalink / raw)
  To: Carlo Caione
  Cc: Mark Brown, linux, bardliao, oder_chiou, pierre-louis.bossart

The patch

   ASoC: rt5651: Enable jack detection on JD* pins

has been applied to the asoc tree at

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 60d5a1a47b9a8381c08d2263b11ac9c757c87746 Mon Sep 17 00:00:00 2001
From: Carlo Caione <carlo@endlessm.com>
Date: Fri, 20 Oct 2017 12:18:55 +0100
Subject: [PATCH] ASoC: rt5651: Enable jack detection on JD* pins

Enable jack detection for the RT5651 codec on the JD* pins.

Signed-off-by: Carlo Caione <carlo@endlessm.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 include/sound/rt5651.h    |   8 +++
 sound/soc/codecs/rt5651.c | 168 +++++++++++++++++++++++++++++++++++++++++++++-
 sound/soc/codecs/rt5651.h |   4 ++
 3 files changed, 178 insertions(+), 2 deletions(-)

diff --git a/include/sound/rt5651.h b/include/sound/rt5651.h
index d35de758dfb5..18b79a761f10 100644
--- a/include/sound/rt5651.h
+++ b/include/sound/rt5651.h
@@ -11,11 +11,19 @@
 #ifndef __LINUX_SND_RT5651_H
 #define __LINUX_SND_RT5651_H
 
+enum rt5651_jd_src {
+	RT5651_JD_NULL,
+	RT5651_JD1_1,
+	RT5651_JD1_2,
+	RT5651_JD2,
+};
+
 struct rt5651_platform_data {
 	/* IN2 can optionally be differential */
 	bool in2_diff;
 
 	bool dmic_en;
+	enum rt5651_jd_src jd_src;
 };
 
 #endif
diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c
index da60b28ba3df..2f0d0055c72f 100644
--- a/sound/soc/codecs/rt5651.c
+++ b/sound/soc/codecs/rt5651.c
@@ -26,6 +26,7 @@
 #include <sound/soc-dapm.h>
 #include <sound/initval.h>
 #include <sound/tlv.h>
+#include <sound/jack.h>
 
 #include "rl6231.h"
 #include "rt5651.h"
@@ -880,6 +881,9 @@ static const struct snd_soc_dapm_widget rt5651_dapm_widgets[] = {
 	SND_SOC_DAPM_SUPPLY("PLL1", RT5651_PWR_ANLG2,
 			RT5651_PWR_PLL_BIT, 0, NULL, 0),
 	/* Input Side */
+	SND_SOC_DAPM_SUPPLY("JD Power", RT5651_PWR_ANLG2,
+		RT5651_PWM_JD_M_BIT, 0, NULL, 0),
+
 	/* micbias */
 	SND_SOC_DAPM_SUPPLY("LDO", RT5651_PWR_ANLG1,
 			RT5651_PWR_LDO_BIT, 0, NULL, 0),
@@ -1528,6 +1532,8 @@ static int rt5651_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
 static int rt5651_set_bias_level(struct snd_soc_codec *codec,
 			enum snd_soc_bias_level level)
 {
+	struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
+
 	switch (level) {
 	case SND_SOC_BIAS_PREPARE:
 		if (SND_SOC_BIAS_STANDBY == snd_soc_codec_get_bias_level(codec)) {
@@ -1556,8 +1562,13 @@ static int rt5651_set_bias_level(struct snd_soc_codec *codec,
 		snd_soc_write(codec, RT5651_PWR_DIG2, 0x0000);
 		snd_soc_write(codec, RT5651_PWR_VOL, 0x0000);
 		snd_soc_write(codec, RT5651_PWR_MIXER, 0x0000);
-		snd_soc_write(codec, RT5651_PWR_ANLG1, 0x0000);
-		snd_soc_write(codec, RT5651_PWR_ANLG2, 0x0000);
+		if (rt5651->pdata.jd_src) {
+			snd_soc_write(codec, RT5651_PWR_ANLG2, 0x0204);
+			snd_soc_write(codec, RT5651_PWR_ANLG1, 0x0002);
+		} else {
+			snd_soc_write(codec, RT5651_PWR_ANLG1, 0x0000);
+			snd_soc_write(codec, RT5651_PWR_ANLG2, 0x0000);
+		}
 		break;
 
 	default:
@@ -1570,6 +1581,7 @@ static int rt5651_set_bias_level(struct snd_soc_codec *codec,
 static int rt5651_probe(struct snd_soc_codec *codec)
 {
 	struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
+	struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
 
 	rt5651->codec = codec;
 
@@ -1585,6 +1597,15 @@ static int rt5651_probe(struct snd_soc_codec *codec)
 
 	snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_OFF);
 
+	if (rt5651->pdata.jd_src) {
+		snd_soc_dapm_force_enable_pin(dapm, "JD Power");
+		snd_soc_dapm_force_enable_pin(dapm, "LDO");
+		snd_soc_dapm_sync(dapm);
+
+		regmap_update_bits(rt5651->regmap, RT5651_MICBIAS,
+				   0x38, 0x38);
+	}
+
 	return 0;
 }
 
@@ -1728,6 +1749,93 @@ static int rt5651_parse_dt(struct rt5651_priv *rt5651, struct device_node *np)
 	return 0;
 }
 
+static irqreturn_t rt5651_irq(int irq, void *data)
+{
+	struct rt5651_priv *rt5651 = data;
+
+	queue_delayed_work(system_power_efficient_wq,
+			   &rt5651->jack_detect_work, msecs_to_jiffies(250));
+
+	return IRQ_HANDLED;
+}
+
+static int rt5651_jack_detect(struct snd_soc_codec *codec, int jack_insert)
+{
+	struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
+	int jack_type;
+
+	if (jack_insert) {
+		snd_soc_dapm_force_enable_pin(dapm, "LDO");
+		snd_soc_dapm_sync(dapm);
+
+		snd_soc_update_bits(codec, RT5651_MICBIAS,
+				    RT5651_MIC1_OVCD_MASK |
+				    RT5651_MIC1_OVTH_MASK |
+				    RT5651_PWR_CLK12M_MASK |
+				    RT5651_PWR_MB_MASK,
+				    RT5651_MIC1_OVCD_EN |
+				    RT5651_MIC1_OVTH_600UA |
+				    RT5651_PWR_MB_PU |
+				    RT5651_PWR_CLK12M_PU);
+		msleep(100);
+		if (snd_soc_read(codec, RT5651_IRQ_CTRL2) & RT5651_MB1_OC_CLR)
+			jack_type = SND_JACK_HEADPHONE;
+		else
+			jack_type = SND_JACK_HEADSET;
+		snd_soc_update_bits(codec, RT5651_IRQ_CTRL2,
+				    RT5651_MB1_OC_CLR, 0);
+	} else { /* jack out */
+		jack_type = 0;
+
+		snd_soc_update_bits(codec, RT5651_MICBIAS,
+				    RT5651_MIC1_OVCD_MASK,
+				    RT5651_MIC1_OVCD_DIS);
+	}
+
+	return jack_type;
+}
+
+static void rt5651_jack_detect_work(struct work_struct *work)
+{
+	struct rt5651_priv *rt5651 =
+		container_of(work, struct rt5651_priv, jack_detect_work.work);
+
+	int report, val = 0;
+
+	if (!rt5651->codec)
+		return;
+
+	switch (rt5651->pdata.jd_src) {
+	case RT5651_JD1_1:
+		val = snd_soc_read(rt5651->codec, RT5651_INT_IRQ_ST) & 0x1000;
+		break;
+	case RT5651_JD1_2:
+		val = snd_soc_read(rt5651->codec, RT5651_INT_IRQ_ST) & 0x2000;
+		break;
+	case RT5651_JD2:
+		val = snd_soc_read(rt5651->codec, RT5651_INT_IRQ_ST) & 0x4000;
+		break;
+	default:
+		break;
+	}
+
+	report = rt5651_jack_detect(rt5651->codec, !val);
+
+	snd_soc_jack_report(rt5651->hp_jack, report, SND_JACK_HEADSET);
+}
+
+int rt5651_set_jack_detect(struct snd_soc_codec *codec,
+			   struct snd_soc_jack *hp_jack)
+{
+	struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
+
+	rt5651->hp_jack = hp_jack;
+	rt5651_irq(0, rt5651);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rt5651_set_jack_detect);
+
 static int rt5651_i2c_probe(struct i2c_client *i2c,
 		    const struct i2c_device_id *id)
 {
@@ -1779,6 +1887,59 @@ static int rt5651_i2c_probe(struct i2c_client *i2c,
 
 	rt5651->hp_mute = 1;
 
+	if (rt5651->pdata.jd_src) {
+
+		/* IRQ output on GPIO1 */
+		regmap_update_bits(rt5651->regmap, RT5651_GPIO_CTRL1,
+				   RT5651_GP1_PIN_MASK, RT5651_GP1_PIN_IRQ);
+
+		switch (rt5651->pdata.jd_src) {
+		case RT5651_JD1_1:
+			regmap_update_bits(rt5651->regmap, RT5651_JD_CTRL2,
+					   RT5651_JD_TRG_SEL_MASK,
+					   RT5651_JD_TRG_SEL_JD1_1);
+			regmap_update_bits(rt5651->regmap, RT5651_IRQ_CTRL1,
+					   RT5651_JD1_1_IRQ_EN,
+					   RT5651_JD1_1_IRQ_EN);
+			break;
+		case RT5651_JD1_2:
+			regmap_update_bits(rt5651->regmap, RT5651_JD_CTRL2,
+					   RT5651_JD_TRG_SEL_MASK,
+					   RT5651_JD_TRG_SEL_JD1_2);
+			regmap_update_bits(rt5651->regmap, RT5651_IRQ_CTRL1,
+					   RT5651_JD1_2_IRQ_EN,
+					   RT5651_JD1_2_IRQ_EN);
+			break;
+		case RT5651_JD2:
+			regmap_update_bits(rt5651->regmap, RT5651_JD_CTRL2,
+					   RT5651_JD_TRG_SEL_MASK,
+					   RT5651_JD_TRG_SEL_JD2);
+			regmap_update_bits(rt5651->regmap, RT5651_IRQ_CTRL1,
+					   RT5651_JD2_IRQ_EN,
+					   RT5651_JD2_IRQ_EN);
+			break;
+		case RT5651_JD_NULL:
+			break;
+		default:
+			dev_warn(&i2c->dev, "Currently only JD1_1 / JD1_2 / JD2 are supported\n");
+			break;
+		}
+	}
+
+	INIT_DELAYED_WORK(&rt5651->jack_detect_work, rt5651_jack_detect_work);
+
+	if (i2c->irq) {
+		ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL,
+						rt5651_irq,
+						IRQF_TRIGGER_RISING |
+						IRQF_TRIGGER_FALLING |
+						IRQF_ONESHOT, "rt5651", rt5651);
+		if (ret) {
+			dev_err(&i2c->dev, "Failed to reguest IRQ: %d\n", ret);
+			return ret;
+		}
+	}
+
 	ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5651,
 				rt5651_dai, ARRAY_SIZE(rt5651_dai));
 
@@ -1787,6 +1948,9 @@ static int rt5651_i2c_probe(struct i2c_client *i2c,
 
 static int rt5651_i2c_remove(struct i2c_client *i2c)
 {
+	struct rt5651_priv *rt5651 = i2c_get_clientdata(i2c);
+
+	cancel_delayed_work_sync(&rt5651->jack_detect_work);
 	snd_soc_unregister_codec(&i2c->dev);
 
 	return 0;
diff --git a/sound/soc/codecs/rt5651.h b/sound/soc/codecs/rt5651.h
index 1bd33cfa6411..4f8b202121d7 100644
--- a/sound/soc/codecs/rt5651.h
+++ b/sound/soc/codecs/rt5651.h
@@ -2062,6 +2062,8 @@ struct rt5651_priv {
 	struct snd_soc_codec *codec;
 	struct rt5651_platform_data pdata;
 	struct regmap *regmap;
+	struct snd_soc_jack *hp_jack;
+	struct delayed_work jack_detect_work;
 
 	int sysclk;
 	int sysclk_src;
@@ -2077,4 +2079,6 @@ struct rt5651_priv {
 	bool hp_mute;
 };
 
+int rt5651_set_jack_detect(struct snd_soc_codec *codec,
+			   struct snd_soc_jack *hp_jack);
 #endif /* __RT5651_H__ */
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2017-10-26 14:18 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-10-20 11:18 [PATCH v2 0/5] rt5651: Enable jack detection Carlo Caione
2017-10-20 11:18 ` [PATCH v2 1/5] ASoC: rt5651: Enable jack detection on JD* pins Carlo Caione
2017-10-26 14:17   ` Applied "ASoC: rt5651: Enable jack detection on JD* pins" to the asoc tree Mark Brown
2017-10-26 14:17     ` Mark Brown
2017-10-26 14:17   ` Mark Brown
2017-10-26 14:17     ` Mark Brown
2017-10-20 11:18 ` [PATCH v2 2/5] ASoC: intel: byt: Add headset jack Carlo Caione
2017-10-26 14:16   ` Applied "ASoC: intel: byt: Add headset jack" to the asoc tree Mark Brown
2017-10-26 14:16     ` Mark Brown
2017-10-20 11:18 ` [PATCH v2 3/5] ASoC: intel: byt: Enable IN2 map quirk for a KIANO laptop Carlo Caione
2017-10-26 14:16   ` Applied "ASoC: intel: byt: Enable IN2 map quirk for a KIANO laptop" to the asoc tree Mark Brown
2017-10-26 14:16     ` Mark Brown
2017-10-20 11:18 ` [PATCH v2 4/5] ASoC: rt5651: Rework quirk logic Carlo Caione
2017-10-26 14:16   ` Applied "ASoC: rt5651: Rework quirk logic" to the asoc tree Mark Brown
2017-10-26 14:16     ` Mark Brown
2017-10-20 11:18 ` [PATCH v2 5/5] ASoC: rt5651: Enable JD1_1 quirk for KIANO laptopt Carlo Caione
2017-10-26 14:16   ` Applied "ASoC: rt5651: Enable JD1_1 quirk for KIANO laptopt" to the asoc tree Mark Brown
2017-10-26 14:16     ` Mark Brown

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.