All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 01/11] ASoC: rt5651: Avoid duplicating DMI quirks between codec and machine driver
@ 2018-02-20 22:15 Hans de Goede
  2018-02-20 22:15 ` [PATCH 02/11] ASoC: rt5651: Remove is_sys_clk_from_pll, it has ordering issues Hans de Goede
                   ` (11 more replies)
  0 siblings, 12 replies; 35+ messages in thread
From: Hans de Goede @ 2018-02-20 22:15 UTC (permalink / raw)
  To: Mark Brown, Bard Liao
  Cc: Hans de Goede, alsa-devel, Carlo Caione, Takashi Iwai

Instead of duplicating the DMI quirks between the codec and machine driver,
add a rt5651_set_pdata() codec private function which the machine driver
can use to pass in pdata.

This means we need to delay setting up the jack-detect registers, so this
commits moves this to rt5651_set_jack() code. Note this is actually a good
thing as before we would register the irq handler before rt5651->hp_jack
was assigned, leading to a potential NULL deref if the jack_detect work
runs before the machine driver has called set_jack.

While at it also move over to the standard snd_soc_codec_set_jack()
function instead of using a codec private function for this.

Note this commit causes the machine-driver to now actually honor the
BYT_RT5651_DMIC_EN quirk, which was ignored before. To avoid this causing
a functional change in what is purely a refactor commit, this commit
removes the quirk from the defaults.

If we really want the BYT_RT5651_DMIC_EN behavior anywhere it should be
specifically enabled by follow up commits.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 sound/soc/codecs/rt5651.c             | 232 +++++++++++++++-------------------
 sound/soc/codecs/rt5651.h             |   6 +-
 sound/soc/intel/boards/bytcr_rt5651.c |  43 +++++--
 3 files changed, 139 insertions(+), 142 deletions(-)

diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c
index 45a73049cf64..c5d19a80506b 100644
--- a/sound/soc/codecs/rt5651.c
+++ b/sound/soc/codecs/rt5651.c
@@ -19,7 +19,6 @@
 #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>
@@ -32,10 +31,6 @@
 #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)
@@ -43,8 +38,6 @@
 
 #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,
@@ -1585,10 +1578,88 @@ static int rt5651_set_bias_level(struct snd_soc_codec *codec,
 	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_set_jack(struct snd_soc_codec *codec,
+			   struct snd_soc_jack *hp_jack, void *data)
+{
+	struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
+	struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
+	int ret;
+
+	if (!rt5651->pdata.jd_src || !rt5651->irq)
+		return -EINVAL;
+
+	/* 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(codec->dev, "Currently only JD1_1 / JD1_2 / JD2 are supported\n");
+		break;
+	}
+
+	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);
+
+	ret = devm_request_threaded_irq(codec->dev, rt5651->irq, NULL,
+					rt5651_irq,
+					IRQF_TRIGGER_RISING |
+					IRQF_TRIGGER_FALLING |
+					IRQF_ONESHOT, "rt5651", rt5651);
+	if (ret) {
+		dev_err(codec->dev, "Failed to reguest IRQ: %d\n", ret);
+		return ret;
+	}
+
+	rt5651->hp_jack = hp_jack;
+	rt5651_irq(0, rt5651);
+
+	return 0;
+}
+
 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;
 
@@ -1604,15 +1675,6 @@ 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;
 }
 
@@ -1698,6 +1760,7 @@ static const struct snd_soc_codec_driver soc_codec_dev_rt5651 = {
 	.resume = rt5651_resume,
 	.set_bias_level = rt5651_set_bias_level,
 	.idle_bias_off = true,
+	.set_jack = rt5651_set_jack,
 	.component_driver = {
 		.controls		= rt5651_snd_controls,
 		.num_controls		= ARRAY_SIZE(rt5651_snd_controls),
@@ -1747,54 +1810,16 @@ 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[] = {
-	{
-		.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,
-	},
-	{}
-};
-
 static int rt5651_parse_dt(struct rt5651_priv *rt5651, struct device_node *np)
 {
-	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;
+	rt5651->pdata.in2_diff =
+		of_property_read_bool(np, "realtek,in2-differential");
+	rt5651->pdata.dmic_en =
+		of_property_read_bool(np, "realtek,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;
-
-	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);
@@ -1860,17 +1885,26 @@ static void rt5651_jack_detect_work(struct work_struct *work)
 	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)
+static void rt5651_apply_pdata(struct rt5651_priv *rt5651)
 {
-	struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
+	if (rt5651->pdata.in2_diff)
+		regmap_update_bits(rt5651->regmap, RT5651_IN1_IN2,
+					RT5651_IN_DF2, RT5651_IN_DF2);
 
-	rt5651->hp_jack = hp_jack;
-	rt5651_irq(0, rt5651);
+	if (rt5651->pdata.dmic_en)
+		regmap_update_bits(rt5651->regmap, RT5651_GPIO_CTRL1,
+				RT5651_GP2_PIN_MASK, RT5651_GP2_PIN_DMIC1_SCL);
+}
 
-	return 0;
+void rt5651_set_pdata(struct snd_soc_codec *codec,
+		      struct rt5651_platform_data *pdata)
+{
+	struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
+
+	rt5651->pdata = *pdata;
+	rt5651_apply_pdata(rt5651);
 }
-EXPORT_SYMBOL_GPL(rt5651_set_jack_detect);
+EXPORT_SYMBOL_GPL(rt5651_set_pdata);
 
 static int rt5651_i2c_probe(struct i2c_client *i2c,
 		    const struct i2c_device_id *id)
@@ -1890,10 +1924,6 @@ 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)) {
@@ -1917,69 +1947,13 @@ static int rt5651_i2c_probe(struct i2c_client *i2c,
 	if (ret != 0)
 		dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret);
 
-	if (rt5651->pdata.in2_diff)
-		regmap_update_bits(rt5651->regmap, RT5651_IN1_IN2,
-					RT5651_IN_DF2, RT5651_IN_DF2);
-
-	if (rt5651->pdata.dmic_en)
-		regmap_update_bits(rt5651->regmap, RT5651_GPIO_CTRL1,
-				RT5651_GP2_PIN_MASK, RT5651_GP2_PIN_DMIC1_SCL);
+	if (pdata || i2c->dev.of_node)
+		rt5651_apply_pdata(rt5651);
 
+	rt5651->irq = i2c->irq;
 	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));
 
diff --git a/sound/soc/codecs/rt5651.h b/sound/soc/codecs/rt5651.h
index 4f8b202121d7..151ac92f6bad 100644
--- a/sound/soc/codecs/rt5651.h
+++ b/sound/soc/codecs/rt5651.h
@@ -2065,6 +2065,7 @@ struct rt5651_priv {
 	struct snd_soc_jack *hp_jack;
 	struct delayed_work jack_detect_work;
 
+	int irq;
 	int sysclk;
 	int sysclk_src;
 	int lrck[RT5651_AIFS];
@@ -2079,6 +2080,7 @@ struct rt5651_priv {
 	bool hp_mute;
 };
 
-int rt5651_set_jack_detect(struct snd_soc_codec *codec,
-			   struct snd_soc_jack *hp_jack);
+void rt5651_set_pdata(struct snd_soc_codec *codec,
+		      struct rt5651_platform_data *pdata);
+
 #endif /* __RT5651_H__ */
diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c
index 49c538f2770a..8ef5b5500fb7 100644
--- a/sound/soc/intel/boards/bytcr_rt5651.c
+++ b/sound/soc/intel/boards/bytcr_rt5651.c
@@ -42,7 +42,15 @@ enum {
 	BYT_RT5651_IN3_MAP,
 };
 
-#define BYT_RT5651_MAP(quirk)	((quirk) & GENMASK(7, 0))
+enum {
+	BYT_RT5651_JD_NULL	= (RT5651_JD_NULL << 4),
+	BYT_RT5651_JD1_1	= (RT5651_JD1_1 << 4),
+	BYT_RT5651_JD1_2	= (RT5651_JD1_2 << 4),
+	BYT_RT5651_JD2		= (RT5651_JD2 << 4),
+};
+
+#define BYT_RT5651_MAP(quirk)	((quirk) & GENMASK(3, 0))
+#define BYT_RT5651_JDSRC(quirk)	(((quirk) & GENMASK(7, 4)) >> 4)
 #define BYT_RT5651_DMIC_EN	BIT(16)
 #define BYT_RT5651_MCLK_EN	BIT(17)
 #define BYT_RT5651_MCLK_25MHZ	BIT(18)
@@ -53,7 +61,6 @@ struct byt_rt5651_private {
 };
 
 static unsigned long byt_rt5651_quirk = BYT_RT5651_DMIC_MAP |
-					BYT_RT5651_DMIC_EN |
 					BYT_RT5651_MCLK_EN;
 
 static void log_quirks(struct device *dev)
@@ -66,6 +73,9 @@ static void log_quirks(struct device *dev)
 		dev_info(dev, "quirk IN2_MAP enabled");
 	if (BYT_RT5651_MAP(byt_rt5651_quirk) == BYT_RT5651_IN3_MAP)
 		dev_info(dev, "quirk IN3_MAP enabled");
+	if (BYT_RT5651_JDSRC(byt_rt5651_quirk))
+		dev_info(dev, "quirk jack-detect src %ld\n",
+			 BYT_RT5651_JDSRC(byt_rt5651_quirk));
 	if (byt_rt5651_quirk & BYT_RT5651_DMIC_EN)
 		dev_info(dev, "quirk DMIC enabled");
 	if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN)
@@ -288,6 +298,7 @@ static const struct dmi_system_id byt_rt5651_quirk_table[] = {
 			DMI_MATCH(DMI_PRODUCT_NAME, "KIANO SlimNote 14.2"),
 		},
 		.driver_data = (void *)(BYT_RT5651_MCLK_EN |
+					BYT_RT5651_JD1_1 |
 					BYT_RT5651_IN1_IN2_MAP),
 	},
 	{}
@@ -299,6 +310,7 @@ static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime)
 	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;
+	struct rt5651_platform_data pdata = {};
 	int num_routes;
 	int ret;
 
@@ -360,17 +372,26 @@ 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;
-	}
+	pdata.jd_src = BYT_RT5651_JDSRC(byt_rt5651_quirk);
+	if (byt_rt5651_quirk & BYT_RT5651_DMIC_EN)
+		pdata.dmic_en = true;
+	rt5651_set_pdata(codec, &pdata);
+
+	if (BYT_RT5651_JDSRC(byt_rt5651_quirk)) {
+		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, "Jack creation failed %d\n", ret);
+			return ret;
+		}
 
-	rt5651_set_jack_detect(codec, &priv->jack);
+		ret = snd_soc_codec_set_jack(codec, &priv->jack, NULL);
+		if (ret)
+			return ret;
+	}
 
-	return ret;
+	return 0;
 }
 
 static const struct snd_soc_pcm_stream byt_rt5651_dai_params = {
-- 
2.14.3

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

* [PATCH 02/11] ASoC: rt5651: Remove is_sys_clk_from_pll, it has ordering issues
  2018-02-20 22:15 [PATCH 01/11] ASoC: rt5651: Avoid duplicating DMI quirks between codec and machine driver Hans de Goede
@ 2018-02-20 22:15 ` Hans de Goede
  2018-02-21 11:18   ` Mark Brown
  2018-02-20 22:15 ` [PATCH 03/11] ASoC: rt5651: Fix bias_level confusion / overcurrent detection deps Hans de Goede
                   ` (10 subsequent siblings)
  11 siblings, 1 reply; 35+ messages in thread
From: Hans de Goede @ 2018-02-20 22:15 UTC (permalink / raw)
  To: Mark Brown, Bard Liao
  Cc: Hans de Goede, alsa-devel, Carlo Caione, Takashi Iwai

dapm_power_widgets() first builds a list of which widgets to power-up
before actually powering any of them up. For dapm-supply widgets their
connected method, in our case is_sys_clk_from_pll() get called at this
point.

Before this commit is_sys_clk_from_pll() was looking at the actually
selected clock in the RT5651_GBL_CLK register. But the sysclk itself is
selected by another dapm-supply (the "Platform Clock" supply in the
machine driver) and any changes to that supply part of the same power-
transition get executed after building the list, causing
is_sys_clk_from_pll() to return the wrong value.

This sometimes leads to the PWR_PLL bit not getting set even though we
have configured an active audio chain and RT5651_GBL_CLK does point to
PLL1 as the sysclk-source.

Note that even if we do not have an active audio chain we should still keep
the PWR_PLL bit set if PLL1 is our sysclk-source, because we must always
have a working sysclk-source, otherwise e.g. jack-detection will not work.

If we don't have an active audio-chain then the machine-driver should
switch the sysclk-source to the RCCLK and if does not then that is a
machine-driver (or UCM config) problem and not something we should try
to work around by disabling our sysclk-source and breaking jack-detect.

TL;DR: The PLL1-supply must always be powered up when PLL1 is the sysclk
source and we can simply set the RT5651_PWR_PLL bit when selecting PLL1.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
Note that many of the other rt56?? drivers have the same
is_sys_clk_from_pll() stuff and may need similar fixes.
---
 sound/soc/codecs/rt5651.c | 25 +++++--------------------
 1 file changed, 5 insertions(+), 20 deletions(-)

diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c
index c5d19a80506b..a48278f6205d 100644
--- a/sound/soc/codecs/rt5651.c
+++ b/sound/soc/codecs/rt5651.c
@@ -393,20 +393,6 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w,
 	return idx;
 }
 
