aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/pci/hda/hda_codec.c44
-rw-r--r--sound/pci/hda/hda_codec.h9
-rw-r--r--sound/pci/hda/hda_intel.c40
-rw-r--r--sound/pci/hda/patch_sigmatel.c9
4 files changed, 69 insertions, 33 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index d1d5fb9d7afb..562403a23488 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -165,28 +165,29 @@ static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd,
165 unsigned int *res) 165 unsigned int *res)
166{ 166{
167 struct hda_bus *bus = codec->bus; 167 struct hda_bus *bus = codec->bus;
168 int err, repeated = 0; 168 int err;
169 169
170 if (res) 170 if (res)
171 *res = -1; 171 *res = -1;
172 again:
172 snd_hda_power_up(codec); 173 snd_hda_power_up(codec);
173 mutex_lock(&bus->cmd_mutex); 174 mutex_lock(&bus->cmd_mutex);
174 again:
175 err = bus->ops.command(bus, cmd); 175 err = bus->ops.command(bus, cmd);
176 if (!err) { 176 if (!err && res)
177 if (res) { 177 *res = bus->ops.get_response(bus);
178 *res = bus->ops.get_response(bus);
179 if (*res == -1 && bus->rirb_error) {
180 if (repeated++ < 1) {
181 snd_printd(KERN_WARNING "hda_codec: "
182 "Trying verb 0x%08x again\n", cmd);
183 goto again;
184 }
185 }
186 }
187 }
188 mutex_unlock(&bus->cmd_mutex); 178 mutex_unlock(&bus->cmd_mutex);
189 snd_hda_power_down(codec); 179 snd_hda_power_down(codec);
180 if (res && *res == -1 && bus->rirb_error) {
181 if (bus->response_reset) {
182 snd_printd("hda_codec: resetting BUS due to "
183 "fatal communication error\n");
184 bus->ops.bus_reset(bus);
185 }
186 goto again;
187 }
188 /* clear reset-flag when the communication gets recovered */
189 if (!err)
190 bus->response_reset = 0;
190 return err; 191 return err;
191} 192}
192 193
@@ -213,11 +214,6 @@ unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid,
213} 214}
214EXPORT_SYMBOL_HDA(snd_hda_codec_read); 215EXPORT_SYMBOL_HDA(snd_hda_codec_read);
215 216
216/* Define the below to send and receive verbs synchronously.
217 * If you often get any codec communication errors, this is worth to try.
218 */
219/* #define SND_HDA_SUPPORT_SYNC_WRITE */
220
221/** 217/**
222 * snd_hda_codec_write - send a single command without waiting for response 218 * snd_hda_codec_write - send a single command without waiting for response
223 * @codec: the HDA codec 219 * @codec: the HDA codec
@@ -234,12 +230,9 @@ int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct,
234 unsigned int verb, unsigned int parm) 230 unsigned int verb, unsigned int parm)
235{ 231{
236 unsigned int cmd = make_codec_cmd(codec, nid, direct, verb, parm); 232 unsigned int cmd = make_codec_cmd(codec, nid, direct, verb, parm);
237#ifdef SND_HDA_SUPPORT_SYNC_WRITE
238 unsigned int res; 233 unsigned int res;
239 return codec_exec_verb(codec, cmd, &res); 234 return codec_exec_verb(codec, cmd,
240#else 235 codec->bus->sync_write ? &res : NULL);
241 return codec_exec_verb(codec, cmd, NULL);
242#endif
243} 236}
244EXPORT_SYMBOL_HDA(snd_hda_codec_write); 237EXPORT_SYMBOL_HDA(snd_hda_codec_write);
245 238
@@ -3894,11 +3887,10 @@ EXPORT_SYMBOL_HDA(auto_pin_cfg_labels);
3894/** 3887/**
3895 * snd_hda_suspend - suspend the codecs 3888 * snd_hda_suspend - suspend the codecs
3896 * @bus: the HDA bus 3889 * @bus: the HDA bus
3897 * @state: suspsend state
3898 * 3890 *
3899 * Returns 0 if successful. 3891 * Returns 0 if successful.
3900 */ 3892 */
3901int snd_hda_suspend(struct hda_bus *bus, pm_message_t state) 3893int snd_hda_suspend(struct hda_bus *bus)
3902{ 3894{
3903 struct hda_codec *codec; 3895 struct hda_codec *codec;
3904 3896
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index c5bd40f77bb9..cad79efaabc9 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -574,6 +574,8 @@ struct hda_bus_ops {
574 /* attach a PCM stream */ 574 /* attach a PCM stream */
575 int (*attach_pcm)(struct hda_bus *bus, struct hda_codec *codec, 575 int (*attach_pcm)(struct hda_bus *bus, struct hda_codec *codec,
576 struct hda_pcm *pcm); 576 struct hda_pcm *pcm);
577 /* reset bus for retry verb */
578 void (*bus_reset)(struct hda_bus *bus);
577#ifdef CONFIG_SND_HDA_POWER_SAVE 579#ifdef CONFIG_SND_HDA_POWER_SAVE
578 /* notify power-up/down from codec to controller */ 580 /* notify power-up/down from codec to controller */
579 void (*pm_notify)(struct hda_bus *bus); 581 void (*pm_notify)(struct hda_bus *bus);
@@ -622,8 +624,13 @@ struct hda_bus {
622 624
623 /* misc op flags */ 625 /* misc op flags */
624 unsigned int needs_damn_long_delay :1; 626 unsigned int needs_damn_long_delay :1;
627 unsigned int allow_bus_reset:1; /* allow bus reset at fatal error */
628 unsigned int sync_write:1; /* sync after verb write */
629 /* status for codec/controller */
625 unsigned int shutdown :1; /* being unloaded */ 630 unsigned int shutdown :1; /* being unloaded */
626 unsigned int rirb_error:1; /* error in codec communication */ 631 unsigned int rirb_error:1; /* error in codec communication */
632 unsigned int response_reset:1; /* controller was reset */
633 unsigned int in_reset:1; /* during reset operation */
627}; 634};
628 635
629/* 636/*
@@ -907,7 +914,7 @@ void snd_hda_get_codec_name(struct hda_codec *codec, char *name, int namelen);
907 * power management 914 * power management
908 */ 915 */
909#ifdef CONFIG_PM 916#ifdef CONFIG_PM
910int snd_hda_suspend(struct hda_bus *bus, pm_message_t state); 917int snd_hda_suspend(struct hda_bus *bus);
911int snd_hda_resume(struct hda_bus *bus); 918int snd_hda_resume(struct hda_bus *bus);
912#endif 919#endif
913 920
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index b063d0e3d325..9f44645a1d04 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -661,14 +661,23 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus)
661 return -1; 661 return -1;
662 } 662 }
663 663
664 snd_printk(KERN_ERR SFX "azx_get_response timeout (ERROR): " 664 /* a fatal communication error; need either to reset or to fallback
665 "last cmd=0x%08x\n", chip->last_cmd); 665 * to the single_cmd mode
666 /* re-initialize CORB/RIRB */ 666 */
667 spin_lock_irq(&chip->reg_lock);
668 bus->rirb_error = 1; 667 bus->rirb_error = 1;
668 if (bus->allow_bus_reset && !bus->response_reset && !bus->in_reset) {
669 bus->response_reset = 1;
670 return -1; /* give a chance to retry */
671 }
672
673 snd_printk(KERN_ERR "hda_intel: azx_get_response timeout, "
674 "switching to single_cmd mode: last cmd=0x%08x\n",
675 chip->last_cmd);
676 chip->single_cmd = 1;
677 bus->response_reset = 0;
678 /* re-initialize CORB/RIRB */
669 azx_free_cmd_io(chip); 679 azx_free_cmd_io(chip);
670 azx_init_cmd_io(chip); 680 azx_init_cmd_io(chip);
671 spin_unlock_irq(&chip->reg_lock);
672 return -1; 681 return -1;
673} 682}
674 683
@@ -709,6 +718,7 @@ static int azx_single_send_cmd(struct hda_bus *bus, u32 val)
709 struct azx *chip = bus->private_data; 718 struct azx *chip = bus->private_data;
710 int timeout = 50; 719 int timeout = 50;
711 720
721 bus->rirb_error = 0;
712 while (timeout--) { 722 while (timeout--) {
713 /* check ICB busy bit */ 723 /* check ICB busy bit */
714 if (!((azx_readw(chip, IRS) & ICH6_IRS_BUSY))) { 724 if (!((azx_readw(chip, IRS) & ICH6_IRS_BUSY))) {
@@ -1247,6 +1257,23 @@ static int azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec,
1247 struct hda_pcm *cpcm); 1257 struct hda_pcm *cpcm);
1248static void azx_stop_chip(struct azx *chip); 1258static void azx_stop_chip(struct azx *chip);
1249 1259
1260static void azx_bus_reset(struct hda_bus *bus)
1261{
1262 struct azx *chip = bus->private_data;
1263 int i;
1264
1265 bus->in_reset = 1;
1266 azx_stop_chip(chip);
1267 azx_init_chip(chip);
1268 if (chip->initialized) {
1269 for (i = 0; i < AZX_MAX_PCMS; i++)
1270 snd_pcm_suspend_all(chip->pcm[i]);
1271 snd_hda_suspend(chip->bus);
1272 snd_hda_resume(chip->bus);
1273 }
1274 bus->in_reset = 0;
1275}
1276
1250/* 1277/*
1251 * Codec initialization 1278 * Codec initialization
1252 */ 1279 */
@@ -1270,6 +1297,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model,
1270 bus_temp.ops.command = azx_send_cmd; 1297 bus_temp.ops.command = azx_send_cmd;
1271 bus_temp.ops.get_response = azx_get_response; 1298 bus_temp.ops.get_response = azx_get_response;
1272 bus_temp.ops.attach_pcm = azx_attach_pcm_stream; 1299 bus_temp.ops.attach_pcm = azx_attach_pcm_stream;
1300 bus_temp.ops.bus_reset = azx_bus_reset;
1273#ifdef CONFIG_SND_HDA_POWER_SAVE 1301#ifdef CONFIG_SND_HDA_POWER_SAVE
1274 bus_temp.power_save = &power_save; 1302 bus_temp.power_save = &power_save;
1275 bus_temp.ops.pm_notify = azx_power_notify; 1303 bus_temp.ops.pm_notify = azx_power_notify;
@@ -1997,7 +2025,7 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state)
1997 for (i = 0; i < AZX_MAX_PCMS; i++) 2025 for (i = 0; i < AZX_MAX_PCMS; i++)
1998 snd_pcm_suspend_all(chip->pcm[i]); 2026 snd_pcm_suspend_all(chip->pcm[i]);
1999 if (chip->initialized) 2027 if (chip->initialized)
2000 snd_hda_suspend(chip->bus, state); 2028 snd_hda_suspend(chip->bus);
2001 azx_stop_chip(chip); 2029 azx_stop_chip(chip);
2002 if (chip->irq >= 0) { 2030 if (chip->irq >= 0) {
2003 free_irq(chip->irq, chip); 2031 free_irq(chip->irq, chip);
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 48f4a36c4813..42f944bb641d 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -5375,6 +5375,15 @@ again:
5375 if (get_wcaps(codec, 0xa) & AC_WCAP_IN_AMP) 5375 if (get_wcaps(codec, 0xa) & AC_WCAP_IN_AMP)
5376 snd_hda_sequence_write_cache(codec, unmute_init); 5376 snd_hda_sequence_write_cache(codec, unmute_init);
5377 5377
5378 /* Some HP machines seem to have unstable codec communications
5379 * especially with ATI fglrx driver. For recovering from the
5380 * CORB/RIRB stall, allow the BUS reset and keep always sync
5381 */
5382 if (spec->board_config == STAC_HP_DV5) {
5383 codec->bus->sync_write = 1;
5384 codec->bus->allow_bus_reset = 1;
5385 }
5386
5378 spec->aloopback_ctl = stac92hd71bxx_loopback; 5387 spec->aloopback_ctl = stac92hd71bxx_loopback;
5379 spec->aloopback_mask = 0x50; 5388 spec->aloopback_mask = 0x50;
5380 spec->aloopback_shift = 0; 5389 spec->aloopback_shift = 0;