From 37b31e24393ea65462718172c4f719b05ddf33c9 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 7 Feb 2013 18:18:19 +0100 Subject: [PATCH] --- yaml --- r: 353279 b: refs/heads/master c: 4eea30914facd2c99061cd70e5b05d3c76c743a2 h: refs/heads/master i: 353277: bea37613401e6c0f98629b6d930b56c1ceace8a0 353275: 16c432d8ba7e9c298ec46862b1cea0892be5ca2f 353271: 20a0e90f42f87e514fb1f4e9326ac12761b93534 353263: 2ff28c920e8a304b93bdfe0a7b6f2c312eb531da 353247: b1518a4b643e5ac744a4447f9c12e63b48b7634e 353215: 37b28b2a64b87b001293962b758167166b1b77e1 353151: b4862814e833df5976a95ae68eb227506c26f827 353023: c7fb17ee1e095d3b3d341fa1002924c14876e6b1 352767: 586b3a985979b1c91ded6a97c72d728d6a607b4b 352255: 8f9982fdf3a441684b407ac383e32c34ca4877a0 v: v3 --- [refs] | 2 +- trunk/sound/pci/hda/hda_codec.c | 62 +++++++++++++++++++++----------- trunk/sound/pci/hda/hda_codec.h | 4 +-- trunk/sound/pci/hda/hda_proc.c | 20 ++++++++--- trunk/sound/pci/hda/patch_hdmi.c | 3 ++ 5 files changed, 62 insertions(+), 29 deletions(-) diff --git a/[refs] b/[refs] index cef41bad98b0..e780f068a3e3 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: c1279f8787f9cddd2f4a7d6abc15375b30b80501 +refs/heads/master: 4eea30914facd2c99061cd70e5b05d3c76c743a2 diff --git a/trunk/sound/pci/hda/hda_codec.c b/trunk/sound/pci/hda/hda_codec.c index f82a64da2f1b..3c925145c119 100644 --- a/trunk/sound/pci/hda/hda_codec.c +++ b/trunk/sound/pci/hda/hda_codec.c @@ -382,13 +382,23 @@ static void remove_conn_list(struct hda_codec *codec) /* read the connection and add to the cache */ static int read_and_add_raw_conns(struct hda_codec *codec, hda_nid_t nid) { - hda_nid_t list[HDA_MAX_CONNECTIONS]; + hda_nid_t list[32]; + hda_nid_t *result = list; int len; len = snd_hda_get_raw_connections(codec, nid, list, ARRAY_SIZE(list)); - if (len < 0) - return len; - return snd_hda_override_conn_list(codec, nid, len, list); + if (len == -ENOSPC) { + len = snd_hda_get_num_raw_conns(codec, nid); + result = kmalloc(sizeof(hda_nid_t) * len, GFP_KERNEL); + if (!result) + return -ENOMEM; + len = snd_hda_get_raw_connections(codec, nid, result, len); + } + if (len >= 0) + len = snd_hda_override_conn_list(codec, nid, len, result); + if (result != list) + kfree(result); + return len; } /** @@ -466,6 +476,27 @@ int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid, } EXPORT_SYMBOL_HDA(snd_hda_get_connections); +/* return CONNLIST_LEN parameter of the given widget */ +static unsigned int get_num_conns(struct hda_codec *codec, hda_nid_t nid) +{ + unsigned int wcaps = get_wcaps(codec, nid); + unsigned int parm; + + if (!(wcaps & AC_WCAP_CONN_LIST) && + get_wcaps_type(wcaps) != AC_WID_VOL_KNB) + return 0; + + parm = snd_hda_param_read(codec, nid, AC_PAR_CONNLIST_LEN); + if (parm == -1) + parm = 0; + return parm; +} + +int snd_hda_get_num_raw_conns(struct hda_codec *codec, hda_nid_t nid) +{ + return get_num_conns(codec, nid) & AC_CLIST_LENGTH; +} + /** * snd_hda_get_raw_connections - copy connection list without cache * @codec: the HDA codec @@ -483,19 +514,16 @@ int snd_hda_get_raw_connections(struct hda_codec *codec, hda_nid_t nid, unsigned int parm; int i, conn_len, conns; unsigned int shift, num_elems, mask; - unsigned int wcaps; hda_nid_t prev_nid; int null_count = 0; if (snd_BUG_ON(!conn_list || max_conns <= 0)) return -EINVAL; - wcaps = get_wcaps(codec, nid); - if (!(wcaps & AC_WCAP_CONN_LIST) && - get_wcaps_type(wcaps) != AC_WID_VOL_KNB) + parm = get_num_conns(codec, nid); + if (!parm) return 0; - parm = snd_hda_param_read(codec, nid, AC_PAR_CONNLIST_LEN); if (parm & AC_CLIST_LONG) { /* long form */ shift = 16; @@ -552,21 +580,13 @@ int snd_hda_get_raw_connections(struct hda_codec *codec, hda_nid_t nid, continue; } for (n = prev_nid + 1; n <= val; n++) { - if (conns >= max_conns) { - snd_printk(KERN_ERR "hda_codec: " - "Too many connections %d for NID 0x%x\n", - conns, nid); - return -EINVAL; - } + if (conns >= max_conns) + return -ENOSPC; conn_list[conns++] = n; } } else { - if (conns >= max_conns) { - snd_printk(KERN_ERR "hda_codec: " - "Too many connections %d for NID 0x%x\n", - conns, nid); - return -EINVAL; - } + if (conns >= max_conns) + return -ENOSPC; conn_list[conns++] = val; } prev_nid = val; diff --git a/trunk/sound/pci/hda/hda_codec.h b/trunk/sound/pci/hda/hda_codec.h index 6c592722efcd..0be18263801b 100644 --- a/trunk/sound/pci/hda/hda_codec.h +++ b/trunk/sound/pci/hda/hda_codec.h @@ -551,9 +551,6 @@ enum { AC_JACK_PORT_BOTH, }; -/* max. connections to a widget */ -#define HDA_MAX_CONNECTIONS 32 - /* max. codec address */ #define HDA_MAX_CODEC_ADDRESS 0x0f @@ -958,6 +955,7 @@ snd_hda_get_num_conns(struct hda_codec *codec, hda_nid_t nid) { return snd_hda_get_connections(codec, nid, NULL, 0); } +int snd_hda_get_num_raw_conns(struct hda_codec *codec, hda_nid_t nid); int snd_hda_get_raw_connections(struct hda_codec *codec, hda_nid_t nid, hda_nid_t *conn_list, int max_conns); int snd_hda_get_conn_list(struct hda_codec *codec, hda_nid_t nid, diff --git a/trunk/sound/pci/hda/hda_proc.c b/trunk/sound/pci/hda/hda_proc.c index 5e02f26606b6..0fee8fae590a 100644 --- a/trunk/sound/pci/hda/hda_proc.c +++ b/trunk/sound/pci/hda/hda_proc.c @@ -22,6 +22,7 @@ */ #include +#include #include #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); } diff --git a/trunk/sound/pci/hda/patch_hdmi.c b/trunk/sound/pci/hda/patch_hdmi.c index 85236da79046..899c4fbbfd83 100644 --- a/trunk/sound/pci/hda/patch_hdmi.c +++ b/trunk/sound/pci/hda/patch_hdmi.c @@ -64,6 +64,9 @@ struct hdmi_spec_per_cvt { unsigned int maxbps; }; +/* max. connections to a widget */ +#define HDA_MAX_CONNECTIONS 32 + struct hdmi_spec_per_pin { hda_nid_t pin_nid; int num_mux_nids;