[alsa-devel] [PATCH RESEND v2 0/4] Cleanups/Bugfixes and DT Prep for CS42L52
This series fixes a bug and cleans up the platform data so the driver can nicely move to DT.
Convert platform data initialization to regmap_update_bits in i2c_probe. Add GPIO for CODEC Reset. Add print message for Rev ID.
Version 2 splits the regmap_patch bug with the MAX_REGISTER increase. Series based off of a clean for-next branch
Brian Austin (4): ASoC: cs42l52: Add platform data for reset gpio ASoC: cs42l52: increase MAX_REGISTER for regmap_register_patch ASoC: cs42l52: convert pdata config to regmap_update_bits ASoC: cs42l52: Add chip rev id message
include/sound/cs42l52.h | 2 + sound/soc/codecs/cs42l52.c | 93 +++++++++++++++++++++++++++------------------- sound/soc/codecs/cs42l52.h | 2 +- 3 files changed, 57 insertions(+), 40 deletions(-)
This patch adds platform data support for a reset GPIO. Also uses reset_gpio to toggle reset of the CODEC
Signed-off-by: Brian Austin brian.austin@cirrus.com --- include/sound/cs42l52.h | 2 ++ sound/soc/codecs/cs42l52.c | 21 +++++++++++++++++---- 2 files changed, 19 insertions(+), 4 deletions(-)
diff --git a/include/sound/cs42l52.h b/include/sound/cs42l52.h index 4c68955..7c2be4a 100644 --- a/include/sound/cs42l52.h +++ b/include/sound/cs42l52.h @@ -31,6 +31,8 @@ struct cs42l52_platform_data { /* Charge Pump Freq. Check datasheet Pg73 */ unsigned int chgfreq;
+ /* Reset GPIO */ + unsigned int reset_gpio; };
#endif /* __CS42L52_H */ diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c index be2ba1b..8367f3c 100644 --- a/sound/soc/codecs/cs42l52.c +++ b/sound/soc/codecs/cs42l52.c @@ -17,6 +17,7 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/delay.h> +#include <linux/gpio.h> #include <linux/pm.h> #include <linux/i2c.h> #include <linux/input.h> @@ -1205,6 +1206,7 @@ static int cs42l52_i2c_probe(struct i2c_client *i2c_client, const struct i2c_device_id *id) { struct cs42l52_private *cs42l52; + struct cs42l52_platform_data *pdata = dev_get_platdata(&i2c_client->dev); int ret; unsigned int devid = 0; unsigned int reg; @@ -1222,11 +1224,22 @@ static int cs42l52_i2c_probe(struct i2c_client *i2c_client, return ret; }
- i2c_set_clientdata(i2c_client, cs42l52); + if (pdata) + cs42l52->pdata = *pdata;
- if (dev_get_platdata(&i2c_client->dev)) - memcpy(&cs42l52->pdata, dev_get_platdata(&i2c_client->dev), - sizeof(cs42l52->pdata)); + if (cs42l52->pdata.reset_gpio) { + ret = gpio_request_one(cs42l52->pdata.reset_gpio, + GPIOF_OUT_INIT_HIGH, "CS42L52 /RST"); + if (ret < 0) { + dev_err(&i2c_client->dev, "Failed to request /RST %d: %d\n", + cs42l52->pdata.reset_gpio, ret); + return ret; + } + gpio_set_value_cansleep(cs42l52->pdata.reset_gpio, 0); + gpio_set_value_cansleep(cs42l52->pdata.reset_gpio, 1); + } + + i2c_set_clientdata(i2c_client, cs42l52);
ret = regmap_register_patch(cs42l52->regmap, cs42l52_threshold_patch, ARRAY_SIZE(cs42l52_threshold_patch));
regmap_register_patch fails without the MAX_REGISTER set to highest register written to. Increase to register 0x47
Signed-off-by: Brian Austin brian.austin@cirrus.com --- sound/soc/codecs/cs42l52.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sound/soc/codecs/cs42l52.h b/sound/soc/codecs/cs42l52.h index 4277012..1a9412d 100644 --- a/sound/soc/codecs/cs42l52.h +++ b/sound/soc/codecs/cs42l52.h @@ -269,6 +269,6 @@ #define CS42L52_FIX_BITS1 0x3E #define CS42L52_FIX_BITS2 0x47
-#define CS42L52_MAX_REGISTER 0x34 +#define CS42L52_MAX_REGISTER 0x47
#endif
On Fri, Oct 25, 2013 at 10:01:15AM -0500, Brian Austin wrote:
regmap_register_patch fails without the MAX_REGISTER set to highest register written to. Increase to register 0x47
Hrm. It probably shouldn't be doing that, unless there's some great reason I've not thought of - this is for random undocumented registers which we ought to be able to exclude from the the register map that Linux knows about. What's the root cause?
On Fri, 25 Oct 2013, Mark Brown wrote:
On Fri, Oct 25, 2013 at 10:01:15AM -0500, Brian Austin wrote:
regmap_register_patch fails without the MAX_REGISTER set to highest register written to. Increase to register 0x47
Hrm. It probably shouldn't be doing that, unless there's some great reason I've not thought of - this is for random undocumented registers which we ought to be able to exclude from the the register map that Linux knows about. What's the root cause?
I thought this odd as well, but if I do not have a .max_register defined that is >= a register in the patch function, it will fail at that register. It does make sense that we should not have to define or mention chicken bits for this stuff.
Could it be related to this?
int regmap_register_patch(struct regmap *map, const struct reg_default *regs, int num_regs) { ...
/* Write out first; it's useful to apply even if we fail later. */ for (i = 0; i < num_regs; i++) { ret = _regmap_write(map, regs[i].reg, regs[i].def); if (ret != 0) { dev_err(map->dev, "Failed to write %x = %x: %d\n", regs[i].reg, regs[i].def, ret); goto out; } }
But it does not seem to apply later. I believe that if I call regcache_cache_bypass it might work.
On Fri, Oct 25, 2013 at 12:49:50PM -0500, Brian Austin wrote:
ret = _regmap_write(map, regs[i].reg, regs[i].def); if (ret != 0) {
That's it, yes... it's due to writeable_register() enforcing the max_register check. Hrm, having looked again I'm not seeing a quick and obvious solution to this so I'll go ahead and apply your patch though we should fix things so that it's not needed.
But it does not seem to apply later. I believe that if I call regcache_cache_bypass it might work.
If it does that's odd, the patch application is done with bypass enabled so it should have no effect.
On Fri, 25 Oct 2013, Mark Brown wrote:
On Fri, Oct 25, 2013 at 12:49:50PM -0500, Brian Austin wrote:
ret = _regmap_write(map, regs[i].reg, regs[i].def); if (ret != 0) {
That's it, yes... it's due to writeable_register() enforcing the max_register check. Hrm, having looked again I'm not seeing a quick and obvious solution to this so I'll go ahead and apply your patch though we should fix things so that it's not needed.
I'll take a look and see about a fix.
Thanks
Hrm. It probably shouldn't be doing that, unless there's some great reason I've not thought of - this is for random undocumented registers which we ought to be able to exclude from the the register map that Linux knows about. What's the root cause?
Let me spend some time after the weekend and see what the deal is. It's not a super critical patch and can wait till we figure out what's up.
-Brian
Moving platform data to bus probe and convert to regmap_update_bits. This will work nicer when converted to device tree instead of having it split into multiple probes
Signed-off-by: Brian Austin brian.austin@cirrus.com --- sound/soc/codecs/cs42l52.c | 69 +++++++++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 35 deletions(-)
diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c index 8367f3c..56c5611 100644 --- a/sound/soc/codecs/cs42l52.c +++ b/sound/soc/codecs/cs42l52.c @@ -1117,40 +1117,6 @@ static int cs42l52_probe(struct snd_soc_codec *codec) cs42l52->sysclk = CS42L52_DEFAULT_CLK; cs42l52->config.format = CS42L52_DEFAULT_FORMAT;
- /* Set Platform MICx CFG */ - snd_soc_update_bits(codec, CS42L52_MICA_CTL, - CS42L52_MIC_CTL_TYPE_MASK, - cs42l52->pdata.mica_cfg << - CS42L52_MIC_CTL_TYPE_SHIFT); - - snd_soc_update_bits(codec, CS42L52_MICB_CTL, - CS42L52_MIC_CTL_TYPE_MASK, - cs42l52->pdata.micb_cfg << - CS42L52_MIC_CTL_TYPE_SHIFT); - - /* if Single Ended, Get Mic_Select */ - if (cs42l52->pdata.mica_cfg) - snd_soc_update_bits(codec, CS42L52_MICA_CTL, - CS42L52_MIC_CTL_MIC_SEL_MASK, - cs42l52->pdata.mica_sel << - CS42L52_MIC_CTL_MIC_SEL_SHIFT); - if (cs42l52->pdata.micb_cfg) - snd_soc_update_bits(codec, CS42L52_MICB_CTL, - CS42L52_MIC_CTL_MIC_SEL_MASK, - cs42l52->pdata.micb_sel << - CS42L52_MIC_CTL_MIC_SEL_SHIFT); - - /* Set Platform Charge Pump Freq */ - snd_soc_update_bits(codec, CS42L52_CHARGE_PUMP, - CS42L52_CHARGE_PUMP_MASK, - cs42l52->pdata.chgfreq << - CS42L52_CHARGE_PUMP_SHIFT); - - /* Set Platform Bias Level */ - snd_soc_update_bits(codec, CS42L52_IFACE_CTL2, - CS42L52_IFACE_CTL2_BIAS_LVL, - cs42l52->pdata.micbias_lvl); - return ret; }
@@ -1257,7 +1223,40 @@ static int cs42l52_i2c_probe(struct i2c_client *i2c_client, return ret; }
- regcache_cache_only(cs42l52->regmap, true); + /* Set Platform Data */ + if (cs42l52->pdata.mica_cfg) + regmap_update_bits(cs42l52->regmap, CS42L52_MICA_CTL, + CS42L52_MIC_CTL_TYPE_MASK, + cs42l52->pdata.mica_cfg << + CS42L52_MIC_CTL_TYPE_SHIFT); + + if (cs42l52->pdata.micb_cfg) + regmap_update_bits(cs42l52->regmap, CS42L52_MICB_CTL, + CS42L52_MIC_CTL_TYPE_MASK, + cs42l52->pdata.micb_cfg << + CS42L52_MIC_CTL_TYPE_SHIFT); + + if (cs42l52->pdata.mica_sel) + regmap_update_bits(cs42l52->regmap, CS42L52_MICA_CTL, + CS42L52_MIC_CTL_MIC_SEL_MASK, + cs42l52->pdata.mica_sel << + CS42L52_MIC_CTL_MIC_SEL_SHIFT); + if (cs42l52->pdata.micb_sel) + regmap_update_bits(cs42l52->regmap, CS42L52_MICB_CTL, + CS42L52_MIC_CTL_MIC_SEL_MASK, + cs42l52->pdata.micb_sel << + CS42L52_MIC_CTL_MIC_SEL_SHIFT); + + if (cs42l52->pdata.chgfreq) + regmap_update_bits(cs42l52->regmap, CS42L52_CHARGE_PUMP, + CS42L52_CHARGE_PUMP_MASK, + cs42l52->pdata.chgfreq << + CS42L52_CHARGE_PUMP_SHIFT); + + if (cs42l52->pdata.micbias_lvl) + regmap_update_bits(cs42l52->regmap, CS42L52_IFACE_CTL2, + CS42L52_IFACE_CTL2_BIAS_LVL, + cs42l52->pdata.micbias_lvl);
ret = snd_soc_register_codec(&i2c_client->dev, &soc_codec_dev_cs42l52, &cs42l52_dai, 1);
On Fri, Oct 25, 2013 at 10:01:16AM -0500, Brian Austin wrote:
Moving platform data to bus probe and convert to regmap_update_bits. This will work nicer when converted to device tree instead of having it split into multiple probes
Applied, thanks.
This patch adds a print message at bootup for the CODEC Rev ID
Signed-off-by: Brian Austin brian.austin@cirrus.com --- sound/soc/codecs/cs42l52.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c index 56c5611..8b427c9 100644 --- a/sound/soc/codecs/cs42l52.c +++ b/sound/soc/codecs/cs42l52.c @@ -1223,6 +1223,9 @@ static int cs42l52_i2c_probe(struct i2c_client *i2c_client, return ret; }
+ dev_info(&i2c_client->dev, "Cirrus Logic CS42L52, Revision: %02X\n", + reg & 0xFF); + /* Set Platform Data */ if (cs42l52->pdata.mica_cfg) regmap_update_bits(cs42l52->regmap, CS42L52_MICA_CTL,
participants (2)
-
Brian Austin
-
Mark Brown