lkml.org 
[lkml]   [2011]   [Nov]   [18]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[02/26] ALSA: hda - Dont add elements of other codecs to vmaster slave
    3.1-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Takashi Iwai <tiwai@suse.de>

    commit aeb4b88ec0a948efce8e3a23a8f964d3560a7308 upstream.

    When a virtual mater control is created, the driver looks for slave
    elements from the assigned card instance. But this may include the
    elements of other codecs when multiple codecs are on the same HD-audio
    bus. This works at the first time, but it'll give Oops when it's once
    freed and re-created via reconfig sysfs.

    This patch changes the element-look-up strategy to limit only to the
    mixer elements of the same codec.

    Reported-by: David Henningsson <david.henningsson@canonical.com>
    Signed-off-by: Takashi Iwai <tiwai@suse.de>
    Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

    ---
    sound/pci/hda/hda_codec.c | 60 +++++++++++++++++++++++++++++-----------------
    1 file changed, 39 insertions(+), 21 deletions(-)

    --- a/sound/pci/hda/hda_codec.c
    +++ b/sound/pci/hda/hda_codec.c
    @@ -2296,6 +2296,39 @@ int snd_hda_codec_reset(struct hda_codec
    return 0;
    }

    +typedef int (*map_slave_func_t)(void *, struct snd_kcontrol *);
    +
    +/* apply the function to all matching slave ctls in the mixer list */
    +static int map_slaves(struct hda_codec *codec, const char * const *slaves,
    + map_slave_func_t func, void *data)
    +{
    + struct hda_nid_item *items;
    + const char * const *s;
    + int i, err;
    +
    + items = codec->mixers.list;
    + for (i = 0; i < codec->mixers.used; i++) {
    + struct snd_kcontrol *sctl = items[i].kctl;
    + if (!sctl || !sctl->id.name ||
    + sctl->id.iface != SNDRV_CTL_ELEM_IFACE_MIXER)
    + continue;
    + for (s = slaves; *s; s++) {
    + if (!strcmp(sctl->id.name, *s)) {
    + err = func(data, sctl);
    + if (err)
    + return err;
    + break;
    + }
    + }
    + }
    + return 0;
    +}
    +
    +static int check_slave_present(void *data, struct snd_kcontrol *sctl)
    +{
    + return 1;
    +}
    +
    /**
    * snd_hda_add_vmaster - create a virtual master control and add slaves
    * @codec: HD-audio codec
    @@ -2316,12 +2349,10 @@ int snd_hda_add_vmaster(struct hda_codec
    unsigned int *tlv, const char * const *slaves)
    {
    struct snd_kcontrol *kctl;
    - const char * const *s;
    int err;

    - for (s = slaves; *s && !snd_hda_find_mixer_ctl(codec, *s); s++)
    - ;
    - if (!*s) {
    + err = map_slaves(codec, slaves, check_slave_present, NULL);
    + if (err != 1) {
    snd_printdd("No slave found for %s\n", name);
    return 0;
    }
    @@ -2332,23 +2363,10 @@ int snd_hda_add_vmaster(struct hda_codec
    if (err < 0)
    return err;

    - for (s = slaves; *s; s++) {
    - struct snd_kcontrol *sctl;
    - int i = 0;
    - for (;;) {
    - sctl = _snd_hda_find_mixer_ctl(codec, *s, i);
    - if (!sctl) {
    - if (!i)
    - snd_printdd("Cannot find slave %s, "
    - "skipped\n", *s);
    - break;
    - }
    - err = snd_ctl_add_slave(kctl, sctl);
    - if (err < 0)
    - return err;
    - i++;
    - }
    - }
    + err = map_slaves(codec, slaves, (map_slave_func_t)snd_ctl_add_slave,
    + kctl);
    + if (err < 0)
    + return err;
    return 0;
    }
    EXPORT_SYMBOL_HDA(snd_hda_add_vmaster);



    \
     
     \ /
      Last update: 2011-11-19 01:13    [W:0.023 / U:34.240 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site