From b7c752d68aee9c066cb0bd2f24ee73aed64575e8 Mon Sep 17 00:00:00 2001
From: Brian Austin <brian.austin@cirrus.com>
Date: Thu, 18 May 2017 16:32:36 +0100
Subject: ASoC: cs35l35: Add Boost Inductor Calculation

Add the Boost Inductor parameters based off the size of the inductor
on the HW setup

Signed-off-by: Brian Austin <brian.austin@cirrus.com>
Signed-off-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 sound/soc/codecs/cs35l35.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 82 insertions(+)

(limited to 'sound/soc/codecs/cs35l35.c')

diff --git a/sound/soc/codecs/cs35l35.c b/sound/soc/codecs/cs35l35.c
index f8aef5869b03..c6eabb8610f0 100644
--- a/sound/soc/codecs/cs35l35.c
+++ b/sound/soc/codecs/cs35l35.c
@@ -756,6 +756,76 @@ static int cs35l35_codec_set_sysclk(struct snd_soc_codec *codec,
 	return ret;
 }
 
+static int cs35l35_boost_inductor(struct cs35l35_private *cs35l35,
+				  int inductor)
+{
+	struct regmap *regmap = cs35l35->regmap;
+	unsigned int bst_ipk = 0;
+
+	/*
+	 * Digital Boost Converter Configuration for feedback,
+	 * ramping, switching frequency, and estimation block seeding.
+	 */
+
+	regmap_update_bits(regmap, CS35L35_BST_CONV_SW_FREQ,
+			   CS35L35_BST_CONV_SWFREQ_MASK, 0x00);
+
+	regmap_read(regmap, CS35L35_BST_PEAK_I, &bst_ipk);
+	bst_ipk &= CS35L35_BST_IPK_MASK;
+
+	switch (inductor) {
+	case 1000: /* 1 uH */
+		regmap_write(regmap, CS35L35_BST_CONV_COEF_1, 0x24);
+		regmap_write(regmap, CS35L35_BST_CONV_COEF_2, 0x24);
+		regmap_update_bits(regmap, CS35L35_BST_CONV_SW_FREQ,
+				   CS35L35_BST_CONV_LBST_MASK, 0x00);
+
+		if (bst_ipk < 0x04)
+			regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x1B);
+		else
+			regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x4E);
+		break;
+	case 1200: /* 1.2 uH */
+		regmap_write(regmap, CS35L35_BST_CONV_COEF_1, 0x20);
+		regmap_write(regmap, CS35L35_BST_CONV_COEF_2, 0x20);
+		regmap_update_bits(regmap, CS35L35_BST_CONV_SW_FREQ,
+				   CS35L35_BST_CONV_LBST_MASK, 0x01);
+
+		if (bst_ipk < 0x04)
+			regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x1B);
+		else
+			regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x47);
+		break;
+	case 1500: /* 1.5uH */
+		regmap_write(regmap, CS35L35_BST_CONV_COEF_1, 0x20);
+		regmap_write(regmap, CS35L35_BST_CONV_COEF_2, 0x20);
+		regmap_update_bits(regmap, CS35L35_BST_CONV_SW_FREQ,
+				   CS35L35_BST_CONV_LBST_MASK, 0x02);
+
+		if (bst_ipk < 0x04)
+			regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x1B);
+		else
+			regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x3C);
+		break;
+	case 2200: /* 2.2uH */
+		regmap_write(regmap, CS35L35_BST_CONV_COEF_1, 0x19);
+		regmap_write(regmap, CS35L35_BST_CONV_COEF_2, 0x25);
+		regmap_update_bits(regmap, CS35L35_BST_CONV_SW_FREQ,
+				   CS35L35_BST_CONV_LBST_MASK, 0x03);
+
+		if (bst_ipk < 0x04)
+			regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x1B);
+		else
+			regmap_write(regmap, CS35L35_BST_CONV_SLOPE_COMP, 0x23);
+		break;
+	default:
+		dev_err(cs35l35->dev, "Invalid Inductor Value %d uH\n",
+			inductor);
+		return -EINVAL;
+	}
+	return 0;
+}
+
 static int cs35l35_codec_probe(struct snd_soc_codec *codec)
 {
 	struct cs35l35_private *cs35l35 = snd_soc_codec_get_drvdata(codec);
@@ -775,6 +845,10 @@ static int cs35l35_codec_probe(struct snd_soc_codec *codec)
 				cs35l35->pdata.bst_ipk <<
 				CS35L35_BST_IPK_SHIFT);
 
