aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/hda_codec.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2009-03-24 02:32:14 -0400
committerTakashi Iwai <tiwai@suse.de>2009-04-21 05:10:39 -0400
commit92c7c8a7d6e03eb4c0a3c5888e35dbc45f24744c (patch)
treef5c8b17029960b6f6bc13d8354c587d300560014 /sound/pci/hda/hda_codec.c
parentc441c2971de52b7045acb708cc9959815f554f66 (diff)
ALSA: hda - Cache PCM and STREAM parameters queries
Cache quries for PCM and STREAM parameters as well as ampcap and pincap sharing the hash table. This will reduce the superfluous access of the same codec verbs. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/hda_codec.c')
-rw-r--r--sound/pci/hda/hda_codec.c97
1 files changed, 61 insertions, 36 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index a4e5e5952115..3d8bf39e6d98 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -1053,6 +1053,8 @@ EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup_stream);
1053/* FIXME: more better hash key? */ 1053/* FIXME: more better hash key? */
1054#define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24)) 1054#define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24))
1055#define HDA_HASH_PINCAP_KEY(nid) (u32)((nid) + (0x02 << 24)) 1055#define HDA_HASH_PINCAP_KEY(nid) (u32)((nid) + (0x02 << 24))
1056#define HDA_HASH_PARPCM_KEY(nid) (u32)((nid) + (0x03 << 24))
1057#define HDA_HASH_PARSTR_KEY(nid) (u32)((nid) + (0x04 << 24))
1056#define INFO_AMP_CAPS (1<<0) 1058#define INFO_AMP_CAPS (1<<0)
1057#define INFO_AMP_VOL(ch) (1 << (1 + (ch))) 1059#define INFO_AMP_VOL(ch) (1 << (1 + (ch)))
1058 1060
@@ -1143,19 +1145,32 @@ int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
1143} 1145}
1144EXPORT_SYMBOL_HDA(snd_hda_override_amp_caps); 1146EXPORT_SYMBOL_HDA(snd_hda_override_amp_caps);
1145 1147
1146u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid) 1148static unsigned int
1149query_caps_hash(struct hda_codec *codec, hda_nid_t nid, u32 key,
1150 unsigned int (*func)(struct hda_codec *, hda_nid_t))
1147{ 1151{
1148 struct hda_amp_info *info; 1152 struct hda_amp_info *info;
1149 1153
1150 info = get_alloc_amp_hash(codec, HDA_HASH_PINCAP_KEY(nid)); 1154 info = get_alloc_amp_hash(codec, key);
1151 if (!info) 1155 if (!info)
1152 return 0; 1156 return 0;
1153 if (!info->head.val) { 1157 if (!info->head.val) {
1154 info->amp_caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
1155 info->head.val |= INFO_AMP_CAPS; 1158 info->head.val |= INFO_AMP_CAPS;
1159 info->amp_caps = func(codec, nid);
1156 } 1160 }
1157 return info->amp_caps; 1161 return info->amp_caps;
1158} 1162}
1163
1164static unsigned int read_pin_cap(struct hda_codec *codec, hda_nid_t nid)
1165{
1166 return snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
1167}
1168
1169u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid)
1170{
1171 return query_caps_hash(codec, nid, HDA_HASH_PINCAP_KEY(nid),
1172 read_pin_cap);
1173}
1159EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps); 1174EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps);
1160 1175
1161/* 1176/*
@@ -2538,6 +2553,41 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate,
2538} 2553}
2539EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format); 2554EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format);
2540 2555
2556static unsigned int get_pcm_param(struct hda_codec *codec, hda_nid_t nid)
2557{
2558 unsigned int val = 0;
2559 if (nid != codec->afg &&
2560 (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD))
2561 val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
2562 if (!val || val == -1)
2563 val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
2564 if (!val || val == -1)
2565 return 0;
2566 return val;
2567}
2568
2569static unsigned int query_pcm_param(struct hda_codec *codec, hda_nid_t nid)
2570{
2571 return query_caps_hash(codec, nid, HDA_HASH_PARPCM_KEY(nid),
2572 get_pcm_param);
2573}
2574
2575static unsigned int get_stream_param(struct hda_codec *codec, hda_nid_t nid)
2576{
2577 unsigned int streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
2578 if (!streams || streams == -1)
2579 streams = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM);
2580 if (!streams || streams == -1)
2581 return 0;
2582 return streams;
2583}
2584
2585static unsigned int query_stream_param(struct hda_codec *codec, hda_nid_t nid)
2586{
2587 return query_caps_hash(codec, nid, HDA_HASH_PARSTR_KEY(nid),
2588 get_stream_param);
2589}
2590
2541/** 2591/**
2542 * snd_hda_query_supported_pcm - query the supported PCM rates and formats 2592 * snd_hda_query_supported_pcm - query the supported PCM rates and formats
2543 * @codec: the HDA codec 2593 * @codec: the HDA codec
@@ -2556,15 +2606,8 @@ static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
2556{ 2606{
2557 unsigned int i, val, wcaps; 2607 unsigned int i, val, wcaps;
2558 2608
2559 val = 0;
2560 wcaps = get_wcaps(codec, nid); 2609 wcaps = get_wcaps(codec, nid);
2561 if (nid != codec->afg && (wcaps & AC_WCAP_FORMAT_OVRD)) { 2610 val = query_pcm_param(codec, nid);
2562 val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
2563 if (val == -1)
2564 return -EIO;
2565 }
2566 if (!val)
2567 val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
2568 2611
2569 if (ratesp) { 2612 if (ratesp) {
2570 u32 rates = 0; 2613 u32 rates = 0;
@@ -2586,15 +2629,9 @@ static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
2586 u64 formats = 0; 2629 u64 formats = 0;
2587 unsigned int streams, bps; 2630 unsigned int streams, bps;
2588 2631
2589 streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM); 2632 streams = query_stream_param(codec, nid);
2590 if (streams == -1) 2633 if (!streams)
2591 return -EIO; 2634 return -EIO;
2592 if (!streams) {
2593 streams = snd_hda_param_read(codec, codec->afg,
2594 AC_PAR_STREAM);
2595 if (streams == -1)
2596 return -EIO;
2597 }
2598 2635
2599 bps = 0; 2636 bps = 0;
2600 if (streams & AC_SUPFMT_PCM) { 2637 if (streams & AC_SUPFMT_PCM) {
@@ -2668,17 +2705,9 @@ int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
2668 int i; 2705 int i;
2669 unsigned int val = 0, rate, stream; 2706 unsigned int val = 0, rate, stream;
2670 2707
2671 if (nid != codec->afg && 2708 val = query_pcm_param(codec, nid);
2672 (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD)) { 2709 if (!val)
2673 val = snd_hda_param_read(codec, nid, AC_PAR_PCM); 2710 return 0;
2674 if (val == -1)
2675 return 0;
2676 }
2677 if (!val) {
2678 val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
2679 if (val == -1)
2680 return 0;
2681 }
2682 2711
2683 rate = format & 0xff00; 2712 rate = format & 0xff00;
2684 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++) 2713 for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++)
@@ -2690,12 +2719,8 @@ int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
2690 if (i >= AC_PAR_PCM_RATE_BITS) 2719 if (i >= AC_PAR_PCM_RATE_BITS)
2691 return 0; 2720 return 0;
2692 2721
2693 stream = snd_hda_param_read(codec, nid, AC_PAR_STREAM); 2722 stream = query_stream_param(codec, nid);
2694 if (stream == -1) 2723 if (!stream)
2695 return 0;
2696 if (!stream && nid != codec->afg)
2697 stream = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM);
2698 if (!stream || stream == -1)
2699 return 0; 2724 return 0;
2700 2725
2701 if (stream & AC_SUPFMT_PCM) { 2726 if (stream & AC_SUPFMT_PCM) {