All of lore.kernel.org
 help / color / mirror / Atom feed
From: Lucas Tanure <tanureal@opensource.cirrus.com>
To: Mark Brown <broonie@kernel.org>, Takashi Iwai <tiwai@suse.com>,
	"Jaroslav Kysela" <perex@perex.cz>, Len Brown <lenb@kernel.org>,
	David Rhodes <david.rhodes@cirrus.com>,
	Liam Girdwood <lgirdwood@gmail.com>,
	"Rafael J . Wysocki" <rafael@kernel.org>
Cc: <alsa-devel@alsa-project.org>, <linux-acpi@vger.kernel.org>,
	<patches@opensource.cirrus.com>, <linux-kernel@vger.kernel.org>,
	Lucas Tanure <tanureal@opensource.cirrus.com>
Subject: [RFC PATCH v2 1/3] sound: cs35l41: Allow HDA systems to use CS35l41 ASoC driver
Date: Wed, 20 Oct 2021 09:59:42 +0100	[thread overview]
Message-ID: <20211020085944.17577-2-tanureal@opensource.cirrus.com> (raw)
In-Reply-To: <20211020085944.17577-1-tanureal@opensource.cirrus.com>

Re-use ASoC driver for supporting for Legion 7 16ACHg6
laptop.
HDA machine driver will find the registered dais for the
Amp and use snd_soc_dai_ops to configure it.

Signed-off-by: Lucas Tanure <tanureal@opensource.cirrus.com>
---
 include/sound/cs35l41.h    |   1 +
 sound/soc/codecs/cs35l41.c | 139 ++++++++++++++++++++++++++++++++++---
 sound/soc/codecs/cs35l41.h |   1 +
 3 files changed, 133 insertions(+), 8 deletions(-)

diff --git a/include/sound/cs35l41.h b/include/sound/cs35l41.h
index 1f1e3c6c9be1..e250d31d4b04 100644
--- a/include/sound/cs35l41.h
+++ b/include/sound/cs35l41.h
@@ -23,6 +23,7 @@ struct cs35l41_irq_cfg {
 };
 
 struct cs35l41_platform_data {
+	bool vspk_always_on;
 	int bst_ind;
 	int bst_ipk;
 	int bst_cap;
diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c
index b16eb6610c0e..e6bb5c047d89 100644
--- a/sound/soc/codecs/cs35l41.c
+++ b/sound/soc/codecs/cs35l41.c
@@ -21,6 +21,7 @@
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
 #include <sound/tlv.h>
+#include <linux/acpi.h>
 
 #include "cs35l41.h"
 
@@ -1039,9 +1040,7 @@ static int cs35l41_set_pdata(struct cs35l41_private *cs35l41)
 {
 	int ret;
 
-	/* Set Platform Data */
-	/* Required */
-	if (cs35l41->pdata.bst_ipk &&
+	if (!cs35l41->pdata.vspk_always_on && cs35l41->pdata.bst_ipk &&
 	    cs35l41->pdata.bst_ind && cs35l41->pdata.bst_cap) {
 		ret = cs35l41_boost_config(cs35l41, cs35l41->pdata.bst_ind,
 					   cs35l41->pdata.bst_cap,
@@ -1051,8 +1050,7 @@ static int cs35l41_set_pdata(struct cs35l41_private *cs35l41)
 			return ret;
 		}
 	} else {
-		dev_err(cs35l41->dev, "Incomplete Boost component DT config\n");
-		return -EINVAL;
+		dev_info(cs35l41->dev, "Boost disabled\n");
 	}
 
 	/* Optional */
@@ -1098,12 +1096,92 @@ static int cs35l41_irq_gpio_config(struct cs35l41_private *cs35l41)
 	return irq_pol;
 }
 
+static const struct reg_sequence cs35l41_safe_to_global_enable[] = {
+	{ 0x00000040,			0x00000055 },
+	{ 0x00000040,			0x000000AA },
+	{ 0x0000742C,			0x0000000F },
+	{ 0x0000742C,			0x00000079 },
+	{ 0x00007438,			0x00585941 },
+	{ CS35L41_PLL_CLK_CTRL,		0x00000420 }, //3200000Hz ,BCLK Input ,PLL_REFCLK_EN = 0
+	{ CS35L41_PLL_CLK_CTRL,		0x00000430 }, //3200000Hz ,BCLK Input ,PLL_REFCLK_EN = 1
+	{ CS35L41_GLOBAL_CLK_CTRL,	0x00000003 }, //GLOBAL_FS = 48 kHz
+	{ CS35L41_SP_ENABLES,		0x00010000 }, //ASP_RX1_EN = 1
+	{ CS35L41_SP_RATE_CTRL,		0x00000021 }, //ASP_BCLK_FREQ = 3.072 MHz
+	{ CS35L41_SP_FORMAT,		0x18180200 }, //ASP_RX_WIDTH = 24 bits, ASP_TX_WIDTH = 24 bits, ASP_FMT=I2S, BCLK Slave, FSYNC Slave
+	{ CS35L41_DAC_PCM1_SRC,		0x00000008 }, //DACPCM1_SRC = ASPRX1
+	{ CS35L41_AMP_DIG_VOL_CTRL,	0x00000000 }, //AMP_VOL_PCM  0.0 dB
+	{ CS35L41_AMP_GAIN_CTRL,	0x00000260 }, //AMP_GAIN_PCM 19.5 dB
+	{ CS35L41_PWR_CTRL2,		0x00000001 }, //AMP_EN = 1
+	{ CS35L41_PWR_CTRL1,		0x00000001 }, //GLOBAL_EN = 1
+	{ 0x00000040,			0x000000CC },
+	{ 0x00000040,			0x00000033 },
+};
+
+static const struct reg_sequence cs35l41_global_enable_to_active[] = {
+	{ 0x00000040,			0x00000055 },
+	{ 0x00000040,			0x000000AA },
+	{ 0x0000742C,			0x000000F9 },
+	{ 0x00007438,			0x00580941 },
+	{ 0x00000040,			0x000000CC },
+	{ 0x00000040,			0x00000033 },
+};
+
+static const struct reg_sequence cs35l41_active_to_safe_first[] = {
+	{ 0x00000040,			0x00000055 },
+	{ 0x00000040,			0x000000AA },
+	{ 0x00007438,			0x00585941 },
+	{ CS35L41_AMP_DIG_VOL_CTRL,	0x0000A678 }, //AMP_VOL_PCM Mute
+	{ CS35L41_PWR_CTRL2,		0x00000000 }, //AMP_EN = 0
+	{ CS35L41_PWR_CTRL1,		0x00000000 },
+	{ 0x0000742C,			0x00000009 },
+	{ 0x00000040,			0x000000CC },
+	{ 0x00000040,			0x00000033 },
+};
+
+static const struct reg_sequence cs35l41_active_to_safe_second[] = {
+	{ 0x00000040,			0x00000055 },
+	{ 0x00000040,			0x000000AA },
+	{ 0x00007438,			0x00580941 },
+	{ 0x00000040,			0x000000CC },
+	{ 0x00000040,			0x00000033 },
+};
+
+static void cs35l41_dai_shutdown(struct snd_pcm_substream *sub, struct snd_soc_dai *dai)
+{
+	struct cs35l41_private *cs35l41 = snd_soc_component_get_drvdata(dai->component);
+
+	if (cs35l41->hda) {
+		regmap_multi_reg_write(cs35l41->regmap, cs35l41_active_to_safe_first,
+				       ARRAY_SIZE(cs35l41_active_to_safe_first));
+		usleep_range(1500, 2000);
+		regmap_multi_reg_write(cs35l41->regmap, cs35l41_active_to_safe_second,
+				       ARRAY_SIZE(cs35l41_active_to_safe_second));
+	}
+}
+
+static int cs35l41_dai_prepare(struct snd_pcm_substream *sub, struct snd_soc_dai *dai)
+{
+	struct cs35l41_private *cs35l41 = snd_soc_component_get_drvdata(dai->component);
+
+	if (cs35l41->hda) {
+		regmap_multi_reg_write(cs35l41->regmap, cs35l41_safe_to_global_enable,
+				       ARRAY_SIZE(cs35l41_safe_to_global_enable));
+		usleep_range(1500, 2000);
+		regmap_multi_reg_write(cs35l41->regmap, cs35l41_global_enable_to_active,
+				      ARRAY_SIZE(cs35l41_global_enable_to_active));
+	}
+
+	return 0;
+}
+
 static const struct snd_soc_dai_ops cs35l41_ops = {
 	.startup = cs35l41_pcm_startup,
 	.set_fmt = cs35l41_set_dai_fmt,
 	.hw_params = cs35l41_pcm_hw_params,
 	.set_sysclk = cs35l41_dai_set_sysclk,
 	.set_channel_map = cs35l41_set_channel_map,
+	.shutdown = cs35l41_dai_shutdown,
+	.prepare = cs35l41_dai_prepare,
 };
 
 static struct snd_soc_dai_driver cs35l41_dai[] = {
@@ -1126,6 +1204,7 @@ static struct snd_soc_dai_driver cs35l41_dai[] = {
 		},
 		.ops = &cs35l41_ops,
 		.symmetric_rate = 1,
+		.symmetric_sample_bits = 1,
 	},
 };
 
@@ -1148,9 +1227,31 @@ static int cs35l41_handle_pdata(struct device *dev,
 {
 	struct cs35l41_irq_cfg *irq_gpio1_config = &pdata->irq_config1;
 	struct cs35l41_irq_cfg *irq_gpio2_config = &pdata->irq_config2;
+	struct acpi_device *adev;
+	struct device *phys_dev;
 	unsigned int val;
 	int ret;
 
+	if (memcmp(dev_name(cs35l41->dev), "i2c-CLSA0100", 12) == 0) {
+		pdata->vspk_always_on = true;
+		cs35l41->hda = true;
+		adev = acpi_dev_get_first_match_dev("CLSA0100", "1", -1);
+		if (!adev) {
+			dev_err(dev, "Failed to find an ACPI device\n");
+			return -ENODEV;
+		}
+
+		phys_dev = get_device(acpi_get_first_physical_node(adev));
+		acpi_dev_put(adev);
+
+		if (!phys_dev) {
+			dev_err(dev, "Failed to find a physical device\n");
+			return -ENODEV;
+		}
+		cs35l41->reset_gpio = gpiod_get_index(phys_dev, NULL, 0, GPIOD_ASIS);
+		return 0;
+	}
+
 	ret = device_property_read_u32(dev, "cirrus,boost-peak-milliamp", &val);
 	if (ret >= 0)
 		pdata->bst_ipk = val;
@@ -1237,6 +1338,16 @@ static const struct reg_sequence cs35l41_revb2_errata_patch[] = {
 	{ 0x00000040,			 0x00003333 },
 };
 
+static const struct reg_sequence cs35l41_reset_to_enabled[] = {
+	{ 0x00000040,			0x00000055 },
+	{ 0x00000040,			0x000000AA },
+	{ 0x00007438,			0x00585941 },
+	{ 0x00007414,			0x08C82222 },
+	{ 0x0000742C,			0x00000009 },
+	{ 0x00000040,			0x000000CC },
+	{ 0x00000040,			0x00000033 },
+};
+
 int cs35l41_probe(struct cs35l41_private *cs35l41,
 		  struct cs35l41_platform_data *pdata)
 {
@@ -1269,8 +1380,8 @@ int cs35l41_probe(struct cs35l41_private *cs35l41,
 	}
 
 	/* returning NULL can be an option if in stereo mode */
-	cs35l41->reset_gpio = devm_gpiod_get_optional(cs35l41->dev, "reset",
-						      GPIOD_OUT_LOW);
+	if (!cs35l41->reset_gpio)
+		cs35l41->reset_gpio = devm_gpiod_get_optional(cs35l41->dev, "reset", GPIOD_OUT_LOW);
 	if (IS_ERR(cs35l41->reset_gpio)) {
 		ret = PTR_ERR(cs35l41->reset_gpio);
 		cs35l41->reset_gpio = NULL;
@@ -1365,6 +1476,16 @@ int cs35l41_probe(struct cs35l41_private *cs35l41,
 		break;
 	}
 
+	if (cs35l41->pdata.vspk_always_on) {
+		ret = regmap_multi_reg_write(cs35l41->regmap, cs35l41_reset_to_enabled,
+					     ARRAY_SIZE(cs35l41_reset_to_enabled));
+		if (ret < 0) {
+			dev_err(cs35l41->dev, "Failed to apply reset to enabled patch: %d\n", ret);
+			goto err;
+		}
+		dev_info(cs35l41->dev, "Safe mode enabled\n");
+	}
+
 	irq_pol = cs35l41_irq_gpio_config(cs35l41);
 
 	/* Set interrupt masks for critical errors */
@@ -1437,7 +1558,9 @@ int cs35l41_remove(struct cs35l41_private *cs35l41)
 {
 	regmap_write(cs35l41->regmap, CS35L41_IRQ1_MASK1, 0xFFFFFFFF);
 	regulator_bulk_disable(CS35L41_NUM_SUPPLIES, cs35l41->supplies);
-	gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
+
+	if (cs35l41->reset_gpio && !cs35l41->pdata.vspk_always_on)
+		gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
 
 	return 0;
 }
diff --git a/sound/soc/codecs/cs35l41.h b/sound/soc/codecs/cs35l41.h
index 0e2639d6ef19..bb1f08e36c04 100644
--- a/sound/soc/codecs/cs35l41.h
+++ b/sound/soc/codecs/cs35l41.h
@@ -762,6 +762,7 @@ struct cs35l41_private {
 	struct regmap *regmap;
 	struct regulator_bulk_data supplies[CS35L41_NUM_SUPPLIES];
 	int irq;
+	bool hda;
 	/* GPIO for /RST */
 	struct gpio_desc *reset_gpio;
 	void (*otp_setup)(struct cs35l41_private *cs35l41, bool is_pre_setup,
-- 
2.33.1


WARNING: multiple messages have this Message-ID (diff)
From: Lucas Tanure <tanureal@opensource.cirrus.com>
To: Mark Brown <broonie@kernel.org>, Takashi Iwai <tiwai@suse.com>,
	"Jaroslav Kysela" <perex@perex.cz>, Len Brown <lenb@kernel.org>,
	David Rhodes <david.rhodes@cirrus.com>,
	Liam Girdwood <lgirdwood@gmail.com>,
	"Rafael J . Wysocki" <rafael@kernel.org>
Cc: linux-acpi@vger.kernel.org, alsa-devel@alsa-project.org,
	linux-kernel@vger.kernel.org,
	Lucas Tanure <tanureal@opensource.cirrus.com>,
	patches@opensource.cirrus.com
Subject: [RFC PATCH v2 1/3] sound: cs35l41: Allow HDA systems to use CS35l41 ASoC driver
Date: Wed, 20 Oct 2021 09:59:42 +0100	[thread overview]
Message-ID: <20211020085944.17577-2-tanureal@opensource.cirrus.com> (raw)
In-Reply-To: <20211020085944.17577-1-tanureal@opensource.cirrus.com>

Re-use ASoC driver for supporting for Legion 7 16ACHg6
laptop.
HDA machine driver will find the registered dais for the
Amp and use snd_soc_dai_ops to configure it.

Signed-off-by: Lucas Tanure <tanureal@opensource.cirrus.com>
---
 include/sound/cs35l41.h    |   1 +
 sound/soc/codecs/cs35l41.c | 139 ++++++++++++++++++++++++++++++++++---
 sound/soc/codecs/cs35l41.h |   1 +
 3 files changed, 133 insertions(+), 8 deletions(-)

diff --git a/include/sound/cs35l41.h b/include/sound/cs35l41.h
index 1f1e3c6c9be1..e250d31d4b04 100644
--- a/include/sound/cs35l41.h
+++ b/include/sound/cs35l41.h
@@ -23,6 +23,7 @@ struct cs35l41_irq_cfg {
 };
 
 struct cs35l41_platform_data {
+	bool vspk_always_on;
 	int bst_ind;
 	int bst_ipk;
 	int bst_cap;
diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c
index b16eb6610c0e..e6bb5c047d89 100644
--- a/sound/soc/codecs/cs35l41.c
+++ b/sound/soc/codecs/cs35l41.c
@@ -21,6 +21,7 @@
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
 #include <sound/tlv.h>
+#include <linux/acpi.h>
 
 #include "cs35l41.h"
 
@@ -1039,9 +1040,7 @@ static int cs35l41_set_pdata(struct cs35l41_private *cs35l41)
 {
 	int ret;
 
-	/* Set Platform Data */
-	/* Required */
-	if (cs35l41->pdata.bst_ipk &&
+	if (!cs35l41->pdata.vspk_always_on && cs35l41->pdata.bst_ipk &&
 	    cs35l41->pdata.bst_ind && cs35l41->pdata.bst_cap) {
 		ret = cs35l41_boost_config(cs35l41, cs35l41->pdata.bst_ind,
 					   cs35l41->pdata.bst_cap,
@@ -1051,8 +1050,7 @@ static int cs35l41_set_pdata(struct cs35l41_private *cs35l41)
 			return ret;
 		}
 	} else {
-		dev_err(cs35l41->dev, "Incomplete Boost component DT config\n");
-		return -EINVAL;
+		dev_info(cs35l41->dev, "Boost disabled\n");
 	}
 
 	/* Optional */
@@ -1098,12 +1096,92 @@ static int cs35l41_irq_gpio_config(struct cs35l41_private *cs35l41)
 	return irq_pol;
 }
 
+static const struct reg_sequence cs35l41_safe_to_global_enable[] = {
+	{ 0x00000040,			0x00000055 },
+	{ 0x00000040,			0x000000AA },
+	{ 0x0000742C,			0x0000000F },
+	{ 0x0000742C,			0x00000079 },
+	{ 0x00007438,			0x00585941 },
+	{ CS35L41_PLL_CLK_CTRL,		0x00000420 }, //3200000Hz ,BCLK Input ,PLL_REFCLK_EN = 0
+	{ CS35L41_PLL_CLK_CTRL,		0x00000430 }, //3200000Hz ,BCLK Input ,PLL_REFCLK_EN = 1
+	{ CS35L41_GLOBAL_CLK_CTRL,	0x00000003 }, //GLOBAL_FS = 48 kHz
+	{ CS35L41_SP_ENABLES,		0x00010000 }, //ASP_RX1_EN = 1
+	{ CS35L41_SP_RATE_CTRL,		0x00000021 }, //ASP_BCLK_FREQ = 3.072 MHz
+	{ CS35L41_SP_FORMAT,		0x18180200 }, //ASP_RX_WIDTH = 24 bits, ASP_TX_WIDTH = 24 bits, ASP_FMT=I2S, BCLK Slave, FSYNC Slave
+	{ CS35L41_DAC_PCM1_SRC,		0x00000008 }, //DACPCM1_SRC = ASPRX1
+	{ CS35L41_AMP_DIG_VOL_CTRL,	0x00000000 }, //AMP_VOL_PCM  0.0 dB
+	{ CS35L41_AMP_GAIN_CTRL,	0x00000260 }, //AMP_GAIN_PCM 19.5 dB
+	{ CS35L41_PWR_CTRL2,		0x00000001 }, //AMP_EN = 1
+	{ CS35L41_PWR_CTRL1,		0x00000001 }, //GLOBAL_EN = 1
+	{ 0x00000040,			0x000000CC },
+	{ 0x00000040,			0x00000033 },
+};
+
+static const struct reg_sequence cs35l41_global_enable_to_active[] = {
+	{ 0x00000040,			0x00000055 },
+	{ 0x00000040,			0x000000AA },
+	{ 0x0000742C,			0x000000F9 },
+	{ 0x00007438,			0x00580941 },
+	{ 0x00000040,			0x000000CC },
+	{ 0x00000040,			0x00000033 },
+};
+
+static const struct reg_sequence cs35l41_active_to_safe_first[] = {
+	{ 0x00000040,			0x00000055 },
+	{ 0x00000040,			0x000000AA },
+	{ 0x00007438,			0x00585941 },
+	{ CS35L41_AMP_DIG_VOL_CTRL,	0x0000A678 }, //AMP_VOL_PCM Mute
+	{ CS35L41_PWR_CTRL2,		0x00000000 }, //AMP_EN = 0
+	{ CS35L41_PWR_CTRL1,		0x00000000 },
+	{ 0x0000742C,			0x00000009 },
+	{ 0x00000040,			0x000000CC },
+	{ 0x00000040,			0x00000033 },
+};
+
+static const struct reg_sequence cs35l41_active_to_safe_second[] = {
+	{ 0x00000040,			0x00000055 },
+	{ 0x00000040,			0x000000AA },
+	{ 0x00007438,			0x00580941 },
+	{ 0x00000040,			0x000000CC },
+	{ 0x00000040,			0x00000033 },
+};
+
+static void cs35l41_dai_shutdown(struct snd_pcm_substream *sub, struct snd_soc_dai *dai)
+{
+	struct cs35l41_private *cs35l41 = snd_soc_component_get_drvdata(dai->component);
+
+	if (cs35l41->hda) {
+		regmap_multi_reg_write(cs35l41->regmap, cs35l41_active_to_safe_first,
+				       ARRAY_SIZE(cs35l41_active_to_safe_first));
+		usleep_range(1500, 2000);
+		regmap_multi_reg_write(cs35l41->regmap, cs35l41_active_to_safe_second,
+				       ARRAY_SIZE(cs35l41_active_to_safe_second));
+	}
+}
+
+static int cs35l41_dai_prepare(struct snd_pcm_substream *sub, struct snd_soc_dai *dai)
+{
+	struct cs35l41_private *cs35l41 = snd_soc_component_get_drvdata(dai->component);
+
+	if (cs35l41->hda) {
+		regmap_multi_reg_write(cs35l41->regmap, cs35l41_safe_to_global_enable,
+				       ARRAY_SIZE(cs35l41_safe_to_global_enable));
+		usleep_range(1500, 2000);
+		regmap_multi_reg_write(cs35l41->regmap, cs35l41_global_enable_to_active,
+				      ARRAY_SIZE(cs35l41_global_enable_to_active));
+	}
+
+	return 0;
+}
+
 static const struct snd_soc_dai_ops cs35l41_ops = {
 	.startup = cs35l41_pcm_startup,
 	.set_fmt = cs35l41_set_dai_fmt,
 	.hw_params = cs35l41_pcm_hw_params,
 	.set_sysclk = cs35l41_dai_set_sysclk,
 	.set_channel_map = cs35l41_set_channel_map,
+	.shutdown = cs35l41_dai_shutdown,
+	.prepare = cs35l41_dai_prepare,
 };
 
 static struct snd_soc_dai_driver cs35l41_dai[] = {
@@ -1126,6 +1204,7 @@ static struct snd_soc_dai_driver cs35l41_dai[] = {
 		},
 		.ops = &cs35l41_ops,
 		.symmetric_rate = 1,
+		.symmetric_sample_bits = 1,
 	},
 };
 
@@ -1148,9 +1227,31 @@ static int cs35l41_handle_pdata(struct device *dev,
 {
 	struct cs35l41_irq_cfg *irq_gpio1_config = &pdata->irq_config1;
 	struct cs35l41_irq_cfg *irq_gpio2_config = &pdata->irq_config2;
+	struct acpi_device *adev;
+	struct device *phys_dev;
 	unsigned int val;
 	int ret;
 
+	if (memcmp(dev_name(cs35l41->dev), "i2c-CLSA0100", 12) == 0) {
+		pdata->vspk_always_on = true;
+		cs35l41->hda = true;
+		adev = acpi_dev_get_first_match_dev("CLSA0100", "1", -1);
+		if (!adev) {
+			dev_err(dev, "Failed to find an ACPI device\n");
+			return -ENODEV;
+		}
+
+		phys_dev = get_device(acpi_get_first_physical_node(adev));
+		acpi_dev_put(adev);
+
+		if (!phys_dev) {
+			dev_err(dev, "Failed to find a physical device\n");
+			return -ENODEV;
+		}
+		cs35l41->reset_gpio = gpiod_get_index(phys_dev, NULL, 0, GPIOD_ASIS);
+		return 0;
+	}
+
 	ret = device_property_read_u32(dev, "cirrus,boost-peak-milliamp", &val);
 	if (ret >= 0)
 		pdata->bst_ipk = val;
@@ -1237,6 +1338,16 @@ static const struct reg_sequence cs35l41_revb2_errata_patch[] = {
 	{ 0x00000040,			 0x00003333 },
 };
 
+static const struct reg_sequence cs35l41_reset_to_enabled[] = {
+	{ 0x00000040,			0x00000055 },
+	{ 0x00000040,			0x000000AA },
+	{ 0x00007438,			0x00585941 },
+	{ 0x00007414,			0x08C82222 },
+	{ 0x0000742C,			0x00000009 },
+	{ 0x00000040,			0x000000CC },
+	{ 0x00000040,			0x00000033 },
+};
+
 int cs35l41_probe(struct cs35l41_private *cs35l41,
 		  struct cs35l41_platform_data *pdata)
 {
@@ -1269,8 +1380,8 @@ int cs35l41_probe(struct cs35l41_private *cs35l41,
 	}
 
 	/* returning NULL can be an option if in stereo mode */
-	cs35l41->reset_gpio = devm_gpiod_get_optional(cs35l41->dev, "reset",
-						      GPIOD_OUT_LOW);
+	if (!cs35l41->reset_gpio)
+		cs35l41->reset_gpio = devm_gpiod_get_optional(cs35l41->dev, "reset", GPIOD_OUT_LOW);
 	if (IS_ERR(cs35l41->reset_gpio)) {
 		ret = PTR_ERR(cs35l41->reset_gpio);
 		cs35l41->reset_gpio = NULL;
@@ -1365,6 +1476,16 @@ int cs35l41_probe(struct cs35l41_private *cs35l41,
 		break;
 	}
 
+	if (cs35l41->pdata.vspk_always_on) {
+		ret = regmap_multi_reg_write(cs35l41->regmap, cs35l41_reset_to_enabled,
+					     ARRAY_SIZE(cs35l41_reset_to_enabled));
+		if (ret < 0) {
+			dev_err(cs35l41->dev, "Failed to apply reset to enabled patch: %d\n", ret);
+			goto err;
+		}
+		dev_info(cs35l41->dev, "Safe mode enabled\n");
+	}
+
 	irq_pol = cs35l41_irq_gpio_config(cs35l41);
 
 	/* Set interrupt masks for critical errors */
@@ -1437,7 +1558,9 @@ int cs35l41_remove(struct cs35l41_private *cs35l41)
 {
 	regmap_write(cs35l41->regmap, CS35L41_IRQ1_MASK1, 0xFFFFFFFF);
 	regulator_bulk_disable(CS35L41_NUM_SUPPLIES, cs35l41->supplies);
-	gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
+
+	if (cs35l41->reset_gpio && !cs35l41->pdata.vspk_always_on)
+		gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
 
 	return 0;
 }
diff --git a/sound/soc/codecs/cs35l41.h b/sound/soc/codecs/cs35l41.h
index 0e2639d6ef19..bb1f08e36c04 100644
--- a/sound/soc/codecs/cs35l41.h
+++ b/sound/soc/codecs/cs35l41.h
@@ -762,6 +762,7 @@ struct cs35l41_private {
 	struct regmap *regmap;
 	struct regulator_bulk_data supplies[CS35L41_NUM_SUPPLIES];
 	int irq;
+	bool hda;
 	/* GPIO for /RST */
 	struct gpio_desc *reset_gpio;
 	void (*otp_setup)(struct cs35l41_private *cs35l41, bool is_pre_setup,
-- 
2.33.1


  reply	other threads:[~2021-10-20  9:00 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-10-20  8:59 [RFC PATCH v2 0/3] Add support for Legion 7 16ACHg6 laptop Lucas Tanure
2021-10-20  8:59 ` Lucas Tanure
2021-10-20  8:59 ` Lucas Tanure [this message]
2021-10-20  8:59   ` [RFC PATCH v2 1/3] sound: cs35l41: Allow HDA systems to use CS35l41 ASoC driver Lucas Tanure
2021-10-20 12:30   ` Mark Brown
2021-10-20 12:30     ` Mark Brown
2021-10-20  8:59 ` [RFC PATCH v2 2/3] ALSA: hda/realtek: Add support for Legion 7 16ACHg6 laptop Speakers Lucas Tanure
2021-10-20  8:59   ` Lucas Tanure
2021-10-20  9:17   ` Takashi Iwai
2021-10-20  9:17     ` Takashi Iwai
2021-10-20  8:59 ` [RFC PATCH v2 3/3] ACPI / scan: Create platform device for INT3515 ACPI nodes Lucas Tanure
2021-10-20  8:59   ` Lucas Tanure

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20211020085944.17577-2-tanureal@opensource.cirrus.com \
    --to=tanureal@opensource.cirrus.com \
    --cc=alsa-devel@alsa-project.org \
    --cc=broonie@kernel.org \
    --cc=david.rhodes@cirrus.com \
    --cc=lenb@kernel.org \
    --cc=lgirdwood@gmail.com \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=patches@opensource.cirrus.com \
    --cc=perex@perex.cz \
    --cc=rafael@kernel.org \
    --cc=tiwai@suse.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.