diff options
author | Takashi Iwai <tiwai@suse.de> | 2013-02-07 18:18:19 +0100 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2013-02-07 20:01:08 +0100 |
commit | 4eea30914facd2c99061cd70e5b05d3c76c743a2 (patch) | |
tree | b65f4322f33b80f20211962fe337d4eb2b50b630 /sound/pci/hda/hda_proc.c | |
parent | c1279f8787f9cddd2f4a7d6abc15375b30b80501 (diff) | |
download | linux-4eea30914facd2c99061cd70e5b05d3c76c743a2.tar.bz2 |
ALSA: hda - Remove limit of widget connections
Currently we set the max number of connections to be 32, but there
seems codec that gives longer connection lists like AD1988, and we see
errors in proc output and else. (Though, in the case of AD1988, it's
a list of all codecs connected to a single vendor widget, so this must
be something fishy, but it's still valid from the h/w design POV.)
This patch tries to remove this restriction. For efficiency, we still
use the fixed size array in the parser, but takes a dynamic array when
the size is reported to be greater than that.
Now the fixed array size is found only in patch_hdmi.c, but it should
be fine, as the codec itself can't support so many pins.
Reported-by: Raymond Yau <superquad.vortex2@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/hda_proc.c')
-rw-r--r-- | sound/pci/hda/hda_proc.c | 20 |
1 files changed, 16 insertions, 4 deletions
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index 5e02f26606b6..0fee8fae590a 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c @@ -22,6 +22,7 @@ */ #include <linux/init.h> +#include <linux/slab.h> #include <sound/core.h> #include "hda_codec.h" #include "hda_local.h" @@ -623,7 +624,7 @@ static void print_codec_info(struct snd_info_entry *entry, snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP); unsigned int wid_type = get_wcaps_type(wid_caps); - hda_nid_t conn[HDA_MAX_CONNECTIONS]; + hda_nid_t *conn = NULL; int conn_len = 0; snd_iprintf(buffer, "Node 0x%02x [%s] wcaps 0x%x:", nid, @@ -660,9 +661,18 @@ static void print_codec_info(struct snd_info_entry *entry, if (wid_type == AC_WID_VOL_KNB) wid_caps |= AC_WCAP_CONN_LIST; - if (wid_caps & AC_WCAP_CONN_LIST) - conn_len = snd_hda_get_raw_connections(codec, nid, conn, - HDA_MAX_CONNECTIONS); + if (wid_caps & AC_WCAP_CONN_LIST) { + conn_len = snd_hda_get_num_raw_conns(codec, nid); + if (conn_len > 0) { + conn = kmalloc(sizeof(hda_nid_t) * conn_len, + GFP_KERNEL); + if (!conn) + return; + if (snd_hda_get_raw_connections(codec, nid, conn, + conn_len) < 0) + conn_len = 0; + } + } if (wid_caps & AC_WCAP_IN_AMP) { snd_iprintf(buffer, " Amp-In caps: "); @@ -735,6 +745,8 @@ static void print_codec_info(struct snd_info_entry *entry, if (codec->proc_widget_hook) codec->proc_widget_hook(buffer, codec, nid); + + kfree(conn); } snd_hda_power_down(codec); } |