Loading sound/pci/hda/hda_codec.c +18 −26 Original line number Original line Diff line number Diff line Loading @@ -165,28 +165,29 @@ static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd, unsigned int *res) unsigned int *res) { { struct hda_bus *bus = codec->bus; struct hda_bus *bus = codec->bus; int err, repeated = 0; int err; if (res) if (res) *res = -1; *res = -1; again: snd_hda_power_up(codec); snd_hda_power_up(codec); mutex_lock(&bus->cmd_mutex); mutex_lock(&bus->cmd_mutex); again: err = bus->ops.command(bus, cmd); err = bus->ops.command(bus, cmd); if (!err) { if (!err && res) if (res) { *res = bus->ops.get_response(bus); *res = bus->ops.get_response(bus); if (*res == -1 && bus->rirb_error) { if (repeated++ < 1) { snd_printd(KERN_WARNING "hda_codec: " "Trying verb 0x%08x again\n", cmd); goto again; } } } } mutex_unlock(&bus->cmd_mutex); mutex_unlock(&bus->cmd_mutex); snd_hda_power_down(codec); snd_hda_power_down(codec); if (res && *res == -1 && bus->rirb_error) { if (bus->response_reset) { snd_printd("hda_codec: resetting BUS due to " "fatal communication error\n"); bus->ops.bus_reset(bus); } goto again; } /* clear reset-flag when the communication gets recovered */ if (!err) bus->response_reset = 0; return err; return err; } } Loading @@ -213,11 +214,6 @@ unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, } } EXPORT_SYMBOL_HDA(snd_hda_codec_read); EXPORT_SYMBOL_HDA(snd_hda_codec_read); /* Define the below to send and receive verbs synchronously. * If you often get any codec communication errors, this is worth to try. */ /* #define SND_HDA_SUPPORT_SYNC_WRITE */ /** /** * snd_hda_codec_write - send a single command without waiting for response * snd_hda_codec_write - send a single command without waiting for response * @codec: the HDA codec * @codec: the HDA codec Loading @@ -234,12 +230,9 @@ int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct, unsigned int verb, unsigned int parm) unsigned int verb, unsigned int parm) { { unsigned int cmd = make_codec_cmd(codec, nid, direct, verb, parm); unsigned int cmd = make_codec_cmd(codec, nid, direct, verb, parm); #ifdef SND_HDA_SUPPORT_SYNC_WRITE unsigned int res; unsigned int res; return codec_exec_verb(codec, cmd, &res); return codec_exec_verb(codec, cmd, #else codec->bus->sync_write ? &res : NULL); return codec_exec_verb(codec, cmd, NULL); #endif } } EXPORT_SYMBOL_HDA(snd_hda_codec_write); EXPORT_SYMBOL_HDA(snd_hda_codec_write); Loading Loading @@ -3894,11 +3887,10 @@ EXPORT_SYMBOL_HDA(auto_pin_cfg_labels); /** /** * snd_hda_suspend - suspend the codecs * snd_hda_suspend - suspend the codecs * @bus: the HDA bus * @bus: the HDA bus * @state: suspsend state * * * Returns 0 if successful. * Returns 0 if successful. */ */ int snd_hda_suspend(struct hda_bus *bus, pm_message_t state) int snd_hda_suspend(struct hda_bus *bus) { { struct hda_codec *codec; struct hda_codec *codec; Loading sound/pci/hda/hda_codec.h +8 −1 Original line number Original line Diff line number Diff line Loading @@ -574,6 +574,8 @@ struct hda_bus_ops { /* attach a PCM stream */ /* attach a PCM stream */ int (*attach_pcm)(struct hda_bus *bus, struct hda_codec *codec, int (*attach_pcm)(struct hda_bus *bus, struct hda_codec *codec, struct hda_pcm *pcm); struct hda_pcm *pcm); /* reset bus for retry verb */ void (*bus_reset)(struct hda_bus *bus); #ifdef CONFIG_SND_HDA_POWER_SAVE #ifdef CONFIG_SND_HDA_POWER_SAVE /* notify power-up/down from codec to controller */ /* notify power-up/down from codec to controller */ void (*pm_notify)(struct hda_bus *bus); void (*pm_notify)(struct hda_bus *bus); Loading Loading @@ -622,8 +624,13 @@ struct hda_bus { /* misc op flags */ /* misc op flags */ unsigned int needs_damn_long_delay :1; unsigned int needs_damn_long_delay :1; unsigned int allow_bus_reset:1; /* allow bus reset at fatal error */ unsigned int sync_write:1; /* sync after verb write */ /* status for codec/controller */ unsigned int shutdown :1; /* being unloaded */ unsigned int shutdown :1; /* being unloaded */ unsigned int rirb_error:1; /* error in codec communication */ unsigned int rirb_error:1; /* error in codec communication */ unsigned int response_reset:1; /* controller was reset */ unsigned int in_reset:1; /* during reset operation */ }; }; /* /* Loading Loading @@ -907,7 +914,7 @@ void snd_hda_get_codec_name(struct hda_codec *codec, char *name, int namelen); * power management * power management */ */ #ifdef CONFIG_PM #ifdef CONFIG_PM int snd_hda_suspend(struct hda_bus *bus, pm_message_t state); int snd_hda_suspend(struct hda_bus *bus); int snd_hda_resume(struct hda_bus *bus); int snd_hda_resume(struct hda_bus *bus); #endif #endif Loading sound/pci/hda/hda_intel.c +34 −6 Original line number Original line Diff line number Diff line Loading @@ -661,14 +661,23 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus) return -1; return -1; } } snd_printk(KERN_ERR SFX "azx_get_response timeout (ERROR): " /* a fatal communication error; need either to reset or to fallback "last cmd=0x%08x\n", chip->last_cmd); * to the single_cmd mode /* re-initialize CORB/RIRB */ */ spin_lock_irq(&chip->reg_lock); bus->rirb_error = 1; bus->rirb_error = 1; if (bus->allow_bus_reset && !bus->response_reset && !bus->in_reset) { bus->response_reset = 1; return -1; /* give a chance to retry */ } snd_printk(KERN_ERR "hda_intel: azx_get_response timeout, " "switching to single_cmd mode: last cmd=0x%08x\n", chip->last_cmd); chip->single_cmd = 1; bus->response_reset = 0; /* re-initialize CORB/RIRB */ azx_free_cmd_io(chip); azx_free_cmd_io(chip); azx_init_cmd_io(chip); azx_init_cmd_io(chip); spin_unlock_irq(&chip->reg_lock); return -1; return -1; } } Loading Loading @@ -709,6 +718,7 @@ static int azx_single_send_cmd(struct hda_bus *bus, u32 val) struct azx *chip = bus->private_data; struct azx *chip = bus->private_data; int timeout = 50; int timeout = 50; bus->rirb_error = 0; while (timeout--) { while (timeout--) { /* check ICB busy bit */ /* check ICB busy bit */ if (!((azx_readw(chip, IRS) & ICH6_IRS_BUSY))) { if (!((azx_readw(chip, IRS) & ICH6_IRS_BUSY))) { Loading Loading @@ -1247,6 +1257,23 @@ static int azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec, struct hda_pcm *cpcm); struct hda_pcm *cpcm); static void azx_stop_chip(struct azx *chip); static void azx_stop_chip(struct azx *chip); static void azx_bus_reset(struct hda_bus *bus) { struct azx *chip = bus->private_data; int i; bus->in_reset = 1; azx_stop_chip(chip); azx_init_chip(chip); if (chip->initialized) { for (i = 0; i < AZX_MAX_PCMS; i++) snd_pcm_suspend_all(chip->pcm[i]); snd_hda_suspend(chip->bus); snd_hda_resume(chip->bus); } bus->in_reset = 0; } /* /* * Codec initialization * Codec initialization */ */ Loading @@ -1270,6 +1297,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model, bus_temp.ops.command = azx_send_cmd; bus_temp.ops.command = azx_send_cmd; bus_temp.ops.get_response = azx_get_response; bus_temp.ops.get_response = azx_get_response; bus_temp.ops.attach_pcm = azx_attach_pcm_stream; bus_temp.ops.attach_pcm = azx_attach_pcm_stream; bus_temp.ops.bus_reset = azx_bus_reset; #ifdef CONFIG_SND_HDA_POWER_SAVE #ifdef CONFIG_SND_HDA_POWER_SAVE bus_temp.power_save = &power_save; bus_temp.power_save = &power_save; bus_temp.ops.pm_notify = azx_power_notify; bus_temp.ops.pm_notify = azx_power_notify; Loading Loading @@ -1997,7 +2025,7 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state) for (i = 0; i < AZX_MAX_PCMS; i++) for (i = 0; i < AZX_MAX_PCMS; i++) snd_pcm_suspend_all(chip->pcm[i]); snd_pcm_suspend_all(chip->pcm[i]); if (chip->initialized) if (chip->initialized) snd_hda_suspend(chip->bus, state); snd_hda_suspend(chip->bus); azx_stop_chip(chip); azx_stop_chip(chip); if (chip->irq >= 0) { if (chip->irq >= 0) { free_irq(chip->irq, chip); free_irq(chip->irq, chip); Loading sound/pci/hda/patch_sigmatel.c +9 −0 Original line number Original line Diff line number Diff line Loading @@ -5375,6 +5375,15 @@ again: if (get_wcaps(codec, 0xa) & AC_WCAP_IN_AMP) if (get_wcaps(codec, 0xa) & AC_WCAP_IN_AMP) snd_hda_sequence_write_cache(codec, unmute_init); snd_hda_sequence_write_cache(codec, unmute_init); /* Some HP machines seem to have unstable codec communications * especially with ATI fglrx driver. For recovering from the * CORB/RIRB stall, allow the BUS reset and keep always sync */ if (spec->board_config == STAC_HP_DV5) { codec->bus->sync_write = 1; codec->bus->allow_bus_reset = 1; } spec->aloopback_ctl = stac92hd71bxx_loopback; spec->aloopback_ctl = stac92hd71bxx_loopback; spec->aloopback_mask = 0x50; spec->aloopback_mask = 0x50; spec->aloopback_shift = 0; spec->aloopback_shift = 0; Loading Loading
sound/pci/hda/hda_codec.c +18 −26 Original line number Original line Diff line number Diff line Loading @@ -165,28 +165,29 @@ static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd, unsigned int *res) unsigned int *res) { { struct hda_bus *bus = codec->bus; struct hda_bus *bus = codec->bus; int err, repeated = 0; int err; if (res) if (res) *res = -1; *res = -1; again: snd_hda_power_up(codec); snd_hda_power_up(codec); mutex_lock(&bus->cmd_mutex); mutex_lock(&bus->cmd_mutex); again: err = bus->ops.command(bus, cmd); err = bus->ops.command(bus, cmd); if (!err) { if (!err && res) if (res) { *res = bus->ops.get_response(bus); *res = bus->ops.get_response(bus); if (*res == -1 && bus->rirb_error) { if (repeated++ < 1) { snd_printd(KERN_WARNING "hda_codec: " "Trying verb 0x%08x again\n", cmd); goto again; } } } } mutex_unlock(&bus->cmd_mutex); mutex_unlock(&bus->cmd_mutex); snd_hda_power_down(codec); snd_hda_power_down(codec); if (res && *res == -1 && bus->rirb_error) { if (bus->response_reset) { snd_printd("hda_codec: resetting BUS due to " "fatal communication error\n"); bus->ops.bus_reset(bus); } goto again; } /* clear reset-flag when the communication gets recovered */ if (!err) bus->response_reset = 0; return err; return err; } } Loading @@ -213,11 +214,6 @@ unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, } } EXPORT_SYMBOL_HDA(snd_hda_codec_read); EXPORT_SYMBOL_HDA(snd_hda_codec_read); /* Define the below to send and receive verbs synchronously. * If you often get any codec communication errors, this is worth to try. */ /* #define SND_HDA_SUPPORT_SYNC_WRITE */ /** /** * snd_hda_codec_write - send a single command without waiting for response * snd_hda_codec_write - send a single command without waiting for response * @codec: the HDA codec * @codec: the HDA codec Loading @@ -234,12 +230,9 @@ int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct, unsigned int verb, unsigned int parm) unsigned int verb, unsigned int parm) { { unsigned int cmd = make_codec_cmd(codec, nid, direct, verb, parm); unsigned int cmd = make_codec_cmd(codec, nid, direct, verb, parm); #ifdef SND_HDA_SUPPORT_SYNC_WRITE unsigned int res; unsigned int res; return codec_exec_verb(codec, cmd, &res); return codec_exec_verb(codec, cmd, #else codec->bus->sync_write ? &res : NULL); return codec_exec_verb(codec, cmd, NULL); #endif } } EXPORT_SYMBOL_HDA(snd_hda_codec_write); EXPORT_SYMBOL_HDA(snd_hda_codec_write); Loading Loading @@ -3894,11 +3887,10 @@ EXPORT_SYMBOL_HDA(auto_pin_cfg_labels); /** /** * snd_hda_suspend - suspend the codecs * snd_hda_suspend - suspend the codecs * @bus: the HDA bus * @bus: the HDA bus * @state: suspsend state * * * Returns 0 if successful. * Returns 0 if successful. */ */ int snd_hda_suspend(struct hda_bus *bus, pm_message_t state) int snd_hda_suspend(struct hda_bus *bus) { { struct hda_codec *codec; struct hda_codec *codec; Loading
sound/pci/hda/hda_codec.h +8 −1 Original line number Original line Diff line number Diff line Loading @@ -574,6 +574,8 @@ struct hda_bus_ops { /* attach a PCM stream */ /* attach a PCM stream */ int (*attach_pcm)(struct hda_bus *bus, struct hda_codec *codec, int (*attach_pcm)(struct hda_bus *bus, struct hda_codec *codec, struct hda_pcm *pcm); struct hda_pcm *pcm); /* reset bus for retry verb */ void (*bus_reset)(struct hda_bus *bus); #ifdef CONFIG_SND_HDA_POWER_SAVE #ifdef CONFIG_SND_HDA_POWER_SAVE /* notify power-up/down from codec to controller */ /* notify power-up/down from codec to controller */ void (*pm_notify)(struct hda_bus *bus); void (*pm_notify)(struct hda_bus *bus); Loading Loading @@ -622,8 +624,13 @@ struct hda_bus { /* misc op flags */ /* misc op flags */ unsigned int needs_damn_long_delay :1; unsigned int needs_damn_long_delay :1; unsigned int allow_bus_reset:1; /* allow bus reset at fatal error */ unsigned int sync_write:1; /* sync after verb write */ /* status for codec/controller */ unsigned int shutdown :1; /* being unloaded */ unsigned int shutdown :1; /* being unloaded */ unsigned int rirb_error:1; /* error in codec communication */ unsigned int rirb_error:1; /* error in codec communication */ unsigned int response_reset:1; /* controller was reset */ unsigned int in_reset:1; /* during reset operation */ }; }; /* /* Loading Loading @@ -907,7 +914,7 @@ void snd_hda_get_codec_name(struct hda_codec *codec, char *name, int namelen); * power management * power management */ */ #ifdef CONFIG_PM #ifdef CONFIG_PM int snd_hda_suspend(struct hda_bus *bus, pm_message_t state); int snd_hda_suspend(struct hda_bus *bus); int snd_hda_resume(struct hda_bus *bus); int snd_hda_resume(struct hda_bus *bus); #endif #endif Loading
sound/pci/hda/hda_intel.c +34 −6 Original line number Original line Diff line number Diff line Loading @@ -661,14 +661,23 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus) return -1; return -1; } } snd_printk(KERN_ERR SFX "azx_get_response timeout (ERROR): " /* a fatal communication error; need either to reset or to fallback "last cmd=0x%08x\n", chip->last_cmd); * to the single_cmd mode /* re-initialize CORB/RIRB */ */ spin_lock_irq(&chip->reg_lock); bus->rirb_error = 1; bus->rirb_error = 1; if (bus->allow_bus_reset && !bus->response_reset && !bus->in_reset) { bus->response_reset = 1; return -1; /* give a chance to retry */ } snd_printk(KERN_ERR "hda_intel: azx_get_response timeout, " "switching to single_cmd mode: last cmd=0x%08x\n", chip->last_cmd); chip->single_cmd = 1; bus->response_reset = 0; /* re-initialize CORB/RIRB */ azx_free_cmd_io(chip); azx_free_cmd_io(chip); azx_init_cmd_io(chip); azx_init_cmd_io(chip); spin_unlock_irq(&chip->reg_lock); return -1; return -1; } } Loading Loading @@ -709,6 +718,7 @@ static int azx_single_send_cmd(struct hda_bus *bus, u32 val) struct azx *chip = bus->private_data; struct azx *chip = bus->private_data; int timeout = 50; int timeout = 50; bus->rirb_error = 0; while (timeout--) { while (timeout--) { /* check ICB busy bit */ /* check ICB busy bit */ if (!((azx_readw(chip, IRS) & ICH6_IRS_BUSY))) { if (!((azx_readw(chip, IRS) & ICH6_IRS_BUSY))) { Loading Loading @@ -1247,6 +1257,23 @@ static int azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec, struct hda_pcm *cpcm); struct hda_pcm *cpcm); static void azx_stop_chip(struct azx *chip); static void azx_stop_chip(struct azx *chip); static void azx_bus_reset(struct hda_bus *bus) { struct azx *chip = bus->private_data; int i; bus->in_reset = 1; azx_stop_chip(chip); azx_init_chip(chip); if (chip->initialized) { for (i = 0; i < AZX_MAX_PCMS; i++) snd_pcm_suspend_all(chip->pcm[i]); snd_hda_suspend(chip->bus); snd_hda_resume(chip->bus); } bus->in_reset = 0; } /* /* * Codec initialization * Codec initialization */ */ Loading @@ -1270,6 +1297,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model, bus_temp.ops.command = azx_send_cmd; bus_temp.ops.command = azx_send_cmd; bus_temp.ops.get_response = azx_get_response; bus_temp.ops.get_response = azx_get_response; bus_temp.ops.attach_pcm = azx_attach_pcm_stream; bus_temp.ops.attach_pcm = azx_attach_pcm_stream; bus_temp.ops.bus_reset = azx_bus_reset; #ifdef CONFIG_SND_HDA_POWER_SAVE #ifdef CONFIG_SND_HDA_POWER_SAVE bus_temp.power_save = &power_save; bus_temp.power_save = &power_save; bus_temp.ops.pm_notify = azx_power_notify; bus_temp.ops.pm_notify = azx_power_notify; Loading Loading @@ -1997,7 +2025,7 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state) for (i = 0; i < AZX_MAX_PCMS; i++) for (i = 0; i < AZX_MAX_PCMS; i++) snd_pcm_suspend_all(chip->pcm[i]); snd_pcm_suspend_all(chip->pcm[i]); if (chip->initialized) if (chip->initialized) snd_hda_suspend(chip->bus, state); snd_hda_suspend(chip->bus); azx_stop_chip(chip); azx_stop_chip(chip); if (chip->irq >= 0) { if (chip->irq >= 0) { free_irq(chip->irq, chip); free_irq(chip->irq, chip); Loading
sound/pci/hda/patch_sigmatel.c +9 −0 Original line number Original line Diff line number Diff line Loading @@ -5375,6 +5375,15 @@ again: if (get_wcaps(codec, 0xa) & AC_WCAP_IN_AMP) if (get_wcaps(codec, 0xa) & AC_WCAP_IN_AMP) snd_hda_sequence_write_cache(codec, unmute_init); snd_hda_sequence_write_cache(codec, unmute_init); /* Some HP machines seem to have unstable codec communications * especially with ATI fglrx driver. For recovering from the * CORB/RIRB stall, allow the BUS reset and keep always sync */ if (spec->board_config == STAC_HP_DV5) { codec->bus->sync_write = 1; codec->bus->allow_bus_reset = 1; } spec->aloopback_ctl = stac92hd71bxx_loopback; spec->aloopback_ctl = stac92hd71bxx_loopback; spec->aloopback_mask = 0x50; spec->aloopback_mask = 0x50; spec->aloopback_shift = 0; spec->aloopback_shift = 0; Loading