X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=sound%2Fpci%2Fhda%2Fhda_intel.c;h=ba2c754f8a026f6513de5a9db779771a382b80b8;hb=refs%2Fheads%2Fvserver;hp=0ff38cbe7471276eef0a41e07fc95eb4746b0955;hpb=76828883507a47dae78837ab5dec5a5b4513c667;p=linux-2.6.git diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 0ff38cbe7..ba2c754f8 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include "hda_codec.h" @@ -53,6 +54,8 @@ static char *id = SNDRV_DEFAULT_STR1; static char *model; static int position_fix; static int probe_mask = -1; +static int single_cmd; +static int enable_msi; module_param(index, int, 0444); MODULE_PARM_DESC(index, "Index value for Intel HD audio interface."); @@ -64,6 +67,10 @@ module_param(position_fix, int, 0444); MODULE_PARM_DESC(position_fix, "Fix DMA pointer (0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size)."); module_param(probe_mask, int, 0444); MODULE_PARM_DESC(probe_mask, "Bitmask to probe codecs (default = -1)."); +module_param(single_cmd, bool, 0444); +MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs (for debugging only)."); +module_param(enable_msi, int, 0); +MODULE_PARM_DESC(enable_msi, "Enable Message Signaled Interrupt (MSI)"); /* just for backward compatibility */ @@ -76,7 +83,11 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6}," "{Intel, ICH7}," "{Intel, ESB2}," "{Intel, ICH8}," + "{Intel, ICH9}," "{ATI, SB450}," + "{ATI, SB600}," + "{ATI, RS600}," + "{ATI, RS690}," "{VIA, VT8251}," "{VIA, VT8237A}," "{SiS, SIS966}," @@ -162,6 +173,12 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; #define ULI_PLAYBACK_INDEX 5 #define ULI_NUM_PLAYBACK 6 +/* ATI HDMI has 1 playback and 0 capture */ +#define ATIHDMI_CAPTURE_INDEX 0 +#define ATIHDMI_NUM_CAPTURE 0 +#define ATIHDMI_PLAYBACK_INDEX 0 +#define ATIHDMI_NUM_PLAYBACK 1 + /* this number is statically defined for simplicity */ #define MAX_AZX_DEV 16 @@ -182,7 +199,6 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; /* STATESTS int mask: SD2,SD1,SD0 */ #define STATESTS_INT_MASK 0x07 -#define AZX_MAX_CODECS 4 /* SD_CTL bits */ #define SD_CTL_STREAM_RESET 0x01 /* stream reset bit */ @@ -234,25 +250,18 @@ enum { #define NVIDIA_HDA_TRANSREG_ADDR 0x4e #define NVIDIA_HDA_ENABLE_COHBITS 0x0f -/* - * Use CORB/RIRB for communication from/to codecs. - * This is the way recommended by Intel (see below). - */ -#define USE_CORB_RIRB - /* */ struct azx_dev { u32 *bdl; /* virtual address of the BDL */ dma_addr_t bdl_addr; /* physical address of the BDL */ - volatile u32 *posbuf; /* position buffer pointer */ + u32 *posbuf; /* position buffer pointer */ unsigned int bufsize; /* size of the play buffer in bytes */ unsigned int fragsize; /* size of each period in bytes */ unsigned int frags; /* number for period in the play buffer */ unsigned int fifo_size; /* FIFO size */ - unsigned int last_pos; /* last updated period position */ void __iomem *sd_addr; /* stream descriptor pointer */ @@ -263,10 +272,11 @@ struct azx_dev { unsigned int format_val; /* format value to be set in the controller and the codec */ unsigned char stream_tag; /* assigned stream */ unsigned char index; /* stream index */ + /* for sanity check of position buffer */ + unsigned int period_intr; - unsigned int opened: 1; - unsigned int running: 1; - unsigned int period_updating: 1; + unsigned int opened :1; + unsigned int running :1; }; /* CORB/RIRB */ @@ -300,7 +310,7 @@ struct azx { /* locks */ spinlock_t reg_lock; - struct semaphore open_mutex; + struct mutex open_mutex; /* streams (x num_streams) */ struct azx_dev *azx_dev; @@ -324,13 +334,17 @@ struct azx { /* flags */ int position_fix; - unsigned int initialized: 1; + unsigned int initialized :1; + unsigned int single_cmd :1; + unsigned int polling_mode :1; + unsigned int msi :1; }; /* driver types */ enum { AZX_DRIVER_ICH, AZX_DRIVER_ATI, + AZX_DRIVER_ATIHDMI, AZX_DRIVER_VIA, AZX_DRIVER_SIS, AZX_DRIVER_ULI, @@ -340,6 +354,7 @@ enum { static char *driver_short_names[] __devinitdata = { [AZX_DRIVER_ICH] = "HDA Intel", [AZX_DRIVER_ATI] = "HDA ATI SB", + [AZX_DRIVER_ATIHDMI] = "HDA ATI HDMI", [AZX_DRIVER_VIA] = "HDA VIA VT82xx", [AZX_DRIVER_SIS] = "HDA SIS966", [AZX_DRIVER_ULI] = "HDA ULI M5461", @@ -383,12 +398,12 @@ static char *driver_short_names[] __devinitdata = { */ #define upper_32bit(addr) (sizeof(addr) > 4 ? (u32)((addr) >> 32) : (u32)0) +static int azx_acquire_irq(struct azx *chip, int do_disconnect); /* * Interface for HD codec */ -#ifdef USE_CORB_RIRB /* * CORB / RIRB interface */ @@ -436,11 +451,7 @@ static void azx_init_cmd_io(struct azx *chip) /* set N=1, get RIRB response interrupt for new entry */ azx_writew(chip, RINTCNT, 1); /* enable rirb dma and response irq */ -#ifdef USE_CORB_RIRB azx_writeb(chip, RIRBCTL, ICH6_RBCTL_DMA_EN | ICH6_RBCTL_IRQ_EN); -#else - azx_writeb(chip, RIRBCTL, ICH6_RBCTL_DMA_EN); -#endif chip->rirb.rp = chip->rirb.cmds = 0; } @@ -452,8 +463,8 @@ static void azx_free_cmd_io(struct azx *chip) } /* send a command */ -static int azx_send_cmd(struct hda_codec *codec, hda_nid_t nid, int direct, - unsigned int verb, unsigned int para) +static int azx_corb_send_cmd(struct hda_codec *codec, hda_nid_t nid, int direct, + unsigned int verb, unsigned int para) { struct azx *chip = codec->bus->private_data; unsigned int wp; @@ -509,26 +520,53 @@ static void azx_update_rirb(struct azx *chip) } /* receive a response */ -static unsigned int azx_get_response(struct hda_codec *codec) +static unsigned int azx_rirb_get_response(struct hda_codec *codec) { struct azx *chip = codec->bus->private_data; - int timeout = 50; + unsigned long timeout; - while (chip->rirb.cmds) { - if (! --timeout) { - if (printk_ratelimit()) - snd_printk(KERN_ERR - "azx_get_response timeout\n"); - chip->rirb.rp = azx_readb(chip, RIRBWP); - chip->rirb.cmds = 0; - return -1; + again: + timeout = jiffies + msecs_to_jiffies(1000); + do { + if (chip->polling_mode) { + spin_lock_irq(&chip->reg_lock); + azx_update_rirb(chip); + spin_unlock_irq(&chip->reg_lock); } - msleep(1); + if (! chip->rirb.cmds) + return chip->rirb.res; /* the last value */ + schedule_timeout_interruptible(1); + } while (time_after_eq(timeout, jiffies)); + + if (chip->msi) { + snd_printk(KERN_WARNING "hda_intel: No response from codec, " + "disabling MSI...\n"); + free_irq(chip->irq, chip); + chip->irq = -1; + pci_disable_msi(chip->pci); + chip->msi = 0; + if (azx_acquire_irq(chip, 1) < 0) + return -1; + goto again; } - return chip->rirb.res; /* the last value */ + + if (!chip->polling_mode) { + snd_printk(KERN_WARNING "hda_intel: azx_get_response timeout, " + "switching to polling mode...\n"); + chip->polling_mode = 1; + goto again; + } + + snd_printk(KERN_ERR "hda_intel: azx_get_response timeout, " + "switching to single_cmd mode...\n"); + chip->rirb.rp = azx_readb(chip, RIRBWP); + chip->rirb.cmds = 0; + /* switch to single_cmd mode */ + chip->single_cmd = 1; + azx_free_cmd_io(chip); + return -1; } -#else /* * Use the single immediate command instead of CORB/RIRB for simplicity * @@ -539,13 +577,10 @@ static unsigned int azx_get_response(struct hda_codec *codec) * I left the codes, however, for debugging/testing purposes. */ -#define azx_alloc_cmd_io(chip) 0 -#define azx_init_cmd_io(chip) -#define azx_free_cmd_io(chip) - /* send a command */ -static int azx_send_cmd(struct hda_codec *codec, hda_nid_t nid, int direct, - unsigned int verb, unsigned int para) +static int azx_single_send_cmd(struct hda_codec *codec, hda_nid_t nid, + int direct, unsigned int verb, + unsigned int para) { struct azx *chip = codec->bus->private_data; u32 val; @@ -573,7 +608,7 @@ static int azx_send_cmd(struct hda_codec *codec, hda_nid_t nid, int direct, } /* receive a response */ -static unsigned int azx_get_response(struct hda_codec *codec) +static unsigned int azx_single_get_response(struct hda_codec *codec) { struct azx *chip = codec->bus->private_data; int timeout = 50; @@ -588,9 +623,35 @@ static unsigned int azx_get_response(struct hda_codec *codec) return (unsigned int)-1; } -#define azx_update_rirb(chip) +/* + * The below are the main callbacks from hda_codec. + * + * They are just the skeleton to call sub-callbacks according to the + * current setting of chip->single_cmd. + */ + +/* send a command */ +static int azx_send_cmd(struct hda_codec *codec, hda_nid_t nid, + int direct, unsigned int verb, + unsigned int para) +{ + struct azx *chip = codec->bus->private_data; + if (chip->single_cmd) + return azx_single_send_cmd(codec, nid, direct, verb, para); + else + return azx_corb_send_cmd(codec, nid, direct, verb, para); +} + +/* get a response */ +static unsigned int azx_get_response(struct hda_codec *codec) +{ + struct azx *chip = codec->bus->private_data; + if (chip->single_cmd) + return azx_single_get_response(codec); + else + return azx_rirb_get_response(codec); +} -#endif /* USE_CORB_RIRB */ /* reset codec link */ static int azx_reset(struct azx *chip) @@ -613,14 +674,14 @@ static int azx_reset(struct azx *chip) azx_writeb(chip, GCTL, azx_readb(chip, GCTL) | ICH6_GCTL_RESET); count = 50; - while (! azx_readb(chip, GCTL) && --count) + while (!azx_readb(chip, GCTL) && --count) msleep(1); - /* Brent Chartrand said to wait >= 540us for codecs to intialize */ + /* Brent Chartrand said to wait >= 540us for codecs to initialize */ msleep(1); /* check to see if controller is ready */ - if (! azx_readb(chip, GCTL)) { + if (!azx_readb(chip, GCTL)) { snd_printd("azx_reset: controller not ready!\n"); return -EBUSY; } @@ -629,7 +690,7 @@ static int azx_reset(struct azx *chip) azx_writel(chip, GCTL, azx_readl(chip, GCTL) | ICH6_GCTL_UREN); /* detect codecs */ - if (! chip->codec_mask) { + if (!chip->codec_mask) { chip->codec_mask = azx_readw(chip, STATESTS); snd_printdd("codec_mask = 0x%x\n", chip->codec_mask); } @@ -737,7 +798,8 @@ static void azx_init_chip(struct azx *chip) azx_int_enable(chip); /* initialize the codec command I/O */ - azx_init_cmd_io(chip); + if (!chip->single_cmd) + azx_init_cmd_io(chip); /* program the position buffer */ azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr); @@ -764,7 +826,7 @@ static void azx_init_chip(struct azx *chip) /* * interrupt handler */ -static irqreturn_t azx_interrupt(int irq, void* dev_id, struct pt_regs *regs) +static irqreturn_t azx_interrupt(int irq, void *dev_id) { struct azx *chip = dev_id; struct azx_dev *azx_dev; @@ -784,11 +846,10 @@ static irqreturn_t azx_interrupt(int irq, void* dev_id, struct pt_regs *regs) if (status & azx_dev->sd_int_sta_mask) { azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK); if (azx_dev->substream && azx_dev->running) { - azx_dev->period_updating = 1; + azx_dev->period_intr++; spin_unlock(&chip->reg_lock); snd_pcm_period_elapsed(azx_dev->substream); spin_lock(&chip->reg_lock); - azx_dev->period_updating = 0; } } } @@ -796,7 +857,7 @@ static irqreturn_t azx_interrupt(int irq, void* dev_id, struct pt_regs *regs) /* clear rirb int */ status = azx_readb(chip, RIRBSTS); if (status & RIRB_INT_MASK) { - if (status & RIRB_INT_RESPONSE) + if (! chip->single_cmd && (status & RIRB_INT_RESPONSE)) azx_update_rirb(chip); azx_writeb(chip, RIRBSTS, RIRB_INT_MASK); } @@ -904,6 +965,16 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev) * Codec initialization */ +static unsigned int azx_max_codecs[] __devinitdata = { + [AZX_DRIVER_ICH] = 3, + [AZX_DRIVER_ATI] = 4, + [AZX_DRIVER_ATIHDMI] = 4, + [AZX_DRIVER_VIA] = 3, /* FIXME: correct? */ + [AZX_DRIVER_SIS] = 3, /* FIXME: correct? */ + [AZX_DRIVER_ULI] = 3, /* FIXME: correct? */ + [AZX_DRIVER_NVIDIA] = 3, /* FIXME: correct? */ +}; + static int __devinit azx_codec_create(struct azx *chip, const char *model) { struct hda_bus_template bus_temp; @@ -920,7 +991,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model) return err; codecs = 0; - for (c = 0; c < AZX_MAX_CODECS; c++) { + for (c = 0; c < azx_max_codecs[chip->driver_type]; c++) { if ((chip->codec_mask & (1 << c)) & probe_mask) { err = snd_hda_codec_new(chip->bus, c, NULL); if (err < 0) @@ -970,8 +1041,9 @@ static struct snd_pcm_hardware azx_pcm_hw = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE /*|*/ - /*SNDRV_PCM_INFO_RESUME*/), + /* No full-resume yet implemented */ + /* SNDRV_PCM_INFO_RESUME |*/ + SNDRV_PCM_INFO_PAUSE), .formats = SNDRV_PCM_FMTBIT_S16_LE, .rates = SNDRV_PCM_RATE_48000, .rate_min = 48000, @@ -1002,10 +1074,10 @@ static int azx_pcm_open(struct snd_pcm_substream *substream) unsigned long flags; int err; - down(&chip->open_mutex); + mutex_lock(&chip->open_mutex); azx_dev = azx_assign_device(chip, substream->stream); if (azx_dev == NULL) { - up(&chip->open_mutex); + mutex_unlock(&chip->open_mutex); return -EBUSY; } runtime->hw = azx_pcm_hw; @@ -1017,7 +1089,7 @@ static int azx_pcm_open(struct snd_pcm_substream *substream) snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); if ((err = hinfo->ops.open(hinfo, apcm->codec, substream)) < 0) { azx_release_device(azx_dev); - up(&chip->open_mutex); + mutex_unlock(&chip->open_mutex); return err; } spin_lock_irqsave(&chip->reg_lock, flags); @@ -1026,7 +1098,7 @@ static int azx_pcm_open(struct snd_pcm_substream *substream) spin_unlock_irqrestore(&chip->reg_lock, flags); runtime->private_data = azx_dev; - up(&chip->open_mutex); + mutex_unlock(&chip->open_mutex); return 0; } @@ -1038,14 +1110,14 @@ static int azx_pcm_close(struct snd_pcm_substream *substream) struct azx_dev *azx_dev = get_azx_dev(substream); unsigned long flags; - down(&chip->open_mutex); + mutex_lock(&chip->open_mutex); spin_lock_irqsave(&chip->reg_lock, flags); azx_dev->substream = NULL; azx_dev->running = 0; spin_unlock_irqrestore(&chip->reg_lock, flags); azx_release_device(azx_dev); hinfo->ops.close(hinfo, apcm->codec, substream); - up(&chip->open_mutex); + mutex_unlock(&chip->open_mutex); return 0; } @@ -1099,7 +1171,6 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1; else azx_dev->fifo_size = 0; - azx_dev->last_pos = 0; return hinfo->ops.prepare(hinfo, apcm->codec, azx_dev->stream_tag, azx_dev->format_val, substream); @@ -1147,10 +1218,20 @@ static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream) struct azx_dev *azx_dev = get_azx_dev(substream); unsigned int pos; - if (chip->position_fix == POS_FIX_POSBUF) { + if (chip->position_fix == POS_FIX_POSBUF || + chip->position_fix == POS_FIX_AUTO) { /* use the position buffer */ - pos = *azx_dev->posbuf; + pos = le32_to_cpu(*azx_dev->posbuf); + if (chip->position_fix == POS_FIX_AUTO && + azx_dev->period_intr == 1 && ! pos) { + printk(KERN_WARNING + "hda-intel: Invalid position buffer, " + "using LPIB read method instead.\n"); + chip->position_fix = POS_FIX_NONE; + goto read_lpib; + } } else { + read_lpib: /* read LPIB */ pos = azx_sd_readl(azx_dev, SD_LPIB); if (chip->position_fix == POS_FIX_FIFO) @@ -1184,7 +1265,12 @@ static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec, struct snd_pcm *pcm; struct azx_pcm *apcm; - snd_assert(cpcm->stream[0].substreams || cpcm->stream[1].substreams, return -EINVAL); + /* if no substreams are defined for both playback and capture, + * it's just a placeholder. ignore it. + */ + if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams) + return 0; + snd_assert(cpcm->name, return -EINVAL); err = snd_pcm_new(chip->card, cpcm->name, pcm_dev, @@ -1210,7 +1296,8 @@ static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec, snd_dma_pci_data(chip->pci), 1024 * 64, 1024 * 128); chip->pcm[pcm_dev] = pcm; - chip->pcm_devs = pcm_dev + 1; + if (chip->pcm_devs < pcm_dev + 1) + chip->pcm_devs = pcm_dev + 1; return 0; } @@ -1288,7 +1375,7 @@ static int __devinit azx_init_stream(struct azx *chip) struct azx_dev *azx_dev = &chip->azx_dev[i]; azx_dev->bdl = (u32 *)(chip->bdl.area + off); azx_dev->bdl_addr = chip->bdl.addr + off; - azx_dev->posbuf = (volatile u32 *)(chip->posbuf.area + i * 8); + azx_dev->posbuf = (u32 __iomem *)(chip->posbuf.area + i * 8); /* offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */ azx_dev->sd_addr = chip->remap_addr + (0x20 * i + 0x80); /* int mask: SDI0=0x01, SDI1=0x02, ... SDO3=0x80 */ @@ -1301,6 +1388,21 @@ static int __devinit azx_init_stream(struct azx *chip) return 0; } +static int azx_acquire_irq(struct azx *chip, int do_disconnect) +{ + if (request_irq(chip->pci->irq, azx_interrupt, + chip->msi ? 0 : IRQF_SHARED, + "HDA Intel", chip)) { + printk(KERN_ERR "hda-intel: unable to grab IRQ %d, " + "disabling device\n", chip->pci->irq); + if (do_disconnect) + snd_card_disconnect(chip->card); + return -1; + } + chip->irq = chip->pci->irq; + return 0; +} + #ifdef CONFIG_PM /* @@ -1317,8 +1419,16 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state) snd_pcm_suspend_all(chip->pcm[i]); snd_hda_suspend(chip->bus, state); azx_free_cmd_io(chip); + if (chip->irq >= 0) { + synchronize_irq(chip->irq); + free_irq(chip->irq, chip); + chip->irq = -1; + } + if (chip->msi) + pci_disable_msi(chip->pci); pci_disable_device(pci); pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); return 0; } @@ -1327,9 +1437,20 @@ static int azx_resume(struct pci_dev *pci) struct snd_card *card = pci_get_drvdata(pci); struct azx *chip = card->private_data; + pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); - pci_enable_device(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "hda-intel: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } pci_set_master(pci); + if (chip->msi) + if (pci_enable_msi(pci) < 0) + chip->msi = 0; + if (azx_acquire_irq(chip, 1) < 0) + return -EIO; azx_init_chip(chip); snd_hda_resume(chip->bus); snd_power_change_state(card, SNDRV_CTL_POWER_D0); @@ -1359,13 +1480,14 @@ static int azx_free(struct azx *chip) /* disable position buffer */ azx_writel(chip, DPLBASE, 0); azx_writel(chip, DPUBASE, 0); - - /* wait a little for interrupts to finish */ - msleep(1); } - if (chip->irq >= 0) + if (chip->irq >= 0) { + synchronize_irq(chip->irq); free_irq(chip->irq, (void*)chip); + } + if (chip->msi) + pci_disable_msi(chip->pci); if (chip->remap_addr) iounmap(chip->remap_addr); @@ -1396,32 +1518,34 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, struct azx **rchip) { struct azx *chip; - int err = 0; + int err; static struct snd_device_ops ops = { .dev_free = azx_dev_free, }; *rchip = NULL; - if ((err = pci_enable_device(pci)) < 0) + err = pci_enable_device(pci); + if (err < 0) return err; chip = kzalloc(sizeof(*chip), GFP_KERNEL); - - if (NULL == chip) { + if (!chip) { snd_printk(KERN_ERR SFX "cannot allocate chip\n"); pci_disable_device(pci); return -ENOMEM; } spin_lock_init(&chip->reg_lock); - init_MUTEX(&chip->open_mutex); + mutex_init(&chip->open_mutex); chip->card = card; chip->pci = pci; chip->irq = -1; chip->driver_type = driver_type; + chip->msi = enable_msi; - chip->position_fix = position_fix ? position_fix : POS_FIX_POSBUF; + chip->position_fix = position_fix; + chip->single_cmd = single_cmd; #if BITS_PER_LONG != 64 /* Fix up base address on ULI M5461 */ @@ -1433,13 +1557,14 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, } #endif - if ((err = pci_request_regions(pci, "ICH HD audio")) < 0) { + err = pci_request_regions(pci, "ICH HD audio"); + if (err < 0) { kfree(chip); pci_disable_device(pci); return err; } - chip->addr = pci_resource_start(pci,0); + chip->addr = pci_resource_start(pci, 0); chip->remap_addr = ioremap_nocache(chip->addr, pci_resource_len(pci,0)); if (chip->remap_addr == NULL) { snd_printk(KERN_ERR SFX "ioremap error\n"); @@ -1447,13 +1572,14 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, goto errout; } - if (request_irq(pci->irq, azx_interrupt, SA_INTERRUPT|SA_SHIRQ, - "HDA Intel", (void*)chip)) { - snd_printk(KERN_ERR SFX "unable to grab IRQ %d\n", pci->irq); + if (chip->msi) + if (pci_enable_msi(pci) < 0) + chip->msi = 0; + + if (azx_acquire_irq(chip, 0) < 0) { err = -EBUSY; goto errout; } - chip->irq = pci->irq; pci_set_master(pci); synchronize_irq(chip->irq); @@ -1465,6 +1591,12 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, chip->playback_index_offset = ULI_PLAYBACK_INDEX; chip->capture_index_offset = ULI_CAPTURE_INDEX; break; + case AZX_DRIVER_ATIHDMI: + chip->playback_streams = ATIHDMI_NUM_PLAYBACK; + chip->capture_streams = ATIHDMI_NUM_CAPTURE; + chip->playback_index_offset = ATIHDMI_PLAYBACK_INDEX; + chip->capture_index_offset = ATIHDMI_CAPTURE_INDEX; + break; default: chip->playback_streams = ICH6_NUM_PLAYBACK; chip->capture_streams = ICH6_NUM_CAPTURE; @@ -1474,7 +1606,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, } chip->num_streams = chip->playback_streams + chip->capture_streams; chip->azx_dev = kcalloc(chip->num_streams, sizeof(*chip->azx_dev), GFP_KERNEL); - if (! chip->azx_dev) { + if (!chip->azx_dev) { snd_printk(KERN_ERR "cannot malloc azx_dev\n"); goto errout; } @@ -1492,8 +1624,9 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, goto errout; } /* allocate CORB/RIRB */ - if ((err = azx_alloc_cmd_io(chip)) < 0) - goto errout; + if (! chip->single_cmd) + if ((err = azx_alloc_cmd_io(chip)) < 0) + goto errout; /* initialize streams */ azx_init_stream(chip); @@ -1504,7 +1637,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, chip->initialized = 1; /* codec detection */ - if (! chip->codec_mask) { + if (!chip->codec_mask) { snd_printk(KERN_ERR SFX "no codecs found!\n"); err = -ENODEV; goto errout; @@ -1531,16 +1664,16 @@ static int __devinit azx_probe(struct pci_dev *pci, const struct pci_device_id * { struct snd_card *card; struct azx *chip; - int err = 0; + int err; card = snd_card_new(index, id, THIS_MODULE, 0); - if (NULL == card) { + if (!card) { snd_printk(KERN_ERR SFX "Error creating card!\n"); return -ENOMEM; } - if ((err = azx_create(card, pci, pci_id->driver_data, - &chip)) < 0) { + err = azx_create(card, pci, pci_id->driver_data, &chip); + if (err < 0) { snd_card_free(card); return err; } @@ -1588,12 +1721,23 @@ static struct pci_device_id azx_ids[] = { { 0x8086, 0x27d8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH7 */ { 0x8086, 0x269a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ESB2 */ { 0x8086, 0x284b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH8 */ + { 0x8086, 0x293e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH9 */ + { 0x8086, 0x293f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH9 */ { 0x1002, 0x437b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB450 */ + { 0x1002, 0x4383, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB600 */ + { 0x1002, 0x793b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RS600 HDMI */ + { 0x1002, 0x7919, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RS690 HDMI */ { 0x1106, 0x3288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_VIA }, /* VIA VT8251/VT8237A */ { 0x1039, 0x7502, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_SIS }, /* SIS966 */ { 0x10b9, 0x5461, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ULI }, /* ULI M5461 */ - { 0x10de, 0x026c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA 026c */ - { 0x10de, 0x0371, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA 0371 */ + { 0x10de, 0x026c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP51 */ + { 0x10de, 0x0371, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP55 */ + { 0x10de, 0x03e4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP61 */ + { 0x10de, 0x03f0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP61 */ + { 0x10de, 0x044a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP65 */ + { 0x10de, 0x044b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP65 */ + { 0x10de, 0x055c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP67 */ + { 0x10de, 0x055d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP67 */ { 0, } }; MODULE_DEVICE_TABLE(pci, azx_ids);