diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 7fd2abe1129..1ed1d88e183 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -946,7 +946,7 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr mutex_init(&codec->control_mutex); init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); - snd_array_init(&codec->mixers, sizeof(struct snd_kcontrol *), 32); + snd_array_init(&codec->mixers, sizeof(struct hda_nid_item), 60); snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16); snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16); if (codec->bus->modelname) { @@ -1517,18 +1517,20 @@ struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec, EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl); /* Add a control element and assign to the codec */ -int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl) +int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid, + struct snd_kcontrol *kctl) { int err; - struct snd_kcontrol **knewp; + struct hda_nid_item *item; err = snd_ctl_add(codec->bus->card, kctl); if (err < 0) return err; - knewp = snd_array_new(&codec->mixers); - if (!knewp) + item = snd_array_new(&codec->mixers); + if (!item) return -ENOMEM; - *knewp = kctl; + item->kctl = kctl; + item->nid = nid; return 0; } EXPORT_SYMBOL_HDA(snd_hda_ctl_add); @@ -1537,9 +1539,9 @@ EXPORT_SYMBOL_HDA(snd_hda_ctl_add); void snd_hda_ctls_clear(struct hda_codec *codec) { int i; - struct snd_kcontrol **kctls = codec->mixers.list; + struct hda_nid_item *items = codec->mixers.list; for (i = 0; i < codec->mixers.used; i++) - snd_ctl_remove(codec->bus->card, kctls[i]); + snd_ctl_remove(codec->bus->card, items[i].kctl); snd_array_free(&codec->mixers); } @@ -1645,7 +1647,7 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name, kctl = snd_ctl_make_virtual_master(name, tlv); if (!kctl) return -ENOMEM; - err = snd_hda_ctl_add(codec, kctl); + err = snd_hda_ctl_add(codec, 0, kctl); if (err < 0) return err; @@ -2139,7 +2141,7 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid) return -ENOMEM; kctl->id.index = idx; kctl->private_value = nid; - err = snd_hda_ctl_add(codec, kctl); + err = snd_hda_ctl_add(codec, nid, kctl); if (err < 0) return err; } @@ -2184,8 +2186,8 @@ int snd_hda_create_spdif_share_sw(struct hda_codec *codec, if (!mout->dig_out_nid) return 0; /* ATTENTION: here mout is passed as private_data, instead of codec */ - return snd_hda_ctl_add(codec, - snd_ctl_new1(&spdif_share_sw, mout)); + return snd_hda_ctl_add(codec, mout->dig_out_nid, + snd_ctl_new1(&spdif_share_sw, mout)); } EXPORT_SYMBOL_HDA(snd_hda_create_spdif_share_sw); @@ -2289,7 +2291,7 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid) if (!kctl) return -ENOMEM; kctl->private_value = nid; - err = snd_hda_ctl_add(codec, kctl); + err = snd_hda_ctl_add(codec, nid, kctl); if (err < 0) return err; } @@ -3165,7 +3167,7 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew) kctl = snd_ctl_new1(knew, codec); if (!kctl) return -ENOMEM; - err = snd_hda_ctl_add(codec, kctl); + err = snd_hda_ctl_add(codec, 0, kctl); if (err < 0) { if (!codec->addr) return err; @@ -3173,7 +3175,7 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew) if (!kctl) return -ENOMEM; kctl->id.device = codec->addr; - err = snd_hda_ctl_add(codec, kctl); + err = snd_hda_ctl_add(codec, 0, kctl); if (err < 0) return err; } diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index b36f6c5a92d..092c6a7c2ff 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c @@ -727,7 +727,8 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node, if (is_loopback) 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); - 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) return err; created = 1; @@ -737,7 +738,8 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node, if (is_loopback) add_input_loopback(codec, node->nid, HDA_OUTPUT, 0); 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) return err; created = 1; @@ -751,7 +753,8 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node, (node->amp_in_caps & AC_AMPCAP_NUM_STEPS)) { 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); - 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) return err; created = 1; @@ -759,7 +762,8 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node, (node->amp_out_caps & AC_AMPCAP_NUM_STEPS)) { 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); - 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) return err; created = 1; @@ -857,7 +861,7 @@ static int build_input_controls(struct hda_codec *codec) } /* 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) return err; @@ -875,7 +879,8 @@ static int build_input_controls(struct hda_codec *codec) HDA_CODEC_VOLUME(name, adc_node->nid, spec->input_mux.items[i].index, 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) return err; } diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 3001794ad29..e6a0918f70d 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h @@ -440,7 +440,13 @@ int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, unsigned int caps); u32 snd_hda_query_pin_caps(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); /* @@ -514,7 +520,8 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec, * AMP control callbacks */ /* 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_direction(kc) (((kc)->private_value >> 18) & 0x1) #define get_amp_index(kc) (((kc)->private_value >> 19) & 0xf) diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index f5b783ce450..f465cff2804 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c @@ -46,6 +46,41 @@ static const char *get_wid_type_name(unsigned int wid_value) 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, struct hda_codec *codec, hda_nid_t nid, int dir) { @@ -309,21 +344,7 @@ static void print_audio_io(struct snd_info_buffer *buffer, struct hda_codec *codec, hda_nid_t nid, unsigned int wid_type) { - int pcm, conv; - for (pcm = 0; pcm < codec->num_pcms; pcm++) { - int type; - struct hda_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); - } - } - conv = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0); + int conv = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0); snd_iprintf(buffer, " Converter: stream=%d, channel=%d\n", (conv & AC_CONV_STREAM) >> AC_CONV_STREAM_SHIFT, @@ -471,6 +492,7 @@ static void print_gpio(struct snd_info_buffer *buffer, (data & (1<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) return err; } diff --git a/sound/pci/hda/patch_ca0110.c b/sound/pci/hda/patch_ca0110.c index d08353d3bb7..af478019088 100644 --- a/sound/pci/hda/patch_ca0110.c +++ b/sound/pci/hda/patch_ca0110.c @@ -144,7 +144,7 @@ static int _add_switch(struct hda_codec *codec, hda_nid_t nid, const char *pfx, struct snd_kcontrol_new knew = HDA_CODEC_MUTE_MONO(namestr, nid, chan, 0, type); 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, @@ -155,7 +155,7 @@ static int _add_volume(struct hda_codec *codec, hda_nid_t nid, const char *pfx, struct snd_kcontrol_new knew = HDA_CODEC_VOLUME_MONO(namestr, nid, chan, 0, type); 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) diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 8ba306856d3..9ac09e4568b 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c @@ -500,7 +500,7 @@ static int add_mute(struct hda_codec *codec, const char *name, int index, knew.private_value = pval; snprintf(tmp, sizeof(tmp), "%s %s Switch", name, dir_sfx[dir]); *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, @@ -513,7 +513,7 @@ static int add_volume(struct hda_codec *codec, const char *name, knew.private_value = pval; snprintf(tmp, sizeof(tmp), "%s %s Volume", name, dir_sfx[dir]); *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) @@ -536,14 +536,14 @@ static int add_vmaster(struct hda_codec *codec, hda_nid_t dac) spec->vmaster_sw = 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) return err; snd_hda_set_vmaster_tlv(codec, dac, HDA_OUTPUT, tlv); spec->vmaster_vol = 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) return err; return 0; @@ -756,13 +756,13 @@ static int build_input(struct hda_codec *codec) if (!kctl) return -ENOMEM; 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) return err; } 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)); if (err < 0) return err; diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 8c04e0e0f65..fff9de24564 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -2461,7 +2461,8 @@ static int alc_build_controls(struct hda_codec *codec) if (!kctl) return -ENOMEM; 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) return err; } diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 87ba239ff1c..a3872b90d6e 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -1085,7 +1085,7 @@ static int stac92xx_build_controls(struct hda_codec *codec) if (!spec->auto_mic && spec->num_dmuxes > 0 && snd_hda_get_bool_hint(codec, "separate_dmux") == 1) { 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)); if (err < 0) return err; @@ -1101,7 +1101,7 @@ static int stac92xx_build_controls(struct hda_codec *codec) spec->spdif_mute = 1; } 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)); if (err < 0) return err;