+	ret = cs35l35_boost_inductor(cs35l35, cs35l35->pdata.boost_ind);
+	if (ret)
+		return ret;
+
 	if (cs35l35->pdata.gain_zc)
 		regmap_update_bits(cs35l35->regmap, CS35L35_PROTECT_CTL,
 				CS35L35_AMP_GAIN_ZC_MASK,
@@ -1198,6 +1272,14 @@ static int cs35l35_handle_of_data(struct i2c_client *i2c_client,
 		pdata->bst_ipk = (val32 - 1680) / 110;
 	}
 
+	ret = of_property_read_u32(np, "cirrus,boost-ind-nanohenry", &val32);
+	if (ret >= 0) {
+		pdata->boost_ind = val32;
+	} else {
+		dev_err(&i2c_client->dev, "Inductor not specified.\n");
+		return -EINVAL;
+	}
+
 	if (of_property_read_u32(np, "cirrus,sp-drv-strength", &val32) >= 0)
 		pdata->sp_drv_str = val32;
 	if (of_property_read_u32(np, "cirrus,sp-drv-unused", &val32) >= 0)
-- 
cgit v1.2.3


From 486fb9590302f811d44fa15401e1736679d33736 Mon Sep 17 00:00:00 2001
From: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
Date: Thu, 18 May 2017 16:32:38 +0100
Subject: ASoC: cs35l35: Correctly handle 0 for bst_ipk

Zero is a totally valid value to specify for the bst_ipk, as such we
should append CS35L35_VALID_PDATA to ensure that it actually makes it
into the register value.

Signed-off-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 sound/soc/codecs/cs35l35.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'sound/soc/codecs/cs35l35.c')

diff --git a/sound/soc/codecs/cs35l35.c b/sound/soc/codecs/cs35l35.c
index c6eabb8610f0..375be49b7fd0 100644
--- a/sound/soc/codecs/cs35l35.c
+++ b/sound/soc/codecs/cs35l35.c
@@ -1269,7 +1269,7 @@ static int cs35l35_handle_of_data(struct i2c_client *i2c_client,
 			return -EINVAL;
 		}
 
-		pdata->bst_ipk = (val32 - 1680) / 110;
+		pdata->bst_ipk = ((val32 - 1680) / 110) | CS35L35_VALID_PDATA;
 	}
 
 	ret = of_property_read_u32(np, "cirrus,boost-ind-nanohenry", &val32);
-- 
cgit v1.2.3


From dc43f46a9b6988a40d4e11d05b8107d4546c61b9 Mon Sep 17 00:00:00 2001
From: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
Date: Wed, 31 May 2017 16:51:13 +0100
Subject: ASoC: cs35l35: Add additional delay for reset

Very fast systems may violate the minimum constraints for time the reset
line needs to remain low, or communicate with the device too soon after
releasing the reset. Fix this by adding some delays in to allow the chip
to properly reset, also factor out the reset into a function as it is
likely it will be re-used in later additions to the driver.

Signed-off-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
Acked-by: Paul Handrigan <Paul.Handrigan@cirrus.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 sound/soc/codecs/cs35l35.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

(limited to 'sound/soc/codecs/cs35l35.c')

diff --git a/sound/soc/codecs/cs35l35.c b/sound/soc/codecs/cs35l35.c
index f8aef5869b03..5ff12e4116e5 100644
--- a/sound/soc/codecs/cs35l35.c
+++ b/sound/soc/codecs/cs35l35.c
@@ -162,6 +162,14 @@ static bool cs35l35_precious_register(struct device *dev, unsigned int reg)
 	}
 }
 
+static void cs35l35_reset(struct cs35l35_private *cs35l35)
+{
+	gpiod_set_value_cansleep(cs35l35->reset_gpio, 0);
+	usleep_range(2000, 2100);
+	gpiod_set_value_cansleep(cs35l35->reset_gpio, 1);
+	usleep_range(1000, 1100);
+}
+
 static int cs35l35_wait_for_pdn(struct cs35l35_private *cs35l35)
 {
 	int ret;
@@ -1454,7 +1462,7 @@ static int cs35l35_i2c_probe(struct i2c_client *i2c_client,
 		}
 	}
 
-	gpiod_set_value_cansleep(cs35l35->reset_gpio, 1);
+	cs35l35_reset(cs35l35);
 
 	init_completion(&cs35l35->pdn_done);
 
-- 
cgit v1.2.3