[alsa-devel] [PATCH v4 3/4] ASoC: codecs: adau1701: switch to direct regmap API usage
Lars-Peter Clausen
lars at metafoo.de
Mon Jun 24 19:08:38 CEST 2013
On 06/24/2013 04:31 PM, Daniel Mack wrote:
> The hardware I/O has to be open-coded due to registers of unequal sizes.
> Other than that, the transition is straight forward.
>
> Signed-off-by: Daniel Mack <zonque at gmail.com>
Acked-by: Lars-Peter Clausen <lars at metafoo.de>
> ---
> sound/soc/codecs/adau1701.c | 118 +++++++++++++++++++++++++++++++-------------
> 1 file changed, 85 insertions(+), 33 deletions(-)
>
> diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c
> index 770d90e..881bab4 100644
> --- a/sound/soc/codecs/adau1701.c
> +++ b/sound/soc/codecs/adau1701.c
> @@ -16,6 +16,7 @@
> #include <linux/of.h>
> #include <linux/of_gpio.h>
> #include <linux/of_device.h>
> +#include <linux/regmap.h>
> #include <sound/core.h>
> #include <sound/pcm.h>
> #include <sound/pcm_params.h>
> @@ -24,16 +25,16 @@
> #include "sigmadsp.h"
> #include "adau1701.h"
>
> -#define ADAU1701_DSPCTRL 0x1c
> -#define ADAU1701_SEROCTL 0x1e
> -#define ADAU1701_SERICTL 0x1f
> +#define ADAU1701_DSPCTRL 0x081c
> +#define ADAU1701_SEROCTL 0x081e
> +#define ADAU1701_SERICTL 0x081f
>
> -#define ADAU1701_AUXNPOW 0x22
> +#define ADAU1701_AUXNPOW 0x0822
>
> -#define ADAU1701_OSCIPOW 0x26
> -#define ADAU1701_DACSET 0x27
> +#define ADAU1701_OSCIPOW 0x0826
> +#define ADAU1701_DACSET 0x0827
>
> -#define ADAU1701_NUM_REGS 0x28
> +#define ADAU1701_MAX_REGISTER 0x0828
>
> #define ADAU1701_DSPCTRL_CR (1 << 2)
> #define ADAU1701_DSPCTRL_DAM (1 << 3)
> @@ -97,6 +98,7 @@ struct adau1701 {
> unsigned int dai_fmt;
> unsigned int pll_clkdiv;
> unsigned int sysclk;
> + struct regmap *regmap;
> };
>
> static const struct snd_kcontrol_new adau1701_controls[] = {
> @@ -128,7 +130,7 @@ static const struct snd_soc_dapm_route adau1701_dapm_routes[] = {
> { "ADC", NULL, "IN1" },
> };
>
> -static unsigned int adau1701_register_size(struct snd_soc_codec *codec,
> +static unsigned int adau1701_register_size(struct device *dev,
> unsigned int reg)
> {
> switch (reg) {
> @@ -142,33 +144,42 @@ static unsigned int adau1701_register_size(struct snd_soc_codec *codec,
> return 1;
> }
>
> - dev_err(codec->dev, "Unsupported register address: %d\n", reg);
> + dev_err(dev, "Unsupported register address: %d\n", reg);
> return 0;
> }
>
> -static int adau1701_write(struct snd_soc_codec *codec, unsigned int reg,
> - unsigned int value)
> +static bool adau1701_volatile_reg(struct device *dev, unsigned int reg)
> {
> + switch (reg) {
> + case ADAU1701_DACSET:
> + return true;
> + default:
> + return false;
> + }
> +}
> +
> +static int adau1701_reg_write(void *context, unsigned int reg,
> + unsigned int value)
> +{
> + struct i2c_client *client = context;
> unsigned int i;
> unsigned int size;
> uint8_t buf[4];
> int ret;
>
> - size = adau1701_register_size(codec, reg);
> + size = adau1701_register_size(&client->dev, reg);
> if (size == 0)
> return -EINVAL;
>
> - snd_soc_cache_write(codec, reg, value);
> -
> - buf[0] = 0x08;
> - buf[1] = reg;
> + buf[0] = reg >> 8;
> + buf[1] = reg & 0xff;
>
> for (i = size + 1; i >= 2; --i) {
> buf[i] = value;
> value >>= 8;
> }
>
> - ret = i2c_master_send(to_i2c_client(codec->dev), buf, size + 2);
> + ret = i2c_master_send(client, buf, size + 2);
> if (ret == size + 2)
> return 0;
> else if (ret < 0)
> @@ -177,16 +188,45 @@ static int adau1701_write(struct snd_soc_codec *codec, unsigned int reg,
> return -EIO;
> }
>
> -static unsigned int adau1701_read(struct snd_soc_codec *codec, unsigned int reg)
> +static int adau1701_reg_read(void *context, unsigned int reg,
> + unsigned int *value)
> {
> - unsigned int value;
> - unsigned int ret;
> + int ret;
> + unsigned int i;
> + unsigned int size;
> + uint8_t send_buf[2], recv_buf[3];
> + struct i2c_client *client = context;
> + struct i2c_msg msgs[2];
> +
> + size = adau1701_register_size(&client->dev, reg);
> + if (size == 0)
> + return -EINVAL;
>
> - ret = snd_soc_cache_read(codec, reg, &value);
> - if (ret)
> + send_buf[0] = reg >> 8;
> + send_buf[1] = reg & 0xff;
> +
> + msgs[0].addr = client->addr;
> + msgs[0].len = sizeof(send_buf);
> + msgs[0].buf = send_buf;
> + msgs[0].flags = 0;
> +
> + msgs[1].addr = client->addr;
> + msgs[1].len = size;
> + msgs[1].buf = recv_buf;
> + msgs[1].flags = I2C_M_RD;
> +
> + ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
> + if (ret < 0)
> return ret;
> + else if (ret != ARRAY_SIZE(msgs))
> + return -EIO;
> +
> + *value = 0;
> +
> + for (i = 0; i < size; i++)
> + *value |= recv_buf[i] << (i * 8);
>
> - return value;
> + return 0;
> }
>
> static int adau1701_reset(struct snd_soc_codec *codec, unsigned int clkdiv)
> @@ -242,8 +282,11 @@ static int adau1701_reset(struct snd_soc_codec *codec, unsigned int clkdiv)
> }
> }
>
> - snd_soc_write(codec, ADAU1701_DACSET, ADAU1701_DACSET_DACINIT);
> - snd_soc_write(codec, ADAU1701_DSPCTRL, ADAU1701_DSPCTRL_CR);
> + regmap_write(adau1701->regmap, ADAU1701_DACSET, ADAU1701_DACSET_DACINIT);
> + regmap_write(adau1701->regmap, ADAU1701_DSPCTRL, ADAU1701_DSPCTRL_CR);
> +
> + regcache_mark_dirty(adau1701->regmap);
> + regcache_sync(adau1701->regmap);
>
> return 0;
> }
> @@ -429,8 +472,8 @@ static int adau1701_set_dai_fmt(struct snd_soc_dai *codec_dai,
>
> adau1701->dai_fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
>
> - snd_soc_write(codec, ADAU1701_SERICTL, serictl);
> - snd_soc_update_bits(codec, ADAU1701_SEROCTL,
> + regmap_write(adau1701->regmap, ADAU1701_SERICTL, serictl);
> + regmap_update_bits(adau1701->regmap, ADAU1701_SEROCTL,
> ~ADAU1701_SEROCTL_WORD_LEN_MASK, seroctl);
>
> return 0;
> @@ -567,9 +610,6 @@ static struct snd_soc_codec_driver adau1701_codec_drv = {
> .set_bias_level = adau1701_set_bias_level,
> .idle_bias_off = true,
>
> - .reg_cache_size = ADAU1701_NUM_REGS,
> - .reg_word_size = sizeof(u16),
> -
> .controls = adau1701_controls,
> .num_controls = ARRAY_SIZE(adau1701_controls),
> .dapm_widgets = adau1701_dapm_widgets,
> @@ -577,12 +617,19 @@ static struct snd_soc_codec_driver adau1701_codec_drv = {
> .dapm_routes = adau1701_dapm_routes,
> .num_dapm_routes = ARRAY_SIZE(adau1701_dapm_routes),
>
> - .write = adau1701_write,
> - .read = adau1701_read,
> -
> .set_sysclk = adau1701_set_sysclk,
> };
>
> +static const struct regmap_config adau1701_regmap = {
> + .reg_bits = 16,
> + .val_bits = 32,
> + .max_register = ADAU1701_MAX_REGISTER,
> + .cache_type = REGCACHE_RBTREE,
> + .volatile_reg = adau1701_volatile_reg,
> + .reg_write = adau1701_reg_write,
> + .reg_read = adau1701_reg_read,
> +};
> +
> static int adau1701_i2c_probe(struct i2c_client *client,
> const struct i2c_device_id *id)
> {
> @@ -596,6 +643,11 @@ static int adau1701_i2c_probe(struct i2c_client *client,
> if (!adau1701)
> return -ENOMEM;
>
> + adau1701->regmap = devm_regmap_init(dev, NULL, client,
> + &adau1701_regmap);
> + if (IS_ERR(adau1701->regmap))
> + return PTR_ERR(adau1701->regmap);
> +
> if (dev->of_node) {
> gpio_nreset = of_get_named_gpio(dev->of_node, "reset-gpio", 0);
> if (gpio_nreset < 0 && gpio_nreset != -ENOENT)
More information about the Alsa-devel
mailing list