ALSA: hda - Cache pin-cap values
authorTakashi Iwai <tiwai@suse.de>
Mon, 23 Mar 2009 12:07:47 +0000 (13:07 +0100)
committerTakashi Iwai <tiwai@suse.de>
Mon, 23 Mar 2009 12:08:33 +0000 (13:08 +0100)
Added snd_hda_query_pin_caps() to read and cache pin-cap values
to avoid too frequently issuing the same verbs.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_generic.c
sound/pci/hda/hda_local.h
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c

index 1b5575ecb0a4d3bb9416b07f8cca42b0d8af88bc..0f70d2d102e0da241e0faee271e82bb9fd1286a1 100644 (file)
@@ -1052,6 +1052,7 @@ EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup_stream);
 
 /* FIXME: more better hash key? */
 #define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24))
+#define HDA_HASH_PINCAP_KEY(nid) (u32)((nid) + (0x02 << 24))
 #define INFO_AMP_CAPS  (1<<0)
 #define INFO_AMP_VOL(ch)       (1 << (1 + (ch)))
 
@@ -1142,6 +1143,21 @@ int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
 }
 EXPORT_SYMBOL_HDA(snd_hda_override_amp_caps);
 
+u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid)
+{
+       struct hda_amp_info *info;
+
+       info = get_alloc_amp_hash(codec, HDA_HASH_PINCAP_KEY(nid));
+       if (!info)
+               return 0;
+       if (!info->head.val) {
+               info->amp_caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
+               info->head.val |= INFO_AMP_CAPS;
+       }
+       return info->amp_caps;
+}
+EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps);
+
 /*
  * read the current volume to info
  * if the cache exists, read the cache value.
index 2c81a683e8f8367ec964313a5f1cb29015c23e62..1d5797a966821aa197460ee1836d99452493c595 100644 (file)
@@ -144,7 +144,7 @@ static int add_new_node(struct hda_codec *codec, struct hda_gspec *spec, hda_nid
        node->type = (node->wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
 
        if (node->type == AC_WID_PIN) {
-               node->pin_caps = snd_hda_param_read(codec, node->nid, AC_PAR_PIN_CAP);
+               node->pin_caps = snd_hda_query_pin_caps(codec, node->nid);
                node->pin_ctl = snd_hda_codec_read(codec, node->nid, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
                node->def_cfg = snd_hda_codec_get_pincfg(codec, node->nid);
        }
index 27428c718fd7199297fa07e78acc6c081d02c55f..83349013b4df1bcd5e8d5ea762153a1e3049920c 100644 (file)
@@ -411,6 +411,7 @@ static inline u32 get_wcaps(struct hda_codec *codec, hda_nid_t nid)
 u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction);
 int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
                              unsigned int caps);
+u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid);
 
 int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl);
 void snd_hda_ctls_clear(struct hda_codec *codec);
index 965a531d2fba366a0870fc1a5bf938d4aac1dae3..bf7e64e2c468b457ff0ca1d0eabeb66f2db8363c 100644 (file)
@@ -770,7 +770,7 @@ static void alc_set_input_pin(struct hda_codec *codec, hda_nid_t nid,
 
        if (auto_pin_type <= AUTO_PIN_FRONT_MIC) {
                unsigned int pincap;
-               pincap = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
+               pincap = snd_hda_query_pin_caps(codec, nid);
                pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
                if (pincap & AC_PINCAP_VREF_80)
                        val = PIN_VREF80;
@@ -16746,13 +16746,13 @@ static int alc662_input_pin_idx(struct hda_codec *codec, hda_nid_t nid,
 
 static int alc662_is_input_pin(struct hda_codec *codec, hda_nid_t nid)
 {
-       unsigned int pincap = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
+       unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
        return (pincap & AC_PINCAP_IN) != 0;
 }
 
 static int alc662_is_output_pin(struct hda_codec *codec, hda_nid_t nid)
 {
-       unsigned int pincap = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
+       unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
        return (pincap & AC_PINCAP_OUT) != 0;
 }
 
index 4da72403fc87e52610f17aa3fce8814f3913fa89..b1c180a9e9beb117aaffa5b28a770df60f07e22c 100644 (file)
@@ -2537,8 +2537,7 @@ static int stac92xx_build_pcms(struct hda_codec *codec)
 
 static unsigned int stac92xx_get_vref(struct hda_codec *codec, hda_nid_t nid)
 {
-       unsigned int pincap = snd_hda_param_read(codec, nid,
-                                                AC_PAR_PIN_CAP);
+       unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
        pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
        if (pincap & AC_PINCAP_VREF_100)
                return AC_PINCTL_VREF_100;
@@ -2799,7 +2798,7 @@ static hda_nid_t check_line_out_switch(struct hda_codec *codec)
        if (cfg->line_out_type != AUTO_PIN_LINE_OUT)
                return 0;
        nid = cfg->input_pins[AUTO_PIN_LINE];
-       pincap = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
+       pincap = snd_hda_query_pin_caps(codec, nid);
        if (pincap & AC_PINCAP_OUT)
                return nid;
        return 0;
@@ -2822,7 +2821,7 @@ static hda_nid_t check_mic_out_switch(struct hda_codec *codec)
                /* some laptops have an internal analog microphone
                 * which can't be used as a output */
                if (get_defcfg_connect(def_conf) != AC_JACK_PORT_FIXED) {
-                       pincap = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
+                       pincap = snd_hda_query_pin_caps(codec, nid);
                        if (pincap & AC_PINCAP_OUT)
                                return nid;
                }