summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2009-05-28 11:59:12 +0200
committerTakashi Iwai <tiwai@suse.de>2009-05-28 12:01:24 +0200
commitb05a7d4fed7e51dca37d0a31baf1466de30b1f01 (patch)
tree35a9a23a6289f5c4c966d1068771ab805f123e9c
parentALSA: hda - Support sync after writing a verb (diff)
downloadlinux-b05a7d4fed7e51dca37d0a31baf1466de30b1f01.tar.xz
linux-b05a7d4fed7e51dca37d0a31baf1466de30b1f01.zip
ALSA: hda - Always sync writes in single_cmd mode
In the single_cmd mode, the hardware cannot store the multiple replies like on RIRB, thus each verb has to sync and wait for the response no matter whether the return value is needed or not. Otherwise it may result in a wrong return value from the previous verb. Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/pci/hda/hda_intel.c36
1 files changed, 23 insertions, 13 deletions
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 01d8d97dca4f..31a695e6e37d 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -673,6 +673,27 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus)
* I left the codes, however, for debugging/testing purposes.
*/
+/* receive a response */
+static int azx_single_wait_for_response(struct azx *chip)
+{
+ int timeout = 50;
+
+ while (timeout--) {
+ /* check IRV busy bit */
+ if (azx_readw(chip, IRS) & ICH6_IRS_VALID) {
+ /* reuse rirb.res as the response return value */
+ chip->rirb.res = azx_readl(chip, IR);
+ return 0;
+ }
+ udelay(1);
+ }
+ if (printk_ratelimit())
+ snd_printd(SFX "get_response timeout: IRS=0x%x\n",
+ azx_readw(chip, IRS));
+ chip->rirb.res = -1;
+ return -EIO;
+}
+
/* send a command */
static int azx_single_send_cmd(struct hda_bus *bus, u32 val)
{
@@ -688,7 +709,7 @@ static int azx_single_send_cmd(struct hda_bus *bus, u32 val)
azx_writel(chip, IC, val);
azx_writew(chip, IRS, azx_readw(chip, IRS) |
ICH6_IRS_BUSY);
- return 0;
+ return azx_single_wait_for_response(chip);
}
udelay(1);
}
@@ -702,18 +723,7 @@ static int azx_single_send_cmd(struct hda_bus *bus, u32 val)
static unsigned int azx_single_get_response(struct hda_bus *bus)
{
struct azx *chip = bus->private_data;
- int timeout = 50;
-
- while (timeout--) {
- /* check IRV busy bit */
- if (azx_readw(chip, IRS) & ICH6_IRS_VALID)
- return azx_readl(chip, IR);
- udelay(1);
- }
- if (printk_ratelimit())
- snd_printd(SFX "get_response timeout: IRS=0x%x\n",
- azx_readw(chip, IRS));
- return (unsigned int)-1;
+ return chip->rirb.res;
}
/*