Modified: trunk/sound/soc/codecs/adau1701.c (9622 => 9623)
--- trunk/sound/soc/codecs/adau1701.c 2011-02-19 11:48:04 UTC (rev 9622)
+++ trunk/sound/soc/codecs/adau1701.c 2011-02-23 02:11:23 UTC (rev 9623)
@@ -1,5 +1,5 @@
/*
- * Driver for ADAU1701 sound codec
+ * Driver for ADAU1701 SigmaDSP processor
*
* Copyright 2011 Analog Devices Inc.
*
@@ -30,122 +30,78 @@
#define ADAU1701_VERSION "0.10"
#define ADAU1701_FIRMWARE "SigmaDSP_fw.bin"
-static const u16 adau1701_reg_defaults[] = {
- 0x0000, /* R0 */
- 0x0000, /* R1 */
- 0x0000, /* R2 */
- 0x0000, /* R3 */
- 0x0000, /* R4 */
- 0x0000, /* R5 */
- 0x0000, /* R6 */
- 0x0000, /* R7 */
- 0x0000, /* R8 */
- 0x0000, /* R9 */
- 0x0000, /* R10 */
- 0x0000, /* R11 */
- 0x0000, /* R12 */
- 0x0000, /* R13 */
- 0x0000, /* R14 */
- 0x0000, /* R15 */
- 0x0000, /* R16 */
- 0x0000, /* R17 */
- 0x0000, /* R18 */
- 0x0000, /* R19 */
- 0x0000, /* R20 */
- 0x0000, /* R21 */
- 0x0000, /* R22 */
- 0x0000, /* R23 */
- 0x0000, /* R24 */
- 0x0000, /* R25 */
- 0x0000, /* R26 */
- 0x0000, /* R27 */
- 0x0000, /* R28 - DSP Core Control */
- 0x0000, /* R29 */
- 0x0000, /* R30 - Serial Output Control */
- 0x0000, /* R31 - Serial Input Control*/
- 0x0000, /* R32 */
- 0x0000, /* R33 */
- 0x0000, /* R34 - Auxiliary ADC and Power Control */
- 0x0000, /* R35 */
- 0x0000, /* R36 - Auxiliary ADC Enable*/
- 0x0000, /* R37 - DAC Setup */
-};
-
/* codec private data */
struct adau1701_priv {
struct snd_soc_codec *codec;
+ enum snd_soc_control_type control_type;
};
/*
- * write register cache
+ * 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 inline int adau1701_write_reg_cache(struct snd_soc_codec *codec,
- unsigned int reg, unsigned int value)
+static int adau1701_write_register(struct snd_soc_codec *codec,
+ u16 reg_address, u8 length, u32 value)
{
- u16 *cache = codec->reg_cache;
-
- if (reg < ADAU1701_FIRSTREG)
- reg = reg + ADAU1701_FIRSTREG;
-
- if ((reg < ADAU1701_FIRSTREG) || (reg > ADAU1701_LASTREG))
- return -1;
-
- cache[reg - ADAU1701_FIRSTREG] = value;
-
- return 0;
-}
-
-/*
- * write a multibyte ADAU1701 register
- */
-static int adau1701_write_reg_block(struct snd_soc_codec *codec,
- unsigned int reg, u8 length, u8 *values)
-{
+ int ret;
int count = length + 2; /*data plus 16bit register address*/
u8 buf[8] = {0, 0, 0, 0, 0, 0, 0, 0};
- buf[0] = (u8)(reg >> 8);
- buf[1] = (u8)(reg & 0xFF);
+ if (length == 0)
+ return -1;
+ buf[0] = (reg_address >> 8) & 0xFF;
+ buf[1] = reg_address & 0xFF;
+ if (length == 1)
+ buf[2] = value & 0xFF;
+ else if (length == 2) {
+ buf[2] = (value >> 8) & 0xFF;
+ buf[3] = value & 0xFF;
+ } else if (length == 3) {
+ buf[2] = (value >> 16) & 0xFF;
+ buf[3] = (value >> 8) & 0xFF;
+ buf[4] = value & 0xFF;
+ }
+ ret = i2c_master_send(codec->control_data, buf, count);
- if (length > 0)
- memcpy(&buf[2], values, length);
+ return ret;
- if (codec->hw_write(codec->control_data, buf, count) == count)
- return 0;
- else {
- dev_err(codec->dev, "address block write failed.");
- return -EIO;
- }
}
/*
- * read ADAU1701 hw register and update cache
+ * read ADAU1701 hw register
*/
-static int adau1701_read_reg_byte(struct snd_soc_codec *codec,
- u16 reg)
+static u32 adau1701_read_register(struct snd_soc_codec *codec,
+ u16 reg_address, u8 length)
{
u8 addr[2];
- u8 buf[1] = {0};
+ u8 buf[2];
+ u32 value = 0;
+ int ret;
- if (reg < ADAU1701_FIRSTREG)
- reg = reg + ADAU1701_FIRSTREG;
+ if (reg_address < ADAU1701_FIRSTREG)
+ reg_address = reg_address + ADAU1701_FIRSTREG;
- if ((reg < ADAU1701_FIRSTREG) || (reg > ADAU1701_LASTREG))
+ if ((reg_address < ADAU1701_FIRSTREG) || (reg_address > ADAU1701_LASTREG))
return -EIO;
- addr[0] = (u8)(reg >> 8);
- addr[1] = (u8)(reg & 0xFF);
+ addr[0] = (reg_address >> 8) & 0xFF;
+ addr[1] = reg_address & 0xFF;
/* write the 2byte read address */
- if (codec->hw_write(codec->control_data, addr, 2) != 2) {
- printk(KERN_ERR "read_reg_byte:address write failed.");
- return -EIO;
- }
+ ret = i2c_master_send(codec->control_data, addr, 2);
+ if (ret)
+ return ret;
- if (i2c_master_recv(codec->control_data, buf, 1) != 1)
- return -EIO;
-
- return buf[0];
+ if (length == 1) {
+ if (i2c_master_recv(codec->control_data, buf, 1) != 1)
+ return -EIO;
+ value = buf[0];
+ } else if (length == 2) {
+ if (i2c_master_recv(codec->control_data, buf, 2) != 2)
+ return -EIO;
+ value = (buf[0] << 8) | buf[1];
+ }
+ return value;
}
static int adau1701_setprogram(struct snd_soc_codec *codec)
@@ -161,11 +117,12 @@
struct snd_soc_dai *dai)
{
struct snd_soc_codec *codec = dai->codec;
- int ret = 0;
+ int reg = 0;
- snd_soc_write(codec, ADAU1701_OSCIPOW, 0x0);
+ reg = SEROCTL_MASTER | SEROCTL_OBF16 | SEROCTL_OLF1024;
+ adau1701_write_register(codec, ADAU1701_SEROCTL, 2, reg);
- return ret;
+ return 0;
}
static void adau1701_shutdown(struct snd_pcm_substream *substream,
@@ -173,24 +130,24 @@
{
struct snd_soc_codec *codec = dai->codec;
- snd_soc_write(codec, ADAU1701_OSCIPOW, 0x02);
-
+ 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 = snd_soc_read(codec, ADAU1701_AUXNPOW);
- reg |= AUXNPOW_AAPD | AUXNPOW_D1PD | AUXNPOW_D0PD;
- snd_soc_write(codec, ADAU1701_AUXNPOW, reg);
+ 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 = snd_soc_read(codec, ADAU1701_AUXNPOW);
- reg &= ~(AUXNPOW_AAPD | AUXNPOW_D1PD | AUXNPOW_D0PD);
- snd_soc_write(codec, ADAU1701_AUXNPOW, reg);
+ 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;
@@ -200,9 +157,9 @@
unsigned int fmt)
{
struct snd_soc_codec *codec = codec_dai->codec;
- u8 reg = 0;
+ u32 reg = 0;
- reg = adau1701_read_reg_byte(codec, (u16)ADAU1701_SERITL1);
+ reg = adau1701_read_register(codec, ADAU1701_SERITL1, 1);
/* interface format */
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
@@ -224,8 +181,8 @@
return 0;
}
- /* set I2S iface format*/
- adau1701_write_reg_block(codec, ADAU1701_SERITL1, 1, ®);
+ /* set iface format*/
+ adau1701_write_register(codec, ADAU1701_SERITL1, 1, reg);
return 0;
}
@@ -235,23 +192,21 @@
u16 reg;
switch (level) {
case SND_SOC_BIAS_ON:
- reg = snd_soc_read(codec, ADAU1701_AUXNPOW);
- reg &= ~(AUXNPOW_AAPD | AUXNPOW_D1PD | AUXNPOW_D0PD |\
- AUXNPOW_VBPD | AUXNPOW_VRPD);
- snd_soc_write(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;
case SND_SOC_BIAS_STANDBY:
- snd_soc_write(codec, ADAU1701_OSCIPOW, 0x02);
break;
case SND_SOC_BIAS_OFF:
/* everything off, dac mute, inactive */
- snd_soc_write(codec, ADAU1701_OSCIPOW, 0x02);
- reg = snd_soc_read(codec, ADAU1701_AUXNPOW);
- reg |= AUXNPOW_AAPD | AUXNPOW_D1PD | AUXNPOW_D0PD |\
- AUXNPOW_VBPD | AUXNPOW_VRPD;
- snd_soc_write(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;
}
@@ -320,38 +275,40 @@
static int adau1701_reg_init(struct snd_soc_codec *codec)
{
- u16 reg16;
- u8 reg[3];
+ u32 reg;
+ int ret = 0;
- reg16 = DSPCTRL_DAM | DSPCTRL_ADM;
- snd_soc_write(codec, ADAU1701_DSPCTRL, reg16);
+ reg = DSPCTRL_DAM | DSPCTRL_ADM;
+ adau1701_write_register(codec, ADAU1701_DSPCTRL, 2, reg);
/* Load default program */
- adau1701_setprogram(codec);
- reg16 = DSPCTRL_DAM | DSPCTRL_ADM;
- snd_soc_write(codec, ADAU1701_DSPCTRL, reg16);
- reg[0] = 0x80;
- adau1701_write_reg_block(codec, ADAU1701_DSPRES, 1, ®[0]);
- snd_soc_write(codec, ADAU1701_SEROCTL, 0);
- /* PLLMODE1 = 1, PLLMODE0 = 0, 256*fs */
- snd_soc_write(codec, ADAU1701_SEROCTL, 0x0d00);
- reg[0] = 0;
- adau1701_write_reg_block(codec, ADAU1701_SERITL1, 1, ®[0]);
- reg[0] = MPCONF_SDATAP | MPCONF_SDATAP << 4;
- reg[1] = 0;
- reg[2] = MPCONF_SDATAP;
- adau1701_write_reg_block(codec, ADAU1701_MPCONF0, 3, ®[0]);
- adau1701_write_reg_block(codec, ADAU1701_MPCONF1, 3, ®[0]);
- snd_soc_write(codec, ADAU1701_AUXNPOW, 0);
- reg16 = AUXADCE_AAEN;
- snd_soc_write(codec, ADAU1701_AUXADCE, reg16);
- reg16 = DACSET_DACEN;
- snd_soc_write(codec, ADAU1701_DACSET, reg16);
- reg16 = DSPCTRL_DAM | DSPCTRL_ADM | DSPCTRL_CR;
- snd_soc_write(codec, ADAU1701_DSPCTRL, reg16);
- /* power-down oscillator */
- snd_soc_write(codec, ADAU1701_OSCIPOW, 0x02);
-
- return 0;
+ ret = adau1701_setprogram(codec);
+ if (ret < 0) {
+ 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, 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 = 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, 2, 0);
+error:
+ return ret;
}
static int adau1701_probe(struct snd_soc_codec *codec)
@@ -361,14 +318,14 @@
struct adau1701_priv *adau1701 = snd_soc_codec_get_drvdata(codec);
adau1701->codec = codec;
- ret = adau1701_reg_init(codec);
+ ret = snd_soc_codec_set_cache_io(codec, 16, 16, adau1701->control_type);
if (ret < 0) {
- dev_err(codec->dev, "failed to initialize\n");
+ dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
}
- ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_I2C);
+ ret = adau1701_reg_init(codec);
if (ret < 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+ dev_err(codec->dev, "failed to initialize\n");
return ret;
}
ret = device_create_file(codec->dev, &dev_attr_dsp);
@@ -378,7 +335,6 @@
return ret;
}
-/* remove everything here */
static int adau1701_remove(struct snd_soc_codec *codec)
{
adau1701_set_bias_level(codec, SND_SOC_BIAS_OFF);
@@ -391,9 +347,6 @@
.suspend = adau1701_suspend,
.resume = adau1701_resume,
.set_bias_level = adau1701_set_bias_level,
- .reg_cache_size = ARRAY_SIZE(adau1701_reg_defaults),
- .reg_word_size = sizeof(u16),
- .reg_cache_default = adau1701_reg_defaults,
};
static __devinit int adau1701_i2c_probe(struct i2c_client *i2c,
@@ -406,6 +359,7 @@
if (adau1701 == NULL)
return -ENOMEM;
+ adau1701->control_type = SND_SOC_I2C;
i2c_set_clientdata(i2c, adau1701);
ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_adau1701, &adau1701_dai, 1);
if (ret < 0)
@@ -430,7 +384,7 @@
/* corgi i2c codec control layer */
static struct i2c_driver adau1701_i2c_driver = {
.driver = {
- .name = "adau1701",
+ .name = "adau1701-codec",
.owner = THIS_MODULE,
},
.probe = adau1701_i2c_probe,
@@ -458,6 +412,6 @@
}
module_exit(adau1701_exit);
-MODULE_DESCRIPTION("ASoC ADAU1701 driver");
+MODULE_DESCRIPTION("ASoC ADAU1701 SigmaDSP driver");
MODULE_AUTHOR("Cliff Cai");
MODULE_LICENSE("GPL");