aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-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) {