Commit 86e1d57e authored by Takashi Iwai's avatar Takashi Iwai

Merge branch 'topic/hda' into for-linus

parents baf92266 ac2c92e0
...@@ -798,6 +798,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. ...@@ -798,6 +798,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
setup before initializing the codecs. This option is setup before initializing the codecs. This option is
available only when CONFIG_SND_HDA_PATCH_LOADER=y is set. available only when CONFIG_SND_HDA_PATCH_LOADER=y is set.
See HD-Audio.txt for details. See HD-Audio.txt for details.
beep_mode - Selects the beep registration mode (0=off, 1=on, 2=
dynamic registration via mute switch on/off); the default
value is set via CONFIG_SND_HDA_INPUT_BEEP_MODE kconfig.
[Single (global) options] [Single (global) options]
single_cmd - Use single immediate commands to communicate with single_cmd - Use single immediate commands to communicate with
......
...@@ -391,6 +391,7 @@ STAC92HD83* ...@@ -391,6 +391,7 @@ STAC92HD83*
ref Reference board ref Reference board
mic-ref Reference board with power management for ports mic-ref Reference board with power management for ports
dell-s14 Dell laptop dell-s14 Dell laptop
hp HP laptops with (inverted) mute-LED
auto BIOS setup (default) auto BIOS setup (default)
STAC9872 STAC9872
......
This diff is collapsed.
...@@ -95,13 +95,13 @@ ...@@ -95,13 +95,13 @@
/* AK4114_REG_IO0 */ /* AK4114_REG_IO0 */
#define AK4114_TX1E (1<<7) /* TX1 Output Enable (1 = enable) */ #define AK4114_TX1E (1<<7) /* TX1 Output Enable (1 = enable) */
#define AK4114_OPS12 (1<<2) /* Output Though Data Selector for TX1 pin */ #define AK4114_OPS12 (1<<6) /* Output Data Selector for TX1 pin */
#define AK4114_OPS11 (1<<1) /* Output Though Data Selector for TX1 pin */ #define AK4114_OPS11 (1<<5) /* Output Data Selector for TX1 pin */
#define AK4114_OPS10 (1<<0) /* Output Though Data Selector for TX1 pin */ #define AK4114_OPS10 (1<<4) /* Output Data Selector for TX1 pin */
#define AK4114_TX0E (1<<3) /* TX0 Output Enable (1 = enable) */ #define AK4114_TX0E (1<<3) /* TX0 Output Enable (1 = enable) */
#define AK4114_OPS02 (1<<2) /* Output Though Data Selector for TX0 pin */ #define AK4114_OPS02 (1<<2) /* Output Data Selector for TX0 pin */
#define AK4114_OPS01 (1<<1) /* Output Though Data Selector for TX0 pin */ #define AK4114_OPS01 (1<<1) /* Output Data Selector for TX0 pin */
#define AK4114_OPS00 (1<<0) /* Output Though Data Selector for TX0 pin */ #define AK4114_OPS00 (1<<0) /* Output Data Selector for TX0 pin */
/* AK4114_REG_IO1 */ /* AK4114_REG_IO1 */
#define AK4114_EFH1 (1<<7) /* Interrupt 0 pin Hold */ #define AK4114_EFH1 (1<<7) /* Interrupt 0 pin Hold */
......
...@@ -68,7 +68,7 @@ struct snd_akm4xxx { ...@@ -68,7 +68,7 @@ struct snd_akm4xxx {
enum { enum {
SND_AK4524, SND_AK4528, SND_AK4529, SND_AK4524, SND_AK4528, SND_AK4529,
SND_AK4355, SND_AK4358, SND_AK4381, SND_AK4355, SND_AK4358, SND_AK4381,
SND_AK5365 SND_AK5365, SND_AK4620,
} type; } type;
/* (array) information of combined codecs */ /* (array) information of combined codecs */
...@@ -76,6 +76,9 @@ struct snd_akm4xxx { ...@@ -76,6 +76,9 @@ struct snd_akm4xxx {
const struct snd_akm4xxx_adc_channel *adc_info; const struct snd_akm4xxx_adc_channel *adc_info;
struct snd_ak4xxx_ops ops; struct snd_ak4xxx_ops ops;
unsigned int num_chips;
unsigned int total_regs;
const char *name;
}; };
void snd_akm4xxx_write(struct snd_akm4xxx *ak, int chip, unsigned char reg, void snd_akm4xxx_write(struct snd_akm4xxx *ak, int chip, unsigned char reg,
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
snd-ak4114-objs := ak4114.o snd-ak4114-objs := ak4114.o
snd-ak4117-objs := ak4117.o snd-ak4117-objs := ak4117.o
snd-ak4113-objs := ak4113.o
snd-ak4xxx-adda-objs := ak4xxx-adda.o snd-ak4xxx-adda-objs := ak4xxx-adda.o
snd-pt2258-objs := pt2258.o snd-pt2258-objs := pt2258.o
snd-tea575x-tuner-objs := tea575x-tuner.o snd-tea575x-tuner-objs := tea575x-tuner.o
...@@ -12,5 +13,5 @@ snd-tea575x-tuner-objs := tea575x-tuner.o ...@@ -12,5 +13,5 @@ snd-tea575x-tuner-objs := tea575x-tuner.o
# Module Dependency # Module Dependency
obj-$(CONFIG_SND_PDAUDIOCF) += snd-ak4117.o obj-$(CONFIG_SND_PDAUDIOCF) += snd-ak4117.o
obj-$(CONFIG_SND_ICE1712) += snd-ak4xxx-adda.o obj-$(CONFIG_SND_ICE1712) += snd-ak4xxx-adda.o
obj-$(CONFIG_SND_ICE1724) += snd-ak4114.o snd-ak4xxx-adda.o snd-pt2258.o obj-$(CONFIG_SND_ICE1724) += snd-ak4114.o snd-ak4113.o snd-ak4xxx-adda.o snd-pt2258.o
obj-$(CONFIG_SND_FM801_TEA575X) += snd-tea575x-tuner.o obj-$(CONFIG_SND_FM801_TEA575X) += snd-tea575x-tuner.o
This diff is collapsed.
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* *
*/ */
#include <asm/io.h> #include <asm/io.h>
#include <linux/delay.h> #include <linux/delay.h>
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <sound/control.h> #include <sound/control.h>
#include <sound/tlv.h> #include <sound/tlv.h>
#include <sound/ak4xxx-adda.h> #include <sound/ak4xxx-adda.h>
#include <sound/info.h>
MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Takashi Iwai <tiwai@suse.de>"); MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Takashi Iwai <tiwai@suse.de>");
MODULE_DESCRIPTION("Routines for control of AK452x / AK43xx AD/DA converters"); MODULE_DESCRIPTION("Routines for control of AK452x / AK43xx AD/DA converters");
...@@ -52,26 +53,21 @@ EXPORT_SYMBOL(snd_akm4xxx_write); ...@@ -52,26 +53,21 @@ EXPORT_SYMBOL(snd_akm4xxx_write);
static void ak4524_reset(struct snd_akm4xxx *ak, int state) static void ak4524_reset(struct snd_akm4xxx *ak, int state)
{ {
unsigned int chip; unsigned int chip;
unsigned char reg, maxreg; unsigned char reg;
if (ak->type == SND_AK4528)
maxreg = 0x06;
else
maxreg = 0x08;
for (chip = 0; chip < ak->num_dacs/2; chip++) { for (chip = 0; chip < ak->num_dacs/2; chip++) {
snd_akm4xxx_write(ak, chip, 0x01, state ? 0x00 : 0x03); snd_akm4xxx_write(ak, chip, 0x01, state ? 0x00 : 0x03);
if (state) if (state)
continue; continue;
/* DAC volumes */ /* DAC volumes */
for (reg = 0x04; reg < maxreg; reg++) for (reg = 0x04; reg < ak->total_regs; reg++)
snd_akm4xxx_write(ak, chip, reg, snd_akm4xxx_write(ak, chip, reg,
snd_akm4xxx_get(ak, chip, reg)); snd_akm4xxx_get(ak, chip, reg));
} }
} }
/* reset procedure for AK4355 and AK4358 */ /* reset procedure for AK4355 and AK4358 */
static void ak435X_reset(struct snd_akm4xxx *ak, int state, static void ak435X_reset(struct snd_akm4xxx *ak, int state)
unsigned char total_regs)
{ {
unsigned char reg; unsigned char reg;
...@@ -79,7 +75,7 @@ static void ak435X_reset(struct snd_akm4xxx *ak, int state, ...@@ -79,7 +75,7 @@ static void ak435X_reset(struct snd_akm4xxx *ak, int state,
snd_akm4xxx_write(ak, 0, 0x01, 0x02); /* reset and soft-mute */ snd_akm4xxx_write(ak, 0, 0x01, 0x02); /* reset and soft-mute */
return; return;
} }
for (reg = 0x00; reg < total_regs; reg++) for (reg = 0x00; reg < ak->total_regs; reg++)
if (reg != 0x01) if (reg != 0x01)
snd_akm4xxx_write(ak, 0, reg, snd_akm4xxx_write(ak, 0, reg,
snd_akm4xxx_get(ak, 0, reg)); snd_akm4xxx_get(ak, 0, reg));
...@@ -91,12 +87,11 @@ static void ak4381_reset(struct snd_akm4xxx *ak, int state) ...@@ -91,12 +87,11 @@ static void ak4381_reset(struct snd_akm4xxx *ak, int state)
{ {
unsigned int chip; unsigned int chip;
unsigned char reg; unsigned char reg;
for (chip = 0; chip < ak->num_dacs/2; chip++) { for (chip = 0; chip < ak->num_dacs/2; chip++) {
snd_akm4xxx_write(ak, chip, 0x00, state ? 0x0c : 0x0f); snd_akm4xxx_write(ak, chip, 0x00, state ? 0x0c : 0x0f);
if (state) if (state)
continue; continue;
for (reg = 0x01; reg < 0x05; reg++) for (reg = 0x01; reg < ak->total_regs; reg++)
snd_akm4xxx_write(ak, chip, reg, snd_akm4xxx_write(ak, chip, reg,
snd_akm4xxx_get(ak, chip, reg)); snd_akm4xxx_get(ak, chip, reg));
} }
...@@ -113,16 +108,17 @@ void snd_akm4xxx_reset(struct snd_akm4xxx *ak, int state) ...@@ -113,16 +108,17 @@ void snd_akm4xxx_reset(struct snd_akm4xxx *ak, int state)
switch (ak->type) { switch (ak->type) {
case SND_AK4524: case SND_AK4524:
case SND_AK4528: case SND_AK4528:
case SND_AK4620:
ak4524_reset(ak, state); ak4524_reset(ak, state);
break; break;
case SND_AK4529: case SND_AK4529:
/* FIXME: needed for ak4529? */ /* FIXME: needed for ak4529? */
break; break;
case SND_AK4355: case SND_AK4355:
ak435X_reset(ak, state, 0x0b); ak435X_reset(ak, state);
break; break;
case SND_AK4358: case SND_AK4358:
ak435X_reset(ak, state, 0x10); ak435X_reset(ak, state);
break; break;
case SND_AK4381: case SND_AK4381:
ak4381_reset(ak, state); ak4381_reset(ak, state);
...@@ -139,7 +135,7 @@ EXPORT_SYMBOL(snd_akm4xxx_reset); ...@@ -139,7 +135,7 @@ EXPORT_SYMBOL(snd_akm4xxx_reset);
* Volume conversion table for non-linear volumes * Volume conversion table for non-linear volumes
* from -63.5dB (mute) to 0dB step 0.5dB * from -63.5dB (mute) to 0dB step 0.5dB
* *
* Used for AK4524 input/ouput attenuation, AK4528, and * Used for AK4524/AK4620 input/ouput attenuation, AK4528, and
* AK5365 input attenuation * AK5365 input attenuation
*/ */
static const unsigned char vol_cvt_datt[128] = { static const unsigned char vol_cvt_datt[128] = {
...@@ -259,8 +255,22 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak) ...@@ -259,8 +255,22 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak)
0x00, 0x0f, /* 0: power-up, un-reset */ 0x00, 0x0f, /* 0: power-up, un-reset */
0xff, 0xff 0xff, 0xff
}; };
static const unsigned char inits_ak4620[] = {
0x00, 0x07, /* 0: normal */
0x01, 0x00, /* 0: reset */
0x01, 0x02, /* 1: RSTAD */
0x01, 0x03, /* 1: RSTDA */
0x01, 0x0f, /* 1: normal */
0x02, 0x60, /* 2: 24bit I2S */
0x03, 0x01, /* 3: deemphasis off */
0x04, 0x00, /* 4: LIN muted */
0x05, 0x00, /* 5: RIN muted */
0x06, 0x00, /* 6: LOUT muted */
0x07, 0x00, /* 7: ROUT muted */
0xff, 0xff
};
int chip, num_chips; int chip;
const unsigned char *ptr, *inits; const unsigned char *ptr, *inits;
unsigned char reg, data; unsigned char reg, data;
...@@ -270,42 +280,64 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak) ...@@ -270,42 +280,64 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak)
switch (ak->type) { switch (ak->type) {
case SND_AK4524: case SND_AK4524:
inits = inits_ak4524; inits = inits_ak4524;
num_chips = ak->num_dacs / 2; ak->num_chips = ak->num_dacs / 2;
ak->name = "ak4524";
ak->total_regs = 0x08;
break; break;
case SND_AK4528: case SND_AK4528:
inits = inits_ak4528; inits = inits_ak4528;
num_chips = ak->num_dacs / 2; ak->num_chips = ak->num_dacs / 2;
ak->name = "ak4528";
ak->total_regs = 0x06;
break; break;
case SND_AK4529: case SND_AK4529:
inits = inits_ak4529; inits = inits_ak4529;
num_chips = 1; ak->num_chips = 1;
ak->name = "ak4529";
ak->total_regs = 0x0d;
break; break;
case SND_AK4355: case SND_AK4355:
inits = inits_ak4355; inits = inits_ak4355;
num_chips = 1; ak->num_chips = 1;
ak->name = "ak4355";
ak->total_regs = 0x0b;
break; break;
case SND_AK4358: case SND_AK4358:
inits = inits_ak4358; inits = inits_ak4358;
num_chips = 1; ak->num_chips = 1;
ak->name = "ak4358";
ak->total_regs = 0x10;
break; break;
case SND_AK4381: case SND_AK4381:
inits = inits_ak4381; inits = inits_ak4381;
num_chips = ak->num_dacs / 2; ak->num_chips = ak->num_dacs / 2;
ak->name = "ak4381";
ak->total_regs = 0x05;
break; break;
case SND_AK5365: case SND_AK5365:
/* FIXME: any init sequence? */ /* FIXME: any init sequence? */
ak->num_chips = 1;
ak->name = "ak5365";
ak->total_regs = 0x08;
return; return;
case SND_AK4620:
inits = inits_ak4620;
ak->num_chips = ak->num_dacs / 2;
ak->name = "ak4620";
ak->total_regs = 0x08;
break;
default: default:
snd_BUG(); snd_BUG();
return; return;
} }
for (chip = 0; chip < num_chips; chip++) { for (chip = 0; chip < ak->num_chips; chip++) {
ptr = inits; ptr = inits;
while (*ptr != 0xff) { while (*ptr != 0xff) {
reg = *ptr++; reg = *ptr++;
data = *ptr++; data = *ptr++;
snd_akm4xxx_write(ak, chip, reg, data); snd_akm4xxx_write(ak, chip, reg, data);
udelay(10);
} }
} }
} }
...@@ -688,6 +720,12 @@ static int build_dac_controls(struct snd_akm4xxx *ak) ...@@ -688,6 +720,12 @@ static int build_dac_controls(struct snd_akm4xxx *ak)
AK_COMPOSE(idx/2, (idx%2) + 3, 0, 255); AK_COMPOSE(idx/2, (idx%2) + 3, 0, 255);
knew.tlv.p = db_scale_linear; knew.tlv.p = db_scale_linear;
break; break;
case SND_AK4620:
/* register 6 & 7 */
knew.private_value =
AK_COMPOSE(idx/2, (idx%2) + 6, 0, 255);
knew.tlv.p = db_scale_linear;
break;
default: default:
return -EINVAL; return -EINVAL;
} }
...@@ -704,10 +742,12 @@ static int build_dac_controls(struct snd_akm4xxx *ak) ...@@ -704,10 +742,12 @@ static int build_dac_controls(struct snd_akm4xxx *ak)
static int build_adc_controls(struct snd_akm4xxx *ak) static int build_adc_controls(struct snd_akm4xxx *ak)
{ {
int idx, err, mixer_ch, num_stereo; int idx, err, mixer_ch, num_stereo, max_steps;
struct snd_kcontrol_new knew; struct snd_kcontrol_new knew;
mixer_ch = 0; mixer_ch = 0;
if (ak->type == SND_AK4528)
return 0; /* no controls */
for (idx = 0; idx < ak->num_adcs;) { for (idx = 0; idx < ak->num_adcs;) {
memset(&knew, 0, sizeof(knew)); memset(&knew, 0, sizeof(knew));
if (! ak->adc_info || ! ak->adc_info[mixer_ch].name) { if (! ak->adc_info || ! ak->adc_info[mixer_ch].name) {
...@@ -733,13 +773,12 @@ static int build_adc_controls(struct snd_akm4xxx *ak) ...@@ -733,13 +773,12 @@ static int build_adc_controls(struct snd_akm4xxx *ak)
} }
/* register 4 & 5 */ /* register 4 & 5 */
if (ak->type == SND_AK5365) if (ak->type == SND_AK5365)
knew.private_value = max_steps = 152;
AK_COMPOSE(idx/2, (idx%2) + 4, 0, 151) |
AK_VOL_CVT | AK_IPGA;
else else
knew.private_value = max_steps = 164;
AK_COMPOSE(idx/2, (idx%2) + 4, 0, 163) | knew.private_value =
AK_VOL_CVT | AK_IPGA; AK_COMPOSE(idx/2, (idx%2) + 4, 0, max_steps) |
AK_VOL_CVT | AK_IPGA;
knew.tlv.p = db_scale_vol_datt; knew.tlv.p = db_scale_vol_datt;
err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak)); err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak));
if (err < 0) if (err < 0)
...@@ -808,6 +847,7 @@ static int build_deemphasis(struct snd_akm4xxx *ak, int num_emphs) ...@@ -808,6 +847,7 @@ static int build_deemphasis(struct snd_akm4xxx *ak, int num_emphs)
switch (ak->type) { switch (ak->type) {
case SND_AK4524: case SND_AK4524:
case SND_AK4528: case SND_AK4528:
case SND_AK4620:
/* register 3 */ /* register 3 */
knew.private_value = AK_COMPOSE(idx, 3, 0, 0); knew.private_value = AK_COMPOSE(idx, 3, 0, 0);
break; break;
...@@ -834,6 +874,35 @@ static int build_deemphasis(struct snd_akm4xxx *ak, int num_emphs) ...@@ -834,6 +874,35 @@ static int build_deemphasis(struct snd_akm4xxx *ak, int num_emphs)
return 0; return 0;
} }
#ifdef CONFIG_PROC_FS
static void proc_regs_read(struct snd_info_entry *entry,
struct snd_info_buffer *buffer)
{
struct snd_akm4xxx *ak = (struct snd_akm4xxx *)entry->private_data;
int reg, val, chip;
for (chip = 0; chip < ak->num_chips; chip++) {
for (reg = 0; reg < ak->total_regs; reg++) {
val = snd_akm4xxx_get(ak, chip, reg);
snd_iprintf(buffer, "chip %d: 0x%02x = 0x%02x\n", chip,
reg, val);
}
}
}
static int proc_init(struct snd_akm4xxx *ak)
{
struct snd_info_entry *entry;
int err;
err = snd_card_proc_new(ak->card, ak->name, &entry);
if (err < 0)
return err;
snd_info_set_text_ops(entry, ak, proc_regs_read);
return 0;
}
#else /* !CONFIG_PROC_FS */
static int proc_init(struct snd_akm4xxx *ak) {}
#endif
int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak) int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak)
{ {
int err, num_emphs; int err, num_emphs;
...@@ -845,18 +914,21 @@ int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak) ...@@ -845,18 +914,21 @@ int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak)
err = build_adc_controls(ak); err = build_adc_controls(ak);
if (err < 0) if (err < 0)
return err; return err;
if (ak->type == SND_AK4355 || ak->type == SND_AK4358) if (ak->type == SND_AK4355 || ak->type == SND_AK4358)
num_emphs = 1; num_emphs = 1;
else if (ak->type == SND_AK4620)
num_emphs = 0;
else else
num_emphs = ak->num_dacs / 2; num_emphs = ak->num_dacs / 2;
err = build_deemphasis(ak, num_emphs); err = build_deemphasis(ak, num_emphs);
if (err < 0)
return err;
err = proc_init(ak);
if (err < 0) if (err < 0)
return err; return err;
return 0; return 0;
} }
EXPORT_SYMBOL(snd_akm4xxx_build_controls); EXPORT_SYMBOL(snd_akm4xxx_build_controls);
static int __init alsa_akm4xxx_module_init(void) static int __init alsa_akm4xxx_module_init(void)
......
...@@ -38,9 +38,20 @@ config SND_HDA_INPUT_BEEP ...@@ -38,9 +38,20 @@ config SND_HDA_INPUT_BEEP
Say Y here to build a digital beep interface for HD-audio Say Y here to build a digital beep interface for HD-audio
driver. This interface is used to generate digital beeps. driver. This interface is used to generate digital beeps.
config SND_HDA_INPUT_BEEP_MODE
int "Digital beep registration mode (0=off, 1=on, 2=mute sw on/off)"
depends on SND_HDA_INPUT_BEEP=y
default "1"
range 0 2
help
Set 0 to disable the digital beep interface for HD-audio by default.
Set 1 to always enable the digital beep interface for HD-audio by
default. Set 2 to control the beep device registration to input
layer using a "Beep Switch" in mixer applications.
config SND_HDA_INPUT_JACK config SND_HDA_INPUT_JACK
bool "Support jack plugging notification via input layer" bool "Support jack plugging notification via input layer"
depends on INPUT=y || INPUT=SND_HDA_INTEL depends on INPUT=y || INPUT=SND
select SND_JACK select SND_JACK
help help
Say Y here to enable the jack plugging notification via Say Y here to enable the jack plugging notification via
......
...@@ -113,23 +113,25 @@ static int snd_hda_beep_event(struct input_dev *dev, unsigned int type, ...@@ -113,23 +113,25 @@ static int snd_hda_beep_event(struct input_dev *dev, unsigned int type,
return 0; return 0;
} }
int snd_hda_attach_beep_device(struct hda_codec *codec, int nid) static void snd_hda_do_detach(struct hda_beep *beep)
{
input_unregister_device(beep->dev);
beep->dev = NULL;
cancel_work_sync(&beep->beep_work);
/* turn off beep for sure */
snd_hda_codec_write_cache(beep->codec, beep->nid, 0,
AC_VERB_SET_BEEP_CONTROL, 0);
}
static int snd_hda_do_attach(struct hda_beep *beep)
{ {
struct input_dev *input_dev; struct input_dev *input_dev;
struct hda_beep *beep; struct hda_codec *codec = beep->codec;
int err; int err;
if (!snd_hda_get_bool_hint(codec, "beep"))
return 0; /* disabled explicitly */
beep = kzalloc(sizeof(*beep), GFP_KERNEL);
if (beep == NULL)
return -ENOMEM;
snprintf(beep->phys, sizeof(beep->phys),
"card%d/codec#%d/beep0", codec->bus->card->number, codec->addr);
input_dev = input_allocate_device(); input_dev = input_allocate_device();
if (!input_dev) { if (!input_dev) {
kfree(beep); printk(KERN_INFO "hda_beep: unable to allocate input device\n");
return -ENOMEM; return -ENOMEM;
} }
...@@ -151,21 +153,96 @@ int snd_hda_attach_beep_device(struct hda_codec *codec, int nid) ...@@ -151,21 +153,96 @@ int snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
err = input_register_device(input_dev); err = input_register_device(input_dev);
if (err < 0) { if (err < 0) {
input_free_device(input_dev); input_free_device(input_dev);
kfree(beep); printk(KERN_INFO "hda_beep: unable to register input device\n");
return err; return err;
} }
beep->dev = input_dev;
return 0;
}
static void snd_hda_do_register(struct work_struct *work)
{
struct hda_beep *beep =
container_of(work, struct hda_beep, register_work);
mutex_lock(&beep->mutex);
if (beep->enabled && !beep->dev)
snd_hda_do_attach(beep);
mutex_unlock(&beep->mutex);
}
static void snd_hda_do_unregister(struct work_struct *work)
{
struct hda_beep *beep =
container_of(work, struct hda_beep, unregister_work.work);
mutex_lock(&beep->mutex);
if (!beep->enabled && beep->dev)
snd_hda_do_detach(beep);
mutex_unlock(&beep->mutex);
}
int snd_hda_enable_beep_device(struct hda_codec *codec, int enable)
{
struct hda_beep *beep = codec->beep;
enable = !!enable;
if (beep == NULL)
return 0;
if (beep->enabled != enable) {
beep->enabled = enable;
if (!enable) {
/* turn off beep */
snd_hda_codec_write_cache(beep->codec, beep->nid, 0,
AC_VERB_SET_BEEP_CONTROL, 0);
}
if (beep->mode == HDA_BEEP_MODE_SWREG) {
if (enable) {
cancel_delayed_work(&beep->unregister_work);
schedule_work(&beep->register_work);
} else {
schedule_delayed_work(&beep->unregister_work,
HZ);
}
}
return 1;
}
return 0;
}
EXPORT_SYMBOL_HDA(snd_hda_enable_beep_device);
int snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
{
struct hda_beep *beep;
if (!snd_hda_get_bool_hint(codec, "beep"))
return 0; /* disabled explicitly by hints */
if (codec->beep_mode == HDA_BEEP_MODE_OFF)
return 0; /* disabled by module option */
beep = kzalloc(sizeof(*beep), GFP_KERNEL);
if (beep == NULL)
return -ENOMEM;
snprintf(beep->phys, sizeof(beep->phys),
"card%d/codec#%d/beep0", codec->bus->card->number, codec->addr);
/* enable linear scale */ /* enable linear scale */
snd_hda_codec_write(codec, nid, 0, snd_hda_codec_write(codec, nid, 0,
AC_VERB_SET_DIGI_CONVERT_2, 0x01); AC_VERB_SET_DIGI_CONVERT_2, 0x01);
beep->nid = nid; beep->nid = nid;
beep->dev = input_dev;
beep->codec = codec; beep->codec = codec;
beep->enabled = 1; beep->mode = codec->beep_mode;
codec->beep = beep; codec->beep = beep;
INIT_WORK(&beep->register_work, &snd_hda_do_register);
INIT_DELAYED_WORK(&beep->unregister_work, &snd_hda_do_unregister);
INIT_WORK(&beep->beep_work, &snd_hda_generate_beep); INIT_WORK(&beep->beep_work, &snd_hda_generate_beep);
mutex_init(&beep->mutex);
if (beep->mode == HDA_BEEP_MODE_ON) {
beep->enabled = 1;
snd_hda_do_register(&beep->register_work);
}
return 0; return 0;
} }
EXPORT_SYMBOL_HDA(snd_hda_attach_beep_device); EXPORT_SYMBOL_HDA(snd_hda_attach_beep_device);
...@@ -174,11 +251,12 @@ void snd_hda_detach_beep_device(struct hda_codec *codec) ...@@ -174,11 +251,12 @@ void snd_hda_detach_beep_device(struct hda_codec *codec)
{ {
struct hda_beep *beep = codec->beep; struct hda_beep *beep = codec->beep;
if (beep) { if (beep) {
cancel_work_sync(&beep->beep_work); cancel_work_sync(&beep->register_work);
cancel_delayed_work(&beep->unregister_work);
input_unregister_device(beep->dev); if (beep->enabled)
kfree(beep); snd_hda_do_detach(beep);
codec->beep = NULL; codec->beep = NULL;
kfree(beep);
} }
} }
EXPORT_SYMBOL_HDA(snd_hda_detach_beep_device); EXPORT_SYMBOL_HDA(snd_hda_detach_beep_device);
...@@ -24,19 +24,29 @@ ...@@ -24,19 +24,29 @@
#include "hda_codec.h" #include "hda_codec.h"
#define HDA_BEEP_MODE_OFF 0
#define HDA_BEEP_MODE_ON 1
#define HDA_BEEP_MODE_SWREG 2
/* beep information */ /* beep information */
struct hda_beep { struct hda_beep {
struct input_dev *dev; struct input_dev *dev;
struct hda_codec *codec; struct hda_codec *codec;
unsigned int mode;
char phys[32]; char phys[32];
int tone; int tone;
hda_nid_t nid; hda_nid_t nid;
unsigned int enabled:1; unsigned int enabled:1;
unsigned int request_enable:1;
unsigned int linear_tone:1; /* linear tone for IDT/STAC codec */ unsigned int linear_tone:1; /* linear tone for IDT/STAC codec */
struct work_struct register_work; /* registration work */
struct delayed_work unregister_work; /* unregistration work */
struct work_struct beep_work; /* scheduled task for beep event */ struct work_struct beep_work; /* scheduled task for beep event */
struct mutex mutex;
}; };
#ifdef CONFIG_SND_HDA_INPUT_BEEP #ifdef CONFIG_SND_HDA_INPUT_BEEP
int snd_hda_enable_beep_device(struct hda_codec *codec, int enable);
int snd_hda_attach_beep_device(struct hda_codec *codec, int nid); int snd_hda_attach_beep_device(struct hda_codec *codec, int nid);
void snd_hda_detach_beep_device(struct hda_codec *codec); void snd_hda_detach_beep_device(struct hda_codec *codec);
#else #else
......
This diff is collapsed.
...@@ -286,6 +286,10 @@ enum { ...@@ -286,6 +286,10 @@ enum {
#define AC_PWRST_D1SUP (1<<1) #define AC_PWRST_D1SUP (1<<1)
#define AC_PWRST_D2SUP (1<<2) #define AC_PWRST_D2SUP (1<<2)
#define AC_PWRST_D3SUP (1<<3) #define AC_PWRST_D3SUP (1<<3)
#define AC_PWRST_D3COLDSUP (1<<4)
#define AC_PWRST_S3D3COLDSUP (1<<29)
#define AC_PWRST_CLKSTOP (1<<30)
#define AC_PWRST_EPSS (1U<<31)
/* Power state values */ /* Power state values */
#define AC_PWRST_SETTING (0xf<<0) #define AC_PWRST_SETTING (0xf<<0)
...@@ -674,6 +678,7 @@ struct hda_codec_ops { ...@@ -674,6 +678,7 @@ struct hda_codec_ops {
#ifdef CONFIG_SND_HDA_POWER_SAVE #ifdef CONFIG_SND_HDA_POWER_SAVE
int (*check_power_status)(struct hda_codec *codec, hda_nid_t nid); int (*check_power_status)(struct hda_codec *codec, hda_nid_t nid);
#endif #endif
void (*reboot_notify)(struct hda_codec *codec);
}; };
/* record for amp information cache */ /* record for amp information cache */
...@@ -771,6 +776,7 @@ struct hda_codec { ...@@ -771,6 +776,7 @@ struct hda_codec {
/* beep device */ /* beep device */
struct hda_beep *beep; struct hda_beep *beep;
unsigned int beep_mode;
/* widget capabilities cache */ /* widget capabilities cache */
unsigned int num_nodes; unsigned int num_nodes;
...@@ -811,6 +817,9 @@ struct hda_codec { ...@@ -811,6 +817,9 @@ struct hda_codec {
unsigned int power_transition :1; /* power-state in transition */ unsigned int power_transition :1; /* power-state in transition */
int power_count; /* current (global) power refcount */ int power_count; /* current (global) power refcount */
struct delayed_work power_work; /* delayed task for powerdown */ struct delayed_work power_work; /* delayed task for powerdown */
unsigned long power_on_acct;
unsigned long power_off_acct;
unsigned long power_jiffies;
#endif #endif
/* codec-specific additional proc output */ /* codec-specific additional proc output */
...@@ -910,6 +919,7 @@ int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid, ...@@ -910,6 +919,7 @@ int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
* Misc * Misc
*/ */
void snd_hda_get_codec_name(struct hda_codec *codec, char *name, int namelen); void snd_hda_get_codec_name(struct hda_codec *codec, char *name, int namelen);
void snd_hda_bus_reboot_notify(struct hda_bus *bus);
/* /*
* power management * power management
...@@ -933,6 +943,7 @@ const char *snd_hda_get_jack_location(u32 cfg); ...@@ -933,6 +943,7 @@ const char *snd_hda_get_jack_location(u32 cfg);
void snd_hda_power_up(struct hda_codec *codec); void snd_hda_power_up(struct hda_codec *codec);
void snd_hda_power_down(struct hda_codec *codec); void snd_hda_power_down(struct hda_codec *codec);
#define snd_hda_codec_needs_resume(codec) codec->power_count #define snd_hda_codec_needs_resume(codec) codec->power_count
void snd_hda_update_power_acct(struct hda_codec *codec);
#else #else
static inline void snd_hda_power_up(struct hda_codec *codec) {} static inline void snd_hda_power_up(struct hda_codec *codec) {}
static inline void snd_hda_power_down(struct hda_codec *codec) {} static inline void snd_hda_power_down(struct hda_codec *codec) {}
......
...@@ -309,17 +309,12 @@ out_fail: ...@@ -309,17 +309,12 @@ out_fail:
return -EINVAL; return -EINVAL;
} }
static int hdmi_present_sense(struct hda_codec *codec, hda_nid_t nid)
{
return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_SENSE, 0);
}
static int hdmi_eld_valid(struct hda_codec *codec, hda_nid_t nid) static int hdmi_eld_valid(struct hda_codec *codec, hda_nid_t nid)
{ {
int eldv; int eldv;
int present; int present;
present = hdmi_present_sense(codec, nid); present = snd_hda_pin_sense(codec, nid);
eldv = (present & AC_PINSENSE_ELDV); eldv = (present & AC_PINSENSE_ELDV);
present = (present & AC_PINSENSE_PRESENCE); present = (present & AC_PINSENSE_PRESENCE);
...@@ -477,6 +472,8 @@ static void hdmi_print_eld_info(struct snd_info_entry *entry, ...@@ -477,6 +472,8 @@ static void hdmi_print_eld_info(struct snd_info_entry *entry,
[4 ... 7] = "reserved" [4 ... 7] = "reserved"
}; };
snd_iprintf(buffer, "monitor_present\t\t%d\n", e->monitor_present);
snd_iprintf(buffer, "eld_valid\t\t%d\n", e->eld_valid);
snd_iprintf(buffer, "monitor_name\t\t%s\n", e->monitor_name); snd_iprintf(buffer, "monitor_name\t\t%s\n", e->monitor_name);
snd_iprintf(buffer, "connection_type\t\t%s\n", snd_iprintf(buffer, "connection_type\t\t%s\n",
eld_connection_type_names[e->conn_type]); eld_connection_type_names[e->conn_type]);
...@@ -518,7 +515,11 @@ static void hdmi_write_eld_info(struct snd_info_entry *entry, ...@@ -518,7 +515,11 @@ static void hdmi_write_eld_info(struct snd_info_entry *entry,
* monitor_name manufacture_id product_id * monitor_name manufacture_id product_id
* eld_version edid_version * eld_version edid_version
*/ */
if (!strcmp(name, "connection_type")) if (!strcmp(name, "monitor_present"))
e->monitor_present = val;
else if (!strcmp(name, "eld_valid"))
e->eld_valid = val;
else if (!strcmp(name, "connection_type"))
e->conn_type = val; e->conn_type = val;
else if (!strcmp(name, "port_id")) else if (!strcmp(name, "port_id"))
e->port_id = val; e->port_id = val;
...@@ -560,13 +561,14 @@ static void hdmi_write_eld_info(struct snd_info_entry *entry, ...@@ -560,13 +561,14 @@ static void hdmi_write_eld_info(struct snd_info_entry *entry,
} }
int snd_hda_eld_proc_new(struct hda_codec *codec, struct hdmi_eld *eld) int snd_hda_eld_proc_new(struct hda_codec *codec, struct hdmi_eld *eld,
int index)
{ {
char name[32]; char name[32];
struct snd_info_entry *entry; struct snd_info_entry *entry;
int err; int err;
snprintf(name, sizeof(name), "eld#%d", codec->addr); snprintf(name, sizeof(name), "eld#%d.%d", codec->addr, index);
err = snd_card_proc_new(codec->bus->card, name, &entry); err = snd_card_proc_new(codec->bus->card, name, &entry);
if (err < 0) if (err < 0)
return err; return err;
......
...@@ -727,7 +727,8 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node, ...@@ -727,7 +727,8 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node,
if (is_loopback) if (is_loopback)
add_input_loopback(codec, node->nid, HDA_INPUT, index); add_input_loopback(codec, node->nid, HDA_INPUT, index);
snd_printdd("[%s] NID=0x%x, DIR=IN, IDX=0x%x\n", name, node->nid, index); snd_printdd("[%s] NID=0x%x, DIR=IN, IDX=0x%x\n", name, node->nid, index);
err = snd_hda_ctl_add(codec, snd_ctl_new1(&knew, codec)); err = snd_hda_ctl_add(codec, node->nid,
snd_ctl_new1(&knew, codec));
if (err < 0) if (err < 0)
return err; return err;
created = 1; created = 1;
...@@ -737,7 +738,8 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node, ...@@ -737,7 +738,8 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node,
if (is_loopback) if (is_loopback)
add_input_loopback(codec, node->nid, HDA_OUTPUT, 0); add_input_loopback(codec, node->nid, HDA_OUTPUT, 0);
snd_printdd("[%s] NID=0x%x, DIR=OUT\n", name, node->nid); snd_printdd("[%s] NID=0x%x, DIR=OUT\n", name, node->nid);
err = snd_hda_ctl_add(codec, snd_ctl_new1(&knew, codec)); err = snd_hda_ctl_add(codec, node->nid,
snd_ctl_new1(&knew, codec));
if (err < 0) if (err < 0)
return err; return err;
created = 1; created = 1;
...@@ -751,7 +753,8 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node, ...@@ -751,7 +753,8 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node,
(node->amp_in_caps & AC_AMPCAP_NUM_STEPS)) { (node->amp_in_caps & AC_AMPCAP_NUM_STEPS)) {
knew = (struct snd_kcontrol_new)HDA_CODEC_VOLUME(name, node->nid, index, HDA_INPUT); knew = (struct snd_kcontrol_new)HDA_CODEC_VOLUME(name, node->nid, index, HDA_INPUT);
snd_printdd("[%s] NID=0x%x, DIR=IN, IDX=0x%x\n", name, node->nid, index); snd_printdd("[%s] NID=0x%x, DIR=IN, IDX=0x%x\n", name, node->nid, index);
err = snd_hda_ctl_add(codec, snd_ctl_new1(&knew, codec)); err = snd_hda_ctl_add(codec, node->nid,
snd_ctl_new1(&knew, codec));
if (err < 0) if (err < 0)
return err; return err;
created = 1; created = 1;
...@@ -759,7 +762,8 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node, ...@@ -759,7 +762,8 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node,
(node->amp_out_caps & AC_AMPCAP_NUM_STEPS)) { (node->amp_out_caps & AC_AMPCAP_NUM_STEPS)) {
knew = (struct snd_kcontrol_new)HDA_CODEC_VOLUME(name, node->nid, 0, HDA_OUTPUT); knew = (struct snd_kcontrol_new)HDA_CODEC_VOLUME(name, node->nid, 0, HDA_OUTPUT);
snd_printdd("[%s] NID=0x%x, DIR=OUT\n", name, node->nid); snd_printdd("[%s] NID=0x%x, DIR=OUT\n", name, node->nid);
err = snd_hda_ctl_add(codec, snd_ctl_new1(&knew, codec)); err = snd_hda_ctl_add(codec, node->nid,
snd_ctl_new1(&knew, codec));
if (err < 0) if (err < 0)
return err; return err;
created = 1; created = 1;
...@@ -857,7 +861,7 @@ static int build_input_controls(struct hda_codec *codec) ...@@ -857,7 +861,7 @@ static int build_input_controls(struct hda_codec *codec)
} }
/* create input MUX if multiple sources are available */ /* create input MUX if multiple sources are available */
err = snd_hda_ctl_add(codec, snd_ctl_new1(&cap_sel, codec)); err = snd_hda_ctl_add(codec, 0, snd_ctl_new1(&cap_sel, codec));
if (err < 0) if (err < 0)
return err; return err;
...@@ -875,7 +879,8 @@ static int build_input_controls(struct hda_codec *codec) ...@@ -875,7 +879,8 @@ static int build_input_controls(struct hda_codec *codec)
HDA_CODEC_VOLUME(name, adc_node->nid, HDA_CODEC_VOLUME(name, adc_node->nid,
spec->input_mux.items[i].index, spec->input_mux.items[i].index,
HDA_INPUT); HDA_INPUT);
err = snd_hda_ctl_add(codec, snd_ctl_new1(&knew, codec)); err = snd_hda_ctl_add(codec, adc_node->nid,
snd_ctl_new1(&knew, codec));
if (err < 0) if (err < 0)
return err; return err;
} }
......
...@@ -154,6 +154,44 @@ int /*__devinit*/ snd_hda_create_hwdep(struct hda_codec *codec) ...@@ -154,6 +154,44 @@ int /*__devinit*/ snd_hda_create_hwdep(struct hda_codec *codec)
return 0; return 0;
} }
#ifdef CONFIG_SND_HDA_POWER_SAVE
static ssize_t power_on_acct_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct snd_hwdep *hwdep = dev_get_drvdata(dev);
struct hda_codec *codec = hwdep->private_data;
snd_hda_update_power_acct(codec);
return sprintf(buf, "%u\n", jiffies_to_msecs(codec->power_on_acct));
}
static ssize_t power_off_acct_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct snd_hwdep *hwdep = dev_get_drvdata(dev);
struct hda_codec *codec = hwdep->private_data;
snd_hda_update_power_acct(codec);
return sprintf(buf, "%u\n", jiffies_to_msecs(codec->power_off_acct));
}
static struct device_attribute power_attrs[] = {
__ATTR_RO(power_on_acct),
__ATTR_RO(power_off_acct),
};
int snd_hda_hwdep_add_power_sysfs(struct hda_codec *codec)
{
struct snd_hwdep *hwdep = codec->hwdep;
int i;
for (i = 0; i < ARRAY_SIZE(power_attrs); i++)
snd_add_device_sysfs_file(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card,
hwdep->device, &power_attrs[i]);
return 0;
}
#endif /* CONFIG_SND_HDA_POWER_SAVE */
#ifdef CONFIG_SND_HDA_RECONFIG #ifdef CONFIG_SND_HDA_RECONFIG
/* /*
......
...@@ -60,10 +60,14 @@ static int bdl_pos_adj[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1}; ...@@ -60,10 +60,14 @@ static int bdl_pos_adj[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1};
static int probe_mask[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1}; static int probe_mask[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1};
static int probe_only[SNDRV_CARDS]; static int probe_only[SNDRV_CARDS];
static int single_cmd; static int single_cmd;
static int enable_msi; static int enable_msi = -1;
#ifdef CONFIG_SND_HDA_PATCH_LOADER #ifdef CONFIG_SND_HDA_PATCH_LOADER
static char *patch[SNDRV_CARDS]; static char *patch[SNDRV_CARDS];
#endif #endif
#ifdef CONFIG_SND_HDA_INPUT_BEEP
static int beep_mode[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] =
CONFIG_SND_HDA_INPUT_BEEP_MODE};
#endif
module_param_array(index, int, NULL, 0444); module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for Intel HD audio interface."); MODULE_PARM_DESC(index, "Index value for Intel HD audio interface.");
...@@ -91,6 +95,11 @@ MODULE_PARM_DESC(enable_msi, "Enable Message Signaled Interrupt (MSI)"); ...@@ -91,6 +95,11 @@ MODULE_PARM_DESC(enable_msi, "Enable Message Signaled Interrupt (MSI)");
module_param_array(patch, charp, NULL, 0444); module_param_array(patch, charp, NULL, 0444);
MODULE_PARM_DESC(patch, "Patch file for Intel HD audio interface."); MODULE_PARM_DESC(patch, "Patch file for Intel HD audio interface.");
#endif #endif
#ifdef CONFIG_SND_HDA_INPUT_BEEP
module_param_array(beep_mode, int, NULL, 0444);
MODULE_PARM_DESC(beep_mode, "Select HDA Beep registration mode "
"(0=off, 1=on, 2=mute switch on/off) (default=1).");
#endif
#ifdef CONFIG_SND_HDA_POWER_SAVE #ifdef CONFIG_SND_HDA_POWER_SAVE
static int power_save = CONFIG_SND_HDA_POWER_SAVE_DEFAULT; static int power_save = CONFIG_SND_HDA_POWER_SAVE_DEFAULT;
...@@ -404,6 +413,7 @@ struct azx { ...@@ -404,6 +413,7 @@ struct azx {
unsigned short codec_mask; unsigned short codec_mask;
int codec_probe_mask; /* copied from probe_mask option */ int codec_probe_mask; /* copied from probe_mask option */
struct hda_bus *bus; struct hda_bus *bus;
unsigned int beep_mode;
/* CORB/RIRB */ /* CORB/RIRB */
struct azx_rb corb; struct azx_rb corb;
...@@ -677,6 +687,14 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus, ...@@ -677,6 +687,14 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus,
} }
} }
if (!chip->polling_mode) {
snd_printk(KERN_WARNING SFX "azx_get_response timeout, "
"switching to polling mode: last cmd=0x%08x\n",
chip->last_cmd[addr]);
chip->polling_mode = 1;
goto again;
}
if (chip->msi) { if (chip->msi) {
snd_printk(KERN_WARNING SFX "No response from codec, " snd_printk(KERN_WARNING SFX "No response from codec, "
"disabling MSI: last cmd=0x%08x\n", "disabling MSI: last cmd=0x%08x\n",
...@@ -692,14 +710,6 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus, ...@@ -692,14 +710,6 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus,
goto again; goto again;
} }
if (!chip->polling_mode) {
snd_printk(KERN_WARNING SFX "azx_get_response timeout, "
"switching to polling mode: last cmd=0x%08x\n",
chip->last_cmd[addr]);
chip->polling_mode = 1;
goto again;
}
if (chip->probing) { if (chip->probing) {
/* If this critical timeout happens during the codec probing /* If this critical timeout happens during the codec probing
* phase, this is likely an access to a non-existing codec * phase, this is likely an access to a non-existing codec
...@@ -1404,6 +1414,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model) ...@@ -1404,6 +1414,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model)
err = snd_hda_codec_new(chip->bus, c, &codec); err = snd_hda_codec_new(chip->bus, c, &codec);
if (err < 0) if (err < 0)
continue; continue;
codec->beep_mode = chip->beep_mode;
codecs++; codecs++;
} }
} }
...@@ -2154,6 +2165,7 @@ static int azx_resume(struct pci_dev *pci) ...@@ -2154,6 +2165,7 @@ static int azx_resume(struct pci_dev *pci)
static int azx_halt(struct notifier_block *nb, unsigned long event, void *buf) static int azx_halt(struct notifier_block *nb, unsigned long event, void *buf)
{ {
struct azx *chip = container_of(nb, struct azx, reboot_notifier); struct azx *chip = container_of(nb, struct azx, reboot_notifier);
snd_hda_bus_reboot_notify(chip->bus);
azx_stop_chip(chip); azx_stop_chip(chip);
return NOTIFY_OK; return NOTIFY_OK;
} }
...@@ -2221,7 +2233,9 @@ static int azx_dev_free(struct snd_device *device) ...@@ -2221,7 +2233,9 @@ static int azx_dev_free(struct snd_device *device)
static struct snd_pci_quirk position_fix_list[] __devinitdata = { static struct snd_pci_quirk position_fix_list[] __devinitdata = {
SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB), SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB), SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB),
SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB), SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB),
{} {}
}; };
...@@ -2304,11 +2318,9 @@ static void __devinit check_probe_mask(struct azx *chip, int dev) ...@@ -2304,11 +2318,9 @@ static void __devinit check_probe_mask(struct azx *chip, int dev)
} }
/* /*
* white-list for enable_msi * white/black-list for enable_msi
*/ */
static struct snd_pci_quirk msi_white_list[] __devinitdata = { static struct snd_pci_quirk msi_black_list[] __devinitdata = {
SND_PCI_QUIRK(0x103c, 0x30f7, "HP Pavilion dv4t-1300", 1),
SND_PCI_QUIRK(0x103c, 0x3607, "HP Compa CQ40", 1),
{} {}
}; };
...@@ -2316,10 +2328,12 @@ static void __devinit check_msi(struct azx *chip) ...@@ -2316,10 +2328,12 @@ static void __devinit check_msi(struct azx *chip)
{ {
const struct snd_pci_quirk *q; const struct snd_pci_quirk *q;
chip->msi = enable_msi; if (enable_msi >= 0) {
if (chip->msi) chip->msi = !!enable_msi;
return; return;
q = snd_pci_quirk_lookup(chip->pci, msi_white_list); }
chip->msi = 1; /* enable MSI as default */
q = snd_pci_quirk_lookup(chip->pci, msi_black_list);
if (q) { if (q) {
printk(KERN_INFO printk(KERN_INFO
"hda_intel: msi for device %04x:%04x set to %d\n", "hda_intel: msi for device %04x:%04x set to %d\n",
...@@ -2578,6 +2592,10 @@ static int __devinit azx_probe(struct pci_dev *pci, ...@@ -2578,6 +2592,10 @@ static int __devinit azx_probe(struct pci_dev *pci,
goto out_free; goto out_free;
card->private_data = chip; card->private_data = chip;
#ifdef CONFIG_SND_HDA_INPUT_BEEP
chip->beep_mode = beep_mode[dev];
#endif
/* create codec instances */ /* create codec instances */
err = azx_codec_create(chip, model[dev]); err = azx_codec_create(chip, model[dev]);
if (err < 0) if (err < 0)
......
...@@ -23,6 +23,15 @@ ...@@ -23,6 +23,15 @@
#ifndef __SOUND_HDA_LOCAL_H #ifndef __SOUND_HDA_LOCAL_H
#define __SOUND_HDA_LOCAL_H #define __SOUND_HDA_LOCAL_H
/* We abuse kcontrol_new.subdev field to pass the NID corresponding to
* the given new control. If id.subdev has a bit flag HDA_SUBDEV_NID_FLAG,
* snd_hda_ctl_add() takes the lower-bit subdev value as a valid NID.
*
* Note that the subdevice field is cleared again before the real registration
* in snd_hda_ctl_add(), so that this value won't appear in the outside.
*/
#define HDA_SUBDEV_NID_FLAG (1U << 31)
/* /*
* for mixer controls * for mixer controls
*/ */
...@@ -33,6 +42,7 @@ ...@@ -33,6 +42,7 @@
/* mono volume with index (index=0,1,...) (channel=1,2) */ /* mono volume with index (index=0,1,...) (channel=1,2) */
#define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ #define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \
.subdevice = HDA_SUBDEV_NID_FLAG | (nid), \
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, \ SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, \
...@@ -53,6 +63,7 @@ ...@@ -53,6 +63,7 @@
/* mono mute switch with index (index=0,1,...) (channel=1,2) */ /* mono mute switch with index (index=0,1,...) (channel=1,2) */
#define HDA_CODEC_MUTE_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ #define HDA_CODEC_MUTE_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \
.subdevice = HDA_SUBDEV_NID_FLAG | (nid), \
.info = snd_hda_mixer_amp_switch_info, \ .info = snd_hda_mixer_amp_switch_info, \
.get = snd_hda_mixer_amp_switch_get, \ .get = snd_hda_mixer_amp_switch_get, \
.put = snd_hda_mixer_amp_switch_put, \ .put = snd_hda_mixer_amp_switch_put, \
...@@ -66,6 +77,28 @@ ...@@ -66,6 +77,28 @@
/* stereo mute switch */ /* stereo mute switch */
#define HDA_CODEC_MUTE(xname, nid, xindex, direction) \ #define HDA_CODEC_MUTE(xname, nid, xindex, direction) \
HDA_CODEC_MUTE_MONO(xname, nid, 3, xindex, direction) HDA_CODEC_MUTE_MONO(xname, nid, 3, xindex, direction)
#ifdef CONFIG_SND_HDA_INPUT_BEEP
/* special beep mono mute switch with index (index=0,1,...) (channel=1,2) */
#define HDA_CODEC_MUTE_BEEP_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \
.subdevice = HDA_SUBDEV_NID_FLAG | (nid), \
.info = snd_hda_mixer_amp_switch_info, \
.get = snd_hda_mixer_amp_switch_get, \
.put = snd_hda_mixer_amp_switch_put_beep, \
.private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, direction) }
#else
/* no digital beep - just the standard one */
#define HDA_CODEC_MUTE_BEEP_MONO_IDX(xname, xcidx, nid, ch, xidx, dir) \
HDA_CODEC_MUTE_MONO_IDX(xname, xcidx, nid, ch, xidx, dir)
#endif /* CONFIG_SND_HDA_INPUT_BEEP */
/* special beep mono mute switch */
#define HDA_CODEC_MUTE_BEEP_MONO(xname, nid, channel, xindex, direction) \
HDA_CODEC_MUTE_BEEP_MONO_IDX(xname, 0, nid, channel, xindex, direction)
/* special beep stereo mute switch */
#define HDA_CODEC_MUTE_BEEP(xname, nid, xindex, direction) \
HDA_CODEC_MUTE_BEEP_MONO(xname, nid, 3, xindex, direction)
extern const char *snd_hda_pcm_type_name[];
int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo); struct snd_ctl_elem_info *uinfo);
...@@ -81,6 +114,10 @@ int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol, ...@@ -81,6 +114,10 @@ int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol); struct snd_ctl_elem_value *ucontrol);
int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol); struct snd_ctl_elem_value *ucontrol);
#ifdef CONFIG_SND_HDA_INPUT_BEEP
int snd_hda_mixer_amp_switch_put_beep(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
#endif
/* lowlevel accessor with caching; use carefully */ /* lowlevel accessor with caching; use carefully */
int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch, int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch,
int direction, int index); int direction, int index);
...@@ -424,8 +461,16 @@ u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction); ...@@ -424,8 +461,16 @@ u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction);
int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
unsigned int caps); unsigned int caps);
u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid); u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid);
u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid);
int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid);
int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl); struct hda_nid_item {
struct snd_kcontrol *kctl;
hda_nid_t nid;
};
int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid,
struct snd_kcontrol *kctl);
void snd_hda_ctls_clear(struct hda_codec *codec); void snd_hda_ctls_clear(struct hda_codec *codec);
/* /*
...@@ -437,6 +482,15 @@ int snd_hda_create_hwdep(struct hda_codec *codec); ...@@ -437,6 +482,15 @@ int snd_hda_create_hwdep(struct hda_codec *codec);
static inline int snd_hda_create_hwdep(struct hda_codec *codec) { return 0; } static inline int snd_hda_create_hwdep(struct hda_codec *codec) { return 0; }
#endif #endif
#if defined(CONFIG_SND_HDA_POWER_SAVE) && defined(CONFIG_SND_HDA_HWDEP)
int snd_hda_hwdep_add_power_sysfs(struct hda_codec *codec);
#else
static inline int snd_hda_hwdep_add_power_sysfs(struct hda_codec *codec)
{
return 0;
}
#endif
#ifdef CONFIG_SND_HDA_RECONFIG #ifdef CONFIG_SND_HDA_RECONFIG
int snd_hda_hwdep_add_sysfs(struct hda_codec *codec); int snd_hda_hwdep_add_sysfs(struct hda_codec *codec);
#else #else
...@@ -490,7 +544,8 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec, ...@@ -490,7 +544,8 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec,
* AMP control callbacks * AMP control callbacks
*/ */
/* retrieve parameters from private_value */ /* retrieve parameters from private_value */
#define get_amp_nid(kc) ((kc)->private_value & 0xffff) #define get_amp_nid_(pv) ((pv) & 0xffff)
#define get_amp_nid(kc) get_amp_nid_((kc)->private_value)
#define get_amp_channels(kc) (((kc)->private_value >> 16) & 0x3) #define get_amp_channels(kc) (((kc)->private_value >> 16) & 0x3)
#define get_amp_direction(kc) (((kc)->private_value >> 18) & 0x1) #define get_amp_direction(kc) (((kc)->private_value >> 18) & 0x1)
#define get_amp_index(kc) (((kc)->private_value >> 19) & 0xf) #define get_amp_index(kc) (((kc)->private_value >> 19) & 0xf)
...@@ -516,9 +571,11 @@ struct cea_sad { ...@@ -516,9 +571,11 @@ struct cea_sad {
* ELD: EDID Like Data * ELD: EDID Like Data
*/ */
struct hdmi_eld { struct hdmi_eld {
bool monitor_present;
bool eld_valid;
int eld_size; int eld_size;
int baseline_len; int baseline_len;
int eld_ver; /* (eld_ver == 0) indicates invalid ELD */ int eld_ver;
int cea_edid_ver; int cea_edid_ver;
char monitor_name[ELD_MAX_MNL + 1]; char monitor_name[ELD_MAX_MNL + 1];
int manufacture_id; int manufacture_id;
...@@ -541,11 +598,13 @@ int snd_hdmi_get_eld(struct hdmi_eld *, struct hda_codec *, hda_nid_t); ...@@ -541,11 +598,13 @@ int snd_hdmi_get_eld(struct hdmi_eld *, struct hda_codec *, hda_nid_t);
void snd_hdmi_show_eld(struct hdmi_eld *eld); void snd_hdmi_show_eld(struct hdmi_eld *eld);
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
int snd_hda_eld_proc_new(struct hda_codec *codec, struct hdmi_eld *eld); int snd_hda_eld_proc_new(struct hda_codec *codec, struct hdmi_eld *eld,
int index);
void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld); void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld);
#else #else
static inline int snd_hda_eld_proc_new(struct hda_codec *codec, static inline int snd_hda_eld_proc_new(struct hda_codec *codec,
struct hdmi_eld *eld) struct hdmi_eld *eld,
int index)
{ {
return 0; return 0;
} }
......
...@@ -26,6 +26,21 @@ ...@@ -26,6 +26,21 @@
#include "hda_codec.h" #include "hda_codec.h"
#include "hda_local.h" #include "hda_local.h"
static char *bits_names(unsigned int bits, char *names[], int size)
{
int i, n;
static char buf[128];
for (i = 0, n = 0; i < size; i++) {
if (bits & (1U<<i) && names[i])
n += snprintf(buf + n, sizeof(buf) - n, " %s",
names[i]);
}
buf[n] = '\0';
return buf;
}
static const char *get_wid_type_name(unsigned int wid_value) static const char *get_wid_type_name(unsigned int wid_value)
{ {
static char *names[16] = { static char *names[16] = {
...@@ -46,6 +61,41 @@ static const char *get_wid_type_name(unsigned int wid_value) ...@@ -46,6 +61,41 @@ static const char *get_wid_type_name(unsigned int wid_value)
return "UNKNOWN Widget"; return "UNKNOWN Widget";
} }
static void print_nid_mixers(struct snd_info_buffer *buffer,
struct hda_codec *codec, hda_nid_t nid)
{
int i;
struct hda_nid_item *items = codec->mixers.list;
struct snd_kcontrol *kctl;
for (i = 0; i < codec->mixers.used; i++) {
if (items[i].nid == nid) {
kctl = items[i].kctl;
snd_iprintf(buffer,
" Control: name=\"%s\", index=%i, device=%i\n",
kctl->id.name, kctl->id.index, kctl->id.device);
}
}
}
static void print_nid_pcms(struct snd_info_buffer *buffer,
struct hda_codec *codec, hda_nid_t nid)
{
int pcm, type;
struct hda_pcm *cpcm;
for (pcm = 0; pcm < codec->num_pcms; pcm++) {
cpcm = &codec->pcm_info[pcm];
for (type = 0; type < 2; type++) {
if (cpcm->stream[type].nid != nid || cpcm->pcm == NULL)
continue;
snd_iprintf(buffer, " Device: name=\"%s\", "
"type=\"%s\", device=%i\n",
cpcm->name,
snd_hda_pcm_type_name[cpcm->pcm_type],
cpcm->pcm->device);
}
}
}
static void print_amp_caps(struct snd_info_buffer *buffer, static void print_amp_caps(struct snd_info_buffer *buffer,
struct hda_codec *codec, hda_nid_t nid, int dir) struct hda_codec *codec, hda_nid_t nid, int dir)
{ {
...@@ -363,8 +413,24 @@ static const char *get_pwr_state(u32 state) ...@@ -363,8 +413,24 @@ static const char *get_pwr_state(u32 state)
static void print_power_state(struct snd_info_buffer *buffer, static void print_power_state(struct snd_info_buffer *buffer,
struct hda_codec *codec, hda_nid_t nid) struct hda_codec *codec, hda_nid_t nid)
{ {
static char *names[] = {
[ilog2(AC_PWRST_D0SUP)] = "D0",
[ilog2(AC_PWRST_D1SUP)] = "D1",
[ilog2(AC_PWRST_D2SUP)] = "D2",
[ilog2(AC_PWRST_D3SUP)] = "D3",
[ilog2(AC_PWRST_D3COLDSUP)] = "D3cold",
[ilog2(AC_PWRST_S3D3COLDSUP)] = "S3D3cold",
[ilog2(AC_PWRST_CLKSTOP)] = "CLKSTOP",
[ilog2(AC_PWRST_EPSS)] = "EPSS",
};
int sup = snd_hda_param_read(codec, nid, AC_PAR_POWER_STATE);
int pwr = snd_hda_codec_read(codec, nid, 0, int pwr = snd_hda_codec_read(codec, nid, 0,
AC_VERB_GET_POWER_STATE, 0); AC_VERB_GET_POWER_STATE, 0);
if (sup)
snd_iprintf(buffer, " Power states: %s\n",
bits_names(sup, names, ARRAY_SIZE(names)));
snd_iprintf(buffer, " Power: setting=%s, actual=%s\n", snd_iprintf(buffer, " Power: setting=%s, actual=%s\n",
get_pwr_state(pwr & AC_PWRST_SETTING), get_pwr_state(pwr & AC_PWRST_SETTING),
get_pwr_state((pwr & AC_PWRST_ACTUAL) >> get_pwr_state((pwr & AC_PWRST_ACTUAL) >>
...@@ -457,6 +523,7 @@ static void print_gpio(struct snd_info_buffer *buffer, ...@@ -457,6 +523,7 @@ static void print_gpio(struct snd_info_buffer *buffer,
(data & (1<<i)) ? 1 : 0, (data & (1<<i)) ? 1 : 0,
(unsol & (1<<i)) ? 1 : 0); (unsol & (1<<i)) ? 1 : 0);
/* FIXME: add GPO and GPI pin information */ /* FIXME: add GPO and GPI pin information */
print_nid_mixers(buffer, codec, nid);
} }
static void print_codec_info(struct snd_info_entry *entry, static void print_codec_info(struct snd_info_entry *entry,
...@@ -536,6 +603,9 @@ static void print_codec_info(struct snd_info_entry *entry, ...@@ -536,6 +603,9 @@ static void print_codec_info(struct snd_info_entry *entry,
snd_iprintf(buffer, " CP"); snd_iprintf(buffer, " CP");
snd_iprintf(buffer, "\n"); snd_iprintf(buffer, "\n");
print_nid_mixers(buffer, codec, nid);
print_nid_pcms(buffer, codec, nid);
/* volume knob is a special widget that always have connection /* volume knob is a special widget that always have connection
* list * list
*/ */
......
...@@ -156,15 +156,19 @@ static const char *ad_slave_sws[] = { ...@@ -156,15 +156,19 @@ static const char *ad_slave_sws[] = {
static void ad198x_free_kctls(struct hda_codec *codec); static void ad198x_free_kctls(struct hda_codec *codec);
#ifdef CONFIG_SND_HDA_INPUT_BEEP
/* additional beep mixers; the actual parameters are overwritten at build */ /* additional beep mixers; the actual parameters are overwritten at build */
static struct snd_kcontrol_new ad_beep_mixer[] = { static struct snd_kcontrol_new ad_beep_mixer[] = {
HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_OUTPUT), HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_OUTPUT),
HDA_CODEC_MUTE("Beep Playback Switch", 0, 0, HDA_OUTPUT), HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_OUTPUT),
{ } /* end */ { } /* end */
}; };
#define set_beep_amp(spec, nid, idx, dir) \ #define set_beep_amp(spec, nid, idx, dir) \
((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir)) /* mono */ ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir)) /* mono */
#else
#define set_beep_amp(spec, nid, idx, dir) /* NOP */
#endif
static int ad198x_build_controls(struct hda_codec *codec) static int ad198x_build_controls(struct hda_codec *codec)
{ {
...@@ -194,6 +198,7 @@ static int ad198x_build_controls(struct hda_codec *codec) ...@@ -194,6 +198,7 @@ static int ad198x_build_controls(struct hda_codec *codec)
} }
/* create beep controls if needed */ /* create beep controls if needed */
#ifdef CONFIG_SND_HDA_INPUT_BEEP
if (spec->beep_amp) { if (spec->beep_amp) {
struct snd_kcontrol_new *knew; struct snd_kcontrol_new *knew;
for (knew = ad_beep_mixer; knew->name; knew++) { for (knew = ad_beep_mixer; knew->name; knew++) {
...@@ -202,11 +207,14 @@ static int ad198x_build_controls(struct hda_codec *codec) ...@@ -202,11 +207,14 @@ static int ad198x_build_controls(struct hda_codec *codec)
if (!kctl) if (!kctl)
return -ENOMEM; return -ENOMEM;
kctl->private_value = spec->beep_amp; kctl->private_value = spec->beep_amp;
err = snd_hda_ctl_add(codec, kctl); err = snd_hda_ctl_add(codec,
get_amp_nid_(spec->beep_amp),
kctl);
if (err < 0) if (err < 0)
return err; return err;
} }
} }
#endif
/* if we have no master control, let's create it */ /* if we have no master control, let's create it */
if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) { if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
...@@ -712,10 +720,10 @@ static struct snd_kcontrol_new ad1986a_laptop_intmic_mixers[] = { ...@@ -712,10 +720,10 @@ static struct snd_kcontrol_new ad1986a_laptop_intmic_mixers[] = {
static void ad1986a_automic(struct hda_codec *codec) static void ad1986a_automic(struct hda_codec *codec)
{ {
unsigned int present; unsigned int present;
present = snd_hda_codec_read(codec, 0x1f, 0, AC_VERB_GET_PIN_SENSE, 0); present = snd_hda_jack_detect(codec, 0x1f);
/* 0 = 0x1f, 2 = 0x1d, 4 = mixed */ /* 0 = 0x1f, 2 = 0x1d, 4 = mixed */
snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_CONNECT_SEL, snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_CONNECT_SEL,
(present & AC_PINSENSE_PRESENCE) ? 0 : 2); present ? 0 : 2);
} }
#define AD1986A_MIC_EVENT 0x36 #define AD1986A_MIC_EVENT 0x36
...@@ -754,10 +762,8 @@ static void ad1986a_update_hp(struct hda_codec *codec) ...@@ -754,10 +762,8 @@ static void ad1986a_update_hp(struct hda_codec *codec)
static void ad1986a_hp_automute(struct hda_codec *codec) static void ad1986a_hp_automute(struct hda_codec *codec)
{ {
struct ad198x_spec *spec = codec->spec; struct ad198x_spec *spec = codec->spec;
unsigned int present;
present = snd_hda_codec_read(codec, 0x1a, 0, AC_VERB_GET_PIN_SENSE, 0); spec->jack_present = snd_hda_jack_detect(codec, 0x1a);
spec->jack_present = !!(present & 0x80000000);
if (spec->inv_jack_detect) if (spec->inv_jack_detect)
spec->jack_present = !spec->jack_present; spec->jack_present = !spec->jack_present;
ad1986a_update_hp(codec); ad1986a_update_hp(codec);
...@@ -1547,8 +1553,7 @@ static void ad1981_hp_automute(struct hda_codec *codec) ...@@ -1547,8 +1553,7 @@ static void ad1981_hp_automute(struct hda_codec *codec)
{ {
unsigned int present; unsigned int present;
present = snd_hda_codec_read(codec, 0x06, 0, present = snd_hda_jack_detect(codec, 0x06);
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
snd_hda_codec_amp_stereo(codec, 0x05, HDA_OUTPUT, 0, snd_hda_codec_amp_stereo(codec, 0x05, HDA_OUTPUT, 0,
HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
} }
...@@ -1568,8 +1573,7 @@ static void ad1981_hp_automic(struct hda_codec *codec) ...@@ -1568,8 +1573,7 @@ static void ad1981_hp_automic(struct hda_codec *codec)
}; };
unsigned int present; unsigned int present;
present = snd_hda_codec_read(codec, 0x08, 0, present = snd_hda_jack_detect(codec, 0x08);
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
if (present) if (present)
snd_hda_sequence_write(codec, mic_jack_on); snd_hda_sequence_write(codec, mic_jack_on);
else else
...@@ -2524,7 +2528,7 @@ static void ad1988_laptop_unsol_event(struct hda_codec *codec, unsigned int res) ...@@ -2524,7 +2528,7 @@ static void ad1988_laptop_unsol_event(struct hda_codec *codec, unsigned int res)
{ {
if ((res >> 26) != AD1988_HP_EVENT) if ((res >> 26) != AD1988_HP_EVENT)
return; return;
if (snd_hda_codec_read(codec, 0x11, 0, AC_VERB_GET_PIN_SENSE, 0) & (1 << 31)) if (snd_hda_jack_detect(codec, 0x11))
snd_hda_sequence_write(codec, ad1988_laptop_hp_on); snd_hda_sequence_write(codec, ad1988_laptop_hp_on);
else else
snd_hda_sequence_write(codec, ad1988_laptop_hp_off); snd_hda_sequence_write(codec, ad1988_laptop_hp_off);
...@@ -2569,6 +2573,8 @@ static int add_control(struct ad198x_spec *spec, int type, const char *name, ...@@ -2569,6 +2573,8 @@ static int add_control(struct ad198x_spec *spec, int type, const char *name,
knew->name = kstrdup(name, GFP_KERNEL); knew->name = kstrdup(name, GFP_KERNEL);
if (! knew->name) if (! knew->name)
return -ENOMEM; return -ENOMEM;
if (get_amp_nid_(val))
knew->subdevice = HDA_SUBDEV_NID_FLAG | get_amp_nid_(val);
knew->private_value = val; knew->private_value = val;
return 0; return 0;
} }
...@@ -3768,8 +3774,7 @@ static void ad1884a_hp_automute(struct hda_codec *codec) ...@@ -3768,8 +3774,7 @@ static void ad1884a_hp_automute(struct hda_codec *codec)
{ {
unsigned int present; unsigned int present;
present = snd_hda_codec_read(codec, 0x11, 0, present = snd_hda_jack_detect(codec, 0x11);
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0, snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE, snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
...@@ -3781,8 +3786,7 @@ static void ad1884a_hp_automic(struct hda_codec *codec) ...@@ -3781,8 +3786,7 @@ static void ad1884a_hp_automic(struct hda_codec *codec)
{ {
unsigned int present; unsigned int present;
present = snd_hda_codec_read(codec, 0x14, 0, present = snd_hda_jack_detect(codec, 0x14);
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL, snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL,
present ? 0 : 1); present ? 0 : 1);
} }
...@@ -3817,13 +3821,9 @@ static void ad1884a_laptop_automute(struct hda_codec *codec) ...@@ -3817,13 +3821,9 @@ static void ad1884a_laptop_automute(struct hda_codec *codec)
{ {
unsigned int present; unsigned int present;
present = snd_hda_codec_read(codec, 0x11, 0, AC_VERB_GET_PIN_SENSE, 0); present = snd_hda_jack_detect(codec, 0x11);
present &= AC_PINSENSE_PRESENCE; if (!present)
if (!present) { present = snd_hda_jack_detect(codec, 0x12);
present = snd_hda_codec_read(codec, 0x12, 0,
AC_VERB_GET_PIN_SENSE, 0);
present &= AC_PINSENSE_PRESENCE;
}
snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0, snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE, snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE,
...@@ -3835,11 +3835,9 @@ static void ad1884a_laptop_automic(struct hda_codec *codec) ...@@ -3835,11 +3835,9 @@ static void ad1884a_laptop_automic(struct hda_codec *codec)
{ {
unsigned int idx; unsigned int idx;
if (snd_hda_codec_read(codec, 0x14, 0, AC_VERB_GET_PIN_SENSE, 0) & if (snd_hda_jack_detect(codec, 0x14))
AC_PINSENSE_PRESENCE)
idx = 0; idx = 0;
else if (snd_hda_codec_read(codec, 0x1c, 0, AC_VERB_GET_PIN_SENSE, 0) & else if (snd_hda_jack_detect(codec, 0x1c))
AC_PINSENSE_PRESENCE)
idx = 4; idx = 4;
else else
idx = 1; idx = 1;
...@@ -4008,8 +4006,7 @@ static void ad1984a_thinkpad_automute(struct hda_codec *codec) ...@@ -4008,8 +4006,7 @@ static void ad1984a_thinkpad_automute(struct hda_codec *codec)
{ {
unsigned int present; unsigned int present;
present = snd_hda_codec_read(codec, 0x11, 0, AC_VERB_GET_PIN_SENSE, 0) present = snd_hda_jack_detect(codec, 0x11);
& AC_PINSENSE_PRESENCE;
snd_hda_codec_amp_stereo(codec, 0x12, HDA_OUTPUT, 0, snd_hda_codec_amp_stereo(codec, 0x12, HDA_OUTPUT, 0,
HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
} }
...@@ -4117,14 +4114,12 @@ static struct snd_kcontrol_new ad1984a_touchsmart_mixers[] = { ...@@ -4117,14 +4114,12 @@ static struct snd_kcontrol_new ad1984a_touchsmart_mixers[] = {
/* switch to external mic if plugged */ /* switch to external mic if plugged */
static void ad1984a_touchsmart_automic(struct hda_codec *codec) static void ad1984a_touchsmart_automic(struct hda_codec *codec)
{ {
if (snd_hda_codec_read(codec, 0x1c, 0, if (snd_hda_jack_detect(codec, 0x1c))
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000) {
snd_hda_codec_write(codec, 0x0c, 0, snd_hda_codec_write(codec, 0x0c, 0,
AC_VERB_SET_CONNECT_SEL, 0x4); AC_VERB_SET_CONNECT_SEL, 0x4);
} else { else
snd_hda_codec_write(codec, 0x0c, 0, snd_hda_codec_write(codec, 0x0c, 0,
AC_VERB_SET_CONNECT_SEL, 0x5); AC_VERB_SET_CONNECT_SEL, 0x5);
}
} }
......
...@@ -144,7 +144,7 @@ static int _add_switch(struct hda_codec *codec, hda_nid_t nid, const char *pfx, ...@@ -144,7 +144,7 @@ static int _add_switch(struct hda_codec *codec, hda_nid_t nid, const char *pfx,
struct snd_kcontrol_new knew = struct snd_kcontrol_new knew =
HDA_CODEC_MUTE_MONO(namestr, nid, chan, 0, type); HDA_CODEC_MUTE_MONO(namestr, nid, chan, 0, type);
sprintf(namestr, "%s %s Switch", pfx, dirstr[dir]); sprintf(namestr, "%s %s Switch", pfx, dirstr[dir]);
return snd_hda_ctl_add(codec, snd_ctl_new1(&knew, codec)); return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec));
} }
static int _add_volume(struct hda_codec *codec, hda_nid_t nid, const char *pfx, static int _add_volume(struct hda_codec *codec, hda_nid_t nid, const char *pfx,
...@@ -155,7 +155,7 @@ static int _add_volume(struct hda_codec *codec, hda_nid_t nid, const char *pfx, ...@@ -155,7 +155,7 @@ static int _add_volume(struct hda_codec *codec, hda_nid_t nid, const char *pfx,
struct snd_kcontrol_new knew = struct snd_kcontrol_new knew =
HDA_CODEC_VOLUME_MONO(namestr, nid, chan, 0, type); HDA_CODEC_VOLUME_MONO(namestr, nid, chan, 0, type);
sprintf(namestr, "%s %s Volume", pfx, dirstr[dir]); sprintf(namestr, "%s %s Volume", pfx, dirstr[dir]);
return snd_hda_ctl_add(codec, snd_ctl_new1(&knew, codec)); return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec));
} }
#define add_out_switch(codec, nid, pfx) _add_switch(codec, nid, pfx, 3, 0) #define add_out_switch(codec, nid, pfx) _add_switch(codec, nid, pfx, 3, 0)
......
...@@ -500,7 +500,7 @@ static int add_mute(struct hda_codec *codec, const char *name, int index, ...@@ -500,7 +500,7 @@ static int add_mute(struct hda_codec *codec, const char *name, int index,
knew.private_value = pval; knew.private_value = pval;
snprintf(tmp, sizeof(tmp), "%s %s Switch", name, dir_sfx[dir]); snprintf(tmp, sizeof(tmp), "%s %s Switch", name, dir_sfx[dir]);
*kctlp = snd_ctl_new1(&knew, codec); *kctlp = snd_ctl_new1(&knew, codec);
return snd_hda_ctl_add(codec, *kctlp); return snd_hda_ctl_add(codec, get_amp_nid_(pval), *kctlp);
} }
static int add_volume(struct hda_codec *codec, const char *name, static int add_volume(struct hda_codec *codec, const char *name,
...@@ -513,7 +513,7 @@ static int add_volume(struct hda_codec *codec, const char *name, ...@@ -513,7 +513,7 @@ static int add_volume(struct hda_codec *codec, const char *name,
knew.private_value = pval; knew.private_value = pval;
snprintf(tmp, sizeof(tmp), "%s %s Volume", name, dir_sfx[dir]); snprintf(tmp, sizeof(tmp), "%s %s Volume", name, dir_sfx[dir]);
*kctlp = snd_ctl_new1(&knew, codec); *kctlp = snd_ctl_new1(&knew, codec);
return snd_hda_ctl_add(codec, *kctlp); return snd_hda_ctl_add(codec, get_amp_nid_(pval), *kctlp);
} }
static void fix_volume_caps(struct hda_codec *codec, hda_nid_t dac) static void fix_volume_caps(struct hda_codec *codec, hda_nid_t dac)
...@@ -536,14 +536,14 @@ static int add_vmaster(struct hda_codec *codec, hda_nid_t dac) ...@@ -536,14 +536,14 @@ static int add_vmaster(struct hda_codec *codec, hda_nid_t dac)
spec->vmaster_sw = spec->vmaster_sw =
snd_ctl_make_virtual_master("Master Playback Switch", NULL); snd_ctl_make_virtual_master("Master Playback Switch", NULL);
err = snd_hda_ctl_add(codec, spec->vmaster_sw); err = snd_hda_ctl_add(codec, dac, spec->vmaster_sw);
if (err < 0) if (err < 0)
return err; return err;
snd_hda_set_vmaster_tlv(codec, dac, HDA_OUTPUT, tlv); snd_hda_set_vmaster_tlv(codec, dac, HDA_OUTPUT, tlv);
spec->vmaster_vol = spec->vmaster_vol =
snd_ctl_make_virtual_master("Master Playback Volume", tlv); snd_ctl_make_virtual_master("Master Playback Volume", tlv);
err = snd_hda_ctl_add(codec, spec->vmaster_vol); err = snd_hda_ctl_add(codec, dac, spec->vmaster_vol);
if (err < 0) if (err < 0)
return err; return err;
return 0; return 0;
...@@ -756,13 +756,13 @@ static int build_input(struct hda_codec *codec) ...@@ -756,13 +756,13 @@ static int build_input(struct hda_codec *codec)
if (!kctl) if (!kctl)
return -ENOMEM; return -ENOMEM;
kctl->private_value = (long)spec->capture_bind[i]; kctl->private_value = (long)spec->capture_bind[i];
err = snd_hda_ctl_add(codec, kctl); err = snd_hda_ctl_add(codec, 0, kctl);
if (err < 0) if (err < 0)
return err; return err;
} }
if (spec->num_inputs > 1 && !spec->mic_detect) { if (spec->num_inputs > 1 && !spec->mic_detect) {
err = snd_hda_ctl_add(codec, err = snd_hda_ctl_add(codec, 0,
snd_ctl_new1(&cs_capture_source, codec)); snd_ctl_new1(&cs_capture_source, codec));
if (err < 0) if (err < 0)
return err; return err;
...@@ -807,7 +807,7 @@ static void cs_automute(struct hda_codec *codec) ...@@ -807,7 +807,7 @@ static void cs_automute(struct hda_codec *codec)
{ {
struct cs_spec *spec = codec->spec; struct cs_spec *spec = codec->spec;
struct auto_pin_cfg *cfg = &spec->autocfg; struct auto_pin_cfg *cfg = &spec->autocfg;
unsigned int caps, present, hp_present; unsigned int caps, hp_present;
hda_nid_t nid; hda_nid_t nid;
int i; int i;
...@@ -817,12 +817,7 @@ static void cs_automute(struct hda_codec *codec) ...@@ -817,12 +817,7 @@ static void cs_automute(struct hda_codec *codec)
caps = snd_hda_query_pin_caps(codec, nid); caps = snd_hda_query_pin_caps(codec, nid);
if (!(caps & AC_PINCAP_PRES_DETECT)) if (!(caps & AC_PINCAP_PRES_DETECT))
continue; continue;
if (caps & AC_PINCAP_TRIG_REQ) hp_present = snd_hda_jack_detect(codec, nid);
snd_hda_codec_read(codec, nid, 0,
AC_VERB_SET_PIN_SENSE, 0);
present = snd_hda_codec_read(codec, nid, 0,
AC_VERB_GET_PIN_SENSE, 0);
hp_present |= (present & AC_PINSENSE_PRESENCE) != 0;
if (hp_present) if (hp_present)
break; break;
} }
...@@ -844,15 +839,11 @@ static void cs_automic(struct hda_codec *codec) ...@@ -844,15 +839,11 @@ static void cs_automic(struct hda_codec *codec)
struct cs_spec *spec = codec->spec; struct cs_spec *spec = codec->spec;
struct auto_pin_cfg *cfg = &spec->autocfg; struct auto_pin_cfg *cfg = &spec->autocfg;
hda_nid_t nid; hda_nid_t nid;
unsigned int caps, present; unsigned int present;
nid = cfg->input_pins[spec->automic_idx]; nid = cfg->input_pins[spec->automic_idx];
caps = snd_hda_query_pin_caps(codec, nid); present = snd_hda_jack_detect(codec, nid);
if (caps & AC_PINCAP_TRIG_REQ) if (present)
snd_hda_codec_read(codec, nid, 0, AC_VERB_SET_PIN_SENSE, 0);
present = snd_hda_codec_read(codec, nid, 0,
AC_VERB_GET_PIN_SENSE, 0);
if (present & AC_PINSENSE_PRESENCE)
change_cur_input(codec, spec->automic_idx, 0); change_cur_input(codec, spec->automic_idx, 0);
else { else {
unsigned int imic = (spec->automic_idx == AUTO_PIN_MIC) ? unsigned int imic = (spec->automic_idx == AUTO_PIN_MIC) ?
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -93,6 +93,7 @@ enum { ...@@ -93,6 +93,7 @@ enum {
STAC_92HD83XXX_REF, STAC_92HD83XXX_REF,
STAC_92HD83XXX_PWR_REF, STAC_92HD83XXX_PWR_REF,
STAC_DELL_S14, STAC_DELL_S14,
STAC_92HD83XXX_HP,
STAC_92HD83XXX_MODELS STAC_92HD83XXX_MODELS
}; };
...@@ -1085,7 +1086,7 @@ static int stac92xx_build_controls(struct hda_codec *codec) ...@@ -1085,7 +1086,7 @@ static int stac92xx_build_controls(struct hda_codec *codec)
if (!spec->auto_mic && spec->num_dmuxes > 0 && if (!spec->auto_mic && spec->num_dmuxes > 0 &&
snd_hda_get_bool_hint(codec, "separate_dmux") == 1) { snd_hda_get_bool_hint(codec, "separate_dmux") == 1) {
stac_dmux_mixer.count = spec->num_dmuxes; stac_dmux_mixer.count = spec->num_dmuxes;
err = snd_hda_ctl_add(codec, err = snd_hda_ctl_add(codec, 0,
snd_ctl_new1(&stac_dmux_mixer, codec)); snd_ctl_new1(&stac_dmux_mixer, codec));
if (err < 0) if (err < 0)
return err; return err;
...@@ -1101,7 +1102,7 @@ static int stac92xx_build_controls(struct hda_codec *codec) ...@@ -1101,7 +1102,7 @@ static int stac92xx_build_controls(struct hda_codec *codec)
spec->spdif_mute = 1; spec->spdif_mute = 1;
} }
stac_smux_mixer.count = spec->num_smuxes; stac_smux_mixer.count = spec->num_smuxes;
err = snd_hda_ctl_add(codec, err = snd_hda_ctl_add(codec, 0,
snd_ctl_new1(&stac_smux_mixer, codec)); snd_ctl_new1(&stac_smux_mixer, codec));
if (err < 0) if (err < 0)
return err; return err;
...@@ -1624,6 +1625,7 @@ static const char *stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = { ...@@ -1624,6 +1625,7 @@ static const char *stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = {
[STAC_92HD83XXX_REF] = "ref", [STAC_92HD83XXX_REF] = "ref",
[STAC_92HD83XXX_PWR_REF] = "mic-ref", [STAC_92HD83XXX_PWR_REF] = "mic-ref",
[STAC_DELL_S14] = "dell-s14", [STAC_DELL_S14] = "dell-s14",
[STAC_92HD83XXX_HP] = "hp",
}; };
static struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { static struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = {
...@@ -1634,6 +1636,8 @@ static struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { ...@@ -1634,6 +1636,8 @@ static struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = {
"DFI LanParty", STAC_92HD83XXX_REF), "DFI LanParty", STAC_92HD83XXX_REF),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ba, SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ba,
"unknown Dell", STAC_DELL_S14), "unknown Dell", STAC_DELL_S14),
SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xff00, 0x3600,
"HP", STAC_92HD83XXX_HP),
{} /* terminator */ {} /* terminator */
}; };
...@@ -2648,6 +2652,7 @@ static int stac92xx_clfe_switch_put(struct snd_kcontrol *kcontrol, ...@@ -2648,6 +2652,7 @@ static int stac92xx_clfe_switch_put(struct snd_kcontrol *kcontrol,
enum { enum {
STAC_CTL_WIDGET_VOL, STAC_CTL_WIDGET_VOL,
STAC_CTL_WIDGET_MUTE, STAC_CTL_WIDGET_MUTE,
STAC_CTL_WIDGET_MUTE_BEEP,
STAC_CTL_WIDGET_MONO_MUX, STAC_CTL_WIDGET_MONO_MUX,
STAC_CTL_WIDGET_HP_SWITCH, STAC_CTL_WIDGET_HP_SWITCH,
STAC_CTL_WIDGET_IO_SWITCH, STAC_CTL_WIDGET_IO_SWITCH,
...@@ -2658,6 +2663,7 @@ enum { ...@@ -2658,6 +2663,7 @@ enum {
static struct snd_kcontrol_new stac92xx_control_templates[] = { static struct snd_kcontrol_new stac92xx_control_templates[] = {
HDA_CODEC_VOLUME(NULL, 0, 0, 0), HDA_CODEC_VOLUME(NULL, 0, 0, 0),
HDA_CODEC_MUTE(NULL, 0, 0, 0), HDA_CODEC_MUTE(NULL, 0, 0, 0),
HDA_CODEC_MUTE_BEEP(NULL, 0, 0, 0),
STAC_MONO_MUX, STAC_MONO_MUX,
STAC_CODEC_HP_SWITCH(NULL), STAC_CODEC_HP_SWITCH(NULL),
STAC_CODEC_IO_SWITCH(NULL, 0), STAC_CODEC_IO_SWITCH(NULL, 0),
...@@ -2669,7 +2675,8 @@ static struct snd_kcontrol_new stac92xx_control_templates[] = { ...@@ -2669,7 +2675,8 @@ static struct snd_kcontrol_new stac92xx_control_templates[] = {
static struct snd_kcontrol_new * static struct snd_kcontrol_new *
stac_control_new(struct sigmatel_spec *spec, stac_control_new(struct sigmatel_spec *spec,
struct snd_kcontrol_new *ktemp, struct snd_kcontrol_new *ktemp,
const char *name) const char *name,
hda_nid_t nid)
{ {
struct snd_kcontrol_new *knew; struct snd_kcontrol_new *knew;
...@@ -2685,6 +2692,8 @@ stac_control_new(struct sigmatel_spec *spec, ...@@ -2685,6 +2692,8 @@ stac_control_new(struct sigmatel_spec *spec,
spec->kctls.alloced--; spec->kctls.alloced--;
return NULL; return NULL;
} }
if (nid)
knew->subdevice = HDA_SUBDEV_NID_FLAG | nid;
return knew; return knew;
} }
...@@ -2693,7 +2702,8 @@ static int stac92xx_add_control_temp(struct sigmatel_spec *spec, ...@@ -2693,7 +2702,8 @@ static int stac92xx_add_control_temp(struct sigmatel_spec *spec,
int idx, const char *name, int idx, const char *name,
unsigned long val) unsigned long val)
{ {
struct snd_kcontrol_new *knew = stac_control_new(spec, ktemp, name); struct snd_kcontrol_new *knew = stac_control_new(spec, ktemp, name,
get_amp_nid_(val));
if (!knew) if (!knew)
return -ENOMEM; return -ENOMEM;
knew->index = idx; knew->index = idx;
...@@ -2764,7 +2774,7 @@ static int stac92xx_add_input_source(struct sigmatel_spec *spec) ...@@ -2764,7 +2774,7 @@ static int stac92xx_add_input_source(struct sigmatel_spec *spec)
if (!spec->num_adcs || imux->num_items <= 1) if (!spec->num_adcs || imux->num_items <= 1)
return 0; /* no need for input source control */ return 0; /* no need for input source control */
knew = stac_control_new(spec, &stac_input_src_temp, knew = stac_control_new(spec, &stac_input_src_temp,
stac_input_src_temp.name); stac_input_src_temp.name, 0);
if (!knew) if (!knew)
return -ENOMEM; return -ENOMEM;
knew->count = spec->num_adcs; knew->count = spec->num_adcs;
...@@ -3221,11 +3231,14 @@ static int stac92xx_auto_create_beep_ctls(struct hda_codec *codec, ...@@ -3221,11 +3231,14 @@ static int stac92xx_auto_create_beep_ctls(struct hda_codec *codec,
{ {
struct sigmatel_spec *spec = codec->spec; struct sigmatel_spec *spec = codec->spec;
u32 caps = query_amp_caps(codec, nid, HDA_OUTPUT); u32 caps = query_amp_caps(codec, nid, HDA_OUTPUT);
int err; int err, type = STAC_CTL_WIDGET_MUTE_BEEP;
if (spec->anabeep_nid == nid)
type = STAC_CTL_WIDGET_MUTE;
/* check for mute support for the the amp */ /* check for mute support for the the amp */
if ((caps & AC_AMPCAP_MUTE) >> AC_AMPCAP_MUTE_SHIFT) { if ((caps & AC_AMPCAP_MUTE) >> AC_AMPCAP_MUTE_SHIFT) {
err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, err = stac92xx_add_control(spec, type,
"Beep Playback Switch", "Beep Playback Switch",
HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT)); HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT));
if (err < 0) if (err < 0)
...@@ -3258,12 +3271,7 @@ static int stac92xx_dig_beep_switch_put(struct snd_kcontrol *kcontrol, ...@@ -3258,12 +3271,7 @@ static int stac92xx_dig_beep_switch_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
int enabled = !!ucontrol->value.integer.value[0]; return snd_hda_enable_beep_device(codec, ucontrol->value.integer.value[0]);
if (codec->beep->enabled != enabled) {
codec->beep->enabled = enabled;
return 1;
}
return 0;
} }
static struct snd_kcontrol_new stac92xx_dig_beep_ctrl = { static struct snd_kcontrol_new stac92xx_dig_beep_ctrl = {
...@@ -3631,6 +3639,26 @@ static void stac92xx_auto_init_hp_out(struct hda_codec *codec) ...@@ -3631,6 +3639,26 @@ static void stac92xx_auto_init_hp_out(struct hda_codec *codec)
} }
} }
static int is_dual_headphones(struct hda_codec *codec)
{
struct sigmatel_spec *spec = codec->spec;
int i, valid_hps;
if (spec->autocfg.line_out_type != AUTO_PIN_SPEAKER_OUT ||
spec->autocfg.hp_outs <= 1)
return 0;
valid_hps = 0;
for (i = 0; i < spec->autocfg.hp_outs; i++) {
hda_nid_t nid = spec->autocfg.hp_pins[i];
unsigned int cfg = snd_hda_codec_get_pincfg(codec, nid);
if (get_defcfg_location(cfg) & AC_JACK_LOC_SEPARATE)
continue;
valid_hps++;
}
return (valid_hps > 1);
}
static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out, hda_nid_t dig_in) static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out, hda_nid_t dig_in)
{ {
struct sigmatel_spec *spec = codec->spec; struct sigmatel_spec *spec = codec->spec;
...@@ -3647,8 +3675,7 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out ...@@ -3647,8 +3675,7 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out
/* If we have no real line-out pin and multiple hp-outs, HPs should /* If we have no real line-out pin and multiple hp-outs, HPs should
* be set up as multi-channel outputs. * be set up as multi-channel outputs.
*/ */
if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT && if (is_dual_headphones(codec)) {
spec->autocfg.hp_outs > 1) {
/* Copy hp_outs to line_outs, backup line_outs in /* Copy hp_outs to line_outs, backup line_outs in
* speaker_outs so that the following routines can handle * speaker_outs so that the following routines can handle
* HP pins as primary outputs. * HP pins as primary outputs.
...@@ -4329,6 +4356,28 @@ static void stac92xx_free_kctls(struct hda_codec *codec) ...@@ -4329,6 +4356,28 @@ static void stac92xx_free_kctls(struct hda_codec *codec)
snd_array_free(&spec->kctls); snd_array_free(&spec->kctls);
} }
static void stac92xx_shutup(struct hda_codec *codec)
{
struct sigmatel_spec *spec = codec->spec;
int i;
hda_nid_t nid;
/* reset each pin before powering down DAC/ADC to avoid click noise */
nid = codec->start_nid;
for (i = 0; i < codec->num_nodes; i++, nid++) {
unsigned int wcaps = get_wcaps(codec, nid);
unsigned int wid_type = get_wcaps_type(wcaps);
if (wid_type == AC_WID_PIN)
snd_hda_codec_read(codec, nid, 0,
AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
}
if (spec->eapd_mask)
stac_gpio_set(codec, spec->gpio_mask,
spec->gpio_dir, spec->gpio_data &
~spec->eapd_mask);
}
static void stac92xx_free(struct hda_codec *codec) static void stac92xx_free(struct hda_codec *codec)
{ {
struct sigmatel_spec *spec = codec->spec; struct sigmatel_spec *spec = codec->spec;
...@@ -4336,6 +4385,7 @@ static void stac92xx_free(struct hda_codec *codec) ...@@ -4336,6 +4385,7 @@ static void stac92xx_free(struct hda_codec *codec)
if (! spec) if (! spec)
return; return;
stac92xx_shutup(codec);
stac92xx_free_jacks(codec); stac92xx_free_jacks(codec);
snd_array_free(&spec->events); snd_array_free(&spec->events);
...@@ -4386,12 +4436,16 @@ static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid, ...@@ -4386,12 +4436,16 @@ static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid,
pin_ctl & ~flag); pin_ctl & ~flag);
} }
static int get_pin_presence(struct hda_codec *codec, hda_nid_t nid) static inline int get_pin_presence(struct hda_codec *codec, hda_nid_t nid)
{ {
if (!nid) if (!nid)
return 0; return 0;
if (snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_SENSE, 0x00) /* NOTE: we can't use snd_hda_jack_detect() here because STAC/IDT
& (1 << 31)) * codecs behave wrongly when SET_PIN_SENSE is triggered, although
* the pincap gives TRIG_REQ bit.
*/
if (snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_SENSE, 0) &
AC_PINSENSE_PRESENCE)
return 1; return 1;
return 0; return 0;
} }
...@@ -4791,28 +4845,28 @@ static int stac92xx_hp_check_power_status(struct hda_codec *codec, ...@@ -4791,28 +4845,28 @@ static int stac92xx_hp_check_power_status(struct hda_codec *codec,
return 0; return 0;
} }
#endif
static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state) static int idt92hd83xxx_hp_check_power_status(struct hda_codec *codec,
hda_nid_t nid)
{ {
struct sigmatel_spec *spec = codec->spec; struct sigmatel_spec *spec = codec->spec;
int i;
hda_nid_t nid;
/* reset each pin before powering down DAC/ADC to avoid click noise */ if (nid != 0x13)
nid = codec->start_nid; return 0;
for (i = 0; i < codec->num_nodes; i++, nid++) { if (snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) & HDA_AMP_MUTE)
unsigned int wcaps = get_wcaps(codec, nid); spec->gpio_data |= spec->gpio_led; /* mute LED on */
unsigned int wid_type = get_wcaps_type(wcaps); else
if (wid_type == AC_WID_PIN) spec->gpio_data &= ~spec->gpio_led; /* mute LED off */
snd_hda_codec_read(codec, nid, 0, stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data);
AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
}
if (spec->eapd_mask) return 0;
stac_gpio_set(codec, spec->gpio_mask, }
spec->gpio_dir, spec->gpio_data &
~spec->eapd_mask); #endif
static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state)
{
stac92xx_shutup(codec);
return 0; return 0;
} }
#endif #endif
...@@ -4827,6 +4881,7 @@ static struct hda_codec_ops stac92xx_patch_ops = { ...@@ -4827,6 +4881,7 @@ static struct hda_codec_ops stac92xx_patch_ops = {
.suspend = stac92xx_suspend, .suspend = stac92xx_suspend,
.resume = stac92xx_resume, .resume = stac92xx_resume,
#endif #endif
.reboot_notify = stac92xx_shutup,
}; };
static int patch_stac9200(struct hda_codec *codec) static int patch_stac9200(struct hda_codec *codec)
...@@ -5172,6 +5227,22 @@ again: ...@@ -5172,6 +5227,22 @@ again:
break; break;
} }
codec->patch_ops = stac92xx_patch_ops;
if (spec->board_config == STAC_92HD83XXX_HP)
spec->gpio_led = 0x01;
#ifdef CONFIG_SND_HDA_POWER_SAVE
if (spec->gpio_led) {
spec->gpio_mask |= spec->gpio_led;
spec->gpio_dir |= spec->gpio_led;
spec->gpio_data |= spec->gpio_led;
/* register check_power_status callback. */
codec->patch_ops.check_power_status =
idt92hd83xxx_hp_check_power_status;
}
#endif
err = stac92xx_parse_auto_config(codec, 0x1d, 0); err = stac92xx_parse_auto_config(codec, 0x1d, 0);
if (!err) { if (!err) {
if (spec->board_config < 0) { if (spec->board_config < 0) {
...@@ -5207,8 +5278,6 @@ again: ...@@ -5207,8 +5278,6 @@ again:
snd_hda_codec_write_cache(codec, nid, 0, snd_hda_codec_write_cache(codec, nid, 0,
AC_VERB_SET_CONNECT_SEL, num_dacs); AC_VERB_SET_CONNECT_SEL, num_dacs);
codec->patch_ops = stac92xx_patch_ops;
codec->proc_widget_hook = stac92hd_proc_hook; codec->proc_widget_hook = stac92hd_proc_hook;
return 0; return 0;
......
This diff is collapsed.
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
snd-ice17xx-ak4xxx-objs := ak4xxx.o snd-ice17xx-ak4xxx-objs := ak4xxx.o
snd-ice1712-objs := ice1712.o delta.o hoontech.o ews.o snd-ice1712-objs := ice1712.o delta.o hoontech.o ews.o
snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o vt1720_mobo.o pontis.o prodigy192.o prodigy_hifi.o juli.o phase.o wtm.o se.o maya44.o snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o vt1720_mobo.o pontis.o prodigy192.o prodigy_hifi.o juli.o phase.o wtm.o se.o maya44.o quartet.o
# Toplevel Module Dependency # Toplevel Module Dependency
obj-$(CONFIG_SND_ICE1712) += snd-ice1712.o snd-ice17xx-ak4xxx.o obj-$(CONFIG_SND_ICE1712) += snd-ice1712.o snd-ice17xx-ak4xxx.o
......
...@@ -298,6 +298,16 @@ static void snd_ice1712_set_gpio_dir(struct snd_ice1712 *ice, unsigned int data) ...@@ -298,6 +298,16 @@ static void snd_ice1712_set_gpio_dir(struct snd_ice1712 *ice, unsigned int data)
inb(ICEREG(ice, DATA)); /* dummy read for pci-posting */ inb(ICEREG(ice, DATA)); /* dummy read for pci-posting */
} }
static unsigned int snd_ice1712_get_gpio_dir(struct snd_ice1712 *ice)
{
return snd_ice1712_read(ice, ICE1712_IREG_GPIO_DIRECTION);
}
static unsigned int snd_ice1712_get_gpio_mask(struct snd_ice1712 *ice)
{
return snd_ice1712_read(ice, ICE1712_IREG_GPIO_WRITE_MASK);
}
static void snd_ice1712_set_gpio_mask(struct snd_ice1712 *ice, unsigned int data) static void snd_ice1712_set_gpio_mask(struct snd_ice1712 *ice, unsigned int data)
{ {
snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, data); snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, data);
...@@ -2557,7 +2567,9 @@ static int __devinit snd_ice1712_create(struct snd_card *card, ...@@ -2557,7 +2567,9 @@ static int __devinit snd_ice1712_create(struct snd_card *card,
mutex_init(&ice->i2c_mutex); mutex_init(&ice->i2c_mutex);
mutex_init(&ice->open_mutex); mutex_init(&ice->open_mutex);
ice->gpio.set_mask = snd_ice1712_set_gpio_mask; ice->gpio.set_mask = snd_ice1712_set_gpio_mask;
ice->gpio.get_mask = snd_ice1712_get_gpio_mask;
ice->gpio.set_dir = snd_ice1712_set_gpio_dir; ice->gpio.set_dir = snd_ice1712_set_gpio_dir;
ice->gpio.get_dir = snd_ice1712_get_gpio_dir;
ice->gpio.set_data = snd_ice1712_set_gpio_data; ice->gpio.set_data = snd_ice1712_set_gpio_data;
ice->gpio.get_data = snd_ice1712_get_gpio_data; ice->gpio.get_data = snd_ice1712_get_gpio_data;
......
...@@ -359,7 +359,9 @@ struct snd_ice1712 { ...@@ -359,7 +359,9 @@ struct snd_ice1712 {
unsigned int saved[2]; /* for ewx_i2c */ unsigned int saved[2]; /* for ewx_i2c */
/* operators */ /* operators */
void (*set_mask)(struct snd_ice1712 *ice, unsigned int data); void (*set_mask)(struct snd_ice1712 *ice, unsigned int data);
unsigned int (*get_mask)(struct snd_ice1712 *ice);
void (*set_dir)(struct snd_ice1712 *ice, unsigned int data); void (*set_dir)(struct snd_ice1712 *ice, unsigned int data);
unsigned int (*get_dir)(struct snd_ice1712 *ice);
void (*set_data)(struct snd_ice1712 *ice, unsigned int data); void (*set_data)(struct snd_ice1712 *ice, unsigned int data);
unsigned int (*get_data)(struct snd_ice1712 *ice); unsigned int (*get_data)(struct snd_ice1712 *ice);
/* misc operators - move to another place? */ /* misc operators - move to another place? */
...@@ -377,8 +379,11 @@ struct snd_ice1712 { ...@@ -377,8 +379,11 @@ struct snd_ice1712 {
unsigned int (*get_rate)(struct snd_ice1712 *ice); unsigned int (*get_rate)(struct snd_ice1712 *ice);
void (*set_rate)(struct snd_ice1712 *ice, unsigned int rate); void (*set_rate)(struct snd_ice1712 *ice, unsigned int rate);
unsigned char (*set_mclk)(struct snd_ice1712 *ice, unsigned int rate); unsigned char (*set_mclk)(struct snd_ice1712 *ice, unsigned int rate);
void (*set_spdif_clock)(struct snd_ice1712 *ice); int (*set_spdif_clock)(struct snd_ice1712 *ice, int type);
int (*get_spdif_master_type)(struct snd_ice1712 *ice);
char **ext_clock_names;
int ext_clock_count;
void (*pro_open)(struct snd_ice1712 *, struct snd_pcm_substream *);
#ifdef CONFIG_PM #ifdef CONFIG_PM
int (*pm_suspend)(struct snd_ice1712 *); int (*pm_suspend)(struct snd_ice1712 *);
int (*pm_resume)(struct snd_ice1712 *); int (*pm_resume)(struct snd_ice1712 *);
...@@ -399,6 +404,11 @@ static inline void snd_ice1712_gpio_set_dir(struct snd_ice1712 *ice, unsigned in ...@@ -399,6 +404,11 @@ static inline void snd_ice1712_gpio_set_dir(struct snd_ice1712 *ice, unsigned in
ice->gpio.set_dir(ice, bits); ice->gpio.set_dir(ice, bits);
} }
static inline unsigned int snd_ice1712_gpio_get_dir(struct snd_ice1712 *ice)
{
return ice->gpio.get_dir(ice);
}
static inline void snd_ice1712_gpio_set_mask(struct snd_ice1712 *ice, unsigned int bits) static inline void snd_ice1712_gpio_set_mask(struct snd_ice1712 *ice, unsigned int bits)
{ {
ice->gpio.set_mask(ice, bits); ice->gpio.set_mask(ice, bits);
......
This diff is collapsed.
...@@ -412,25 +412,6 @@ static struct snd_kcontrol_new juli_mute_controls[] __devinitdata = { ...@@ -412,25 +412,6 @@ static struct snd_kcontrol_new juli_mute_controls[] __devinitdata = {
}, },
}; };
static void ak4358_proc_regs_read(struct snd_info_entry *entry,
struct snd_info_buffer *buffer)
{
struct snd_ice1712 *ice = (struct snd_ice1712 *)entry->private_data;
int reg, val;
for (reg = 0; reg <= 0xf; reg++) {
val = snd_akm4xxx_get(ice->akm, 0, reg);
snd_iprintf(buffer, "0x%02x = 0x%02x\n", reg, val);
}
}
static void ak4358_proc_init(struct snd_ice1712 *ice)
{
struct snd_info_entry *entry;
if (!snd_card_proc_new(ice->card, "ak4358_codec", &entry))
snd_info_set_text_ops(entry, ice, ak4358_proc_regs_read);
}
static char *slave_vols[] __devinitdata = { static char *slave_vols[] __devinitdata = {
PCM_VOLUME, PCM_VOLUME,
MONITOR_AN_IN_VOLUME, MONITOR_AN_IN_VOLUME,
...@@ -496,8 +477,6 @@ static int __devinit juli_add_controls(struct snd_ice1712 *ice) ...@@ -496,8 +477,6 @@ static int __devinit juli_add_controls(struct snd_ice1712 *ice)
/* only capture SPDIF over AK4114 */ /* only capture SPDIF over AK4114 */
err = snd_ak4114_build(spec->ak4114, NULL, err = snd_ak4114_build(spec->ak4114, NULL,
ice->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream); ice->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream);
ak4358_proc_init(ice);
if (err < 0) if (err < 0)
return err; return err;
return 0; return 0;
...@@ -575,13 +554,14 @@ static inline unsigned char juli_set_mclk(struct snd_ice1712 *ice, ...@@ -575,13 +554,14 @@ static inline unsigned char juli_set_mclk(struct snd_ice1712 *ice,
} }
/* setting clock to external - SPDIF */ /* setting clock to external - SPDIF */
static void juli_set_spdif_clock(struct snd_ice1712 *ice) static int juli_set_spdif_clock(struct snd_ice1712 *ice, int type)
{ {
unsigned int old; unsigned int old;
old = ice->gpio.get_data(ice); old = ice->gpio.get_data(ice);
/* external clock (= 0), multiply 1x, 48kHz */ /* external clock (= 0), multiply 1x, 48kHz */
ice->gpio.set_data(ice, (old & ~GPIO_RATE_MASK) | GPIO_MULTI_1X | ice->gpio.set_data(ice, (old & ~GPIO_RATE_MASK) | GPIO_MULTI_1X |
GPIO_FREQ_48KHZ); GPIO_FREQ_48KHZ);
return 0;
} }
/* Called when ak4114 detects change in the input SPDIF stream */ /* Called when ak4114 detects change in the input SPDIF stream */
......
This diff is collapsed.
#ifndef __SOUND_QTET_H
#define __SOUND_QTET_H
#define QTET_DEVICE_DESC "{Infrasonic,Quartet},"
#define VT1724_SUBDEVICE_QTET 0x30305349 /* Infrasonic Quartet */
extern struct snd_ice1712_card_info snd_vt1724_qtet_cards[];
#endif /* __SOUND_QTET_H */
snd-oxygen-lib-objs := oxygen_io.o oxygen_lib.o oxygen_mixer.o oxygen_pcm.o snd-oxygen-lib-objs := oxygen_io.o oxygen_lib.o oxygen_mixer.o oxygen_pcm.o
snd-hifier-objs := hifier.o snd-hifier-objs := hifier.o
snd-oxygen-objs := oxygen.o snd-oxygen-objs := oxygen.o
snd-virtuoso-objs := virtuoso.o snd-virtuoso-objs := virtuoso.o xonar_lib.o \
xonar_pcm179x.o xonar_cs43xx.o xonar_hdmi.o
obj-$(CONFIG_SND_OXYGEN_LIB) += snd-oxygen-lib.o obj-$(CONFIG_SND_OXYGEN_LIB) += snd-oxygen-lib.o
obj-$(CONFIG_SND_HIFIER) += snd-hifier.o obj-$(CONFIG_SND_HIFIER) += snd-hifier.o
......
#ifndef CS2000_H_INCLUDED
#define CS2000_H_INCLUDED
#define CS2000_DEV_ID 0x01
#define CS2000_DEV_CTRL 0x02
#define CS2000_DEV_CFG_1 0x03
#define CS2000_DEV_CFG_2 0x04
#define CS2000_GLOBAL_CFG 0x05
#define CS2000_RATIO_0 0x06 /* 32 bits, big endian */
#define CS2000_RATIO_1 0x0a
#define CS2000_RATIO_2 0x0e
#define CS2000_RATIO_3 0x12
#define CS2000_FUN_CFG_1 0x16
#define CS2000_FUN_CFG_2 0x17
#define CS2000_FUN_CFG_3 0x1e
/* DEV_ID */
#define CS2000_DEVICE_MASK 0xf8
#define CS2000_REVISION_MASK 0x07
/* DEV_CTRL */
#define CS2000_UNLOCK 0x80
#define CS2000_AUX_OUT_DIS 0x02
#define CS2000_CLK_OUT_DIS 0x01
/* DEV_CFG_1 */
#define CS2000_R_MOD_SEL_MASK 0xe0
#define CS2000_R_MOD_SEL_1 0x00
#define CS2000_R_MOD_SEL_2 0x20
#define CS2000_R_MOD_SEL_4 0x40
#define CS2000_R_MOD_SEL_8 0x60
#define CS2000_R_MOD_SEL_1_2 0x80
#define CS2000_R_MOD_SEL_1_4 0xa0
#define CS2000_R_MOD_SEL_1_8 0xc0
#define CS2000_R_MOD_SEL_1_16 0xe0
#define CS2000_R_SEL_MASK 0x18
#define CS2000_R_SEL_SHIFT 3
#define CS2000_AUX_OUT_SRC_MASK 0x06
#define CS2000_AUX_OUT_SRC_REF_CLK 0x00
#define CS2000_AUX_OUT_SRC_CLK_IN 0x02
#define CS2000_AUX_OUT_SRC_CLK_OUT 0x04
#define CS2000_AUX_OUT_SRC_PLL_LOCK 0x06
#define CS2000_EN_DEV_CFG_1 0x01
/* DEV_CFG_2 */
#define CS2000_LOCK_CLK_MASK 0x06
#define CS2000_LOCK_CLK_SHIFT 1
#define CS2000_FRAC_N_SRC_MASK 0x01
#define CS2000_FRAC_N_SRC_STATIC 0x00
#define CS2000_FRAC_N_SRC_DYNAMIC 0x01
/* GLOBAL_CFG */
#define CS2000_FREEZE 0x08
#define CS2000_EN_DEV_CFG_2 0x01
/* FUN_CFG_1 */
#define CS2000_CLK_SKIP_EN 0x80
#define CS2000_AUX_LOCK_CFG_MASK 0x40
#define CS2000_AUX_LOCK_CFG_PP_HIGH 0x00
#define CS2000_AUX_LOCK_CFG_OD_LOW 0x40
#define CS2000_REF_CLK_DIV_MASK 0x18
#define CS2000_REF_CLK_DIV_4 0x00
#define CS2000_REF_CLK_DIV_2 0x08
#define CS2000_REF_CLK_DIV_1 0x10
/* FUN_CFG_2 */
#define CS2000_CLK_OUT_UNL 0x10
#define CS2000_L_F_RATIO_CFG_MASK 0x08
#define CS2000_L_F_RATIO_CFG_20_12 0x00
#define CS2000_L_F_RATIO_CFG_12_20 0x08
/* FUN_CFG_3 */
#define CS2000_CLK_IN_BW_MASK 0x70
#define CS2000_CLK_IN_BW_1 0x00
#define CS2000_CLK_IN_BW_2 0x10
#define CS2000_CLK_IN_BW_4 0x20
#define CS2000_CLK_IN_BW_8 0x30
#define CS2000_CLK_IN_BW_16 0x40
#define CS2000_CLK_IN_BW_32 0x50
#define CS2000_CLK_IN_BW_64 0x60
#define CS2000_CLK_IN_BW_128 0x70
#endif
This diff is collapsed.
This diff is collapsed.
...@@ -78,12 +78,15 @@ struct oxygen_model { ...@@ -78,12 +78,15 @@ struct oxygen_model {
void (*resume)(struct oxygen *chip); void (*resume)(struct oxygen *chip);
void (*pcm_hardware_filter)(unsigned int channel, void (*pcm_hardware_filter)(unsigned int channel,
struct snd_pcm_hardware *hardware); struct snd_pcm_hardware *hardware);
unsigned int (*get_i2s_mclk)(struct oxygen *chip, unsigned int channel,
struct snd_pcm_hw_params *hw_params);
void (*set_dac_params)(struct oxygen *chip, void (*set_dac_params)(struct oxygen *chip,
struct snd_pcm_hw_params *params); struct snd_pcm_hw_params *params);
void (*set_adc_params)(struct oxygen *chip, void (*set_adc_params)(struct oxygen *chip,
struct snd_pcm_hw_params *params); struct snd_pcm_hw_params *params);
void (*update_dac_volume)(struct oxygen *chip); void (*update_dac_volume)(struct oxygen *chip);
void (*update_dac_mute)(struct oxygen *chip); void (*update_dac_mute)(struct oxygen *chip);
void (*update_center_lfe_mix)(struct oxygen *chip, bool mixed);
void (*gpio_changed)(struct oxygen *chip); void (*gpio_changed)(struct oxygen *chip);
void (*uart_input)(struct oxygen *chip); void (*uart_input)(struct oxygen *chip);
void (*ac97_switch)(struct oxygen *chip, void (*ac97_switch)(struct oxygen *chip,
...@@ -162,6 +165,8 @@ void oxygen_update_spdif_source(struct oxygen *chip); ...@@ -162,6 +165,8 @@ void oxygen_update_spdif_source(struct oxygen *chip);
/* oxygen_pcm.c */ /* oxygen_pcm.c */
int oxygen_pcm_init(struct oxygen *chip); int oxygen_pcm_init(struct oxygen *chip);
unsigned int oxygen_default_i2s_mclk(struct oxygen *chip, unsigned int channel,
struct snd_pcm_hw_params *hw_params);
/* oxygen_io.c */ /* oxygen_io.c */
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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