Commit 06cddefc authored by Mark Brown's avatar Mark Brown

Merge branch 'reg-cache' into for-2.6.32

parents b9b5cc26 27ded041
...@@ -209,11 +209,20 @@ typedef int (*hw_read_t)(void *,char* ,int); ...@@ -209,11 +209,20 @@ typedef int (*hw_read_t)(void *,char* ,int);
extern struct snd_ac97_bus_ops soc_ac97_ops; extern struct snd_ac97_bus_ops soc_ac97_ops;
enum snd_soc_control_type {
SND_SOC_CUSTOM,
SND_SOC_I2C,
SND_SOC_SPI,
};
int snd_soc_register_platform(struct snd_soc_platform *platform); int snd_soc_register_platform(struct snd_soc_platform *platform);
void snd_soc_unregister_platform(struct snd_soc_platform *platform); void snd_soc_unregister_platform(struct snd_soc_platform *platform);
int snd_soc_register_codec(struct snd_soc_codec *codec); int snd_soc_register_codec(struct snd_soc_codec *codec);
void snd_soc_unregister_codec(struct snd_soc_codec *codec); void snd_soc_unregister_codec(struct snd_soc_codec *codec);
int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, int reg); int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, int reg);
int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
int addr_bits, int data_bits,
enum snd_soc_control_type control);
#ifdef CONFIG_PM #ifdef CONFIG_PM
int snd_soc_suspend_device(struct device *dev); int snd_soc_suspend_device(struct device *dev);
...@@ -387,7 +396,7 @@ struct snd_soc_codec { ...@@ -387,7 +396,7 @@ struct snd_soc_codec {
int (*volatile_register)(unsigned int); int (*volatile_register)(unsigned int);
int (*readable_register)(unsigned int); int (*readable_register)(unsigned int);
hw_write_t hw_write; hw_write_t hw_write;
hw_read_t hw_read; unsigned int (*hw_read)(struct snd_soc_codec *, unsigned int);
void *reg_cache; void *reg_cache;
short reg_cache_size; short reg_cache_size;
short reg_cache_step; short reg_cache_step;
......
snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o
obj-$(CONFIG_SND_SOC) += snd-soc-core.o obj-$(CONFIG_SND_SOC) += snd-soc-core.o
obj-$(CONFIG_SND_SOC) += codecs/ obj-$(CONFIG_SND_SOC) += codecs/
......
...@@ -145,8 +145,8 @@ static int aic3x_read(struct snd_soc_codec *codec, unsigned int reg, ...@@ -145,8 +145,8 @@ static int aic3x_read(struct snd_soc_codec *codec, unsigned int reg,
u8 *value) u8 *value)
{ {
*value = reg & 0xff; *value = reg & 0xff;
if (codec->hw_read(codec->control_data, value, 1) != 1)
return -EIO; value[0] = i2c_smbus_read_byte_data(codec->control_data, value[0]);
aic3x_write_reg_cache(codec, reg, *value); aic3x_write_reg_cache(codec, reg, *value);
return 0; return 0;
...@@ -1325,12 +1325,6 @@ static struct i2c_driver aic3x_i2c_driver = { ...@@ -1325,12 +1325,6 @@ static struct i2c_driver aic3x_i2c_driver = {
.id_table = aic3x_i2c_id, .id_table = aic3x_i2c_id,
}; };
static int aic3x_i2c_read(struct i2c_client *client, u8 *value, int len)
{
value[0] = i2c_smbus_read_byte_data(client, value[0]);
return (len == 1);
}
static int aic3x_add_i2c_device(struct platform_device *pdev, static int aic3x_add_i2c_device(struct platform_device *pdev,
const struct aic3x_setup_data *setup) const struct aic3x_setup_data *setup)
{ {
...@@ -1403,7 +1397,6 @@ static int aic3x_probe(struct platform_device *pdev) ...@@ -1403,7 +1397,6 @@ static int aic3x_probe(struct platform_device *pdev)
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
if (setup->i2c_address) { if (setup->i2c_address) {
codec->hw_write = (hw_write_t) i2c_master_send; codec->hw_write = (hw_write_t) i2c_master_send;
codec->hw_read = (hw_read_t) aic3x_i2c_read;
ret = aic3x_add_i2c_device(pdev, setup); ret = aic3x_add_i2c_device(pdev, setup);
} }
#else #else
......
This diff is collapsed.
...@@ -62,7 +62,7 @@ static const u16 wm8523_reg[WM8523_REGISTER_COUNT] = { ...@@ -62,7 +62,7 @@ static const u16 wm8523_reg[WM8523_REGISTER_COUNT] = {
0x0000, /* R8 - ZERO_DETECT */ 0x0000, /* R8 - ZERO_DETECT */
}; };
static int wm8523_volatile(unsigned int reg) static int wm8523_volatile_register(unsigned int reg)
{ {
switch (reg) { switch (reg) {
case WM8523_DEVICE_ID: case WM8523_DEVICE_ID:
...@@ -73,71 +73,9 @@ static int wm8523_volatile(unsigned int reg) ...@@ -73,71 +73,9 @@ static int wm8523_volatile(unsigned int reg)
} }
} }
static int wm8523_write(struct snd_soc_codec *codec, unsigned int reg,
unsigned int value)
{
struct wm8523_priv *wm8523 = codec->private_data;
u8 data[3];
BUG_ON(reg > WM8523_MAX_REGISTER);
data[0] = reg;
data[1] = (value >> 8) & 0x00ff;
data[2] = value & 0x00ff;
if (!wm8523_volatile(reg))
wm8523->reg_cache[reg] = value;
if (codec->hw_write(codec->control_data, data, 3) == 3)
return 0;
else
return -EIO;
}
static int wm8523_reset(struct snd_soc_codec *codec) static int wm8523_reset(struct snd_soc_codec *codec)
{ {
return wm8523_write(codec, WM8523_DEVICE_ID, 0); return snd_soc_write(codec, WM8523_DEVICE_ID, 0);
}
static unsigned int wm8523_read_hw(struct snd_soc_codec *codec, u8 reg)
{
struct i2c_msg xfer[2];
u16 data;
int ret;
struct i2c_client *i2c = codec->control_data;
/* Write register */
xfer[0].addr = i2c->addr;
xfer[0].flags = 0;
xfer[0].len = 1;
xfer[0].buf = ®
/* Read data */
xfer[1].addr = i2c->addr;
xfer[1].flags = I2C_M_RD;
xfer[1].len = 2;
xfer[1].buf = (u8 *)&data;
ret = i2c_transfer(i2c->adapter, xfer, 2);
if (ret != 2) {
dev_err(codec->dev, "Failed to read 0x%x: %d\n", reg, ret);
return 0;
}
return (data >> 8) | ((data & 0xff) << 8);
}
static unsigned int wm8523_read(struct snd_soc_codec *codec,
unsigned int reg)
{
u16 *reg_cache = codec->reg_cache;
BUG_ON(reg > WM8523_MAX_REGISTER);
if (wm8523_volatile(reg))
return wm8523_read_hw(codec, reg);
else
return reg_cache[reg];
} }
static const DECLARE_TLV_DB_SCALE(dac_tlv, -10000, 25, 0); static const DECLARE_TLV_DB_SCALE(dac_tlv, -10000, 25, 0);
...@@ -228,8 +166,8 @@ static int wm8523_hw_params(struct snd_pcm_substream *substream, ...@@ -228,8 +166,8 @@ static int wm8523_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_codec *codec = socdev->card->codec; struct snd_soc_codec *codec = socdev->card->codec;
struct wm8523_priv *wm8523 = codec->private_data; struct wm8523_priv *wm8523 = codec->private_data;
int i; int i;
u16 aifctrl1 = wm8523_read(codec, WM8523_AIF_CTRL1); u16 aifctrl1 = snd_soc_read(codec, WM8523_AIF_CTRL1);
u16 aifctrl2 = wm8523_read(codec, WM8523_AIF_CTRL2); u16 aifctrl2 = snd_soc_read(codec, WM8523_AIF_CTRL2);
/* Find a supported LRCLK ratio */ /* Find a supported LRCLK ratio */
for (i = 0; i < ARRAY_SIZE(lrclk_ratios); i++) { for (i = 0; i < ARRAY_SIZE(lrclk_ratios); i++) {
...@@ -263,8 +201,8 @@ static int wm8523_hw_params(struct snd_pcm_substream *substream, ...@@ -263,8 +201,8 @@ static int wm8523_hw_params(struct snd_pcm_substream *substream,
break; break;
} }
wm8523_write(codec, WM8523_AIF_CTRL1, aifctrl1); snd_soc_write(codec, WM8523_AIF_CTRL1, aifctrl1);
wm8523_write(codec, WM8523_AIF_CTRL2, aifctrl2); snd_soc_write(codec, WM8523_AIF_CTRL2, aifctrl2);
return 0; return 0;
} }
...@@ -322,7 +260,7 @@ static int wm8523_set_dai_fmt(struct snd_soc_dai *codec_dai, ...@@ -322,7 +260,7 @@ static int wm8523_set_dai_fmt(struct snd_soc_dai *codec_dai,
unsigned int fmt) unsigned int fmt)
{ {
struct snd_soc_codec *codec = codec_dai->codec; struct snd_soc_codec *codec = codec_dai->codec;
u16 aifctrl1 = wm8523_read(codec, WM8523_AIF_CTRL1); u16 aifctrl1 = snd_soc_read(codec, WM8523_AIF_CTRL1);
aifctrl1 &= ~(WM8523_BCLK_INV_MASK | WM8523_LRCLK_INV_MASK | aifctrl1 &= ~(WM8523_BCLK_INV_MASK | WM8523_LRCLK_INV_MASK |
WM8523_FMT_MASK | WM8523_AIF_MSTR_MASK); WM8523_FMT_MASK | WM8523_AIF_MSTR_MASK);
...@@ -372,7 +310,7 @@ static int wm8523_set_dai_fmt(struct snd_soc_dai *codec_dai, ...@@ -372,7 +310,7 @@ static int wm8523_set_dai_fmt(struct snd_soc_dai *codec_dai,
return -EINVAL; return -EINVAL;
} }
wm8523_write(codec, WM8523_AIF_CTRL1, aifctrl1); snd_soc_write(codec, WM8523_AIF_CTRL1, aifctrl1);
return 0; return 0;
} }
...@@ -411,7 +349,7 @@ static int wm8523_set_bias_level(struct snd_soc_codec *codec, ...@@ -411,7 +349,7 @@ static int wm8523_set_bias_level(struct snd_soc_codec *codec,
/* Sync back default/cached values */ /* Sync back default/cached values */
for (i = WM8523_AIF_CTRL1; for (i = WM8523_AIF_CTRL1;
i < WM8523_MAX_REGISTER; i++) i < WM8523_MAX_REGISTER; i++)
wm8523_write(codec, i, wm8523->reg_cache[i]); snd_soc_write(codec, i, wm8523->reg_cache[i]);
msleep(100); msleep(100);
...@@ -543,7 +481,8 @@ struct snd_soc_codec_device soc_codec_dev_wm8523 = { ...@@ -543,7 +481,8 @@ struct snd_soc_codec_device soc_codec_dev_wm8523 = {
}; };
EXPORT_SYMBOL_GPL(soc_codec_dev_wm8523); EXPORT_SYMBOL_GPL(soc_codec_dev_wm8523);
static int wm8523_register(struct wm8523_priv *wm8523) static int wm8523_register(struct wm8523_priv *wm8523,
enum snd_soc_control_type control)
{ {
int ret; int ret;
struct snd_soc_codec *codec = &wm8523->codec; struct snd_soc_codec *codec = &wm8523->codec;
...@@ -561,14 +500,13 @@ static int wm8523_register(struct wm8523_priv *wm8523) ...@@ -561,14 +500,13 @@ static int wm8523_register(struct wm8523_priv *wm8523)
codec->private_data = wm8523; codec->private_data = wm8523;
codec->name = "WM8523"; codec->name = "WM8523";
codec->owner = THIS_MODULE; codec->owner = THIS_MODULE;
codec->read = wm8523_read;
codec->write = wm8523_write;
codec->bias_level = SND_SOC_BIAS_OFF; codec->bias_level = SND_SOC_BIAS_OFF;
codec->set_bias_level = wm8523_set_bias_level; codec->set_bias_level = wm8523_set_bias_level;
codec->dai = &wm8523_dai; codec->dai = &wm8523_dai;
codec->num_dai = 1; codec->num_dai = 1;
codec->reg_cache_size = WM8523_REGISTER_COUNT; codec->reg_cache_size = WM8523_REGISTER_COUNT;
codec->reg_cache = &wm8523->reg_cache; codec->reg_cache = &wm8523->reg_cache;
codec->volatile_register = wm8523_volatile_register;
wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0]; wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0];
wm8523->rate_constraint.count = wm8523->rate_constraint.count =
...@@ -576,6 +514,12 @@ static int wm8523_register(struct wm8523_priv *wm8523) ...@@ -576,6 +514,12 @@ static int wm8523_register(struct wm8523_priv *wm8523)
memcpy(codec->reg_cache, wm8523_reg, sizeof(wm8523_reg)); memcpy(codec->reg_cache, wm8523_reg, sizeof(wm8523_reg));
ret = snd_soc_codec_set_cache_io(codec, 8, 16, control);
if (ret != 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
goto err;
}
for (i = 0; i < ARRAY_SIZE(wm8523->supplies); i++) for (i = 0; i < ARRAY_SIZE(wm8523->supplies); i++)
wm8523->supplies[i].supply = wm8523_supply_names[i]; wm8523->supplies[i].supply = wm8523_supply_names[i];
...@@ -593,7 +537,7 @@ static int wm8523_register(struct wm8523_priv *wm8523) ...@@ -593,7 +537,7 @@ static int wm8523_register(struct wm8523_priv *wm8523)
goto err_get; goto err_get;
} }
ret = wm8523_read(codec, WM8523_DEVICE_ID); ret = snd_soc_read(codec, WM8523_DEVICE_ID);
if (ret < 0) { if (ret < 0) {
dev_err(codec->dev, "Failed to read ID register\n"); dev_err(codec->dev, "Failed to read ID register\n");
goto err_enable; goto err_enable;
...@@ -604,7 +548,7 @@ static int wm8523_register(struct wm8523_priv *wm8523) ...@@ -604,7 +548,7 @@ static int wm8523_register(struct wm8523_priv *wm8523)
goto err_enable; goto err_enable;
} }
ret = wm8523_read(codec, WM8523_REVISION); ret = snd_soc_read(codec, WM8523_REVISION);
if (ret < 0) { if (ret < 0) {
dev_err(codec->dev, "Failed to read revision register\n"); dev_err(codec->dev, "Failed to read revision register\n");
goto err_enable; goto err_enable;
...@@ -684,7 +628,7 @@ static __devinit int wm8523_i2c_probe(struct i2c_client *i2c, ...@@ -684,7 +628,7 @@ static __devinit int wm8523_i2c_probe(struct i2c_client *i2c,
codec->dev = &i2c->dev; codec->dev = &i2c->dev;
return wm8523_register(wm8523); return wm8523_register(wm8523, SND_SOC_I2C);
} }
static __devexit int wm8523_i2c_remove(struct i2c_client *client) static __devexit int wm8523_i2c_remove(struct i2c_client *client)
......
...@@ -205,73 +205,6 @@ struct wm8580_priv { ...@@ -205,73 +205,6 @@ struct wm8580_priv {
struct pll_state b; struct pll_state b;
}; };
/*
* read wm8580 register cache
*/
static inline unsigned int wm8580_read_reg_cache(struct snd_soc_codec *codec,
unsigned int reg)
{
u16 *cache = codec->reg_cache;
BUG_ON(reg >= ARRAY_SIZE(wm8580_reg));
return cache[reg];
}
/*
* write wm8580 register cache
*/
static inline void wm8580_write_reg_cache(struct snd_soc_codec *codec,
unsigned int reg, unsigned int value)
{
u16 *cache = codec->reg_cache;
cache[reg] = value;
}
/*
* write to the WM8580 register space
*/
static int wm8580_write(struct snd_soc_codec *codec, unsigned int reg,
unsigned int value)
{
u8 data[2];
BUG_ON(reg >= ARRAY_SIZE(wm8580_reg));
/* Registers are 9 bits wide */
value &= 0x1ff;
switch (reg) {
case WM8580_RESET:
/* Uncached */
break;
default:
if (value == wm8580_read_reg_cache(codec, reg))
return 0;
}
/* data is
* D15..D9 WM8580 register offset
* D8...D0 register data
*/
data[0] = (reg << 1) | ((value >> 8) & 0x0001);
data[1] = value & 0x00ff;
wm8580_write_reg_cache(codec, reg, value);
if (codec->hw_write(codec->control_data, data, 2) == 2)
return 0;
else
return -EIO;
}
static inline unsigned int wm8580_read(struct snd_soc_codec *codec,
unsigned int reg)
{
switch (reg) {
default:
return wm8580_read_reg_cache(codec, reg);
}
}
static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1); static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1);
static int wm8580_out_vu(struct snd_kcontrol *kcontrol, static int wm8580_out_vu(struct snd_kcontrol *kcontrol,
...@@ -280,25 +213,22 @@ static int wm8580_out_vu(struct snd_kcontrol *kcontrol, ...@@ -280,25 +213,22 @@ static int wm8580_out_vu(struct snd_kcontrol *kcontrol,
struct soc_mixer_control *mc = struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value; (struct soc_mixer_control *)kcontrol->private_value;
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
u16 *reg_cache = codec->reg_cache;
unsigned int reg = mc->reg; unsigned int reg = mc->reg;
unsigned int reg2 = mc->rreg; unsigned int reg2 = mc->rreg;
int ret; int ret;
u16 val;
/* Clear the register cache so we write without VU set */ /* Clear the register cache so we write without VU set */
wm8580_write_reg_cache(codec, reg, 0); reg_cache[reg] = 0;
wm8580_write_reg_cache(codec, reg2, 0); reg_cache[reg2] = 0;
ret = snd_soc_put_volsw_2r(kcontrol, ucontrol); ret = snd_soc_put_volsw_2r(kcontrol, ucontrol);
if (ret < 0) if (ret < 0)
return ret; return ret;
/* Now write again with the volume update bit set */ /* Now write again with the volume update bit set */
val = wm8580_read_reg_cache(codec, reg); snd_soc_update_bits(codec, reg, 0x100, 0x100);
wm8580_write(codec, reg, val | 0x0100); snd_soc_update_bits(codec, reg2, 0x100, 0x100);
val = wm8580_read_reg_cache(codec, reg2);
wm8580_write(codec, reg2, val | 0x0100);
return 0; return 0;
} }
...@@ -521,27 +451,27 @@ static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai, ...@@ -521,27 +451,27 @@ static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai,
/* Always disable the PLL - it is not safe to leave it running /* Always disable the PLL - it is not safe to leave it running
* while reprogramming it. * while reprogramming it.
*/ */
reg = wm8580_read(codec, WM8580_PWRDN2); reg = snd_soc_read(codec, WM8580_PWRDN2);
wm8580_write(codec, WM8580_PWRDN2, reg | pwr_mask); snd_soc_write(codec, WM8580_PWRDN2, reg | pwr_mask);
if (!freq_in || !freq_out) if (!freq_in || !freq_out)
return 0; return 0;
wm8580_write(codec, WM8580_PLLA1 + offset, pll_div.k & 0x1ff); snd_soc_write(codec, WM8580_PLLA1 + offset, pll_div.k & 0x1ff);
wm8580_write(codec, WM8580_PLLA2 + offset, (pll_div.k >> 9) & 0xff); snd_soc_write(codec, WM8580_PLLA2 + offset, (pll_div.k >> 9) & 0xff);
wm8580_write(codec, WM8580_PLLA3 + offset, snd_soc_write(codec, WM8580_PLLA3 + offset,
(pll_div.k >> 18 & 0xf) | (pll_div.n << 4)); (pll_div.k >> 18 & 0xf) | (pll_div.n << 4));
reg = wm8580_read(codec, WM8580_PLLA4 + offset); reg = snd_soc_read(codec, WM8580_PLLA4 + offset);
reg &= ~0x3f; reg &= ~0x3f;
reg |= pll_div.prescale | pll_div.postscale << 1 | reg |= pll_div.prescale | pll_div.postscale << 1 |
pll_div.freqmode << 3; pll_div.freqmode << 3;
wm8580_write(codec, WM8580_PLLA4 + offset, reg); snd_soc_write(codec, WM8580_PLLA4 + offset, reg);
/* All done, turn it on */ /* All done, turn it on */
reg = wm8580_read(codec, WM8580_PWRDN2); reg = snd_soc_read(codec, WM8580_PWRDN2);
wm8580_write(codec, WM8580_PWRDN2, reg & ~pwr_mask); snd_soc_write(codec, WM8580_PWRDN2, reg & ~pwr_mask);
return 0; return 0;
} }
...@@ -556,7 +486,7 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream, ...@@ -556,7 +486,7 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->card->codec; struct snd_soc_codec *codec = socdev->card->codec;
u16 paifb = wm8580_read(codec, WM8580_PAIF3 + dai->id); u16 paifb = snd_soc_read(codec, WM8580_PAIF3 + dai->id);
paifb &= ~WM8580_AIF_LENGTH_MASK; paifb &= ~WM8580_AIF_LENGTH_MASK;
/* bit size */ /* bit size */
...@@ -576,7 +506,7 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream, ...@@ -576,7 +506,7 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream,
return -EINVAL; return -EINVAL;
} }
wm8580_write(codec, WM8580_PAIF3 + dai->id, paifb); snd_soc_write(codec, WM8580_PAIF3 + dai->id, paifb);
return 0; return 0;
} }
...@@ -588,8 +518,8 @@ static int wm8580_set_paif_dai_fmt(struct snd_soc_dai *codec_dai, ...@@ -588,8 +518,8 @@ static int wm8580_set_paif_dai_fmt(struct snd_soc_dai *codec_dai,
unsigned int aifb; unsigned int aifb;
int can_invert_lrclk; int can_invert_lrclk;
aifa = wm8580_read(codec, WM8580_PAIF1 + codec_dai->id); aifa = snd_soc_read(codec, WM8580_PAIF1 + codec_dai->id);
aifb = wm8580_read(codec, WM8580_PAIF3 + codec_dai->id); aifb = snd_soc_read(codec, WM8580_PAIF3 + codec_dai->id);
aifb &= ~(WM8580_AIF_FMT_MASK | WM8580_AIF_LRP | WM8580_AIF_BCP); aifb &= ~(WM8580_AIF_FMT_MASK | WM8580_AIF_LRP | WM8580_AIF_BCP);
...@@ -655,8 +585,8 @@ static int wm8580_set_paif_dai_fmt(struct snd_soc_dai *codec_dai, ...@@ -655,8 +585,8 @@ static int wm8580_set_paif_dai_fmt(struct snd_soc_dai *codec_dai,
return -EINVAL; return -EINVAL;
} }
wm8580_write(codec, WM8580_PAIF1 + codec_dai->id, aifa); snd_soc_write(codec, WM8580_PAIF1 + codec_dai->id, aifa);
wm8580_write(codec, WM8580_PAIF3 + codec_dai->id, aifb); snd_soc_write(codec, WM8580_PAIF3 + codec_dai->id, aifb);
return 0; return 0;
} }
...@@ -669,7 +599,7 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai, ...@@ -669,7 +599,7 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
switch (div_id) { switch (div_id) {
case WM8580_MCLK: case WM8580_MCLK:
reg = wm8580_read(codec, WM8580_PLLB4); reg = snd_soc_read(codec, WM8580_PLLB4);
reg &= ~WM8580_PLLB4_MCLKOUTSRC_MASK; reg &= ~WM8580_PLLB4_MCLKOUTSRC_MASK;
switch (div) { switch (div) {
...@@ -691,11 +621,11 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai, ...@@ -691,11 +621,11 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
default: default:
return -EINVAL; return -EINVAL;
} }
wm8580_write(codec, WM8580_PLLB4, reg); snd_soc_write(codec, WM8580_PLLB4, reg);
break; break;
case WM8580_DAC_CLKSEL: case WM8580_DAC_CLKSEL:
reg = wm8580_read(codec, WM8580_CLKSEL); reg = snd_soc_read(codec, WM8580_CLKSEL);
reg &= ~WM8580_CLKSEL_DAC_CLKSEL_MASK; reg &= ~WM8580_CLKSEL_DAC_CLKSEL_MASK;
switch (div) { switch (div) {
...@@ -713,11 +643,11 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai, ...@@ -713,11 +643,11 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
default: default:
return -EINVAL; return -EINVAL;
} }
wm8580_write(codec, WM8580_CLKSEL, reg); snd_soc_write(codec, WM8580_CLKSEL, reg);
break; break;
case WM8580_CLKOUTSRC: case WM8580_CLKOUTSRC:
reg = wm8580_read(codec, WM8580_PLLB4); reg = snd_soc_read(codec, WM8580_PLLB4);
reg &= ~WM8580_PLLB4_CLKOUTSRC_MASK; reg &= ~WM8580_PLLB4_CLKOUTSRC_MASK;
switch (div) { switch (div) {
...@@ -739,7 +669,7 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai, ...@@ -739,7 +669,7 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
default: default:
return -EINVAL; return -EINVAL;
} }
wm8580_write(codec, WM8580_PLLB4, reg); snd_soc_write(codec, WM8580_PLLB4, reg);
break; break;
default: default:
...@@ -754,14 +684,14 @@ static int wm8580_digital_mute(struct snd_soc_dai *codec_dai, int mute) ...@@ -754,14 +684,14 @@ static int wm8580_digital_mute(struct snd_soc_dai *codec_dai, int mute)
struct snd_soc_codec *codec = codec_dai->codec; struct snd_soc_codec *codec = codec_dai->codec;
unsigned int reg; unsigned int reg;
reg = wm8580_read(codec, WM8580_DAC_CONTROL5); reg = snd_soc_read(codec, WM8580_DAC_CONTROL5);
if (mute) if (mute)
reg |= WM8580_DAC_CONTROL5_MUTEALL; reg |= WM8580_DAC_CONTROL5_MUTEALL;
else else
reg &= ~WM8580_DAC_CONTROL5_MUTEALL; reg &= ~WM8580_DAC_CONTROL5_MUTEALL;
wm8580_write(codec, WM8580_DAC_CONTROL5, reg); snd_soc_write(codec, WM8580_DAC_CONTROL5, reg);
return 0; return 0;
} }
...@@ -778,20 +708,20 @@ static int wm8580_set_bias_level(struct snd_soc_codec *codec, ...@@ -778,20 +708,20 @@ static int wm8580_set_bias_level(struct snd_soc_codec *codec,
case SND_SOC_BIAS_STANDBY: case SND_SOC_BIAS_STANDBY:
if (codec->bias_level == SND_SOC_BIAS_OFF) { if (codec->bias_level == SND_SOC_BIAS_OFF) {
/* Power up and get individual control of the DACs */ /* Power up and get individual control of the DACs */
reg = wm8580_read(codec, WM8580_PWRDN1); reg = snd_soc_read(codec, WM8580_PWRDN1);
reg &= ~(WM8580_PWRDN1_PWDN | WM8580_PWRDN1_ALLDACPD); reg &= ~(WM8580_PWRDN1_PWDN | WM8580_PWRDN1_ALLDACPD);
wm8580_write(codec, WM8580_PWRDN1, reg); snd_soc_write(codec, WM8580_PWRDN1, reg);
/* Make VMID high impedence */ /* Make VMID high impedence */
reg = wm8580_read(codec, WM8580_ADC_CONTROL1); reg = snd_soc_read(codec, WM8580_ADC_CONTROL1);
reg &= ~0x100; reg &= ~0x100;
wm8580_write(codec, WM8580_ADC_CONTROL1, reg); snd_soc_write(codec, WM8580_ADC_CONTROL1, reg);
} }
break; break;
case SND_SOC_BIAS_OFF: case SND_SOC_BIAS_OFF:
reg = wm8580_read(codec, WM8580_PWRDN1); reg = snd_soc_read(codec, WM8580_PWRDN1);
wm8580_write(codec, WM8580_PWRDN1, reg | WM8580_PWRDN1_PWDN); snd_soc_write(codec, WM8580_PWRDN1, reg | WM8580_PWRDN1_PWDN);
break; break;
} }
codec->bias_level = level; codec->bias_level = level;
...@@ -902,7 +832,8 @@ struct snd_soc_codec_device soc_codec_dev_wm8580 = { ...@@ -902,7 +832,8 @@ struct snd_soc_codec_device soc_codec_dev_wm8580 = {
}; };
EXPORT_SYMBOL_GPL(soc_codec_dev_wm8580); EXPORT_SYMBOL_GPL(soc_codec_dev_wm8580);
static int wm8580_register(struct wm8580_priv *wm8580) static int wm8580_register(struct wm8580_priv *wm8580,
enum snd_soc_control_type control)
{ {
int ret, i; int ret, i;
struct snd_soc_codec *codec = &wm8580->codec; struct snd_soc_codec *codec = &wm8580->codec;
...@@ -920,8 +851,6 @@ static int wm8580_register(struct wm8580_priv *wm8580) ...@@ -920,8 +851,6 @@ static int wm8580_register(struct wm8580_priv *wm8580)
codec->private_data = wm8580; codec->private_data = wm8580;
codec->name = "WM8580"; codec->name = "WM8580";
codec->owner = THIS_MODULE; codec->owner = THIS_MODULE;
codec->read = wm8580_read_reg_cache;
codec->write = wm8580_write;
codec->bias_level = SND_SOC_BIAS_OFF; codec->bias_level = SND_SOC_BIAS_OFF;
codec->set_bias_level = wm8580_set_bias_level; codec->set_bias_level = wm8580_set_bias_level;
codec->dai = wm8580_dai; codec->dai = wm8580_dai;
...@@ -931,6 +860,12 @@ static int wm8580_register(struct wm8580_priv *wm8580) ...@@ -931,6 +860,12 @@ static int wm8580_register(struct wm8580_priv *wm8580)
memcpy(codec->reg_cache, wm8580_reg, sizeof(wm8580_reg)); memcpy(codec->reg_cache, wm8580_reg, sizeof(wm8580_reg));
ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
goto err;
}
for (i = 0; i < ARRAY_SIZE(wm8580->supplies); i++) for (i = 0; i < ARRAY_SIZE(wm8580->supplies); i++)
wm8580->supplies[i].supply = wm8580_supply_names[i]; wm8580->supplies[i].supply = wm8580_supply_names[i];
...@@ -949,7 +884,7 @@ static int wm8580_register(struct wm8580_priv *wm8580) ...@@ -949,7 +884,7 @@ static int wm8580_register(struct wm8580_priv *wm8580)
} }
/* Get the codec into a known state */ /* Get the codec into a known state */
ret = wm8580_write(codec, WM8580_RESET, 0); ret = snd_soc_write(codec, WM8580_RESET, 0);
if (ret != 0) { if (ret != 0) {
dev_err(codec->dev, "Failed to reset codec: %d\n", ret); dev_err(codec->dev, "Failed to reset codec: %d\n", ret);
goto err_regulator_enable; goto err_regulator_enable;
...@@ -1010,14 +945,13 @@ static int wm8580_i2c_probe(struct i2c_client *i2c, ...@@ -1010,14 +945,13 @@ static int wm8580_i2c_probe(struct i2c_client *i2c,
return -ENOMEM; return -ENOMEM;
codec = &wm8580->codec; codec = &wm8580->codec;
codec->hw_write = (hw_write_t)i2c_master_send;
i2c_set_clientdata(i2c, wm8580); i2c_set_clientdata(i2c, wm8580);
codec->control_data = i2c; codec->control_data = i2c;
codec->dev = &i2c->dev; codec->dev = &i2c->dev;
return wm8580_register(wm8580); return wm8580_register(wm8580, SND_SOC_I2C);
} }
static int wm8580_i2c_remove(struct i2c_client *client) static int wm8580_i2c_remove(struct i2c_client *client)
......
...@@ -43,45 +43,6 @@ static const u16 wm8728_reg_defaults[] = { ...@@ -43,45 +43,6 @@ static const u16 wm8728_reg_defaults[] = {
0x100, 0x100,
}; };
static inline unsigned int wm8728_read_reg_cache(struct snd_soc_codec *codec,
unsigned int reg)
{
u16 *cache = codec->reg_cache;
BUG_ON(reg >= ARRAY_SIZE(wm8728_reg_defaults));
return cache[reg];
}
static inline void wm8728_write_reg_cache(struct snd_soc_codec *codec,
u16 reg, unsigned int value)
{
u16 *cache = codec->reg_cache;
BUG_ON(reg >= ARRAY_SIZE(wm8728_reg_defaults));
cache[reg] = value;
}
/*
* write to the WM8728 register space
*/
static int wm8728_write(struct snd_soc_codec *codec, unsigned int reg,
unsigned int value)
{
u8 data[2];
/* data is
* D15..D9 WM8728 register offset
* D8...D0 register data
*/
data[0] = (reg << 1) | ((value >> 8) & 0x0001);
data[1] = value & 0x00ff;
wm8728_write_reg_cache(codec, reg, value);
if (codec->hw_write(codec->control_data, data, 2) == 2)
return 0;
else
return -EIO;
}
static const DECLARE_TLV_DB_SCALE(wm8728_tlv, -12750, 50, 1); static const DECLARE_TLV_DB_SCALE(wm8728_tlv, -12750, 50, 1);
static const struct snd_kcontrol_new wm8728_snd_controls[] = { static const struct snd_kcontrol_new wm8728_snd_controls[] = {
...@@ -121,12 +82,12 @@ static int wm8728_add_widgets(struct snd_soc_codec *codec) ...@@ -121,12 +82,12 @@ static int wm8728_add_widgets(struct snd_soc_codec *codec)
static int wm8728_mute(struct snd_soc_dai *dai, int mute) static int wm8728_mute(struct snd_soc_dai *dai, int mute)
{ {
struct snd_soc_codec *codec = dai->codec; struct snd_soc_codec *codec = dai->codec;
u16 mute_reg = wm8728_read_reg_cache(codec, WM8728_DACCTL); u16 mute_reg = snd_soc_read(codec, WM8728_DACCTL);
if (mute) if (mute)
wm8728_write(codec, WM8728_DACCTL, mute_reg | 1); snd_soc_write(codec, WM8728_DACCTL, mute_reg | 1);
else else
wm8728_write(codec, WM8728_DACCTL, mute_reg & ~1); snd_soc_write(codec, WM8728_DACCTL, mute_reg & ~1);
return 0; return 0;
} }
...@@ -138,7 +99,7 @@ static int wm8728_hw_params(struct snd_pcm_substream *substream, ...@@ -138,7 +99,7 @@ static int wm8728_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->card->codec; struct snd_soc_codec *codec = socdev->card->codec;
u16 dac = wm8728_read_reg_cache(codec, WM8728_DACCTL); u16 dac = snd_soc_read(codec, WM8728_DACCTL);
dac &= ~0x18; dac &= ~0x18;
...@@ -155,7 +116,7 @@ static int wm8728_hw_params(struct snd_pcm_substream *substream, ...@@ -155,7 +116,7 @@ static int wm8728_hw_params(struct snd_pcm_substream *substream,
return -EINVAL; return -EINVAL;
} }
wm8728_write(codec, WM8728_DACCTL, dac); snd_soc_write(codec, WM8728_DACCTL, dac);
return 0; return 0;
} }
...@@ -164,7 +125,7 @@ static int wm8728_set_dai_fmt(struct snd_soc_dai *codec_dai, ...@@ -164,7 +125,7 @@ static int wm8728_set_dai_fmt(struct snd_soc_dai *codec_dai,
unsigned int fmt) unsigned int fmt)
{ {
struct snd_soc_codec *codec = codec_dai->codec; struct snd_soc_codec *codec = codec_dai->codec;
u16 iface = wm8728_read_reg_cache(codec, WM8728_IFCTL); u16 iface = snd_soc_read(codec, WM8728_IFCTL);
/* Currently only I2S is supported by the driver, though the /* Currently only I2S is supported by the driver, though the
* hardware is more flexible. * hardware is more flexible.
...@@ -204,7 +165,7 @@ static int wm8728_set_dai_fmt(struct snd_soc_dai *codec_dai, ...@@ -204,7 +165,7 @@ static int wm8728_set_dai_fmt(struct snd_soc_dai *codec_dai,
return -EINVAL; return -EINVAL;
} }
wm8728_write(codec, WM8728_IFCTL, iface); snd_soc_write(codec, WM8728_IFCTL, iface);
return 0; return 0;
} }
...@@ -220,19 +181,19 @@ static int wm8728_set_bias_level(struct snd_soc_codec *codec, ...@@ -220,19 +181,19 @@ static int wm8728_set_bias_level(struct snd_soc_codec *codec,
case SND_SOC_BIAS_STANDBY: case SND_SOC_BIAS_STANDBY:
if (codec->bias_level == SND_SOC_BIAS_OFF) { if (codec->bias_level == SND_SOC_BIAS_OFF) {
/* Power everything up... */ /* Power everything up... */
reg = wm8728_read_reg_cache(codec, WM8728_DACCTL); reg = snd_soc_read(codec, WM8728_DACCTL);
wm8728_write(codec, WM8728_DACCTL, reg & ~0x4); snd_soc_write(codec, WM8728_DACCTL, reg & ~0x4);
/* ..then sync in the register cache. */ /* ..then sync in the register cache. */
for (i = 0; i < ARRAY_SIZE(wm8728_reg_defaults); i++) for (i = 0; i < ARRAY_SIZE(wm8728_reg_defaults); i++)
wm8728_write(codec, i, snd_soc_write(codec, i,
wm8728_read_reg_cache(codec, i)); snd_soc_read(codec, i));
} }
break; break;
case SND_SOC_BIAS_OFF: case SND_SOC_BIAS_OFF:
reg = wm8728_read_reg_cache(codec, WM8728_DACCTL); reg = snd_soc_read(codec, WM8728_DACCTL);
wm8728_write(codec, WM8728_DACCTL, reg | 0x4); snd_soc_write(codec, WM8728_DACCTL, reg | 0x4);
break; break;
} }
codec->bias_level = level; codec->bias_level = level;
...@@ -287,15 +248,14 @@ static int wm8728_resume(struct platform_device *pdev) ...@@ -287,15 +248,14 @@ static int wm8728_resume(struct platform_device *pdev)
* initialise the WM8728 driver * initialise the WM8728 driver
* register the mixer and dsp interfaces with the kernel * register the mixer and dsp interfaces with the kernel
*/ */
static int wm8728_init(struct snd_soc_device *socdev) static int wm8728_init(struct snd_soc_device *socdev,
enum snd_soc_control_type control)
{ {
struct snd_soc_codec *codec = socdev->card->codec; struct snd_soc_codec *codec = socdev->card->codec;
int ret = 0; int ret = 0;
codec->name = "WM8728"; codec->name = "WM8728";
codec->owner = THIS_MODULE; codec->owner = THIS_MODULE;
codec->read = wm8728_read_reg_cache;
codec->write = wm8728_write;
codec->set_bias_level = wm8728_set_bias_level; codec->set_bias_level = wm8728_set_bias_level;
codec->dai = &wm8728_dai; codec->dai = &wm8728_dai;
codec->num_dai = 1; codec->num_dai = 1;
...@@ -307,11 +267,18 @@ static int wm8728_init(struct snd_soc_device *socdev) ...@@ -307,11 +267,18 @@ static int wm8728_init(struct snd_soc_device *socdev)
if (codec->reg_cache == NULL) if (codec->reg_cache == NULL)
return -ENOMEM; return -ENOMEM;
ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
if (ret < 0) {
printk(KERN_ERR "wm8728: failed to configure cache I/O: %d\n",
ret);
goto err;
}
/* register pcms */ /* register pcms */
ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
if (ret < 0) { if (ret < 0) {
printk(KERN_ERR "wm8728: failed to create pcms\n"); printk(KERN_ERR "wm8728: failed to create pcms\n");
goto pcm_err; goto err;
} }
/* power on device */ /* power on device */
...@@ -331,7 +298,7 @@ static int wm8728_init(struct snd_soc_device *socdev) ...@@ -331,7 +298,7 @@ static int wm8728_init(struct snd_soc_device *socdev)
card_err: card_err:
snd_soc_free_pcms(socdev); snd_soc_free_pcms(socdev);
snd_soc_dapm_free(socdev); snd_soc_dapm_free(socdev);
pcm_err: err:
kfree(codec->reg_cache); kfree(codec->reg_cache);
return ret; return ret;
} }
...@@ -357,7 +324,7 @@ static int wm8728_i2c_probe(struct i2c_client *i2c, ...@@ -357,7 +324,7 @@ static int wm8728_i2c_probe(struct i2c_client *i2c,
i2c_set_clientdata(i2c, codec); i2c_set_clientdata(i2c, codec);
codec->control_data = i2c; codec->control_data = i2c;
ret = wm8728_init(socdev); ret = wm8728_init(socdev, SND_SOC_I2C);
if (ret < 0) if (ret < 0)
pr_err("failed to initialise WM8728\n"); pr_err("failed to initialise WM8728\n");
...@@ -437,7 +404,7 @@ static int __devinit wm8728_spi_probe(struct spi_device *spi) ...@@ -437,7 +404,7 @@ static int __devinit wm8728_spi_probe(struct spi_device *spi)
codec->control_data = spi; codec->control_data = spi;
ret = wm8728_init(socdev); ret = wm8728_init(socdev, SND_SOC_SPI);
if (ret < 0) if (ret < 0)
dev_err(&spi->dev, "failed to initialise WM8728\n"); dev_err(&spi->dev, "failed to initialise WM8728\n");
...@@ -458,30 +425,6 @@ static struct spi_driver wm8728_spi_driver = { ...@@ -458,30 +425,6 @@ static struct spi_driver wm8728_spi_driver = {
.probe = wm8728_spi_probe, .probe = wm8728_spi_probe,
.remove = __devexit_p(wm8728_spi_remove), .remove = __devexit_p(wm8728_spi_remove),
}; };
static int wm8728_spi_write(struct spi_device *spi, const char *data, int len)
{
struct spi_transfer t;
struct spi_message m;
u8 msg[2];
if (len <= 0)
return 0;
msg[0] = data[0];
msg[1] = data[1];
spi_message_init(&m);
memset(&t, 0, (sizeof t));
t.tx_buf = &msg[0];
t.len = len;
spi_message_add_tail(&t, &m);
spi_sync(spi, &m);
return len;
}
#endif /* CONFIG_SPI_MASTER */ #endif /* CONFIG_SPI_MASTER */
static int wm8728_probe(struct platform_device *pdev) static int wm8728_probe(struct platform_device *pdev)
...@@ -506,13 +449,11 @@ static int wm8728_probe(struct platform_device *pdev) ...@@ -506,13 +449,11 @@ static int wm8728_probe(struct platform_device *pdev)
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
if (setup->i2c_address) { if (setup->i2c_address) {
codec->hw_write = (hw_write_t)i2c_master_send;
ret = wm8728_add_i2c_device(pdev, setup); ret = wm8728_add_i2c_device(pdev, setup);
} }
#endif #endif
#if defined(CONFIG_SPI_MASTER) #if defined(CONFIG_SPI_MASTER)
if (setup->spi) { if (setup->spi) {
codec->hw_write = (hw_write_t)wm8728_spi_write;
ret = spi_register_driver(&wm8728_spi_driver); ret = spi_register_driver(&wm8728_spi_driver);
if (ret != 0) if (ret != 0)
printk(KERN_ERR "can't add spi driver"); printk(KERN_ERR "can't add spi driver");
......
...@@ -51,60 +51,12 @@ static int wm8731_spi_write(struct spi_device *spi, const char *data, int len); ...@@ -51,60 +51,12 @@ static int wm8731_spi_write(struct spi_device *spi, const char *data, int len);
* There is no point in caching the reset register * There is no point in caching the reset register
*/ */
static const u16 wm8731_reg[WM8731_CACHEREGNUM] = { static const u16 wm8731_reg[WM8731_CACHEREGNUM] = {
0x0097, 0x0097, 0x0079, 0x0079, 0x0097, 0x0097, 0x0079, 0x0079,
0x000a, 0x0008, 0x009f, 0x000a, 0x000a, 0x0008, 0x009f, 0x000a,
0x0000, 0x0000 0x0000, 0x0000
}; };
/* #define wm8731_reset(c) snd_soc_write(c, WM8731_RESET, 0)
* read wm8731 register cache
*/
static inline unsigned int wm8731_read_reg_cache(struct snd_soc_codec *codec,
unsigned int reg)
{
u16 *cache = codec->reg_cache;
if (reg == WM8731_RESET)
return 0;
if (reg >= WM8731_CACHEREGNUM)
return -1;
return cache[reg];
}
/*
* write wm8731 register cache
*/
static inline void wm8731_write_reg_cache(struct snd_soc_codec *codec,
u16 reg, unsigned int value)
{
u16 *cache = codec->reg_cache;
if (reg >= WM8731_CACHEREGNUM)
return;
cache[reg] = value;
}
/*
* write to the WM8731 register space
*/
static int wm8731_write(struct snd_soc_codec *codec, unsigned int reg,
unsigned int value)
{
u8 data[2];
/* data is
* D15..D9 WM8731 register offset
* D8...D0 register data
*/
data[0] = (reg << 1) | ((value >> 8) & 0x0001);
data[1] = value & 0x00ff;
wm8731_write_reg_cache(codec, reg, value);
if (codec->hw_write(codec->control_data, data, 2) == 2)
return 0;
else
return -EIO;
}
#define wm8731_reset(c) wm8731_write(c, WM8731_RESET, 0)
static const char *wm8731_input_select[] = {"Line In", "Mic"}; static const char *wm8731_input_select[] = {"Line In", "Mic"};
static const char *wm8731_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"}; static const char *wm8731_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"};
...@@ -267,12 +219,12 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream, ...@@ -267,12 +219,12 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->card->codec; struct snd_soc_codec *codec = socdev->card->codec;
struct wm8731_priv *wm8731 = codec->private_data; struct wm8731_priv *wm8731 = codec->private_data;
u16 iface = wm8731_read_reg_cache(codec, WM8731_IFACE) & 0xfff3; u16 iface = snd_soc_read(codec, WM8731_IFACE) & 0xfff3;
int i = get_coeff(wm8731->sysclk, params_rate(params)); int i = get_coeff(wm8731->sysclk, params_rate(params));
u16 srate = (coeff_div[i].sr << 2) | u16 srate = (coeff_div[i].sr << 2) |
(coeff_div[i].bosr << 1) | coeff_div[i].usb; (coeff_div[i].bosr << 1) | coeff_div[i].usb;
wm8731_write(codec, WM8731_SRATE, srate); snd_soc_write(codec, WM8731_SRATE, srate);
/* bit size */ /* bit size */
switch (params_format(params)) { switch (params_format(params)) {
...@@ -286,7 +238,7 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream, ...@@ -286,7 +238,7 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream,
break; break;
} }
wm8731_write(codec, WM8731_IFACE, iface); snd_soc_write(codec, WM8731_IFACE, iface);
return 0; return 0;
} }
...@@ -298,7 +250,7 @@ static int wm8731_pcm_prepare(struct snd_pcm_substream *substream, ...@@ -298,7 +250,7 @@ static int wm8731_pcm_prepare(struct snd_pcm_substream *substream,
struct snd_soc_codec *codec = socdev->card->codec; struct snd_soc_codec *codec = socdev->card->codec;
/* set active */ /* set active */
wm8731_write(codec, WM8731_ACTIVE, 0x0001); snd_soc_write(codec, WM8731_ACTIVE, 0x0001);
return 0; return 0;
} }
...@@ -313,19 +265,19 @@ static void wm8731_shutdown(struct snd_pcm_substream *substream, ...@@ -313,19 +265,19 @@ static void wm8731_shutdown(struct snd_pcm_substream *substream,
/* deactivate */ /* deactivate */
if (!codec->active) { if (!codec->active) {
udelay(50); udelay(50);
wm8731_write(codec, WM8731_ACTIVE, 0x0); snd_soc_write(codec, WM8731_ACTIVE, 0x0);
} }
} }
static int wm8731_mute(struct snd_soc_dai *dai, int mute) static int wm8731_mute(struct snd_soc_dai *dai, int mute)
{ {
struct snd_soc_codec *codec = dai->codec; struct snd_soc_codec *codec = dai->codec;
u16 mute_reg = wm8731_read_reg_cache(codec, WM8731_APDIGI) & 0xfff7; u16 mute_reg = snd_soc_read(codec, WM8731_APDIGI) & 0xfff7;
if (mute) if (mute)
wm8731_write(codec, WM8731_APDIGI, mute_reg | 0x8); snd_soc_write(codec, WM8731_APDIGI, mute_reg | 0x8);
else else
wm8731_write(codec, WM8731_APDIGI, mute_reg); snd_soc_write(codec, WM8731_APDIGI, mute_reg);
return 0; return 0;
} }
...@@ -403,7 +355,7 @@ static int wm8731_set_dai_fmt(struct snd_soc_dai *codec_dai, ...@@ -403,7 +355,7 @@ static int wm8731_set_dai_fmt(struct snd_soc_dai *codec_dai,
} }
/* set iface */ /* set iface */
wm8731_write(codec, WM8731_IFACE, iface); snd_soc_write(codec, WM8731_IFACE, iface);
return 0; return 0;
} }
...@@ -419,12 +371,12 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec, ...@@ -419,12 +371,12 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec,
break; break;
case SND_SOC_BIAS_STANDBY: case SND_SOC_BIAS_STANDBY:
/* Clear PWROFF, gate CLKOUT, everything else as-is */ /* Clear PWROFF, gate CLKOUT, everything else as-is */
reg = wm8731_read_reg_cache(codec, WM8731_PWR) & 0xff7f; reg = snd_soc_read(codec, WM8731_PWR) & 0xff7f;
wm8731_write(codec, WM8731_PWR, reg | 0x0040); snd_soc_write(codec, WM8731_PWR, reg | 0x0040);
break; break;
case SND_SOC_BIAS_OFF: case SND_SOC_BIAS_OFF:
wm8731_write(codec, WM8731_ACTIVE, 0x0); snd_soc_write(codec, WM8731_ACTIVE, 0x0);
wm8731_write(codec, WM8731_PWR, 0xffff); snd_soc_write(codec, WM8731_PWR, 0xffff);
break; break;
} }
codec->bias_level = level; codec->bias_level = level;
...@@ -474,7 +426,7 @@ static int wm8731_suspend(struct platform_device *pdev, pm_message_t state) ...@@ -474,7 +426,7 @@ static int wm8731_suspend(struct platform_device *pdev, pm_message_t state)
struct snd_soc_device *socdev = platform_get_drvdata(pdev); struct snd_soc_device *socdev = platform_get_drvdata(pdev);
struct snd_soc_codec *codec = socdev->card->codec; struct snd_soc_codec *codec = socdev->card->codec;
wm8731_write(codec, WM8731_ACTIVE, 0x0); snd_soc_write(codec, WM8731_ACTIVE, 0x0);
wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0; return 0;
} }
...@@ -560,11 +512,11 @@ struct snd_soc_codec_device soc_codec_dev_wm8731 = { ...@@ -560,11 +512,11 @@ struct snd_soc_codec_device soc_codec_dev_wm8731 = {
}; };
EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731); EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731);
static int wm8731_register(struct wm8731_priv *wm8731) static int wm8731_register(struct wm8731_priv *wm8731,
enum snd_soc_control_type control)
{ {
int ret; int ret;
struct snd_soc_codec *codec = &wm8731->codec; struct snd_soc_codec *codec = &wm8731->codec;
u16 reg;
if (wm8731_codec) { if (wm8731_codec) {
dev_err(codec->dev, "Another WM8731 is registered\n"); dev_err(codec->dev, "Another WM8731 is registered\n");
...@@ -579,8 +531,6 @@ static int wm8731_register(struct wm8731_priv *wm8731) ...@@ -579,8 +531,6 @@ static int wm8731_register(struct wm8731_priv *wm8731)
codec->private_data = wm8731; codec->private_data = wm8731;
codec->name = "WM8731"; codec->name = "WM8731";
codec->owner = THIS_MODULE; codec->owner = THIS_MODULE;
codec->read = wm8731_read_reg_cache;
codec->write = wm8731_write;
codec->bias_level = SND_SOC_BIAS_OFF; codec->bias_level = SND_SOC_BIAS_OFF;
codec->set_bias_level = wm8731_set_bias_level; codec->set_bias_level = wm8731_set_bias_level;
codec->dai = &wm8731_dai; codec->dai = &wm8731_dai;
...@@ -590,6 +540,12 @@ static int wm8731_register(struct wm8731_priv *wm8731) ...@@ -590,6 +540,12 @@ static int wm8731_register(struct wm8731_priv *wm8731)
memcpy(codec->reg_cache, wm8731_reg, sizeof(wm8731_reg)); memcpy(codec->reg_cache, wm8731_reg, sizeof(wm8731_reg));
ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
goto err;
}
ret = wm8731_reset(codec); ret = wm8731_reset(codec);
if (ret < 0) { if (ret < 0) {
dev_err(codec->dev, "Failed to issue reset: %d\n", ret); dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
...@@ -601,18 +557,13 @@ static int wm8731_register(struct wm8731_priv *wm8731) ...@@ -601,18 +557,13 @@ static int wm8731_register(struct wm8731_priv *wm8731)
wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY); wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
/* Latch the update bits */ /* Latch the update bits */
reg = wm8731_read_reg_cache(codec, WM8731_LOUT1V); snd_soc_update_bits(codec, WM8731_LOUT1V, 0x100, 0);
wm8731_write(codec, WM8731_LOUT1V, reg & ~0x0100); snd_soc_update_bits(codec, WM8731_ROUT1V, 0x100, 0);
reg = wm8731_read_reg_cache(codec, WM8731_ROUT1V); snd_soc_update_bits(codec, WM8731_LINVOL, 0x100, 0);
wm8731_write(codec, WM8731_ROUT1V, reg & ~0x0100); snd_soc_update_bits(codec, WM8731_RINVOL, 0x100, 0);
reg = wm8731_read_reg_cache(codec, WM8731_LINVOL);
wm8731_write(codec, WM8731_LINVOL, reg & ~0x0100);
reg = wm8731_read_reg_cache(codec, WM8731_RINVOL);
wm8731_write(codec, WM8731_RINVOL, reg & ~0x0100);
/* Disable bypass path by default */ /* Disable bypass path by default */
reg = wm8731_read_reg_cache(codec, WM8731_APANA); snd_soc_update_bits(codec, WM8731_APANA, 0x4, 0);
wm8731_write(codec, WM8731_APANA, reg & ~0x4);
wm8731_codec = codec; wm8731_codec = codec;
...@@ -648,30 +599,6 @@ static void wm8731_unregister(struct wm8731_priv *wm8731) ...@@ -648,30 +599,6 @@ static void wm8731_unregister(struct wm8731_priv *wm8731)
} }
#if defined(CONFIG_SPI_MASTER) #if defined(CONFIG_SPI_MASTER)
static int wm8731_spi_write(struct spi_device *spi, const char *data, int len)
{
struct spi_transfer t;
struct spi_message m;
u8 msg[2];
if (len <= 0)
return 0;
msg[0] = data[0];
msg[1] = data[1];
spi_message_init(&m);
memset(&t, 0, (sizeof t));
t.tx_buf = &msg[0];
t.len = len;
spi_message_add_tail(&t, &m);
spi_sync(spi, &m);
return len;
}
static int __devinit wm8731_spi_probe(struct spi_device *spi) static int __devinit wm8731_spi_probe(struct spi_device *spi)
{ {
struct snd_soc_codec *codec; struct snd_soc_codec *codec;
...@@ -683,12 +610,11 @@ static int __devinit wm8731_spi_probe(struct spi_device *spi) ...@@ -683,12 +610,11 @@ static int __devinit wm8731_spi_probe(struct spi_device *spi)
codec = &wm8731->codec; codec = &wm8731->codec;
codec->control_data = spi; codec->control_data = spi;
codec->hw_write = (hw_write_t)wm8731_spi_write;
codec->dev = &spi->dev; codec->dev = &spi->dev;
dev_set_drvdata(&spi->dev, wm8731); dev_set_drvdata(&spi->dev, wm8731);
return wm8731_register(wm8731); return wm8731_register(wm8731, SND_SOC_SPI);
} }
static int __devexit wm8731_spi_remove(struct spi_device *spi) static int __devexit wm8731_spi_remove(struct spi_device *spi)
...@@ -740,14 +666,13 @@ static __devinit int wm8731_i2c_probe(struct i2c_client *i2c, ...@@ -740,14 +666,13 @@ static __devinit int wm8731_i2c_probe(struct i2c_client *i2c,
return -ENOMEM; return -ENOMEM;
codec = &wm8731->codec; codec = &wm8731->codec;
codec->hw_write = (hw_write_t)i2c_master_send;
i2c_set_clientdata(i2c, wm8731); i2c_set_clientdata(i2c, wm8731);
codec->control_data = i2c; codec->control_data = i2c;
codec->dev = &i2c->dev; codec->dev = &i2c->dev;
return wm8731_register(wm8731); return wm8731_register(wm8731, SND_SOC_I2C);
} }
static __devexit int wm8731_i2c_remove(struct i2c_client *client) static __devexit int wm8731_i2c_remove(struct i2c_client *client)
......
...@@ -55,50 +55,7 @@ static const u16 wm8750_reg[] = { ...@@ -55,50 +55,7 @@ static const u16 wm8750_reg[] = {
0x0079, 0x0079, 0x0079, /* 40 */ 0x0079, 0x0079, 0x0079, /* 40 */
}; };
/* #define wm8750_reset(c) snd_soc_write(c, WM8750_RESET, 0)
* read wm8750 register cache
*/
static inline unsigned int wm8750_read_reg_cache(struct snd_soc_codec *codec,
unsigned int reg)
{
u16 *cache = codec->reg_cache;
if (reg > WM8750_CACHE_REGNUM)
return -1;
return cache[reg];
}
/*
* write wm8750 register cache
*/
static inline void wm8750_write_reg_cache(struct snd_soc_codec *codec,
unsigned int reg, unsigned int value)
{
u16 *cache = codec->reg_cache;
if (reg > WM8750_CACHE_REGNUM)
return;
cache[reg] = value;
}
static int wm8750_write(struct snd_soc_codec *codec, unsigned int reg,
unsigned int value)
{
u8 data[2];
/* data is
* D15..D9 WM8753 register offset
* D8...D0 register data
*/
data[0] = (reg << 1) | ((value >> 8) & 0x0001);
data[1] = value & 0x00ff;
wm8750_write_reg_cache(codec, reg, value);
if (codec->hw_write(codec->control_data, data, 2) == 2)
return 0;
else
return -EIO;
}
#define wm8750_reset(c) wm8750_write(c, WM8750_RESET, 0)
/* /*
* WM8750 Controls * WM8750 Controls
...@@ -594,7 +551,7 @@ static int wm8750_set_dai_fmt(struct snd_soc_dai *codec_dai, ...@@ -594,7 +551,7 @@ static int wm8750_set_dai_fmt(struct snd_soc_dai *codec_dai,
return -EINVAL; return -EINVAL;
} }
wm8750_write(codec, WM8750_IFACE, iface); snd_soc_write(codec, WM8750_IFACE, iface);
return 0; return 0;
} }
...@@ -606,8 +563,8 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream, ...@@ -606,8 +563,8 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->card->codec; struct snd_soc_codec *codec = socdev->card->codec;
struct wm8750_priv *wm8750 = codec->private_data; struct wm8750_priv *wm8750 = codec->private_data;
u16 iface = wm8750_read_reg_cache(codec, WM8750_IFACE) & 0x1f3; u16 iface = snd_soc_read(codec, WM8750_IFACE) & 0x1f3;
u16 srate = wm8750_read_reg_cache(codec, WM8750_SRATE) & 0x1c0; u16 srate = snd_soc_read(codec, WM8750_SRATE) & 0x1c0;
int coeff = get_coeff(wm8750->sysclk, params_rate(params)); int coeff = get_coeff(wm8750->sysclk, params_rate(params));
/* bit size */ /* bit size */
...@@ -626,9 +583,9 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream, ...@@ -626,9 +583,9 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream,
} }
/* set iface & srate */ /* set iface & srate */
wm8750_write(codec, WM8750_IFACE, iface); snd_soc_write(codec, WM8750_IFACE, iface);
if (coeff >= 0) if (coeff >= 0)
wm8750_write(codec, WM8750_SRATE, srate | snd_soc_write(codec, WM8750_SRATE, srate |
(coeff_div[coeff].sr << 1) | coeff_div[coeff].usb); (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb);
return 0; return 0;
...@@ -637,35 +594,35 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream, ...@@ -637,35 +594,35 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream,
static int wm8750_mute(struct snd_soc_dai *dai, int mute) static int wm8750_mute(struct snd_soc_dai *dai, int mute)
{ {
struct snd_soc_codec *codec = dai->codec; struct snd_soc_codec *codec = dai->codec;
u16 mute_reg = wm8750_read_reg_cache(codec, WM8750_ADCDAC) & 0xfff7; u16 mute_reg = snd_soc_read(codec, WM8750_ADCDAC) & 0xfff7;
if (mute) if (mute)
wm8750_write(codec, WM8750_ADCDAC, mute_reg | 0x8); snd_soc_write(codec, WM8750_ADCDAC, mute_reg | 0x8);
else else
wm8750_write(codec, WM8750_ADCDAC, mute_reg); snd_soc_write(codec, WM8750_ADCDAC, mute_reg);
return 0; return 0;
} }
static int wm8750_set_bias_level(struct snd_soc_codec *codec, static int wm8750_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level) enum snd_soc_bias_level level)
{ {
u16 pwr_reg = wm8750_read_reg_cache(codec, WM8750_PWR1) & 0xfe3e; u16 pwr_reg = snd_soc_read(codec, WM8750_PWR1) & 0xfe3e;
switch (level) { switch (level) {
case SND_SOC_BIAS_ON: case SND_SOC_BIAS_ON:
/* set vmid to 50k and unmute dac */ /* set vmid to 50k and unmute dac */
wm8750_write(codec, WM8750_PWR1, pwr_reg | 0x00c0); snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x00c0);
break; break;
case SND_SOC_BIAS_PREPARE: case SND_SOC_BIAS_PREPARE:
/* set vmid to 5k for quick power up */ /* set vmid to 5k for quick power up */
wm8750_write(codec, WM8750_PWR1, pwr_reg | 0x01c1); snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x01c1);
break; break;
case SND_SOC_BIAS_STANDBY: case SND_SOC_BIAS_STANDBY:
/* mute dac and set vmid to 500k, enable VREF */ /* mute dac and set vmid to 500k, enable VREF */
wm8750_write(codec, WM8750_PWR1, pwr_reg | 0x0141); snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x0141);
break; break;
case SND_SOC_BIAS_OFF: case SND_SOC_BIAS_OFF:
wm8750_write(codec, WM8750_PWR1, 0x0001); snd_soc_write(codec, WM8750_PWR1, 0x0001);
break; break;
} }
codec->bias_level = level; codec->bias_level = level;
...@@ -754,15 +711,14 @@ static int wm8750_resume(struct platform_device *pdev) ...@@ -754,15 +711,14 @@ static int wm8750_resume(struct platform_device *pdev)
* initialise the WM8750 driver * initialise the WM8750 driver
* register the mixer and dsp interfaces with the kernel * register the mixer and dsp interfaces with the kernel
*/ */
static int wm8750_init(struct snd_soc_device *socdev) static int wm8750_init(struct snd_soc_device *socdev,
enum snd_soc_control_type control)
{ {
struct snd_soc_codec *codec = socdev->card->codec; struct snd_soc_codec *codec = socdev->card->codec;
int reg, ret = 0; int reg, ret = 0;
codec->name = "WM8750"; codec->name = "WM8750";
codec->owner = THIS_MODULE; codec->owner = THIS_MODULE;
codec->read = wm8750_read_reg_cache;
codec->write = wm8750_write;
codec->set_bias_level = wm8750_set_bias_level; codec->set_bias_level = wm8750_set_bias_level;
codec->dai = &wm8750_dai; codec->dai = &wm8750_dai;
codec->num_dai = 1; codec->num_dai = 1;
...@@ -771,13 +727,23 @@ static int wm8750_init(struct snd_soc_device *socdev) ...@@ -771,13 +727,23 @@ static int wm8750_init(struct snd_soc_device *socdev)
if (codec->reg_cache == NULL) if (codec->reg_cache == NULL)
return -ENOMEM; return -ENOMEM;
wm8750_reset(codec); ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
if (ret < 0) {
printk(KERN_ERR "wm8750: failed to set cache I/O: %d\n", ret);
goto err;
}
ret = wm8750_reset(codec);
if (ret < 0) {
printk(KERN_ERR "wm8750: failed to reset: %d\n", ret);
goto err;
}
/* register pcms */ /* register pcms */
ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
if (ret < 0) { if (ret < 0) {
printk(KERN_ERR "wm8750: failed to create pcms\n"); printk(KERN_ERR "wm8750: failed to create pcms\n");
goto pcm_err; goto err;
} }
/* charge output caps */ /* charge output caps */
...@@ -786,22 +752,22 @@ static int wm8750_init(struct snd_soc_device *socdev) ...@@ -786,22 +752,22 @@ static int wm8750_init(struct snd_soc_device *socdev)
schedule_delayed_work(&codec->delayed_work, msecs_to_jiffies(1000)); schedule_delayed_work(&codec->delayed_work, msecs_to_jiffies(1000));
/* set the update bits */ /* set the update bits */
reg = wm8750_read_reg_cache(codec, WM8750_LDAC); reg = snd_soc_read(codec, WM8750_LDAC);
wm8750_write(codec, WM8750_LDAC, reg | 0x0100); snd_soc_write(codec, WM8750_LDAC, reg | 0x0100);
reg = wm8750_read_reg_cache(codec, WM8750_RDAC); reg = snd_soc_read(codec, WM8750_RDAC);
wm8750_write(codec, WM8750_RDAC, reg | 0x0100); snd_soc_write(codec, WM8750_RDAC, reg | 0x0100);
reg = wm8750_read_reg_cache(codec, WM8750_LOUT1V); reg = snd_soc_read(codec, WM8750_LOUT1V);
wm8750_write(codec, WM8750_LOUT1V, reg | 0x0100); snd_soc_write(codec, WM8750_LOUT1V, reg | 0x0100);
reg = wm8750_read_reg_cache(codec, WM8750_ROUT1V); reg = snd_soc_read(codec, WM8750_ROUT1V);
wm8750_write(codec, WM8750_ROUT1V, reg | 0x0100); snd_soc_write(codec, WM8750_ROUT1V, reg | 0x0100);
reg = wm8750_read_reg_cache(codec, WM8750_LOUT2V); reg = snd_soc_read(codec, WM8750_LOUT2V);
wm8750_write(codec, WM8750_LOUT2V, reg | 0x0100); snd_soc_write(codec, WM8750_LOUT2V, reg | 0x0100);
reg = wm8750_read_reg_cache(codec, WM8750_ROUT2V); reg = snd_soc_read(codec, WM8750_ROUT2V);
wm8750_write(codec, WM8750_ROUT2V, reg | 0x0100); snd_soc_write(codec, WM8750_ROUT2V, reg | 0x0100);
reg = wm8750_read_reg_cache(codec, WM8750_LINVOL); reg = snd_soc_read(codec, WM8750_LINVOL);
wm8750_write(codec, WM8750_LINVOL, reg | 0x0100); snd_soc_write(codec, WM8750_LINVOL, reg | 0x0100);
reg = wm8750_read_reg_cache(codec, WM8750_RINVOL); reg = snd_soc_read(codec, WM8750_RINVOL);
wm8750_write(codec, WM8750_RINVOL, reg | 0x0100); snd_soc_write(codec, WM8750_RINVOL, reg | 0x0100);
snd_soc_add_controls(codec, wm8750_snd_controls, snd_soc_add_controls(codec, wm8750_snd_controls,
ARRAY_SIZE(wm8750_snd_controls)); ARRAY_SIZE(wm8750_snd_controls));
...@@ -816,7 +782,7 @@ static int wm8750_init(struct snd_soc_device *socdev) ...@@ -816,7 +782,7 @@ static int wm8750_init(struct snd_soc_device *socdev)
card_err: card_err:
snd_soc_free_pcms(socdev); snd_soc_free_pcms(socdev);
snd_soc_dapm_free(socdev); snd_soc_dapm_free(socdev);
pcm_err: err:
kfree(codec->reg_cache); kfree(codec->reg_cache);
return ret; return ret;
} }
...@@ -844,7 +810,7 @@ static int wm8750_i2c_probe(struct i2c_client *i2c, ...@@ -844,7 +810,7 @@ static int wm8750_i2c_probe(struct i2c_client *i2c,
i2c_set_clientdata(i2c, codec); i2c_set_clientdata(i2c, codec);
codec->control_data = i2c; codec->control_data = i2c;
ret = wm8750_init(socdev); ret = wm8750_init(socdev, SND_SOC_I2C);
if (ret < 0) if (ret < 0)
pr_err("failed to initialise WM8750\n"); pr_err("failed to initialise WM8750\n");
...@@ -924,7 +890,7 @@ static int __devinit wm8750_spi_probe(struct spi_device *spi) ...@@ -924,7 +890,7 @@ static int __devinit wm8750_spi_probe(struct spi_device *spi)
codec->control_data = spi; codec->control_data = spi;
ret = wm8750_init(socdev); ret = wm8750_init(socdev, SND_SOC_SPI);
if (ret < 0) if (ret < 0)
dev_err(&spi->dev, "failed to initialise WM8750\n"); dev_err(&spi->dev, "failed to initialise WM8750\n");
...@@ -945,30 +911,6 @@ static struct spi_driver wm8750_spi_driver = { ...@@ -945,30 +911,6 @@ static struct spi_driver wm8750_spi_driver = {
.probe = wm8750_spi_probe, .probe = wm8750_spi_probe,
.remove = __devexit_p(wm8750_spi_remove), .remove = __devexit_p(wm8750_spi_remove),
}; };
static int wm8750_spi_write(struct spi_device *spi, const char *data, int len)
{
struct spi_transfer t;
struct spi_message m;
u8 msg[2];
if (len <= 0)
return 0;
msg[0] = data[0];
msg[1] = data[1];
spi_message_init(&m);
memset(&t, 0, (sizeof t));
t.tx_buf = &msg[0];
t.len = len;
spi_message_add_tail(&t, &m);
spi_sync(spi, &m);
return len;
}
#endif #endif
static int wm8750_probe(struct platform_device *pdev) static int wm8750_probe(struct platform_device *pdev)
...@@ -1002,13 +944,11 @@ static int wm8750_probe(struct platform_device *pdev) ...@@ -1002,13 +944,11 @@ static int wm8750_probe(struct platform_device *pdev)
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
if (setup->i2c_address) { if (setup->i2c_address) {
codec->hw_write = (hw_write_t)i2c_master_send;
ret = wm8750_add_i2c_device(pdev, setup); ret = wm8750_add_i2c_device(pdev, setup);
} }
#endif #endif
#if defined(CONFIG_SPI_MASTER) #if defined(CONFIG_SPI_MASTER)
if (setup->spi) { if (setup->spi) {
codec->hw_write = (hw_write_t)wm8750_spi_write;
ret = spi_register_driver(&wm8750_spi_driver); ret = spi_register_driver(&wm8750_spi_driver);
if (ret != 0) if (ret != 0)
printk(KERN_ERR "can't add spi driver"); printk(KERN_ERR "can't add spi driver");
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -59,44 +59,7 @@ static const u16 wm8971_reg[] = { ...@@ -59,44 +59,7 @@ static const u16 wm8971_reg[] = {
0x0079, 0x0079, 0x0079, /* 40 */ 0x0079, 0x0079, 0x0079, /* 40 */
}; };
static inline unsigned int wm8971_read_reg_cache(struct snd_soc_codec *codec, #define wm8971_reset(c) snd_soc_write(c, WM8971_RESET, 0)
unsigned int reg)
{
u16 *cache = codec->reg_cache;
if (reg < WM8971_REG_COUNT)
return cache[reg];
return -1;
}
static inline void wm8971_write_reg_cache(struct snd_soc_codec *codec,
unsigned int reg, unsigned int value)
{
u16 *cache = codec->reg_cache;
if (reg < WM8971_REG_COUNT)
cache[reg] = value;
}
static int wm8971_write(struct snd_soc_codec *codec, unsigned int reg,
unsigned int value)
{
u8 data[2];
/* data is
* D15..D9 WM8753 register offset
* D8...D0 register data
*/
data[0] = (reg << 1) | ((value >> 8) & 0x0001);
data[1] = value & 0x00ff;
wm8971_write_reg_cache (codec, reg, value);
if (codec->hw_write(codec->control_data, data, 2) == 2)
return 0;
else
return -EIO;
}
#define wm8971_reset(c) wm8971_write(c, WM8971_RESET, 0)
/* WM8971 Controls */ /* WM8971 Controls */
static const char *wm8971_bass[] = { "Linear Control", "Adaptive Boost" }; static const char *wm8971_bass[] = { "Linear Control", "Adaptive Boost" };
...@@ -521,7 +484,7 @@ static int wm8971_set_dai_fmt(struct snd_soc_dai *codec_dai, ...@@ -521,7 +484,7 @@ static int wm8971_set_dai_fmt(struct snd_soc_dai *codec_dai,
return -EINVAL; return -EINVAL;
} }
wm8971_write(codec, WM8971_IFACE, iface); snd_soc_write(codec, WM8971_IFACE, iface);
return 0; return 0;
} }
...@@ -533,8 +496,8 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream, ...@@ -533,8 +496,8 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->card->codec; struct snd_soc_codec *codec = socdev->card->codec;
struct wm8971_priv *wm8971 = codec->private_data; struct wm8971_priv *wm8971 = codec->private_data;
u16 iface = wm8971_read_reg_cache(codec, WM8971_IFACE) & 0x1f3; u16 iface = snd_soc_read(codec, WM8971_IFACE) & 0x1f3;
u16 srate = wm8971_read_reg_cache(codec, WM8971_SRATE) & 0x1c0; u16 srate = snd_soc_read(codec, WM8971_SRATE) & 0x1c0;
int coeff = get_coeff(wm8971->sysclk, params_rate(params)); int coeff = get_coeff(wm8971->sysclk, params_rate(params));
/* bit size */ /* bit size */
...@@ -553,9 +516,9 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream, ...@@ -553,9 +516,9 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream,
} }
/* set iface & srate */ /* set iface & srate */
wm8971_write(codec, WM8971_IFACE, iface); snd_soc_write(codec, WM8971_IFACE, iface);
if (coeff >= 0) if (coeff >= 0)
wm8971_write(codec, WM8971_SRATE, srate | snd_soc_write(codec, WM8971_SRATE, srate |
(coeff_div[coeff].sr << 1) | coeff_div[coeff].usb); (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb);
return 0; return 0;
...@@ -564,33 +527,33 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream, ...@@ -564,33 +527,33 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream,
static int wm8971_mute(struct snd_soc_dai *dai, int mute) static int wm8971_mute(struct snd_soc_dai *dai, int mute)
{ {
struct snd_soc_codec *codec = dai->codec; struct snd_soc_codec *codec = dai->codec;
u16 mute_reg = wm8971_read_reg_cache(codec, WM8971_ADCDAC) & 0xfff7; u16 mute_reg = snd_soc_read(codec, WM8971_ADCDAC) & 0xfff7;
if (mute) if (mute)
wm8971_write(codec, WM8971_ADCDAC, mute_reg | 0x8); snd_soc_write(codec, WM8971_ADCDAC, mute_reg | 0x8);
else else
wm8971_write(codec, WM8971_ADCDAC, mute_reg); snd_soc_write(codec, WM8971_ADCDAC, mute_reg);
return 0; return 0;
} }
static int wm8971_set_bias_level(struct snd_soc_codec *codec, static int wm8971_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level) enum snd_soc_bias_level level)
{ {
u16 pwr_reg = wm8971_read_reg_cache(codec, WM8971_PWR1) & 0xfe3e; u16 pwr_reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e;
switch (level) { switch (level) {
case SND_SOC_BIAS_ON: case SND_SOC_BIAS_ON:
/* set vmid to 50k and unmute dac */ /* set vmid to 50k and unmute dac */
wm8971_write(codec, WM8971_PWR1, pwr_reg | 0x00c1); snd_soc_write(codec, WM8971_PWR1, pwr_reg | 0x00c1);
break; break;
case SND_SOC_BIAS_PREPARE: case SND_SOC_BIAS_PREPARE:
break; break;
case SND_SOC_BIAS_STANDBY: case SND_SOC_BIAS_STANDBY:
/* mute dac and set vmid to 500k, enable VREF */ /* mute dac and set vmid to 500k, enable VREF */
wm8971_write(codec, WM8971_PWR1, pwr_reg | 0x0140); snd_soc_write(codec, WM8971_PWR1, pwr_reg | 0x0140);
break; break;
case SND_SOC_BIAS_OFF: case SND_SOC_BIAS_OFF:
wm8971_write(codec, WM8971_PWR1, 0x0001); snd_soc_write(codec, WM8971_PWR1, 0x0001);
break; break;
} }
codec->bias_level = level; codec->bias_level = level;
...@@ -667,8 +630,8 @@ static int wm8971_resume(struct platform_device *pdev) ...@@ -667,8 +630,8 @@ static int wm8971_resume(struct platform_device *pdev)
/* charge wm8971 caps */ /* charge wm8971 caps */
if (codec->suspend_bias_level == SND_SOC_BIAS_ON) { if (codec->suspend_bias_level == SND_SOC_BIAS_ON) {
reg = wm8971_read_reg_cache(codec, WM8971_PWR1) & 0xfe3e; reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e;
wm8971_write(codec, WM8971_PWR1, reg | 0x01c0); snd_soc_write(codec, WM8971_PWR1, reg | 0x01c0);
codec->bias_level = SND_SOC_BIAS_ON; codec->bias_level = SND_SOC_BIAS_ON;
queue_delayed_work(wm8971_workq, &codec->delayed_work, queue_delayed_work(wm8971_workq, &codec->delayed_work,
msecs_to_jiffies(1000)); msecs_to_jiffies(1000));
...@@ -677,15 +640,14 @@ static int wm8971_resume(struct platform_device *pdev) ...@@ -677,15 +640,14 @@ static int wm8971_resume(struct platform_device *pdev)
return 0; return 0;
} }
static int wm8971_init(struct snd_soc_device *socdev) static int wm8971_init(struct snd_soc_device *socdev,
enum snd_soc_control_type control)
{ {
struct snd_soc_codec *codec = socdev->card->codec; struct snd_soc_codec *codec = socdev->card->codec;
int reg, ret = 0; int reg, ret = 0;
codec->name = "WM8971"; codec->name = "WM8971";
codec->owner = THIS_MODULE; codec->owner = THIS_MODULE;
codec->read = wm8971_read_reg_cache;
codec->write = wm8971_write;
codec->set_bias_level = wm8971_set_bias_level; codec->set_bias_level = wm8971_set_bias_level;
codec->dai = &wm8971_dai; codec->dai = &wm8971_dai;
codec->reg_cache_size = ARRAY_SIZE(wm8971_reg); codec->reg_cache_size = ARRAY_SIZE(wm8971_reg);
...@@ -695,42 +657,48 @@ static int wm8971_init(struct snd_soc_device *socdev) ...@@ -695,42 +657,48 @@ static int wm8971_init(struct snd_soc_device *socdev)
if (codec->reg_cache == NULL) if (codec->reg_cache == NULL)
return -ENOMEM; return -ENOMEM;
ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
if (ret < 0) {
printk(KERN_ERR "wm8971: failed to set cache I/O: %d\n", ret);
goto err;
}
wm8971_reset(codec); wm8971_reset(codec);
/* register pcms */ /* register pcms */
ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
if (ret < 0) { if (ret < 0) {
printk(KERN_ERR "wm8971: failed to create pcms\n"); printk(KERN_ERR "wm8971: failed to create pcms\n");
goto pcm_err; goto err;
} }
/* charge output caps - set vmid to 5k for quick power up */ /* charge output caps - set vmid to 5k for quick power up */
reg = wm8971_read_reg_cache(codec, WM8971_PWR1) & 0xfe3e; reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e;
wm8971_write(codec, WM8971_PWR1, reg | 0x01c0); snd_soc_write(codec, WM8971_PWR1, reg | 0x01c0);
codec->bias_level = SND_SOC_BIAS_STANDBY; codec->bias_level = SND_SOC_BIAS_STANDBY;
queue_delayed_work(wm8971_workq, &codec->delayed_work, queue_delayed_work(wm8971_workq, &codec->delayed_work,
msecs_to_jiffies(1000)); msecs_to_jiffies(1000));
/* set the update bits */ /* set the update bits */
reg = wm8971_read_reg_cache(codec, WM8971_LDAC); reg = snd_soc_read(codec, WM8971_LDAC);
wm8971_write(codec, WM8971_LDAC, reg | 0x0100); snd_soc_write(codec, WM8971_LDAC, reg | 0x0100);
reg = wm8971_read_reg_cache(codec, WM8971_RDAC); reg = snd_soc_read(codec, WM8971_RDAC);
wm8971_write(codec, WM8971_RDAC, reg | 0x0100); snd_soc_write(codec, WM8971_RDAC, reg | 0x0100);
reg = wm8971_read_reg_cache(codec, WM8971_LOUT1V); reg = snd_soc_read(codec, WM8971_LOUT1V);
wm8971_write(codec, WM8971_LOUT1V, reg | 0x0100); snd_soc_write(codec, WM8971_LOUT1V, reg | 0x0100);
reg = wm8971_read_reg_cache(codec, WM8971_ROUT1V); reg = snd_soc_read(codec, WM8971_ROUT1V);
wm8971_write(codec, WM8971_ROUT1V, reg | 0x0100); snd_soc_write(codec, WM8971_ROUT1V, reg | 0x0100);
reg = wm8971_read_reg_cache(codec, WM8971_LOUT2V); reg = snd_soc_read(codec, WM8971_LOUT2V);
wm8971_write(codec, WM8971_LOUT2V, reg | 0x0100); snd_soc_write(codec, WM8971_LOUT2V, reg | 0x0100);
reg = wm8971_read_reg_cache(codec, WM8971_ROUT2V); reg = snd_soc_read(codec, WM8971_ROUT2V);
wm8971_write(codec, WM8971_ROUT2V, reg | 0x0100); snd_soc_write(codec, WM8971_ROUT2V, reg | 0x0100);
reg = wm8971_read_reg_cache(codec, WM8971_LINVOL); reg = snd_soc_read(codec, WM8971_LINVOL);
wm8971_write(codec, WM8971_LINVOL, reg | 0x0100); snd_soc_write(codec, WM8971_LINVOL, reg | 0x0100);
reg = wm8971_read_reg_cache(codec, WM8971_RINVOL); reg = snd_soc_read(codec, WM8971_RINVOL);
wm8971_write(codec, WM8971_RINVOL, reg | 0x0100); snd_soc_write(codec, WM8971_RINVOL, reg | 0x0100);
snd_soc_add_controls(codec, wm8971_snd_controls, snd_soc_add_controls(codec, wm8971_snd_controls,
ARRAY_SIZE(wm8971_snd_controls)); ARRAY_SIZE(wm8971_snd_controls));
...@@ -745,7 +713,7 @@ static int wm8971_init(struct snd_soc_device *socdev) ...@@ -745,7 +713,7 @@ static int wm8971_init(struct snd_soc_device *socdev)
card_err: card_err:
snd_soc_free_pcms(socdev); snd_soc_free_pcms(socdev);
snd_soc_dapm_free(socdev); snd_soc_dapm_free(socdev);
pcm_err: err:
kfree(codec->reg_cache); kfree(codec->reg_cache);
return ret; return ret;
} }
...@@ -767,7 +735,7 @@ static int wm8971_i2c_probe(struct i2c_client *i2c, ...@@ -767,7 +735,7 @@ static int wm8971_i2c_probe(struct i2c_client *i2c,
codec->control_data = i2c; codec->control_data = i2c;
ret = wm8971_init(socdev); ret = wm8971_init(socdev, SND_SOC_I2C);
if (ret < 0) if (ret < 0)
pr_err("failed to initialise WM8971\n"); pr_err("failed to initialise WM8971\n");
...@@ -877,7 +845,6 @@ static int wm8971_probe(struct platform_device *pdev) ...@@ -877,7 +845,6 @@ static int wm8971_probe(struct platform_device *pdev)
#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE) #if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
if (setup->i2c_address) { if (setup->i2c_address) {
codec->hw_write = (hw_write_t)i2c_master_send;
ret = wm8971_add_i2c_device(pdev, setup); ret = wm8971_add_i2c_device(pdev, setup);
} }
#endif #endif
......
...@@ -57,50 +57,7 @@ struct wm8988_priv { ...@@ -57,50 +57,7 @@ struct wm8988_priv {
}; };
/* #define wm8988_reset(c) snd_soc_write(c, WM8988_RESET, 0)
* read wm8988 register cache
*/
static inline unsigned int wm8988_read_reg_cache(struct snd_soc_codec *codec,
unsigned int reg)
{
u16 *cache = codec->reg_cache;
if (reg > WM8988_NUM_REG)
return -1;
return cache[reg];
}
/*
* write wm8988 register cache
*/
static inline void wm8988_write_reg_cache(struct snd_soc_codec *codec,
unsigned int reg, unsigned int value)
{
u16 *cache = codec->reg_cache;
if (reg > WM8988_NUM_REG)
return;
cache[reg] = value;
}
static int wm8988_write(struct snd_soc_codec *codec, unsigned int reg,
unsigned int value)
{
u8 data[2];
/* data is
* D15..D9 WM8753 register offset
* D8...D0 register data
*/
data[0] = (reg << 1) | ((value >> 8) & 0x0001);
data[1] = value & 0x00ff;
wm8988_write_reg_cache(codec, reg, value);
if (codec->hw_write(codec->control_data, data, 2) == 2)
return 0;
else
return -EIO;
}
#define wm8988_reset(c) wm8988_write(c, WM8988_RESET, 0)
/* /*
* WM8988 Controls * WM8988 Controls
...@@ -226,15 +183,15 @@ static int wm8988_lrc_control(struct snd_soc_dapm_widget *w, ...@@ -226,15 +183,15 @@ static int wm8988_lrc_control(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event) struct snd_kcontrol *kcontrol, int event)
{ {
struct snd_soc_codec *codec = w->codec; struct snd_soc_codec *codec = w->codec;
u16 adctl2 = wm8988_read_reg_cache(codec, WM8988_ADCTL2); u16 adctl2 = snd_soc_read(codec, WM8988_ADCTL2);
/* Use the DAC to gate LRC if active, otherwise use ADC */ /* Use the DAC to gate LRC if active, otherwise use ADC */
if (wm8988_read_reg_cache(codec, WM8988_PWR2) & 0x180) if (snd_soc_read(codec, WM8988_PWR2) & 0x180)
adctl2 &= ~0x4; adctl2 &= ~0x4;
else else
adctl2 |= 0x4; adctl2 |= 0x4;
return wm8988_write(codec, WM8988_ADCTL2, adctl2); return snd_soc_write(codec, WM8988_ADCTL2, adctl2);
} }
static const char *wm8988_line_texts[] = { static const char *wm8988_line_texts[] = {
...@@ -619,7 +576,7 @@ static int wm8988_set_dai_fmt(struct snd_soc_dai *codec_dai, ...@@ -619,7 +576,7 @@ static int wm8988_set_dai_fmt(struct snd_soc_dai *codec_dai,
return -EINVAL; return -EINVAL;
} }
wm8988_write(codec, WM8988_IFACE, iface); snd_soc_write(codec, WM8988_IFACE, iface);
return 0; return 0;
} }
...@@ -653,8 +610,8 @@ static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream, ...@@ -653,8 +610,8 @@ static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->card->codec; struct snd_soc_codec *codec = socdev->card->codec;
struct wm8988_priv *wm8988 = codec->private_data; struct wm8988_priv *wm8988 = codec->private_data;
u16 iface = wm8988_read_reg_cache(codec, WM8988_IFACE) & 0x1f3; u16 iface = snd_soc_read(codec, WM8988_IFACE) & 0x1f3;
u16 srate = wm8988_read_reg_cache(codec, WM8988_SRATE) & 0x180; u16 srate = snd_soc_read(codec, WM8988_SRATE) & 0x180;
int coeff; int coeff;
coeff = get_coeff(wm8988->sysclk, params_rate(params)); coeff = get_coeff(wm8988->sysclk, params_rate(params));
...@@ -685,9 +642,9 @@ static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream, ...@@ -685,9 +642,9 @@ static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream,
} }
/* set iface & srate */ /* set iface & srate */
wm8988_write(codec, WM8988_IFACE, iface); snd_soc_write(codec, WM8988_IFACE, iface);
if (coeff >= 0) if (coeff >= 0)
wm8988_write(codec, WM8988_SRATE, srate | snd_soc_write(codec, WM8988_SRATE, srate |
(coeff_div[coeff].sr << 1) | coeff_div[coeff].usb); (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb);
return 0; return 0;
...@@ -696,19 +653,19 @@ static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream, ...@@ -696,19 +653,19 @@ static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream,
static int wm8988_mute(struct snd_soc_dai *dai, int mute) static int wm8988_mute(struct snd_soc_dai *dai, int mute)
{ {
struct snd_soc_codec *codec = dai->codec; struct snd_soc_codec *codec = dai->codec;
u16 mute_reg = wm8988_read_reg_cache(codec, WM8988_ADCDAC) & 0xfff7; u16 mute_reg = snd_soc_read(codec, WM8988_ADCDAC) & 0xfff7;
if (mute) if (mute)
wm8988_write(codec, WM8988_ADCDAC, mute_reg | 0x8); snd_soc_write(codec, WM8988_ADCDAC, mute_reg | 0x8);
else else
wm8988_write(codec, WM8988_ADCDAC, mute_reg); snd_soc_write(codec, WM8988_ADCDAC, mute_reg);
return 0; return 0;
} }
static int wm8988_set_bias_level(struct snd_soc_codec *codec, static int wm8988_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level) enum snd_soc_bias_level level)
{ {
u16 pwr_reg = wm8988_read_reg_cache(codec, WM8988_PWR1) & ~0x1c1; u16 pwr_reg = snd_soc_read(codec, WM8988_PWR1) & ~0x1c1;
switch (level) { switch (level) {
case SND_SOC_BIAS_ON: case SND_SOC_BIAS_ON:
...@@ -716,24 +673,24 @@ static int wm8988_set_bias_level(struct snd_soc_codec *codec, ...@@ -716,24 +673,24 @@ static int wm8988_set_bias_level(struct snd_soc_codec *codec,
case SND_SOC_BIAS_PREPARE: case SND_SOC_BIAS_PREPARE:
/* VREF, VMID=2x50k, digital enabled */ /* VREF, VMID=2x50k, digital enabled */
wm8988_write(codec, WM8988_PWR1, pwr_reg | 0x00c0); snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x00c0);
break; break;
case SND_SOC_BIAS_STANDBY: case SND_SOC_BIAS_STANDBY:
if (codec->bias_level == SND_SOC_BIAS_OFF) { if (codec->bias_level == SND_SOC_BIAS_OFF) {
/* VREF, VMID=2x5k */ /* VREF, VMID=2x5k */
wm8988_write(codec, WM8988_PWR1, pwr_reg | 0x1c1); snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x1c1);
/* Charge caps */ /* Charge caps */
msleep(100); msleep(100);
} }
/* VREF, VMID=2*500k, digital stopped */ /* VREF, VMID=2*500k, digital stopped */
wm8988_write(codec, WM8988_PWR1, pwr_reg | 0x0141); snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x0141);
break; break;
case SND_SOC_BIAS_OFF: case SND_SOC_BIAS_OFF:
wm8988_write(codec, WM8988_PWR1, 0x0000); snd_soc_write(codec, WM8988_PWR1, 0x0000);
break; break;
} }
codec->bias_level = level; codec->bias_level = level;
...@@ -868,7 +825,8 @@ struct snd_soc_codec_device soc_codec_dev_wm8988 = { ...@@ -868,7 +825,8 @@ struct snd_soc_codec_device soc_codec_dev_wm8988 = {
}; };
EXPORT_SYMBOL_GPL(soc_codec_dev_wm8988); EXPORT_SYMBOL_GPL(soc_codec_dev_wm8988);
static int wm8988_register(struct wm8988_priv *wm8988) static int wm8988_register(struct wm8988_priv *wm8988,
enum snd_soc_control_type control)
{ {
struct snd_soc_codec *codec = &wm8988->codec; struct snd_soc_codec *codec = &wm8988->codec;
int ret; int ret;
...@@ -887,8 +845,6 @@ static int wm8988_register(struct wm8988_priv *wm8988) ...@@ -887,8 +845,6 @@ static int wm8988_register(struct wm8988_priv *wm8988)
codec->private_data = wm8988; codec->private_data = wm8988;
codec->name = "WM8988"; codec->name = "WM8988";
codec->owner = THIS_MODULE; codec->owner = THIS_MODULE;
codec->read = wm8988_read_reg_cache;
codec->write = wm8988_write;
codec->dai = &wm8988_dai; codec->dai = &wm8988_dai;
codec->num_dai = 1; codec->num_dai = 1;
codec->reg_cache_size = ARRAY_SIZE(wm8988->reg_cache); codec->reg_cache_size = ARRAY_SIZE(wm8988->reg_cache);
...@@ -899,6 +855,12 @@ static int wm8988_register(struct wm8988_priv *wm8988) ...@@ -899,6 +855,12 @@ static int wm8988_register(struct wm8988_priv *wm8988)
memcpy(codec->reg_cache, wm8988_reg, memcpy(codec->reg_cache, wm8988_reg,
sizeof(wm8988_reg)); sizeof(wm8988_reg));
ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
goto err;
}
ret = wm8988_reset(codec); ret = wm8988_reset(codec);
if (ret < 0) { if (ret < 0) {
dev_err(codec->dev, "Failed to issue reset\n"); dev_err(codec->dev, "Failed to issue reset\n");
...@@ -906,16 +868,16 @@ static int wm8988_register(struct wm8988_priv *wm8988) ...@@ -906,16 +868,16 @@ static int wm8988_register(struct wm8988_priv *wm8988)
} }
/* set the update bits (we always update left then right) */ /* set the update bits (we always update left then right) */
reg = wm8988_read_reg_cache(codec, WM8988_RADC); reg = snd_soc_read(codec, WM8988_RADC);
wm8988_write(codec, WM8988_RADC, reg | 0x100); snd_soc_write(codec, WM8988_RADC, reg | 0x100);
reg = wm8988_read_reg_cache(codec, WM8988_RDAC); reg = snd_soc_read(codec, WM8988_RDAC);
wm8988_write(codec, WM8988_RDAC, reg | 0x0100); snd_soc_write(codec, WM8988_RDAC, reg | 0x0100);
reg = wm8988_read_reg_cache(codec, WM8988_ROUT1V); reg = snd_soc_read(codec, WM8988_ROUT1V);
wm8988_write(codec, WM8988_ROUT1V, reg | 0x0100); snd_soc_write(codec, WM8988_ROUT1V, reg | 0x0100);
reg = wm8988_read_reg_cache(codec, WM8988_ROUT2V); reg = snd_soc_read(codec, WM8988_ROUT2V);
wm8988_write(codec, WM8988_ROUT2V, reg | 0x0100); snd_soc_write(codec, WM8988_ROUT2V, reg | 0x0100);
reg = wm8988_read_reg_cache(codec, WM8988_RINVOL); reg = snd_soc_read(codec, WM8988_RINVOL);
wm8988_write(codec, WM8988_RINVOL, reg | 0x0100); snd_soc_write(codec, WM8988_RINVOL, reg | 0x0100);
wm8988_set_bias_level(&wm8988->codec, SND_SOC_BIAS_STANDBY); wm8988_set_bias_level(&wm8988->codec, SND_SOC_BIAS_STANDBY);
...@@ -966,14 +928,13 @@ static int wm8988_i2c_probe(struct i2c_client *i2c, ...@@ -966,14 +928,13 @@ static int wm8988_i2c_probe(struct i2c_client *i2c,
return -ENOMEM; return -ENOMEM;
codec = &wm8988->codec; codec = &wm8988->codec;
codec->hw_write = (hw_write_t)i2c_master_send;
i2c_set_clientdata(i2c, wm8988); i2c_set_clientdata(i2c, wm8988);
codec->control_data = i2c; codec->control_data = i2c;
codec->dev = &i2c->dev; codec->dev = &i2c->dev;
return wm8988_register(wm8988); return wm8988_register(wm8988, SND_SOC_I2C);
} }
static int wm8988_i2c_remove(struct i2c_client *client) static int wm8988_i2c_remove(struct i2c_client *client)
...@@ -1018,30 +979,6 @@ static struct i2c_driver wm8988_i2c_driver = { ...@@ -1018,30 +979,6 @@ static struct i2c_driver wm8988_i2c_driver = {
#endif #endif
#if defined(CONFIG_SPI_MASTER) #if defined(CONFIG_SPI_MASTER)
static int wm8988_spi_write(struct spi_device *spi, const char *data, int len)
{
struct spi_transfer t;
struct spi_message m;
u8 msg[2];
if (len <= 0)
return 0;
msg[0] = data[0];
msg[1] = data[1];
spi_message_init(&m);
memset(&t, 0, (sizeof t));
t.tx_buf = &msg[0];
t.len = len;
spi_message_add_tail(&t, &m);
spi_sync(spi, &m);
return len;
}
static int __devinit wm8988_spi_probe(struct spi_device *spi) static int __devinit wm8988_spi_probe(struct spi_device *spi)
{ {
struct wm8988_priv *wm8988; struct wm8988_priv *wm8988;
...@@ -1052,13 +989,12 @@ static int __devinit wm8988_spi_probe(struct spi_device *spi) ...@@ -1052,13 +989,12 @@ static int __devinit wm8988_spi_probe(struct spi_device *spi)
return -ENOMEM; return -ENOMEM;
codec = &wm8988->codec; codec = &wm8988->codec;
codec->hw_write = (hw_write_t)wm8988_spi_write;
codec->control_data = spi; codec->control_data = spi;
codec->dev = &spi->dev; codec->dev = &spi->dev;
spi->dev.driver_data = wm8988; spi->dev.driver_data = wm8988;
return wm8988_register(wm8988); return wm8988_register(wm8988, SND_SOC_SPI);
} }
static int __devexit wm8988_spi_remove(struct spi_device *spi) static int __devexit wm8988_spi_remove(struct spi_device *spi)
......
This diff is collapsed.
This diff is collapsed.
/*
* soc-cache.c -- ASoC register cache helpers
*
* Copyright 2009 Wolfson Microelectronics PLC.
*
* Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#include <linux/i2c.h>
#include <linux/spi/spi.h>
#include <sound/soc.h>
static unsigned int snd_soc_7_9_read(struct snd_soc_codec *codec,
unsigned int reg)
{
u16 *cache = codec->reg_cache;
if (reg >= codec->reg_cache_size)
return -1;
return cache[reg];
}
static int snd_soc_7_9_write(struct snd_soc_codec *codec, unsigned int reg,
unsigned int value)
{
u16 *cache = codec->reg_cache;
u8 data[2];
int ret;
BUG_ON(codec->volatile_register);
data[0] = (reg << 1) | ((value >> 8) & 0x0001);
data[1] = value & 0x00ff;
if (reg < codec->reg_cache_size)
cache[reg] = value;
ret = codec->hw_write(codec->control_data, data, 2);
if (ret == 2)
return 0;
if (ret < 0)
return ret;
else
return -EIO;
}
#if defined(CONFIG_SPI_MASTER)
static int snd_soc_7_9_spi_write(void *control_data, const char *data,
int len)
{
struct spi_device *spi = control_data;
struct spi_transfer t;
struct spi_message m;
u8 msg[2];
if (len <= 0)
return 0;
msg[0] = data[0];
msg[1] = data[1];
spi_message_init(&m);
memset(&t, 0, (sizeof t));
t.tx_buf = &msg[0];
t.len = len;
spi_message_add_tail(&t, &m);
spi_sync(spi, &m);
return len;
}
#else
#define snd_soc_7_9_spi_write NULL
#endif
static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg,
unsigned int value)
{
u16 *reg_cache = codec->reg_cache;
u8 data[3];
data[0] = reg;
data[1] = (value >> 8) & 0xff;
data[2] = value & 0xff;
if (!snd_soc_codec_volatile_register(codec, reg))
reg_cache[reg] = value;
if (codec->hw_write(codec->control_data, data, 3) == 3)
return 0;
else
return -EIO;
}
static unsigned int snd_soc_8_16_read(struct snd_soc_codec *codec,
unsigned int reg)
{
u16 *cache = codec->reg_cache;
if (reg >= codec->reg_cache_size ||
snd_soc_codec_volatile_register(codec, reg))
return codec->hw_read(codec, reg);
else
return cache[reg];
}
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static unsigned int snd_soc_8_16_read_i2c(struct snd_soc_codec *codec,
unsigned int r)
{
struct i2c_msg xfer[2];
u8 reg = r;
u16 data;
int ret;
struct i2c_client *client = codec->control_data;
/* Write register */
xfer[0].addr = client->addr;
xfer[0].flags = 0;
xfer[0].len = 1;
xfer[0].buf = &reg;
/* Read data */
xfer[1].addr = client->addr;
xfer[1].flags = I2C_M_RD;
xfer[1].len = 2;
xfer[1].buf = (u8 *)&data;
ret = i2c_transfer(client->adapter, xfer, 2);
if (ret != 2) {
dev_err(&client->dev, "i2c_transfer() returned %d\n", ret);
return 0;
}
return (data >> 8) | ((data & 0xff) << 8);
}
#else
#define snd_soc_8_16_read_i2c NULL
#endif
static struct {
int addr_bits;
int data_bits;
int (*write)(struct snd_soc_codec *codec, unsigned int, unsigned int);
int (*spi_write)(void *, const char *, int);
unsigned int (*read)(struct snd_soc_codec *, unsigned int);
unsigned int (*i2c_read)(struct snd_soc_codec *, unsigned int);
} io_types[] = {
{ 7, 9, snd_soc_7_9_write, snd_soc_7_9_spi_write, snd_soc_7_9_read },
{ 8, 16, snd_soc_8_16_write, NULL, snd_soc_8_16_read,
snd_soc_8_16_read_i2c },
};
/**
* snd_soc_codec_set_cache_io: Set up standard I/O functions.
*
* @codec: CODEC to configure.
* @type: Type of cache.
* @addr_bits: Number of bits of register address data.
* @data_bits: Number of bits of data per register.
* @control: Control bus used.
*
* Register formats are frequently shared between many I2C and SPI
* devices. In order to promote code reuse the ASoC core provides
* some standard implementations of CODEC read and write operations
* which can be set up using this function.
*
* The caller is responsible for allocating and initialising the
* actual cache.
*
* Note that at present this code cannot be used by CODECs with
* volatile registers.
*/
int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
int addr_bits, int data_bits,
enum snd_soc_control_type control)
{
int i;
for (i = 0; i < ARRAY_SIZE(io_types); i++)
if (io_types[i].addr_bits == addr_bits &&
io_types[i].data_bits == data_bits)
break;
if (i == ARRAY_SIZE(io_types)) {
printk(KERN_ERR
"No I/O functions for %d bit address %d bit data\n",
addr_bits, data_bits);
return -EINVAL;
}
codec->write = io_types[i].write;
codec->read = io_types[i].read;
switch (control) {
case SND_SOC_CUSTOM:
break;
case SND_SOC_I2C:
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
codec->hw_write = (hw_write_t)i2c_master_send;
#endif
if (io_types[i].i2c_read)
codec->hw_read = io_types[i].i2c_read;
break;
case SND_SOC_SPI:
if (io_types[i].spi_write)
codec->hw_write = io_types[i].spi_write;
break;
}
return 0;
}
EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment