* [PATCH v4 1/4] ASoC: codecs: adau1701: move firmware download to adau1701_reset()
2013-06-24 14:31 [PATCH v4 0/4] ASoC: codecs: some more improvements for adau1701 Daniel Mack
@ 2013-06-24 14:31 ` Daniel Mack
2013-06-24 17:12 ` Lars-Peter Clausen
2013-06-24 14:31 ` [PATCH v4 2/4] ASoC: codecs: adau1701: allow configuration of PLL mode pins Daniel Mack
` (2 subsequent siblings)
3 siblings, 1 reply; 7+ messages in thread
From: Daniel Mack @ 2013-06-24 14:31 UTC (permalink / raw)
To: alsa-devel; +Cc: broonie, lars, Daniel Mack
The chip needs a new download after each reset, so the code to do that
needs to live in adau1701_reset().
Signed-off-by: Daniel Mack <zonque@gmail.com>
---
sound/soc/codecs/adau1701.c | 32 ++++++++++++--------------------
1 file changed, 12 insertions(+), 20 deletions(-)
diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c
index b6b1a77..997fc3b 100644
--- a/sound/soc/codecs/adau1701.c
+++ b/sound/soc/codecs/adau1701.c
@@ -184,27 +184,20 @@ static unsigned int adau1701_read(struct snd_soc_codec *codec, unsigned int reg)
return value;
}
-static void adau1701_reset(struct snd_soc_codec *codec)
+static int adau1701_reset(struct snd_soc_codec *codec)
{
struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec);
-
- if (!gpio_is_valid(adau1701->gpio_nreset))
- return;
-
- gpio_set_value(adau1701->gpio_nreset, 0);
- /* minimum reset time is 20ns */
- udelay(1);
- gpio_set_value(adau1701->gpio_nreset, 1);
- /* power-up time may be as long as 85ms */
- mdelay(85);
-}
-
-static int adau1701_init(struct snd_soc_codec *codec)
-{
- int ret;
struct i2c_client *client = to_i2c_client(codec->dev);
+ int ret;
- adau1701_reset(codec);
+ if (gpio_is_valid(adau1701->gpio_nreset)) {
+ gpio_set_value(adau1701->gpio_nreset, 0);
+ /* minimum reset time is 20ns */
+ udelay(1);
+ gpio_set_value(adau1701->gpio_nreset, 1);
+ /* power-up time may be as long as 85ms */
+ mdelay(85);
+ }
ret = process_sigma_firmware(client, ADAU1701_FIRMWARE);
if (ret) {
@@ -213,6 +206,7 @@ static int adau1701_init(struct snd_soc_codec *codec)
}
snd_soc_write(codec, ADAU1701_DACSET, ADAU1701_DACSET_DACINIT);
+ snd_soc_write(codec, ADAU1701_DSPCTRL, ADAU1701_DSPCTRL_CR);
return 0;
}
@@ -498,12 +492,10 @@ static int adau1701_probe(struct snd_soc_codec *codec)
codec->control_data = to_i2c_client(codec->dev);
- ret = adau1701_init(codec);
+ ret = adau1701_reset(codec);
if (ret)
return ret;
- snd_soc_write(codec, ADAU1701_DSPCTRL, ADAU1701_DSPCTRL_CR);
-
return 0;
}
--
1.8.1.4
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH v4 1/4] ASoC: codecs: adau1701: move firmware download to adau1701_reset()
2013-06-24 14:31 ` [PATCH v4 1/4] ASoC: codecs: adau1701: move firmware download to adau1701_reset() Daniel Mack
@ 2013-06-24 17:12 ` Lars-Peter Clausen
0 siblings, 0 replies; 7+ messages in thread
From: Lars-Peter Clausen @ 2013-06-24 17:12 UTC (permalink / raw)
To: Daniel Mack; +Cc: alsa-devel, broonie
On 06/24/2013 04:31 PM, Daniel Mack wrote:
> The chip needs a new download after each reset, so the code to do that
> needs to live in adau1701_reset().
>
> Signed-off-by: Daniel Mack <zonque@gmail.com>
Acked-by: Lars-Peter Clausen <lars@metafoo.de>
> ---
> sound/soc/codecs/adau1701.c | 32 ++++++++++++--------------------
> 1 file changed, 12 insertions(+), 20 deletions(-)
>
> diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c
> index b6b1a77..997fc3b 100644
> --- a/sound/soc/codecs/adau1701.c
> +++ b/sound/soc/codecs/adau1701.c
> @@ -184,27 +184,20 @@ static unsigned int adau1701_read(struct snd_soc_codec *codec, unsigned int reg)
> return value;
> }
>
> -static void adau1701_reset(struct snd_soc_codec *codec)
> +static int adau1701_reset(struct snd_soc_codec *codec)
> {
> struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec);
> -
> - if (!gpio_is_valid(adau1701->gpio_nreset))
> - return;
> -
> - gpio_set_value(adau1701->gpio_nreset, 0);
> - /* minimum reset time is 20ns */
> - udelay(1);
> - gpio_set_value(adau1701->gpio_nreset, 1);
> - /* power-up time may be as long as 85ms */
> - mdelay(85);
> -}
> -
> -static int adau1701_init(struct snd_soc_codec *codec)
> -{
> - int ret;
> struct i2c_client *client = to_i2c_client(codec->dev);
> + int ret;
>
> - adau1701_reset(codec);
> + if (gpio_is_valid(adau1701->gpio_nreset)) {
> + gpio_set_value(adau1701->gpio_nreset, 0);
> + /* minimum reset time is 20ns */
> + udelay(1);
> + gpio_set_value(adau1701->gpio_nreset, 1);
> + /* power-up time may be as long as 85ms */
> + mdelay(85);
> + }
>
> ret = process_sigma_firmware(client, ADAU1701_FIRMWARE);
> if (ret) {
> @@ -213,6 +206,7 @@ static int adau1701_init(struct snd_soc_codec *codec)
> }
>
> snd_soc_write(codec, ADAU1701_DACSET, ADAU1701_DACSET_DACINIT);
> + snd_soc_write(codec, ADAU1701_DSPCTRL, ADAU1701_DSPCTRL_CR);
>
> return 0;
> }
> @@ -498,12 +492,10 @@ static int adau1701_probe(struct snd_soc_codec *codec)
>
> codec->control_data = to_i2c_client(codec->dev);
>
> - ret = adau1701_init(codec);
> + ret = adau1701_reset(codec);
> if (ret)
> return ret;
>
> - snd_soc_write(codec, ADAU1701_DSPCTRL, ADAU1701_DSPCTRL_CR);
> -
> return 0;
> }
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v4 2/4] ASoC: codecs: adau1701: allow configuration of PLL mode pins
2013-06-24 14:31 [PATCH v4 0/4] ASoC: codecs: some more improvements for adau1701 Daniel Mack
2013-06-24 14:31 ` [PATCH v4 1/4] ASoC: codecs: adau1701: move firmware download to adau1701_reset() Daniel Mack
@ 2013-06-24 14:31 ` Daniel Mack
2013-06-24 14:31 ` [PATCH v4 3/4] ASoC: codecs: adau1701: switch to direct regmap API usage Daniel Mack
2013-06-24 14:31 ` [PATCH v4 4/4] ASoC: codecs: adau1701: add support for pin muxing Daniel Mack
3 siblings, 0 replies; 7+ messages in thread
From: Daniel Mack @ 2013-06-24 14:31 UTC (permalink / raw)
To: alsa-devel; +Cc: broonie, lars, Daniel Mack
The ADAU1701 has 2 hardware pins to configure the PLL mode in accordance
to the MCLK-to-LRCLK ratio. These pins have to be stable before the chip
is released from reset, and a full reset cycle, including a new firmware
download is needed whenever they change.
This patch adds GPIO properties to the DT bindings of the Codec, and
implements makes the set_sysclk memorize the configured sysclk.
Because the run-time parameters are unknown at probe time, the first
firmware download is postponed to the first hw_params call, when the
driver can determine the mclk/lrclk divider. Subsequent downloads
are only issued when the divider configuration changes.
Signed-off-by: Daniel Mack <zonque@gmail.com>
Acked-by: Lars-Peter Clausen <lars@metafoo.de>
---
.../devicetree/bindings/sound/adi,adau1701.txt | 6 ++
sound/soc/codecs/adau1701.c | 105 +++++++++++++++++++--
2 files changed, 104 insertions(+), 7 deletions(-)
diff --git a/Documentation/devicetree/bindings/sound/adi,adau1701.txt b/Documentation/devicetree/bindings/sound/adi,adau1701.txt
index 3afeda7..a9fbed1 100644
--- a/Documentation/devicetree/bindings/sound/adi,adau1701.txt
+++ b/Documentation/devicetree/bindings/sound/adi,adau1701.txt
@@ -11,6 +11,11 @@ Optional properties:
- reset-gpio: A GPIO spec to define which pin is connected to the
chip's !RESET pin. If specified, the driver will
assert a hardware reset at probe time.
+ - adi,pll-mode-gpios: An array of two GPIO specs to describe the GPIOs
+ the ADAU's PLL config pins are connected to.
+ The state of the pins are set according to the
+ configured clock divider on ASoC side before the
+ firmware is loaded.
Examples:
@@ -19,5 +24,6 @@ Examples:
compatible = "adi,adau1701";
reg = <0x34>;
reset-gpio = <&gpio 23 0>;
+ adi,pll-mode-gpios = <&gpio 24 0 &gpio 25 0>;
};
};
diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c
index 997fc3b..770d90e 100644
--- a/sound/soc/codecs/adau1701.c
+++ b/sound/soc/codecs/adau1701.c
@@ -87,11 +87,16 @@
#define ADAU1701_OSCIPOW_OPD 0x04
#define ADAU1701_DACSET_DACINIT 1
+#define ADAU1707_CLKDIV_UNSET (-1UL)
+
#define ADAU1701_FIRMWARE "adau1701.bin"
struct adau1701 {
int gpio_nreset;
+ int gpio_pll_mode[2];
unsigned int dai_fmt;
+ unsigned int pll_clkdiv;
+ unsigned int sysclk;
};
static const struct snd_kcontrol_new adau1701_controls[] = {
@@ -184,12 +189,38 @@ static unsigned int adau1701_read(struct snd_soc_codec *codec, unsigned int reg)
return value;
}
-static int adau1701_reset(struct snd_soc_codec *codec)
+static int adau1701_reset(struct snd_soc_codec *codec, unsigned int clkdiv)
{
struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec);
struct i2c_client *client = to_i2c_client(codec->dev);
int ret;
+ if (clkdiv != ADAU1707_CLKDIV_UNSET &&
+ gpio_is_valid(adau1701->gpio_pll_mode[0]) &&
+ gpio_is_valid(adau1701->gpio_pll_mode[1])) {
+ switch (clkdiv) {
+ case 64:
+ gpio_set_value(adau1701->gpio_pll_mode[0], 0);
+ gpio_set_value(adau1701->gpio_pll_mode[1], 0);
+ break;
+ case 256:
+ gpio_set_value(adau1701->gpio_pll_mode[0], 0);
+ gpio_set_value(adau1701->gpio_pll_mode[1], 1);
+ break;
+ case 384:
+ gpio_set_value(adau1701->gpio_pll_mode[0], 1);
+ gpio_set_value(adau1701->gpio_pll_mode[1], 0);
+ break;
+ case 0: /* fallback */
+ case 512:
+ gpio_set_value(adau1701->gpio_pll_mode[0], 1);
+ gpio_set_value(adau1701->gpio_pll_mode[1], 1);
+ break;
+ }
+ }
+
+ adau1701->pll_clkdiv = clkdiv;
+
if (gpio_is_valid(adau1701->gpio_nreset)) {
gpio_set_value(adau1701->gpio_nreset, 0);
/* minimum reset time is 20ns */
@@ -199,10 +230,16 @@ static int adau1701_reset(struct snd_soc_codec *codec)
mdelay(85);
}
- ret = process_sigma_firmware(client, ADAU1701_FIRMWARE);
- if (ret) {
- dev_warn(codec->dev, "Failed to load firmware\n");
- return ret;
+ /*
+ * Postpone the firmware download to a point in time when we
+ * know the correct PLL setup
+ */
+ if (clkdiv != ADAU1707_CLKDIV_UNSET) {
+ ret = process_sigma_firmware(client, ADAU1701_FIRMWARE);
+ if (ret) {
+ dev_warn(codec->dev, "Failed to load firmware\n");
+ return ret;
+ }
}
snd_soc_write(codec, ADAU1701_DACSET, ADAU1701_DACSET_DACINIT);
@@ -285,8 +322,22 @@ static int adau1701_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
{
struct snd_soc_codec *codec = dai->codec;
+ struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec);
+ unsigned int clkdiv = adau1701->sysclk / params_rate(params);
snd_pcm_format_t format;
unsigned int val;
+ int ret;
+
+ /*
+ * If the mclk/lrclk ratio changes, the chip needs updated PLL
+ * mode GPIO settings, and a full reset cycle, including a new
+ * firmware upload.
+ */
+ if (clkdiv != adau1701->pll_clkdiv) {
+ ret = adau1701_reset(codec, clkdiv);
+ if (ret < 0)
+ return ret;
+ }
switch (params_rate(params)) {
case 192000:
@@ -429,6 +480,7 @@ static int adau1701_set_sysclk(struct snd_soc_codec *codec, int clk_id,
int source, unsigned int freq, int dir)
{
unsigned int val;
+ struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec);
switch (clk_id) {
case ADAU1701_CLK_SRC_OSC:
@@ -442,6 +494,7 @@ static int adau1701_set_sysclk(struct snd_soc_codec *codec, int clk_id,
}
snd_soc_update_bits(codec, ADAU1701_OSCIPOW, ADAU1701_OSCIPOW_OPD, val);
+ adau1701->sysclk = freq;
return 0;
}
@@ -489,11 +542,21 @@ MODULE_DEVICE_TABLE(of, adau1701_dt_ids);
static int adau1701_probe(struct snd_soc_codec *codec)
{
int ret;
+ struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec);
codec->control_data = to_i2c_client(codec->dev);
- ret = adau1701_reset(codec);
- if (ret)
+ /*
+ * Let the pll_clkdiv variable default to something that won't happen
+ * at runtime. That way, we can postpone the firmware download from
+ * adau1701_reset() to a point in time when we know the correct PLL
+ * mode parameters.
+ */
+ adau1701->pll_clkdiv = ADAU1707_CLKDIV_UNSET;
+
+ /* initalize with pre-configured pll mode settings */
+ ret = adau1701_reset(codec, adau1701->pll_clkdiv);
+ if (ret < 0)
return ret;
return 0;
@@ -526,6 +589,7 @@ static int adau1701_i2c_probe(struct i2c_client *client,
struct adau1701 *adau1701;
struct device *dev = &client->dev;
int gpio_nreset = -EINVAL;
+ int gpio_pll_mode[2] = { -EINVAL, -EINVAL };
int ret;
adau1701 = devm_kzalloc(dev, sizeof(*adau1701), GFP_KERNEL);
@@ -536,6 +600,16 @@ static int adau1701_i2c_probe(struct i2c_client *client,
gpio_nreset = of_get_named_gpio(dev->of_node, "reset-gpio", 0);
if (gpio_nreset < 0 && gpio_nreset != -ENOENT)
return gpio_nreset;
+
+ gpio_pll_mode[0] = of_get_named_gpio(dev->of_node,
+ "adi,pll-mode-gpios", 0);
+ if (gpio_pll_mode[0] < 0 && gpio_pll_mode[0] != -ENOENT)
+ return gpio_pll_mode[0];
+
+ gpio_pll_mode[1] = of_get_named_gpio(dev->of_node,
+ "adi,pll-mode-gpios", 1);
+ if (gpio_pll_mode[1] < 0 && gpio_pll_mode[1] != -ENOENT)
+ return gpio_pll_mode[1];
}
if (gpio_is_valid(gpio_nreset)) {
@@ -545,7 +619,24 @@ static int adau1701_i2c_probe(struct i2c_client *client,
return ret;
}
+ if (gpio_is_valid(gpio_pll_mode[0]) &&
+ gpio_is_valid(gpio_pll_mode[1])) {
+ ret = devm_gpio_request_one(dev, gpio_pll_mode[0],
+ GPIOF_OUT_INIT_LOW,
+ "ADAU1701 PLL mode 0");
+ if (ret < 0)
+ return ret;
+
+ ret = devm_gpio_request_one(dev, gpio_pll_mode[1],
+ GPIOF_OUT_INIT_LOW,
+ "ADAU1701 PLL mode 1");
+ if (ret < 0)
+ return ret;
+ }
+
adau1701->gpio_nreset = gpio_nreset;
+ adau1701->gpio_pll_mode[0] = gpio_pll_mode[0];
+ adau1701->gpio_pll_mode[1] = gpio_pll_mode[1];
i2c_set_clientdata(client, adau1701);
ret = snd_soc_register_codec(&client->dev, &adau1701_codec_drv,
--
1.8.1.4
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH v4 3/4] ASoC: codecs: adau1701: switch to direct regmap API usage
2013-06-24 14:31 [PATCH v4 0/4] ASoC: codecs: some more improvements for adau1701 Daniel Mack
2013-06-24 14:31 ` [PATCH v4 1/4] ASoC: codecs: adau1701: move firmware download to adau1701_reset() Daniel Mack
2013-06-24 14:31 ` [PATCH v4 2/4] ASoC: codecs: adau1701: allow configuration of PLL mode pins Daniel Mack
@ 2013-06-24 14:31 ` Daniel Mack
2013-06-24 17:08 ` Lars-Peter Clausen
2013-06-24 14:31 ` [PATCH v4 4/4] ASoC: codecs: adau1701: add support for pin muxing Daniel Mack
3 siblings, 1 reply; 7+ messages in thread
From: Daniel Mack @ 2013-06-24 14:31 UTC (permalink / raw)
To: alsa-devel; +Cc: broonie, lars, Daniel Mack
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@gmail.com>
---
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)
--
1.8.1.4
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH v4 3/4] ASoC: codecs: adau1701: switch to direct regmap API usage
2013-06-24 14:31 ` [PATCH v4 3/4] ASoC: codecs: adau1701: switch to direct regmap API usage Daniel Mack
@ 2013-06-24 17:08 ` Lars-Peter Clausen
0 siblings, 0 replies; 7+ messages in thread
From: Lars-Peter Clausen @ 2013-06-24 17:08 UTC (permalink / raw)
To: Daniel Mack; +Cc: alsa-devel, broonie
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@gmail.com>
Acked-by: Lars-Peter Clausen <lars@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)
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v4 4/4] ASoC: codecs: adau1701: add support for pin muxing
2013-06-24 14:31 [PATCH v4 0/4] ASoC: codecs: some more improvements for adau1701 Daniel Mack
` (2 preceding siblings ...)
2013-06-24 14:31 ` [PATCH v4 3/4] ASoC: codecs: adau1701: switch to direct regmap API usage Daniel Mack
@ 2013-06-24 14:31 ` Daniel Mack
3 siblings, 0 replies; 7+ messages in thread
From: Daniel Mack @ 2013-06-24 14:31 UTC (permalink / raw)
To: alsa-devel; +Cc: broonie, lars, Daniel Mack
The ADAU1701 has 12 pins that can be configured depending on the system
configuration. Allow settting the corresponding registers from DT.
Signed-off-by: Daniel Mack <zonque@gmail.com>
Acked-by: Lars-Peter Clausen <lars@metafoo.de>
---
.../devicetree/bindings/sound/adi,adau1701.txt | 6 ++++
sound/soc/codecs/adau1701.c | 32 ++++++++++++++++++++--
2 files changed, 36 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/sound/adi,adau1701.txt b/Documentation/devicetree/bindings/sound/adi,adau1701.txt
index a9fbed1..547a49b 100644
--- a/Documentation/devicetree/bindings/sound/adi,adau1701.txt
+++ b/Documentation/devicetree/bindings/sound/adi,adau1701.txt
@@ -16,6 +16,10 @@ Optional properties:
The state of the pins are set according to the
configured clock divider on ASoC side before the
firmware is loaded.
+ - adi,pin-config: An array of 12 numerical values selecting one of the
+ pin configurations as described in the datasheet,
+ table 53. Note that the value of this property has
+ to be prefixed with '/bits/ 8'.
Examples:
@@ -25,5 +29,7 @@ Examples:
reg = <0x34>;
reset-gpio = <&gpio 23 0>;
adi,pll-mode-gpios = <&gpio 24 0 &gpio 25 0>;
+ adi,pin-config = /bits/ 8 <0x4 0x7 0x5 0x5 0x4 0x4
+ 0x4 0x4 0x4 0x4 0x4 0x4>;
};
};
diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c
index 881bab4..0e250f1 100644
--- a/sound/soc/codecs/adau1701.c
+++ b/sound/soc/codecs/adau1701.c
@@ -30,6 +30,9 @@
#define ADAU1701_SERICTL 0x081f
#define ADAU1701_AUXNPOW 0x0822
+#define ADAU1701_PINCONF_0 0x0820
+#define ADAU1701_PINCONF_1 0x0821
+#define ADAU1701_AUXNPOW 0x0822
#define ADAU1701_OSCIPOW 0x0826
#define ADAU1701_DACSET 0x0827
@@ -99,6 +102,7 @@ struct adau1701 {
unsigned int pll_clkdiv;
unsigned int sysclk;
struct regmap *regmap;
+ u8 pin_config[12];
};
static const struct snd_kcontrol_new adau1701_controls[] = {
@@ -134,6 +138,9 @@ static unsigned int adau1701_register_size(struct device *dev,
unsigned int reg)
{
switch (reg) {
+ case ADAU1701_PINCONF_0:
+ case ADAU1701_PINCONF_1:
+ return 3;
case ADAU1701_DSPCTRL:
case ADAU1701_SEROCTL:
case ADAU1701_AUXNPOW:
@@ -164,7 +171,7 @@ static int adau1701_reg_write(void *context, unsigned int reg,
struct i2c_client *client = context;
unsigned int i;
unsigned int size;
- uint8_t buf[4];
+ uint8_t buf[5];
int ret;
size = adau1701_register_size(&client->dev, reg);
@@ -584,7 +591,8 @@ MODULE_DEVICE_TABLE(of, adau1701_dt_ids);
static int adau1701_probe(struct snd_soc_codec *codec)
{
- int ret;
+ int i, ret;
+ unsigned int val;
struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec);
codec->control_data = to_i2c_client(codec->dev);
@@ -602,6 +610,19 @@ static int adau1701_probe(struct snd_soc_codec *codec)
if (ret < 0)
return ret;
+ /* set up pin config */
+ val = 0;
+ for (i = 0; i < 6; i++)
+ val |= adau1701->pin_config[i] << (i * 4);
+
+ regmap_write(adau1701->regmap, ADAU1701_PINCONF_0, val);
+
+ val = 0;
+ for (i = 0; i < 6; i++)
+ val |= adau1701->pin_config[i + 6] << (i * 4);
+
+ regmap_write(adau1701->regmap, ADAU1701_PINCONF_1, val);
+
return 0;
}
@@ -662,6 +683,13 @@ static int adau1701_i2c_probe(struct i2c_client *client,
"adi,pll-mode-gpios", 1);
if (gpio_pll_mode[1] < 0 && gpio_pll_mode[1] != -ENOENT)
return gpio_pll_mode[1];
+
+ of_property_read_u32(dev->of_node, "adi,pll-clkdiv",
+ &adau1701->pll_clkdiv);
+
+ of_property_read_u8_array(dev->of_node, "adi,pin-config",
+ adau1701->pin_config,
+ ARRAY_SIZE(adau1701->pin_config));
}
if (gpio_is_valid(gpio_nreset)) {
--
1.8.1.4
^ permalink raw reply related [flat|nested] 7+ messages in thread