summaryrefslogtreecommitdiff
path: root/sound/soc
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/codecs/ad1836.h2
-rw-r--r--sound/soc/codecs/ak4535.c10
-rw-r--r--sound/soc/codecs/ak4642.c22
-rw-r--r--sound/soc/codecs/sta32x.c63
-rw-r--r--sound/soc/codecs/sta32x.h1
-rw-r--r--sound/soc/codecs/wm8711.c4
-rw-r--r--sound/soc/codecs/wm8731.c1
-rw-r--r--sound/soc/codecs/wm8741.c4
-rw-r--r--sound/soc/codecs/wm8753.c3
-rw-r--r--sound/soc/codecs/wm8904.c2
-rw-r--r--sound/soc/codecs/wm8940.c2
-rw-r--r--sound/soc/codecs/wm8962.c55
-rw-r--r--sound/soc/codecs/wm8994.c6
-rw-r--r--sound/soc/codecs/wm8996.c2
-rw-r--r--sound/soc/fsl/fsl_ssi.c1
15 files changed, 129 insertions, 49 deletions
diff --git a/sound/soc/codecs/ad1836.h b/sound/soc/codecs/ad1836.h
index 444747f0db2..dd7be0dbbc5 100644
--- a/sound/soc/codecs/ad1836.h
+++ b/sound/soc/codecs/ad1836.h
@@ -34,7 +34,7 @@
#define AD1836_ADC_CTRL2 13
#define AD1836_ADC_WORD_LEN_MASK 0x30
-#define AD1836_ADC_WORD_OFFSET 5
+#define AD1836_ADC_WORD_OFFSET 4
#define AD1836_ADC_SERFMT_MASK (7 << 6)
#define AD1836_ADC_SERFMT_PCK256 (0x4 << 6)
#define AD1836_ADC_SERFMT_PCK128 (0x5 << 6)
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c
index e1a214ee757..65abd09e1ca 100644
--- a/sound/soc/codecs/ak4535.c
+++ b/sound/soc/codecs/ak4535.c
@@ -40,11 +40,11 @@ struct ak4535_priv {
/*
* ak4535 register cache
*/
-static const u16 ak4535_reg[AK4535_CACHEREGNUM] = {
- 0x0000, 0x0080, 0x0000, 0x0003,
- 0x0002, 0x0000, 0x0011, 0x0001,
- 0x0000, 0x0040, 0x0036, 0x0010,
- 0x0000, 0x0000, 0x0057, 0x0000,
+static const u8 ak4535_reg[AK4535_CACHEREGNUM] = {
+ 0x00, 0x80, 0x00, 0x03,
+ 0x02, 0x00, 0x11, 0x01,
+ 0x00, 0x40, 0x36, 0x10,
+ 0x00, 0x00, 0x57, 0x00,
};
/*
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c
index 65f46047b1c..79c1b3d79f1 100644
--- a/sound/soc/codecs/ak4642.c
+++ b/sound/soc/codecs/ak4642.c
@@ -162,17 +162,17 @@ struct ak4642_priv {
/*
* ak4642 register cache
*/
-static const u16 ak4642_reg[AK4642_CACHEREGNUM] = {
- 0x0000, 0x0000, 0x0001, 0x0000,
- 0x0002, 0x0000, 0x0000, 0x0000,
- 0x00e1, 0x00e1, 0x0018, 0x0000,
- 0x00e1, 0x0018, 0x0011, 0x0008,
- 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000,
+static const u8 ak4642_reg[AK4642_CACHEREGNUM] = {
+ 0x00, 0x00, 0x01, 0x00,
+ 0x02, 0x00, 0x00, 0x00,
+ 0xe1, 0xe1, 0x18, 0x00,
+ 0xe1, 0x18, 0x11, 0x08,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00,
};
/*
diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c
index fbd7eb9e61c..d5630aff6a0 100644
--- a/sound/soc/codecs/sta32x.c
+++ b/sound/soc/codecs/sta32x.c
@@ -76,6 +76,8 @@ struct sta32x_priv {
unsigned int mclk;
unsigned int format;
+
+ u32 coef_shadow[STA32X_COEF_COUNT];
};
static const DECLARE_TLV_DB_SCALE(mvol_tlv, -12700, 50, 1);
@@ -227,6 +229,7 @@ static int sta32x_coefficient_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
int numcoef = kcontrol->private_value >> 16;
int index = kcontrol->private_value & 0xffff;
unsigned int cfud;
@@ -239,6 +242,11 @@ static int sta32x_coefficient_put(struct snd_kcontrol *kcontrol,
snd_soc_write(codec, STA32X_CFUD, cfud);
snd_soc_write(codec, STA32X_CFADDR2, index);
+ for (i = 0; i < numcoef && (index + i < STA32X_COEF_COUNT); i++)
+ sta32x->coef_shadow[index + i] =
+ (ucontrol->value.bytes.data[3 * i] << 16)
+ | (ucontrol->value.bytes.data[3 * i + 1] << 8)
+ | (ucontrol->value.bytes.data[3 * i + 2]);
for (i = 0; i < 3 * numcoef; i++)
snd_soc_write(codec, STA32X_B1CF1 + i,
ucontrol->value.bytes.data[i]);
@@ -252,6 +260,48 @@ static int sta32x_coefficient_put(struct snd_kcontrol *kcontrol,
return 0;
}
+int sta32x_sync_coef_shadow(struct snd_soc_codec *codec)
+{
+ struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
+ unsigned int cfud;
+ int i;
+
+ /* preserve reserved bits in STA32X_CFUD */
+ cfud = snd_soc_read(codec, STA32X_CFUD) & 0xf0;
+
+ for (i = 0; i < STA32X_COEF_COUNT; i++) {
+ snd_soc_write(codec, STA32X_CFADDR2, i);
+ snd_soc_write(codec, STA32X_B1CF1,
+ (sta32x->coef_shadow[i] >> 16) & 0xff);
+ snd_soc_write(codec, STA32X_B1CF2,
+ (sta32x->coef_shadow[i] >> 8) & 0xff);
+ snd_soc_write(codec, STA32X_B1CF3,
+ (sta32x->coef_shadow[i]) & 0xff);
+ /* chip documentation does not say if the bits are
+ * self-clearing, so do it explicitly */
+ snd_soc_write(codec, STA32X_CFUD, cfud);
+ snd_soc_write(codec, STA32X_CFUD, cfud | 0x01);
+ }
+ return 0;
+}
+
+int sta32x_cache_sync(struct snd_soc_codec *codec)
+{
+ unsigned int mute;
+ int rc;
+
+ if (!codec->cache_sync)
+ return 0;
+
+ /* mute during register sync */
+ mute = snd_soc_read(codec, STA32X_MMUTE);
+ snd_soc_write(codec, STA32X_MMUTE, mute | STA32X_MMUTE_MMUTE);
+ sta32x_sync_coef_shadow(codec);
+ rc = snd_soc_cache_sync(codec);
+ snd_soc_write(codec, STA32X_MMUTE, mute);
+ return rc;
+}
+
#define SINGLE_COEF(xname, index) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = sta32x_coefficient_info, \
@@ -657,7 +707,7 @@ static int sta32x_set_bias_level(struct snd_soc_codec *codec,
return ret;
}
- snd_soc_cache_sync(codec);
+ sta32x_cache_sync(codec);
}
/* Power up to mute */
@@ -792,6 +842,17 @@ static int sta32x_probe(struct snd_soc_codec *codec)
STA32X_CxCFG_OM_MASK,
2 << STA32X_CxCFG_OM_SHIFT);
+ /* initialize coefficient shadow RAM with reset values */
+ for (i = 4; i <= 49; i += 5)
+ sta32x->coef_shadow[i] = 0x400000;
+ for (i = 50; i <= 54; i++)
+ sta32x->coef_shadow[i] = 0x7fffff;
+ sta32x->coef_shadow[55] = 0x5a9df7;
+ sta32x->coef_shadow[56] = 0x7fffff;
+ sta32x->coef_shadow[59] = 0x7fffff;
+ sta32x->coef_shadow[60] = 0x400000;
+ sta32x->coef_shadow[61] = 0x400000;
+
sta32x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
/* Bias level configuration will have done an extra enable */
regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies);
diff --git a/sound/soc/codecs/sta32x.h b/sound/soc/codecs/sta32x.h
index b97ee5a7566..d8e32a6262e 100644
--- a/sound/soc/codecs/sta32x.h
+++ b/sound/soc/codecs/sta32x.h
@@ -19,6 +19,7 @@
/* STA326 register addresses */
#define STA32X_REGISTER_COUNT 0x2d
+#define STA32X_COEF_COUNT 62
#define STA32X_CONFA 0x00
#define STA32X_CONFB 0x01
diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c
index a537e4af6ae..1dae5c4d993 100644
--- a/sound/soc/codecs/wm8711.c
+++ b/sound/soc/codecs/wm8711.c
@@ -150,7 +150,7 @@ static int wm8711_hw_params(struct snd_pcm_substream *substream,
{
struct snd_soc_codec *codec = dai->codec;
struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec);
- u16 iface = snd_soc_read(codec, WM8711_IFACE) & 0xfffc;
+ u16 iface = snd_soc_read(codec, WM8711_IFACE) & 0xfff3;
int i = get_coeff(wm8711->sysclk, params_rate(params));
u16 srate = (coeff_div[i].sr << 2) |
(coeff_div[i].bosr << 1) | coeff_div[i].usb;
@@ -231,7 +231,7 @@ static int wm8711_set_dai_fmt(struct snd_soc_dai *codec_dai,
unsigned int fmt)
{
struct snd_soc_codec *codec = codec_dai->codec;
- u16 iface = 0;
+ u16 iface = snd_soc_read(codec, WM8711_IFACE) & 0x000c;
/* set master/slave audio interface */
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index 76b4361e9b8..f5a0ec4ade5 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -463,6 +463,7 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec,
snd_soc_write(codec, WM8731_PWR, 0xffff);
regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies),
wm8731->supplies);
+ codec->cache_sync = 1;
break;
}
codec->dapm.bias_level = level;
diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c
index 25af901fe81..c173aee3390 100644
--- a/sound/soc/codecs/wm8741.c
+++ b/sound/soc/codecs/wm8741.c
@@ -337,10 +337,10 @@ static int wm8741_set_dai_fmt(struct snd_soc_dai *codec_dai,
iface |= 0x0004;
break;
case SND_SOC_DAIFMT_DSP_A:
- iface |= 0x0003;
+ iface |= 0x000C;
break;
case SND_SOC_DAIFMT_DSP_B:
- iface |= 0x0013;
+ iface |= 0x001C;
break;
default:
return -EINVAL;
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index aa091a0d818..66d18a3e57f 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -189,6 +189,9 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol,
struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
u16 ioctl;
+ if (wm8753->dai_func == ucontrol->value.integer.value[0])
+ return 0;
+
if (codec->active)
return -EBUSY;
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
index b085575d4aa..cbba0b1d647 100644
--- a/sound/soc/codecs/wm8904.c
+++ b/sound/soc/codecs/wm8904.c
@@ -868,7 +868,7 @@ SOC_ENUM("Right Capture Mode", rin_mode),
SOC_DOUBLE_R("Capture Volume", WM8904_ANALOGUE_LEFT_INPUT_0,
WM8904_ANALOGUE_RIGHT_INPUT_0, 0, 31, 0),
SOC_DOUBLE_R("Capture Switch", WM8904_ANALOGUE_LEFT_INPUT_0,
- WM8904_ANALOGUE_RIGHT_INPUT_0, 7, 1, 0),
+ WM8904_ANALOGUE_RIGHT_INPUT_0, 7, 1, 1),
SOC_SINGLE("High Pass Filter Switch", WM8904_ADC_DIGITAL_0, 4, 1, 0),
SOC_ENUM("High Pass Filter Mode", hpf_mode),
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c
index 056daa0010f..d40da04db37 100644
--- a/sound/soc/codecs/wm8940.c
+++ b/sound/soc/codecs/wm8940.c
@@ -470,6 +470,8 @@ static int wm8940_set_bias_level(struct snd_soc_codec *codec,
break;
}
+ codec->dapm.bias_level = level;
+
return ret;
}
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index d2c315fa1b9..c6106753090 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -1959,7 +1959,13 @@ static int wm8962_readable_register(struct snd_soc_codec *codec, unsigned int re
static int wm8962_reset(struct snd_soc_codec *codec)
{
- return snd_soc_write(codec, WM8962_SOFTWARE_RESET, 0x6243);
+ int ret;
+
+ ret = snd_soc_write(codec, WM8962_SOFTWARE_RESET, 0x6243);
+ if (ret != 0)
+ return ret;
+
+ return snd_soc_write(codec, WM8962_PLL_SOFTWARE_RESET, 0);
}
static const DECLARE_TLV_DB_SCALE(inpga_tlv, -2325, 75, 0);
@@ -2021,7 +2027,6 @@ static int wm8962_put_spk_sw(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
- u16 *reg_cache = codec->reg_cache;
int ret;
/* Apply the update (if any) */
@@ -2030,16 +2035,19 @@ static int wm8962_put_spk_sw(struct snd_kcontrol *kcontrol,
return 0;
/* If the left PGA is enabled hit that VU bit... */
- if (reg_cache[WM8962_PWR_MGMT_2] & WM8962_SPKOUTL_PGA_ENA)
- return snd_soc_write(codec, WM8962_SPKOUTL_VOLUME,
- reg_cache[WM8962_SPKOUTL_VOLUME]);
+ ret = snd_soc_read(codec, WM8962_PWR_MGMT_2);
+ if (ret & WM8962_SPKOUTL_PGA_ENA) {
+ snd_soc_write(codec, WM8962_SPKOUTL_VOLUME,
+ snd_soc_read(codec, WM8962_SPKOUTL_VOLUME));
+ return 1;
+ }
/* ...otherwise the right. The VU is stereo. */
- if (reg_cache[WM8962_PWR_MGMT_2] & WM8962_SPKOUTR_PGA_ENA)
- return snd_soc_write(codec, WM8962_SPKOUTR_VOLUME,
- reg_cache[WM8962_SPKOUTR_VOLUME]);
+ if (ret & WM8962_SPKOUTR_PGA_ENA)
+ snd_soc_write(codec, WM8962_SPKOUTR_VOLUME,
+ snd_soc_read(codec, WM8962_SPKOUTR_VOLUME));
- return 0;
+ return 1;
}
static const char *cap_hpf_mode_text[] = {
@@ -2225,15 +2233,14 @@ static int sysclk_event(struct snd_soc_dapm_widget *w,
snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1,
WM8962_FLL_ENA, WM8962_FLL_ENA);
- if (wm8962->irq) {
- timeout = msecs_to_jiffies(5);
- timeout = wait_for_completion_timeout(&wm8962->fll_lock,
- timeout);
-
- if (timeout == 0)
- dev_err(codec->dev,
- "Timed out starting FLL\n");
- }
+
+ timeout = msecs_to_jiffies(5);
+ timeout = wait_for_completion_timeout(&wm8962->fll_lock,
+ timeout);
+
+ if (wm8962->irq && timeout == 0)
+ dev_err(codec->dev,
+ "Timed out starting FLL\n");
}
break;
@@ -2365,7 +2372,6 @@ static int out_pga_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
- u16 *reg_cache = codec->reg_cache;
int reg;
switch (w->shift) {
@@ -2388,7 +2394,7 @@ static int out_pga_event(struct snd_soc_dapm_widget *w,
switch (event) {
case SND_SOC_DAPM_POST_PMU:
- return snd_soc_write(codec, reg, reg_cache[reg]);
+ return snd_soc_write(codec, reg, snd_soc_read(codec, reg));
default:
BUG();
return -EINVAL;
@@ -3058,9 +3064,9 @@ static int wm8962_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
int aif0 = 0;
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
- case SND_SOC_DAIFMT_DSP_A:
- aif0 |= WM8962_LRCLK_INV;
case SND_SOC_DAIFMT_DSP_B:
+ aif0 |= WM8962_LRCLK_INV | 3;
+ case SND_SOC_DAIFMT_DSP_A:
aif0 |= 3;
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
@@ -3847,6 +3853,11 @@ static int wm8962_probe(struct snd_soc_codec *codec)
snd_soc_update_bits(codec, WM8962_CLOCKING2,
WM8962_CLKREG_OVD, WM8962_CLKREG_OVD);
+ /* Ensure that the oscillator and PLLs are disabled */
+ snd_soc_update_bits(codec, WM8962_PLL2,
+ WM8962_OSC_ENA | WM8962_PLL2_ENA | WM8962_PLL3_ENA,
+ 0);
+
regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
if (pdata) {
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index b393f9fac97..fa0a48066aa 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -56,7 +56,7 @@ static int wm8994_retune_mobile_base[] = {
static int wm8994_readable(struct snd_soc_codec *codec, unsigned int reg)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
- struct wm8994 *control = wm8994->control_data;
+ struct wm8994 *control = codec->control_data;
switch (reg) {
case WM8994_GPIO_1:
@@ -1282,7 +1282,7 @@ SND_SOC_DAPM_MUX("AIF2DAC Mux", SND_SOC_NOPM, 0, 0, &aif2dac_mux),
SND_SOC_DAPM_MUX("AIF2ADC Mux", SND_SOC_NOPM, 0, 0, &aif2adc_mux),
SND_SOC_DAPM_AIF_IN("AIF3DACDAT", "AIF3 Playback", 0, SND_SOC_NOPM, 0, 0),
-SND_SOC_DAPM_AIF_IN("AIF3ADCDAT", "AIF3 Capture", 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_OUT("AIF3ADCDAT", "AIF3 Capture", 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_SUPPLY("TOCLK", WM8994_CLOCKING_1, 4, 0, NULL, 0),
@@ -2311,7 +2311,7 @@ static void wm8994_aif_shutdown(struct snd_pcm_substream *substream,
rate_reg = WM8994_AIF1_RATE;
break;
case 2:
- rate_reg = WM8994_AIF1_RATE;
+ rate_reg = WM8994_AIF2_RATE;
break;
default:
break;
diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c
index 0cdb9d10567..c9c4e5c5949 100644
--- a/sound/soc/codecs/wm8996.c
+++ b/sound/soc/codecs/wm8996.c
@@ -1847,7 +1847,7 @@ static int wm8996_hw_params(struct snd_pcm_substream *substream,
snd_soc_update_bits(codec, lrclk_reg, WM8996_AIF1RX_RATE_MASK,
lrclk);
snd_soc_update_bits(codec, WM8996_AIF_CLOCKING_2,
- WM8996_DSP1_DIV_SHIFT << dsp_shift, dsp);
+ WM8996_DSP1_DIV_MASK << dsp_shift, dsp);
return 0;
}
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index d48afea5d93..672982924f1 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -703,6 +703,7 @@ static int __devinit fsl_ssi_probe(struct platform_device *pdev)
/* Initialize the the device_attribute structure */
dev_attr = &ssi_private->dev_attr;
+ sysfs_attr_init(&dev_attr->attr);
dev_attr->attr.name = "statistics";
dev_attr->attr.mode = S_IRUGO;
dev_attr->show = fsl_sysfs_ssi_show;