diff options
Diffstat (limited to 'sound/pci/intel8x0.c')
| -rw-r--r-- | sound/pci/intel8x0.c | 643 |
1 files changed, 463 insertions, 180 deletions
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index c52abd0bf22..c91860e0a28 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -32,7 +32,7 @@ #include <linux/init.h> #include <linux/pci.h> #include <linux/slab.h> -#include <linux/moduleparam.h> +#include <linux/module.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/ac97_codec.h> @@ -42,6 +42,12 @@ #include <asm/pgtable.h> #include <asm/cacheflush.h> +#ifdef CONFIG_KVM_GUEST +#include <linux/kvm_para.h> +#else +#define kvm_para_available() (0) +#endif + MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); MODULE_DESCRIPTION("Intel 82801AA,82901AB,i810,i820,i830,i840,i845,MX440; SiS 7012; Ali 5455"); MODULE_LICENSE("GPL"); @@ -59,6 +65,12 @@ MODULE_SUPPORTED_DEVICE("{{Intel,82801AA-ICH}," "{SiS,SI7012}," "{NVidia,nForce Audio}," "{NVidia,nForce2 Audio}," + "{NVidia,nForce3 Audio}," + "{NVidia,MCP04}," + "{NVidia,MCP501}," + "{NVidia,CK804}," + "{NVidia,CK8}," + "{NVidia,CK8S}," "{AMD,AMD768}," "{AMD,AMD8111}," "{ALI,M5455}}"); @@ -67,30 +79,33 @@ static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ static int ac97_clock; static char *ac97_quirk; -static int buggy_semaphore; +static bool buggy_semaphore; static int buggy_irq = -1; /* auto-check */ -static int xbox; +static bool xbox; static int spdif_aclink = -1; +static int inside_vm = -1; module_param(index, int, 0444); MODULE_PARM_DESC(index, "Index value for Intel i8x0 soundcard."); module_param(id, charp, 0444); MODULE_PARM_DESC(id, "ID string for Intel i8x0 soundcard."); module_param(ac97_clock, int, 0444); -MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (0 = auto-detect)."); +MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (0 = whitelist + auto-detect, 1 = force autodetect)."); module_param(ac97_quirk, charp, 0444); MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware."); module_param(buggy_semaphore, bool, 0444); MODULE_PARM_DESC(buggy_semaphore, "Enable workaround for hardwares with problematic codec semaphores."); -module_param(buggy_irq, bool, 0444); +module_param(buggy_irq, bint, 0444); MODULE_PARM_DESC(buggy_irq, "Enable workaround for buggy interrupts on some motherboards."); module_param(xbox, bool, 0444); MODULE_PARM_DESC(xbox, "Set to 1 for Xbox, if you have problems with the AC'97 codec detection."); module_param(spdif_aclink, int, 0444); MODULE_PARM_DESC(spdif_aclink, "S/PDIF over AC-link."); +module_param(inside_vm, bint, 0444); +MODULE_PARM_DESC(inside_vm, "KVM/Parallels optimization."); /* just for backward compatibility */ -static int enable; +static bool enable; module_param(enable, bool, 0444); static int joystick; module_param(joystick, int, 0444); @@ -155,7 +170,8 @@ DEFINE_REGSET(SP, 0x60); /* SPDIF out */ #define ICH_PCM_SPDIF_69 0x80000000 /* s/pdif pcm on slots 6&9 */ #define ICH_PCM_SPDIF_1011 0xc0000000 /* s/pdif pcm on slots 10&11 */ #define ICH_PCM_20BIT 0x00400000 /* 20-bit samples (ICH4) */ -#define ICH_PCM_246_MASK 0x00300000 /* 6 channels (not all chips) */ +#define ICH_PCM_246_MASK 0x00300000 /* chan mask (not all chips) */ +#define ICH_PCM_8 0x00300000 /* 8 channels (not all chips) */ #define ICH_PCM_6 0x00200000 /* 6 channels (not all chips) */ #define ICH_PCM_4 0x00100000 /* 4 channels (not all chips) */ #define ICH_PCM_2 0x00000000 /* 2 channels (stereo) */ @@ -348,6 +364,7 @@ struct ichdev { unsigned int fragsize1; unsigned int position; unsigned int pos_shift; + unsigned int last_pos; int frags; int lvi; int lvi_frag; @@ -382,6 +399,7 @@ struct intel8x0 { unsigned multi4: 1, multi6: 1, + multi8 :1, dra: 1, smp20bit: 1; unsigned in_ac97_init: 1, @@ -391,6 +409,7 @@ struct intel8x0 { unsigned buggy_irq: 1; /* workaround for buggy mobos */ unsigned xbox: 1; /* workaround for Xbox AC'97 detection */ unsigned buggy_semaphore: 1; /* workaround for buggy codec semaphore */ + unsigned inside_vm: 1; /* enable VM optimization */ int spdif_idx; /* SPDIF BAR index; *_SPBAR or -1 if use PCMOUT */ unsigned int sdm_saved; /* SDM reg value */ @@ -411,30 +430,30 @@ struct intel8x0 { u32 int_sta_mask; /* interrupt status mask */ }; -static struct pci_device_id snd_intel8x0_ids[] = { - { 0x8086, 0x2415, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* 82801AA */ - { 0x8086, 0x2425, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* 82901AB */ - { 0x8086, 0x2445, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* 82801BA */ - { 0x8086, 0x2485, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* ICH3 */ - { 0x8086, 0x24c5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL_ICH4 }, /* ICH4 */ - { 0x8086, 0x24d5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL_ICH4 }, /* ICH5 */ - { 0x8086, 0x25a6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL_ICH4 }, /* ESB */ - { 0x8086, 0x266e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL_ICH4 }, /* ICH6 */ - { 0x8086, 0x27de, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL_ICH4 }, /* ICH7 */ - { 0x8086, 0x2698, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL_ICH4 }, /* ESB2 */ - { 0x8086, 0x7195, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* 440MX */ - { 0x1039, 0x7012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_SIS }, /* SI7012 */ - { 0x10de, 0x01b1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE }, /* NFORCE */ - { 0x10de, 0x003a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE }, /* MCP04 */ - { 0x10de, 0x006a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE }, /* NFORCE2 */ - { 0x10de, 0x0059, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE }, /* CK804 */ - { 0x10de, 0x008a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE }, /* CK8 */ - { 0x10de, 0x00da, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE }, /* NFORCE3 */ - { 0x10de, 0x00ea, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE }, /* CK8S */ - { 0x10de, 0x026b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE }, /* MCP51 */ - { 0x1022, 0x746d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* AMD8111 */ - { 0x1022, 0x7445, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* AMD768 */ - { 0x10b9, 0x5455, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_ALI }, /* Ali5455 */ +static DEFINE_PCI_DEVICE_TABLE(snd_intel8x0_ids) = { + { PCI_VDEVICE(INTEL, 0x2415), DEVICE_INTEL }, /* 82801AA */ + { PCI_VDEVICE(INTEL, 0x2425), DEVICE_INTEL }, /* 82901AB */ + { PCI_VDEVICE(INTEL, 0x2445), DEVICE_INTEL }, /* 82801BA */ + { PCI_VDEVICE(INTEL, 0x2485), DEVICE_INTEL }, /* ICH3 */ + { PCI_VDEVICE(INTEL, 0x24c5), DEVICE_INTEL_ICH4 }, /* ICH4 */ + { PCI_VDEVICE(INTEL, 0x24d5), DEVICE_INTEL_ICH4 }, /* ICH5 */ + { PCI_VDEVICE(INTEL, 0x25a6), DEVICE_INTEL_ICH4 }, /* ESB */ + { PCI_VDEVICE(INTEL, 0x266e), DEVICE_INTEL_ICH4 }, /* ICH6 */ + { PCI_VDEVICE(INTEL, 0x27de), DEVICE_INTEL_ICH4 }, /* ICH7 */ + { PCI_VDEVICE(INTEL, 0x2698), DEVICE_INTEL_ICH4 }, /* ESB2 */ + { PCI_VDEVICE(INTEL, 0x7195), DEVICE_INTEL }, /* 440MX */ + { PCI_VDEVICE(SI, 0x7012), DEVICE_SIS }, /* SI7012 */ + { PCI_VDEVICE(NVIDIA, 0x01b1), DEVICE_NFORCE }, /* NFORCE */ + { PCI_VDEVICE(NVIDIA, 0x003a), DEVICE_NFORCE }, /* MCP04 */ + { PCI_VDEVICE(NVIDIA, 0x006a), DEVICE_NFORCE }, /* NFORCE2 */ + { PCI_VDEVICE(NVIDIA, 0x0059), DEVICE_NFORCE }, /* CK804 */ + { PCI_VDEVICE(NVIDIA, 0x008a), DEVICE_NFORCE }, /* CK8 */ + { PCI_VDEVICE(NVIDIA, 0x00da), DEVICE_NFORCE }, /* NFORCE3 */ + { PCI_VDEVICE(NVIDIA, 0x00ea), DEVICE_NFORCE }, /* CK8S */ + { PCI_VDEVICE(NVIDIA, 0x026b), DEVICE_NFORCE }, /* MCP51 */ + { PCI_VDEVICE(AMD, 0x746d), DEVICE_INTEL }, /* AMD8111 */ + { PCI_VDEVICE(AMD, 0x7445), DEVICE_INTEL }, /* AMD768 */ + { PCI_VDEVICE(AL, 0x5455), DEVICE_ALI }, /* Ali5455 */ { 0, } }; @@ -525,10 +544,11 @@ static int snd_intel8x0_codec_semaphore(struct intel8x0 *chip, unsigned int code udelay(10); } while (time--); - /* access to some forbidden (non existant) ac97 registers will not + /* access to some forbidden (non existent) ac97 registers will not * reset the semaphore. So even if you don't get the semaphore, still * continue the access. We don't need the semaphore anyway. */ - snd_printk(KERN_ERR "codec_semaphore: semaphore is not ready [0x%x][0x%x]\n", + dev_err(chip->card->dev, + "codec_semaphore: semaphore is not ready [0x%x][0x%x]\n", igetbyte(chip, ICHREG(ACC_SEMA)), igetdword(chip, ICHREG(GLOB_STA))); iagetword(chip, 0); /* clear semaphore flag */ /* I don't care about the semaphore */ @@ -543,7 +563,9 @@ static void snd_intel8x0_codec_write(struct snd_ac97 *ac97, if (snd_intel8x0_codec_semaphore(chip, ac97->num) < 0) { if (! chip->in_ac97_init) - snd_printk(KERN_ERR "codec_write %d: semaphore is not ready for register 0x%x\n", ac97->num, reg); + dev_err(chip->card->dev, + "codec_write %d: semaphore is not ready for register 0x%x\n", + ac97->num, reg); } iaputword(chip, reg + ac97->num * 0x80, val); } @@ -557,7 +579,9 @@ static unsigned short snd_intel8x0_codec_read(struct snd_ac97 *ac97, if (snd_intel8x0_codec_semaphore(chip, ac97->num) < 0) { if (! chip->in_ac97_init) - snd_printk(KERN_ERR "codec_read %d: semaphore is not ready for register 0x%x\n", ac97->num, reg); + dev_err(chip->card->dev, + "codec_read %d: semaphore is not ready for register 0x%x\n", + ac97->num, reg); res = 0xffff; } else { res = iagetword(chip, reg + ac97->num * 0x80); @@ -566,15 +590,17 @@ static unsigned short snd_intel8x0_codec_read(struct snd_ac97 *ac97, iputdword(chip, ICHREG(GLOB_STA), tmp & ~(chip->codec_ready_bits | ICH_GSCI)); if (! chip->in_ac97_init) - snd_printk(KERN_ERR "codec_read %d: read timeout for register 0x%x\n", ac97->num, reg); + dev_err(chip->card->dev, + "codec_read %d: read timeout for register 0x%x\n", + ac97->num, reg); res = 0xffff; } } return res; } -static void __devinit snd_intel8x0_codec_read_test(struct intel8x0 *chip, - unsigned int codec) +static void snd_intel8x0_codec_read_test(struct intel8x0 *chip, + unsigned int codec) { unsigned int tmp; @@ -600,7 +626,7 @@ static int snd_intel8x0_ali_codec_ready(struct intel8x0 *chip, int mask) return 0; } if (! chip->in_ac97_init) - snd_printd(KERN_WARNING "intel8x0: AC97 codec ready timeout.\n"); + dev_warn(chip->card->dev, "AC97 codec ready timeout.\n"); return -EBUSY; } @@ -609,10 +635,10 @@ static int snd_intel8x0_ali_codec_semaphore(struct intel8x0 *chip) int time = 100; if (chip->buggy_semaphore) return 0; /* just ignore ... */ - while (time-- && (igetdword(chip, ICHREG(ALI_CAS)) & ALI_CAS_SEM_BUSY)) + while (--time && (igetdword(chip, ICHREG(ALI_CAS)) & ALI_CAS_SEM_BUSY)) udelay(1); if (! time && ! chip->in_ac97_init) - snd_printk(KERN_WARNING "ali_codec_semaphore timeout\n"); + dev_warn(chip->card->dev, "ali_codec_semaphore timeout\n"); return snd_intel8x0_ali_codec_ready(chip, ALI_CSPSR_CODEC_READY); } @@ -681,7 +707,7 @@ static void snd_intel8x0_setup_periods(struct intel8x0 *chip, struct ichdev *ich bdbar[idx + 1] = cpu_to_le32(0x80000000 | /* interrupt on completion */ ichdev->fragsize >> ichdev->pos_shift); #if 0 - printk("bdbar[%i] = 0x%x [0x%x]\n", + dev_dbg(chip->card->dev, "bdbar[%i] = 0x%x [0x%x]\n", idx + 0, bdbar[idx + 0], bdbar[idx + 1]); #endif } @@ -693,8 +719,10 @@ static void snd_intel8x0_setup_periods(struct intel8x0 *chip, struct ichdev *ich ichdev->lvi_frag = ICH_REG_LVI_MASK % ichdev->frags; ichdev->position = 0; #if 0 - printk("lvi_frag = %i, frags = %i, period_size = 0x%x, period_size1 = 0x%x\n", - ichdev->lvi_frag, ichdev->frags, ichdev->fragsize, ichdev->fragsize1); + dev_dbg(chip->card->dev, + "lvi_frag = %i, frags = %i, period_size = 0x%x, period_size1 = 0x%x\n", + ichdev->lvi_frag, ichdev->frags, ichdev->fragsize, + ichdev->fragsize1); #endif /* clear interrupts */ iputbyte(chip, port + ichdev->roff_sr, ICH_FIFOE | ICH_BCIS | ICH_LVBCI); @@ -705,7 +733,7 @@ static void snd_intel8x0_setup_periods(struct intel8x0 *chip, struct ichdev *ich * Intel 82443MX running a 100MHz processor system bus has a hardware bug, * which aborts PCI busmaster for audio transfer. A workaround is to set * the pages as non-cached. For details, see the errata in - * http://www.intel.com/design/chipsets/specupdt/245051.htm + * http://download.intel.com/design/chipsets/specupdt/24505108.pdf */ static void fill_nocache(void *buf, int size, int nocache) { @@ -760,7 +788,8 @@ static inline void snd_intel8x0_update(struct intel8x0 *chip, struct ichdev *ich ichdev->lvi_frag %= ichdev->frags; ichdev->bdbar[ichdev->lvi * 2] = cpu_to_le32(ichdev->physbuf + ichdev->lvi_frag * ichdev->fragsize1); #if 0 - printk("new: bdbar[%i] = 0x%x [0x%x], prefetch = %i, all = 0x%x, 0x%x\n", + dev_dbg(chip->card->dev, + "new: bdbar[%i] = 0x%x [0x%x], prefetch = %i, all = 0x%x, 0x%x\n", ichdev->lvi * 2, ichdev->bdbar[ichdev->lvi * 2], ichdev->bdbar[ichdev->lvi * 2 + 1], inb(ICH_REG_OFF_PIV + port), inl(port + 4), inb(port + ICH_REG_OFF_CR)); @@ -827,7 +856,9 @@ static int snd_intel8x0_pcm_trigger(struct snd_pcm_substream *substream, int cmd ichdev->suspended = 0; /* fallthru */ case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: val = ICH_IOCE | ICH_STARTBM; + ichdev->last_pos = ichdev->position; break; case SNDRV_PCM_TRIGGER_SUSPEND: ichdev->suspended = 1; @@ -838,9 +869,6 @@ static int snd_intel8x0_pcm_trigger(struct snd_pcm_substream *substream, int cmd case SNDRV_PCM_TRIGGER_PAUSE_PUSH: val = ICH_IOCE; break; - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - val = ICH_IOCE | ICH_STARTBM; - break; default: return -EINVAL; } @@ -997,6 +1025,8 @@ static void snd_intel8x0_setup_pcm_out(struct intel8x0 *chip, cnt |= ICH_PCM_4; else if (runtime->channels == 6) cnt |= ICH_PCM_6; + else if (runtime->channels == 8) + cnt |= ICH_PCM_8; if (chip->device_type == DEVICE_NFORCE) { /* reset to 2ch once to keep the 6 channel data in alignment, * to start from Front Left always @@ -1040,7 +1070,7 @@ static snd_pcm_uframes_t snd_intel8x0_pcm_pointer(struct snd_pcm_substream *subs struct intel8x0 *chip = snd_pcm_substream_chip(substream); struct ichdev *ichdev = get_ichdev(substream); size_t ptr1, ptr; - int civ, timeout = 100; + int civ, timeout = 10; unsigned int position; spin_lock(&chip->reg_lock); @@ -1052,13 +1082,37 @@ static snd_pcm_uframes_t snd_intel8x0_pcm_pointer(struct snd_pcm_substream *subs udelay(10); continue; } - if (civ == igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV) && - ptr1 == igetword(chip, ichdev->reg_offset + ichdev->roff_picb)) + if (civ != igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV)) + continue; + + /* IO read operation is very expensive inside virtual machine + * as it is emulated. The probability that subsequent PICB read + * will return different result is high enough to loop till + * timeout here. + * Same CIV is strict enough condition to be sure that PICB + * is valid inside VM on emulated card. */ + if (chip->inside_vm) + break; + if (ptr1 == igetword(chip, ichdev->reg_offset + ichdev->roff_picb)) break; } while (timeout--); - ptr1 <<= ichdev->pos_shift; - ptr = ichdev->fragsize1 - ptr1; - ptr += position; + ptr = ichdev->last_pos; + if (ptr1 != 0) { + ptr1 <<= ichdev->pos_shift; + ptr = ichdev->fragsize1 - ptr1; + ptr += position; + if (ptr < ichdev->last_pos) { + unsigned int pos_base, last_base; + pos_base = position / ichdev->fragsize1; + last_base = ichdev->last_pos / ichdev->fragsize1; + /* another sanity check; ptr1 can go back to full + * before the base position is updated + */ + if (pos_base == last_base) + ptr = ichdev->last_pos; + } + } + ichdev->last_pos = ptr; spin_unlock(&chip->reg_lock); if (ptr >= ichdev->size) return 0; @@ -1106,6 +1160,16 @@ static struct snd_pcm_hw_constraint_list hw_constraints_channels6 = { .mask = 0, }; +static unsigned int channels8[] = { + 2, 4, 6, 8, +}; + +static struct snd_pcm_hw_constraint_list hw_constraints_channels8 = { + .count = ARRAY_SIZE(channels8), + .list = channels8, + .mask = 0, +}; + static int snd_intel8x0_pcm_open(struct snd_pcm_substream *substream, struct ichdev *ichdev) { struct intel8x0 *chip = snd_pcm_substream_chip(substream); @@ -1136,7 +1200,12 @@ static int snd_intel8x0_playback_open(struct snd_pcm_substream *substream) if (err < 0) return err; - if (chip->multi6) { + if (chip->multi8) { + runtime->hw.channels_max = 8; + snd_pcm_hw_constraint_list(runtime, 0, + SNDRV_PCM_HW_PARAM_CHANNELS, + &hw_constraints_channels8); + } else if (chip->multi6) { runtime->hw.channels_max = 6; snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &hw_constraints_channels6); @@ -1445,8 +1514,8 @@ struct ich_pcm_table { int ac97_idx; }; -static int __devinit snd_intel8x0_pcm1(struct intel8x0 *chip, int device, - struct ich_pcm_table *rec) +static int snd_intel8x0_pcm1(struct intel8x0 *chip, int device, + struct ich_pcm_table *rec) { struct snd_pcm *pcm; int err; @@ -1479,10 +1548,29 @@ static int __devinit snd_intel8x0_pcm1(struct intel8x0 *chip, int device, snd_dma_pci_data(chip->pci), rec->prealloc_size, rec->prealloc_max_size); + if (rec->playback_ops && + rec->playback_ops->open == snd_intel8x0_playback_open) { + struct snd_pcm_chmap *chmap; + int chs = 2; + if (chip->multi8) + chs = 8; + else if (chip->multi6) + chs = 6; + else if (chip->multi4) + chs = 4; + err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, + snd_pcm_alt_chmaps, chs, 0, + &chmap); + if (err < 0) + return err; + chmap->channel_mask = SND_PCM_CHMAP_MASK_2468; + chip->ac97[0]->chmaps[SNDRV_PCM_STREAM_PLAYBACK] = chmap; + } + return 0; } -static struct ich_pcm_table intel_pcms[] __devinitdata = { +static struct ich_pcm_table intel_pcms[] = { { .playback_ops = &snd_intel8x0_playback_ops, .capture_ops = &snd_intel8x0_capture_ops, @@ -1519,7 +1607,7 @@ static struct ich_pcm_table intel_pcms[] __devinitdata = { }, }; -static struct ich_pcm_table nforce_pcms[] __devinitdata = { +static struct ich_pcm_table nforce_pcms[] = { { .playback_ops = &snd_intel8x0_playback_ops, .capture_ops = &snd_intel8x0_capture_ops, @@ -1542,7 +1630,7 @@ static struct ich_pcm_table nforce_pcms[] __devinitdata = { }, }; -static struct ich_pcm_table ali_pcms[] __devinitdata = { +static struct ich_pcm_table ali_pcms[] = { { .playback_ops = &snd_intel8x0_ali_playback_ops, .capture_ops = &snd_intel8x0_ali_capture_ops, @@ -1574,7 +1662,7 @@ static struct ich_pcm_table ali_pcms[] __devinitdata = { #endif }; -static int __devinit snd_intel8x0_pcm(struct intel8x0 *chip) +static int snd_intel8x0_pcm(struct intel8x0 *chip) { int i, tblsize, device, err; struct ich_pcm_table *tbl, *rec; @@ -1637,7 +1725,7 @@ static void snd_intel8x0_mixer_free_ac97(struct snd_ac97 *ac97) chip->ac97[ac97->num] = NULL; } -static struct ac97_pcm ac97_pcm_defs[] __devinitdata = { +static struct ac97_pcm ac97_pcm_defs[] = { /* front PCM */ { .exclusive = 1, @@ -1707,7 +1795,7 @@ static struct ac97_pcm ac97_pcm_defs[] __devinitdata = { }, }; -static struct ac97_quirk ac97_quirks[] __devinitdata = { +static struct ac97_quirk ac97_quirks[] = { { .subvendor = 0x0e11, .subdevice = 0x000e, @@ -1734,6 +1822,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { }, { .subvendor = 0x1014, + .subdevice = 0x0534, + .name = "ThinkPad X31", + .type = AC97_TUNE_INV_EAPD + }, + { + .subvendor = 0x1014, .subdevice = 0x1f00, .name = "MS-9128", .type = AC97_TUNE_ALC_JACK @@ -1812,6 +1906,18 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { }, { .subvendor = 0x1028, + .subdevice = 0x016a, + .name = "Dell Inspiron 8600", /* STAC9750/51 */ + .type = AC97_TUNE_HP_ONLY + }, + { + .subvendor = 0x1028, + .subdevice = 0x0182, + .name = "Dell Latitude D610", /* STAC9750/51 */ + .type = AC97_TUNE_HP_ONLY + }, + { + .subvendor = 0x1028, .subdevice = 0x0186, .name = "Dell Latitude D810", /* cf. Malone #41015 */ .type = AC97_TUNE_HP_MUTE_LED @@ -1824,6 +1930,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { }, { .subvendor = 0x1028, + .subdevice = 0x0189, + .name = "Dell Inspiron 9300", + .type = AC97_TUNE_HP_MUTE_LED + }, + { + .subvendor = 0x1028, .subdevice = 0x0191, .name = "Dell Inspiron 8600", .type = AC97_TUNE_HP_ONLY @@ -1854,12 +1966,6 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { }, { .subvendor = 0x103c, - .subdevice = 0x0934, - .name = "HP nx8220", - .type = AC97_TUNE_MUTE_LED - }, - { - .subvendor = 0x103c, .subdevice = 0x129d, .name = "HP xw8000", .type = AC97_TUNE_HP_ONLY @@ -1908,10 +2014,28 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { }, { .subvendor = 0x104d, + .subdevice = 0x8144, + .name = "Sony", + .type = AC97_TUNE_INV_EAPD + }, + { + .subvendor = 0x104d, .subdevice = 0x8197, .name = "Sony S1XP", .type = AC97_TUNE_INV_EAPD }, + { + .subvendor = 0x104d, + .subdevice = 0x81c0, + .name = "Sony VAIO VGN-T350P", /*AD1981B*/ + .type = AC97_TUNE_INV_EAPD + }, + { + .subvendor = 0x104d, + .subdevice = 0x81c5, + .name = "Sony VAIO VGN-B1VP", /*AD1981B*/ + .type = AC97_TUNE_INV_EAPD + }, { .subvendor = 0x1043, .subdevice = 0x80f3, @@ -1938,6 +2062,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { }, { .subvendor = 0x10cf, + .subdevice = 0x127d, + .name = "Fujitsu Lifebook P7010", + .type = AC97_TUNE_HP_ONLY + }, + { + .subvendor = 0x10cf, .subdevice = 0x127e, .name = "Fujitsu Lifebook C1211D", .type = AC97_TUNE_HP_ONLY @@ -1997,6 +2127,18 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { .type = AC97_TUNE_HP_ONLY }, { + .subvendor = 0x161f, + .subdevice = 0x202f, + .name = "Gateway M520", + .type = AC97_TUNE_INV_EAPD + }, + { + .subvendor = 0x161f, + .subdevice = 0x203a, + .name = "Gateway 4525GZ", /* AD1981B */ + .type = AC97_TUNE_INV_EAPD + }, + { .subvendor = 0x1734, .subdevice = 0x0088, .name = "Fujitsu-Siemens D1522", /* AD1981 */ @@ -2060,8 +2202,8 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { { } /* terminator */ }; -static int __devinit snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock, - const char *quirk_override) +static int snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock, + const char *quirk_override) { struct snd_ac97_bus *pbus; struct snd_ac97_template ac97; @@ -2090,7 +2232,7 @@ static int __devinit snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock, case DEVICE_INTEL_ICH4: chip->spdif_idx = ICHD_SPBAR; break; - }; + } } chip->in_ac97_init = 1; @@ -2113,8 +2255,8 @@ static int __devinit snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock, snd_intel8x0_codec_read_test(chip, codecs); chip->ac97_sdin[codecs] = igetbyte(chip, ICHREG(SDM)) & ICH_LDI_MASK; - snd_assert(chip->ac97_sdin[codecs] < 3, - chip->ac97_sdin[codecs] = 0); + if (snd_BUG_ON(chip->ac97_sdin[codecs] >= 3)) + chip->ac97_sdin[codecs] = 0; } else chip->ac97_sdin[codecs] = i; codecs++; @@ -2154,7 +2296,8 @@ static int __devinit snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock, ac97.num = i; if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97[i])) < 0) { if (err != -EACCES) - snd_printk(KERN_ERR "Unable to initialize codec #%d\n", i); + dev_err(chip->card->dev, + "Unable to initialize codec #%d\n", i); if (i == 0) goto __err; } @@ -2203,8 +2346,11 @@ static int __devinit snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock, } if (pbus->pcms[0].r[0].slots & (1 << AC97_SLOT_PCM_SLEFT)) { chip->multi4 = 1; - if (pbus->pcms[0].r[0].slots & (1 << AC97_SLOT_LFE)) + if (pbus->pcms[0].r[0].slots & (1 << AC97_SLOT_LFE)) { chip->multi6 = 1; + if (chip->ac97[0]->flags & AC97_HAS_8CH) + chip->multi8 = 1; + } } if (pbus->pcms[0].r[1].rslots[0]) { chip->dra = 1; @@ -2253,23 +2399,23 @@ static void do_ali_reset(struct intel8x0 *chip) iputdword(chip, ICHREG(ALI_INTERRUPTSR), 0x00000000); } -static int snd_intel8x0_ich_chip_init(struct intel8x0 *chip, int probing) -{ - unsigned long end_time; - unsigned int cnt, status, nstatus; - - /* put logic to right state */ - /* first clear status bits */ - status = ICH_RCS | ICH_MCINT | ICH_POINT | ICH_PIINT; - if (chip->device_type == DEVICE_NFORCE) - status |= ICH_NVSPINT; - cnt = igetdword(chip, ICHREG(GLOB_STA)); - iputdword(chip, ICHREG(GLOB_STA), cnt & status); +#ifdef CONFIG_SND_AC97_POWER_SAVE +static struct snd_pci_quirk ich_chip_reset_mode[] = { + SND_PCI_QUIRK(0x1014, 0x051f, "Thinkpad R32", 1), + { } /* end */ +}; +static int snd_intel8x0_ich_chip_cold_reset(struct intel8x0 *chip) +{ + unsigned int cnt; /* ACLink on, 2 channels */ + + if (snd_pci_quirk_lookup(chip->pci, ich_chip_reset_mode)) + return -EIO; + cnt = igetdword(chip, ICHREG(GLOB_CNT)); cnt &= ~(ICH_ACLINK | ICH_PCM_246_MASK); -#ifdef CONFIG_SND_AC97_POWER_SAVE + /* do cold reset - the full ac97 powerdown may leave the controller * in a warm state but actually it cannot communicate with the codec. */ @@ -2278,22 +2424,58 @@ static int snd_intel8x0_ich_chip_init(struct intel8x0 *chip, int probing) udelay(10); iputdword(chip, ICHREG(GLOB_CNT), cnt | ICH_AC97COLD); msleep(1); + return 0; +} +#define snd_intel8x0_ich_chip_can_cold_reset(chip) \ + (!snd_pci_quirk_lookup(chip->pci, ich_chip_reset_mode)) #else +#define snd_intel8x0_ich_chip_cold_reset(chip) 0 +#define snd_intel8x0_ich_chip_can_cold_reset(chip) (0) +#endif + +static int snd_intel8x0_ich_chip_reset(struct intel8x0 *chip) +{ + unsigned long end_time; + unsigned int cnt; + /* ACLink on, 2 channels */ + cnt = igetdword(chip, ICHREG(GLOB_CNT)); + cnt &= ~(ICH_ACLINK | ICH_PCM_246_MASK); /* finish cold or do warm reset */ cnt |= (cnt & ICH_AC97COLD) == 0 ? ICH_AC97COLD : ICH_AC97WARM; iputdword(chip, ICHREG(GLOB_CNT), cnt); end_time = (jiffies + (HZ / 4)) + 1; do { if ((igetdword(chip, ICHREG(GLOB_CNT)) & ICH_AC97WARM) == 0) - goto __ok; + return 0; schedule_timeout_uninterruptible(1); } while (time_after_eq(end_time, jiffies)); - snd_printk(KERN_ERR "AC'97 warm reset still in progress? [0x%x]\n", + dev_err(chip->card->dev, "AC'97 warm reset still in progress? [0x%x]\n", igetdword(chip, ICHREG(GLOB_CNT))); return -EIO; +} + +static int snd_intel8x0_ich_chip_init(struct intel8x0 *chip, int probing) +{ + unsigned long end_time; + unsigned int status, nstatus; + unsigned int cnt; + int err; + + /* put logic to right state */ + /* first clear status bits */ + status = ICH_RCS | ICH_MCINT | ICH_POINT | ICH_PIINT; + if (chip->device_type == DEVICE_NFORCE) + status |= ICH_NVSPINT; + cnt = igetdword(chip, ICHREG(GLOB_STA)); + iputdword(chip, ICHREG(GLOB_STA), cnt & status); + + if (snd_intel8x0_ich_chip_can_cold_reset(chip)) + err = snd_intel8x0_ich_chip_cold_reset(chip); + else + err = snd_intel8x0_ich_chip_reset(chip); + if (err < 0) + return err; - __ok: -#endif if (probing) { /* wait for any codec ready status. * Once it becomes ready it should remain ready @@ -2309,7 +2491,8 @@ static int snd_intel8x0_ich_chip_init(struct intel8x0 *chip, int probing) } while (time_after_eq(end_time, jiffies)); if (! status) { /* no codec is found */ - snd_printk(KERN_ERR "codec_ready: codec is not ready [0x%x]\n", + dev_err(chip->card->dev, + "codec_ready: codec is not ready [0x%x]\n", igetdword(chip, ICHREG(GLOB_STA))); return -EIO; } @@ -2373,7 +2556,7 @@ static int snd_intel8x0_ali_chip_init(struct intel8x0 *chip, int probing) goto __ok; schedule_timeout_uninterruptible(1); } - snd_printk(KERN_ERR "AC'97 reset failed.\n"); + dev_err(chip->card->dev, "AC'97 reset failed.\n"); if (probing) return -EIO; @@ -2417,7 +2600,7 @@ static int snd_intel8x0_chip_init(struct intel8x0 *chip, int probing) break; } if (timeout == 0) - printk(KERN_ERR "intel8x0: reset of registers failed?\n"); + dev_err(chip->card->dev, "reset of registers failed?\n"); } /* initialize Buffer Descriptor Lists */ for (i = 0; i < chip->bdbars_count; i++) @@ -2446,7 +2629,7 @@ static int snd_intel8x0_free(struct intel8x0 *chip) pci_write_config_dword(chip->pci, 0x4c, val); } /* --- */ - synchronize_irq(chip->irq); + __hw_end: if (chip->irq >= 0) free_irq(chip->irq, chip); @@ -2465,13 +2648,14 @@ static int snd_intel8x0_free(struct intel8x0 *chip) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP /* * power management */ -static int intel8x0_suspend(struct pci_dev *pci, pm_message_t state) +static int intel8x0_suspend(struct device *dev) { - struct snd_card *card = pci_get_drvdata(pci); + struct pci_dev *pci = to_pci_dev(dev); + struct snd_card *card = dev_get_drvdata(dev); struct intel8x0 *chip = card->private_data; int i; @@ -2495,7 +2679,6 @@ static int intel8x0_suspend(struct pci_dev *pci, pm_message_t state) chip->sdm_saved = igetbyte(chip, ICHREG(SDM)); if (chip->irq >= 0) { - synchronize_irq(chip->irq); free_irq(chip->irq, chip); chip->irq = -1; } @@ -2504,30 +2687,30 @@ static int intel8x0_suspend(struct pci_dev *pci, pm_message_t state) /* The call below may disable built-in speaker on some laptops * after S2RAM. So, don't touch it. */ - /* pci_set_power_state(pci, pci_choose_state(pci, state)); */ + /* pci_set_power_state(pci, PCI_D3hot); */ return 0; } -static int intel8x0_resume(struct pci_dev *pci) +static int intel8x0_resume(struct device *dev) { - struct snd_card *card = pci_get_drvdata(pci); + struct pci_dev *pci = to_pci_dev(dev); + struct snd_card *card = dev_get_drvdata(dev); struct intel8x0 *chip = card->private_data; int i; pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); if (pci_enable_device(pci) < 0) { - printk(KERN_ERR "intel8x0: pci_enable_device failed, " - "disabling device\n"); + dev_err(dev, "pci_enable_device failed, disabling device\n"); snd_card_disconnect(card); return -EIO; } pci_set_master(pci); snd_intel8x0_chip_init(chip, 0); if (request_irq(pci->irq, snd_intel8x0_interrupt, - IRQF_SHARED, card->shortname, chip)) { - printk(KERN_ERR "intel8x0: unable to grab IRQ %d, " - "disabling device\n", pci->irq); + IRQF_SHARED, KBUILD_MODNAME, chip)) { + dev_err(dev, "unable to grab IRQ %d, disabling device\n", + pci->irq); snd_card_disconnect(card); return -EIO; } @@ -2580,34 +2763,43 @@ static int intel8x0_resume(struct pci_dev *pci) snd_power_change_state(card, SNDRV_CTL_POWER_D0); return 0; } -#endif /* CONFIG_PM */ + +static SIMPLE_DEV_PM_OPS(intel8x0_pm, intel8x0_suspend, intel8x0_resume); +#define INTEL8X0_PM_OPS &intel8x0_pm +#else +#define INTEL8X0_PM_OPS NULL +#endif /* CONFIG_PM_SLEEP */ #define INTEL8X0_TESTBUF_SIZE 32768 /* enough large for one shot */ -static void __devinit intel8x0_measure_ac97_clock(struct intel8x0 *chip) +static void intel8x0_measure_ac97_clock(struct intel8x0 *chip) { struct snd_pcm_substream *subs; struct ichdev *ichdev; unsigned long port; - unsigned long pos, t; - struct timeval start_time, stop_time; + unsigned long pos, pos1, t; + int civ, timeout = 1000, attempt = 1; + ktime_t start_time, stop_time; if (chip->ac97_bus->clock != 48000) return; /* specified in module option */ + __again: subs = chip->pcm[0]->streams[0].substream; if (! subs || subs->dma_buffer.bytes < INTEL8X0_TESTBUF_SIZE) { - snd_printk(KERN_WARNING "no playback buffer allocated - aborting measure ac97 clock\n"); + dev_warn(chip->card->dev, + "no playback buffer allocated - aborting measure ac97 clock\n"); return; } ichdev = &chip->ichd[ICHD_PCMOUT]; ichdev->physbuf = subs->dma_buffer.addr; - ichdev->size = chip->ichd[ICHD_PCMOUT].fragsize = INTEL8X0_TESTBUF_SIZE; + ichdev->size = ichdev->fragsize = INTEL8X0_TESTBUF_SIZE; ichdev->substream = NULL; /* don't process interrupts */ /* set rate */ if (snd_ac97_set_rate(chip->ac97[0], AC97_PCM_FRONT_DAC_RATE, 48000) < 0) { - snd_printk(KERN_ERR "cannot set ac97 rate: clock = %d\n", chip->ac97_bus->clock); + dev_err(chip->card->dev, "cannot set ac97 rate: clock = %d\n", + chip->ac97_bus->clock); return; } snd_intel8x0_setup_periods(chip, ichdev); @@ -2621,16 +2813,31 @@ static void __devinit intel8x0_measure_ac97_clock(struct intel8x0 *chip) iputbyte(chip, port + ICH_REG_OFF_CR, ICH_IOCE); iputdword(chip, ICHREG(ALI_DMACR), 1 << ichdev->ali_slot); } - do_gettimeofday(&start_time); + start_time = ktime_get(); spin_unlock_irq(&chip->reg_lock); msleep(50); spin_lock_irq(&chip->reg_lock); /* check the position */ - pos = ichdev->fragsize1; - pos -= igetword(chip, ichdev->reg_offset + ichdev->roff_picb) << ichdev->pos_shift; - pos += ichdev->position; + do { + civ = igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV); + pos1 = igetword(chip, ichdev->reg_offset + ichdev->roff_picb); + if (pos1 == 0) { + udelay(10); + continue; + } + if (civ == igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV) && + pos1 == igetword(chip, ichdev->reg_offset + ichdev->roff_picb)) + break; + } while (timeout--); + if (pos1 == 0) { /* oops, this value is not reliable */ + pos = 0; + } else { + pos = ichdev->fragsize1; + pos -= pos1 << ichdev->pos_shift; + pos += ichdev->position; + } chip->in_measurement = 0; - do_gettimeofday(&stop_time); + stop_time = ktime_get(); /* stop */ if (chip->device_type == DEVICE_ALI) { iputdword(chip, ICHREG(ALI_DMACR), 1 << (ichdev->ali_slot + 16)); @@ -2645,26 +2852,69 @@ static void __devinit intel8x0_measure_ac97_clock(struct intel8x0 *chip) iputbyte(chip, port + ICH_REG_OFF_CR, ICH_RESETREGS); spin_unlock_irq(&chip->reg_lock); - t = stop_time.tv_sec - start_time.tv_sec; - t *= 1000000; - t += stop_time.tv_usec - start_time.tv_usec; - printk(KERN_INFO "%s: measured %lu usecs\n", __FUNCTION__, t); + if (pos == 0) { + dev_err(chip->card->dev, + "measure - unreliable DMA position..\n"); + __retry: + if (attempt < 3) { + msleep(300); + attempt++; + goto __again; + } + goto __end; + } + + pos /= 4; + t = ktime_us_delta(stop_time, start_time); + dev_info(chip->card->dev, + "%s: measured %lu usecs (%lu samples)\n", __func__, t, pos); if (t == 0) { - snd_printk(KERN_ERR "?? calculation error..\n"); - return; + dev_err(chip->card->dev, "?? calculation error..\n"); + goto __retry; } - pos = (pos / 4) * 1000; + pos *= 1000; pos = (pos / t) * 1000 + ((pos % t) * 1000) / t; - if (pos < 40000 || pos >= 60000) + if (pos < 40000 || pos >= 60000) { /* abnormal value. hw problem? */ - printk(KERN_INFO "intel8x0: measured clock %ld rejected\n", pos); + dev_info(chip->card->dev, "measured clock %ld rejected\n", pos); + goto __retry; + } else if (pos > 40500 && pos < 41500) + /* first exception - 41000Hz reference clock */ + chip->ac97_bus->clock = 41000; + else if (pos > 43600 && pos < 44600) + /* second exception - 44100HZ reference clock */ + chip->ac97_bus->clock = 44100; else if (pos < 47500 || pos > 48500) /* not 48000Hz, tuning the clock.. */ chip->ac97_bus->clock = (chip->ac97_bus->clock * 48000) / pos; - printk(KERN_INFO "intel8x0: clocking to %d\n", chip->ac97_bus->clock); + __end: + dev_info(chip->card->dev, "clocking to %d\n", chip->ac97_bus->clock); snd_ac97_update_power(chip->ac97[0], AC97_PCM_FRONT_DAC_RATE, 0); } +static struct snd_pci_quirk intel8x0_clock_list[] = { + SND_PCI_QUIRK(0x0e11, 0x008a, "AD1885", 41000), + SND_PCI_QUIRK(0x1028, 0x00be, "AD1885", 44100), + SND_PCI_QUIRK(0x1028, 0x0177, "AD1980", 48000), + SND_PCI_QUIRK(0x1028, 0x01ad, "AD1981B", 48000), + SND_PCI_QUIRK(0x1043, 0x80f3, "AD1985", 48000), + { } /* terminator */ +}; + +static int intel8x0_in_clock_list(struct intel8x0 *chip) +{ + struct pci_dev *pci = chip->pci; + const struct snd_pci_quirk *wl; + + wl = snd_pci_quirk_lookup(pci, intel8x0_clock_list); + if (!wl) + return 0; + dev_info(chip->card->dev, "white list rate for %04x:%04x is %i\n", + pci->subsystem_vendor, pci->subsystem_device, wl->value); + chip->ac97_bus->clock = wl->value; + return 1; +} + #ifdef CONFIG_PROC_FS static void snd_intel8x0_proc_read(struct snd_info_entry * entry, struct snd_info_buffer *buffer) @@ -2700,7 +2950,7 @@ static void snd_intel8x0_proc_read(struct snd_info_entry * entry, chip->ac97_sdin[2]); } -static void __devinit snd_intel8x0_proc_init(struct intel8x0 * chip) +static void snd_intel8x0_proc_init(struct intel8x0 *chip) { struct snd_info_entry *entry; @@ -2729,10 +2979,49 @@ static unsigned int sis_codec_bits[3] = { ICH_PCR, ICH_SCR, ICH_SIS_TCR }; -static int __devinit snd_intel8x0_create(struct snd_card *card, - struct pci_dev *pci, - unsigned long device_type, - struct intel8x0 ** r_intel8x0) +static int snd_intel8x0_inside_vm(struct pci_dev *pci) +{ + int result = inside_vm; + char *msg = NULL; + + /* check module parameter first (override detection) */ + if (result >= 0) { + msg = result ? "enable (forced) VM" : "disable (forced) VM"; + goto fini; + } + + /* detect KVM and Parallels virtual environments */ + result = kvm_para_available(); +#ifdef X86_FEATURE_HYPERVISOR + result = result || boot_cpu_has(X86_FEATURE_HYPERVISOR); +#endif + if (!result) + goto fini; + + /* check for known (emulated) devices */ + if (pci->subsystem_vendor == 0x1af4 && + pci->subsystem_device == 0x1100) { + /* KVM emulated sound, PCI SSID: 1af4:1100 */ + msg = "enable KVM"; + } else if (pci->subsystem_vendor == 0x1ab8) { + /* Parallels VM emulated sound, PCI SSID: 1ab8:xxxx */ + msg = "enable Parallels VM"; + } else { + msg = "disable (unknown or VT-d) VM"; + result = 0; + } + +fini: + if (msg != NULL) + dev_info(&pci->dev, "%s optimization\n", msg); + + return result; +} + +static int snd_intel8x0_create(struct snd_card *card, + struct pci_dev *pci, + unsigned long device_type, + struct intel8x0 **r_intel8x0) { struct intel8x0 *chip; int err; @@ -2796,6 +3085,8 @@ static int __devinit snd_intel8x0_create(struct snd_card *card, if (xbox) chip->xbox = 1; + chip->inside_vm = snd_intel8x0_inside_vm(pci); + if (pci->vendor == PCI_VENDOR_ID_INTEL && pci->device == PCI_DEVICE_ID_INTEL_440MX) chip->fix_nocache = 1; /* enable workaround */ @@ -2817,7 +3108,7 @@ static int __devinit snd_intel8x0_create(struct snd_card *card, else chip->addr = pci_iomap(pci, 0, 0); if (!chip->addr) { - snd_printk(KERN_ERR "AC'97 space ioremap problem\n"); + dev_err(card->dev, "AC'97 space ioremap problem\n"); snd_intel8x0_free(chip); return -EIO; } @@ -2826,7 +3117,7 @@ static int __devinit snd_intel8x0_create(struct snd_card *card, else chip->bmaddr = pci_iomap(pci, 1, 0); if (!chip->bmaddr) { - snd_printk(KERN_ERR "Controller space ioremap problem\n"); + dev_err(card->dev, "Controller space ioremap problem\n"); snd_intel8x0_free(chip); return -EIO; } @@ -2871,7 +3162,7 @@ static int __devinit snd_intel8x0_create(struct snd_card *card, chip->bdbars_count * sizeof(u32) * ICH_MAX_FRAGS * 2, &chip->bdbars) < 0) { snd_intel8x0_free(chip); - snd_printk(KERN_ERR "intel8x0: cannot allocate buffer descriptors\n"); + dev_err(card->dev, "cannot allocate buffer descriptors\n"); return -ENOMEM; } /* tables must be aligned to 8 bytes here, but the kernel pages @@ -2924,8 +3215,8 @@ static int __devinit snd_intel8x0_create(struct snd_card *card, /* request irq after initializaing int_sta_mask, etc */ if (request_irq(pci->irq, snd_intel8x0_interrupt, - IRQF_SHARED, card->shortname, chip)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); + IRQF_SHARED, KBUILD_MODNAME, chip)) { + dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq); snd_intel8x0_free(chip); return -EBUSY; } @@ -2936,8 +3227,6 @@ static int __devinit snd_intel8x0_create(struct snd_card *card, return err; } - snd_card_set_dev(card, &pci->dev); - *r_intel8x0 = chip; return 0; } @@ -2945,7 +3234,7 @@ static int __devinit snd_intel8x0_create(struct snd_card *card, static struct shortname_table { unsigned int id; const char *s; -} shortnames[] __devinitdata = { +} shortnames[] = { { PCI_DEVICE_ID_INTEL_82801AA_5, "Intel 82801AA-ICH" }, { PCI_DEVICE_ID_INTEL_82801AB_5, "Intel 82901AB-ICH0" }, { PCI_DEVICE_ID_INTEL_82801BA_4, "Intel 82801BA-ICH2" }, @@ -2971,40 +3260,42 @@ static struct shortname_table { { 0, NULL }, }; -static struct snd_pci_quirk spdif_aclink_defaults[] __devinitdata = { +static struct snd_pci_quirk spdif_aclink_defaults[] = { SND_PCI_QUIRK(0x147b, 0x1c1a, "ASUS KN8", 1), { } /* end */ }; /* look up white/black list for SPDIF over ac-link */ -static int __devinit check_default_spdif_aclink(struct pci_dev *pci) +static int check_default_spdif_aclink(struct pci_dev *pci) { const struct snd_pci_quirk *w; w = snd_pci_quirk_lookup(pci, spdif_aclink_defaults); if (w) { if (w->value) - snd_printdd(KERN_INFO "intel8x0: Using SPDIF over " - "AC-Link for %s\n", w->name); + dev_dbg(&pci->dev, + "Using SPDIF over AC-Link for %s\n", + snd_pci_quirk_name(w)); else - snd_printdd(KERN_INFO "intel8x0: Using integrated " - "SPDIF DMA for %s\n", w->name); + dev_dbg(&pci->dev, + "Using integrated SPDIF DMA for %s\n", + snd_pci_quirk_name(w)); return w->value; } return 0; } -static int __devinit snd_intel8x0_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) +static int snd_intel8x0_probe(struct pci_dev *pci, + const struct pci_device_id *pci_id) { struct snd_card *card; struct intel8x0 *chip; int err; struct shortname_table *name; - card = snd_card_new(index, id, THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_new(&pci->dev, index, id, THIS_MODULE, 0, &card); + if (err < 0) + return err; if (spdif_aclink < 0) spdif_aclink = check_default_spdif_aclink(pci); @@ -3060,8 +3351,14 @@ static int __devinit snd_intel8x0_probe(struct pci_dev *pci, "%s with %s at irq %i", card->shortname, snd_ac97_get_short_name(chip->ac97[0]), chip->irq); - if (! ac97_clock) - intel8x0_measure_ac97_clock(chip); + if (ac97_clock == 0 || ac97_clock == 1) { + if (ac97_clock == 0) { + if (intel8x0_in_clock_list(chip) == 0) + intel8x0_measure_ac97_clock(chip); + } else { + intel8x0_measure_ac97_clock(chip); + } + } if ((err = snd_card_register(card)) < 0) { snd_card_free(card); @@ -3071,33 +3368,19 @@ static int __devinit snd_intel8x0_probe(struct pci_dev *pci, return 0; } -static void __devexit snd_intel8x0_remove(struct pci_dev *pci) +static void snd_intel8x0_remove(struct pci_dev *pci) { snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); } -static struct pci_driver driver = { - .name = "Intel ICH", +static struct pci_driver intel8x0_driver = { + .name = KBUILD_MODNAME, .id_table = snd_intel8x0_ids, .probe = snd_intel8x0_probe, - .remove = __devexit_p(snd_intel8x0_remove), -#ifdef CONFIG_PM - .suspend = intel8x0_suspend, - .resume = intel8x0_resume, -#endif + .remove = snd_intel8x0_remove, + .driver = { + .pm = INTEL8X0_PM_OPS, + }, }; - -static int __init alsa_card_intel8x0_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit alsa_card_intel8x0_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_intel8x0_init) -module_exit(alsa_card_intel8x0_exit) +module_pci_driver(intel8x0_driver); |
