Skip to content

Commit

Permalink
[ALSA] hda-codec - More fix of ALC880 codec support
Browse files Browse the repository at this point in the history
Documentation,HDA Codec driver,HDA generic driver,HDA Intel driver
- Fix some invalid configurations, typos in the last patch
- Make init_verbs chainable, so that different configs can share the same
  init_verbs
- Reorder and clean up the source codes in patch_realtek.c
- Add the pin default configuration parser, used commonly in cmedia
  and realtek patch codes.
- Add 'auto' model to ALC880 for auto-configuration from BIOS
  Use this model as default, and 3-stack as fallback

Signed-off-by: Takashi Iwai <tiwai@suse.de>
  • Loading branch information
Takashi Iwai authored and Jaroslav Kysela committed Jun 22, 2005
1 parent b636a71 commit e9edcee
Show file tree
Hide file tree
Showing 7 changed files with 1,218 additions and 1,105 deletions.
4 changes: 4 additions & 0 deletions Documentation/sound/alsa/ALSA-Configuration.txt
Original file line number Diff line number Diff line change
Expand Up @@ -638,13 +638,17 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
5stack-digout 5-jack in back, 2-jack in front, a SPDIF out
w810 3-jack
z71v 3-jack (HP shared SPDIF)
asus 3-jack
uniwill 3-jack
F1734 2-jack

CMI9880
minimal 3-jack in back
min_fp 3-jack in back, 2-jack in front
full 6-jack in back, 2-jack in front
full_dig 6-jack in back, 2-jack in front, SPDIF I/O
allout 5-jack in back, 2-jack in front, SPDIF out
auto auto-config reading BIOS (default)

Note 2: If you get click noises on output, try the module option
position_fix=1 or 2. position_fix=1 will use the SD_LPIB
Expand Down
103 changes: 101 additions & 2 deletions sound/pci/hda/hda_codec.c
Original file line number Diff line number Diff line change
Expand Up @@ -1520,9 +1520,9 @@ int snd_hda_build_pcms(struct hda_bus *bus)
*
* If no entries are matching, the function returns a negative value.
*/
int snd_hda_check_board_config(struct hda_codec *codec, struct hda_board_config *tbl)
int snd_hda_check_board_config(struct hda_codec *codec, const struct hda_board_config *tbl)
{
struct hda_board_config *c;
const struct hda_board_config *c;

if (codec->bus->modelname) {
for (c = tbl; c->modelname || c->pci_subvendor; c++) {
Expand Down Expand Up @@ -1714,6 +1714,105 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, struct hda_multi_o
return 0;
}

/*
* Helper for automatic ping configuration
*/
/* parse all pin widgets and store the useful pin nids to cfg */
int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *cfg)
{
hda_nid_t nid, nid_start;
int i, j, nodes;
short seq, sequences[4], assoc_line_out;

memset(cfg, 0, sizeof(*cfg));

memset(sequences, 0, sizeof(sequences));
assoc_line_out = 0;

nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid_start);
for (nid = nid_start; nid < nodes + nid_start; nid++) {
unsigned int wid_caps = snd_hda_param_read(codec, nid,
AC_PAR_AUDIO_WIDGET_CAP);
unsigned int wid_type = (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
unsigned int def_conf;
short assoc, loc;

/* read all default configuration for pin complex */
if (wid_type != AC_WID_PIN)
continue;
def_conf = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
continue;
loc = get_defcfg_location(def_conf);
switch (get_defcfg_device(def_conf)) {
case AC_JACK_LINE_OUT:
case AC_JACK_SPEAKER:
seq = get_defcfg_sequence(def_conf);
assoc = get_defcfg_association(def_conf);
if (! assoc)
continue;
if (! assoc_line_out)
assoc_line_out = assoc;
else if (assoc_line_out != assoc)
continue;
if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins))
continue;
cfg->line_out_pins[cfg->line_outs] = nid;
sequences[cfg->line_outs] = seq;
cfg->line_outs++;
break;
case AC_JACK_HP_OUT:
cfg->hp_pin = nid;
break;
case AC_JACK_MIC_IN:
if (loc == AC_JACK_LOC_FRONT)
cfg->input_pins[AUTO_PIN_FRONT_MIC] = nid;
else
cfg->input_pins[AUTO_PIN_MIC] = nid;
break;
case AC_JACK_LINE_IN:
if (loc == AC_JACK_LOC_FRONT)
cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid;
else
cfg->input_pins[AUTO_PIN_LINE] = nid;
break;
case AC_JACK_CD:
cfg->input_pins[AUTO_PIN_CD] = nid;
break;
case AC_JACK_AUX:
cfg->input_pins[AUTO_PIN_AUX] = nid;
break;
case AC_JACK_SPDIF_OUT:
cfg->dig_out_pin = nid;
break;
case AC_JACK_SPDIF_IN:
cfg->dig_in_pin = nid;
break;
}
}

