Modified: branches/linux-2.6.37/sound/soc/codecs/adau1701.c (9725 => 9726)
--- branches/linux-2.6.37/sound/soc/codecs/adau1701.c 2011-03-17 20:49:53 UTC (rev 9725)
+++ branches/linux-2.6.37/sound/soc/codecs/adau1701.c 2011-03-18 03:43:38 UTC (rev 9726)
@@ -26,125 +26,66 @@
#include "adau1701.h"
-#define ADAU1701_FIRMWARE "adau1701.bin"
-#define USE_OSCILLATOR 1
+#define AUDIO_NAME "adau1701"
+#define ADAU1701_VERSION "0.10"
+#define ADAU1701_FIRMWARE "SigmaDSP_fw.bin"
+
/* 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, u32 value)
+ u16 reg_address, u8 length, u32 value)
{
- int i;
- int length, count;
- u8 buf[8];
+ int ret;
+ int count = length + 2; /*data plus 16bit register address*/
+ u8 buf[8] = {0, 0, 0, 0, 0, 0, 0, 0};
- 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 == 0)
+ return -1;
+ buf[0] = (reg_address >> 8) & 0xFF;
+ buf[1] = reg_address & 0xFF;
if (length == 1)
- buf[2] = value;
+ buf[2] = value & 0xFF;
else if (length == 2) {
- buf[2] = value >> 8;
- buf[3] = value;
+ buf[2] = (value >> 8) & 0xFF;
+ buf[3] = value & 0xFF;
} else if (length == 3) {
- 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;
+ buf[2] = (value >> 16) & 0xFF;
+ buf[3] = (value >> 8) & 0xFF;
+ buf[4] = value & 0xFF;
}
- return i2c_master_send(codec->control_data, buf, count);
+ ret = i2c_master_send(codec->control_data, buf, count);
+
+ return ret;
+
}
/*
* read ADAU1701 hw register
*/
static u32 adau1701_read_register(struct snd_soc_codec *codec,
- u16 reg_address)
+ u16 reg_address, u8 length)
{
u8 addr[2];
- u8 buf[3];
- int ret, i, length;
+ u8 buf[2];
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;
- addr[1] = reg_address;
+ addr[0] = (reg_address >> 8) & 0xFF;
+ addr[1] = reg_address & 0xFF;
/* write the 2byte read address */
ret = i2c_master_send(codec->control_data, addr, 2);
@@ -159,17 +100,13 @@
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;
+ int ret = 0;
ret = process_sigma_firmware(codec->control_data, ADAU1701_FIRMWARE);
@@ -180,11 +117,10 @@
struct snd_soc_dai *dai)
{
struct snd_soc_codec *codec = dai->codec;
- u16 reg;
+ int reg = 0;
- reg = ADAU1701_SEROCTL_MASTER | ADAU1701_SEROCTL_OBF16 |
- ADAU1701_SEROCTL_OLF1024;
- adau1701_write_register(codec, ADAU1701_SEROCTL, reg);
+ reg = SEROCTL_MASTER | SEROCTL_OBF16 | SEROCTL_OLF1024;
+ adau1701_write_register(codec, ADAU1701_SEROCTL, 2, reg);
return 0;
}
@@ -194,27 +130,46 @@
{
struct snd_soc_codec *codec = dai->codec;
- adau1701_write_register(codec, ADAU1701_SEROCTL, 0);
+ adau1701_write_register(codec, ADAU1701_SEROCTL, 2, 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;
- u8 reg;
+ u32 reg = 0;
- reg = adau1701_read_register(codec, ADAU1701_SERITL1);
+ reg = adau1701_read_register(codec, ADAU1701_SERITL1, 1);
/* 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 |= ADAU1701_SERITL1_LEFTJ;
+ reg |= SERITL1_LEFTJ;
break;
/* TODO: support TDM */
default:
- return -EINVAL;
+ return 0;
}
/* clock inversion */
@@ -223,11 +178,11 @@
break;
/* TODO: support signal inversions */
default:
- return -EINVAL;
+ return 0;
}
/* set iface format*/
- adau1701_write_register(codec, ADAU1701_SERITL1, reg);
+ adau1701_write_register(codec, ADAU1701_SERITL1, 1, reg);
return 0;
}
@@ -237,12 +192,10 @@
u16 reg;
switch (level) {
case SND_SOC_BIAS_ON:
- 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);
+ 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);
break;
case SND_SOC_BIAS_PREPARE:
break;
@@ -250,12 +203,10 @@
break;
case SND_SOC_BIAS_OFF:
/* everything off, dac mute, inactive */
- 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);
+ 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);
break;
}
@@ -271,11 +222,12 @@
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,
@@ -292,6 +244,7 @@
},
.ops = &adau1701_dai_ops,
};
+EXPORT_SYMBOL_GPL(adau1701_dai);
static int adau1701_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
@@ -309,16 +262,10 @@
struct device_attribute *attr,
const char *buf, size_t count)
{
- int ret;
- u32 reg;
+ int ret = 0;
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
@@ -329,36 +276,37 @@
static int adau1701_reg_init(struct snd_soc_codec *codec)
{
u32 reg;
- int ret;
+ int ret = 0;
+ reg = DSPCTRL_DAM | DSPCTRL_ADM;
+ adau1701_write_register(codec, ADAU1701_DSPCTRL, 2, reg);
/* Load default program */
ret = adau1701_setprogram(codec);
if (ret < 0) {
- dev_err(codec->dev, "Loading program data failed\n");
+ printk(KERN_ERR "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, reg);
- adau1701_write_register(codec, ADAU1701_SEROCTL, 0);
- adau1701_write_register(codec, ADAU1701_SERITL1, 0);
+ adau1701_write_register(codec, ADAU1701_DSPRES, 1, reg);
+ adau1701_write_register(codec, ADAU1701_SEROCTL, 2, 0);
+ adau1701_write_register(codec, ADAU1701_SERITL1, 1, 0);
/* Configure the multipurpose pins as serial in/out pins */
- 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
+ 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);
/* Power-up the oscillator */
- adau1701_write_register(codec, ADAU1701_OSCIPOW, 0);
-#endif
+ adau1701_write_register(codec, ADAU1701_OSCIPOW, 2, 0);
error:
return ret;
}
@@ -389,7 +337,8 @@
static int adau1701_remove(struct snd_soc_codec *codec)
{
- return adau1701_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ adau1701_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ return 0;
}
struct snd_soc_codec_driver soc_codec_dev_adau1701 = {
@@ -448,9 +397,10 @@
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;
}