Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 270533
b: refs/heads/master
c: 6f88a4e
h: refs/heads/master
i:
  270531: fdc3ccc
v: v3
  • Loading branch information
Mark Brown committed Aug 22, 2011
1 parent 969a1b2 commit 56d59d2
Show file tree
Hide file tree
Showing 2 changed files with 157 additions and 2 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 1ab63da7212d4422cbc40d4ead5cff97f6050a50
refs/heads/master: 6f88a4e5785fbf4db9a2c7e16670e1f19e6566d2
157 changes: 156 additions & 1 deletion trunk/sound/soc/codecs/wm8962.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ struct wm8962_priv {
int fll_fref;
int fll_fout;

u16 dsp2_ena;

struct delayed_work mic_work;
struct snd_soc_jack *jack;

Expand Down Expand Up @@ -965,7 +967,7 @@ static const struct wm8962_reg_access {
[584] = { 0x002D, 0x002D, 0x0000 }, /* R584 - IRQ Debounce */
[586] = { 0xC000, 0xC000, 0x0000 }, /* R586 - MICINT Source Pol */
[768] = { 0x0001, 0x0001, 0x0000 }, /* R768 - DSP2 Power Management */
[1037] = { 0x0000, 0x003F, 0x0000 }, /* R1037 - DSP2_ExecControl */
[1037] = { 0x0000, 0x003F, 0xFFFF }, /* R1037 - DSP2_ExecControl */
[4096] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4096 - Write Sequencer 0 */
[4097] = { 0x00FF, 0x00FF, 0x0000 }, /* R4097 - Write Sequencer 1 */
[4098] = { 0x070F, 0x070F, 0x0000 }, /* R4098 - Write Sequencer 2 */
Expand Down Expand Up @@ -1986,6 +1988,122 @@ static const unsigned int classd_tlv[] = {
};
static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);

static int wm8962_dsp2_write_config(struct snd_soc_codec *codec)
{
return 0;
}

static int wm8962_dsp2_set_enable(struct snd_soc_codec *codec, u16 val)
{
u16 adcl = snd_soc_read(codec, WM8962_LEFT_ADC_VOLUME);
u16 adcr = snd_soc_read(codec, WM8962_RIGHT_ADC_VOLUME);
u16 dac = snd_soc_read(codec, WM8962_ADC_DAC_CONTROL_1);

/* Mute the ADCs and DACs */
snd_soc_write(codec, WM8962_LEFT_ADC_VOLUME, 0);
snd_soc_write(codec, WM8962_RIGHT_ADC_VOLUME, WM8962_ADC_VU);
snd_soc_update_bits(codec, WM8962_ADC_DAC_CONTROL_1,
WM8962_DAC_MUTE, WM8962_DAC_MUTE);

snd_soc_write(codec, WM8962_SOUNDSTAGE_ENABLES_0, val);

/* Restore the ADCs and DACs */
snd_soc_write(codec, WM8962_LEFT_ADC_VOLUME, adcl);
snd_soc_write(codec, WM8962_RIGHT_ADC_VOLUME, adcr);
snd_soc_update_bits(codec, WM8962_ADC_DAC_CONTROL_1,
WM8962_DAC_MUTE, dac);

return 0;
}

static int wm8962_dsp2_start(struct snd_soc_codec *codec)
{
struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);

wm8962_dsp2_write_config(codec);

snd_soc_write(codec, WM8962_DSP2_EXECCONTROL, WM8962_DSP2_RUNR);

wm8962_dsp2_set_enable(codec, wm8962->dsp2_ena);

return 0;
}

static int wm8962_dsp2_stop(struct snd_soc_codec *codec)
{
wm8962_dsp2_set_enable(codec, 0);

snd_soc_write(codec, WM8962_DSP2_EXECCONTROL, WM8962_DSP2_STOP);

return 0;
}

#define WM8962_DSP2_ENABLE(xname, xshift) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = wm8962_dsp2_ena_info, \
.get = wm8962_dsp2_ena_get, .put = wm8962_dsp2_ena_put, \
.private_value = xshift }

static int wm8962_dsp2_ena_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;

uinfo->count = 1;
uinfo->value.integer.min = 0;
uinfo->value.integer.max = 1;

return 0;
}

static int wm8962_dsp2_ena_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
int shift = kcontrol->private_value;
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);

ucontrol->value.integer.value[0] = !!(wm8962->dsp2_ena & 1 << shift);

return 0;
}

static int wm8962_dsp2_ena_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
int shift = kcontrol->private_value;
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
int old = wm8962->dsp2_ena;
int ret = 0;
int dsp2_running = snd_soc_read(codec, WM8962_DSP2_POWER_MANAGEMENT) &
WM8962_DSP2_ENA;

