aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2009-04-21 05:11:54 -0400
committerTakashi Iwai <tiwai@suse.de>2009-04-21 05:11:54 -0400
commitb97bedcdedb4ae95b2128a4770dfc160e113b174 (patch)
treec604636b8991e0e53a20e0dbe666a57afe72ea45
parent858940773ad5f9dfe32ddb34fa1c90638c5a39df (diff)
parent586be3fcf97eec22fbc0ef6d67e823706aea7167 (diff)
Merge branch 'topic/hda-cache' into topic/hda
-rw-r--r--sound/pci/hda/hda_codec.c114
-rw-r--r--sound/pci/hda/hda_codec.h1
-rw-r--r--sound/pci/hda/hda_intel.c19
-rw-r--r--sound/pci/hda/patch_realtek.c5
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}
1147EXPORT_SYMBOL_HDA(snd_hda_override_amp_caps); 1158EXPORT_SYMBOL_HDA(snd_hda_override_amp_caps);
1148 1159
1149u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid) 1160static unsigned int
1161query_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
1176static 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
1181u32 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}
1162EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps); 1186EXPORT_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}
2548EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format); 2572EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format);
2549 2573
2574static 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
2587static 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
2593static 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
2603static 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;
1040do_sku: 1043do_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