summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2011-06-28 12:45:47 +0200
committerTakashi Iwai <tiwai@suse.de>2011-06-29 08:01:46 +0200
commit8d087c7600499463b7b8e3d4da4da40669cb8bfa (patch)
tree817ba350193d4c1cd77546dbd0bbe0d68ee14ecf
parent63f10d2ca78c17cdd612c1daee7daffacca8b7fb (diff)
ALSA: hda - Create snd_hda_get_conn_index() helper function
Create snd_hda_get_conn_index() helper function for obtaining the connection index of the widget. Replaced the similar codes used in several codec-drivers with this common helper. Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/pci/hda/hda_codec.c42
-rw-r--r--sound/pci/hda/hda_codec.h2
-rw-r--r--sound/pci/hda/patch_cirrus.c16
-rw-r--r--sound/pci/hda/patch_cmedia.c11
-rw-r--r--sound/pci/hda/patch_conexant.c15
-rw-r--r--sound/pci/hda/patch_realtek.c14
-rw-r--r--sound/pci/hda/patch_sigmatel.c27
-rw-r--r--sound/pci/hda/patch_via.c40
8 files changed, 59 insertions, 108 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 26c420de91c3..7f8502388a82 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -411,11 +411,8 @@ static int _hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
wcaps = get_wcaps(codec, nid);
if (!(wcaps & AC_WCAP_CONN_LIST) &&
- get_wcaps_type(wcaps) != AC_WID_VOL_KNB) {
- snd_printk(KERN_WARNING "hda_codec: "
- "connection list not available for 0x%x\n", nid);
- return -EINVAL;
- }
+ get_wcaps_type(wcaps) != AC_WID_VOL_KNB)
+ return 0;
parm = snd_hda_param_read(codec, nid, AC_PAR_CONNLIST_LEN);
if (parm & AC_CLIST_LONG) {
@@ -506,6 +503,41 @@ static bool add_conn_list(struct snd_array *array, hda_nid_t nid)
}
/**
+ * snd_hda_get_conn_index - get the connection index of the given NID
+ * @codec: the HDA codec
+ * @mux: NID containing the list
+ * @nid: NID to select
+ * @recursive: 1 when searching NID recursively, otherwise 0
+ *
+ * Parses the connection list of the widget @mux and checks whether the
+ * widget @nid is present. If it is, return the connection index.
+ * Otherwise it returns -1.
+ */
+int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux,
+ hda_nid_t nid, int recursive)
+{
+ hda_nid_t conn[HDA_MAX_NUM_INPUTS];
+ int i, nums;
+
+ nums = snd_hda_get_connections(codec, mux, conn, ARRAY_SIZE(conn));
+ for (i = 0; i < nums; i++)
+ if (conn[i] == nid)
+ return i;
+ if (!recursive)
+ return -1;
+ if (recursive > 5) {
+ snd_printd("hda_codec: too deep connection for 0x%x\n", nid);
+ return -1;
+ }
+ recursive++;
+ for (i = 0; i < nums; i++)
+ if (snd_hda_get_conn_index(codec, conn[i], nid, recursive) >= 0)
+ return i;
+ return -1;
+}
+EXPORT_SYMBOL_HDA(snd_hda_get_conn_index);
+
+/**
* snd_hda_queue_unsol_event - add an unsolicited event to queue
* @bus: the BUS
* @res: unsolicited event (lower 32bit of RIRB entry)
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 79ef65e3ae14..10d500d2ba33 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -905,6 +905,8 @@ int snd_hda_get_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,
const hda_nid_t **listp);
+int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux,
+ hda_nid_t nid, int recursive);
int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
u32 *ratesp, u64 *formatsp, unsigned int *bpsp);
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c
index c7b5ca28fa77..7f93739b1e33 100644
--- a/sound/pci/hda/patch_cirrus.c
+++ b/sound/pci/hda/patch_cirrus.c
@@ -346,21 +346,15 @@ static hda_nid_t get_adc(struct hda_codec *codec, hda_nid_t pin,
nid = codec->start_nid;
for (i = 0; i < codec->num_nodes; i++, nid++) {
- hda_nid_t pins[2];
unsigned int type;
- int j, nums;
+ int idx;
type = get_wcaps_type(get_wcaps(codec, nid));
if (type != AC_WID_AUD_IN)
continue;
- nums = snd_hda_get_connections(codec, nid, pins,
- ARRAY_SIZE(pins));
- if (nums <= 0)
- continue;
- for (j = 0; j < nums; j++) {
- if (pins[j] == pin) {
- *idxp = j;
- return nid;
- }
+ idx = snd_hda_get_conn_index(codec, nid, pin, 0);
+ if (idx >= 0) {
+ *idxp = idx;
+ return nid;
}
}
return 0;
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c
index 9eaf99b01aec..08af4847c07a 100644
--- a/sound/pci/hda/patch_cmedia.c
+++ b/sound/pci/hda/patch_cmedia.c
@@ -403,7 +403,6 @@ static int cmi9880_fill_multi_init(struct hda_codec *codec, const struct auto_pi
/* clear the table, only one c-media dac assumed here */
memset(spec->multi_init, 0, sizeof(spec->multi_init));
for (j = 0, i = 0; i < cfg->line_outs; i++) {
- hda_nid_t conn[4];
nid = cfg->line_out_pins[i];
/* set as output */
spec->multi_init[j].nid = nid;
@@ -416,12 +415,10 @@ static int cmi9880_fill_multi_init(struct hda_codec *codec, const struct auto_pi
spec->multi_init[j].verb = AC_VERB_SET_CONNECT_SEL;
spec->multi_init[j].param = 0;
/* find the index in connect list */
- len = snd_hda_get_connections(codec, nid, conn, 4);
- for (k = 0; k < len; k++)
- if (conn[k] == spec->dac_nids[i]) {
- spec->multi_init[j].param = k;
- break;
- }
+ k = snd_hda_get_conn_index(codec, nid,
+ spec->dac_nids[i], 0);
+ if (k >= 0)
+ spec->multi_init[j].param = k;
j++;
}
}
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 6e864276b744..40cf7f16f587 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -3308,19 +3308,8 @@ static const struct hda_pcm_stream cx_auto_pcm_analog_capture = {
static const hda_nid_t cx_auto_adc_nids[] = { 0x14 };
-/* get the connection index of @nid in the widget @mux */
-static int get_connection_index(struct hda_codec *codec, hda_nid_t mux,
- hda_nid_t nid)
-{
- hda_nid_t conn[HDA_MAX_NUM_INPUTS];
- int i, nums;
-
- nums = snd_hda_get_connections(codec, mux, conn, ARRAY_SIZE(conn));
- for (i = 0; i < nums; i++)
- if (conn[i] == nid)
- return i;
- return -1;
-}
+#define get_connection_index(codec, mux, nid)\
+ snd_hda_get_conn_index(codec, mux, nid, 0)
/* get an unassigned DAC from the given list.
* Return the nid if found and reduce the DAC list, or return zero if
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index cf383ede281d..7b96dcef2c62 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -1195,18 +1195,8 @@ static void alc_line_automute(struct hda_codec *codec)
update_speakers(codec);
}
-static int get_connection_index(struct hda_codec *codec, hda_nid_t mux,
- hda_nid_t nid)
-{
- hda_nid_t conn[HDA_MAX_NUM_INPUTS];
- int i, nums;
-
- nums = snd_hda_get_connections(codec, mux, conn, ARRAY_SIZE(conn));
- for (i = 0; i < nums; i++)
- if (conn[i] == nid)
- return i;
- return -1;
-}
+#define get_connection_index(codec, mux, nid) \
+ snd_hda_get_conn_index(codec, mux, nid, 0)
/* switch the current ADC according to the jack state */
static void alc_dual_mic_adc_auto_switch(struct hda_codec *codec)
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 7407095cbc78..56425a53cf1b 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -3408,30 +3408,9 @@ static hda_nid_t get_connected_node(struct hda_codec *codec, hda_nid_t mux,
return 0;
}
-static int get_connection_index(struct hda_codec *codec, hda_nid_t mux,
- hda_nid_t nid)
-{
- hda_nid_t conn[HDA_MAX_NUM_INPUTS];
- int i, nums;
-
- if (!(get_wcaps(codec, mux) & AC_WCAP_CONN_LIST))
- return -1;
-
- nums = snd_hda_get_connections(codec, mux, conn, ARRAY_SIZE(conn));
- for (i = 0; i < nums; i++)
- if (conn[i] == nid)
- return i;
-
- for (i = 0; i < nums; i++) {
- unsigned int wid_caps = get_wcaps(codec, conn[i]);
- unsigned int wid_type = get_wcaps_type(wid_caps);
-
- if (wid_type != AC_WID_PIN && wid_type != AC_WID_AUD_MIX)
- if (get_connection_index(codec, conn[i], nid) >= 0)
- return i;
- }
- return -1;
-}
+/* look for NID recursively */
+#define get_connection_index(codec, mux, nid) \
+ snd_hda_get_conn_index(codec, mux, nid, 1)
/* create a volume assigned to the given pin (only if supported) */
/* return 1 if the volume control is created */
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index 997b7057a549..76142c1389d7 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -410,27 +410,8 @@ static int via_new_analog_input(struct via_spec *spec, const char *ctlname,
return 0;
}
-/* return the index of the given widget nid as the source of mux;
- * return -1 if not found;
- * if num_conns is non-NULL, set the total number of connections
- */
-static int __get_connection_index(struct hda_codec *codec, hda_nid_t mux,
- hda_nid_t nid, int *num_conns)
-{
- hda_nid_t conn[HDA_MAX_NUM_INPUTS];
- int i, nums;
-
- nums = snd_hda_get_connections(codec, mux, conn, ARRAY_SIZE(conn));
- if (num_conns)
- *num_conns = nums;
- for (i = 0; i < nums; i++)
- if (conn[i] == nid)
- return i;
- return -1;
-}
-
#define get_connection_index(codec, mux, nid) \
- __get_connection_index(codec, mux, nid, NULL)
+ snd_hda_get_conn_index(codec, mux, nid, 0)
static bool check_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
unsigned int mask)
@@ -2011,23 +1992,10 @@ static void add_loopback_list(struct via_spec *spec, hda_nid_t mix, int idx)
spec->loopback.amplist = spec->loopback_list;
}
-/* check whether the path from src to dst is reachable */
static bool is_reachable_nid(struct hda_codec *codec, hda_nid_t src,
- hda_nid_t dst, int depth)
+ hda_nid_t dst)
{
- hda_nid_t conn[8];
- int i, nums;
-
- nums = snd_hda_get_connections(codec, src, conn, ARRAY_SIZE(conn));
- for (i = 0; i < nums; i++)
- if (conn[i] == dst)
- return true;
- if (++depth > MAX_NID_PATH_DEPTH)
- return false;
- for (i = 0; i < nums; i++)
- if (is_reachable_nid(codec, conn[i], dst, depth))
- return true;
- return false;
+ return snd_hda_get_conn_index(codec, src, dst, 1) >= 0;
}
/* add the input-route to the given pin */
@@ -2046,7 +2014,7 @@ static bool add_input_route(struct hda_codec *codec, hda_nid_t pin)
continue;
spec->inputs[spec->num_inputs].mux_idx = idx;
} else {
- if (!is_reachable_nid(codec, spec->adc_nids[c], pin, 0))
+ if (!is_reachable_nid(codec, spec->adc_nids[c], pin))
continue;
}
spec->inputs[spec->num_inputs].adc_idx = c;