mutex_lock(&codec->mutex);

if (ucontrol->value.integer.value[0])
wm8962->dsp2_ena |= 1 << shift;
else
wm8962->dsp2_ena &= ~(1 << shift);

if (wm8962->dsp2_ena == old)
goto out;

ret = 1;

if (dsp2_running) {
if (wm8962->dsp2_ena)
wm8962_dsp2_set_enable(codec, wm8962->dsp2_ena);
else
wm8962_dsp2_stop(codec);
}

out:
mutex_unlock(&codec->mutex);

return ret;
}

/* The VU bits for the headphones are in a different register to the mute
* bits and only take effect on the PGA if it is actually powered.
*/
Expand Down Expand Up @@ -2144,6 +2262,11 @@ SOC_DOUBLE_R_TLV("EQ4 Volume", WM8962_EQ3, WM8962_EQ23,
WM8962_EQL_B4_GAIN_SHIFT, 31, 0, eq_tlv),
SOC_DOUBLE_R_TLV("EQ5 Volume", WM8962_EQ3, WM8962_EQ23,
WM8962_EQL_B5_GAIN_SHIFT, 31, 0, eq_tlv),

WM8962_DSP2_ENABLE("VSS Switch", WM8962_VSS_ENA_SHIFT),
WM8962_DSP2_ENABLE("HPF1 Switch", WM8962_HPF1_ENA_SHIFT),
WM8962_DSP2_ENABLE("HPF2 Switch", WM8962_HPF2_ENA_SHIFT),
WM8962_DSP2_ENABLE("HD Bass Switch", WM8962_HDBASS_ENA_SHIFT),
};

static const struct snd_kcontrol_new wm8962_spk_mono_controls[] = {
Expand Down Expand Up @@ -2403,6 +2526,31 @@ static int out_pga_event(struct snd_soc_dapm_widget *w,
}
}

static int dsp2_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);

switch (event) {
case SND_SOC_DAPM_POST_PMU:
if (wm8962->dsp2_ena)
wm8962_dsp2_start(codec);
break;

case SND_SOC_DAPM_PRE_PMD:
if (wm8962->dsp2_ena)
wm8962_dsp2_stop(codec);
break;

default:
BUG();
return -EINVAL;
}

return 0;
}

static const char *st_text[] = { "None", "Right", "Left" };

static const struct soc_enum str_enum =
Expand Down Expand Up @@ -2525,6 +2673,9 @@ SND_SOC_DAPM_SUPPLY("SYSCLK", WM8962_CLOCKING2, 5, 0, sysclk_event,
SND_SOC_DAPM_SUPPLY("Charge Pump", WM8962_CHARGE_PUMP_1, 0, 0, cp_event,
SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_SUPPLY("TOCLK", WM8962_ADDITIONAL_CONTROL_1, 0, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY_S("DSP2", 1, WM8962_DSP2_POWER_MANAGEMENT,
WM8962_DSP2_ENA_SHIFT, 0, dsp2_event,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),

SND_SOC_DAPM_MIXER("INPGAL", WM8962_LEFT_INPUT_PGA_CONTROL, 4, 0,
inpgal, ARRAY_SIZE(inpgal)),
Expand Down Expand Up @@ -2620,11 +2771,13 @@ static const struct snd_soc_dapm_route wm8962_intercon[] = {
{ "ADCL", NULL, "TOCLK" },
{ "ADCL", NULL, "MIXINL" },
{ "ADCL", NULL, "DMIC" },
{ "ADCL", NULL, "DSP2" },

{ "ADCR", NULL, "SYSCLK" },
{ "ADCR", NULL, "TOCLK" },
{ "ADCR", NULL, "MIXINR" },
{ "ADCR", NULL, "DMIC" },
{ "ADCR", NULL, "DSP2" },

{ "STL", "Left", "ADCL" },
{ "STL", "Right", "ADCR" },
Expand All @@ -2636,11 +2789,13 @@ static const struct snd_soc_dapm_route wm8962_intercon[] = {
{ "DACL", NULL, "TOCLK" },
{ "DACL", NULL, "Beep" },
{ "DACL", NULL, "STL" },
{ "DACL", NULL, "DSP2" },

{ "DACR", NULL, "SYSCLK" },
{ "DACR", NULL, "TOCLK" },
{ "DACR", NULL, "Beep" },
{ "DACR", NULL, "STR" },
{ "DACR", NULL, "DSP2" },

{ "HPMIXL", "IN4L Switch", "IN4L" },
{ "HPMIXL", "IN4R Switch", "IN4R" },
Expand Down

0 comments on commit 56d59d2

Please sign in to comment.