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>
This commit is contained in:
Brian Austin 2017-05-18 16:32:36 +01:00 committed by Mark Brown
parent 2ea659a9ef
commit b7c752d68a
3 changed files with 90 additions and 0 deletions

View File

@ -99,6 +99,8 @@ struct cs35l35_platform_data {
bool shared_bst; bool shared_bst;
/* Specifies this amp is using an external boost supply */ /* Specifies this amp is using an external boost supply */
bool ext_bst; bool ext_bst;
/* Inductor Value */
int boost_ind;
/* ClassH Algorithm */ /* ClassH Algorithm */
struct classh_cfg classh_algo; struct classh_cfg classh_algo;
/* Monitor Config */ /* Monitor Config */

View File

@ -756,6 +756,76 @@ static int cs35l35_codec_set_sysclk(struct snd_soc_codec *codec,
return ret; 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) static int cs35l35_codec_probe(struct snd_soc_codec *codec)
{ {
struct cs35l35_private *cs35l35 = snd_soc_codec_get_drvdata(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->pdata.bst_ipk <<
CS35L35_BST_IPK_SHIFT); CS35L35_BST_IPK_SHIFT);
ret = cs35l35_boost_inductor(cs35l35, cs35l35->pdata.boost_ind);
if (ret)
return ret;
if (cs35l35->pdata.gain_zc) if (cs35l35->pdata.gain_zc)
regmap_update_bits(cs35l35->regmap, CS35L35_PROTECT_CTL, regmap_update_bits(cs35l35->regmap, CS35L35_PROTECT_CTL,
CS35L35_AMP_GAIN_ZC_MASK, 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; 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) if (of_property_read_u32(np, "cirrus,sp-drv-strength", &val32) >= 0)
pdata->sp_drv_str = val32; pdata->sp_drv_str = val32;
if (of_property_read_u32(np, "cirrus,sp-drv-unused", &val32) >= 0) if (of_property_read_u32(np, "cirrus,sp-drv-unused", &val32) >= 0)

View File

@ -200,6 +200,12 @@
#define CS35L35_SP_I2S_DRV_MASK 0x03 #define CS35L35_SP_I2S_DRV_MASK 0x03
#define CS35L35_SP_I2S_DRV_SHIFT 0 #define CS35L35_SP_I2S_DRV_SHIFT 0
/* Boost Converter Config */
#define CS35L35_BST_CONV_COEFF_MASK 0xFF
#define CS35L35_BST_CONV_SLOPE_MASK 0xFF
#define CS35L35_BST_CONV_LBST_MASK 0x03
#define CS35L35_BST_CONV_SWFREQ_MASK 0xF0
/* Class H Algorithm Control */ /* Class H Algorithm Control */
#define CS35L35_CH_STEREO_MASK 0x40 #define CS35L35_CH_STEREO_MASK 0x40
#define CS35L35_CH_STEREO_SHIFT 6 #define CS35L35_CH_STEREO_SHIFT 6