Commit b05a7d4f authored by Takashi Iwai's avatar Takashi Iwai

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: default avatarTakashi Iwai <tiwai@suse.de>
parent aa2936f5
...@@ -673,6 +673,27 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus) ...@@ -673,6 +673,27 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus)
* I left the codes, however, for debugging/testing purposes. * 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 */ /* send a command */
static int azx_single_send_cmd(struct hda_bus *bus, u32 val) 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) ...@@ -688,7 +709,7 @@ static int azx_single_send_cmd(struct hda_bus *bus, u32 val)
azx_writel(chip, IC, val); azx_writel(chip, IC, val);
azx_writew(chip, IRS, azx_readw(chip, IRS) | azx_writew(chip, IRS, azx_readw(chip, IRS) |
ICH6_IRS_BUSY); ICH6_IRS_BUSY);
return 0; return azx_single_wait_for_response(chip);
} }
udelay(1); udelay(1);
} }
...@@ -702,18 +723,7 @@ static int azx_single_send_cmd(struct hda_bus *bus, u32 val) ...@@ -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) static unsigned int azx_single_get_response(struct hda_bus *bus)
{ {
struct azx *chip = bus->private_data; struct azx *chip = bus->private_data;
int timeout = 50; return chip->rirb.res;
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;
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment