Modified: trunk/sound/soc/codecs/adau1701.c (9706 => 9707)
--- trunk/sound/soc/codecs/adau1701.c 2011-03-14 22:25:35 UTC (rev 9706)
+++ trunk/sound/soc/codecs/adau1701.c 2011-03-15 10:28:39 UTC (rev 9707)
@@ -26,66 +26,125 @@
#include "adau1701.h"
-#define AUDIO_NAME "adau1701"
-#define ADAU1701_VERSION "0.10"
-#define ADAU1701_FIRMWARE "SigmaDSP_fw.bin"
-
+#define ADAU1701_FIRMWARE "adau1701.bin"
+#define USE_OSCILLATOR 1
/* codec private data */
struct adau1701_priv {
struct snd_soc_codec *codec;
enum snd_soc_control_type control_type;
};
+struct register_lut {
+ u16 address;
+ int length;
+};
+
+static const struct register_lut register_table[] = {
+
+ {ADAU1701_IFACE0, 4},
+ {ADAU1701_IFACE1, 4},
+ {ADAU1701_IFACE2, 4},
+ {ADAU1701_IFACE3, 4},
+ {ADAU1701_IFACE4, 4},
+ {ADAU1701_IFACE5, 4},
+ {ADAU1701_IFACE6, 4},
+ {ADAU1701_IFACE7, 4},
+
+ {ADAU1701_GPIOSET, 2},
+
+ {ADAU1701_AUXADC0, 2},
+ {ADAU1701_AUXADC1, 2},
+ {ADAU1701_AUXADC2, 2},
+ {ADAU1701_AUXADC3, 2},
+
+ {ADAU1701_DATCAP0, 2},
+ {ADAU1701_DATCAP1, 2},
+
+ {ADAU1701_DSPCTRL, 2},
+ {ADAU1701_DSPRES, 1},
+ {ADAU1701_SEROCTL, 1},
+ {ADAU1701_SERITL1, 1},
+
+ {ADAU1701_MPCONF0, 3},
+ {ADAU1701_MPCONF1, 3},
+
+ {ADAU1701_AUXNPOW, 2},
+ {ADAU1701_AUXADCE, 2},
+
+ {ADAU1701_OSCIPOW, 2},
+ {ADAU1701_DACSET, 2},
+};
/*
* Write a ADAU1701 register,since the register length is from 1 to 5,
* So, use our own read/write functions instead of snd_soc_read/write.
*/
static int adau1701_write_register(struct snd_soc_codec *codec,
- u16 reg_address, u8 length, u32 value)
+ u16 reg_address, u32 value)
{
- int ret;
- int count = length + 2; /*data plus 16bit register address*/
- u8 buf[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+ int i;
+ int length, count;
+ u8 buf[8];
- if (length == 0)
- return -1;
- buf[0] = (reg_address >> 8) & 0xFF;
- buf[1] = reg_address & 0xFF;
+ for (i = 0; i < ARRAY_SIZE(register_table); i++) {
+ if (register_table[i].address == reg_address)
+ break;
+ }
+ if (i == ARRAY_SIZE(register_table)) {
+ dev_err(codec->dev, "Wrong Register Address\n");
+ return -EINVAL;
+ }
+ length = register_table[i].length;
+ count = length + 2; /*data plus 16bit register address*/
+
+ buf[0] = reg_address >> 8;
+ buf[1] = reg_address;
if (length == 1)
- buf[2] = value & 0xFF;
+ buf[2] = value;
else if (length == 2) {
- buf[2] = (value >> 8) & 0xFF;
- buf[3] = value & 0xFF;
+ buf[2] = value >> 8;
+ buf[3] = value;
} else if (length == 3) {
- buf[2] = (value >> 16) & 0xFF;
- buf[3] = (value >> 8) & 0xFF;
- buf[4] = value & 0xFF;
+ buf[2] = value >> 16;
+ buf[3] = value >> 8;
+ buf[4] = value;
+ } else if (length == 4) {
+ buf[2] = value >> 24;
+ buf[3] = value >> 16;
+ buf[4] = value >> 8;
+ buf[5] = value;
}
- ret = i2c_master_send(codec->control_data, buf, count);
-
- return ret;
-
+ return i2c_master_send(codec->control_data, buf, count);
}
/*
* read ADAU1701 hw register
*/
static u32 adau1701_read_register(struct snd_soc_codec *codec,
- u16 reg_address, u8 length)
+ u16 reg_address)
{
u8 addr[2];
- u8 buf[2];
+ u8 buf[3];
+ int ret, i, length;
u32 value = 0;
- int ret;
+ for (i = 0; i < ARRAY_SIZE(register_table); i++) {
+ if (register_table[i].address == reg_address)
+ break;
+ }
+ if (i == ARRAY_SIZE(register_table)) {
+ dev_err(codec->dev, "Wrong Register Address\n");
+ return -EINVAL;
+ }
+ length = register_table[i].length;
+
if (reg_address < ADAU1701_FIRSTREG)
reg_address = reg_address + ADAU1701_FIRSTREG;
if ((reg_address < ADAU1701_FIRSTREG) || (reg_address > ADAU1701_LASTREG))
return -EIO;
- addr[0] = (reg_address >> 8) & 0xFF;
- addr[1] = reg_address & 0xFF;
+ addr[0] = reg_address >> 8;
+ addr[1] = reg_address;
/* write the 2byte read address */
ret = i2c_master_send(codec->control_data, addr, 2);
@@ -100,13 +159,17 @@
if (i2c_master_recv(codec->control_data, buf, 2) != 2)
return -EIO;
value = (buf[0] << 8) | buf[1];
+ } else if (length == 3) {
+ if (i2c_master_recv(codec->control_data, buf, 3) != 3)
+ return -EIO;
+ value = (buf[0] << 16) | (buf[1] << 8) | buf[2];
}
return value;
}
static int adau1701_setprogram(struct snd_soc_codec *codec)
{
- int ret = 0;
+ int ret;
ret = process_sigma_firmware(codec->control_data, ADAU1701_FIRMWARE);
@@ -117,10 +180,11 @@
struct snd_soc_dai *dai)
{
struct snd_soc_codec *codec = dai->codec;
- int reg = 0;
+ u16 reg;
- reg = SEROCTL_MASTER | SEROCTL_OBF16 | SEROCTL_OLF1024;
- adau1701_write_register(codec, ADAU1701_SEROCTL, 2, reg);
+ reg = ADAU1701_SEROCTL_MASTER | ADAU1701_SEROCTL_OBF16 |
+ ADAU1701_SEROCTL_OLF1024;
+ adau1701_write_register(codec, ADAU1701_SEROCTL, reg);
return 0;
}
@@ -130,46 +194,27 @@
{
struct snd_soc_codec *codec = dai->codec;
- adau1701_write_register(codec, ADAU1701_SEROCTL, 2, 0);
+ adau1701_write_register(codec, ADAU1701_SEROCTL, 0);
}
-static int adau1701_mute(struct snd_soc_dai *dai, int mute)
-{
- struct snd_soc_codec *codec = dai->codec;
- u16 reg = 0;
-
- if (mute) {
- /* mute inputs/outputs */
- reg = adau1701_read_register(codec, ADAU1701_AUXNPOW, 2);
- reg |= AUXNPOW_AAPD | AUXNPOW_D0PD | AUXNPOW_D1PD | AUXNPOW_D2PD | AUXNPOW_D3PD;
- adau1701_write_register(codec, ADAU1701_AUXNPOW, 2, reg);
- } else {
- /* unmute inputs/outputs */
- reg = adau1701_read_register(codec, ADAU1701_AUXNPOW, 2);
- reg &= ~(AUXNPOW_AAPD | AUXNPOW_D0PD | AUXNPOW_D1PD | AUXNPOW_D2PD | AUXNPOW_D3PD);
- adau1701_write_register(codec, ADAU1701_AUXNPOW, 2, reg);
- }
-
- return 0;
-}
-
static int adau1701_set_dai_fmt(struct snd_soc_dai *codec_dai,
unsigned int fmt)
{
struct snd_soc_codec *codec = codec_dai->codec;
- u32 reg = 0;
+ u8 reg;
- reg = adau1701_read_register(codec, ADAU1701_SERITL1, 1);
+ reg = adau1701_read_register(codec, ADAU1701_SERITL1);
/* interface format */
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
+ reg &= ~ADAU1701_SERITL1_MSK;
break;
case SND_SOC_DAIFMT_LEFT_J:
- reg |= SERITL1_LEFTJ;
+ reg |= ADAU1701_SERITL1_LEFTJ;
break;
/* TODO: support TDM */
default:
- return 0;
+ return -EINVAL;
}
/* clock inversion */
@@ -178,11 +223,11 @@
break;
/* TODO: support signal inversions */
default:
- return 0;
+ return -EINVAL;
}
/* set iface format*/
- adau1701_write_register(codec, ADAU1701_SERITL1, 1, reg);
+ adau1701_write_register(codec, ADAU1701_SERITL1, reg);
return 0;
}
@@ -192,10 +237,12 @@
u16 reg;
switch (level) {
case SND_SOC_BIAS_ON:
- reg = adau1701_read_register(codec, ADAU1701_AUXNPOW, 2);
- reg &= ~(AUXNPOW_AAPD | AUXNPOW_D0PD | AUXNPOW_D1PD | AUXNPOW_D2PD |
- AUXNPOW_D3PD | AUXNPOW_VBPD | AUXNPOW_VRPD);
- adau1701_write_register(codec, ADAU1701_AUXNPOW, 2, reg);
+ reg = adau1701_read_register(codec, ADAU1701_AUXNPOW);
+ reg &= ~(ADAU1701_AUXNPOW_AAPD | ADAU1701_AUXNPOW_D0PD |
+ ADAU1701_AUXNPOW_D1PD | ADAU1701_AUXNPOW_D2PD |
+ ADAU1701_AUXNPOW_D3PD | ADAU1701_AUXNPOW_VBPD |
+ ADAU1701_AUXNPOW_VRPD);
+ adau1701_write_register(codec, ADAU1701_AUXNPOW, reg);
break;
case SND_SOC_BIAS_PREPARE:
break;
@@ -203,10 +250,12 @@
break;
case SND_SOC_BIAS_OFF:
/* everything off, dac mute, inactive */
- reg = adau1701_read_register(codec, ADAU1701_AUXNPOW, 2);
- reg |= AUXNPOW_AAPD | AUXNPOW_D0PD | AUXNPOW_D1PD | AUXNPOW_D2PD |
- AUXNPOW_D3PD | AUXNPOW_VBPD | AUXNPOW_VRPD;
- adau1701_write_register(codec, ADAU1701_AUXNPOW, 2, reg);
+ reg = adau1701_read_register(codec, ADAU1701_AUXNPOW);
+ reg |= ADAU1701_AUXNPOW_AAPD | ADAU1701_AUXNPOW_D0PD |
+ ADAU1701_AUXNPOW_D1PD | ADAU1701_AUXNPOW_D2PD |
+ ADAU1701_AUXNPOW_D3PD | ADAU1701_AUXNPOW_VBPD |
+ ADAU1701_AUXNPOW_VRPD;
+ adau1701_write_register(codec, ADAU1701_AUXNPOW, reg);
break;
}
@@ -222,12 +271,11 @@
static struct snd_soc_dai_ops adau1701_dai_ops = {
.prepare = adau1701_pcm_prepare,
.shutdown = adau1701_shutdown,
- .digital_mute = adau1701_mute,
.set_fmt = adau1701_set_dai_fmt,
};
struct snd_soc_dai_driver adau1701_dai = {
- .name = "ADAU1701",
+ .name = "adau1701",
.playback = {
.stream_name = "Playback",
.channels_min = 2,
@@ -244,7 +292,6 @@
},
.ops = &adau1701_dai_ops,
};
-EXPORT_SYMBOL_GPL(adau1701_dai);
static int adau1701_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
@@ -262,10 +309,16 @@
struct device_attribute *attr,
const char *buf, size_t count)
{
- int ret = 0;
+ int ret;
+ u32 reg;
struct adau1701_priv *adau1701 = dev_get_drvdata(dev);
struct snd_soc_codec *codec = adau1701->codec;
+
+ reg = ADAU1701_DSPCTRL_DAM | ADAU1701_DSPCTRL_ADM;
+ adau1701_write_register(codec, ADAU1701_DSPCTRL, reg);
ret = adau1701_setprogram(codec);
+ reg = ADAU1701_DSPCTRL_DAM | ADAU1701_DSPCTRL_ADM;
+ adau1701_write_register(codec, ADAU1701_DSPCTRL, reg);
if (ret)
return ret;
else
@@ -276,37 +329,36 @@
static int adau1701_reg_init(struct snd_soc_codec *codec)
{
u32 reg;
- int ret = 0;
+ int ret;
- reg = DSPCTRL_DAM | DSPCTRL_ADM;
- adau1701_write_register(codec, ADAU1701_DSPCTRL, 2, reg);
/* Load default program */
ret = adau1701_setprogram(codec);
if (ret < 0) {
- printk(KERN_ERR "Loading program data failed\n");
+ dev_err(codec->dev, "Loading program data failed\n");
goto error;
}
- reg = DSPCTRL_DAM | DSPCTRL_ADM;
- adau1701_write_register(codec, ADAU1701_DSPCTRL, 2, reg);
reg = 0x08;
- adau1701_write_register(codec, ADAU1701_DSPRES, 1, reg);
- adau1701_write_register(codec, ADAU1701_SEROCTL, 2, 0);
- adau1701_write_register(codec, ADAU1701_SERITL1, 1, 0);
+ adau1701_write_register(codec, ADAU1701_DSPRES, reg);
+ adau1701_write_register(codec, ADAU1701_SEROCTL, 0);
+ adau1701_write_register(codec, ADAU1701_SERITL1, 0);
/* Configure the multipurpose pins as serial in/out pins */
- reg = MPCONF_SDATAP | MPCONF_SDATAP << 16 | MPCONF_SDATAP << 20;
- adau1701_write_register(codec, ADAU1701_MPCONF0, 3, reg);
- reg = MPCONF_AUXADC << 8 | MPCONF_SDATAP << 12 | MPCONF_SDATAP << 16 |
- MPCONF_SDATAP << 20;
- adau1701_write_register(codec, ADAU1701_MPCONF1, 3, reg);
- adau1701_write_register(codec, ADAU1701_AUXNPOW, 2, 0);
- reg = AUXADCE_AAEN;
- adau1701_write_register(codec, ADAU1701_AUXADCE, 2, reg);
- reg = DACSET_DACEN;
- adau1701_write_register(codec, ADAU1701_DACSET, 2, reg);
- reg = DSPCTRL_DAM | DSPCTRL_ADM | DSPCTRL_CR;
- adau1701_write_register(codec, ADAU1701_DSPCTRL, 2, reg);
+ reg = ADAU1701_MPCONF_SDATAP | ADAU1701_MPCONF_SDATAP << 16 |
+ ADAU1701_MPCONF_SDATAP << 20;
+ adau1701_write_register(codec, ADAU1701_MPCONF0, reg);
+ reg = ADAU1701_MPCONF_AUXADC << 8 | ADAU1701_MPCONF_SDATAP << 12 |
+ ADAU1701_MPCONF_SDATAP << 16 | ADAU1701_MPCONF_SDATAP << 20;
+ adau1701_write_register(codec, ADAU1701_MPCONF1, reg);
+ adau1701_write_register(codec, ADAU1701_AUXNPOW, 0);
+ reg = ADAU1701_AUXADCE_AAEN;
+ adau1701_write_register(codec, ADAU1701_AUXADCE, reg);
+ reg = ADAU1701_DACSET_DACEN;
+ adau1701_write_register(codec, ADAU1701_DACSET, reg);
+ reg = ADAU1701_DSPCTRL_DAM | ADAU1701_DSPCTRL_ADM | ADAU1701_DSPCTRL_CR;
+ adau1701_write_register(codec, ADAU1701_DSPCTRL, reg);
+#ifdef USE_OSCILLATOR
/* Power-up the oscillator */
- adau1701_write_register(codec, ADAU1701_OSCIPOW, 2, 0);
+ adau1701_write_register(codec, ADAU1701_OSCIPOW, 0);
+#endif
error:
return ret;
}
@@ -337,8 +389,7 @@
static int adau1701_remove(struct snd_soc_codec *codec)
{
- adau1701_set_bias_level(codec, SND_SOC_BIAS_OFF);
- return 0;
+ return adau1701_set_bias_level(codec, SND_SOC_BIAS_OFF);
}
struct snd_soc_codec_driver soc_codec_dev_adau1701 = {
@@ -397,10 +448,9 @@
int ret;
ret = i2c_add_driver(&adau1701_i2c_driver);
- if (ret != 0) {
+ if (ret != 0)
printk(KERN_ERR "Failed to register adau1701 I2C driver: %d\n",
ret);
- }
return ret;
}