diff options
author | Takashi Iwai <tiwai@suse.de> | 2009-04-21 05:11:54 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2009-04-21 05:11:54 -0400 |
commit | b97bedcdedb4ae95b2128a4770dfc160e113b174 (patch) | |
tree | c604636b8991e0e53a20e0dbe666a57afe72ea45 | |
parent | 858940773ad5f9dfe32ddb34fa1c90638c5a39df (diff) | |
parent | 586be3fcf97eec22fbc0ef6d67e823706aea7167 (diff) |
Merge branch 'topic/hda-cache' into topic/hda
-rw-r--r-- | sound/pci/hda/hda_codec.c | 114 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.h | 1 | ||||
-rw-r--r-- | sound/pci/hda/hda_intel.c | 19 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 5 |
4 files changed, 90 insertions, 49 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 66a7d3de9fa0..b649033a4c81 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -175,14 +175,23 @@ unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, | |||
175 | unsigned int verb, unsigned int parm) | 175 | unsigned int verb, unsigned int parm) |
176 | { | 176 | { |
177 | struct hda_bus *bus = codec->bus; | 177 | struct hda_bus *bus = codec->bus; |
178 | unsigned int res; | 178 | unsigned int cmd, res; |
179 | int repeated = 0; | ||
179 | 180 | ||
180 | res = make_codec_cmd(codec, nid, direct, verb, parm); | 181 | cmd = make_codec_cmd(codec, nid, direct, verb, parm); |
181 | snd_hda_power_up(codec); | 182 | snd_hda_power_up(codec); |
182 | mutex_lock(&bus->cmd_mutex); | 183 | mutex_lock(&bus->cmd_mutex); |
183 | if (!bus->ops.command(bus, res)) | 184 | again: |
185 | if (!bus->ops.command(bus, cmd)) { | ||
184 | res = bus->ops.get_response(bus); | 186 | res = bus->ops.get_response(bus); |
185 | else | 187 | if (res == -1 && bus->rirb_error) { |
188 | if (repeated++ < 1) { | ||
189 | snd_printd(KERN_WARNING "hda_codec: " | ||
190 | "Trying verb 0x%08x again\n", cmd); | ||
191 | goto again; | ||
192 | } | ||
193 | } | ||
194 | } else | ||
186 | res = (unsigned int)-1; | 195 | res = (unsigned int)-1; |
187 | mutex_unlock(&bus->cmd_mutex); | 196 | mutex_unlock(&bus->cmd_mutex); |
188 | snd_hda_power_down(codec); | 197 | snd_hda_power_down(codec); |
@@ -1056,6 +1065,8 @@ EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup_stream); | |||
1056 | /* FIXME: more better hash key? */ | 1065 | /* FIXME: more better hash key? */ |
1057 | #define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24)) | 1066 | #define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24)) |
1058 | #define HDA_HASH_PINCAP_KEY(nid) (u32)((nid) + (0x02 << 24)) | 1067 | #define HDA_HASH_PINCAP_KEY(nid) (u32)((nid) + (0x02 << 24)) |
1068 | #define HDA_HASH_PARPCM_KEY(nid) (u32)((nid) + (0x03 << 24)) | ||
1069 | #define HDA_HASH_PARSTR_KEY(nid) (u32)((nid) + (0x04 << 24)) | ||
1059 | #define INFO_AMP_CAPS (1<<0) | 1070 | #define INFO_AMP_CAPS (1<<0) |
1060 | #define INFO_AMP_VOL(ch) (1 << (1 + (ch))) | 1071 | #define INFO_AMP_VOL(ch) (1 << (1 + (ch))) |
1061 | 1072 | ||
@@ -1146,19 +1157,32 @@ int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, | |||
1146 | } | 1157 | } |
1147 | EXPORT_SYMBOL_HDA(snd_hda_override_amp_caps); | 1158 | EXPORT_SYMBOL_HDA(snd_hda_override_amp_caps); |
1148 | 1159 | ||
1149 | u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid) | 1160 | static unsigned int |
1161 | query_caps_hash(struct hda_codec *codec, hda_nid_t nid, u32 key, | ||
1162 | unsigned int (*func)(struct hda_codec *, hda_nid_t)) | ||
1150 | { | 1163 | { |
1151 | struct hda_amp_info *info; | 1164 | struct hda_amp_info *info; |
1152 | 1165 | ||
1153 | info = get_alloc_amp_hash(codec, HDA_HASH_PINCAP_KEY(nid)); | 1166 | info = get_alloc_amp_hash(codec, key); |
1154 | if (!info) | 1167 | if (!info) |
1155 | return 0; | 1168 | return 0; |
1156 | if (!info->head.val) { | 1169 | if (!info->head.val) { |
1157 | info->amp_caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); | ||
1158 | info->head.val |= INFO_AMP_CAPS; | 1170 | info->head.val |= INFO_AMP_CAPS; |
1171 | info->amp_caps = func(codec, nid); | ||
1159 | } | 1172 | } |
1160 | return info->amp_caps; | 1173 | return info->amp_caps; |
1161 | } | 1174 | } |
1175 | |||
1176 | static unsigned int read_pin_cap(struct hda_codec *codec, hda_nid_t nid) | ||
1177 | { | ||
1178 | return snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); | ||
1179 | } | ||
1180 | |||
1181 | u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid) | ||
1182 | { | ||
1183 | return query_caps_hash(codec, nid, HDA_HASH_PINCAP_KEY(nid), | ||
1184 | read_pin_cap); | ||
1185 | } | ||
1162 | EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps); | 1186 | EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps); |
1163 | 1187 | ||
1164 | /* | 1188 | /* |
@@ -2547,6 +2571,41 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate, | |||
2547 | } | 2571 | } |
2548 | EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format); | 2572 | EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format); |
2549 | 2573 | ||
2574 | static unsigned int get_pcm_param(struct hda_codec *codec, hda_nid_t nid) | ||
2575 | { | ||
2576 | unsigned int val = 0; | ||
2577 | if (nid != codec->afg && | ||
2578 | (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD)) | ||
2579 | val = snd_hda_param_read(codec, nid, AC_PAR_PCM); | ||
2580 | if (!val || val == -1) | ||
2581 | val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM); | ||
2582 | if (!val || val == -1) | ||
2583 | return 0; | ||
2584 | return val; | ||
2585 | } | ||
2586 | |||
2587 | static unsigned int query_pcm_param(struct hda_codec *codec, hda_nid_t nid) | ||
2588 | { | ||
2589 | return query_caps_hash(codec, nid, HDA_HASH_PARPCM_KEY(nid), | ||
2590 | get_pcm_param); | ||
2591 | } | ||
2592 | |||
2593 | static unsigned int get_stream_param(struct hda_codec *codec, hda_nid_t nid) | ||
2594 | { | ||
2595 | unsigned int streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM); | ||
2596 | if (!streams || streams == -1) | ||
2597 | streams = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM); | ||
2598 | if (!streams || streams == -1) | ||
2599 | return 0; | ||
2600 | return streams; | ||
2601 | } | ||
2602 | |||
2603 | static unsigned int query_stream_param(struct hda_codec *codec, hda_nid_t nid) | ||
2604 | { | ||
2605 | return query_caps_hash(codec, nid, HDA_HASH_PARSTR_KEY(nid), | ||
2606 | get_stream_param); | ||
2607 | } | ||
2608 | |||
2550 | /** | 2609 | /** |
2551 | * snd_hda_query_supported_pcm - query the supported PCM rates and formats | 2610 | * snd_hda_query_supported_pcm - query the supported PCM rates and formats |
2552 | * @codec: the HDA codec | 2611 | * @codec: the HDA codec |
@@ -2565,15 +2624,8 @@ static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, | |||
2565 | { | 2624 | { |
2566 | unsigned int i, val, wcaps; | 2625 | unsigned int i, val, wcaps; |
2567 | 2626 | ||
2568 | val = 0; | ||
2569 | wcaps = get_wcaps(codec, nid); | 2627 | wcaps = get_wcaps(codec, nid); |
2570 | if (nid != codec->afg && (wcaps & AC_WCAP_FORMAT_OVRD)) { | 2628 | val = query_pcm_param(codec, nid); |
2571 | val = snd_hda_param_read(codec, nid, AC_PAR_PCM); | ||
2572 | if (val == -1) | ||
2573 | return -EIO; | ||
2574 | } | ||
2575 | if (!val) | ||
2576 | val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM); | ||
2577 | 2629 | ||
2578 | if (ratesp) { | 2630 | if (ratesp) { |
2579 | u32 rates = 0; | 2631 | u32 rates = 0; |
@@ -2595,15 +2647,9 @@ static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, | |||
2595 | u64 formats = 0; | 2647 | u64 formats = 0; |
2596 | unsigned int streams, bps; | 2648 | unsigned int streams, bps; |
2597 | 2649 | ||
2598 | streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM); | 2650 | streams = query_stream_param(codec, nid); |
2599 | if (streams == -1) | 2651 | if (!streams) |
2600 | return -EIO; | 2652 | return -EIO; |
2601 | if (!streams) { | ||
2602 | streams = snd_hda_param_read(codec, codec->afg, | ||
2603 | AC_PAR_STREAM); | ||
2604 | if (streams == -1) | ||
2605 | return -EIO; | ||
2606 | } | ||
2607 | 2653 | ||
2608 | bps = 0; | 2654 | bps = 0; |
2609 | if (streams & AC_SUPFMT_PCM) { | 2655 | if (streams & AC_SUPFMT_PCM) { |
@@ -2677,17 +2723,9 @@ int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid, | |||
2677 | int i; | 2723 | int i; |
2678 | unsigned int val = 0, rate, stream; | 2724 | unsigned int val = 0, rate, stream; |
2679 | 2725 | ||
2680 | if (nid != codec->afg && | 2726 | val = query_pcm_param(codec, nid); |
2681 | (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD)) { | 2727 | if (!val) |
2682 | val = snd_hda_param_read(codec, nid, AC_PAR_PCM); | 2728 | return 0; |
2683 | if (val == -1) | ||
2684 | return 0; | ||
2685 | } | ||
2686 | if (!val) { | ||
2687 | val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM); | ||
2688 | if (val == -1) | ||
2689 | return 0; | ||
2690 | } | ||
2691 | 2729 | ||
2692 | rate = format & 0xff00; | 2730 | rate = format & 0xff00; |
2693 | for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++) | 2731 | for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++) |
@@ -2699,12 +2737,8 @@ int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid, | |||
2699 | if (i >= AC_PAR_PCM_RATE_BITS) | 2737 | if (i >= AC_PAR_PCM_RATE_BITS) |
2700 | return 0; | 2738 | return 0; |
2701 | 2739 | ||
2702 | stream = snd_hda_param_read(codec, nid, AC_PAR_STREAM); | 2740 | stream = query_stream_param(codec, nid); |
2703 | if (stream == -1) | 2741 | if (!stream) |
2704 | return 0; | ||
2705 | if (!stream && nid != codec->afg) | ||
2706 | stream = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM); | ||
2707 | if (!stream || stream == -1) | ||
2708 | return 0; | 2742 | return 0; |
2709 | 2743 | ||
2710 | if (stream & AC_SUPFMT_PCM) { | 2744 | if (stream & AC_SUPFMT_PCM) { |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 2fdecf4b0eb6..cd8979c7670b 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -623,6 +623,7 @@ struct hda_bus { | |||
623 | /* misc op flags */ | 623 | /* misc op flags */ |
624 | unsigned int needs_damn_long_delay :1; | 624 | unsigned int needs_damn_long_delay :1; |
625 | unsigned int shutdown :1; /* being unloaded */ | 625 | unsigned int shutdown :1; /* being unloaded */ |
626 | unsigned int rirb_error:1; /* error in codec communication */ | ||
626 | }; | 627 | }; |
627 | 628 | ||
628 | /* | 629 | /* |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 41db5d4da478..04f19f8cad84 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -606,6 +606,7 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus) | |||
606 | } | 606 | } |
607 | if (!chip->rirb.cmds) { | 607 | if (!chip->rirb.cmds) { |
608 | smp_rmb(); | 608 | smp_rmb(); |
609 | bus->rirb_error = 0; | ||
609 | return chip->rirb.res; /* the last value */ | 610 | return chip->rirb.res; /* the last value */ |
610 | } | 611 | } |
611 | if (time_after(jiffies, timeout)) | 612 | if (time_after(jiffies, timeout)) |
@@ -625,8 +626,10 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus) | |||
625 | chip->irq = -1; | 626 | chip->irq = -1; |
626 | pci_disable_msi(chip->pci); | 627 | pci_disable_msi(chip->pci); |
627 | chip->msi = 0; | 628 | chip->msi = 0; |
628 | if (azx_acquire_irq(chip, 1) < 0) | 629 | if (azx_acquire_irq(chip, 1) < 0) { |
630 | bus->rirb_error = 1; | ||
629 | return -1; | 631 | return -1; |
632 | } | ||
630 | goto again; | 633 | goto again; |
631 | } | 634 | } |
632 | 635 | ||
@@ -646,14 +649,12 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus) | |||
646 | return -1; | 649 | return -1; |
647 | } | 650 | } |
648 | 651 | ||
649 | snd_printk(KERN_ERR "hda_intel: azx_get_response timeout, " | 652 | snd_printk(KERN_ERR "hda_intel: azx_get_response timeout (ERROR): " |
650 | "switching to single_cmd mode: last cmd=0x%08x\n", | 653 | "last cmd=0x%08x\n", chip->last_cmd); |
651 | chip->last_cmd); | 654 | spin_lock_irq(&chip->reg_lock); |
652 | chip->rirb.rp = azx_readb(chip, RIRBWP); | 655 | chip->rirb.cmds = 0; /* reset the index */ |
653 | chip->rirb.cmds = 0; | 656 | bus->rirb_error = 1; |
654 | /* switch to single_cmd mode */ | 657 | spin_unlock_irq(&chip->reg_lock); |
655 | chip->single_cmd = 1; | ||
656 | azx_free_cmd_io(chip); | ||
657 | return -1; | 658 | return -1; |
658 | } | 659 | } |
659 | 660 | ||
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index c9300a3427ea..a6ec87a5c066 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -1024,6 +1024,9 @@ static void alc_subsystem_id(struct hda_codec *codec, | |||
1024 | if (codec->vendor_id == 0x10ec0260) | 1024 | if (codec->vendor_id == 0x10ec0260) |
1025 | nid = 0x17; | 1025 | nid = 0x17; |
1026 | ass = snd_hda_codec_get_pincfg(codec, nid); | 1026 | ass = snd_hda_codec_get_pincfg(codec, nid); |
1027 | snd_printd("realtek: No valid SSID, " | ||
1028 | "checking pincfg 0x%08x for NID 0x%x\n", | ||
1029 | nid, ass); | ||
1027 | if (!(ass & 1) && !(ass & 0x100000)) | 1030 | if (!(ass & 1) && !(ass & 0x100000)) |
1028 | return; | 1031 | return; |
1029 | if ((ass >> 30) != 1) /* no physical connection */ | 1032 | if ((ass >> 30) != 1) /* no physical connection */ |
@@ -1038,6 +1041,8 @@ static void alc_subsystem_id(struct hda_codec *codec, | |||
1038 | if (((ass >> 16) & 0xf) != tmp) | 1041 | if (((ass >> 16) & 0xf) != tmp) |
1039 | return; | 1042 | return; |
1040 | do_sku: | 1043 | do_sku: |
1044 | snd_printd("realtek: Enabling init ASM_ID=0x%04x CODEC_ID=%08x\n", | ||
1045 | ass & 0xffff, codec->vendor_id); | ||
1041 | /* | 1046 | /* |
1042 | * 0 : override | 1047 | * 0 : override |
1043 | * 1 : Swap Jack | 1048 | * 1 : Swap Jack |