/* sort by sequence */
for (i = 0; i < cfg->line_outs; i++)
for (j = i + 1; j < cfg->line_outs; j++)
if (sequences[i] > sequences[j]) {
seq = sequences[i];
sequences[i] = sequences[j];
sequences[j] = seq;
nid = cfg->line_out_pins[i];
cfg->line_out_pins[i] = cfg->line_out_pins[j];
cfg->line_out_pins[j] = nid;
}

/* Swap surround and CLFE: the association order is front/CLFE/surr/back */
if (cfg->line_outs >= 3) {
nid = cfg->line_out_pins[1];
cfg->line_out_pins[1] = cfg->line_out_pins[2];
cfg->line_out_pins[2] = nid;
}

return 0;
}

#ifdef CONFIG_PM
/*
* power management
Expand Down
10 changes: 5 additions & 5 deletions sound/pci/hda/hda_generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ struct hda_gspec {
/*
* retrieve the default device type from the default config value
*/
#define get_defcfg_type(node) (((node)->def_cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT)
#define get_defcfg_location(node) (((node)->def_cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT)
#define defcfg_type(node) (((node)->def_cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT)
#define defcfg_location(node) (((node)->def_cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT)

/*
* destructor
Expand Down Expand Up @@ -323,7 +323,7 @@ static struct hda_gnode *parse_output_jack(struct hda_codec *codec,
if (! (node->pin_caps & AC_PINCAP_OUT))
continue;
if (jack_type >= 0) {
if (jack_type != get_defcfg_type(node))
if (jack_type != defcfg_type(node))
continue;
if (node->wid_caps & AC_WCAP_DIGITAL)
continue; /* skip SPDIF */
Expand Down Expand Up @@ -418,8 +418,8 @@ static int capture_source_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uc
*/
static const char *get_input_type(struct hda_gnode *node, unsigned int *pinctl)
{
unsigned int location = get_defcfg_location(node);
switch (get_defcfg_type(node)) {
unsigned int location = defcfg_location(node);
switch (defcfg_type(node)) {
case AC_JACK_LINE_IN:
if ((location & 0x0f) == AC_JACK_LOC_FRONT)
return "Front Line";
Expand Down
2 changes: 1 addition & 1 deletion sound/pci/hda/hda_intel.c
Original file line number Diff line number Diff line change
Expand Up @@ -1458,7 +1458,7 @@ static struct pci_device_id azx_ids[] = {
{ 0x8086, 0x269a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ESB2 */
{ 0x1002, 0x437b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ATI SB450 */
{ 0x1106, 0x3288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* VIA VT8251/VT8237A */
{ 0x10b9, 0x5461, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ULI */
{ 0x10b9, 0x5461, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ALI 5461? */
{ 0, }
};
MODULE_DEVICE_TABLE(pci, azx_ids);
Expand Down
33 changes: 32 additions & 1 deletion sound/pci/hda/hda_local.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ struct hda_board_config {
unsigned short pci_subdevice;
};

int snd_hda_check_board_config(struct hda_codec *codec, struct hda_board_config *tbl);
int snd_hda_check_board_config(struct hda_codec *codec, const struct hda_board_config *tbl);
int snd_hda_add_new_ctls(struct hda_codec *codec, snd_kcontrol_new_t *knew);

/*
Expand Down Expand Up @@ -158,4 +158,35 @@ struct hda_bus_unsolicited {
struct work_struct work;
};

/*
* Helper for automatic ping configuration
*/

enum {
AUTO_PIN_MIC,
AUTO_PIN_FRONT_MIC,
AUTO_PIN_LINE,
AUTO_PIN_FRONT_LINE,
AUTO_PIN_CD,
AUTO_PIN_AUX,
AUTO_PIN_LAST
};

struct auto_pin_cfg {
int line_outs;
hda_nid_t line_out_pins[4]; /* sorted in the order of Front/Surr/CLFE/Side */
hda_nid_t hp_pin;
hda_nid_t input_pins[AUTO_PIN_LAST];
hda_nid_t dig_out_pin;
hda_nid_t dig_in_pin;
};

#define get_defcfg_connect(cfg) ((cfg & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT)
#define get_defcfg_association(cfg) ((cfg & AC_DEFCFG_DEF_ASSOC) >> AC_DEFCFG_ASSOC_SHIFT)
#define get_defcfg_location(cfg) ((cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT)
#define get_defcfg_sequence(cfg) (cfg & AC_DEFCFG_SEQUENCE)
#define get_defcfg_device(cfg) ((cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT)

int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *cfg);

#endif /* __SOUND_HDA_LOCAL_H */
Loading

0 comments on commit e9edcee

Please sign in to comment.