Loading sound/pci/hda/hda_codec.c +73 −6 Original line number Original line Diff line number Diff line Loading @@ -931,6 +931,7 @@ static void snd_hda_codec_free(struct hda_codec *codec) #endif #endif list_del(&codec->list); list_del(&codec->list); snd_array_free(&codec->mixers); snd_array_free(&codec->mixers); snd_array_free(&codec->nids); codec->bus->caddr_tbl[codec->addr] = NULL; codec->bus->caddr_tbl[codec->addr] = NULL; if (codec->patch_ops.free) if (codec->patch_ops.free) codec->patch_ops.free(codec); codec->patch_ops.free(codec); Loading Loading @@ -985,7 +986,8 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr mutex_init(&codec->control_mutex); mutex_init(&codec->control_mutex); init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); snd_array_init(&codec->mixers, sizeof(struct hda_nid_item), 60); snd_array_init(&codec->mixers, sizeof(struct hda_nid_item), 32); snd_array_init(&codec->nids, sizeof(struct hda_nid_item), 32); snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16); snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16); snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16); snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16); if (codec->bus->modelname) { if (codec->bus->modelname) { Loading Loading @@ -1706,7 +1708,7 @@ struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec, EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl); EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl); /** /** * snd_hda_ctl-add - Add a control element and assign to the codec * snd_hda_ctl_add - Add a control element and assign to the codec * @codec: HD-audio codec * @codec: HD-audio codec * @nid: corresponding NID (optional) * @nid: corresponding NID (optional) * @kctl: the control element to assign * @kctl: the control element to assign Loading @@ -1721,19 +1723,25 @@ EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl); * * * snd_hda_ctl_add() checks the control subdev id field whether * snd_hda_ctl_add() checks the control subdev id field whether * #HDA_SUBDEV_NID_FLAG bit is set. If set (and @nid is zero), the lower * #HDA_SUBDEV_NID_FLAG bit is set. If set (and @nid is zero), the lower * bits value is taken as the NID to assign. * bits value is taken as the NID to assign. The #HDA_NID_ITEM_AMP bit * specifies if kctl->private_value is a HDA amplifier value. */ */ int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid, int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid, struct snd_kcontrol *kctl) struct snd_kcontrol *kctl) { { int err; int err; unsigned short flags = 0; struct hda_nid_item *item; struct hda_nid_item *item; if (kctl->id.subdevice & HDA_SUBDEV_NID_FLAG) { if (kctl->id.subdevice & HDA_SUBDEV_AMP_FLAG) { flags |= HDA_NID_ITEM_AMP; if (nid == 0) if (nid == 0) nid = get_amp_nid_(kctl->private_value); } if ((kctl->id.subdevice & HDA_SUBDEV_NID_FLAG) != 0 && nid == 0) nid = kctl->id.subdevice & 0xffff; nid = kctl->id.subdevice & 0xffff; if (kctl->id.subdevice & (HDA_SUBDEV_NID_FLAG|HDA_SUBDEV_AMP_FLAG)) kctl->id.subdevice = 0; kctl->id.subdevice = 0; } err = snd_ctl_add(codec->bus->card, kctl); err = snd_ctl_add(codec->bus->card, kctl); if (err < 0) if (err < 0) return err; return err; Loading @@ -1742,10 +1750,40 @@ int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid, return -ENOMEM; return -ENOMEM; item->kctl = kctl; item->kctl = kctl; item->nid = nid; item->nid = nid; item->flags = flags; return 0; return 0; } } EXPORT_SYMBOL_HDA(snd_hda_ctl_add); EXPORT_SYMBOL_HDA(snd_hda_ctl_add); /** * snd_hda_add_nid - Assign a NID to a control element * @codec: HD-audio codec * @nid: corresponding NID (optional) * @kctl: the control element to assign * @index: index to kctl * * Add the given control element to an array inside the codec instance. * This function is used when #snd_hda_ctl_add cannot be used for 1:1 * NID:KCTL mapping - for example "Capture Source" selector. */ int snd_hda_add_nid(struct hda_codec *codec, struct snd_kcontrol *kctl, unsigned int index, hda_nid_t nid) { struct hda_nid_item *item; if (nid > 0) { item = snd_array_new(&codec->nids); if (!item) return -ENOMEM; item->kctl = kctl; item->index = index; item->nid = nid; return 0; } return -EINVAL; } EXPORT_SYMBOL_HDA(snd_hda_add_nid); /** /** * snd_hda_ctls_clear - Clear all controls assigned to the given codec * snd_hda_ctls_clear - Clear all controls assigned to the given codec * @codec: HD-audio codec * @codec: HD-audio codec Loading @@ -1757,6 +1795,7 @@ void snd_hda_ctls_clear(struct hda_codec *codec) for (i = 0; i < codec->mixers.used; i++) for (i = 0; i < codec->mixers.used; i++) snd_ctl_remove(codec->bus->card, items[i].kctl); snd_ctl_remove(codec->bus->card, items[i].kctl); snd_array_free(&codec->mixers); snd_array_free(&codec->mixers); snd_array_free(&codec->nids); } } /* pseudo device locking /* pseudo device locking Loading Loading @@ -3476,6 +3515,8 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew) for (; knew->name; knew++) { for (; knew->name; knew++) { struct snd_kcontrol *kctl; struct snd_kcontrol *kctl; if (knew->iface == -1) /* skip this codec private value */ continue; kctl = snd_ctl_new1(knew, codec); kctl = snd_ctl_new1(knew, codec); if (!kctl) if (!kctl) return -ENOMEM; return -ENOMEM; Loading @@ -3496,6 +3537,32 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew) } } EXPORT_SYMBOL_HDA(snd_hda_add_new_ctls); EXPORT_SYMBOL_HDA(snd_hda_add_new_ctls); /** * snd_hda_add_nids - assign nids to controls from the array * @codec: the HDA codec * @kctl: struct snd_kcontrol * @index: index to kctl * @nids: the array of hda_nid_t * @size: count of hda_nid_t items * * This helper function assigns NIDs in the given array to a control element. * * Returns 0 if successful, or a negative error code. */ int snd_hda_add_nids(struct hda_codec *codec, struct snd_kcontrol *kctl, unsigned int index, hda_nid_t *nids, unsigned int size) { int err; for ( ; size > 0; size--, nids++) { err = snd_hda_add_nid(codec, kctl, index, *nids); if (err < 0) return err; } return 0; } EXPORT_SYMBOL_HDA(snd_hda_add_nids); #ifdef CONFIG_SND_HDA_POWER_SAVE #ifdef CONFIG_SND_HDA_POWER_SAVE static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, unsigned int power_state); unsigned int power_state); Loading sound/pci/hda/hda_codec.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -789,6 +789,7 @@ struct hda_codec { u32 *wcaps; u32 *wcaps; struct snd_array mixers; /* list of assigned mixer elements */ struct snd_array mixers; /* list of assigned mixer elements */ struct snd_array nids; /* list of mapped mixer elements */ struct hda_cache_rec amp_cache; /* cache for amp access */ struct hda_cache_rec amp_cache; /* cache for amp access */ struct hda_cache_rec cmd_cache; /* cache for other commands */ struct hda_cache_rec cmd_cache; /* cache for other commands */ Loading sound/pci/hda/hda_generic.c +2 −1 Original line number Original line Diff line number Diff line Loading @@ -861,7 +861,8 @@ 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, 0, snd_ctl_new1(&cap_sel, codec)); err = snd_hda_ctl_add(codec, spec->adc_node->nid, snd_ctl_new1(&cap_sel, codec)); if (err < 0) if (err < 0) return err; return err; Loading sound/pci/hda/hda_local.h +13 −3 Original line number Original line Diff line number Diff line Loading @@ -31,6 +31,7 @@ * in snd_hda_ctl_add(), so that this value won't appear in the outside. * in snd_hda_ctl_add(), so that this value won't appear in the outside. */ */ #define HDA_SUBDEV_NID_FLAG (1U << 31) #define HDA_SUBDEV_NID_FLAG (1U << 31) #define HDA_SUBDEV_AMP_FLAG (1U << 30) /* /* * for mixer controls * for mixer controls Loading @@ -42,7 +43,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), \ .subdevice = HDA_SUBDEV_AMP_FLAG, \ .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, \ Loading @@ -63,7 +64,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), \ .subdevice = HDA_SUBDEV_AMP_FLAG, \ .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, \ Loading @@ -81,7 +82,7 @@ /* special beep mono mute switch with index (index=0,1,...) (channel=1,2) */ /* 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) \ #define HDA_CODEC_MUTE_BEEP_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), \ .subdevice = HDA_SUBDEV_AMP_FLAG, \ .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_beep, \ .put = snd_hda_mixer_amp_switch_put_beep, \ Loading Loading @@ -342,6 +343,8 @@ int snd_hda_check_board_codec_sid_config(struct hda_codec *codec, const struct snd_pci_quirk *tbl); const struct snd_pci_quirk *tbl); int snd_hda_add_new_ctls(struct hda_codec *codec, int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew); struct snd_kcontrol_new *knew); int snd_hda_add_nids(struct hda_codec *codec, struct snd_kcontrol *kctl, unsigned int index, hda_nid_t *nids, unsigned int size); /* /* * unsolicited event handler * unsolicited event handler Loading Loading @@ -464,13 +467,20 @@ 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); 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_jack_detect(struct hda_codec *codec, hda_nid_t nid); /* flags for hda_nid_item */ #define HDA_NID_ITEM_AMP (1<<0) struct hda_nid_item { struct hda_nid_item { struct snd_kcontrol *kctl; struct snd_kcontrol *kctl; unsigned int index; hda_nid_t nid; hda_nid_t nid; unsigned short flags; }; }; int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid, int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid, struct snd_kcontrol *kctl); struct snd_kcontrol *kctl); int snd_hda_add_nid(struct hda_codec *codec, struct snd_kcontrol *kctl, unsigned int index, hda_nid_t nid); void snd_hda_ctls_clear(struct hda_codec *codec); void snd_hda_ctls_clear(struct hda_codec *codec); /* /* Loading sound/pci/hda/hda_proc.c +22 −9 Original line number Original line Diff line number Diff line Loading @@ -61,18 +61,29 @@ 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, static void print_nid_array(struct snd_info_buffer *buffer, struct hda_codec *codec, hda_nid_t nid) struct hda_codec *codec, hda_nid_t nid, struct snd_array *array) { { int i; int i; struct hda_nid_item *items = codec->mixers.list; struct hda_nid_item *items = array->list, *item; struct snd_kcontrol *kctl; struct snd_kcontrol *kctl; for (i = 0; i < codec->mixers.used; i++) { for (i = 0; i < array->used; i++) { if (items[i].nid == nid) { item = &items[i]; kctl = items[i].kctl; if (item->nid == nid) { kctl = item->kctl; snd_iprintf(buffer, snd_iprintf(buffer, " Control: name=\"%s\", index=%i, device=%i\n", " Control: name=\"%s\", index=%i, device=%i\n", kctl->id.name, kctl->id.index, kctl->id.device); kctl->id.name, kctl->id.index + item->index, kctl->id.device); if (item->flags & HDA_NID_ITEM_AMP) snd_iprintf(buffer, " ControlAmp: chs=%lu, dir=%s, " "idx=%lu, ofs=%lu\n", get_amp_channels(kctl), get_amp_direction(kctl) ? "Out" : "In", get_amp_index(kctl), get_amp_offset(kctl)); } } } } } } Loading Loading @@ -528,7 +539,8 @@ 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); print_nid_array(buffer, codec, nid, &codec->mixers); print_nid_array(buffer, codec, nid, &codec->nids); } } static void print_codec_info(struct snd_info_entry *entry, static void print_codec_info(struct snd_info_entry *entry, Loading Loading @@ -608,7 +620,8 @@ 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_array(buffer, codec, nid, &codec->mixers); print_nid_array(buffer, codec, nid, &codec->nids); print_nid_pcms(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 Loading Loading
sound/pci/hda/hda_codec.c +73 −6 Original line number Original line Diff line number Diff line Loading @@ -931,6 +931,7 @@ static void snd_hda_codec_free(struct hda_codec *codec) #endif #endif list_del(&codec->list); list_del(&codec->list); snd_array_free(&codec->mixers); snd_array_free(&codec->mixers); snd_array_free(&codec->nids); codec->bus->caddr_tbl[codec->addr] = NULL; codec->bus->caddr_tbl[codec->addr] = NULL; if (codec->patch_ops.free) if (codec->patch_ops.free) codec->patch_ops.free(codec); codec->patch_ops.free(codec); Loading Loading @@ -985,7 +986,8 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr mutex_init(&codec->control_mutex); mutex_init(&codec->control_mutex); init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); snd_array_init(&codec->mixers, sizeof(struct hda_nid_item), 60); snd_array_init(&codec->mixers, sizeof(struct hda_nid_item), 32); snd_array_init(&codec->nids, sizeof(struct hda_nid_item), 32); snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16); snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16); snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16); snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16); if (codec->bus->modelname) { if (codec->bus->modelname) { Loading Loading @@ -1706,7 +1708,7 @@ struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec, EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl); EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl); /** /** * snd_hda_ctl-add - Add a control element and assign to the codec * snd_hda_ctl_add - Add a control element and assign to the codec * @codec: HD-audio codec * @codec: HD-audio codec * @nid: corresponding NID (optional) * @nid: corresponding NID (optional) * @kctl: the control element to assign * @kctl: the control element to assign Loading @@ -1721,19 +1723,25 @@ EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl); * * * snd_hda_ctl_add() checks the control subdev id field whether * snd_hda_ctl_add() checks the control subdev id field whether * #HDA_SUBDEV_NID_FLAG bit is set. If set (and @nid is zero), the lower * #HDA_SUBDEV_NID_FLAG bit is set. If set (and @nid is zero), the lower * bits value is taken as the NID to assign. * bits value is taken as the NID to assign. The #HDA_NID_ITEM_AMP bit * specifies if kctl->private_value is a HDA amplifier value. */ */ int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid, int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid, struct snd_kcontrol *kctl) struct snd_kcontrol *kctl) { { int err; int err; unsigned short flags = 0; struct hda_nid_item *item; struct hda_nid_item *item; if (kctl->id.subdevice & HDA_SUBDEV_NID_FLAG) { if (kctl->id.subdevice & HDA_SUBDEV_AMP_FLAG) { flags |= HDA_NID_ITEM_AMP; if (nid == 0) if (nid == 0) nid = get_amp_nid_(kctl->private_value); } if ((kctl->id.subdevice & HDA_SUBDEV_NID_FLAG) != 0 && nid == 0) nid = kctl->id.subdevice & 0xffff; nid = kctl->id.subdevice & 0xffff; if (kctl->id.subdevice & (HDA_SUBDEV_NID_FLAG|HDA_SUBDEV_AMP_FLAG)) kctl->id.subdevice = 0; kctl->id.subdevice = 0; } err = snd_ctl_add(codec->bus->card, kctl); err = snd_ctl_add(codec->bus->card, kctl); if (err < 0) if (err < 0) return err; return err; Loading @@ -1742,10 +1750,40 @@ int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid, return -ENOMEM; return -ENOMEM; item->kctl = kctl; item->kctl = kctl; item->nid = nid; item->nid = nid; item->flags = flags; return 0; return 0; } } EXPORT_SYMBOL_HDA(snd_hda_ctl_add); EXPORT_SYMBOL_HDA(snd_hda_ctl_add); /** * snd_hda_add_nid - Assign a NID to a control element * @codec: HD-audio codec * @nid: corresponding NID (optional) * @kctl: the control element to assign * @index: index to kctl * * Add the given control element to an array inside the codec instance. * This function is used when #snd_hda_ctl_add cannot be used for 1:1 * NID:KCTL mapping - for example "Capture Source" selector. */ int snd_hda_add_nid(struct hda_codec *codec, struct snd_kcontrol *kctl, unsigned int index, hda_nid_t nid) { struct hda_nid_item *item; if (nid > 0) { item = snd_array_new(&codec->nids); if (!item) return -ENOMEM; item->kctl = kctl; item->index = index; item->nid = nid; return 0; } return -EINVAL; } EXPORT_SYMBOL_HDA(snd_hda_add_nid); /** /** * snd_hda_ctls_clear - Clear all controls assigned to the given codec * snd_hda_ctls_clear - Clear all controls assigned to the given codec * @codec: HD-audio codec * @codec: HD-audio codec Loading @@ -1757,6 +1795,7 @@ void snd_hda_ctls_clear(struct hda_codec *codec) for (i = 0; i < codec->mixers.used; i++) for (i = 0; i < codec->mixers.used; i++) snd_ctl_remove(codec->bus->card, items[i].kctl); snd_ctl_remove(codec->bus->card, items[i].kctl); snd_array_free(&codec->mixers); snd_array_free(&codec->mixers); snd_array_free(&codec->nids); } } /* pseudo device locking /* pseudo device locking Loading Loading @@ -3476,6 +3515,8 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew) for (; knew->name; knew++) { for (; knew->name; knew++) { struct snd_kcontrol *kctl; struct snd_kcontrol *kctl; if (knew->iface == -1) /* skip this codec private value */ continue; kctl = snd_ctl_new1(knew, codec); kctl = snd_ctl_new1(knew, codec); if (!kctl) if (!kctl) return -ENOMEM; return -ENOMEM; Loading @@ -3496,6 +3537,32 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew) } } EXPORT_SYMBOL_HDA(snd_hda_add_new_ctls); EXPORT_SYMBOL_HDA(snd_hda_add_new_ctls); /** * snd_hda_add_nids - assign nids to controls from the array * @codec: the HDA codec * @kctl: struct snd_kcontrol * @index: index to kctl * @nids: the array of hda_nid_t * @size: count of hda_nid_t items * * This helper function assigns NIDs in the given array to a control element. * * Returns 0 if successful, or a negative error code. */ int snd_hda_add_nids(struct hda_codec *codec, struct snd_kcontrol *kctl, unsigned int index, hda_nid_t *nids, unsigned int size) { int err; for ( ; size > 0; size--, nids++) { err = snd_hda_add_nid(codec, kctl, index, *nids); if (err < 0) return err; } return 0; } EXPORT_SYMBOL_HDA(snd_hda_add_nids); #ifdef CONFIG_SND_HDA_POWER_SAVE #ifdef CONFIG_SND_HDA_POWER_SAVE static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, unsigned int power_state); unsigned int power_state); Loading
sound/pci/hda/hda_codec.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -789,6 +789,7 @@ struct hda_codec { u32 *wcaps; u32 *wcaps; struct snd_array mixers; /* list of assigned mixer elements */ struct snd_array mixers; /* list of assigned mixer elements */ struct snd_array nids; /* list of mapped mixer elements */ struct hda_cache_rec amp_cache; /* cache for amp access */ struct hda_cache_rec amp_cache; /* cache for amp access */ struct hda_cache_rec cmd_cache; /* cache for other commands */ struct hda_cache_rec cmd_cache; /* cache for other commands */ Loading
sound/pci/hda/hda_generic.c +2 −1 Original line number Original line Diff line number Diff line Loading @@ -861,7 +861,8 @@ 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, 0, snd_ctl_new1(&cap_sel, codec)); err = snd_hda_ctl_add(codec, spec->adc_node->nid, snd_ctl_new1(&cap_sel, codec)); if (err < 0) if (err < 0) return err; return err; Loading
sound/pci/hda/hda_local.h +13 −3 Original line number Original line Diff line number Diff line Loading @@ -31,6 +31,7 @@ * in snd_hda_ctl_add(), so that this value won't appear in the outside. * in snd_hda_ctl_add(), so that this value won't appear in the outside. */ */ #define HDA_SUBDEV_NID_FLAG (1U << 31) #define HDA_SUBDEV_NID_FLAG (1U << 31) #define HDA_SUBDEV_AMP_FLAG (1U << 30) /* /* * for mixer controls * for mixer controls Loading @@ -42,7 +43,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), \ .subdevice = HDA_SUBDEV_AMP_FLAG, \ .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, \ Loading @@ -63,7 +64,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), \ .subdevice = HDA_SUBDEV_AMP_FLAG, \ .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, \ Loading @@ -81,7 +82,7 @@ /* special beep mono mute switch with index (index=0,1,...) (channel=1,2) */ /* 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) \ #define HDA_CODEC_MUTE_BEEP_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), \ .subdevice = HDA_SUBDEV_AMP_FLAG, \ .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_beep, \ .put = snd_hda_mixer_amp_switch_put_beep, \ Loading Loading @@ -342,6 +343,8 @@ int snd_hda_check_board_codec_sid_config(struct hda_codec *codec, const struct snd_pci_quirk *tbl); const struct snd_pci_quirk *tbl); int snd_hda_add_new_ctls(struct hda_codec *codec, int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew); struct snd_kcontrol_new *knew); int snd_hda_add_nids(struct hda_codec *codec, struct snd_kcontrol *kctl, unsigned int index, hda_nid_t *nids, unsigned int size); /* /* * unsolicited event handler * unsolicited event handler Loading Loading @@ -464,13 +467,20 @@ 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); 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_jack_detect(struct hda_codec *codec, hda_nid_t nid); /* flags for hda_nid_item */ #define HDA_NID_ITEM_AMP (1<<0) struct hda_nid_item { struct hda_nid_item { struct snd_kcontrol *kctl; struct snd_kcontrol *kctl; unsigned int index; hda_nid_t nid; hda_nid_t nid; unsigned short flags; }; }; int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid, int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid, struct snd_kcontrol *kctl); struct snd_kcontrol *kctl); int snd_hda_add_nid(struct hda_codec *codec, struct snd_kcontrol *kctl, unsigned int index, hda_nid_t nid); void snd_hda_ctls_clear(struct hda_codec *codec); void snd_hda_ctls_clear(struct hda_codec *codec); /* /* Loading
sound/pci/hda/hda_proc.c +22 −9 Original line number Original line Diff line number Diff line Loading @@ -61,18 +61,29 @@ 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, static void print_nid_array(struct snd_info_buffer *buffer, struct hda_codec *codec, hda_nid_t nid) struct hda_codec *codec, hda_nid_t nid, struct snd_array *array) { { int i; int i; struct hda_nid_item *items = codec->mixers.list; struct hda_nid_item *items = array->list, *item; struct snd_kcontrol *kctl; struct snd_kcontrol *kctl; for (i = 0; i < codec->mixers.used; i++) { for (i = 0; i < array->used; i++) { if (items[i].nid == nid) { item = &items[i]; kctl = items[i].kctl; if (item->nid == nid) { kctl = item->kctl; snd_iprintf(buffer, snd_iprintf(buffer, " Control: name=\"%s\", index=%i, device=%i\n", " Control: name=\"%s\", index=%i, device=%i\n", kctl->id.name, kctl->id.index, kctl->id.device); kctl->id.name, kctl->id.index + item->index, kctl->id.device); if (item->flags & HDA_NID_ITEM_AMP) snd_iprintf(buffer, " ControlAmp: chs=%lu, dir=%s, " "idx=%lu, ofs=%lu\n", get_amp_channels(kctl), get_amp_direction(kctl) ? "Out" : "In", get_amp_index(kctl), get_amp_offset(kctl)); } } } } } } Loading Loading @@ -528,7 +539,8 @@ 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); print_nid_array(buffer, codec, nid, &codec->mixers); print_nid_array(buffer, codec, nid, &codec->nids); } } static void print_codec_info(struct snd_info_entry *entry, static void print_codec_info(struct snd_info_entry *entry, Loading Loading @@ -608,7 +620,8 @@ 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_array(buffer, codec, nid, &codec->mixers); print_nid_array(buffer, codec, nid, &codec->nids); print_nid_pcms(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 Loading