Merge branch 'fix/hda' into topic/hda

This commit is contained in:
Takashi Iwai 2009-08-03 08:37:17 +02:00
commit e44d4e4cee
5 changed files with 88 additions and 36 deletions

View file

@ -185,7 +185,7 @@ static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd,
mutex_lock(&bus->cmd_mutex); mutex_lock(&bus->cmd_mutex);
err = bus->ops.command(bus, cmd); err = bus->ops.command(bus, cmd);
if (!err && res) if (!err && res)
*res = bus->ops.get_response(bus); *res = bus->ops.get_response(bus, codec->addr);
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 (res && *res == -1 && bus->rirb_error) {

View file

@ -568,7 +568,7 @@ struct hda_bus_ops {
/* send a single command */ /* send a single command */
int (*command)(struct hda_bus *bus, unsigned int cmd); int (*command)(struct hda_bus *bus, unsigned int cmd);
/* get a response from the last command */ /* get a response from the last command */
unsigned int (*get_response)(struct hda_bus *bus); unsigned int (*get_response)(struct hda_bus *bus, unsigned int addr);
/* free the private data */ /* free the private data */
void (*private_free)(struct hda_bus *); void (*private_free)(struct hda_bus *);
/* attach a PCM stream */ /* attach a PCM stream */

View file

@ -260,7 +260,7 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
/* STATESTS int mask: S3,SD2,SD1,SD0 */ /* STATESTS int mask: S3,SD2,SD1,SD0 */
#define AZX_MAX_CODECS 4 #define AZX_MAX_CODECS 4
#define STATESTS_INT_MASK 0x0f #define STATESTS_INT_MASK ((1 << AZX_MAX_CODECS) - 1)
/* SD_CTL bits */ /* SD_CTL bits */
#define SD_CTL_STREAM_RESET 0x01 /* stream reset bit */ #define SD_CTL_STREAM_RESET 0x01 /* stream reset bit */
@ -368,8 +368,8 @@ struct azx_rb {
dma_addr_t addr; /* physical address of CORB/RIRB buffer */ dma_addr_t addr; /* physical address of CORB/RIRB buffer */
/* for RIRB */ /* for RIRB */
unsigned short rp, wp; /* read/write pointers */ unsigned short rp, wp; /* read/write pointers */
int cmds; /* number of pending requests */ int cmds[AZX_MAX_CODECS]; /* number of pending requests */
u32 res; /* last read value */ u32 res[AZX_MAX_CODECS]; /* last read value */
}; };
struct azx { struct azx {
@ -425,7 +425,7 @@ struct azx {
unsigned int probing :1; /* codec probing phase */ unsigned int probing :1; /* codec probing phase */
/* for debugging */ /* for debugging */
unsigned int last_cmd; /* last issued command (to sync) */ unsigned int last_cmd[AZX_MAX_CODECS];
/* for pending irqs */ /* for pending irqs */
struct work_struct irq_pending_work; struct work_struct irq_pending_work;
@ -520,6 +520,7 @@ static int azx_alloc_cmd_io(struct azx *chip)
static void azx_init_cmd_io(struct azx *chip) static void azx_init_cmd_io(struct azx *chip)
{ {
spin_lock_irq(&chip->reg_lock);
/* CORB set up */ /* CORB set up */
chip->corb.addr = chip->rb.addr; chip->corb.addr = chip->rb.addr;
chip->corb.buf = (u32 *)chip->rb.area; chip->corb.buf = (u32 *)chip->rb.area;
@ -538,7 +539,8 @@ static void azx_init_cmd_io(struct azx *chip)
/* RIRB set up */ /* RIRB set up */
chip->rirb.addr = chip->rb.addr + 2048; chip->rirb.addr = chip->rb.addr + 2048;
chip->rirb.buf = (u32 *)(chip->rb.area + 2048); chip->rirb.buf = (u32 *)(chip->rb.area + 2048);
chip->rirb.wp = chip->rirb.rp = chip->rirb.cmds = 0; chip->rirb.wp = chip->rirb.rp = 0;
memset(chip->rirb.cmds, 0, sizeof(chip->rirb.cmds));
azx_writel(chip, RIRBLBASE, (u32)chip->rirb.addr); azx_writel(chip, RIRBLBASE, (u32)chip->rirb.addr);
azx_writel(chip, RIRBUBASE, upper_32_bits(chip->rirb.addr)); azx_writel(chip, RIRBUBASE, upper_32_bits(chip->rirb.addr));
@ -550,30 +552,60 @@ static void azx_init_cmd_io(struct azx *chip)
azx_writew(chip, RINTCNT, 1); azx_writew(chip, RINTCNT, 1);
/* enable rirb dma and response irq */ /* enable rirb dma and response irq */
azx_writeb(chip, RIRBCTL, ICH6_RBCTL_DMA_EN | ICH6_RBCTL_IRQ_EN); azx_writeb(chip, RIRBCTL, ICH6_RBCTL_DMA_EN | ICH6_RBCTL_IRQ_EN);
spin_unlock_irq(&chip->reg_lock);
} }
static void azx_free_cmd_io(struct azx *chip) static void azx_free_cmd_io(struct azx *chip)
{ {
spin_lock_irq(&chip->reg_lock);
/* disable ringbuffer DMAs */ /* disable ringbuffer DMAs */
azx_writeb(chip, RIRBCTL, 0); azx_writeb(chip, RIRBCTL, 0);
azx_writeb(chip, CORBCTL, 0); azx_writeb(chip, CORBCTL, 0);
spin_unlock_irq(&chip->reg_lock);
}
static unsigned int azx_command_addr(u32 cmd)
{
unsigned int addr = cmd >> 28;
if (addr >= AZX_MAX_CODECS) {
snd_BUG();
addr = 0;
}
return addr;
}
static unsigned int azx_response_addr(u32 res)
{
unsigned int addr = res & 0xf;
if (addr >= AZX_MAX_CODECS) {
snd_BUG();
addr = 0;
}
return addr;
} }
/* send a command */ /* send a command */
static int azx_corb_send_cmd(struct hda_bus *bus, u32 val) static int azx_corb_send_cmd(struct hda_bus *bus, u32 val)
{ {
struct azx *chip = bus->private_data; struct azx *chip = bus->private_data;
unsigned int addr = azx_command_addr(val);
unsigned int wp; unsigned int wp;
spin_lock_irq(&chip->reg_lock);
/* add command to corb */ /* add command to corb */
wp = azx_readb(chip, CORBWP); wp = azx_readb(chip, CORBWP);
wp++; wp++;
wp %= ICH6_MAX_CORB_ENTRIES; wp %= ICH6_MAX_CORB_ENTRIES;
spin_lock_irq(&chip->reg_lock); chip->rirb.cmds[addr]++;
chip->rirb.cmds++;
chip->corb.buf[wp] = cpu_to_le32(val); chip->corb.buf[wp] = cpu_to_le32(val);
azx_writel(chip, CORBWP, wp); azx_writel(chip, CORBWP, wp);
spin_unlock_irq(&chip->reg_lock); spin_unlock_irq(&chip->reg_lock);
return 0; return 0;
@ -585,13 +617,14 @@ static int azx_corb_send_cmd(struct hda_bus *bus, u32 val)
static void azx_update_rirb(struct azx *chip) static void azx_update_rirb(struct azx *chip)
{ {
unsigned int rp, wp; unsigned int rp, wp;
unsigned int addr;
u32 res, res_ex; u32 res, res_ex;
wp = azx_readb(chip, RIRBWP); wp = azx_readb(chip, RIRBWP);
if (wp == chip->rirb.wp) if (wp == chip->rirb.wp)
return; return;
chip->rirb.wp = wp; chip->rirb.wp = wp;
while (chip->rirb.rp != wp) { while (chip->rirb.rp != wp) {
chip->rirb.rp++; chip->rirb.rp++;
chip->rirb.rp %= ICH6_MAX_RIRB_ENTRIES; chip->rirb.rp %= ICH6_MAX_RIRB_ENTRIES;
@ -599,18 +632,24 @@ static void azx_update_rirb(struct azx *chip)
rp = chip->rirb.rp << 1; /* an RIRB entry is 8-bytes */ rp = chip->rirb.rp << 1; /* an RIRB entry is 8-bytes */
res_ex = le32_to_cpu(chip->rirb.buf[rp + 1]); res_ex = le32_to_cpu(chip->rirb.buf[rp + 1]);
res = le32_to_cpu(chip->rirb.buf[rp]); res = le32_to_cpu(chip->rirb.buf[rp]);
addr = azx_response_addr(res_ex);
if (res_ex & ICH6_RIRB_EX_UNSOL_EV) if (res_ex & ICH6_RIRB_EX_UNSOL_EV)
snd_hda_queue_unsol_event(chip->bus, res, res_ex); snd_hda_queue_unsol_event(chip->bus, res, res_ex);
else if (chip->rirb.cmds) { else if (chip->rirb.cmds[addr]) {
chip->rirb.res = res; chip->rirb.res[addr] = res;
smp_wmb(); smp_wmb();
chip->rirb.cmds--; chip->rirb.cmds[addr]--;
} } else
snd_printk(KERN_ERR SFX "spurious response %#x:%#x, "
"last cmd=%#08x\n",
res, res_ex,
chip->last_cmd[addr]);
} }
} }
/* receive a response */ /* receive a response */
static unsigned int azx_rirb_get_response(struct hda_bus *bus) static unsigned int azx_rirb_get_response(struct hda_bus *bus,
unsigned int addr)
{ {
struct azx *chip = bus->private_data; struct azx *chip = bus->private_data;
unsigned long timeout; unsigned long timeout;
@ -623,10 +662,10 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus)
azx_update_rirb(chip); azx_update_rirb(chip);
spin_unlock_irq(&chip->reg_lock); spin_unlock_irq(&chip->reg_lock);
} }
if (!chip->rirb.cmds) { if (!chip->rirb.cmds[addr]) {
smp_rmb(); smp_rmb();
bus->rirb_error = 0; bus->rirb_error = 0;
return chip->rirb.res; /* the last value */ return chip->rirb.res[addr]; /* the last value */
} }
if (time_after(jiffies, timeout)) if (time_after(jiffies, timeout))
break; break;
@ -640,7 +679,8 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus)
if (chip->msi) { if (chip->msi) {
snd_printk(KERN_WARNING SFX "No response from codec, " snd_printk(KERN_WARNING SFX "No response from codec, "
"disabling MSI: last cmd=0x%08x\n", chip->last_cmd); "disabling MSI: last cmd=0x%08x\n",
chip->last_cmd[addr]);
free_irq(chip->irq, chip); free_irq(chip->irq, chip);
chip->irq = -1; chip->irq = -1;
pci_disable_msi(chip->pci); pci_disable_msi(chip->pci);
@ -655,7 +695,7 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus)
if (!chip->polling_mode) { if (!chip->polling_mode) {
snd_printk(KERN_WARNING SFX "azx_get_response timeout, " snd_printk(KERN_WARNING SFX "azx_get_response timeout, "
"switching to polling mode: last cmd=0x%08x\n", "switching to polling mode: last cmd=0x%08x\n",
chip->last_cmd); chip->last_cmd[addr]);
chip->polling_mode = 1; chip->polling_mode = 1;
goto again; goto again;
} }
@ -679,7 +719,7 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus)
snd_printk(KERN_ERR "hda_intel: azx_get_response timeout, " snd_printk(KERN_ERR "hda_intel: azx_get_response timeout, "
"switching to single_cmd mode: last cmd=0x%08x\n", "switching to single_cmd mode: last cmd=0x%08x\n",
chip->last_cmd); chip->last_cmd[addr]);
chip->single_cmd = 1; chip->single_cmd = 1;
bus->response_reset = 0; bus->response_reset = 0;
/* re-initialize CORB/RIRB */ /* re-initialize CORB/RIRB */
@ -699,7 +739,7 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus)
*/ */
/* receive a response */ /* receive a response */
static int azx_single_wait_for_response(struct azx *chip) static int azx_single_wait_for_response(struct azx *chip, unsigned int addr)
{ {
int timeout = 50; int timeout = 50;
@ -707,7 +747,7 @@ static int azx_single_wait_for_response(struct azx *chip)
/* check IRV busy bit */ /* check IRV busy bit */
if (azx_readw(chip, IRS) & ICH6_IRS_VALID) { if (azx_readw(chip, IRS) & ICH6_IRS_VALID) {
/* reuse rirb.res as the response return value */ /* reuse rirb.res as the response return value */
chip->rirb.res = azx_readl(chip, IR); chip->rirb.res[addr] = azx_readl(chip, IR);
return 0; return 0;
} }
udelay(1); udelay(1);
@ -715,7 +755,7 @@ static int azx_single_wait_for_response(struct azx *chip)
if (printk_ratelimit()) if (printk_ratelimit())
snd_printd(SFX "get_response timeout: IRS=0x%x\n", snd_printd(SFX "get_response timeout: IRS=0x%x\n",
azx_readw(chip, IRS)); azx_readw(chip, IRS));
chip->rirb.res = -1; chip->rirb.res[addr] = -1;
return -EIO; return -EIO;
} }
@ -723,6 +763,7 @@ static int azx_single_wait_for_response(struct azx *chip)
static int azx_single_send_cmd(struct hda_bus *bus, u32 val) static int azx_single_send_cmd(struct hda_bus *bus, u32 val)
{ {
struct azx *chip = bus->private_data; struct azx *chip = bus->private_data;
unsigned int addr = azx_command_addr(val);
int timeout = 50; int timeout = 50;
bus->rirb_error = 0; bus->rirb_error = 0;
@ -735,7 +776,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 azx_single_wait_for_response(chip); return azx_single_wait_for_response(chip, addr);
} }
udelay(1); udelay(1);
} }
@ -746,10 +787,11 @@ static int azx_single_send_cmd(struct hda_bus *bus, u32 val)
} }
/* receive a response */ /* receive a response */
static unsigned int azx_single_get_response(struct hda_bus *bus) static unsigned int azx_single_get_response(struct hda_bus *bus,
unsigned int addr)
{ {
struct azx *chip = bus->private_data; struct azx *chip = bus->private_data;
return chip->rirb.res; return chip->rirb.res[addr];
} }
/* /*
@ -764,7 +806,7 @@ static int azx_send_cmd(struct hda_bus *bus, unsigned int val)
{ {
struct azx *chip = bus->private_data; struct azx *chip = bus->private_data;
chip->last_cmd = val; chip->last_cmd[azx_command_addr(val)] = val;
if (chip->single_cmd) if (chip->single_cmd)
return azx_single_send_cmd(bus, val); return azx_single_send_cmd(bus, val);
else else
@ -772,13 +814,14 @@ static int azx_send_cmd(struct hda_bus *bus, unsigned int val)
} }
/* get a response */ /* get a response */
static unsigned int azx_get_response(struct hda_bus *bus) static unsigned int azx_get_response(struct hda_bus *bus,
unsigned int addr)
{ {
struct azx *chip = bus->private_data; struct azx *chip = bus->private_data;
if (chip->single_cmd) if (chip->single_cmd)
return azx_single_get_response(bus); return azx_single_get_response(bus, addr);
else else
return azx_rirb_get_response(bus); return azx_rirb_get_response(bus, addr);
} }
#ifdef CONFIG_SND_HDA_POWER_SAVE #ifdef CONFIG_SND_HDA_POWER_SAVE
@ -1250,10 +1293,12 @@ static int probe_codec(struct azx *chip, int addr)
(AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID; (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID;
unsigned int res; unsigned int res;
mutex_lock(&chip->bus->cmd_mutex);
chip->probing = 1; chip->probing = 1;
azx_send_cmd(chip->bus, cmd); azx_send_cmd(chip->bus, cmd);
res = azx_get_response(chip->bus); res = azx_get_response(chip->bus, addr);
chip->probing = 0; chip->probing = 0;
mutex_unlock(&chip->bus->cmd_mutex);
if (res == -1) if (res == -1)
return -EIO; return -EIO;
snd_printdd(SFX "codec #%d probed OK\n", addr); snd_printdd(SFX "codec #%d probed OK\n", addr);

View file

@ -271,13 +271,13 @@ struct alc_spec {
*/ */
unsigned int num_init_verbs; unsigned int num_init_verbs;
char stream_name_analog[16]; /* analog PCM stream */ char stream_name_analog[32]; /* analog PCM stream */
struct hda_pcm_stream *stream_analog_playback; struct hda_pcm_stream *stream_analog_playback;
struct hda_pcm_stream *stream_analog_capture; struct hda_pcm_stream *stream_analog_capture;
struct hda_pcm_stream *stream_analog_alt_playback; struct hda_pcm_stream *stream_analog_alt_playback;
struct hda_pcm_stream *stream_analog_alt_capture; struct hda_pcm_stream *stream_analog_alt_capture;
char stream_name_digital[16]; /* digital PCM stream */ char stream_name_digital[32]; /* digital PCM stream */
struct hda_pcm_stream *stream_digital_playback; struct hda_pcm_stream *stream_digital_playback;
struct hda_pcm_stream *stream_digital_capture; struct hda_pcm_stream *stream_digital_capture;
@ -557,7 +557,7 @@ static int alc_pin_mode_get(struct snd_kcontrol *kcontrol,
/* Find enumerated value for current pinctl setting */ /* Find enumerated value for current pinctl setting */
i = alc_pin_mode_min(dir); i = alc_pin_mode_min(dir);
while (alc_pin_mode_values[i] != pinctl && i <= alc_pin_mode_max(dir)) while (i <= alc_pin_mode_max(dir) && alc_pin_mode_values[i] != pinctl)
i++; i++;
*valp = i <= alc_pin_mode_max(dir) ? i: alc_pin_mode_min(dir); *valp = i <= alc_pin_mode_max(dir) ? i: alc_pin_mode_min(dir);
return 0; return 0;
@ -15018,7 +15018,7 @@ static struct snd_pci_quirk alc861vd_cfg_tbl[] = {
SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST), SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST),
SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba A135", ALC861VD_LENOVO), SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba A135", ALC861VD_LENOVO),
/*SND_PCI_QUIRK(0x1179, 0xff00, "DALLAS", ALC861VD_DALLAS),*/ /*lenovo*/ /*SND_PCI_QUIRK(0x1179, 0xff00, "DALLAS", ALC861VD_DALLAS),*/ /*lenovo*/
SND_PCI_QUIRK(0x1179, 0xff01, "DALLAS", ALC861VD_DALLAS), SND_PCI_QUIRK(0x1179, 0xff01, "Toshiba A135", ALC861VD_LENOVO),
SND_PCI_QUIRK(0x1179, 0xff03, "Toshiba P205", ALC861VD_LENOVO), SND_PCI_QUIRK(0x1179, 0xff03, "Toshiba P205", ALC861VD_LENOVO),
SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba L30-149", ALC861VD_DALLAS), SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba L30-149", ALC861VD_DALLAS),
SND_PCI_QUIRK(0x1565, 0x820d, "Biostar NF61S SE", ALC861VD_6ST_DIG), SND_PCI_QUIRK(0x1565, 0x820d, "Biostar NF61S SE", ALC861VD_6ST_DIG),

View file

@ -2251,7 +2251,7 @@ static struct snd_pci_quirk stac927x_cfg_tbl[] = {
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f3, "Dell Inspiron 1420", STAC_DELL_BIOS), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f3, "Dell Inspiron 1420", STAC_DELL_BIOS),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0227, "Dell Vostro 1400 ", STAC_DELL_BIOS), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0227, "Dell Vostro 1400 ", STAC_DELL_BIOS),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x022e, "Dell ", STAC_DELL_BIOS), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x022e, "Dell ", STAC_DELL_BIOS),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x022f, "Dell Inspiron 1525", STAC_DELL_3ST), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x022f, "Dell Inspiron 1525", STAC_DELL_BIOS),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0242, "Dell ", STAC_DELL_BIOS), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0242, "Dell ", STAC_DELL_BIOS),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0243, "Dell ", STAC_DELL_BIOS), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0243, "Dell ", STAC_DELL_BIOS),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ff, "Dell ", STAC_DELL_BIOS), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ff, "Dell ", STAC_DELL_BIOS),
@ -5870,6 +5870,13 @@ static int patch_stac927x(struct hda_codec *codec)
/* GPIO2 High = Enable EAPD */ /* GPIO2 High = Enable EAPD */
spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x04; spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x04;
spec->gpio_data = 0x04; spec->gpio_data = 0x04;
switch (codec->subsystem_id) {
case 0x1028022f:
/* correct EAPD to be GPIO0 */
spec->eapd_mask = spec->gpio_mask = 0x01;
spec->gpio_dir = spec->gpio_data = 0x01;
break;
};
spec->dmic_nids = stac927x_dmic_nids; spec->dmic_nids = stac927x_dmic_nids;
spec->num_dmics = STAC927X_NUM_DMICS; spec->num_dmics = STAC927X_NUM_DMICS;