diff options
Diffstat (limited to 'sound/pci/intel8x0.c')
-rw-r--r-- | sound/pci/intel8x0.c | 85 |
1 files changed, 62 insertions, 23 deletions
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index e900cdc84849..57648810eaf1 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c | |||
@@ -689,7 +689,7 @@ static void snd_intel8x0_setup_periods(struct intel8x0 *chip, struct ichdev *ich | |||
689 | bdbar[idx + 1] = cpu_to_le32(0x80000000 | /* interrupt on completion */ | 689 | bdbar[idx + 1] = cpu_to_le32(0x80000000 | /* interrupt on completion */ |
690 | ichdev->fragsize >> ichdev->pos_shift); | 690 | ichdev->fragsize >> ichdev->pos_shift); |
691 | #if 0 | 691 | #if 0 |
692 | printk("bdbar[%i] = 0x%x [0x%x]\n", | 692 | printk(KERN_DEBUG "bdbar[%i] = 0x%x [0x%x]\n", |
693 | idx + 0, bdbar[idx + 0], bdbar[idx + 1]); | 693 | idx + 0, bdbar[idx + 0], bdbar[idx + 1]); |
694 | #endif | 694 | #endif |
695 | } | 695 | } |
@@ -701,8 +701,10 @@ static void snd_intel8x0_setup_periods(struct intel8x0 *chip, struct ichdev *ich | |||
701 | ichdev->lvi_frag = ICH_REG_LVI_MASK % ichdev->frags; | 701 | ichdev->lvi_frag = ICH_REG_LVI_MASK % ichdev->frags; |
702 | ichdev->position = 0; | 702 | ichdev->position = 0; |
703 | #if 0 | 703 | #if 0 |
704 | printk("lvi_frag = %i, frags = %i, period_size = 0x%x, period_size1 = 0x%x\n", | 704 | printk(KERN_DEBUG "lvi_frag = %i, frags = %i, period_size = 0x%x, " |
705 | ichdev->lvi_frag, ichdev->frags, ichdev->fragsize, ichdev->fragsize1); | 705 | "period_size1 = 0x%x\n", |
706 | ichdev->lvi_frag, ichdev->frags, ichdev->fragsize, | ||
707 | ichdev->fragsize1); | ||
706 | #endif | 708 | #endif |
707 | /* clear interrupts */ | 709 | /* clear interrupts */ |
708 | iputbyte(chip, port + ichdev->roff_sr, ICH_FIFOE | ICH_BCIS | ICH_LVBCI); | 710 | iputbyte(chip, port + ichdev->roff_sr, ICH_FIFOE | ICH_BCIS | ICH_LVBCI); |
@@ -768,7 +770,8 @@ static inline void snd_intel8x0_update(struct intel8x0 *chip, struct ichdev *ich | |||
768 | ichdev->lvi_frag %= ichdev->frags; | 770 | ichdev->lvi_frag %= ichdev->frags; |
769 | ichdev->bdbar[ichdev->lvi * 2] = cpu_to_le32(ichdev->physbuf + ichdev->lvi_frag * ichdev->fragsize1); | 771 | ichdev->bdbar[ichdev->lvi * 2] = cpu_to_le32(ichdev->physbuf + ichdev->lvi_frag * ichdev->fragsize1); |
770 | #if 0 | 772 | #if 0 |
771 | printk("new: bdbar[%i] = 0x%x [0x%x], prefetch = %i, all = 0x%x, 0x%x\n", | 773 | printk(KERN_DEBUG "new: bdbar[%i] = 0x%x [0x%x], prefetch = %i, " |
774 | "all = 0x%x, 0x%x\n", | ||
772 | ichdev->lvi * 2, ichdev->bdbar[ichdev->lvi * 2], | 775 | ichdev->lvi * 2, ichdev->bdbar[ichdev->lvi * 2], |
773 | ichdev->bdbar[ichdev->lvi * 2 + 1], inb(ICH_REG_OFF_PIV + port), | 776 | ichdev->bdbar[ichdev->lvi * 2 + 1], inb(ICH_REG_OFF_PIV + port), |
774 | inl(port + 4), inb(port + ICH_REG_OFF_CR)); | 777 | inl(port + 4), inb(port + ICH_REG_OFF_CR)); |
@@ -2287,23 +2290,23 @@ static void do_ali_reset(struct intel8x0 *chip) | |||
2287 | iputdword(chip, ICHREG(ALI_INTERRUPTSR), 0x00000000); | 2290 | iputdword(chip, ICHREG(ALI_INTERRUPTSR), 0x00000000); |
2288 | } | 2291 | } |
2289 | 2292 | ||
2290 | static int snd_intel8x0_ich_chip_init(struct intel8x0 *chip, int probing) | 2293 | #ifdef CONFIG_SND_AC97_POWER_SAVE |
2291 | { | 2294 | static struct snd_pci_quirk ich_chip_reset_mode[] = { |
2292 | unsigned long end_time; | 2295 | SND_PCI_QUIRK(0x1014, 0x051f, "Thinkpad R32", 1), |
2293 | unsigned int cnt, status, nstatus; | 2296 | { } /* end */ |
2294 | 2297 | }; | |
2295 | /* put logic to right state */ | ||
2296 | /* first clear status bits */ | ||
2297 | status = ICH_RCS | ICH_MCINT | ICH_POINT | ICH_PIINT; | ||
2298 | if (chip->device_type == DEVICE_NFORCE) | ||
2299 | status |= ICH_NVSPINT; | ||
2300 | cnt = igetdword(chip, ICHREG(GLOB_STA)); | ||
2301 | iputdword(chip, ICHREG(GLOB_STA), cnt & status); | ||
2302 | 2298 | ||
2299 | static int snd_intel8x0_ich_chip_cold_reset(struct intel8x0 *chip) | ||
2300 | { | ||
2301 | unsigned int cnt; | ||
2303 | /* ACLink on, 2 channels */ | 2302 | /* ACLink on, 2 channels */ |
2303 | |||
2304 | if (snd_pci_quirk_lookup(chip->pci, ich_chip_reset_mode)) | ||
2305 | return -EIO; | ||
2306 | |||
2304 | cnt = igetdword(chip, ICHREG(GLOB_CNT)); | 2307 | cnt = igetdword(chip, ICHREG(GLOB_CNT)); |
2305 | cnt &= ~(ICH_ACLINK | ICH_PCM_246_MASK); | 2308 | cnt &= ~(ICH_ACLINK | ICH_PCM_246_MASK); |
2306 | #ifdef CONFIG_SND_AC97_POWER_SAVE | 2309 | |
2307 | /* do cold reset - the full ac97 powerdown may leave the controller | 2310 | /* do cold reset - the full ac97 powerdown may leave the controller |
2308 | * in a warm state but actually it cannot communicate with the codec. | 2311 | * in a warm state but actually it cannot communicate with the codec. |
2309 | */ | 2312 | */ |
@@ -2312,22 +2315,58 @@ static int snd_intel8x0_ich_chip_init(struct intel8x0 *chip, int probing) | |||
2312 | udelay(10); | 2315 | udelay(10); |
2313 | iputdword(chip, ICHREG(GLOB_CNT), cnt | ICH_AC97COLD); | 2316 | iputdword(chip, ICHREG(GLOB_CNT), cnt | ICH_AC97COLD); |
2314 | msleep(1); | 2317 | msleep(1); |
2318 | return 0; | ||
2319 | } | ||
2320 | #define snd_intel8x0_ich_chip_can_cold_reset(chip) \ | ||
2321 | (!snd_pci_quirk_lookup(chip->pci, ich_chip_reset_mode)) | ||
2315 | #else | 2322 | #else |
2323 | #define snd_intel8x0_ich_chip_cold_reset(chip) 0 | ||
2324 | #define snd_intel8x0_ich_chip_can_cold_reset(chip) (0) | ||
2325 | #endif | ||
2326 | |||
2327 | static int snd_intel8x0_ich_chip_reset(struct intel8x0 *chip) | ||
2328 | { | ||
2329 | unsigned long end_time; | ||
2330 | unsigned int cnt; | ||
2331 | /* ACLink on, 2 channels */ | ||
2332 | cnt = igetdword(chip, ICHREG(GLOB_CNT)); | ||
2333 | cnt &= ~(ICH_ACLINK | ICH_PCM_246_MASK); | ||
2316 | /* finish cold or do warm reset */ | 2334 | /* finish cold or do warm reset */ |
2317 | cnt |= (cnt & ICH_AC97COLD) == 0 ? ICH_AC97COLD : ICH_AC97WARM; | 2335 | cnt |= (cnt & ICH_AC97COLD) == 0 ? ICH_AC97COLD : ICH_AC97WARM; |
2318 | iputdword(chip, ICHREG(GLOB_CNT), cnt); | 2336 | iputdword(chip, ICHREG(GLOB_CNT), cnt); |
2319 | end_time = (jiffies + (HZ / 4)) + 1; | 2337 | end_time = (jiffies + (HZ / 4)) + 1; |
2320 | do { | 2338 | do { |
2321 | if ((igetdword(chip, ICHREG(GLOB_CNT)) & ICH_AC97WARM) == 0) | 2339 | if ((igetdword(chip, ICHREG(GLOB_CNT)) & ICH_AC97WARM) == 0) |
2322 | goto __ok; | 2340 | return 0; |
2323 | schedule_timeout_uninterruptible(1); | 2341 | schedule_timeout_uninterruptible(1); |
2324 | } while (time_after_eq(end_time, jiffies)); | 2342 | } while (time_after_eq(end_time, jiffies)); |
2325 | snd_printk(KERN_ERR "AC'97 warm reset still in progress? [0x%x]\n", | 2343 | snd_printk(KERN_ERR "AC'97 warm reset still in progress? [0x%x]\n", |
2326 | igetdword(chip, ICHREG(GLOB_CNT))); | 2344 | igetdword(chip, ICHREG(GLOB_CNT))); |
2327 | return -EIO; | 2345 | return -EIO; |
2346 | } | ||
2347 | |||
2348 | static int snd_intel8x0_ich_chip_init(struct intel8x0 *chip, int probing) | ||
2349 | { | ||
2350 | unsigned long end_time; | ||
2351 | unsigned int status, nstatus; | ||
2352 | unsigned int cnt; | ||
2353 | int err; | ||
2354 | |||
2355 | /* put logic to right state */ | ||
2356 | /* first clear status bits */ | ||
2357 | status = ICH_RCS | ICH_MCINT | ICH_POINT | ICH_PIINT; | ||
2358 | if (chip->device_type == DEVICE_NFORCE) | ||
2359 | status |= ICH_NVSPINT; | ||
2360 | cnt = igetdword(chip, ICHREG(GLOB_STA)); | ||
2361 | iputdword(chip, ICHREG(GLOB_STA), cnt & status); | ||
2362 | |||
2363 | if (snd_intel8x0_ich_chip_can_cold_reset(chip)) | ||
2364 | err = snd_intel8x0_ich_chip_cold_reset(chip); | ||
2365 | else | ||
2366 | err = snd_intel8x0_ich_chip_reset(chip); | ||
2367 | if (err < 0) | ||
2368 | return err; | ||
2328 | 2369 | ||
2329 | __ok: | ||
2330 | #endif | ||
2331 | if (probing) { | 2370 | if (probing) { |
2332 | /* wait for any codec ready status. | 2371 | /* wait for any codec ready status. |
2333 | * Once it becomes ready it should remain ready | 2372 | * Once it becomes ready it should remain ready |
@@ -3058,9 +3097,9 @@ static int __devinit snd_intel8x0_probe(struct pci_dev *pci, | |||
3058 | int err; | 3097 | int err; |
3059 | struct shortname_table *name; | 3098 | struct shortname_table *name; |
3060 | 3099 | ||
3061 | card = snd_card_new(index, id, THIS_MODULE, 0); | 3100 | err = snd_card_create(index, id, THIS_MODULE, 0, &card); |
3062 | if (card == NULL) | 3101 | if (err < 0) |
3063 | return -ENOMEM; | 3102 | return err; |
3064 | 3103 | ||
3065 | if (spdif_aclink < 0) | 3104 | if (spdif_aclink < 0) |
3066 | spdif_aclink = check_default_spdif_aclink(pci); | 3105 | spdif_aclink = check_default_spdif_aclink(pci); |