-static int is_sysclk_from_pll(struct snd_soc_dapm_widget *source,
-			 struct snd_soc_dapm_widget *sink)
-{
-	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm);
-	unsigned int val;
-
-	val = snd_soc_read(codec, RT5651_GLB_CLK);
-	val &= RT5651_SCLK_SRC_MASK;
-	if (val == RT5651_SCLK_SRC_PLL1)
-		return 1;
-	else
-		return 0;
-}
-
 /* Digital Mixer */
 static const struct snd_kcontrol_new rt5651_sto1_adc_l_mix[] = {
 	SOC_DAPM_SINGLE("ADC1 Switch", RT5651_STO1_ADC_MIXER,
@@ -878,8 +864,6 @@ static const struct snd_soc_dapm_widget rt5651_dapm_widgets[] = {
 	SND_SOC_DAPM_SUPPLY_S("ADC ASRC", 1, RT5651_PLL_MODE_2,
 			      11, 0, NULL, 0),
 
-	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),
@@ -1162,7 +1146,6 @@ static const struct snd_soc_dapm_route rt5651_dapm_routes[] = {
 	{"Stereo1 ADC MIXL", "ADC1 Switch", "Stereo1 ADC L1 Mux"},
 	{"Stereo1 ADC MIXL", "ADC2 Switch", "Stereo1 ADC L2 Mux"},
 	{"Stereo1 ADC MIXL", NULL, "Stereo1 Filter"},
-	{"Stereo1 Filter", NULL, "PLL1", is_sysclk_from_pll},
 	{"Stereo1 Filter", NULL, "ADC ASRC"},
 
 	{"Stereo1 ADC MIXR", "ADC1 Switch", "Stereo1 ADC R1 Mux"},
@@ -1172,7 +1155,6 @@ static const struct snd_soc_dapm_route rt5651_dapm_routes[] = {
 	{"Stereo2 ADC MIXL", "ADC1 Switch", "Stereo2 ADC L1 Mux"},
 	{"Stereo2 ADC MIXL", "ADC2 Switch", "Stereo2 ADC L2 Mux"},
 	{"Stereo2 ADC MIXL", NULL, "Stereo2 Filter"},
-	{"Stereo2 Filter", NULL, "PLL1", is_sysclk_from_pll},
 	{"Stereo2 Filter", NULL, "ADC ASRC"},
 
 	{"Stereo2 ADC MIXR", "ADC1 Switch", "Stereo2 ADC R1 Mux"},
@@ -1239,10 +1221,8 @@ static const struct snd_soc_dapm_route rt5651_dapm_routes[] = {
 	{"PDM R Mux", "DD MIX", "DAC MIXR"},
 
 	{"DAC L1", NULL, "Stereo DAC MIXL"},
-	{"DAC L1", NULL, "PLL1", is_sysclk_from_pll},
 	{"DAC L1", NULL, "DAC L1 Power"},
 	{"DAC R1", NULL, "Stereo DAC MIXR"},
-	{"DAC R1", NULL, "PLL1", is_sysclk_from_pll},
 	{"DAC R1", NULL, "DAC R1 Power"},
 
 	{"DD MIXL", "DAC L1 Switch", "DAC MIXL"},
@@ -1438,6 +1418,7 @@ static int rt5651_set_dai_sysclk(struct snd_soc_dai *dai,
 	struct snd_soc_codec *codec = dai->codec;
 	struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
 	unsigned int reg_val = 0;
+	unsigned int pll_bit = 0;
 
 	if (freq == rt5651->sysclk && clk_id == rt5651->sysclk_src)
 		return 0;
@@ -1448,6 +1429,7 @@ static int rt5651_set_dai_sysclk(struct snd_soc_dai *dai,
 		break;
 	case RT5651_SCLK_S_PLL1:
 		reg_val |= RT5651_SCLK_SRC_PLL1;
+		pll_bit |= RT5651_PWR_PLL;
 		break;
 	case RT5651_SCLK_S_RCCLK:
 		reg_val |= RT5651_SCLK_SRC_RCCLK;
@@ -1456,6 +1438,9 @@ static int rt5651_set_dai_sysclk(struct snd_soc_dai *dai,
 		dev_err(codec->dev, "Invalid clock id (%d)\n", clk_id);
 		return -EINVAL;
 	}
+
+	snd_soc_update_bits(codec, RT5651_PWR_ANLG2,
+		RT5651_PWR_PLL, pll_bit);
 	snd_soc_update_bits(codec, RT5651_GLB_CLK,
 		RT5651_SCLK_SRC_MASK, reg_val);
 	rt5651->sysclk = freq;
-- 
2.14.3

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

* [PATCH 03/11] ASoC: rt5651: Fix bias_level confusion / overcurrent detection deps
  2018-02-20 22:15 [PATCH 01/11] ASoC: rt5651: Avoid duplicating DMI quirks between codec and machine driver Hans de Goede
  2018-02-20 22:15 ` [PATCH 02/11] ASoC: rt5651: Remove is_sys_clk_from_pll, it has ordering issues Hans de Goede
@ 2018-02-20 22:15 ` Hans de Goede
  2018-02-21 11:40   ` Mark Brown
  2018-02-20 22:15 ` [PATCH 04/11] ASoC: rt5651: Simplify set_bias_level() Hans de Goede
                   ` (9 subsequent siblings)
  11 siblings, 1 reply; 35+ messages in thread
From: Hans de Goede @ 2018-02-20 22:15 UTC (permalink / raw)
  To: Mark Brown, Bard Liao
  Cc: Hans de Goede, alsa-devel, Carlo Caione, Takashi Iwai

Overcurrent detection (ovcd) requires the following to be on:
1) The LDO supply
2) The micbias1 supply
3) General analog voltages such as vref aka a bias_level of standby

Before this commit deps 2. and 3. were not met (unless a stream recording
from the mic was active).

3. Is not met because rt5651_set_bias_level() was only enabling this when
reaching a bias level of prepared instead of doing this in the normal
standby bias level, which the dapm core will select as soon as any pins /
supplies are on. This commit fixes by making rt5651_set_bias_level() behave
as a normal set_bias function for other codecs and already enabling these
things at standby level.

This change to rt5651_set_bias_level() causes a problem because when jack-
detect is used the bias-level was always set to standby because of the
"JD Power" supply being force-enabled.

As the set_bias_level code already leaves the RT5651_PWR_JD_M bit on when
entering standby (now off) when jd is in use, we can simply drop the
"JD Power" supply so that the bias-level properly becomes off when nothing
is happening. For the same reason we should also not enable the LDO supply
until we actually want to do ovcd detection.

2. is fixed by simply force-enabling "micbias1" when doing ovcd, this
commit also adds code to turn both the micbias1 and the LDO supplies of
again when we're done, note they will only really get turned off if the
ovcd was the only user.

The snd_soc_codec_force_bias_level(BIAS_OFF) call done in rt5651_probe()
will now turn off PWR_ANLG1, so the programming of PWR_ANLG1 before the
snd_soc_codec_force_bias_level() now is a no-op and can be removed.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 sound/soc/codecs/rt5651.c | 39 ++++++++++++++++-----------------------
 1 file changed, 16 insertions(+), 23 deletions(-)

diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c
index a48278f6205d..52fb835ea584 100644
--- a/sound/soc/codecs/rt5651.c
+++ b/sound/soc/codecs/rt5651.c
@@ -864,10 +864,6 @@ static const struct snd_soc_dapm_widget rt5651_dapm_widgets[] = {
 	SND_SOC_DAPM_SUPPLY_S("ADC ASRC", 1, RT5651_PLL_MODE_2,
 			      11, 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),
@@ -1520,8 +1516,8 @@ static int rt5651_set_bias_level(struct snd_soc_codec *codec,
 	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)) {
+	case SND_SOC_BIAS_STANDBY:
+		if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) {
 			snd_soc_update_bits(codec, RT5651_PWR_ANLG1,
 				RT5651_PWR_VREF1 | RT5651_PWR_MB |
 				RT5651_PWR_BG | RT5651_PWR_VREF2,
@@ -1541,7 +1537,7 @@ static int rt5651_set_bias_level(struct snd_soc_codec *codec,
 		}
 		break;
 
-	case SND_SOC_BIAS_STANDBY:
+	case SND_SOC_BIAS_OFF:
 		snd_soc_write(codec, RT5651_D_MISC, 0x0010);
 		snd_soc_write(codec, RT5651_PWR_DIG1, 0x0000);
 		snd_soc_write(codec, RT5651_PWR_DIG2, 0x0000);
@@ -1576,7 +1572,6 @@ static irqreturn_t rt5651_irq(int irq, void *data)
 static int rt5651_set_jack(struct snd_soc_codec *codec,
 			   struct snd_soc_jack *hp_jack, void *data)
 {
-	struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
 	struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
 	int ret;
 
@@ -1619,9 +1614,8 @@ static int rt5651_set_jack(struct snd_soc_codec *codec,
 		break;
 	}
 
-	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_PWR_ANLG2, RT5651_PWR_JD_M,
+			   RT5651_PWR_JD_M);
 
 	regmap_update_bits(rt5651->regmap, RT5651_MICBIAS,
 			   0x38, 0x38);
@@ -1648,16 +1642,6 @@ static int rt5651_probe(struct snd_soc_codec *codec)
 
 	rt5651->codec = codec;
 
-	snd_soc_update_bits(codec, RT5651_PWR_ANLG1,
-		RT5651_PWR_VREF1 | RT5651_PWR_MB |
-		RT5651_PWR_BG | RT5651_PWR_VREF2,
-		RT5651_PWR_VREF1 | RT5651_PWR_MB |
-		RT5651_PWR_BG | RT5651_PWR_VREF2);
-	usleep_range(10000, 15000);
-	snd_soc_update_bits(codec, RT5651_PWR_ANLG1,
-		RT5651_PWR_FV1 | RT5651_PWR_FV2,
-		RT5651_PWR_FV1 | RT5651_PWR_FV2);
-
 	snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_OFF);
 
 	return 0;
@@ -1811,8 +1795,11 @@ static int rt5651_jack_detect(struct snd_soc_codec *codec, int jack_insert)
 	int jack_type;
 
 	if (jack_insert) {
-		snd_soc_dapm_force_enable_pin(dapm, "LDO");
-		snd_soc_dapm_sync(dapm);
+		snd_soc_dapm_mutex_lock(dapm);
+		snd_soc_dapm_force_enable_pin_unlocked(dapm, "LDO");
+		snd_soc_dapm_force_enable_pin_unlocked(dapm, "micbias1");
+		snd_soc_dapm_sync_unlocked(dapm);
+		snd_soc_dapm_mutex_unlock(dapm);
 
 		snd_soc_update_bits(codec, RT5651_MICBIAS,
 				    RT5651_MIC1_OVCD_MASK |
@@ -1830,6 +1817,12 @@ static int rt5651_jack_detect(struct snd_soc_codec *codec, int jack_insert)
 			jack_type = SND_JACK_HEADSET;
 		snd_soc_update_bits(codec, RT5651_IRQ_CTRL2,
 				    RT5651_MB1_OC_CLR, 0);
+
+		snd_soc_dapm_mutex_lock(dapm);
+		snd_soc_dapm_disable_pin_unlocked(dapm, "micbias1");
+		snd_soc_dapm_disable_pin_unlocked(dapm, "LDO");
+		snd_soc_dapm_sync_unlocked(dapm);
+		snd_soc_dapm_mutex_unlock(dapm);
 	} else { /* jack out */
 		jack_type = 0;
 
-- 
2.14.3

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

* [PATCH 04/11] ASoC: rt5651: Simplify set_bias_level()
  2018-02-20 22:15 [PATCH 01/11] ASoC: rt5651: Avoid duplicating DMI quirks between codec and machine driver Hans de Goede
  2018-02-20 22:15 ` [PATCH 02/11] ASoC: rt5651: Remove is_sys_clk_from_pll, it has ordering issues Hans de Goede
  2018-02-20 22:15 ` [PATCH 03/11] ASoC: rt5651: Fix bias_level confusion / overcurrent detection deps Hans de Goede
@ 2018-02-20 22:15 ` Hans de Goede
  2018-02-21 11:43   ` Mark Brown
  2018-02-20 22:15 ` [PATCH 05/11] ASoC: rt5651: Allow specifying micbias over-current thresholds through pdata Hans de Goede
                   ` (8 subsequent siblings)
  11 siblings, 1 reply; 35+ messages in thread
From: Hans de Goede @ 2018-02-20 22:15 UTC (permalink / raw)
  To: Mark Brown, Bard Liao
  Cc: Hans de Goede, alsa-devel, Carlo Caione, Takashi Iwai

There is no need to set the LDO voltage to 1.2 volt each time we enter
standby, instead always leave it 1.2 volt on BIAS_OFF. Note we do a
snd_soc_codec_force_bias_level(BIAS_OFF) on probe, so this will configure
it correctly right from the start.

For PWR_ANLG2 leave the RT5651_PWR_JD_M and PLL bits as is instead of
having different code-paths for when we've jack-detect vs when we don't.

Note that this also stops enabling the PLL bit when we've a jd_src and we
are running of the RCCLK, this is intentional.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 sound/soc/codecs/rt5651.c | 17 +++++------------
 1 file changed, 5 insertions(+), 12 deletions(-)

diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c
index 52fb835ea584..4b0509f7e001 100644
--- a/sound/soc/codecs/rt5651.c
+++ b/sound/soc/codecs/rt5651.c
@@ -1513,8 +1513,6 @@ 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_STANDBY:
 		if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) {
@@ -1527,9 +1525,6 @@ static int rt5651_set_bias_level(struct snd_soc_codec *codec,
 			snd_soc_update_bits(codec, RT5651_PWR_ANLG1,
 				RT5651_PWR_FV1 | RT5651_PWR_FV2,
 				RT5651_PWR_FV1 | RT5651_PWR_FV2);
-			snd_soc_update_bits(codec, RT5651_PWR_ANLG1,
-				RT5651_PWR_LDO_DVO_MASK,
-				RT5651_PWR_LDO_DVO_1_2V);
 			snd_soc_update_bits(codec, RT5651_D_MISC, 0x1, 0x1);
 			if (snd_soc_read(codec, RT5651_PLL_MODE_1) & 0x9200)
 				snd_soc_update_bits(codec, RT5651_D_MISC,
@@ -1543,13 +1538,11 @@ 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);
-		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);
-		}
+		snd_soc_write(codec, RT5651_PWR_ANLG1, RT5651_PWR_LDO_DVO_1_2V);
+		/* Leave PLL1 and jack-detect power as is, all others off */
+		snd_soc_update_bits(codec, RT5651_PWR_ANLG2,
+				    ~(RT5651_PWR_PLL | RT5651_PWR_JD_M),
+				    0x0000);
 		break;
 
 	default:
-- 
2.14.3

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

* [PATCH 05/11] ASoC: rt5651: Allow specifying micbias over-current thresholds through pdata
  2018-02-20 22:15 [PATCH 01/11] ASoC: rt5651: Avoid duplicating DMI quirks between codec and machine driver Hans de Goede
                   ` (2 preceding siblings ...)
  2018-02-20 22:15 ` [PATCH 04/11] ASoC: rt5651: Simplify set_bias_level() Hans de Goede
@ 2018-02-20 22:15 ` Hans de Goede
  2018-02-20 22:15 ` [PATCH 06/11] ASoC: rt5651: Improve headphone vs headset detection Hans de Goede
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 35+ messages in thread
From: Hans de Goede @ 2018-02-20 22:15 UTC (permalink / raw)
  To: Mark Brown, Bard Liao
  Cc: Hans de Goede, alsa-devel, Carlo Caione, Takashi Iwai

OVer-Current-Detection (OVCD) for the micbias current is used to detect if
an inserted jack is a headset or headphones (mic shorted to ground).

Some boards may need different values for the OVCD threshold because of a
resistor on the board in serial with or parallel to the jack mic contact.

This commit adds support for the sofar unset OVCD scale-factor register
values and adds support for specifying both the current threshold and the
scale-factor to pdata and this commets sets these values only once from
rt5651_set_jack() instead of setting them every time we do jack-detection.

This commit sets the new pdata values for this to 2000uA with a
scale-factor of 0.75 for the KIANO SlimNote 14.2 device, which is the
only rt5652 using device on which jack-detection is currently enabled.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 include/sound/rt5651.h                | 29 +++++++++++++++++++++++++++-
 sound/soc/codecs/rt5651.c             | 27 +++++++++++++++++---------
 sound/soc/codecs/rt5651.h             | 10 ++++++++++
 sound/soc/intel/boards/bytcr_rt5651.c | 36 +++++++++++++++++++++++++++++------
 4 files changed, 86 insertions(+), 16 deletions(-)

diff --git a/include/sound/rt5651.h b/include/sound/rt5651.h
index 18b79a761f10..7b000406589c 100644
--- a/include/sound/rt5651.h
+++ b/include/sound/rt5651.h
@@ -18,12 +18,39 @@ enum rt5651_jd_src {
 	RT5651_JD2,
 };
 
+/* These mirror the RT5651_MIC1_OVTH_*UA consts and MUST be in the same order */
+enum rt5651_ovth_curr {
+	RT5651_OVTH_600UA,
+	RT5651_OVTH_1500UA,
+	RT5651_OVTH_2000UA,
+};
+
+/* These mirror the RT5651_MIC_OVCD_SF* consts and MUST be in the same order */
+enum rt5651_ovcd_sf {
+	RT5651_OVCD_SF_0P5,
+	RT5651_OVCD_SF_0P75,
+	RT5651_OVCD_SF_1P0,
+	RT5651_OVCD_SF_1P5,
+};
+
+/*
+ * Note testing on various boards has shown that good defaults for ovth_curr
+ * and ovth_sf are 2000UA and 0.75. For an effective threshold of 1500UA,
+ * this seems to be more reliable then 1500UA and 1.0. Some boards may need
+ * different values because of a resistor on the board in serial with or
+ * parallel to the jack mic contact.
+ */
 struct rt5651_platform_data {
 	/* IN2 can optionally be differential */
 	bool in2_diff;
-
+	/* Configure GPIO2 as DMIC1 SCL */
 	bool dmic_en;
+	/* Jack detect source or JD_NULL to disable jack-detect */
 	enum rt5651_jd_src jd_src;
+	/* Jack micbias overcurrent detect current threshold */
+	enum rt5651_ovth_curr ovth_curr;
+	/* Jack micbias overcurrent detect current scale-factor */
+	enum rt5651_ovcd_sf ovth_sf;
 };
 
 #endif
diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c
index 4b0509f7e001..1e20cdb8b569 100644
--- a/sound/soc/codecs/rt5651.c
+++ b/sound/soc/codecs/rt5651.c
@@ -1575,6 +1575,7 @@ static int rt5651_set_jack(struct snd_soc_codec *codec,
 	regmap_update_bits(rt5651->regmap, RT5651_GPIO_CTRL1,
 			   RT5651_GP1_PIN_MASK, RT5651_GP1_PIN_IRQ);
 
+	/* Select jack detect source */
 	switch (rt5651->pdata.jd_src) {
 	case RT5651_JD1_1:
 		regmap_update_bits(rt5651->regmap, RT5651_JD_CTRL2,
@@ -1607,11 +1608,25 @@ static int rt5651_set_jack(struct snd_soc_codec *codec,
 		break;
 	}
 
+	/* Enable jack detect power */
 	regmap_update_bits(rt5651->regmap, RT5651_PWR_ANLG2, RT5651_PWR_JD_M,
 			   RT5651_PWR_JD_M);
 
+	/*
+	 * Set OVCD threshold current and scale-factor from pdata.
+	 */
+	regmap_write(rt5651->regmap, RT5651_PR_BASE + RT5651_BIAS_CUR4, 0xa800 |
+		     (rt5651->pdata.ovth_sf << RT5651_MIC_OVCD_SF_SFT));
+
 	regmap_update_bits(rt5651->regmap, RT5651_MICBIAS,
-			   0x38, 0x38);
+			   RT5651_MIC1_OVCD_MASK |
+			   RT5651_MIC1_OVTH_MASK |
+			   RT5651_PWR_CLK12M_MASK |
+			   RT5651_PWR_MB_MASK,
+			   RT5651_MIC1_OVCD_DIS |
+			   (rt5651->pdata.ovth_curr << RT5651_MIC1_OVTH_SFT) |
+			   RT5651_PWR_MB_PU |
+			   RT5651_PWR_CLK12M_PU);
 
 	ret = devm_request_threaded_irq(codec->dev, rt5651->irq, NULL,
 					rt5651_irq,
@@ -1795,14 +1810,8 @@ static int rt5651_jack_detect(struct snd_soc_codec *codec, int jack_insert)
 		snd_soc_dapm_mutex_unlock(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);
+				    RT5651_MIC1_OVCD_MASK,
+				    RT5651_MIC1_OVCD_EN);
 		msleep(100);
 		if (snd_soc_read(codec, RT5651_IRQ_CTRL2) & RT5651_MB1_OC_CLR)
 			jack_type = SND_JACK_HEADPHONE;
diff --git a/sound/soc/codecs/rt5651.h b/sound/soc/codecs/rt5651.h
index 151ac92f6bad..96168a1e87c1 100644
--- a/sound/soc/codecs/rt5651.h
+++ b/sound/soc/codecs/rt5651.h
@@ -138,6 +138,7 @@
 /* Index of Codec Private Register definition */
 #define RT5651_BIAS_CUR1			0x12
 #define RT5651_BIAS_CUR3			0x14
+#define RT5651_BIAS_CUR4			0x15
 #define RT5651_CLSD_INT_REG1			0x1c
 #define RT5651_CHPUMP_INT_REG1			0x24
 #define RT5651_MAMP_INT_REG2			0x37
@@ -1966,6 +1967,15 @@
 #define RT5651_D_GATE_EN_SFT			0
 
 /* Codec Private Register definition */
+
+/* MIC Over current threshold scale factor (0x15) */
+#define RT5651_MIC_OVCD_SF_MASK			(0x3 << 8)
+#define RT5651_MIC_OVCD_SF_SFT			8
+#define RT5651_MIC_OVCD_SF_0P5			(0x0 << 8)
+#define RT5651_MIC_OVCD_SF_0P75			(0x1 << 8)
+#define RT5651_MIC_OVCD_SF_1P0			(0x2 << 8)
+#define RT5651_MIC_OVCD_SF_1P5			(0x3 << 8)
+
 /* 3D Speaker Control (0x63) */
 #define RT5651_3D_SPK_MASK			(0x1 << 15)
 #define RT5651_3D_SPK_SFT			15
diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c
index 8ef5b5500fb7..a6cc0bc85db8 100644
--- a/sound/soc/intel/boards/bytcr_rt5651.c
+++ b/sound/soc/intel/boards/bytcr_rt5651.c
@@ -49,11 +49,26 @@ enum {
 	BYT_RT5651_JD2		= (RT5651_JD2 << 4),
 };
 
-#define BYT_RT5651_MAP(quirk)	((quirk) & GENMASK(3, 0))
-#define BYT_RT5651_JDSRC(quirk)	(((quirk) & GENMASK(7, 4)) >> 4)
-#define BYT_RT5651_DMIC_EN	BIT(16)
-#define BYT_RT5651_MCLK_EN	BIT(17)
-#define BYT_RT5651_MCLK_25MHZ	BIT(18)
+enum {
+	BYT_RT5651_OVTH_600UA	= (RT5651_OVTH_600UA << 8),
+	BYT_RT5651_OVTH_1500UA	= (RT5651_OVTH_1500UA << 8),
+	BYT_RT5651_OVTH_2000UA	= (RT5651_OVTH_2000UA << 8),
+};
+
+enum {
+	BYT_RT5651_OVCD_SF_0P5	= (RT5651_OVCD_SF_0P5 << 12),
+	BYT_RT5651_OVCD_SF_0P75	= (RT5651_OVCD_SF_0P75 << 12),
+	BYT_RT5651_OVCD_SF_1P0	= (RT5651_OVCD_SF_1P0 << 12),
+	BYT_RT5651_OVCD_SF_1P5	= (RT5651_OVCD_SF_1P5 << 12),
+};
+
+#define BYT_RT5651_MAP(quirk)		((quirk) & GENMASK(3, 0))
+#define BYT_RT5651_JDSRC(quirk)		(((quirk) & GENMASK(7, 4)) >> 4)
+#define BYT_RT5651_OVTH(quirk)		(((quirk) & GENMASK(11, 8)) >> 8)
+#define BYT_RT5651_OVCD_SF(quirk)	(((quirk) & GENMASK(15, 12)) >> 12)
+#define BYT_RT5651_DMIC_EN		BIT(16)
+#define BYT_RT5651_MCLK_EN		BIT(17)
+#define BYT_RT5651_MCLK_25MHZ		BIT(18)
 
 struct byt_rt5651_private {
 	struct clk *mclk;
@@ -73,9 +88,14 @@ static void log_quirks(struct device *dev)
 		dev_info(dev, "quirk IN2_MAP enabled");
 	if (BYT_RT5651_MAP(byt_rt5651_quirk) == BYT_RT5651_IN3_MAP)
 		dev_info(dev, "quirk IN3_MAP enabled");
-	if (BYT_RT5651_JDSRC(byt_rt5651_quirk))
+	if (BYT_RT5651_JDSRC(byt_rt5651_quirk)) {
 		dev_info(dev, "quirk jack-detect src %ld\n",
 			 BYT_RT5651_JDSRC(byt_rt5651_quirk));
+		dev_info(dev, "quirk ovth_curr %ld\n",
+			 BYT_RT5651_OVTH(byt_rt5651_quirk));
+		dev_info(dev, "quirk ovth_sf %ld\n",
+			 BYT_RT5651_OVCD_SF(byt_rt5651_quirk));
+	}
 	if (byt_rt5651_quirk & BYT_RT5651_DMIC_EN)
 		dev_info(dev, "quirk DMIC enabled");
 	if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN)
@@ -299,6 +319,8 @@ static const struct dmi_system_id byt_rt5651_quirk_table[] = {
 		},
 		.driver_data = (void *)(BYT_RT5651_MCLK_EN |
 					BYT_RT5651_JD1_1 |
+					BYT_RT5651_OVTH_2000UA |
+					BYT_RT5651_OVCD_SF_0P75 |
 					BYT_RT5651_IN1_IN2_MAP),
 	},
 	{}
@@ -373,6 +395,8 @@ static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime)
 	}
 
 	pdata.jd_src = BYT_RT5651_JDSRC(byt_rt5651_quirk);
+	pdata.ovth_curr = BYT_RT5651_OVTH(byt_rt5651_quirk);
+	pdata.ovth_sf = BYT_RT5651_OVCD_SF(byt_rt5651_quirk);
 	if (byt_rt5651_quirk & BYT_RT5651_DMIC_EN)
 		pdata.dmic_en = true;
 	rt5651_set_pdata(codec, &pdata);
-- 
2.14.3

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

* [PATCH 06/11] ASoC: rt5651: Improve headphone vs headset detection
  2018-02-20 22:15 [PATCH 01/11] ASoC: rt5651: Avoid duplicating DMI quirks between codec and machine driver Hans de Goede
                   ` (3 preceding siblings ...)
  2018-02-20 22:15 ` [PATCH 05/11] ASoC: rt5651: Allow specifying micbias over-current thresholds through pdata Hans de Goede
@ 2018-02-20 22:15 ` Hans de Goede
  2018-02-21 12:05   ` Mark Brown
  2018-02-20 22:15 ` [PATCH 07/11] ASoC: Intel: bytcr_rt5651: Configure PLL1 before using it Hans de Goede
                   ` (6 subsequent siblings)
  11 siblings, 1 reply; 35+ messages in thread
From: Hans de Goede @ 2018-02-20 22:15 UTC (permalink / raw)
  To: Mark Brown, Bard Liao
  Cc: Hans de Goede, alsa-devel, Carlo Caione, Takashi Iwai

Headphone vs headset detection relies on OVCD and testing on the rt5640 and
rt5651 (which seem to have the same OVCD detection) has shown that getting
OVCD detection to work reliabe on these codecs is somewhat finicky.

This commit ports my work to make this reliable on the rt5640 over to the
rt5651, making the following OVCD changes, each of which has been tested
individually and each of which has shown to be necessary on the rt5651:

1) When the mic-gnd contacts are short-circuited by a headphones plug, the
hardware periodically retries if it can apply the bias-current leading to
the OVCD status flip-flopping 1-0-1 with it being 0 about 10% of the time.
This commit enables the sticky bit for the OVCD status to deal with this.

2) When using RCCLK instead of MCLK / PLL1 the OVCD status often gets stuck
at its last value, force-enable the platform clock to avoid this.

3) Change the detection algorithm to require 5 identical OVCD values in a
row, as OVCD may bounce a bit after jack insertion.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
Note this is based on the jack-detection work I've been doing for the rt5640,
I took a detour and ended up fixing this for rt5651 first, the rt5640 work
is almost ready too and I hope to post a version of that upstream soon.
---
 include/sound/rt5651.h                |   4 +
 sound/soc/codecs/rt5651.c             | 237 +++++++++++++++++++++++-----------
 sound/soc/codecs/rt5651.h             |   6 +-
 sound/soc/intel/boards/bytcr_rt5651.c |   2 +
 4 files changed, 171 insertions(+), 78 deletions(-)

diff --git a/include/sound/rt5651.h b/include/sound/rt5651.h
index 7b000406589c..7122236aec60 100644
--- a/include/sound/rt5651.h
+++ b/include/sound/rt5651.h
@@ -45,12 +45,16 @@ struct rt5651_platform_data {
 	bool in2_diff;
 	/* Configure GPIO2 as DMIC1 SCL */
 	bool dmic_en;
+	/* Jack detect is inverted */
+	bool jd_inverted;
 	/* Jack detect source or JD_NULL to disable jack-detect */
 	enum rt5651_jd_src jd_src;
 	/* Jack micbias overcurrent detect current threshold */
 	enum rt5651_ovth_curr ovth_curr;
 	/* Jack micbias overcurrent detect current scale-factor */
 	enum rt5651_ovcd_sf ovth_sf;
+	/* Platform clock dapm supply name */
+	const char *clk;
 };
 
 #endif
diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c
index 1e20cdb8b569..2a2ce0a7d870 100644
--- a/sound/soc/codecs/rt5651.c
+++ b/sound/soc/codecs/rt5651.c
@@ -1552,13 +1552,153 @@ static int rt5651_set_bias_level(struct snd_soc_codec *codec,
 	return 0;
 }
 
+/*
+ * Note we do not toggle the RT5651_MIC1_OVCD_EN bit in these 2 functions,
+ * to ensure reliable OVCD operation it *must* be enabled before enabling
+ * the supplies, which may already be enabled.
+ */
+static void rt5651_enable_micbias1_ovcd(struct snd_soc_codec *codec)
+{
+	struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
+	struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
+
+	snd_soc_dapm_mutex_lock(dapm);
+	snd_soc_dapm_force_enable_pin_unlocked(dapm, "LDO");
+	snd_soc_dapm_force_enable_pin_unlocked(dapm, "micbias1");
+	/* OVCD is unreliable when used with RCCLK as sysclk-source */
+	if (rt5651->pdata.clk)
+		snd_soc_dapm_force_enable_pin_unlocked(dapm, rt5651->pdata.clk);
+	snd_soc_dapm_sync_unlocked(dapm);
+	snd_soc_dapm_mutex_unlock(dapm);
+}
+
+static void rt5651_disable_micbias1_ovcd(struct snd_soc_codec *codec)
+{
+	struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
+	struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
+
+	snd_soc_dapm_mutex_lock(dapm);
+	if (rt5651->pdata.clk)
+		snd_soc_dapm_disable_pin_unlocked(dapm, rt5651->pdata.clk);
+	snd_soc_dapm_disable_pin_unlocked(dapm, "micbias1");
+	snd_soc_dapm_disable_pin_unlocked(dapm, "LDO");
+	snd_soc_dapm_sync_unlocked(dapm);
+	snd_soc_dapm_mutex_unlock(dapm);
+}
+
+static void rt5651_clear_micbias1_ovcd(struct snd_soc_codec *codec)
+{
+	snd_soc_update_bits(codec, RT5651_IRQ_CTRL2, RT5651_MB1_OC_STATUS, 0);
+}
+
+static bool rt5651_micbias1_ovcd(struct snd_soc_codec *codec)
+{
+	int val;
+
+	val = snd_soc_read(codec, RT5651_IRQ_CTRL2);
+	dev_dbg(codec->dev, "irq ctrl2 %#04x\n", val);
+
+	return (val & RT5651_MB1_OC_STATUS);
+}
+
+static bool rt5651_jack_inserted(struct snd_soc_codec *codec)
+{
+	struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
+	int val;
+
+	val = snd_soc_read(codec, RT5651_INT_IRQ_ST);
+	dev_dbg(codec->dev, "irq status %#04x\n", val);
+
+	switch (rt5651->pdata.jd_src) {
+	case RT5651_JD1_1:
+		val &= 0x1000;
+		break;
+	case RT5651_JD1_2:
+		val &= 0x2000;
+		break;
+	case RT5651_JD2:
+		val &= 0x4000;
+		break;
+	default:
+		break;
+	}
+
+	if (rt5651->pdata.jd_inverted)
+		return val == 0;
+	else
+		return val != 0;
+}
+
+/* Jack detect and button-press timings */
+#define JACK_SETTLE_TIME	100 /* milli seconds */
+#define JACK_DETECT_COUNT	5
+#define JACK_DETECT_MAXCOUNT	20  /* Aprox. 2 seconds worth of tries */
+
+static int rt5651_detect_headset(struct snd_soc_codec *codec)
+{
+	int i, headset_count = 0, headphone_count = 0;
+
+	/*
+	 * We get the insertion event before the jack is fully inserted at which
+	 * point the second ring on a TRRS connector may short the 2nd ring and
+	 * sleeve contacts, also the overcurrent detection is not entirely
+	 * reliable. So we try several times with a wait in between until we
+	 * detect the same type JACK_DETECT_COUNT times in a row.
+	 */
+	for (i = 0; i < JACK_DETECT_MAXCOUNT; i++) {
+		/* Clear any previous over-current status flag */
+		rt5651_clear_micbias1_ovcd(codec);
+
+		msleep(JACK_SETTLE_TIME);
+
+		/* Check the jack is still connected before checking ovcd */
+		if (!rt5651_jack_inserted(codec))
+			return 0;
+
+		if (rt5651_micbias1_ovcd(codec)) {
+			/*
+			 * Over current detected, there is a short between the
+			 * 2nd ring contact and the ground, so a TRS connector
+			 * without a mic contact and thus plain headphones.
+			 */
+			dev_dbg(codec->dev, "%s: mic-gnd shorted\n", __func__);
+			headset_count = 0;
+			headphone_count++;
+			if (headphone_count == JACK_DETECT_COUNT)
+				return SND_JACK_HEADPHONE;
+		} else {
+			dev_dbg(codec->dev, "%s: mic-gnd open\n", __func__);
+			headphone_count = 0;
+			headset_count++;
+			if (headset_count == JACK_DETECT_COUNT)
+				return SND_JACK_HEADSET;
+		}
+	}
+
+	dev_err(codec->dev, "Error detecting headset vs headphones, bad contact?, assuming headphones\n");
+	return SND_JACK_HEADPHONE;
+}
+
+static void rt5651_jack_detect_work(struct work_struct *work)
+{
+	struct rt5651_priv *rt5651 =
+		container_of(work, struct rt5651_priv, jack_detect_work);
+	int report = 0;
+
+	if (rt5651_jack_inserted(rt5651->codec)) {
+		rt5651_enable_micbias1_ovcd(rt5651->codec);
+		report = rt5651_detect_headset(rt5651->codec);
+		rt5651_disable_micbias1_ovcd(rt5651->codec);
+	}
+
+	snd_soc_jack_report(rt5651->hp_jack, report, SND_JACK_HEADSET);
+}
+
 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));
-
+	queue_work(system_power_efficient_wq, &rt5651->jack_detect_work);
 	return IRQ_HANDLED;
 }
 
@@ -1614,6 +1754,8 @@ static int rt5651_set_jack(struct snd_soc_codec *codec,
 
 	/*
 	 * Set OVCD threshold current and scale-factor from pdata.
+	 * OVCD seems to be more reliable when enabled before enabling the
+	 * LDO2 / MICBIAS1 supplies, so we enable it here once.
 	 */
 	regmap_write(rt5651->regmap, RT5651_PR_BASE + RT5651_BIAS_CUR4, 0xa800 |
 		     (rt5651->pdata.ovth_sf << RT5651_MIC_OVCD_SF_SFT));
@@ -1623,11 +1765,23 @@ static int rt5651_set_jack(struct snd_soc_codec *codec,
 			   RT5651_MIC1_OVTH_MASK |
 			   RT5651_PWR_CLK12M_MASK |
 			   RT5651_PWR_MB_MASK,
-			   RT5651_MIC1_OVCD_DIS |
+			   RT5651_MIC1_OVCD_EN |
 			   (rt5651->pdata.ovth_curr << RT5651_MIC1_OVTH_SFT) |
 			   RT5651_PWR_MB_PU |
 			   RT5651_PWR_CLK12M_PU);
 
+	/*
+	 * The over-current-detect is only reliable in detecting the absence
+	 * of over-current, when the mic-contact in the jack is short-circuited,
+	 * the hardware periodically retries if it can apply the bias-current
+	 * leading to the ovcd status flip-flopping 1-0-1 with it being 0 about
+	 * 10% of the time, as we poll the ovcd status bit we might hit that
+	 * 10%, so we enable sticky mode and when checking OVCD we clear the
+	 * status, msleep() a bit and then check to get a reliable reading.
+	 */
+	snd_soc_update_bits(codec, RT5651_IRQ_CTRL2, RT5651_MB1_OC_STKY_MASK,
+			    RT5651_MB1_OC_STKY_EN);
+
 	ret = devm_request_threaded_irq(codec->dev, rt5651->irq, NULL,
 					rt5651_irq,
 					IRQF_TRIGGER_RISING |
@@ -1639,7 +1793,8 @@ static int rt5651_set_jack(struct snd_soc_codec *codec,
 	}
 
 	rt5651->hp_jack = hp_jack;
-	rt5651_irq(0, rt5651);
+	/* Get initial jack status */
+	queue_work(system_power_efficient_wq, &rt5651->jack_detect_work);
 
 	return 0;
 }
@@ -1797,74 +1952,6 @@ static int rt5651_parse_dt(struct rt5651_priv *rt5651, struct device_node *np)
 	return 0;
 }
 
-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_mutex_lock(dapm);
-		snd_soc_dapm_force_enable_pin_unlocked(dapm, "LDO");
-		snd_soc_dapm_force_enable_pin_unlocked(dapm, "micbias1");
-		snd_soc_dapm_sync_unlocked(dapm);
-		snd_soc_dapm_mutex_unlock(dapm);
-
-		snd_soc_update_bits(codec, RT5651_MICBIAS,
-				    RT5651_MIC1_OVCD_MASK,
-				    RT5651_MIC1_OVCD_EN);
-		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);
-
-		snd_soc_dapm_mutex_lock(dapm);
-		snd_soc_dapm_disable_pin_unlocked(dapm, "micbias1");
-		snd_soc_dapm_disable_pin_unlocked(dapm, "LDO");
-		snd_soc_dapm_sync_unlocked(dapm);
-		snd_soc_dapm_mutex_unlock(dapm);
-	} 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);
-}
-
 static void rt5651_apply_pdata(struct rt5651_priv *rt5651)
 {
 	if (rt5651->pdata.in2_diff)
@@ -1932,7 +2019,7 @@ static int rt5651_i2c_probe(struct i2c_client *i2c,
 
 	rt5651->irq = i2c->irq;
 	rt5651->hp_mute = 1;
-	INIT_DELAYED_WORK(&rt5651->jack_detect_work, rt5651_jack_detect_work);
+	INIT_WORK(&rt5651->jack_detect_work, rt5651_jack_detect_work);
 
 	ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5651,
 				rt5651_dai, ARRAY_SIZE(rt5651_dai));
@@ -1944,7 +2031,7 @@ 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);
+	cancel_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 96168a1e87c1..9d5f764ba467 100644
--- a/sound/soc/codecs/rt5651.h
+++ b/sound/soc/codecs/rt5651.h
@@ -1598,8 +1598,8 @@
 #define RT5651_MB1_OC_P_NOR			(0x0 << 7)
 #define RT5651_MB1_OC_P_INV			(0x1 << 7)
 #define RT5651_MB2_OC_P_MASK			(0x1 << 6)
-#define RT5651_MB1_OC_CLR			(0x1 << 3)
-#define RT5651_MB1_OC_CLR_SFT			3
+#define RT5651_MB1_OC_STATUS			(0x1 << 3)
+#define RT5651_MB1_OC_STATUS_SFT		3
 #define RT5651_STA_GPIO8			(0x1)
 #define RT5651_STA_GPIO8_BIT			0
 
@@ -2073,7 +2073,7 @@ struct rt5651_priv {
 	struct rt5651_platform_data pdata;
 	struct regmap *regmap;
 	struct snd_soc_jack *hp_jack;
-	struct delayed_work jack_detect_work;
+	struct work_struct jack_detect_work;
 
 	int irq;
 	int sysclk;
diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c
index a6cc0bc85db8..dfe5bd3dbb6c 100644
--- a/sound/soc/intel/boards/bytcr_rt5651.c
+++ b/sound/soc/intel/boards/bytcr_rt5651.c
@@ -394,6 +394,8 @@ static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime)
 			dev_err(card->dev, "unable to set MCLK rate\n");
 	}
 
+	pdata.clk = "Platform Clock";
+	pdata.jd_inverted = true;
 	pdata.jd_src = BYT_RT5651_JDSRC(byt_rt5651_quirk);
 	pdata.ovth_curr = BYT_RT5651_OVTH(byt_rt5651_quirk);
 	pdata.ovth_sf = BYT_RT5651_OVCD_SF(byt_rt5651_quirk);
-- 
2.14.3

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

* [PATCH 07/11] ASoC: Intel: bytcr_rt5651: Configure PLL1 before using it
  2018-02-20 22:15 [PATCH 01/11] ASoC: rt5651: Avoid duplicating DMI quirks between codec and machine driver Hans de Goede
                   ` (4 preceding siblings ...)
  2018-02-20 22:15 ` [PATCH 06/11] ASoC: rt5651: Improve headphone vs headset detection Hans de Goede
@ 2018-02-20 22:15 ` Hans de Goede
  2018-02-20 22:15 ` [PATCH 08/11] ASoC: Intel: bytcr_rt5651: Rename IN3_MAP to IN1_HS_IN3_MAP Hans de Goede
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 35+ messages in thread
From: Hans de Goede @ 2018-02-20 22:15 UTC (permalink / raw)
  To: Mark Brown, Bard Liao
  Cc: Hans de Goede, alsa-devel, Carlo Caione, Takashi Iwai

When platform_clock_control() first selects PLL1 as sysclk the PLL_CTRL
registers have not been setup yet and we effectively have an invalid clock
configuration until byt_rt5651_aif1_hw_params() gets called.

Add a new byt_rt5651_prepare_and_enable_pll1() helper and use that from
both platform_clock_control() and byt_rt5651_aif1_hw_params() to fix this.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 sound/soc/intel/boards/bytcr_rt5651.c | 79 ++++++++++++++++++-----------------
 1 file changed, 41 insertions(+), 38 deletions(-)

diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c
index dfe5bd3dbb6c..15df49697e97 100644
--- a/sound/soc/intel/boards/bytcr_rt5651.c
+++ b/sound/soc/intel/boards/bytcr_rt5651.c
@@ -106,6 +106,44 @@ static void log_quirks(struct device *dev)
 
 #define BYT_CODEC_DAI1	"rt5651-aif1"
 
+static int byt_rt5651_prepare_and_enable_pll1(struct snd_soc_dai *codec_dai,
+					      int rate)
+{
+	int ret;
+
+	/* Configure the PLL before selecting it */
+	if (!(byt_rt5651_quirk & BYT_RT5651_MCLK_EN)) {
+		/* 2x25 bit slots on SSP2 */
+		ret = snd_soc_dai_set_pll(codec_dai, 0,
+					  RT5651_PLL1_S_BCLK1,
+					  rate * 50, rate * 512);
+	} else {
+		if (byt_rt5651_quirk & BYT_RT5651_MCLK_25MHZ) {
+			ret = snd_soc_dai_set_pll(codec_dai, 0,
+						  RT5651_PLL1_S_MCLK,
+						  25000000, rate * 512);
+		} else {
+			ret = snd_soc_dai_set_pll(codec_dai, 0,
+						  RT5651_PLL1_S_MCLK,
+						  19200000, rate * 512);
+		}
+	}
+
+	if (ret < 0) {
+		dev_err(codec_dai->codec->dev, "can't set pll: %d\n", ret);
+		return ret;
+	}
+
+	ret = snd_soc_dai_set_sysclk(codec_dai, RT5651_SCLK_S_PLL1,
+				     rate * 512, SND_SOC_CLOCK_IN);
+	if (ret < 0) {
+		dev_err(codec_dai->codec->dev, "can't set clock %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
 static int platform_clock_control(struct snd_soc_dapm_widget *w,
 				  struct snd_kcontrol *k, int  event)
 {
@@ -131,9 +169,7 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w,
 				return ret;
 			}
 		}
-		ret = snd_soc_dai_set_sysclk(codec_dai, RT5651_SCLK_S_PLL1,
-					     48000 * 512,
-					     SND_SOC_CLOCK_IN);
+		ret = byt_rt5651_prepare_and_enable_pll1(codec_dai, 48000);
 	} else {
 		/*
 		 * Set codec clock source to internal clock before
@@ -247,44 +283,11 @@ static int byt_rt5651_aif1_hw_params(struct snd_pcm_substream *substream,
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	int ret;
+	int rate = params_rate(params);
 
 	snd_soc_dai_set_bclk_ratio(codec_dai, 50);
 
-	ret = snd_soc_dai_set_sysclk(codec_dai, RT5651_SCLK_S_PLL1,
-				     params_rate(params) * 512,
-				     SND_SOC_CLOCK_IN);
-	if (ret < 0) {
-		dev_err(rtd->dev, "can't set codec clock %d\n", ret);
-		return ret;
-	}
-
-	if (!(byt_rt5651_quirk & BYT_RT5651_MCLK_EN)) {
-		/* 2x25 bit slots on SSP2 */
-		ret = snd_soc_dai_set_pll(codec_dai, 0,
-					RT5651_PLL1_S_BCLK1,
-					params_rate(params) * 50,
-					params_rate(params) * 512);
-	} else {
-		if (byt_rt5651_quirk & BYT_RT5651_MCLK_25MHZ) {
-			ret = snd_soc_dai_set_pll(codec_dai, 0,
-						RT5651_PLL1_S_MCLK,
-						25000000,
-						params_rate(params) * 512);
-		} else {
-			ret = snd_soc_dai_set_pll(codec_dai, 0,
-						RT5651_PLL1_S_MCLK,
-						19200000,
-						params_rate(params) * 512);
-		}
-	}
-
-	if (ret < 0) {
-		dev_err(rtd->dev, "can't set codec pll: %d\n", ret);
-		return ret;
-	}
-
-	return 0;
+	return byt_rt5651_prepare_and_enable_pll1(codec_dai, rate);
 }
 
 static int byt_rt5651_quirk_cb(const struct dmi_system_id *id)
-- 
2.14.3

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

* [PATCH 08/11] ASoC: Intel: bytcr_rt5651: Rename IN3_MAP to IN1_HS_IN3_MAP
  2018-02-20 22:15 [PATCH 01/11] ASoC: rt5651: Avoid duplicating DMI quirks between codec and machine driver Hans de Goede
                   ` (5 preceding siblings ...)
  2018-02-20 22:15 ` [PATCH 07/11] ASoC: Intel: bytcr_rt5651: Configure PLL1 before using it Hans de Goede
@ 2018-02-20 22:15 ` Hans de Goede
  2018-02-20 22:15 ` [PATCH 09/11] ASoC: Intel: bytcr_rt5651: Add new IN2_HS_IN3 input map and a quirk using it Hans de Goede
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 35+ messages in thread
From: Hans de Goede @ 2018-02-20 22:15 UTC (permalink / raw)
  To: Mark Brown, Bard Liao
  Cc: Hans de Goede, alsa-devel, Carlo Caione, Takashi Iwai

All the mappings are named for where the internal mic is routed and in that
sense the newly added in3_map really is the same as in1_map, what makes it
different is that it maps the headset mic at IN3 rather then at IN2.

Rename in3_map to in1_hs_in3_map to better reflect what it actually does.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 sound/soc/intel/boards/bytcr_rt5651.c | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c
index 15df49697e97..608a3339d523 100644
--- a/sound/soc/intel/boards/bytcr_rt5651.c
+++ b/sound/soc/intel/boards/bytcr_rt5651.c
@@ -39,7 +39,7 @@ enum {
 	BYT_RT5651_IN1_MAP,
 	BYT_RT5651_IN2_MAP,
 	BYT_RT5651_IN1_IN2_MAP,
-	BYT_RT5651_IN3_MAP,
+	BYT_RT5651_IN1_HS_IN3_MAP,
 };
 
 enum {
@@ -86,8 +86,8 @@ static void log_quirks(struct device *dev)
 		dev_info(dev, "quirk IN1_MAP enabled");
 	if (BYT_RT5651_MAP(byt_rt5651_quirk) == BYT_RT5651_IN2_MAP)
 		dev_info(dev, "quirk IN2_MAP enabled");
-	if (BYT_RT5651_MAP(byt_rt5651_quirk) == BYT_RT5651_IN3_MAP)
-		dev_info(dev, "quirk IN3_MAP enabled");
+	if (BYT_RT5651_MAP(byt_rt5651_quirk) == BYT_RT5651_IN1_HS_IN3_MAP)
+		dev_info(dev, "quirk IN1_HS_IN3_MAP enabled");
 	if (BYT_RT5651_JDSRC(byt_rt5651_quirk)) {
 		dev_info(dev, "quirk jack-detect src %ld\n",
 			 BYT_RT5651_JDSRC(byt_rt5651_quirk));
@@ -236,8 +236,8 @@ static const struct snd_soc_dapm_route byt_rt5651_intmic_dmic_map[] = {
 
 static const struct snd_soc_dapm_route byt_rt5651_intmic_in1_map[] = {
 	{"Internal Mic", NULL, "micbias1"},
-	{"IN2P", NULL, "Headset Mic"},
 	{"IN1P", NULL, "Internal Mic"},
+	{"IN2P", NULL, "Headset Mic"},
 };
 
 static const struct snd_soc_dapm_route byt_rt5651_intmic_in2_map[] = {
@@ -253,10 +253,10 @@ static const struct snd_soc_dapm_route byt_rt5651_intmic_in1_in2_map[] = {
 	{"IN3P", NULL, "Headset Mic"},
 };
 
-static const struct snd_soc_dapm_route byt_rt5651_intmic_in3_map[] = {
+static const struct snd_soc_dapm_route byt_rt5651_intmic_in1_hs_in3_map[] = {
 	{"Internal Mic", NULL, "micbias1"},
-	{"IN3P", NULL, "Headset Mic"},
 	{"IN1P", NULL, "Internal Mic"},
+	{"IN3P", NULL, "Headset Mic"},
 };
 
 static const struct snd_kcontrol_new byt_rt5651_controls[] = {
@@ -303,7 +303,7 @@ static const struct dmi_system_id byt_rt5651_quirk_table[] = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Circuitco"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "Minnowboard Max B3 PLATFORM"),
 		},
-		.driver_data = (void *)(BYT_RT5651_IN3_MAP),
+		.driver_data = (void *)(BYT_RT5651_IN1_HS_IN3_MAP),
 	},
 	{
 		.callback = byt_rt5651_quirk_cb,
@@ -312,7 +312,7 @@ static const struct dmi_system_id byt_rt5651_quirk_table[] = {
 			DMI_MATCH(DMI_PRODUCT_NAME, "Minnowboard Turbot"),
 		},
 		.driver_data = (void *)(BYT_RT5651_MCLK_EN |
-					BYT_RT5651_IN3_MAP),
+					BYT_RT5651_IN1_HS_IN3_MAP),
 	},
 	{
 		.callback = byt_rt5651_quirk_cb,
@@ -354,9 +354,9 @@ static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime)
 		custom_map = byt_rt5651_intmic_in1_in2_map;
 		num_routes = ARRAY_SIZE(byt_rt5651_intmic_in1_in2_map);
 		break;
-	case BYT_RT5651_IN3_MAP:
-		custom_map = byt_rt5651_intmic_in3_map;
-		num_routes = ARRAY_SIZE(byt_rt5651_intmic_in3_map);
+	case BYT_RT5651_IN1_HS_IN3_MAP:
+		custom_map = byt_rt5651_intmic_in1_hs_in3_map;
+		num_routes = ARRAY_SIZE(byt_rt5651_intmic_in1_hs_in3_map);
 		break;
 	default:
 		custom_map = byt_rt5651_intmic_dmic_map;
-- 
2.14.3

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

* [PATCH 09/11] ASoC: Intel: bytcr_rt5651: Add new IN2_HS_IN3 input map and a quirk using it
  2018-02-20 22:15 [PATCH 01/11] ASoC: rt5651: Avoid duplicating DMI quirks between codec and machine driver Hans de Goede
                   ` (6 preceding siblings ...)
  2018-02-20 22:15 ` [PATCH 08/11] ASoC: Intel: bytcr_rt5651: Rename IN3_MAP to IN1_HS_IN3_MAP Hans de Goede
@ 2018-02-20 22:15 ` Hans de Goede
  2018-02-20 22:15 ` [PATCH 10/11] ASoC: Intel: bytcr_rt5651: Add support for Bay Trail CR / SSP0 using boards Hans de Goede
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 35+ messages in thread
From: Hans de Goede @ 2018-02-20 22:15 UTC (permalink / raw)
  To: Mark Brown, Bard Liao
  Cc: Hans de Goede, alsa-devel, Carlo Caione, Takashi Iwai

Add a new IN2_HS_IN3 input map and add a quirk for the input mapping and
jack-detect source for the Chuwi Vi8 Plus tablet, which uses this new map.

Note the Chuwi Vi8 Plus lists an extra GPIO in its codecs ACPI resources
which needs to be driven high to enable the external speaker amplifier,
this is not supported yet and will be fixed in a future patch.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 sound/soc/intel/boards/bytcr_rt5651.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c
index 608a3339d523..9a23ac9172b4 100644
--- a/sound/soc/intel/boards/bytcr_rt5651.c
+++ b/sound/soc/intel/boards/bytcr_rt5651.c
@@ -40,6 +40,7 @@ enum {
 	BYT_RT5651_IN2_MAP,
 	BYT_RT5651_IN1_IN2_MAP,
 	BYT_RT5651_IN1_HS_IN3_MAP,
+	BYT_RT5651_IN2_HS_IN3_MAP,
 };
 
 enum {
@@ -88,6 +89,8 @@ static void log_quirks(struct device *dev)
 		dev_info(dev, "quirk IN2_MAP enabled");
 	if (BYT_RT5651_MAP(byt_rt5651_quirk) == BYT_RT5651_IN1_HS_IN3_MAP)
 		dev_info(dev, "quirk IN1_HS_IN3_MAP enabled");
+	if (BYT_RT5651_MAP(byt_rt5651_quirk) == BYT_RT5651_IN2_HS_IN3_MAP)
+		dev_info(dev, "quirk IN2_HS_IN3_MAP enabled");
 	if (BYT_RT5651_JDSRC(byt_rt5651_quirk)) {
 		dev_info(dev, "quirk jack-detect src %ld\n",
 			 BYT_RT5651_JDSRC(byt_rt5651_quirk));
@@ -259,6 +262,12 @@ static const struct snd_soc_dapm_route byt_rt5651_intmic_in1_hs_in3_map[] = {
 	{"IN3P", NULL, "Headset Mic"},
 };
 
+static const struct snd_soc_dapm_route byt_rt5651_intmic_in2_hs_in3_map[] = {
+	{"Internal Mic", NULL, "micbias1"},
+	{"IN2P", NULL, "Internal Mic"},
+	{"IN3P", NULL, "Headset Mic"},
+};
+
 static const struct snd_kcontrol_new byt_rt5651_controls[] = {
 	SOC_DAPM_PIN_SWITCH("Headphone"),
 	SOC_DAPM_PIN_SWITCH("Headset Mic"),
@@ -326,6 +335,19 @@ static const struct dmi_system_id byt_rt5651_quirk_table[] = {
 					BYT_RT5651_OVCD_SF_0P75 |
 					BYT_RT5651_IN1_IN2_MAP),
 	},
+	{
+		/* Chuwi Vi8 Plus (CWI519) */
+		.callback = byt_rt5651_quirk_cb,
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Hampoo"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "D2D3_Vi8A1"),
+		},
+		.driver_data = (void *)(BYT_RT5651_MCLK_EN |
+					BYT_RT5651_JD1_1 |
+					BYT_RT5651_OVTH_2000UA |
+					BYT_RT5651_OVCD_SF_0P75 |
+					BYT_RT5651_IN2_HS_IN3_MAP),
+	},
 	{}
 };
 
@@ -358,6 +380,10 @@ static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime)
 		custom_map = byt_rt5651_intmic_in1_hs_in3_map;
 		num_routes = ARRAY_SIZE(byt_rt5651_intmic_in1_hs_in3_map);
 		break;
+	case BYT_RT5651_IN2_HS_IN3_MAP:
+		custom_map = byt_rt5651_intmic_in2_hs_in3_map;
+		num_routes = ARRAY_SIZE(byt_rt5651_intmic_in2_hs_in3_map);
+		break;
 	default:
 		custom_map = byt_rt5651_intmic_dmic_map;
 		num_routes = ARRAY_SIZE(byt_rt5651_intmic_dmic_map);
-- 
2.14.3

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

* [PATCH 10/11] ASoC: Intel: bytcr_rt5651: Add support for Bay Trail CR / SSP0 using boards
  2018-02-20 22:15 [PATCH 01/11] ASoC: rt5651: Avoid duplicating DMI quirks between codec and machine driver Hans de Goede
                   ` (7 preceding siblings ...)
  2018-02-20 22:15 ` [PATCH 09/11] ASoC: Intel: bytcr_rt5651: Add new IN2_HS_IN3 input map and a quirk using it Hans de Goede
@ 2018-02-20 22:15 ` Hans de Goede
  2018-02-20 22:44   ` Pierre-Louis Bossart
  2018-02-20 22:15 ` [PATCH 11/11] ASoC: Intel: bytcr_rt5651: Add quirk for the VIOS LTH17 laptop Hans de Goede
                   ` (2 subsequent siblings)
  11 siblings, 1 reply; 35+ messages in thread
From: Hans de Goede @ 2018-02-20 22:15 UTC (permalink / raw)
  To: Mark Brown, Bard Liao
  Cc: Hans de Goede, alsa-devel, Carlo Caione, Takashi Iwai

Despite its name being prefixed with bytcr, before this commit the
bytcr_rt5651 machine driver could not work with Bay Trail CR boards,
as those only have SSP0 and it only supported SSP0-AIF1 setups.

This commit adds support for this, autodetecting AIF1 vs AIF2 based on
BIOS tables.

While at it also add support for SSP2-AIF2 setups, as that requires only
minimal extra code on top of the code adding SSP0-AIF1 / SSP0-AIF2 support.

Note this code is all copy-pasted from bytcr_rt5640.c. I've looked into
merging the 2 machine drivers into 1 to avoid copy-pasting, but there are
enough subtile differences to make this hard *and* with all the quirks the
machine driver already is full with if (variant-foo) then ... else ...
constructs adding more of these is going to make the code unreadable.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 sound/soc/intel/boards/bytcr_rt5651.c | 225 +++++++++++++++++++++++++++++++---
 1 file changed, 206 insertions(+), 19 deletions(-)

diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c
index 9a23ac9172b4..c14c5940ff87 100644
--- a/sound/soc/intel/boards/bytcr_rt5651.c
+++ b/sound/soc/intel/boards/bytcr_rt5651.c
@@ -25,6 +25,7 @@
 #include <linux/device.h>
 #include <linux/dmi.h>
 #include <linux/slab.h>
+#include <asm/cpu_device_id.h>
 #include <asm/platform_sst_audio.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -70,14 +71,16 @@ enum {
 #define BYT_RT5651_DMIC_EN		BIT(16)
 #define BYT_RT5651_MCLK_EN		BIT(17)
 #define BYT_RT5651_MCLK_25MHZ		BIT(18)
+#define BYT_RT5651_SSP2_AIF2		BIT(19) /* default is using AIF1  */
+#define BYT_RT5651_SSP0_AIF1		BIT(20)
+#define BYT_RT5651_SSP0_AIF2		BIT(21)
 
 struct byt_rt5651_private {
 	struct clk *mclk;
 	struct snd_soc_jack jack;
 };
 
-static unsigned long byt_rt5651_quirk = BYT_RT5651_DMIC_MAP |
-					BYT_RT5651_MCLK_EN;
+static unsigned long byt_rt5651_quirk = BYT_RT5651_MCLK_EN;
 
 static void log_quirks(struct device *dev)
 {
@@ -105,9 +108,16 @@ static void log_quirks(struct device *dev)
 		dev_info(dev, "quirk MCLK_EN enabled");
 	if (byt_rt5651_quirk & BYT_RT5651_MCLK_25MHZ)
 		dev_info(dev, "quirk MCLK_25MHZ enabled");
+	if (byt_rt5651_quirk & BYT_RT5651_SSP2_AIF2)
+		dev_info(dev, "quirk SSP2_AIF2 enabled\n");
+	if (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF1)
+		dev_info(dev, "quirk SSP0_AIF1 enabled\n");
+	if (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2)
+		dev_info(dev, "quirk SSP0_AIF2 enabled\n");
 }
 
 #define BYT_CODEC_DAI1	"rt5651-aif1"
+#define BYT_CODEC_DAI2	"rt5651-aif2"
 
 static int byt_rt5651_prepare_and_enable_pll1(struct snd_soc_dai *codec_dai,
 					      int rate)
@@ -116,10 +126,19 @@ static int byt_rt5651_prepare_and_enable_pll1(struct snd_soc_dai *codec_dai,
 
 	/* Configure the PLL before selecting it */
 	if (!(byt_rt5651_quirk & BYT_RT5651_MCLK_EN)) {
-		/* 2x25 bit slots on SSP2 */
-		ret = snd_soc_dai_set_pll(codec_dai, 0,
-					  RT5651_PLL1_S_BCLK1,
-					  rate * 50, rate * 512);
+		/* use bitclock as PLL input */
+		if ((byt_rt5651_quirk & BYT_RT5651_SSP0_AIF1) ||
+		    (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2)) {
+			/* 2x16 bit slots on SSP0 */
+			ret = snd_soc_dai_set_pll(codec_dai, 0,
+						  RT5651_PLL1_S_BCLK1,
+						  rate * 32, rate * 512);
+		} else {
+			/* 2x25 bit slots on SSP2 */
+			ret = snd_soc_dai_set_pll(codec_dai, 0,
+						  RT5651_PLL1_S_BCLK1,
+						  rate * 50, rate * 512);
+		}
 	} else {
 		if (byt_rt5651_quirk & BYT_RT5651_MCLK_25MHZ) {
 			ret = snd_soc_dai_set_pll(codec_dai, 0,
@@ -157,6 +176,8 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w,
 	int ret;
 
 	codec_dai = snd_soc_card_get_codec_dai(card, BYT_CODEC_DAI1);
+	if (!codec_dai)
+		codec_dai = snd_soc_card_get_codec_dai(card, BYT_CODEC_DAI2);
 	if (!codec_dai) {
 		dev_err(card->dev,
 			"Codec dai not found; Unable to set platform clock\n");
@@ -214,13 +235,6 @@ static const struct snd_soc_dapm_route byt_rt5651_audio_map[] = {
 	{"Speaker", NULL, "Platform Clock"},
 	{"Line In", NULL, "Platform Clock"},
 
-	{"AIF1 Playback", NULL, "ssp2 Tx"},
-	{"ssp2 Tx", NULL, "codec_out0"},
-	{"ssp2 Tx", NULL, "codec_out1"},
-	{"codec_in0", NULL, "ssp2 Rx"},
-	{"codec_in1", NULL, "ssp2 Rx"},
-	{"ssp2 Rx", NULL, "AIF1 Capture"},
-
 	{"Headset Mic", NULL, "micbias1"}, /* lowercase for rt5651 */
 	{"Headphone", NULL, "HPOL"},
 	{"Headphone", NULL, "HPOR"},
@@ -268,6 +282,42 @@ static const struct snd_soc_dapm_route byt_rt5651_intmic_in2_hs_in3_map[] = {
 	{"IN3P", NULL, "Headset Mic"},
 };
 
+static const struct snd_soc_dapm_route byt_rt5651_ssp0_aif1_map[] = {
+	{"ssp0 Tx", NULL, "modem_out"},
+	{"modem_in", NULL, "ssp0 Rx"},
+
+	{"AIF1 Playback", NULL, "ssp0 Tx"},
+	{"ssp0 Rx", NULL, "AIF1 Capture"},
+};
+
+static const struct snd_soc_dapm_route byt_rt5651_ssp0_aif2_map[] = {
+	{"ssp0 Tx", NULL, "modem_out"},
+	{"modem_in", NULL, "ssp0 Rx"},
+
+	{"AIF2 Playback", NULL, "ssp0 Tx"},
+	{"ssp0 Rx", NULL, "AIF2 Capture"},
+};
+
+static const struct snd_soc_dapm_route byt_rt5651_ssp2_aif1_map[] = {
+	{"ssp2 Tx", NULL, "codec_out0"},
+	{"ssp2 Tx", NULL, "codec_out1"},
+	{"codec_in0", NULL, "ssp2 Rx"},
+	{"codec_in1", NULL, "ssp2 Rx"},
+
+	{"AIF1 Playback", NULL, "ssp2 Tx"},
+	{"ssp2 Rx", NULL, "AIF1 Capture"},
+};
+
+static const struct snd_soc_dapm_route byt_rt5651_ssp2_aif2_map[] = {
+	{"ssp2 Tx", NULL, "codec_out0"},
+	{"ssp2 Tx", NULL, "codec_out1"},
+	{"codec_in0", NULL, "ssp2 Rx"},
+	{"codec_in1", NULL, "ssp2 Rx"},
+
+	{"AIF2 Playback", NULL, "ssp2 Tx"},
+	{"ssp2 Rx", NULL, "AIF2 Capture"},
+};
+
 static const struct snd_kcontrol_new byt_rt5651_controls[] = {
 	SOC_DAPM_PIN_SWITCH("Headphone"),
 	SOC_DAPM_PIN_SWITCH("Headset Mic"),
@@ -392,6 +442,26 @@ static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime)
 	if (ret)
 		return ret;
 
+	if (byt_rt5651_quirk & BYT_RT5651_SSP2_AIF2) {
+		ret = snd_soc_dapm_add_routes(&card->dapm,
+					byt_rt5651_ssp2_aif2_map,
+					ARRAY_SIZE(byt_rt5651_ssp2_aif2_map));
+	} else if (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF1) {
+		ret = snd_soc_dapm_add_routes(&card->dapm,
+					byt_rt5651_ssp0_aif1_map,
+					ARRAY_SIZE(byt_rt5651_ssp0_aif1_map));
+	} else if (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2) {
+		ret = snd_soc_dapm_add_routes(&card->dapm,
+					byt_rt5651_ssp0_aif2_map,
+					ARRAY_SIZE(byt_rt5651_ssp0_aif2_map));
+	} else {
+		ret = snd_soc_dapm_add_routes(&card->dapm,
+					byt_rt5651_ssp2_aif1_map,
+					ARRAY_SIZE(byt_rt5651_ssp2_aif1_map));
+	}
+	if (ret)
+		return ret;
+
 	ret = snd_soc_add_card_controls(card, byt_rt5651_controls,
 					ARRAY_SIZE(byt_rt5651_controls));
 	if (ret) {
@@ -464,18 +534,26 @@ static int byt_rt5651_codec_fixup(struct snd_soc_pcm_runtime *rtd,
 			SNDRV_PCM_HW_PARAM_RATE);
 	struct snd_interval *channels = hw_param_interval(params,
 						SNDRV_PCM_HW_PARAM_CHANNELS);
-	int ret;
+	int ret, bits;
 
-	/* The DSP will covert the FE rate to 48k, stereo, 24bits */
+	/* The DSP will covert the FE rate to 48k, stereo */
 	rate->min = rate->max = 48000;
 	channels->min = channels->max = 2;
 
-	/* set SSP2 to 24-bit */
-	params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
+	if ((byt_rt5651_quirk & BYT_RT5651_SSP0_AIF1) ||
+	    (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2)) {
+		/* set SSP0 to 16-bit */
+		params_set_format(params, SNDRV_PCM_FORMAT_S16_LE);
+		bits = 16;
+	} else {
+		/* set SSP2 to 24-bit */
+		params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
+		bits = 24;
+	}
 
 	/*
 	 * Default mode for SSP configuration is TDM 4 slot, override config
-	 * with explicit setting to I2S 2ch 24-bit. The word length is set with
+	 * with explicit setting to I2S 2ch. The word length is set with
 	 * dai_set_tdm_slot() since there is no other API exposed
 	 */
 	ret = snd_soc_dai_set_fmt(rtd->cpu_dai,
@@ -489,7 +567,7 @@ static int byt_rt5651_codec_fixup(struct snd_soc_pcm_runtime *rtd,
 		return ret;
 	}
 
-	ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 24);
+	ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, bits);
 	if (ret < 0) {
 		dev_err(rtd->dev, "can't set I2S config, err %d\n", ret);
 		return ret;
@@ -583,12 +661,32 @@ static struct snd_soc_card byt_rt5651_card = {
 };
 
 static char byt_rt5651_codec_name[SND_ACPI_I2C_ID_LEN];
+static char byt_rt5651_codec_aif_name[12]; /*  = "rt5651-aif[1|2]" */
+static char byt_rt5651_cpu_dai_name[10]; /*  = "ssp[0|2]-port" */
+
+static bool is_valleyview(void)
+{
+	static const struct x86_cpu_id cpu_ids[] = {
+		{ X86_VENDOR_INTEL, 6, 55 }, /* Valleyview, Bay Trail */
+		{}
+	};
+
+	if (!x86_match_cpu(cpu_ids))
+		return false;
+	return true;
+}
+
+struct acpi_chan_package {   /* ACPICA seems to require 64 bit integers */
+	u64 aif_value;       /* 1: AIF1, 2: AIF2 */
+	u64 mclock_value;    /* usually 25MHz (0x17d7940), ignored */
+};
 
 static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
 {
 	struct byt_rt5651_private *priv;
 	struct snd_soc_acpi_mach *mach;
 	const char *i2c_name = NULL;
+	bool is_bytcr = false;
 	int ret_val = 0;
 	int dai_index = 0;
 	int i;
@@ -620,10 +718,99 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
 		byt_rt5651_dais[dai_index].codec_name = byt_rt5651_codec_name;
 	}
 
+	/*
+	 * swap SSP0 if bytcr is detected
+	 * (will be overridden if DMI quirk is detected)
+	 */
+	if (is_valleyview()) {
+		struct sst_platform_info *p_info = mach->pdata;
+		const struct sst_res_info *res_info = p_info->res_info;
+
+		if (res_info->acpi_ipc_irq_index == 0)
+			is_bytcr = true;
+	}
+
+	if (is_bytcr) {
+		/*
+		 * Baytrail CR platforms may have CHAN package in BIOS, try
+		 * to find relevant routing quirk based as done on Windows
+		 * platforms. We have to read the information directly from the
+		 * BIOS, at this stage the card is not created and the links
+		 * with the codec driver/pdata are non-existent
+		 */
+
+		struct acpi_chan_package chan_package;
+
+		/* format specified: 2 64-bit integers */
+		struct acpi_buffer format = {sizeof("NN"), "NN"};
+		struct acpi_buffer state = {0, NULL};
+		struct snd_soc_acpi_package_context pkg_ctx;
+		bool pkg_found = false;
+
+		state.length = sizeof(chan_package);
+		state.pointer = &chan_package;
+
+		pkg_ctx.name = "CHAN";
+		pkg_ctx.length = 2;
+		pkg_ctx.format = &format;
+		pkg_ctx.state = &state;
+		pkg_ctx.data_valid = false;
+
+		pkg_found = snd_soc_acpi_find_package_from_hid(mach->id,
+							       &pkg_ctx);
+		if (pkg_found) {
+			if (chan_package.aif_value == 1) {
+				dev_info(&pdev->dev, "BIOS Routing: AIF1 connected\n");
+				byt_rt5651_quirk |= BYT_RT5651_SSP0_AIF1;
+			} else  if (chan_package.aif_value == 2) {
+				dev_info(&pdev->dev, "BIOS Routing: AIF2 connected\n");
+				byt_rt5651_quirk |= BYT_RT5651_SSP0_AIF2;
+			} else {
+				dev_info(&pdev->dev, "BIOS Routing isn't valid, ignored\n");
+				pkg_found = false;
+			}
+		}
+
+		if (!pkg_found) {
+			/* no BIOS indications, assume SSP0-AIF2 connection */
+			byt_rt5651_quirk |= BYT_RT5651_SSP0_AIF2;
+		}
+
+		/* change defaults for Baytrail-CR capture */
+		byt_rt5651_quirk |= BYT_RT5651_JD1_1 |
+				    BYT_RT5651_OVTH_2000UA |
+				    BYT_RT5651_OVCD_SF_0P75 |
+				    BYT_RT5651_IN2_HS_IN3_MAP;
+	} else {
+		byt_rt5651_quirk |= BYT_RT5651_DMIC_MAP;
+	}
+
 	/* check quirks before creating card */
 	dmi_check_system(byt_rt5651_quirk_table);
 	log_quirks(&pdev->dev);
 
+	if ((byt_rt5651_quirk & BYT_RT5651_SSP2_AIF2) ||
+	    (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2)) {
+		/* fixup codec aif name */
+		snprintf(byt_rt5651_codec_aif_name,
+			sizeof(byt_rt5651_codec_aif_name),
+			"%s", "rt5651-aif2");
+
+		byt_rt5651_dais[dai_index].codec_dai_name =
+			byt_rt5651_codec_aif_name;
+	}
+
+	if ((byt_rt5651_quirk & BYT_RT5651_SSP0_AIF1) ||
+	    (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2)) {
+		/* fixup cpu dai name name */
+		snprintf(byt_rt5651_cpu_dai_name,
+			sizeof(byt_rt5651_cpu_dai_name),
+			"%s", "ssp0-port");
+
+		byt_rt5651_dais[dai_index].cpu_dai_name =
+			byt_rt5651_cpu_dai_name;
+	}
+
 	if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN) {
 		priv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
 		if (IS_ERR(priv->mclk)) {
-- 
2.14.3

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

* [PATCH 11/11] ASoC: Intel: bytcr_rt5651: Add quirk for the VIOS LTH17 laptop
  2018-02-20 22:15 [PATCH 01/11] ASoC: rt5651: Avoid duplicating DMI quirks between codec and machine driver Hans de Goede
                   ` (8 preceding siblings ...)
  2018-02-20 22:15 ` [PATCH 10/11] ASoC: Intel: bytcr_rt5651: Add support for Bay Trail CR / SSP0 using boards Hans de Goede
@ 2018-02-20 22:15 ` Hans de Goede
  2018-02-21 11:54 ` [PATCH 01/11] ASoC: rt5651: Avoid duplicating DMI quirks between codec and machine driver Mark Brown
  2018-02-21 17:36 ` Carlo Caione
  11 siblings, 0 replies; 35+ messages in thread
From: Hans de Goede @ 2018-02-20 22:15 UTC (permalink / raw)
  To: Mark Brown, Bard Liao
  Cc: Hans de Goede, alsa-devel, Carlo Caione, Takashi Iwai

Add a quirk setting up jack-detect and input routing for the
VIOS LTH17 laptop.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 sound/soc/intel/boards/bytcr_rt5651.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c
index c14c5940ff87..c4260ca3cbed 100644
--- a/sound/soc/intel/boards/bytcr_rt5651.c
+++ b/sound/soc/intel/boards/bytcr_rt5651.c
@@ -398,6 +398,19 @@ static const struct dmi_system_id byt_rt5651_quirk_table[] = {
 					BYT_RT5651_OVCD_SF_0P75 |
 					BYT_RT5651_IN2_HS_IN3_MAP),
 	},
+	{
+		/* VIOS LTH17 */
+		.callback = byt_rt5651_quirk_cb,
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "VIOS"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "LTH17"),
+		},
+		.driver_data = (void *)(BYT_RT5651_MCLK_EN |
+					BYT_RT5651_JD1_1 |
+					BYT_RT5651_OVTH_2000UA |
+					BYT_RT5651_OVCD_SF_1P0 |
+					BYT_RT5651_IN1_IN2_MAP),
+	},
 	{}
 };
 
-- 
2.14.3

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

* Re: [PATCH 10/11] ASoC: Intel: bytcr_rt5651: Add support for Bay Trail CR / SSP0 using boards
  2018-02-20 22:15 ` [PATCH 10/11] ASoC: Intel: bytcr_rt5651: Add support for Bay Trail CR / SSP0 using boards Hans de Goede
@ 2018-02-20 22:44   ` Pierre-Louis Bossart
  2018-02-24 11:52     ` Hans de Goede
  0 siblings, 1 reply; 35+ messages in thread
From: Pierre-Louis Bossart @ 2018-02-20 22:44 UTC (permalink / raw)
  To: Hans de Goede, Mark Brown, Bard Liao
  Cc: alsa-devel, Carlo Caione, Takashi Iwai

On 2/20/18 4:15 PM, Hans de Goede wrote:
> Despite its name being prefixed with bytcr, before this commit the
> bytcr_rt5651 machine driver could not work with Bay Trail CR boards,
> as those only have SSP0 and it only supported SSP0-AIF1 setups.
> 
> This commit adds support for this, autodetecting AIF1 vs AIF2 based on
> BIOS tables.
> 
> While at it also add support for SSP2-AIF2 setups, as that requires only
> minimal extra code on top of the code adding SSP0-AIF1 / SSP0-AIF2 support.
> 
> Note this code is all copy-pasted from bytcr_rt5640.c. I've looked into
> merging the 2 machine drivers into 1 to avoid copy-pasting, but there are
> enough subtile differences to make this hard *and* with all the quirks the
> machine driver already is full with if (variant-foo) then ... else ...
> constructs adding more of these is going to make the code unreadable.
> 
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> ---
>   sound/soc/intel/boards/bytcr_rt5651.c | 225 +++++++++++++++++++++++++++++++---
>   1 file changed, 206 insertions(+), 19 deletions(-)
> 
> diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c
> index 9a23ac9172b4..c14c5940ff87 100644
> --- a/sound/soc/intel/boards/bytcr_rt5651.c
> +++ b/sound/soc/intel/boards/bytcr_rt5651.c
> @@ -25,6 +25,7 @@
>   #include <linux/device.h>
>   #include <linux/dmi.h>
>   #include <linux/slab.h>
> +#include <asm/cpu_device_id.h>
>   #include <asm/platform_sst_audio.h>
>   #include <sound/pcm.h>
>   #include <sound/pcm_params.h>
> @@ -70,14 +71,16 @@ enum {
>   #define BYT_RT5651_DMIC_EN		BIT(16)
>   #define BYT_RT5651_MCLK_EN		BIT(17)
>   #define BYT_RT5651_MCLK_25MHZ		BIT(18)
> +#define BYT_RT5651_SSP2_AIF2		BIT(19) /* default is using AIF1  */
> +#define BYT_RT5651_SSP0_AIF1		BIT(20)
> +#define BYT_RT5651_SSP0_AIF2		BIT(21)
>   
>   struct byt_rt5651_private {
>   	struct clk *mclk;
>   	struct snd_soc_jack jack;
>   };
>   
> -static unsigned long byt_rt5651_quirk = BYT_RT5651_DMIC_MAP |
> -					BYT_RT5651_MCLK_EN;
> +static unsigned long byt_rt5651_quirk = BYT_RT5651_MCLK_EN;
>   
>   static void log_quirks(struct device *dev)
>   {
> @@ -105,9 +108,16 @@ static void log_quirks(struct device *dev)
>   		dev_info(dev, "quirk MCLK_EN enabled");
>   	if (byt_rt5651_quirk & BYT_RT5651_MCLK_25MHZ)
>   		dev_info(dev, "quirk MCLK_25MHZ enabled");
> +	if (byt_rt5651_quirk & BYT_RT5651_SSP2_AIF2)
> +		dev_info(dev, "quirk SSP2_AIF2 enabled\n");
> +	if (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF1)
> +		dev_info(dev, "quirk SSP0_AIF1 enabled\n");
> +	if (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2)
> +		dev_info(dev, "quirk SSP0_AIF2 enabled\n");
>   }
>   
>   #define BYT_CODEC_DAI1	"rt5651-aif1"
> +#define BYT_CODEC_DAI2	"rt5651-aif2"
>   
>   static int byt_rt5651_prepare_and_enable_pll1(struct snd_soc_dai *codec_dai,
>   					      int rate)
> @@ -116,10 +126,19 @@ static int byt_rt5651_prepare_and_enable_pll1(struct snd_soc_dai *codec_dai,
>   
>   	/* Configure the PLL before selecting it */
>   	if (!(byt_rt5651_quirk & BYT_RT5651_MCLK_EN)) {
> -		/* 2x25 bit slots on SSP2 */
> -		ret = snd_soc_dai_set_pll(codec_dai, 0,
> -					  RT5651_PLL1_S_BCLK1,
> -					  rate * 50, rate * 512);
> +		/* use bitclock as PLL input */
> +		if ((byt_rt5651_quirk & BYT_RT5651_SSP0_AIF1) ||
> +		    (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2)) {
> +			/* 2x16 bit slots on SSP0 */
> +			ret = snd_soc_dai_set_pll(codec_dai, 0,
> +						  RT5651_PLL1_S_BCLK1,
> +						  rate * 32, rate * 512);
> +		} else {
> +			/* 2x25 bit slots on SSP2 */
> +			ret = snd_soc_dai_set_pll(codec_dai, 0,
> +						  RT5651_PLL1_S_BCLK1,
> +						  rate * 50, rate * 512);
> +		}

This part is conflicting a bit with what we are currently enabling for 
SOF - and that's probably because the quirks combine two separate pieces 
of information.
1. the SSP0-AIF1 routing
2. the limitation to 16-bit on SSP0 with the legacy closed-source firmware.

Could we instead use information coming from the actual hardware params, 
as done in the fixup() function below? If possible I'd like to limit 
this 16/24 configuration to the fixup, if we add it it the PLL settings 
it's not going to work so well.

Thanks!



>   	} else {
>   		if (byt_rt5651_quirk & BYT_RT5651_MCLK_25MHZ) {
>   			ret = snd_soc_dai_set_pll(codec_dai, 0,
> @@ -157,6 +176,8 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w,
>   	int ret;
>   
>   	codec_dai = snd_soc_card_get_codec_dai(card, BYT_CODEC_DAI1);
> +	if (!codec_dai)
> +		codec_dai = snd_soc_card_get_codec_dai(card, BYT_CODEC_DAI2);
>   	if (!codec_dai) {
>   		dev_err(card->dev,
>   			"Codec dai not found; Unable to set platform clock\n");
> @@ -214,13 +235,6 @@ static const struct snd_soc_dapm_route byt_rt5651_audio_map[] = {
>   	{"Speaker", NULL, "Platform Clock"},
>   	{"Line In", NULL, "Platform Clock"},
>   
> -	{"AIF1 Playback", NULL, "ssp2 Tx"},
> -	{"ssp2 Tx", NULL, "codec_out0"},
> -	{"ssp2 Tx", NULL, "codec_out1"},
> -	{"codec_in0", NULL, "ssp2 Rx"},
> -	{"codec_in1", NULL, "ssp2 Rx"},
> -	{"ssp2 Rx", NULL, "AIF1 Capture"},
> -
>   	{"Headset Mic", NULL, "micbias1"}, /* lowercase for rt5651 */
>   	{"Headphone", NULL, "HPOL"},
>   	{"Headphone", NULL, "HPOR"},
> @@ -268,6 +282,42 @@ static const struct snd_soc_dapm_route byt_rt5651_intmic_in2_hs_in3_map[] = {
>   	{"IN3P", NULL, "Headset Mic"},
>   };
>   
> +static const struct snd_soc_dapm_route byt_rt5651_ssp0_aif1_map[] = {
> +	{"ssp0 Tx", NULL, "modem_out"},
> +	{"modem_in", NULL, "ssp0 Rx"},
> +
> +	{"AIF1 Playback", NULL, "ssp0 Tx"},
> +	{"ssp0 Rx", NULL, "AIF1 Capture"},
> +};
> +
> +static const struct snd_soc_dapm_route byt_rt5651_ssp0_aif2_map[] = {
> +	{"ssp0 Tx", NULL, "modem_out"},
> +	{"modem_in", NULL, "ssp0 Rx"},
> +
> +	{"AIF2 Playback", NULL, "ssp0 Tx"},
> +	{"ssp0 Rx", NULL, "AIF2 Capture"},
> +};
> +
> +static const struct snd_soc_dapm_route byt_rt5651_ssp2_aif1_map[] = {
> +	{"ssp2 Tx", NULL, "codec_out0"},
> +	{"ssp2 Tx", NULL, "codec_out1"},
> +	{"codec_in0", NULL, "ssp2 Rx"},
> +	{"codec_in1", NULL, "ssp2 Rx"},
> +
> +	{"AIF1 Playback", NULL, "ssp2 Tx"},
> +	{"ssp2 Rx", NULL, "AIF1 Capture"},
> +};
> +
> +static const struct snd_soc_dapm_route byt_rt5651_ssp2_aif2_map[] = {
> +	{"ssp2 Tx", NULL, "codec_out0"},
> +	{"ssp2 Tx", NULL, "codec_out1"},
> +	{"codec_in0", NULL, "ssp2 Rx"},
> +	{"codec_in1", NULL, "ssp2 Rx"},
> +
> +	{"AIF2 Playback", NULL, "ssp2 Tx"},
> +	{"ssp2 Rx", NULL, "AIF2 Capture"},
> +};
> +
>   static const struct snd_kcontrol_new byt_rt5651_controls[] = {
>   	SOC_DAPM_PIN_SWITCH("Headphone"),
>   	SOC_DAPM_PIN_SWITCH("Headset Mic"),
> @@ -392,6 +442,26 @@ static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime)
>   	if (ret)
>   		return ret;
>   
> +	if (byt_rt5651_quirk & BYT_RT5651_SSP2_AIF2) {
> +		ret = snd_soc_dapm_add_routes(&card->dapm,
> +					byt_rt5651_ssp2_aif2_map,
> +					ARRAY_SIZE(byt_rt5651_ssp2_aif2_map));
> +	} else if (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF1) {
> +		ret = snd_soc_dapm_add_routes(&card->dapm,
> +					byt_rt5651_ssp0_aif1_map,
> +					ARRAY_SIZE(byt_rt5651_ssp0_aif1_map));
> +	} else if (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2) {
> +		ret = snd_soc_dapm_add_routes(&card->dapm,
> +					byt_rt5651_ssp0_aif2_map,
> +					ARRAY_SIZE(byt_rt5651_ssp0_aif2_map));
> +	} else {
> +		ret = snd_soc_dapm_add_routes(&card->dapm,
> +					byt_rt5651_ssp2_aif1_map,
> +					ARRAY_SIZE(byt_rt5651_ssp2_aif1_map));
> +	}
> +	if (ret)
> +		return ret;
> +
>   	ret = snd_soc_add_card_controls(card, byt_rt5651_controls,
>   					ARRAY_SIZE(byt_rt5651_controls));
>   	if (ret) {
> @@ -464,18 +534,26 @@ static int byt_rt5651_codec_fixup(struct snd_soc_pcm_runtime *rtd,
>   			SNDRV_PCM_HW_PARAM_RATE);
>   	struct snd_interval *channels = hw_param_interval(params,
>   						SNDRV_PCM_HW_PARAM_CHANNELS);
> -	int ret;
> +	int ret, bits;
>   
> -	/* The DSP will covert the FE rate to 48k, stereo, 24bits */
> +	/* The DSP will covert the FE rate to 48k, stereo */
>   	rate->min = rate->max = 48000;
>   	channels->min = channels->max = 2;
>   
> -	/* set SSP2 to 24-bit */
> -	params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
> +	if ((byt_rt5651_quirk & BYT_RT5651_SSP0_AIF1) ||
> +	    (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2)) {
> +		/* set SSP0 to 16-bit */
> +		params_set_format(params, SNDRV_PCM_FORMAT_S16_LE);
> +		bits = 16;
> +	} else {
> +		/* set SSP2 to 24-bit */
> +		params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
> +		bits = 24;
> +	}
>   
>   	/*
>   	 * Default mode for SSP configuration is TDM 4 slot, override config
> -	 * with explicit setting to I2S 2ch 24-bit. The word length is set with
> +	 * with explicit setting to I2S 2ch. The word length is set with
>   	 * dai_set_tdm_slot() since there is no other API exposed
>   	 */
>   	ret = snd_soc_dai_set_fmt(rtd->cpu_dai,
> @@ -489,7 +567,7 @@ static int byt_rt5651_codec_fixup(struct snd_soc_pcm_runtime *rtd,
>   		return ret;
>   	}
>   
> -	ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 24);
> +	ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, bits);
>   	if (ret < 0) {
>   		dev_err(rtd->dev, "can't set I2S config, err %d\n", ret);
>   		return ret;
> @@ -583,12 +661,32 @@ static struct snd_soc_card byt_rt5651_card = {
>   };
>   
>   static char byt_rt5651_codec_name[SND_ACPI_I2C_ID_LEN];
> +static char byt_rt5651_codec_aif_name[12]; /*  = "rt5651-aif[1|2]" */
> +static char byt_rt5651_cpu_dai_name[10]; /*  = "ssp[0|2]-port" */
> +
> +static bool is_valleyview(void)
> +{
> +	static const struct x86_cpu_id cpu_ids[] = {
> +		{ X86_VENDOR_INTEL, 6, 55 }, /* Valleyview, Bay Trail */
> +		{}
> +	};
> +
> +	if (!x86_match_cpu(cpu_ids))
> +		return false;
> +	return true;
> +}
> +
> +struct acpi_chan_package {   /* ACPICA seems to require 64 bit integers */
> +	u64 aif_value;       /* 1: AIF1, 2: AIF2 */
> +	u64 mclock_value;    /* usually 25MHz (0x17d7940), ignored */
> +};
>   
>   static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
>   {
>   	struct byt_rt5651_private *priv;
>   	struct snd_soc_acpi_mach *mach;
>   	const char *i2c_name = NULL;
> +	bool is_bytcr = false;
>   	int ret_val = 0;
>   	int dai_index = 0;
>   	int i;
> @@ -620,10 +718,99 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
>   		byt_rt5651_dais[dai_index].codec_name = byt_rt5651_codec_name;
>   	}
>   
> +	/*
> +	 * swap SSP0 if bytcr is detected
> +	 * (will be overridden if DMI quirk is detected)
> +	 */
> +	if (is_valleyview()) {
> +		struct sst_platform_info *p_info = mach->pdata;
> +		const struct sst_res_info *res_info = p_info->res_info;
> +
> +		if (res_info->acpi_ipc_irq_index == 0)
> +			is_bytcr = true;
> +	}
> +
> +	if (is_bytcr) {
> +		/*
> +		 * Baytrail CR platforms may have CHAN package in BIOS, try
> +		 * to find relevant routing quirk based as done on Windows
> +		 * platforms. We have to read the information directly from the
> +		 * BIOS, at this stage the card is not created and the links
> +		 * with the codec driver/pdata are non-existent
> +		 */
> +
> +		struct acpi_chan_package chan_package;
> +
> +		/* format specified: 2 64-bit integers */
> +		struct acpi_buffer format = {sizeof("NN"), "NN"};
> +		struct acpi_buffer state = {0, NULL};
> +		struct snd_soc_acpi_package_context pkg_ctx;
> +		bool pkg_found = false;
> +
> +		state.length = sizeof(chan_package);
> +		state.pointer = &chan_package;
> +
> +		pkg_ctx.name = "CHAN";
> +		pkg_ctx.length = 2;
> +		pkg_ctx.format = &format;
> +		pkg_ctx.state = &state;
> +		pkg_ctx.data_valid = false;
> +
> +		pkg_found = snd_soc_acpi_find_package_from_hid(mach->id,
> +							       &pkg_ctx);
> +		if (pkg_found) {
> +			if (chan_package.aif_value == 1) {
> +				dev_info(&pdev->dev, "BIOS Routing: AIF1 connected\n");
> +				byt_rt5651_quirk |= BYT_RT5651_SSP0_AIF1;
> +			} else  if (chan_package.aif_value == 2) {
> +				dev_info(&pdev->dev, "BIOS Routing: AIF2 connected\n");
> +				byt_rt5651_quirk |= BYT_RT5651_SSP0_AIF2;
> +			} else {
> +				dev_info(&pdev->dev, "BIOS Routing isn't valid, ignored\n");
> +				pkg_found = false;
> +			}
> +		}
> +
> +		if (!pkg_found) {
> +			/* no BIOS indications, assume SSP0-AIF2 connection */
> +			byt_rt5651_quirk |= BYT_RT5651_SSP0_AIF2;
> +		}
> +
> +		/* change defaults for Baytrail-CR capture */
> +		byt_rt5651_quirk |= BYT_RT5651_JD1_1 |
> +				    BYT_RT5651_OVTH_2000UA |
> +				    BYT_RT5651_OVCD_SF_0P75 |
> +				    BYT_RT5651_IN2_HS_IN3_MAP;
> +	} else {
> +		byt_rt5651_quirk |= BYT_RT5651_DMIC_MAP;
> +	}
> +
>   	/* check quirks before creating card */
>   	dmi_check_system(byt_rt5651_quirk_table);
>   	log_quirks(&pdev->dev);
>   
> +	if ((byt_rt5651_quirk & BYT_RT5651_SSP2_AIF2) ||
> +	    (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2)) {
> +		/* fixup codec aif name */
> +		snprintf(byt_rt5651_codec_aif_name,
> +			sizeof(byt_rt5651_codec_aif_name),
> +			"%s", "rt5651-aif2");
> +
> +		byt_rt5651_dais[dai_index].codec_dai_name =
> +			byt_rt5651_codec_aif_name;
> +	}
> +
> +	if ((byt_rt5651_quirk & BYT_RT5651_SSP0_AIF1) ||
> +	    (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2)) {
> +		/* fixup cpu dai name name */
> +		snprintf(byt_rt5651_cpu_dai_name,
> +			sizeof(byt_rt5651_cpu_dai_name),
> +			"%s", "ssp0-port");
> +
> +		byt_rt5651_dais[dai_index].cpu_dai_name =
> +			byt_rt5651_cpu_dai_name;
> +	}
> +
>   	if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN) {
>   		priv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
>   		if (IS_ERR(priv->mclk)) {
> 

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

* Re: [PATCH 02/11] ASoC: rt5651: Remove is_sys_clk_from_pll, it has ordering issues
  2018-02-20 22:15 ` [PATCH 02/11] ASoC: rt5651: Remove is_sys_clk_from_pll, it has ordering issues Hans de Goede
@ 2018-02-21 11:18   ` Mark Brown
  2018-02-21 19:38     ` Hans de Goede
  0 siblings, 1 reply; 35+ messages in thread
From: Mark Brown @ 2018-02-21 11:18 UTC (permalink / raw)
  To: Hans de Goede; +Cc: Bard Liao, alsa-devel, Carlo Caione, Takashi Iwai


[-- Attachment #1.1: Type: text/plain, Size: 434 bytes --]

On Tue, Feb 20, 2018 at 11:15:02PM +0100, Hans de Goede wrote:

> TL;DR: The PLL1-supply must always be powered up when PLL1 is the sysclk
> source and we can simply set the RT5651_PWR_PLL bit when selecting PLL1.

Only if jack detection is enabled, if jack detection is not in use for
some reason then the PLL isn't required and should be powered off - this
is normally handled by having the jack detection code force enable
things.

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



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

* Re: [PATCH 03/11] ASoC: rt5651: Fix bias_level confusion / overcurrent detection deps
  2018-02-20 22:15 ` [PATCH 03/11] ASoC: rt5651: Fix bias_level confusion / overcurrent detection deps Hans de Goede
@ 2018-02-21 11:40   ` Mark Brown
  2018-02-21 19:43     ` Hans de Goede
  0 siblings, 1 reply; 35+ messages in thread
From: Mark Brown @ 2018-02-21 11:40 UTC (permalink / raw)
  To: Hans de Goede; +Cc: Bard Liao, alsa-devel, Carlo Caione, Takashi Iwai


[-- Attachment #1.1: Type: text/plain, Size: 2131 bytes --]

On Tue, Feb 20, 2018 at 11:15:03PM +0100, Hans de Goede wrote:
> Overcurrent detection (ovcd) requires the following to be on:
> 1) The LDO supply
> 2) The micbias1 supply
> 3) General analog voltages such as vref aka a bias_level of standby
> 
> Before this commit deps 2. and 3. were not met (unless a stream recording
> from the mic was active).

What does the overcurrent detection detect overcurrent on?

> 3. Is not met because rt5651_set_bias_level() was only enabling this when
> reaching a bias level of prepared instead of doing this in the normal
> standby bias level, which the dapm core will select as soon as any pins /
> supplies are on. This commit fixes by making rt5651_set_bias_level() behave
> as a normal set_bias function for other codecs and already enabling these
> things at standby level.

...

> 2. is fixed by simply force-enabling "micbias1" when doing ovcd, this
> commit also adds code to turn both the micbias1 and the LDO supplies of
> again when we're done, note they will only really get turned off if the
> ovcd was the only user.
> 
> The snd_soc_codec_force_bias_level(BIAS_OFF) call done in rt5651_probe()
> will now turn off PWR_ANLG1, so the programming of PWR_ANLG1 before the
> snd_soc_codec_force_bias_level() now is a no-op and can be removed.

This is two or three changes combined into a single commit which makes
it harder to review :(

> @@ -1811,8 +1795,11 @@ static int rt5651_jack_detect(struct snd_soc_codec *codec, int jack_insert)
>  	int jack_type;
>  
>  	if (jack_insert) {
> -		snd_soc_dapm_force_enable_pin(dapm, "LDO");
> -		snd_soc_dapm_sync(dapm);
> +		snd_soc_dapm_mutex_lock(dapm);
> +		snd_soc_dapm_force_enable_pin_unlocked(dapm, "LDO");
> +		snd_soc_dapm_force_enable_pin_unlocked(dapm, "micbias1");
> +		snd_soc_dapm_sync_unlocked(dapm);
> +		snd_soc_dapm_mutex_unlock(dapm);
>  
>  		snd_soc_update_bits(codec, RT5651_MICBIAS,
>  				    RT5651_MIC1_OVCD_MASK |

This is now only enabling the LDO and bias when the jack is inserted -
is that enough?  The changelog isn't very clear about what is going on
here.

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



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

* Re: [PATCH 04/11] ASoC: rt5651: Simplify set_bias_level()
  2018-02-20 22:15 ` [PATCH 04/11] ASoC: rt5651: Simplify set_bias_level() Hans de Goede
@ 2018-02-21 11:43   ` Mark Brown
  2018-02-21 20:11     ` Hans de Goede
  0 siblings, 1 reply; 35+ messages in thread
From: Mark Brown @ 2018-02-21 11:43 UTC (permalink / raw)
  To: Hans de Goede; +Cc: Bard Liao, alsa-devel, Carlo Caione, Takashi Iwai


[-- Attachment #1.1: Type: text/plain, Size: 727 bytes --]

On Tue, Feb 20, 2018 at 11:15:04PM +0100, Hans de Goede wrote:
> There is no need to set the LDO voltage to 1.2 volt each time we enter
> standby, instead always leave it 1.2 volt on BIAS_OFF. Note we do a
> snd_soc_codec_force_bias_level(BIAS_OFF) on probe, so this will configure
> it correctly right from the start.

That force on probe sounds like a problem...  if this is being done once
at startup it should be done in the probe function, not in the bias
level configuration.

Also, are you sure this is a good fix?  If the bias voltage is being
configured all the time does that perhaps indicate that for better
performance or something it should have been being set to some other
voltage when the device is in standby?

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



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

* Re: [PATCH 01/11] ASoC: rt5651: Avoid duplicating DMI quirks between codec and machine driver
  2018-02-20 22:15 [PATCH 01/11] ASoC: rt5651: Avoid duplicating DMI quirks between codec and machine driver Hans de Goede
                   ` (9 preceding siblings ...)
  2018-02-20 22:15 ` [PATCH 11/11] ASoC: Intel: bytcr_rt5651: Add quirk for the VIOS LTH17 laptop Hans de Goede
@ 2018-02-21 11:54 ` Mark Brown
  2018-02-21 19:23   ` Hans de Goede
  2018-02-21 17:36 ` Carlo Caione
  11 siblings, 1 reply; 35+ messages in thread
From: Mark Brown @ 2018-02-21 11:54 UTC (permalink / raw)
  To: Hans de Goede; +Cc: Bard Liao, alsa-devel, Carlo Caione, Takashi Iwai


[-- Attachment #1.1: Type: text/plain, Size: 952 bytes --]

On Tue, Feb 20, 2018 at 11:15:01PM +0100, Hans de Goede wrote:
> Instead of duplicating the DMI quirks between the codec and machine driver,
> add a rt5651_set_pdata() codec private function which the machine driver
> can use to pass in pdata.

It's not clear to me that this is a great idea.  The goal in general is
to keep as much of the CODEC configuration in the CODEC driver as
possible so we can move more towards generic machine drivers, this is
moving us in the opposite drection quite dramatically.  That might get
in the way of improvements we could be making when we get the component
based changes further on and can avoid having all the DPCM stuff in the
Intel drivers.

It is really unfortunate that ACPI based systems aren't embracing
standards here and using this mess of open coded quirks but it feels
like the way to do this is to keep the code as close as possible to well
designed firmware interfaces and hope that they come round.

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



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

* Re: [PATCH 06/11] ASoC: rt5651: Improve headphone vs headset detection
  2018-02-20 22:15 ` [PATCH 06/11] ASoC: rt5651: Improve headphone vs headset detection Hans de Goede
@ 2018-02-21 12:05   ` Mark Brown
  2018-02-21 20:22     ` Hans de Goede
  0 siblings, 1 reply; 35+ messages in thread
From: Mark Brown @ 2018-02-21 12:05 UTC (permalink / raw)
  To: Hans de Goede; +Cc: Bard Liao, alsa-devel, Carlo Caione, Takashi Iwai


[-- Attachment #1.1: Type: text/plain, Size: 1176 bytes --]

On Tue, Feb 20, 2018 at 11:15:06PM +0100, Hans de Goede wrote:

> This commit ports my work to make this reliable on the rt5640 over to the
> rt5651, making the following OVCD changes, each of which has been tested
> individually and each of which has shown to be necessary on the rt5651:

It's a big rewrite everything commit :(

> +/*
> + * Note we do not toggle the RT5651_MIC1_OVCD_EN bit in these 2 functions,
> + * to ensure reliable OVCD operation it *must* be enabled before enabling
> + * the supplies, which may already be enabled.
> + */
> +static void rt5651_enable_micbias1_ovcd(struct snd_soc_codec *codec)
> +{

I'm finding this comment pretty confusing - it would probably be clearer
if it said something like "since the supplies may also be enabled by
other DAPM operations we toggle the bit in $PLACE instead and only make
sure the supplies are enabled here".

> +static bool rt5651_jack_inserted(struct snd_soc_codec *codec)
> +{

BTW all these changes are in terms of snd_soc_codec not
snd_soc_component, we're trying to move everytihng up a level so that
all devices are components.  A bunch of refactoring went in just after
the merge window doing that.

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



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

* Re: [PATCH 01/11] ASoC: rt5651: Avoid duplicating DMI quirks between codec and machine driver
  2018-02-20 22:15 [PATCH 01/11] ASoC: rt5651: Avoid duplicating DMI quirks between codec and machine driver Hans de Goede
                   ` (10 preceding siblings ...)
  2018-02-21 11:54 ` [PATCH 01/11] ASoC: rt5651: Avoid duplicating DMI quirks between codec and machine driver Mark Brown
@ 2018-02-21 17:36 ` Carlo Caione
  2018-02-21 20:55   ` Hans de Goede
  11 siblings, 1 reply; 35+ messages in thread
From: Carlo Caione @ 2018-02-21 17:36 UTC (permalink / raw)
  To: Hans de Goede; +Cc: Bard Liao, alsa-devel, Mark Brown, Takashi Iwai

On Tue, Feb 20, 2018 at 10:15 PM, Hans de Goede <hdegoede@redhat.com> wrote:
> Instead of duplicating the DMI quirks between the codec and machine driver,
> add a rt5651_set_pdata() codec private function which the machine driver
> can use to pass in pdata.

Commenting here for the whole series (I don't see the cover letter):

Tested-by: Carlo Caione <carlo@endlessm.com>

(On the quirked KIANO laptop).

Thanks!


-- 
Carlo Caione  |  +44.7384.69.16.04  |  Endless

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

* Re: [PATCH 01/11] ASoC: rt5651: Avoid duplicating DMI quirks between codec and machine driver
  2018-02-21 11:54 ` [PATCH 01/11] ASoC: rt5651: Avoid duplicating DMI quirks between codec and machine driver Mark Brown
@ 2018-02-21 19:23   ` Hans de Goede
  2018-02-22 11:08     ` Hans de Goede
  2018-02-22 11:32     ` Mark Brown
  0 siblings, 2 replies; 35+ messages in thread
From: Hans de Goede @ 2018-02-21 19:23 UTC (permalink / raw)
  To: Mark Brown; +Cc: Bard Liao, alsa-devel, Carlo Caione, Takashi Iwai

Hi,

On 21-02-18 12:54, Mark Brown wrote:
> On Tue, Feb 20, 2018 at 11:15:01PM +0100, Hans de Goede wrote:
>> Instead of duplicating the DMI quirks between the codec and machine driver,
>> add a rt5651_set_pdata() codec private function which the machine driver
>> can use to pass in pdata.
> 
> It's not clear to me that this is a great idea.  The goal in general is
> to keep as much of the CODEC configuration in the CODEC driver as
> possible so we can move more towards generic machine drivers, this is
> moving us in the opposite drection quite dramatically.

Not really, instead of having Intel/ACPI specific quirks in the codec
driver it moves everything over to pdata, so in a way this unifies the
device-tree and ACPI paths.

Also to me it seems that the Intel specific machine driver is the
logical place to put quirks for Intel platforms rather then poluting the
platform-agnostic codec driver with this.

> That might get
> in the way of improvements we could be making when we get the component
> based changes further on and can avoid having all the DPCM stuff in the
> Intel drivers.
> 
> It is really unfortunate that ACPI based systems aren't embracing
> standards here and using this mess of open coded quirks but it feels
> like the way to do this is to keep the code as close as possible to well
> designed firmware interfaces and hope that they come round.

Both devicetree and ACPI code-paths are filling pdata and that is the
only thing the codec driver cares about after this patch. so this is
using a well designed interface (but a non firmware one). I can understand
if you would prefer to use the functions from include/linux/property.h
for this, but those simply do not work for ACPI platforms atm.

If you look further in this series then quirks for at least 2 more models
are added and I expect more to show up in the future, I really do not want
to duplicate these over 2 files.

One possible solution here would be to add device-properties to the codec
i2c-device from the machine-driver using device_add_properties() and make
the codec driver consume those.

This has probe-ordering issues, but those can be worked around by exporting
something like the rt5651_apply_pdata() function from this patch and make
the machine driver call that after it has attached the properties.

I'm not sure if this extra level of indirection buys us much though, the
DT binding maintainers will not accept binding docs for these kind of
kernel internal only device-properties until there are actual DT users
of them, so for now this would mainly add a bunch of extra code for
little gain.

Regards,

Hans

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

* Re: [PATCH 02/11] ASoC: rt5651: Remove is_sys_clk_from_pll, it has ordering issues
  2018-02-21 11:18   ` Mark Brown
@ 2018-02-21 19:38     ` Hans de Goede
  2018-02-22 10:48       ` Mark Brown
  0 siblings, 1 reply; 35+ messages in thread
From: Hans de Goede @ 2018-02-21 19:38 UTC (permalink / raw)
  To: Mark Brown; +Cc: Bard Liao, alsa-devel, Carlo Caione, Takashi Iwai

Hi,

On 21-02-18 12:18, Mark Brown wrote:
> On Tue, Feb 20, 2018 at 11:15:02PM +0100, Hans de Goede wrote:
> 
>> TL;DR: The PLL1-supply must always be powered up when PLL1 is the sysclk
>> source and we can simply set the RT5651_PWR_PLL bit when selecting PLL1.
> 
> Only if jack detection is enabled, if jack detection is not in use for
> some reason then the PLL isn't required and should be powered off - this
> is normally handled by having the jack detection code force enable
> things.

As the commit message tries to explain, the code this removes is fundamentally
broken and this is not jack-detection related:

    "dapm_power_widgets() first builds a list of which widgets to power-up
     before actually powering any of them up. For dapm-supply widgets their
     connected method, in our case is_sys_clk_from_pll() get called at this
     point.

     Before this commit is_sys_clk_from_pll() was looking at the actually
     selected clock in the RT5651_GBL_CLK register. But the sysclk itself is
     selected by another dapm-supply (the "Platform Clock" supply in the
     machine driver) and any changes to that supply part of the same power-
     transition get executed after building the list, causing
     is_sys_clk_from_pll() to return the wrong value."

I actually wrote this patch for the rt5640 driver first (but my rt5640
work / patch-series is not finished yet). I saw the following problem
on rt5640 boards before even introducing jack-detect:

1) Have a generic UCM file
2) Start recording
3) Select an input which is not part of the input-map quirk in the machine driver
4) Switch to an input which is part of the input-map
5) Notice how only silence is recorded
6) Use i2c-get to get the PWR_ANLG2 register, observe that the PLL-bit is OFF at
    this point despite a stream being recorded due to the ordering issues
7) Use i2c-get to get the GLB_CLK register notice that it does point to PLL1,
    so is_sys_clk_from_pll() will return 1 if called *NOW*, but clearly it
    returned 0 when called as proven by 6) which shows the ordering issue is real
8) Use i2c-set to enable the PLL-bit in PWR_ANLG2 and the recording starts working

As I tried to explain in the commit message the is_sys_clk_from_pll() thingie
simply can NOT work because it should check for what the GLB_CLK register will
be *after* the dapm transaction / transition but in reality it checks for what it
was *before* the transition, which means that it will only return the right thing
if 2 transitions are made in a row where the second transition preserves the
GLB_CLK value of the first.

As for that the PLL should be powered-off when not needed, I agree but that
is controlled by the machine-driver through the "Platform Clock" dapm supply
and if that leaves things on for some reason then that is the problem which
we actually need to fix, e.g. this will also leave the MCLK input clk enabled
needlessly.

I really don't see how configuring a broken sysclk (GBL_CLK points to PLL1,
but PLL-bit in PWR_ANLG2 is OFF) is ever a good thing, instead we should make
sure we always switch to the RCCLK when we don't need the SYSCLK.

Last force-enabling the PLL bit on all machines where we can do jack-detection
(not only over-current, but the JD irq in general needs a valid sysclk) would
in practice mean always force-enabling the PLL bit since almost all boards have
jack-detection once we add the necessary quirks, so this really is not a solution.

Regards,

Hans

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

* Re: [PATCH 03/11] ASoC: rt5651: Fix bias_level confusion / overcurrent detection deps
  2018-02-21 11:40   ` Mark Brown
@ 2018-02-21 19:43     ` Hans de Goede
  2018-02-22 10:52       ` Mark Brown
  0 siblings, 1 reply; 35+ messages in thread
From: Hans de Goede @ 2018-02-21 19:43 UTC (permalink / raw)
  To: Mark Brown; +Cc: Bard Liao, alsa-devel, Carlo Caione, Takashi Iwai

Hi,

On 21-02-18 12:40, Mark Brown wrote:
> On Tue, Feb 20, 2018 at 11:15:03PM +0100, Hans de Goede wrote:
>> Overcurrent detection (ovcd) requires the following to be on:
>> 1) The LDO supply
>> 2) The micbias1 supply
>> 3) General analog voltages such as vref aka a bias_level of standby
>>
>> Before this commit deps 2. and 3. were not met (unless a stream recording
>> from the mic was active).
> 
> What does the overcurrent detection detect overcurrent on?

On the micbias current, which is why we need the micbias1 supply on
to do OVCD, which we use to determine if we've a headset (speakers
+ microphone) or headphones (speakers only, mic contact shorted to
ground) plugged in.

>> 3. Is not met because rt5651_set_bias_level() was only enabling this when
>> reaching a bias level of prepared instead of doing this in the normal
>> standby bias level, which the dapm core will select as soon as any pins /
>> supplies are on. This commit fixes by making rt5651_set_bias_level() behave
>> as a normal set_bias function for other codecs and already enabling these
>> things at standby level.
> 
> ...
> 
>> 2. is fixed by simply force-enabling "micbias1" when doing ovcd, this
>> commit also adds code to turn both the micbias1 and the LDO supplies of
>> again when we're done, note they will only really get turned off if the
>> ovcd was the only user.
>>
>> The snd_soc_codec_force_bias_level(BIAS_OFF) call done in rt5651_probe()
>> will now turn off PWR_ANLG1, so the programming of PWR_ANLG1 before the
>> snd_soc_codec_force_bias_level() now is a no-op and can be removed.
> 
> This is two or three changes combined into a single commit which makes
> it harder to review :(

I can split this up, but I cannot guarantee then that there will not
be a state between 1 of the commits where OVCD is not even more broken
then before.

>> @@ -1811,8 +1795,11 @@ static int rt5651_jack_detect(struct snd_soc_codec *codec, int jack_insert)
>>   	int jack_type;
>>   
>>   	if (jack_insert) {
>> -		snd_soc_dapm_force_enable_pin(dapm, "LDO");
>> -		snd_soc_dapm_sync(dapm);
>> +		snd_soc_dapm_mutex_lock(dapm);
>> +		snd_soc_dapm_force_enable_pin_unlocked(dapm, "LDO");
>> +		snd_soc_dapm_force_enable_pin_unlocked(dapm, "micbias1");
>> +		snd_soc_dapm_sync_unlocked(dapm);
>> +		snd_soc_dapm_mutex_unlock(dapm);
>>   
>>   		snd_soc_update_bits(codec, RT5651_MICBIAS,
>>   				    RT5651_MIC1_OVCD_MASK |
> 
> This is now only enabling the LDO and bias when the jack is inserted -
> is that enough?

Yes, we only need to do OVCD on an insertion event to differ between
headset vs headphones.

Regards,

Hans

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

* Re: [PATCH 04/11] ASoC: rt5651: Simplify set_bias_level()
  2018-02-21 11:43   ` Mark Brown
@ 2018-02-21 20:11     ` Hans de Goede
  2018-02-22 11:12       ` Mark Brown
  0 siblings, 1 reply; 35+ messages in thread
From: Hans de Goede @ 2018-02-21 20:11 UTC (permalink / raw)
  To: Mark Brown; +Cc: Bard Liao, alsa-devel, Carlo Caione, Takashi Iwai

Hi,

On 21-02-18 12:43, Mark Brown wrote:
> On Tue, Feb 20, 2018 at 11:15:04PM +0100, Hans de Goede wrote:
>> There is no need to set the LDO voltage to 1.2 volt each time we enter
>> standby, instead always leave it 1.2 volt on BIAS_OFF. Note we do a
>> snd_soc_codec_force_bias_level(BIAS_OFF) on probe, so this will configure
>> it correctly right from the start.
> 
> That force on probe sounds like a problem...  if this is being done once
> at startup it should be done in the probe function, not in the bias
> level configuration.

This is more like "we do a snd_soc_codec_force_bias_level(BIAS_OFF)
on probe anyways and that already sets the level to 1.2 volt, so
we don't need to do this explicitly at probe time".

> Also, are you sure this is a good fix?  If the bias voltage is being
> configured all the time does that perhaps indicate that for better
> performance or something it should have been being set to some other
> voltage when the device is in standby?

We switch the LDO off when in the bias level is BIAS_OFF and on
at 1.2 volt when in standby or higher. Before this commit we would
unconditionally write 0 to PWR_ANLG1 not only turning off all
supplies, but additionally changing the LDO voltage control bits
to 00, which requires reprogramming them when we go back to
standby. The value of the LDO voltage controls bits when in
BIAS_OFF does not matter as the LDO on/off bit is set to off,
so the purpose of this commit is to replace the blindly setting
of PWR_ANLG1 to 0 with setting all the bits in PWR_ANLG1 to 0,
while leaving the 2 LDO voltage-control bits as-is, so that
we don't need to reprogram these 2 bits when entering standby.

Regards,

Hans

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

* Re: [PATCH 06/11] ASoC: rt5651: Improve headphone vs headset detection
  2018-02-21 12:05   ` Mark Brown
@ 2018-02-21 20:22     ` Hans de Goede
  0 siblings, 0 replies; 35+ messages in thread
From: Hans de Goede @ 2018-02-21 20:22 UTC (permalink / raw)
  To: Mark Brown; +Cc: Bard Liao, alsa-devel, Carlo Caione, Takashi Iwai

Hi,

On 21-02-18 13:05, Mark Brown wrote:
> On Tue, Feb 20, 2018 at 11:15:06PM +0100, Hans de Goede wrote:
> 
>> This commit ports my work to make this reliable on the rt5640 over to the
>> rt5651, making the following OVCD changes, each of which has been tested
>> individually and each of which has shown to be necessary on the rt5651:
> 
> It's a big rewrite everything commit :(

Yes your right, given that the headphone vs headset detection was pretty
broken before this commit I just ported my pending rt5640 work over
in one go. I will split this up better for the next version.

>> +/*
>> + * Note we do not toggle the RT5651_MIC1_OVCD_EN bit in these 2 functions,
>> + * to ensure reliable OVCD operation it *must* be enabled before enabling
>> + * the supplies, which may already be enabled.
>> + */
>> +static void rt5651_enable_micbias1_ovcd(struct snd_soc_codec *codec)
>> +{
> 
> I'm finding this comment pretty confusing - it would probably be clearer
> if it said something like "since the supplies may also be enabled by
> other DAPM operations we toggle the bit in $PLACE instead and only make
> sure the supplies are enabled here".

Ok I will update the comment.

>> +static bool rt5651_jack_inserted(struct snd_soc_codec *codec)
>> +{
> 
> BTW all these changes are in terms of snd_soc_codec not
> snd_soc_component, we're trying to move everytihng up a level so that
> all devices are components.  A bunch of refactoring went in just after
> the merge window doing that.

Ugh, just my luck to hit a refactoring like that with a big series.
Ah well I will rebase everything on top of your -next and try to use
component instead of codec everywhere.

Regards,

Hans

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

* Re: [PATCH 01/11] ASoC: rt5651: Avoid duplicating DMI quirks between codec and machine driver
  2018-02-21 17:36 ` Carlo Caione
@ 2018-02-21 20:55   ` Hans de Goede
  0 siblings, 0 replies; 35+ messages in thread
From: Hans de Goede @ 2018-02-21 20:55 UTC (permalink / raw)
  To: Carlo Caione; +Cc: Bard Liao, alsa-devel, Mark Brown, Takashi Iwai

Hi,

On 21-02-18 18:36, Carlo Caione wrote:
> On Tue, Feb 20, 2018 at 10:15 PM, Hans de Goede <hdegoede@redhat.com> wrote:
>> Instead of duplicating the DMI quirks between the codec and machine driver,
>> add a rt5651_set_pdata() codec private function which the machine driver
>> can use to pass in pdata.
> 
> Commenting here for the whole series (I don't see the cover letter):
> 
> Tested-by: Carlo Caione <carlo@endlessm.com>
> 
> (On the quirked KIANO laptop).

Great, thank you for testing, so are the issues with headset vs
headphone detection not working fixed after this series?

Regards,

Hans

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

* Re: [PATCH 02/11] ASoC: rt5651: Remove is_sys_clk_from_pll, it has ordering issues
  2018-02-21 19:38     ` Hans de Goede
@ 2018-02-22 10:48       ` Mark Brown
  2018-02-22 11:00         ` Hans de Goede
  0 siblings, 1 reply; 35+ messages in thread
From: Mark Brown @ 2018-02-22 10:48 UTC (permalink / raw)
  To: Hans de Goede; +Cc: Bard Liao, alsa-devel, Carlo Caione, Takashi Iwai


[-- Attachment #1.1: Type: text/plain, Size: 2438 bytes --]

On Wed, Feb 21, 2018 at 08:38:01PM +0100, Hans de Goede wrote:
> On 21-02-18 12:18, Mark Brown wrote:
> > On Tue, Feb 20, 2018 at 11:15:02PM +0100, Hans de Goede wrote:

> > Only if jack detection is enabled, if jack detection is not in use for
> > some reason then the PLL isn't required and should be powered off - this
> > is normally handled by having the jack detection code force enable
> > things.

> As the commit message tries to explain, the code this removes is fundamentally
> broken and this is not jack-detection related:

>    "dapm_power_widgets() first builds a list of which widgets to power-up
>     before actually powering any of them up. For dapm-supply widgets their
>     connected method, in our case is_sys_clk_from_pll() get called at this
>     point.

>     Before this commit is_sys_clk_from_pll() was looking at the actually
>     selected clock in the RT5651_GBL_CLK register. But the sysclk itself is
>     selected by another dapm-supply (the "Platform Clock" supply in the
>     machine driver) and any changes to that supply part of the same power-
>     transition get executed after building the list, causing
>     is_sys_clk_from_pll() to return the wrong value."

Right, but there's a couple of jumps in your reasoning with the actual
solution.

> As for that the PLL should be powered-off when not needed, I agree but that
> is controlled by the machine-driver through the "Platform Clock" dapm supply
> and if that leaves things on for some reason then that is the problem which
> we actually need to fix, e.g. this will also leave the MCLK input clk enabled
> needlessly.

I don't follow this bit, sorry.  If there's a DAPM supply that's being
enabled when it's not needed then we should just disable it.

> I really don't see how configuring a broken sysclk (GBL_CLK points to PLL1,
> but PLL-bit in PWR_ANLG2 is OFF) is ever a good thing, instead we should make
> sure we always switch to the RCCLK when we don't need the SYSCLK.

> Last force-enabling the PLL bit on all machines where we can do jack-detection
> (not only over-current, but the JD irq in general needs a valid sysclk) would
> in practice mean always force-enabling the PLL bit since almost all boards have
> jack-detection once we add the necessary quirks, so this really is not a solution.

A bit confused here as well, sorry - I think you're assuming I'm
suggesting some particular solution but I'm not sure what that is.

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



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

* Re: [PATCH 03/11] ASoC: rt5651: Fix bias_level confusion / overcurrent detection deps
  2018-02-21 19:43     ` Hans de Goede
@ 2018-02-22 10:52       ` Mark Brown
  2018-02-22 11:04         ` Hans de Goede
  0 siblings, 1 reply; 35+ messages in thread
From: Mark Brown @ 2018-02-22 10:52 UTC (permalink / raw)
  To: Hans de Goede; +Cc: Bard Liao, alsa-devel, Carlo Caione, Takashi Iwai


[-- Attachment #1.1: Type: text/plain, Size: 431 bytes --]

On Wed, Feb 21, 2018 at 08:43:47PM +0100, Hans de Goede wrote:
> On 21-02-18 12:40, Mark Brown wrote:

> > This is now only enabling the LDO and bias when the jack is inserted -
> > is that enough?

> Yes, we only need to do OVCD on an insertion event to differ between
> headset vs headphones.

Is there not a fault protection aspect to this?  The naming and the
separate control makes this seem like it's got some wider purpose.

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



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

* Re: [PATCH 02/11] ASoC: rt5651: Remove is_sys_clk_from_pll, it has ordering issues
  2018-02-22 10:48       ` Mark Brown
@ 2018-02-22 11:00         ` Hans de Goede
  2018-02-22 11:13           ` Mark Brown
  0 siblings, 1 reply; 35+ messages in thread
From: Hans de Goede @ 2018-02-22 11:00 UTC (permalink / raw)
  To: Mark Brown; +Cc: Bard Liao, alsa-devel, Carlo Caione, Takashi Iwai

Hi,

On 22-02-18 11:48, Mark Brown wrote:
> On Wed, Feb 21, 2018 at 08:38:01PM +0100, Hans de Goede wrote:
>> On 21-02-18 12:18, Mark Brown wrote:
>>> On Tue, Feb 20, 2018 at 11:15:02PM +0100, Hans de Goede wrote:
> 
>>> Only if jack detection is enabled, if jack detection is not in use for
>>> some reason then the PLL isn't required and should be powered off - this
>>> is normally handled by having the jack detection code force enable
>>> things.
> 
>> As the commit message tries to explain, the code this removes is fundamentally
>> broken and this is not jack-detection related:
> 
>>     "dapm_power_widgets() first builds a list of which widgets to power-up
>>      before actually powering any of them up. For dapm-supply widgets their
>>      connected method, in our case is_sys_clk_from_pll() get called at this
>>      point.
> 
>>      Before this commit is_sys_clk_from_pll() was looking at the actually
>>      selected clock in the RT5651_GBL_CLK register. But the sysclk itself is
>>      selected by another dapm-supply (the "Platform Clock" supply in the
>>      machine driver) and any changes to that supply part of the same power-
>>      transition get executed after building the list, causing
>>      is_sys_clk_from_pll() to return the wrong value."
> 

> Right, but there's a couple of jumps in your reasoning with the actual
> solution.
> 
>> As for that the PLL should be powered-off when not needed, I agree but that
>> is controlled by the machine-driver through the "Platform Clock" dapm supply
>> and if that leaves things on for some reason then that is the problem which
>> we actually need to fix, e.g. this will also leave the MCLK input clk enabled
>> needlessly.
> 
> I don't follow this bit, sorry.  If there's a DAPM supply that's being
> enabled when it's not needed then we should just disable it.

Right, that is exactly what I'm saying too.

Whether we use PLL1 as sys-clk or the RCCLK is controlled by the
"Platform Clock" dapm supply. If we proper disable that supply when we don't
need PLL1, then it will switch to RCCLK and we can simply have
rt5651_set_dai_sysclk() enable / disable the PLL pwr bit in PWR_ANLG2 when
we switch clock rather then using the is_sys_clk_from_pll() check.

I hope this helps clear up the confusion surrounding this patch. And I guess
I need to improve the commit message...

Regards,

Hans

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

* Re: [PATCH 03/11] ASoC: rt5651: Fix bias_level confusion / overcurrent detection deps
  2018-02-22 10:52       ` Mark Brown
@ 2018-02-22 11:04         ` Hans de Goede
  0 siblings, 0 replies; 35+ messages in thread
From: Hans de Goede @ 2018-02-22 11:04 UTC (permalink / raw)
  To: Mark Brown; +Cc: Bard Liao, alsa-devel, Carlo Caione, Takashi Iwai

Hi,

On 22-02-18 11:52, Mark Brown wrote:
> On Wed, Feb 21, 2018 at 08:43:47PM +0100, Hans de Goede wrote:
>> On 21-02-18 12:40, Mark Brown wrote:
> 
>>> This is now only enabling the LDO and bias when the jack is inserted -
>>> is that enough?
> 
>> Yes, we only need to do OVCD on an insertion event to differ between
>> headset vs headphones.
> 
> Is there not a fault protection aspect to this?  The naming and the
> separate control makes this seem like it's got some wider purpose.

That is a good question, my patch series ends up always enabling this
because my testing has shown that it works better (*) when enabled
before the supplies feeding it are enabled, and there is no harm
in leaving it enabled while the supplies are disabled.

This will automatically also give us the fault protection when micbias1
is on because we're actually recording from the mic, rather then that
it is forced on for a short while for the headset vs headphones detection.

So after this series we are good wrt its function for fault protection
too. Note that the datasheet is not clear on if it is really necessary
for this, but I think it makes sense to have this enabled at all times.

Regards,

Hans

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

* Re: [PATCH 01/11] ASoC: rt5651: Avoid duplicating DMI quirks between codec and machine driver
  2018-02-21 19:23   ` Hans de Goede
@ 2018-02-22 11:08     ` Hans de Goede
  2018-02-22 11:35       ` Mark Brown
  2018-02-22 11:32     ` Mark Brown
  1 sibling, 1 reply; 35+ messages in thread
From: Hans de Goede @ 2018-02-22 11:08 UTC (permalink / raw)
  To: Mark Brown; +Cc: Bard Liao, alsa-devel, Carlo Caione, Takashi Iwai

Hi Mark,

On 21-02-18 20:23, Hans de Goede wrote:
> Hi,
> 
> On 21-02-18 12:54, Mark Brown wrote:
>> On Tue, Feb 20, 2018 at 11:15:01PM +0100, Hans de Goede wrote:
>>> Instead of duplicating the DMI quirks between the codec and machine driver,
>>> add a rt5651_set_pdata() codec private function which the machine driver
>>> can use to pass in pdata.
>>
>> It's not clear to me that this is a great idea.  The goal in general is
>> to keep as much of the CODEC configuration in the CODEC driver as
>> possible so we can move more towards generic machine drivers, this is
>> moving us in the opposite drection quite dramatically.
> 
> Not really, instead of having Intel/ACPI specific quirks in the codec
> driver it moves everything over to pdata, so in a way this unifies the
> device-tree and ACPI paths.
> 
> Also to me it seems that the Intel specific machine driver is the
> logical place to put quirks for Intel platforms rather then poluting the
> platform-agnostic codec driver with this.
> 
>> That might get
>> in the way of improvements we could be making when we get the component
>> based changes further on and can avoid having all the DPCM stuff in the
>> Intel drivers.
>>
>> It is really unfortunate that ACPI based systems aren't embracing
>> standards here and using this mess of open coded quirks but it feels
>> like the way to do this is to keep the code as close as possible to well
>> designed firmware interfaces and hope that they come round.
> 
> Both devicetree and ACPI code-paths are filling pdata and that is the
> only thing the codec driver cares about after this patch. so this is
> using a well designed interface (but a non firmware one). I can understand
> if you would prefer to use the functions from include/linux/property.h
> for this, but those simply do not work for ACPI platforms atm.
> 
> If you look further in this series then quirks for at least 2 more models
> are added and I expect more to show up in the future, I really do not want
> to duplicate these over 2 files.
> 
> One possible solution here would be to add device-properties to the codec
> i2c-device from the machine-driver using device_add_properties() and make
> the codec driver consume those.
> 
> This has probe-ordering issues, but those can be worked around by exporting
> something like the rt5651_apply_pdata() function from this patch and make
> the machine driver call that after it has attached the properties.
> 
> I'm not sure if this extra level of indirection buys us much though, the
> DT binding maintainers will not accept binding docs for these kind of
> kernel internal only device-properties until there are actual DT users
> of them, so for now this would mainly add a bunch of extra code for
> little gain.

So thinking more about this I think that having the codec driver only
check device-properties and completely killing platform_data is the best
way forward / best way to clean this up.

Combined with either device-tree or the machine driver setting these device
properties for now, and in the future the ACPI tables can set these properties
directly and we can hopefully won't need to add new quirks to the machine
driver.

I plan to start reworking this series this afternoon, so any feedback
on the device-properties plan would be appreciated...

Regards,

Hans

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

* Re: [PATCH 04/11] ASoC: rt5651: Simplify set_bias_level()
  2018-02-21 20:11     ` Hans de Goede
@ 2018-02-22 11:12       ` Mark Brown
  0 siblings, 0 replies; 35+ messages in thread
From: Mark Brown @ 2018-02-22 11:12 UTC (permalink / raw)
  To: Hans de Goede; +Cc: Bard Liao, alsa-devel, Carlo Caione, Takashi Iwai


[-- Attachment #1.1: Type: text/plain, Size: 1442 bytes --]

On Wed, Feb 21, 2018 at 09:11:34PM +0100, Hans de Goede wrote:
> On 21-02-18 12:43, Mark Brown wrote:
> > On Tue, Feb 20, 2018 at 11:15:04PM +0100, Hans de Goede wrote:
> > > There is no need to set the LDO voltage to 1.2 volt each time we enter
> > > standby, instead always leave it 1.2 volt on BIAS_OFF. Note we do a
> > > snd_soc_codec_force_bias_level(BIAS_OFF) on probe, so this will configure
> > > it correctly right from the start.

> > That force on probe sounds like a problem...  if this is being done once
> > at startup it should be done in the probe function, not in the bias
> > level configuration.

> This is more like "we do a snd_soc_codec_force_bias_level(BIAS_OFF)
> on probe anyways and that already sets the level to 1.2 volt, so
> we don't need to do this explicitly at probe time".

What I'm saying is that if the code is written such that you need to do
that _force_bias_level() then it's not very idiomatic which is a bit
worrying - it might be safer to reorganize the code so that this isn't
required any more.

> > Also, are you sure this is a good fix?  If the bias voltage is being
> > configured all the time does that perhaps indicate that for better
> > performance or something it should have been being set to some other
> > voltage when the device is in standby?

> We switch the LDO off when in the bias level is BIAS_OFF and on
> at 1.2 volt when in standby or higher. Before this commit we would

OK.

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



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

* Re: [PATCH 02/11] ASoC: rt5651: Remove is_sys_clk_from_pll, it has ordering issues
  2018-02-22 11:00         ` Hans de Goede
@ 2018-02-22 11:13           ` Mark Brown
  0 siblings, 0 replies; 35+ messages in thread
From: Mark Brown @ 2018-02-22 11:13 UTC (permalink / raw)
  To: Hans de Goede; +Cc: Bard Liao, alsa-devel, Carlo Caione, Takashi Iwai


[-- Attachment #1.1: Type: text/plain, Size: 231 bytes --]

On Thu, Feb 22, 2018 at 12:00:35PM +0100, Hans de Goede wrote:

> I hope this helps clear up the confusion surrounding this patch. And I guess
> I need to improve the commit message...

Yeah, that's *probably* the main issue here.

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



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

* Re: [PATCH 01/11] ASoC: rt5651: Avoid duplicating DMI quirks between codec and machine driver
  2018-02-21 19:23   ` Hans de Goede
  2018-02-22 11:08     ` Hans de Goede
@ 2018-02-22 11:32     ` Mark Brown
  1 sibling, 0 replies; 35+ messages in thread
From: Mark Brown @ 2018-02-22 11:32 UTC (permalink / raw)
  To: Hans de Goede; +Cc: Bard Liao, alsa-devel, Carlo Caione, Takashi Iwai


[-- Attachment #1.1: Type: text/plain, Size: 2858 bytes --]

On Wed, Feb 21, 2018 at 08:23:01PM +0100, Hans de Goede wrote:
> On 21-02-18 12:54, Mark Brown wrote:

> > It's not clear to me that this is a great idea.  The goal in general is
> > to keep as much of the CODEC configuration in the CODEC driver as
> > possible so we can move more towards generic machine drivers, this is
> > moving us in the opposite drection quite dramatically.

> Not really, instead of having Intel/ACPI specific quirks in the codec
> driver it moves everything over to pdata, so in a way this unifies the
> device-tree and ACPI paths.

Bear in mind that ACPI isn't x86 specific any more, and on x86 those
Intel drivers really are Intel specific rather than x86 specific - AMD
are doing their own completely different thing.  Much ACPI, so
standards, sadly :(

> Also to me it seems that the Intel specific machine driver is the
> logical place to put quirks for Intel platforms rather then poluting the
> platform-agnostic codec driver with this.

> > It is really unfortunate that ACPI based systems aren't embracing
> > standards here and using this mess of open coded quirks but it feels
> > like the way to do this is to keep the code as close as possible to well
> > designed firmware interfaces and hope that they come round.

> Both devicetree and ACPI code-paths are filling pdata and that is the
> only thing the codec driver cares about after this patch. so this is
> using a well designed interface (but a non firmware one). I can understand

It's not just platform data, it's also putting the platform data in
through a regular driver outside of the usual device model stuff.

> if you would prefer to use the functions from include/linux/property.h
> for this, but those simply do not work for ACPI platforms atm.

Yeah, they work fine with DSD which is the official ACPI way to pass
device specific data through.

> One possible solution here would be to add device-properties to the codec
> i2c-device from the machine-driver using device_add_properties() and make
> the codec driver consume those.

> This has probe-ordering issues, but those can be worked around by exporting
> something like the rt5651_apply_pdata() function from this patch and make
> the machine driver call that after it has attached the properties.

The ordering is part of the issue, yeah.  It increases fragility if we
have to wait to parse the platform data until later on in init, but only
on some systems.

> I'm not sure if this extra level of indirection buys us much though, the
> DT binding maintainers will not accept binding docs for these kind of
> kernel internal only device-properties until there are actual DT users
> of them, so for now this would mainly add a bunch of extra code for
> little gain.

I'm not aware of any such policy from the DT people, and in any case
the individual driver bindings go through subsystems so...

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



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

* Re: [PATCH 01/11] ASoC: rt5651: Avoid duplicating DMI quirks between codec and machine driver
  2018-02-22 11:08     ` Hans de Goede
@ 2018-02-22 11:35       ` Mark Brown
  2018-02-22 20:38         ` Hans de Goede
  0 siblings, 1 reply; 35+ messages in thread
From: Mark Brown @ 2018-02-22 11:35 UTC (permalink / raw)
  To: Hans de Goede; +Cc: Bard Liao, alsa-devel, Carlo Caione, Takashi Iwai


[-- Attachment #1.1: Type: text/plain, Size: 794 bytes --]

On Thu, Feb 22, 2018 at 12:08:29PM +0100, Hans de Goede wrote:

> So thinking more about this I think that having the codec driver only
> check device-properties and completely killing platform_data is the best
> way forward / best way to clean this up.

> Combined with either device-tree or the machine driver setting these device
> properties for now, and in the future the ACPI tables can set these properties
> directly and we can hopefully won't need to add new quirks to the machine
> driver.

The device properties thing seems reasonable enough.  I'm still not
super convinced the machine driver is the right place, but let's see the
code.  I think ideally the arch code would have a way to put all the
device property based quirks for these systems like we IIRC do for some
DT fixups.

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



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

* Re: [PATCH 01/11] ASoC: rt5651: Avoid duplicating DMI quirks between codec and machine driver
  2018-02-22 11:35       ` Mark Brown
@ 2018-02-22 20:38         ` Hans de Goede
  0 siblings, 0 replies; 35+ messages in thread
From: Hans de Goede @ 2018-02-22 20:38 UTC (permalink / raw)
  To: Mark Brown; +Cc: Bard Liao, alsa-devel, Carlo Caione, Takashi Iwai

Hi,

On 22-02-18 12:35, Mark Brown wrote:
> On Thu, Feb 22, 2018 at 12:08:29PM +0100, Hans de Goede wrote:
> 
>> So thinking more about this I think that having the codec driver only
>> check device-properties and completely killing platform_data is the best
>> way forward / best way to clean this up.
> 
>> Combined with either device-tree or the machine driver setting these device
>> properties for now, and in the future the ACPI tables can set these properties
>> directly and we can hopefully won't need to add new quirks to the machine
>> driver.
> 
> The device properties thing seems reasonable enough.  I'm still not
> super convinced the machine driver is the right place, but let's see the
> code.  I think ideally the arch code would have a way to put all the
> device property based quirks for these systems like we IIRC do for some
> DT fixups.

We've already tried something like that for fixing a similar situation
(not enough info in ACPI for the driver to function) for silead
touchscreens:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/log/drivers/platform/x86/silead_dmi.c

Note that this device-property providing driver can only be
builtin, it cannot be built as a module (otherwise we're back
to having ordering issues). We (Dmitry and I) have gotten quite
some flack about needlessly growing the bzImage size with data
only used on a small subset of x86 devices and this construction
is not something which I want to repeat (nor would advise
others to repeat).

We really need to have a way to have these quirks table in a module
which only loads on devices which need it. So in my mind the
machine driver is a good place for this.

Regards,

Hans

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

* Re: [PATCH 10/11] ASoC: Intel: bytcr_rt5651: Add support for Bay Trail CR / SSP0 using boards
  2018-02-20 22:44   ` Pierre-Louis Bossart
@ 2018-02-24 11:52     ` Hans de Goede
  0 siblings, 0 replies; 35+ messages in thread
From: Hans de Goede @ 2018-02-24 11:52 UTC (permalink / raw)
  To: Pierre-Louis Bossart, Mark Brown, Bard Liao
  Cc: alsa-devel, Carlo Caione, Takashi Iwai

Hi,

On 20-02-18 23:44, Pierre-Louis Bossart wrote:
> On 2/20/18 4:15 PM, Hans de Goede wrote:
>> Despite its name being prefixed with bytcr, before this commit the
>> bytcr_rt5651 machine driver could not work with Bay Trail CR boards,
>> as those only have SSP0 and it only supported SSP0-AIF1 setups.
>>
>> This commit adds support for this, autodetecting AIF1 vs AIF2 based on
>> BIOS tables.
>>
>> While at it also add support for SSP2-AIF2 setups, as that requires only
>> minimal extra code on top of the code adding SSP0-AIF1 / SSP0-AIF2 support.
>>
>> Note this code is all copy-pasted from bytcr_rt5640.c. I've looked into
>> merging the 2 machine drivers into 1 to avoid copy-pasting, but there are
>> enough subtile differences to make this hard *and* with all the quirks the
>> machine driver already is full with if (variant-foo) then ... else ...
>> constructs adding more of these is going to make the code unreadable.
>>
>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>> ---
>>   sound/soc/intel/boards/bytcr_rt5651.c | 225 +++++++++++++++++++++++++++++++---
>>   1 file changed, 206 insertions(+), 19 deletions(-)
>>
>> diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c
>> index 9a23ac9172b4..c14c5940ff87 100644
>> --- a/sound/soc/intel/boards/bytcr_rt5651.c
>> +++ b/sound/soc/intel/boards/bytcr_rt5651.c
>> @@ -25,6 +25,7 @@
>>   #include <linux/device.h>
>>   #include <linux/dmi.h>
>>   #include <linux/slab.h>
>> +#include <asm/cpu_device_id.h>
>>   #include <asm/platform_sst_audio.h>
>>   #include <sound/pcm.h>
>>   #include <sound/pcm_params.h>
>> @@ -70,14 +71,16 @@ enum {
>>   #define BYT_RT5651_DMIC_EN        BIT(16)
>>   #define BYT_RT5651_MCLK_EN        BIT(17)
>>   #define BYT_RT5651_MCLK_25MHZ        BIT(18)
>> +#define BYT_RT5651_SSP2_AIF2        BIT(19) /* default is using AIF1  */
>> +#define BYT_RT5651_SSP0_AIF1        BIT(20)
>> +#define BYT_RT5651_SSP0_AIF2        BIT(21)
>>   struct byt_rt5651_private {
>>       struct clk *mclk;
>>       struct snd_soc_jack jack;
>>   };
>> -static unsigned long byt_rt5651_quirk = BYT_RT5651_DMIC_MAP |
>> -                    BYT_RT5651_MCLK_EN;
>> +static unsigned long byt_rt5651_quirk = BYT_RT5651_MCLK_EN;
>>   static void log_quirks(struct device *dev)
>>   {
>> @@ -105,9 +108,16 @@ static void log_quirks(struct device *dev)
>>           dev_info(dev, "quirk MCLK_EN enabled");
>>       if (byt_rt5651_quirk & BYT_RT5651_MCLK_25MHZ)
>>           dev_info(dev, "quirk MCLK_25MHZ enabled");
>> +    if (byt_rt5651_quirk & BYT_RT5651_SSP2_AIF2)
>> +        dev_info(dev, "quirk SSP2_AIF2 enabled\n");
>> +    if (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF1)
>> +        dev_info(dev, "quirk SSP0_AIF1 enabled\n");
>> +    if (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2)
>> +        dev_info(dev, "quirk SSP0_AIF2 enabled\n");
>>   }
>>   #define BYT_CODEC_DAI1    "rt5651-aif1"
>> +#define BYT_CODEC_DAI2    "rt5651-aif2"
>>   static int byt_rt5651_prepare_and_enable_pll1(struct snd_soc_dai *codec_dai,
>>                             int rate)
>> @@ -116,10 +126,19 @@ static int byt_rt5651_prepare_and_enable_pll1(struct snd_soc_dai *codec_dai,
>>       /* Configure the PLL before selecting it */
>>       if (!(byt_rt5651_quirk & BYT_RT5651_MCLK_EN)) {
>> -        /* 2x25 bit slots on SSP2 */
>> -        ret = snd_soc_dai_set_pll(codec_dai, 0,
>> -                      RT5651_PLL1_S_BCLK1,
>> -                      rate * 50, rate * 512);
>> +        /* use bitclock as PLL input */
>> +        if ((byt_rt5651_quirk & BYT_RT5651_SSP0_AIF1) ||
>> +            (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2)) {
>> +            /* 2x16 bit slots on SSP0 */
>> +            ret = snd_soc_dai_set_pll(codec_dai, 0,
>> +                          RT5651_PLL1_S_BCLK1,
>> +                          rate * 32, rate * 512);
>> +        } else {
>> +            /* 2x25 bit slots on SSP2 */
>> +            ret = snd_soc_dai_set_pll(codec_dai, 0,
>> +                          RT5651_PLL1_S_BCLK1,
>> +                          rate * 50, rate * 512);
>> +        }
> 
> This part is conflicting a bit with what we are currently enabling for SOF - and that's probably because the quirks combine two separate pieces of information.
> 1. the SSP0-AIF1 routing
> 2. the limitation to 16-bit on SSP0 with the legacy closed-source firmware.
> 
> Could we instead use information coming from the actual hardware params, as done in the fixup() function below? If possible I'd like to limit this 16/24 configuration to the fixup, if we add it it the PLL settings it's not going to work so well.

Ok, I believe I've fixed this to be more to your liking for v2 of this
patch-set which I'm working on.

Regards,

Hans



> 
> Thanks!
> 
> 
> 
>>       } else {
>>           if (byt_rt5651_quirk & BYT_RT5651_MCLK_25MHZ) {
>>               ret = snd_soc_dai_set_pll(codec_dai, 0,
>> @@ -157,6 +176,8 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w,
>>       int ret;
>>       codec_dai = snd_soc_card_get_codec_dai(card, BYT_CODEC_DAI1);
>> +    if (!codec_dai)
>> +        codec_dai = snd_soc_card_get_codec_dai(card, BYT_CODEC_DAI2);
>>       if (!codec_dai) {
>>           dev_err(card->dev,
>>               "Codec dai not found; Unable to set platform clock\n");
>> @@ -214,13 +235,6 @@ static const struct snd_soc_dapm_route byt_rt5651_audio_map[] = {
>>       {"Speaker", NULL, "Platform Clock"},
>>       {"Line In", NULL, "Platform Clock"},
>> -    {"AIF1 Playback", NULL, "ssp2 Tx"},
>> -    {"ssp2 Tx", NULL, "codec_out0"},
>> -    {"ssp2 Tx", NULL, "codec_out1"},
>> -    {"codec_in0", NULL, "ssp2 Rx"},
>> -    {"codec_in1", NULL, "ssp2 Rx"},
>> -    {"ssp2 Rx", NULL, "AIF1 Capture"},
>> -
>>       {"Headset Mic", NULL, "micbias1"}, /* lowercase for rt5651 */
>>       {"Headphone", NULL, "HPOL"},
>>       {"Headphone", NULL, "HPOR"},
>> @@ -268,6 +282,42 @@ static const struct snd_soc_dapm_route byt_rt5651_intmic_in2_hs_in3_map[] = {
>>       {"IN3P", NULL, "Headset Mic"},
>>   };
>> +static const struct snd_soc_dapm_route byt_rt5651_ssp0_aif1_map[] = {
>> +    {"ssp0 Tx", NULL, "modem_out"},
>> +    {"modem_in", NULL, "ssp0 Rx"},
>> +
>> +    {"AIF1 Playback", NULL, "ssp0 Tx"},
>> +    {"ssp0 Rx", NULL, "AIF1 Capture"},
>> +};
>> +
>> +static const struct snd_soc_dapm_route byt_rt5651_ssp0_aif2_map[] = {
>> +    {"ssp0 Tx", NULL, "modem_out"},
>> +    {"modem_in", NULL, "ssp0 Rx"},
>> +
>> +    {"AIF2 Playback", NULL, "ssp0 Tx"},
>> +    {"ssp0 Rx", NULL, "AIF2 Capture"},
>> +};
>> +
>> +static const struct snd_soc_dapm_route byt_rt5651_ssp2_aif1_map[] = {
>> +    {"ssp2 Tx", NULL, "codec_out0"},
>> +    {"ssp2 Tx", NULL, "codec_out1"},
>> +    {"codec_in0", NULL, "ssp2 Rx"},
>> +    {"codec_in1", NULL, "ssp2 Rx"},
>> +
>> +    {"AIF1 Playback", NULL, "ssp2 Tx"},
>> +    {"ssp2 Rx", NULL, "AIF1 Capture"},
>> +};
>> +
>> +static const struct snd_soc_dapm_route byt_rt5651_ssp2_aif2_map[] = {
>> +    {"ssp2 Tx", NULL, "codec_out0"},
>> +    {"ssp2 Tx", NULL, "codec_out1"},
>> +    {"codec_in0", NULL, "ssp2 Rx"},
>> +    {"codec_in1", NULL, "ssp2 Rx"},
>> +
>> +    {"AIF2 Playback", NULL, "ssp2 Tx"},
>> +    {"ssp2 Rx", NULL, "AIF2 Capture"},
>> +};
>> +
>>   static const struct snd_kcontrol_new byt_rt5651_controls[] = {
>>       SOC_DAPM_PIN_SWITCH("Headphone"),
>>       SOC_DAPM_PIN_SWITCH("Headset Mic"),
>> @@ -392,6 +442,26 @@ static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime)
>>       if (ret)
>>           return ret;
>> +    if (byt_rt5651_quirk & BYT_RT5651_SSP2_AIF2) {
>> +        ret = snd_soc_dapm_add_routes(&card->dapm,
>> +                    byt_rt5651_ssp2_aif2_map,
>> +                    ARRAY_SIZE(byt_rt5651_ssp2_aif2_map));
>> +    } else if (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF1) {
>> +        ret = snd_soc_dapm_add_routes(&card->dapm,
>> +                    byt_rt5651_ssp0_aif1_map,
>> +                    ARRAY_SIZE(byt_rt5651_ssp0_aif1_map));
>> +    } else if (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2) {
>> +        ret = snd_soc_dapm_add_routes(&card->dapm,
>> +                    byt_rt5651_ssp0_aif2_map,
>> +                    ARRAY_SIZE(byt_rt5651_ssp0_aif2_map));
>> +    } else {
>> +        ret = snd_soc_dapm_add_routes(&card->dapm,
>> +                    byt_rt5651_ssp2_aif1_map,
>> +                    ARRAY_SIZE(byt_rt5651_ssp2_aif1_map));
>> +    }
>> +    if (ret)
>> +        return ret;
>> +
>>       ret = snd_soc_add_card_controls(card, byt_rt5651_controls,
>>                       ARRAY_SIZE(byt_rt5651_controls));
>>       if (ret) {
>> @@ -464,18 +534,26 @@ static int byt_rt5651_codec_fixup(struct snd_soc_pcm_runtime *rtd,
>>               SNDRV_PCM_HW_PARAM_RATE);
>>       struct snd_interval *channels = hw_param_interval(params,
>>                           SNDRV_PCM_HW_PARAM_CHANNELS);
>> -    int ret;
>> +    int ret, bits;
>> -    /* The DSP will covert the FE rate to 48k, stereo, 24bits */
>> +    /* The DSP will covert the FE rate to 48k, stereo */
>>       rate->min = rate->max = 48000;
>>       channels->min = channels->max = 2;
>> -    /* set SSP2 to 24-bit */
>> -    params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
>> +    if ((byt_rt5651_quirk & BYT_RT5651_SSP0_AIF1) ||
>> +        (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2)) {
>> +        /* set SSP0 to 16-bit */
>> +        params_set_format(params, SNDRV_PCM_FORMAT_S16_LE);
>> +        bits = 16;
>> +    } else {
>> +        /* set SSP2 to 24-bit */
>> +        params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
>> +        bits = 24;
>> +    }
>>       /*
>>        * Default mode for SSP configuration is TDM 4 slot, override config
>> -     * with explicit setting to I2S 2ch 24-bit. The word length is set with
>> +     * with explicit setting to I2S 2ch. The word length is set with
>>        * dai_set_tdm_slot() since there is no other API exposed
>>        */
>>       ret = snd_soc_dai_set_fmt(rtd->cpu_dai,
>> @@ -489,7 +567,7 @@ static int byt_rt5651_codec_fixup(struct snd_soc_pcm_runtime *rtd,
>>           return ret;
>>       }
>> -    ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 24);
>> +    ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, bits);
>>       if (ret < 0) {
>>           dev_err(rtd->dev, "can't set I2S config, err %d\n", ret);
>>           return ret;
>> @@ -583,12 +661,32 @@ static struct snd_soc_card byt_rt5651_card = {
>>   };
>>   static char byt_rt5651_codec_name[SND_ACPI_I2C_ID_LEN];
>> +static char byt_rt5651_codec_aif_name[12]; /*  = "rt5651-aif[1|2]" */
>> +static char byt_rt5651_cpu_dai_name[10]; /*  = "ssp[0|2]-port" */
>> +
>> +static bool is_valleyview(void)
>> +{
>> +    static const struct x86_cpu_id cpu_ids[] = {
>> +        { X86_VENDOR_INTEL, 6, 55 }, /* Valleyview, Bay Trail */
>> +        {}
>> +    };
>> +
>> +    if (!x86_match_cpu(cpu_ids))
>> +        return false;
>> +    return true;
>> +}
>> +
>> +struct acpi_chan_package {   /* ACPICA seems to require 64 bit integers */
>> +    u64 aif_value;       /* 1: AIF1, 2: AIF2 */
>> +    u64 mclock_value;    /* usually 25MHz (0x17d7940), ignored */
>> +};
>>   static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
>>   {
>>       struct byt_rt5651_private *priv;
>>       struct snd_soc_acpi_mach *mach;
>>       const char *i2c_name = NULL;
>> +    bool is_bytcr = false;
>>       int ret_val = 0;
>>       int dai_index = 0;
>>       int i;
>> @@ -620,10 +718,99 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
>>           byt_rt5651_dais[dai_index].codec_name = byt_rt5651_codec_name;
>>       }
>> +    /*
>> +     * swap SSP0 if bytcr is detected
>> +     * (will be overridden if DMI quirk is detected)
>> +     */
>> +    if (is_valleyview()) {
>> +        struct sst_platform_info *p_info = mach->pdata;
>> +        const struct sst_res_info *res_info = p_info->res_info;
>> +
>> +        if (res_info->acpi_ipc_irq_index == 0)
>> +            is_bytcr = true;
>> +    }
>> +
>> +    if (is_bytcr) {
>> +        /*
>> +         * Baytrail CR platforms may have CHAN package in BIOS, try
>> +         * to find relevant routing quirk based as done on Windows
>> +         * platforms. We have to read the information directly from the
>> +         * BIOS, at this stage the card is not created and the links
>> +         * with the codec driver/pdata are non-existent
>> +         */
>> +
>> +        struct acpi_chan_package chan_package;
>> +
>> +        /* format specified: 2 64-bit integers */
>> +        struct acpi_buffer format = {sizeof("NN"), "NN"};
>> +        struct acpi_buffer state = {0, NULL};
>> +        struct snd_soc_acpi_package_context pkg_ctx;
>> +        bool pkg_found = false;
>> +
>> +        state.length = sizeof(chan_package);
>> +        state.pointer = &chan_package;
>> +
>> +        pkg_ctx.name = "CHAN";
>> +        pkg_ctx.length = 2;
>> +        pkg_ctx.format = &format;
>> +        pkg_ctx.state = &state;
>> +        pkg_ctx.data_valid = false;
>> +
>> +        pkg_found = snd_soc_acpi_find_package_from_hid(mach->id,
>> +                                   &pkg_ctx);
>> +        if (pkg_found) {
>> +            if (chan_package.aif_value == 1) {
>> +                dev_info(&pdev->dev, "BIOS Routing: AIF1 connected\n");
>> +                byt_rt5651_quirk |= BYT_RT5651_SSP0_AIF1;
>> +            } else  if (chan_package.aif_value == 2) {
>> +                dev_info(&pdev->dev, "BIOS Routing: AIF2 connected\n");
>> +                byt_rt5651_quirk |= BYT_RT5651_SSP0_AIF2;
>> +            } else {
>> +                dev_info(&pdev->dev, "BIOS Routing isn't valid, ignored\n");
>> +                pkg_found = false;
>> +            }
>> +        }
>> +
>> +        if (!pkg_found) {
>> +            /* no BIOS indications, assume SSP0-AIF2 connection */
>> +            byt_rt5651_quirk |= BYT_RT5651_SSP0_AIF2;
>> +        }
>> +
>> +        /* change defaults for Baytrail-CR capture */
>> +        byt_rt5651_quirk |= BYT_RT5651_JD1_1 |
>> +                    BYT_RT5651_OVTH_2000UA |
>> +                    BYT_RT5651_OVCD_SF_0P75 |
>> +                    BYT_RT5651_IN2_HS_IN3_MAP;
>> +    } else {
>> +        byt_rt5651_quirk |= BYT_RT5651_DMIC_MAP;
>> +    }
>> +
>>       /* check quirks before creating card */
>>       dmi_check_system(byt_rt5651_quirk_table);
>>       log_quirks(&pdev->dev);
>> +    if ((byt_rt5651_quirk & BYT_RT5651_SSP2_AIF2) ||
>> +        (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2)) {
>> +        /* fixup codec aif name */
>> +        snprintf(byt_rt5651_codec_aif_name,
>> +            sizeof(byt_rt5651_codec_aif_name),
>> +            "%s", "rt5651-aif2");
>> +
>> +        byt_rt5651_dais[dai_index].codec_dai_name =
>> +            byt_rt5651_codec_aif_name;
>> +    }
>> +
>> +    if ((byt_rt5651_quirk & BYT_RT5651_SSP0_AIF1) ||
>> +        (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2)) {
>> +        /* fixup cpu dai name name */
>> +        snprintf(byt_rt5651_cpu_dai_name,
>> +            sizeof(byt_rt5651_cpu_dai_name),
>> +            "%s", "ssp0-port");
>> +
>> +        byt_rt5651_dais[dai_index].cpu_dai_name =
>> +            byt_rt5651_cpu_dai_name;
>> +    }
>> +
>>       if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN) {
>>           priv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
>>           if (IS_ERR(priv->mclk)) {
>>
> 
_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel

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

end of thread, other threads:[~2018-02-24 11:52 UTC | newest]

Thread overview: 35+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-02-20 22:15 [PATCH 01/11] ASoC: rt5651: Avoid duplicating DMI quirks between codec and machine driver Hans de Goede
2018-02-20 22:15 ` [PATCH 02/11] ASoC: rt5651: Remove is_sys_clk_from_pll, it has ordering issues Hans de Goede
2018-02-21 11:18   ` Mark Brown
2018-02-21 19:38     ` Hans de Goede
2018-02-22 10:48       ` Mark Brown
2018-02-22 11:00         ` Hans de Goede
2018-02-22 11:13           ` Mark Brown
2018-02-20 22:15 ` [PATCH 03/11] ASoC: rt5651: Fix bias_level confusion / overcurrent detection deps Hans de Goede
2018-02-21 11:40   ` Mark Brown
2018-02-21 19:43     ` Hans de Goede
2018-02-22 10:52       ` Mark Brown
2018-02-22 11:04         ` Hans de Goede
2018-02-20 22:15 ` [PATCH 04/11] ASoC: rt5651: Simplify set_bias_level() Hans de Goede
2018-02-21 11:43   ` Mark Brown
2018-02-21 20:11     ` Hans de Goede
2018-02-22 11:12       ` Mark Brown
2018-02-20 22:15 ` [PATCH 05/11] ASoC: rt5651: Allow specifying micbias over-current thresholds through pdata Hans de Goede
2018-02-20 22:15 ` [PATCH 06/11] ASoC: rt5651: Improve headphone vs headset detection Hans de Goede
2018-02-21 12:05   ` Mark Brown
2018-02-21 20:22     ` Hans de Goede
2018-02-20 22:15 ` [PATCH 07/11] ASoC: Intel: bytcr_rt5651: Configure PLL1 before using it Hans de Goede
2018-02-20 22:15 ` [PATCH 08/11] ASoC: Intel: bytcr_rt5651: Rename IN3_MAP to IN1_HS_IN3_MAP Hans de Goede
2018-02-20 22:15 ` [PATCH 09/11] ASoC: Intel: bytcr_rt5651: Add new IN2_HS_IN3 input map and a quirk using it Hans de Goede
2018-02-20 22:15 ` [PATCH 10/11] ASoC: Intel: bytcr_rt5651: Add support for Bay Trail CR / SSP0 using boards Hans de Goede
2018-02-20 22:44   ` Pierre-Louis Bossart
2018-02-24 11:52     ` Hans de Goede
2018-02-20 22:15 ` [PATCH 11/11] ASoC: Intel: bytcr_rt5651: Add quirk for the VIOS LTH17 laptop Hans de Goede
2018-02-21 11:54 ` [PATCH 01/11] ASoC: rt5651: Avoid duplicating DMI quirks between codec and machine driver Mark Brown
2018-02-21 19:23   ` Hans de Goede
2018-02-22 11:08     ` Hans de Goede
2018-02-22 11:35       ` Mark Brown
2018-02-22 20:38         ` Hans de Goede
2018-02-22 11:32     ` Mark Brown
2018-02-21 17:36 ` Carlo Caione
2018-02-21 20:55   ` Hans de Goede

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.