Commit 0cd257bf authored by Mark Brown's avatar Mark Brown

ASoC: alc5623: Convert to direct regmap API usage

Convert to directly use the regmap API, allowing us to eliminate the last
user of the ASoC level I/O implementations (there are still open coded
I/O implementations in drivers), avoiding duplicating code in regmap.

We no longer cache the entire CODEC register map on probe since the more
advanced cache infrastructure in regmap is able to fill the cache on
demand.
Signed-off-by: default avatarMark Brown <broonie@linaro.org>
parent e84f2463
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/regmap.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/pcm.h> #include <sound/pcm.h>
...@@ -38,26 +39,13 @@ MODULE_PARM_DESC(caps_charge, "ALC5623 cap charge time (msecs)"); ...@@ -38,26 +39,13 @@ MODULE_PARM_DESC(caps_charge, "ALC5623 cap charge time (msecs)");
/* codec private data */ /* codec private data */
struct alc5623_priv { struct alc5623_priv {
enum snd_soc_control_type control_type; struct regmap *regmap;
u8 id; u8 id;
unsigned int sysclk; unsigned int sysclk;
u16 reg_cache[ALC5623_VENDOR_ID2+2];
unsigned int add_ctrl; unsigned int add_ctrl;
unsigned int jack_det_ctrl; unsigned int jack_det_ctrl;
}; };
static void alc5623_fill_cache(struct snd_soc_codec *codec)
{
int i, step = codec->driver->reg_cache_step;
u16 *cache = codec->reg_cache;
/* not really efficient ... */
codec->cache_bypass = 1;
for (i = 0 ; i < codec->driver->reg_cache_size ; i += step)
cache[i] = snd_soc_read(codec, i);
codec->cache_bypass = 0;
}
static inline int alc5623_reset(struct snd_soc_codec *codec) static inline int alc5623_reset(struct snd_soc_codec *codec)
{ {
return snd_soc_write(codec, ALC5623_RESET, 0); return snd_soc_write(codec, ALC5623_RESET, 0);
...@@ -875,18 +863,28 @@ static struct snd_soc_dai_driver alc5623_dai = { ...@@ -875,18 +863,28 @@ static struct snd_soc_dai_driver alc5623_dai = {
static int alc5623_suspend(struct snd_soc_codec *codec) static int alc5623_suspend(struct snd_soc_codec *codec)
{ {
struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec);
alc5623_set_bias_level(codec, SND_SOC_BIAS_OFF); alc5623_set_bias_level(codec, SND_SOC_BIAS_OFF);
regcache_cache_only(alc5623->regmap, true);
return 0; return 0;
} }
static int alc5623_resume(struct snd_soc_codec *codec) static int alc5623_resume(struct snd_soc_codec *codec)
{ {
int i, step = codec->driver->reg_cache_step; struct alc5623_priv *alc5623 = snd_soc_codec_get_drvdata(codec);
u16 *cache = codec->reg_cache; int ret;
/* Sync reg_cache with the hardware */ /* Sync reg_cache with the hardware */
for (i = 2 ; i < codec->driver->reg_cache_size ; i += step) regcache_cache_only(alc5623->regmap, false);
snd_soc_write(codec, i, cache[i]); ret = regcache_sync(alc5623->regmap);
if (ret != 0) {
dev_err(codec->dev, "Failed to sync register cache: %d\n",
ret);
regcache_cache_only(alc5623->regmap, true);
return ret;
}
alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY); alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
...@@ -906,14 +904,14 @@ static int alc5623_probe(struct snd_soc_codec *codec) ...@@ -906,14 +904,14 @@ static int alc5623_probe(struct snd_soc_codec *codec)
struct snd_soc_dapm_context *dapm = &codec->dapm; struct snd_soc_dapm_context *dapm = &codec->dapm;
int ret; int ret;
ret = snd_soc_codec_set_cache_io(codec, 8, 16, alc5623->control_type); codec->control_data = alc5623->regmap;
ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
if (ret < 0) { if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret; return ret;
} }
alc5623_reset(codec); alc5623_reset(codec);
alc5623_fill_cache(codec);
/* power on device */ /* power on device */
alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY); alc5623_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
...@@ -986,9 +984,15 @@ static struct snd_soc_codec_driver soc_codec_device_alc5623 = { ...@@ -986,9 +984,15 @@ static struct snd_soc_codec_driver soc_codec_device_alc5623 = {
.suspend = alc5623_suspend, .suspend = alc5623_suspend,
.resume = alc5623_resume, .resume = alc5623_resume,
.set_bias_level = alc5623_set_bias_level, .set_bias_level = alc5623_set_bias_level,
.reg_cache_size = ALC5623_VENDOR_ID2+2, };
.reg_word_size = sizeof(u16),
.reg_cache_step = 2, static const struct regmap_config alc5623_regmap = {
.reg_bits = 8,
.val_bits = 16,
.reg_stride = 2,
.max_register = ALC5623_VENDOR_ID2,
.cache_type = REGCACHE_RBTREE,
}; };
/* /*
...@@ -1002,19 +1006,32 @@ static int alc5623_i2c_probe(struct i2c_client *client, ...@@ -1002,19 +1006,32 @@ static int alc5623_i2c_probe(struct i2c_client *client,
{ {
struct alc5623_platform_data *pdata; struct alc5623_platform_data *pdata;
struct alc5623_priv *alc5623; struct alc5623_priv *alc5623;
int ret, vid1, vid2; unsigned int vid1, vid2;
int ret;
vid1 = i2c_smbus_read_word_data(client, ALC5623_VENDOR_ID1); alc5623 = devm_kzalloc(&client->dev, sizeof(struct alc5623_priv),
if (vid1 < 0) { GFP_KERNEL);
dev_err(&client->dev, "failed to read I2C\n"); if (alc5623 == NULL)
return -EIO; return -ENOMEM;
alc5623->regmap = devm_regmap_init_i2c(client, &alc5623_regmap);
if (IS_ERR(alc5623->regmap)) {
ret = PTR_ERR(alc5623->regmap);
dev_err(&client->dev, "Failed to initialise I/O: %d\n", ret);
return ret;
}
ret = regmap_read(alc5623->regmap, ALC5623_VENDOR_ID1, &vid1);
if (ret < 0) {
dev_err(&client->dev, "failed to read vendor ID1: %d\n", ret);
return ret;
} }
vid1 = ((vid1 & 0xff) << 8) | (vid1 >> 8); vid1 = ((vid1 & 0xff) << 8) | (vid1 >> 8);
vid2 = i2c_smbus_read_byte_data(client, ALC5623_VENDOR_ID2); ret = regmap_read(alc5623->regmap, ALC5623_VENDOR_ID2, &vid2);
if (vid2 < 0) { if (ret < 0) {
dev_err(&client->dev, "failed to read I2C\n"); dev_err(&client->dev, "failed to read vendor ID2: %d\n", ret);
return -EIO; return ret;
} }
if ((vid1 != 0x10ec) || (vid2 != id->driver_data)) { if ((vid1 != 0x10ec) || (vid2 != id->driver_data)) {
...@@ -1027,11 +1044,6 @@ static int alc5623_i2c_probe(struct i2c_client *client, ...@@ -1027,11 +1044,6 @@ static int alc5623_i2c_probe(struct i2c_client *client,
dev_dbg(&client->dev, "Found codec id : alc56%02x\n", vid2); dev_dbg(&client->dev, "Found codec id : alc56%02x\n", vid2);
alc5623 = devm_kzalloc(&client->dev, sizeof(struct alc5623_priv),
GFP_KERNEL);
if (alc5623 == NULL)
return -ENOMEM;
pdata = client->dev.platform_data; pdata = client->dev.platform_data;
if (pdata) { if (pdata) {
alc5623->add_ctrl = pdata->add_ctrl; alc5623->add_ctrl = pdata->add_ctrl;
...@@ -1054,7 +1066,6 @@ static int alc5623_i2c_probe(struct i2c_client *client, ...@@ -1054,7 +1066,6 @@ static int alc5623_i2c_probe(struct i2c_client *client,
} }
i2c_set_clientdata(client, alc5623); i2c_set_clientdata(client, alc5623);
alc5623->control_type = SND_SOC_I2C;
ret = snd_soc_register_codec(&client->dev, ret = snd_soc_register_codec(&client->dev,
&soc_codec_device_alc5623, &alc5623_dai, 1); &soc_codec_device_alc5623, &alc5623_dai, 1);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment