ALSA: hda - Create snd_hda_get_conn_index() helper function
authorTakashi Iwai <tiwai@suse.de>
Tue, 28 Jun 2011 10:45:47 +0000 (12:45 +0200)
committerTakashi Iwai <tiwai@suse.de>
Wed, 29 Jun 2011 06:01:46 +0000 (08:01 +0200)
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>
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_codec.h
sound/pci/hda/patch_cirrus.c
sound/pci/hda/patch_cmedia.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/pci/hda/patch_via.c

index 26c420de91c3c3eeb88777f847ae962ba984df40..7f8502388a822ec3c194f3b87847f67800b243f7 100644 (file)
@@ -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) {
@@ -505,6 +502,41 @@ static bool add_conn_list(struct snd_array *array, hda_nid_t nid)
        return true;
 }
 
+/**
+ * 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
index 79ef65e3ae14a9f158dcb677d8aa136633326031..10d500d2ba33fa51bd8743face2301f1169fb0e9 100644 (file)
@@ -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);
 
index c7b5ca28fa775ead21c4149c3ebb4e7e3d127a7d..7f93739b1e3339cf131d13f5372c9f5da9abf401 100644 (file)
@@ -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;
index 9eaf99b01aecdf5172336dd5f642e463b2e66154..08af4847c07a75ea863052625056a86d99203b34 100644 (file)
@@ -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++;
                }
        }
index 6e864276b74492e94fa54c7236d0659aa4fa4c44..40cf7f16f58730ade3ce7e4924bca80ca44fed54 100644 (file)
@@ -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
index cf383ede281dd9ddbee40d7d68298f666f2f2bf9..7b96dcef2c6250e123e6c54ca5ff2d4187e55ddd 100644 (file)
@@ -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)
index 7407095cbc78c0894794748661bb15916621fd5f..56425a53cf1bbbc3c8a71f6d249c0ad66bae6868 100644 (file)
@@ -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 */
index 997b7057a549ca208ca7e67069529527e358b1f9..76142c1389d748887c1b1e3fd81a5c2ad606699f 100644 (file)
@@ -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;