diff options
Diffstat (limited to 'sound/pci/intel8x0.c')
| -rw-r--r-- | sound/pci/intel8x0.c | 149 |
1 files changed, 94 insertions, 55 deletions
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 174237f4a22c..ebbf2cf4ca0f 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c | |||
| @@ -178,6 +178,8 @@ DEFINE_REGSET(SP, 0x60); /* SPDIF out */ | |||
| 178 | #define ICH_SAMPLE_CAP 0x00c00000 /* ICH4: sample capability bits (RO) */ | 178 | #define ICH_SAMPLE_CAP 0x00c00000 /* ICH4: sample capability bits (RO) */ |
| 179 | #define ICH_SAMPLE_16_20 0x00400000 /* ICH4: 16- and 20-bit samples */ | 179 | #define ICH_SAMPLE_16_20 0x00400000 /* ICH4: 16- and 20-bit samples */ |
| 180 | #define ICH_MULTICHAN_CAP 0x00300000 /* ICH4: multi-channel capability bits (RO) */ | 180 | #define ICH_MULTICHAN_CAP 0x00300000 /* ICH4: multi-channel capability bits (RO) */ |
| 181 | #define ICH_SIS_TRI 0x00080000 /* SIS: tertiary resume irq */ | ||
| 182 | #define ICH_SIS_TCR 0x00040000 /* SIS: tertiary codec ready */ | ||
| 181 | #define ICH_MD3 0x00020000 /* modem power down semaphore */ | 183 | #define ICH_MD3 0x00020000 /* modem power down semaphore */ |
| 182 | #define ICH_AD3 0x00010000 /* audio power down semaphore */ | 184 | #define ICH_AD3 0x00010000 /* audio power down semaphore */ |
| 183 | #define ICH_RCS 0x00008000 /* read completion status */ | 185 | #define ICH_RCS 0x00008000 /* read completion status */ |
| @@ -398,6 +400,10 @@ struct intel8x0 { | |||
| 398 | struct snd_ac97_bus *ac97_bus; | 400 | struct snd_ac97_bus *ac97_bus; |
| 399 | struct snd_ac97 *ac97[3]; | 401 | struct snd_ac97 *ac97[3]; |
| 400 | unsigned int ac97_sdin[3]; | 402 | unsigned int ac97_sdin[3]; |
| 403 | unsigned int max_codecs, ncodecs; | ||
| 404 | unsigned int *codec_bit; | ||
| 405 | unsigned int codec_isr_bits; | ||
| 406 | unsigned int codec_ready_bits; | ||
| 401 | 407 | ||
| 402 | spinlock_t reg_lock; | 408 | spinlock_t reg_lock; |
| 403 | 409 | ||
| @@ -516,18 +522,6 @@ static void iaputword(struct intel8x0 *chip, u32 offset, u16 val) | |||
| 516 | * access to AC97 codec via normal i/o (for ICH and SIS7012) | 522 | * access to AC97 codec via normal i/o (for ICH and SIS7012) |
| 517 | */ | 523 | */ |
| 518 | 524 | ||
| 519 | /* return the GLOB_STA bit for the corresponding codec */ | ||
| 520 | static unsigned int get_ich_codec_bit(struct intel8x0 *chip, unsigned int codec) | ||
| 521 | { | ||
| 522 | static unsigned int codec_bit[3] = { | ||
| 523 | ICH_PCR, ICH_SCR, ICH_TCR | ||
| 524 | }; | ||
| 525 | snd_assert(codec < 3, return ICH_PCR); | ||
| 526 | if (chip->device_type == DEVICE_INTEL_ICH4) | ||
| 527 | codec = chip->ac97_sdin[codec]; | ||
| 528 | return codec_bit[codec]; | ||
| 529 | } | ||
| 530 | |||
| 531 | static int snd_intel8x0_codec_semaphore(struct intel8x0 *chip, unsigned int codec) | 525 | static int snd_intel8x0_codec_semaphore(struct intel8x0 *chip, unsigned int codec) |
| 532 | { | 526 | { |
| 533 | int time; | 527 | int time; |
| @@ -537,9 +531,9 @@ static int snd_intel8x0_codec_semaphore(struct intel8x0 *chip, unsigned int code | |||
| 537 | if (chip->in_sdin_init) { | 531 | if (chip->in_sdin_init) { |
| 538 | /* we don't know the ready bit assignment at the moment */ | 532 | /* we don't know the ready bit assignment at the moment */ |
| 539 | /* so we check any */ | 533 | /* so we check any */ |
| 540 | codec = ICH_PCR | ICH_SCR | ICH_TCR; | 534 | codec = chip->codec_isr_bits; |
| 541 | } else { | 535 | } else { |
| 542 | codec = get_ich_codec_bit(chip, codec); | 536 | codec = chip->codec_bit[chip->ac97_sdin[codec]]; |
| 543 | } | 537 | } |
| 544 | 538 | ||
| 545 | /* codec ready ? */ | 539 | /* codec ready ? */ |
| @@ -596,7 +590,7 @@ static unsigned short snd_intel8x0_codec_read(struct snd_ac97 *ac97, | |||
| 596 | if ((tmp = igetdword(chip, ICHREG(GLOB_STA))) & ICH_RCS) { | 590 | if ((tmp = igetdword(chip, ICHREG(GLOB_STA))) & ICH_RCS) { |
| 597 | /* reset RCS and preserve other R/WC bits */ | 591 | /* reset RCS and preserve other R/WC bits */ |
| 598 | iputdword(chip, ICHREG(GLOB_STA), tmp & | 592 | iputdword(chip, ICHREG(GLOB_STA), tmp & |
| 599 | ~(ICH_SRI|ICH_PRI|ICH_TRI|ICH_GSCI)); | 593 | ~(chip->codec_ready_bits | ICH_GSCI)); |
| 600 | if (! chip->in_ac97_init) | 594 | if (! chip->in_ac97_init) |
| 601 | snd_printk(KERN_ERR "codec_read %d: read timeout for register 0x%x\n", ac97->num, reg); | 595 | snd_printk(KERN_ERR "codec_read %d: read timeout for register 0x%x\n", ac97->num, reg); |
| 602 | res = 0xffff; | 596 | res = 0xffff; |
| @@ -605,7 +599,8 @@ static unsigned short snd_intel8x0_codec_read(struct snd_ac97 *ac97, | |||
| 605 | return res; | 599 | return res; |
| 606 | } | 600 | } |
| 607 | 601 | ||
| 608 | static void snd_intel8x0_codec_read_test(struct intel8x0 *chip, unsigned int codec) | 602 | static void __devinit snd_intel8x0_codec_read_test(struct intel8x0 *chip, |
| 603 | unsigned int codec) | ||
| 609 | { | 604 | { |
| 610 | unsigned int tmp; | 605 | unsigned int tmp; |
| 611 | 606 | ||
| @@ -614,7 +609,7 @@ static void snd_intel8x0_codec_read_test(struct intel8x0 *chip, unsigned int cod | |||
| 614 | if ((tmp = igetdword(chip, ICHREG(GLOB_STA))) & ICH_RCS) { | 609 | if ((tmp = igetdword(chip, ICHREG(GLOB_STA))) & ICH_RCS) { |
| 615 | /* reset RCS and preserve other R/WC bits */ | 610 | /* reset RCS and preserve other R/WC bits */ |
| 616 | iputdword(chip, ICHREG(GLOB_STA), tmp & | 611 | iputdword(chip, ICHREG(GLOB_STA), tmp & |
| 617 | ~(ICH_SRI|ICH_PRI|ICH_TRI|ICH_GSCI)); | 612 | ~(chip->codec_ready_bits | ICH_GSCI)); |
| 618 | } | 613 | } |
| 619 | } | 614 | } |
| 620 | } | 615 | } |
| @@ -2078,23 +2073,24 @@ static int __devinit snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock, | |||
| 2078 | if (chip->device_type != DEVICE_ALI) { | 2073 | if (chip->device_type != DEVICE_ALI) { |
| 2079 | glob_sta = igetdword(chip, ICHREG(GLOB_STA)); | 2074 | glob_sta = igetdword(chip, ICHREG(GLOB_STA)); |
| 2080 | ops = &standard_bus_ops; | 2075 | ops = &standard_bus_ops; |
| 2081 | if (chip->device_type == DEVICE_INTEL_ICH4) { | 2076 | chip->in_sdin_init = 1; |
| 2082 | codecs = 0; | 2077 | codecs = 0; |
| 2083 | if (glob_sta & ICH_PCR) | 2078 | for (i = 0; i < chip->max_codecs; i++) { |
| 2084 | codecs++; | 2079 | if (! (glob_sta & chip->codec_bit[i])) |
| 2085 | if (glob_sta & ICH_SCR) | 2080 | continue; |
| 2086 | codecs++; | 2081 | if (chip->device_type == DEVICE_INTEL_ICH4) { |
| 2087 | if (glob_sta & ICH_TCR) | 2082 | snd_intel8x0_codec_read_test(chip, codecs); |
| 2088 | codecs++; | 2083 | chip->ac97_sdin[codecs] = |
| 2089 | chip->in_sdin_init = 1; | 2084 | igetbyte(chip, ICHREG(SDM)) & ICH_LDI_MASK; |
| 2090 | for (i = 0; i < codecs; i++) { | 2085 | snd_assert(chip->ac97_sdin[codecs] < 3, |
| 2091 | snd_intel8x0_codec_read_test(chip, i); | 2086 | chip->ac97_sdin[codecs] = 0); |
| 2092 | chip->ac97_sdin[i] = igetbyte(chip, ICHREG(SDM)) & ICH_LDI_MASK; | 2087 | } else |
| 2093 | } | 2088 | chip->ac97_sdin[codecs] = i; |
| 2094 | chip->in_sdin_init = 0; | 2089 | codecs++; |
| 2095 | } else { | ||
| 2096 | codecs = glob_sta & ICH_SCR ? 2 : 1; | ||
| 2097 | } | 2090 | } |
| 2091 | chip->in_sdin_init = 0; | ||
| 2092 | if (! codecs) | ||
| 2093 | codecs = 1; | ||
| 2098 | } else { | 2094 | } else { |
| 2099 | ops = &ali_bus_ops; | 2095 | ops = &ali_bus_ops; |
| 2100 | codecs = 1; | 2096 | codecs = 1; |
| @@ -2120,6 +2116,7 @@ static int __devinit snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock, | |||
| 2120 | else | 2116 | else |
| 2121 | pbus->dra = 1; | 2117 | pbus->dra = 1; |
| 2122 | chip->ac97_bus = pbus; | 2118 | chip->ac97_bus = pbus; |
| 2119 | chip->ncodecs = codecs; | ||
| 2123 | 2120 | ||
| 2124 | ac97.pci = chip->pci; | 2121 | ac97.pci = chip->pci; |
| 2125 | for (i = 0; i < codecs; i++) { | 2122 | for (i = 0; i < codecs; i++) { |
| @@ -2264,7 +2261,7 @@ static int snd_intel8x0_ich_chip_init(struct intel8x0 *chip, int probing) | |||
| 2264 | end_time = jiffies + HZ; | 2261 | end_time = jiffies + HZ; |
| 2265 | do { | 2262 | do { |
| 2266 | status = igetdword(chip, ICHREG(GLOB_STA)) & | 2263 | status = igetdword(chip, ICHREG(GLOB_STA)) & |
| 2267 | (ICH_PCR | ICH_SCR | ICH_TCR); | 2264 | chip->codec_isr_bits; |
| 2268 | if (status) | 2265 | if (status) |
| 2269 | break; | 2266 | break; |
| 2270 | schedule_timeout_uninterruptible(1); | 2267 | schedule_timeout_uninterruptible(1); |
| @@ -2276,32 +2273,27 @@ static int snd_intel8x0_ich_chip_init(struct intel8x0 *chip, int probing) | |||
| 2276 | return -EIO; | 2273 | return -EIO; |
| 2277 | } | 2274 | } |
| 2278 | 2275 | ||
| 2279 | if (chip->device_type == DEVICE_INTEL_ICH4) | ||
| 2280 | /* ICH4 can have three codecs */ | ||
| 2281 | nstatus = ICH_PCR | ICH_SCR | ICH_TCR; | ||
| 2282 | else | ||
| 2283 | /* others up to two codecs */ | ||
| 2284 | nstatus = ICH_PCR | ICH_SCR; | ||
| 2285 | |||
| 2286 | /* wait for other codecs ready status. */ | 2276 | /* wait for other codecs ready status. */ |
| 2287 | end_time = jiffies + HZ / 4; | 2277 | end_time = jiffies + HZ / 4; |
| 2288 | while (status != nstatus && time_after_eq(end_time, jiffies)) { | 2278 | while (status != chip->codec_isr_bits && |
| 2279 | time_after_eq(end_time, jiffies)) { | ||
| 2289 | schedule_timeout_uninterruptible(1); | 2280 | schedule_timeout_uninterruptible(1); |
| 2290 | status |= igetdword(chip, ICHREG(GLOB_STA)) & nstatus; | 2281 | status |= igetdword(chip, ICHREG(GLOB_STA)) & |
| 2282 | chip->codec_isr_bits; | ||
| 2291 | } | 2283 | } |
| 2292 | 2284 | ||
| 2293 | } else { | 2285 | } else { |
| 2294 | /* resume phase */ | 2286 | /* resume phase */ |
| 2295 | int i; | 2287 | int i; |
| 2296 | status = 0; | 2288 | status = 0; |
| 2297 | for (i = 0; i < 3; i++) | 2289 | for (i = 0; i < chip->ncodecs; i++) |
| 2298 | if (chip->ac97[i]) | 2290 | if (chip->ac97[i]) |
| 2299 | status |= get_ich_codec_bit(chip, i); | 2291 | status |= chip->codec_bit[chip->ac97_sdin[i]]; |
| 2300 | /* wait until all the probed codecs are ready */ | 2292 | /* wait until all the probed codecs are ready */ |
| 2301 | end_time = jiffies + HZ; | 2293 | end_time = jiffies + HZ; |
| 2302 | do { | 2294 | do { |
| 2303 | nstatus = igetdword(chip, ICHREG(GLOB_STA)) & | 2295 | nstatus = igetdword(chip, ICHREG(GLOB_STA)) & |
| 2304 | (ICH_PCR | ICH_SCR | ICH_TCR); | 2296 | chip->codec_isr_bits; |
| 2305 | if (status == nstatus) | 2297 | if (status == nstatus) |
| 2306 | break; | 2298 | break; |
| 2307 | schedule_timeout_uninterruptible(1); | 2299 | schedule_timeout_uninterruptible(1); |
| @@ -2359,7 +2351,7 @@ static int snd_intel8x0_ali_chip_init(struct intel8x0 *chip, int probing) | |||
| 2359 | 2351 | ||
| 2360 | static int snd_intel8x0_chip_init(struct intel8x0 *chip, int probing) | 2352 | static int snd_intel8x0_chip_init(struct intel8x0 *chip, int probing) |
| 2361 | { | 2353 | { |
| 2362 | unsigned int i; | 2354 | unsigned int i, timeout; |
| 2363 | int err; | 2355 | int err; |
| 2364 | 2356 | ||
| 2365 | if (chip->device_type != DEVICE_ALI) { | 2357 | if (chip->device_type != DEVICE_ALI) { |
| @@ -2377,6 +2369,15 @@ static int snd_intel8x0_chip_init(struct intel8x0 *chip, int probing) | |||
| 2377 | /* reset channels */ | 2369 | /* reset channels */ |
| 2378 | for (i = 0; i < chip->bdbars_count; i++) | 2370 | for (i = 0; i < chip->bdbars_count; i++) |
| 2379 | iputbyte(chip, ICH_REG_OFF_CR + chip->ichd[i].reg_offset, ICH_RESETREGS); | 2371 | iputbyte(chip, ICH_REG_OFF_CR + chip->ichd[i].reg_offset, ICH_RESETREGS); |
| 2372 | for (i = 0; i < chip->bdbars_count; i++) { | ||
| 2373 | timeout = 100000; | ||
| 2374 | while (--timeout != 0) { | ||
| 2375 | if ((igetbyte(chip, ICH_REG_OFF_CR + chip->ichd[i].reg_offset) & ICH_RESETREGS) == 0) | ||
| 2376 | break; | ||
| 2377 | } | ||
| 2378 | if (timeout == 0) | ||
| 2379 | printk(KERN_ERR "intel8x0: reset of registers failed?\n"); | ||
| 2380 | } | ||
| 2380 | /* initialize Buffer Descriptor Lists */ | 2381 | /* initialize Buffer Descriptor Lists */ |
| 2381 | for (i = 0; i < chip->bdbars_count; i++) | 2382 | for (i = 0; i < chip->bdbars_count; i++) |
| 2382 | iputdword(chip, ICH_REG_OFF_BDBAR + chip->ichd[i].reg_offset, | 2383 | iputdword(chip, ICH_REG_OFF_BDBAR + chip->ichd[i].reg_offset, |
| @@ -2447,7 +2448,7 @@ static int intel8x0_suspend(struct pci_dev *pci, pm_message_t state) | |||
| 2447 | } | 2448 | } |
| 2448 | } | 2449 | } |
| 2449 | } | 2450 | } |
| 2450 | for (i = 0; i < 3; i++) | 2451 | for (i = 0; i < chip->ncodecs; i++) |
| 2451 | snd_ac97_suspend(chip->ac97[i]); | 2452 | snd_ac97_suspend(chip->ac97[i]); |
| 2452 | if (chip->device_type == DEVICE_INTEL_ICH4) | 2453 | if (chip->device_type == DEVICE_INTEL_ICH4) |
| 2453 | chip->sdm_saved = igetbyte(chip, ICHREG(SDM)); | 2454 | chip->sdm_saved = igetbyte(chip, ICHREG(SDM)); |
| @@ -2488,7 +2489,7 @@ static int intel8x0_resume(struct pci_dev *pci) | |||
| 2488 | if (chip->fix_nocache) | 2489 | if (chip->fix_nocache) |
| 2489 | fill_nocache(chip->bdbars.area, chip->bdbars.bytes, 1); | 2490 | fill_nocache(chip->bdbars.area, chip->bdbars.bytes, 1); |
| 2490 | 2491 | ||
| 2491 | for (i = 0; i < 3; i++) | 2492 | for (i = 0; i < chip->ncodecs; i++) |
| 2492 | snd_ac97_resume(chip->ac97[i]); | 2493 | snd_ac97_resume(chip->ac97[i]); |
| 2493 | 2494 | ||
| 2494 | /* refill nocache */ | 2495 | /* refill nocache */ |
| @@ -2619,12 +2620,20 @@ static void snd_intel8x0_proc_read(struct snd_info_entry * entry, | |||
| 2619 | snd_iprintf(buffer, "Global status : 0x%08x\n", tmp); | 2620 | snd_iprintf(buffer, "Global status : 0x%08x\n", tmp); |
| 2620 | if (chip->device_type == DEVICE_INTEL_ICH4) | 2621 | if (chip->device_type == DEVICE_INTEL_ICH4) |
| 2621 | snd_iprintf(buffer, "SDM : 0x%08x\n", igetdword(chip, ICHREG(SDM))); | 2622 | snd_iprintf(buffer, "SDM : 0x%08x\n", igetdword(chip, ICHREG(SDM))); |
| 2622 | snd_iprintf(buffer, "AC'97 codecs ready :%s%s%s%s\n", | 2623 | snd_iprintf(buffer, "AC'97 codecs ready :"); |
| 2623 | tmp & ICH_PCR ? " primary" : "", | 2624 | if (tmp & chip->codec_isr_bits) { |
| 2624 | tmp & ICH_SCR ? " secondary" : "", | 2625 | int i; |
| 2625 | tmp & ICH_TCR ? " tertiary" : "", | 2626 | static const char *codecs[3] = { |
| 2626 | (tmp & (ICH_PCR | ICH_SCR | ICH_TCR)) == 0 ? " none" : ""); | 2627 | "primary", "secondary", "tertiary" |
| 2627 | if (chip->device_type == DEVICE_INTEL_ICH4) | 2628 | }; |
| 2629 | for (i = 0; i < chip->max_codecs; i++) | ||
| 2630 | if (tmp & chip->codec_bit[i]) | ||
| 2631 | snd_iprintf(buffer, " %s", codecs[i]); | ||
| 2632 | } else | ||
| 2633 | snd_iprintf(buffer, " none"); | ||
| 2634 | snd_iprintf(buffer, "\n"); | ||
| 2635 | if (chip->device_type == DEVICE_INTEL_ICH4 || | ||
| 2636 | chip->device_type == DEVICE_SIS) | ||
| 2628 | snd_iprintf(buffer, "AC'97 codecs SDIN : %i %i %i\n", | 2637 | snd_iprintf(buffer, "AC'97 codecs SDIN : %i %i %i\n", |
| 2629 | chip->ac97_sdin[0], | 2638 | chip->ac97_sdin[0], |
| 2630 | chip->ac97_sdin[1], | 2639 | chip->ac97_sdin[1], |
| @@ -2653,6 +2662,13 @@ struct ich_reg_info { | |||
| 2653 | unsigned int offset; | 2662 | unsigned int offset; |
| 2654 | }; | 2663 | }; |
| 2655 | 2664 | ||
| 2665 | static unsigned int ich_codec_bits[3] = { | ||
| 2666 | ICH_PCR, ICH_SCR, ICH_TCR | ||
| 2667 | }; | ||
| 2668 | static unsigned int sis_codec_bits[3] = { | ||
| 2669 | ICH_PCR, ICH_SCR, ICH_SIS_TCR | ||
| 2670 | }; | ||
| 2671 | |||
| 2656 | static int __devinit snd_intel8x0_create(struct snd_card *card, | 2672 | static int __devinit snd_intel8x0_create(struct snd_card *card, |
| 2657 | struct pci_dev *pci, | 2673 | struct pci_dev *pci, |
| 2658 | unsigned long device_type, | 2674 | unsigned long device_type, |
| @@ -2835,6 +2851,29 @@ static int __devinit snd_intel8x0_create(struct snd_card *card, | |||
| 2835 | pci_set_master(pci); | 2851 | pci_set_master(pci); |
| 2836 | synchronize_irq(chip->irq); | 2852 | synchronize_irq(chip->irq); |
| 2837 | 2853 | ||
| 2854 | switch(chip->device_type) { | ||
| 2855 | case DEVICE_INTEL_ICH4: | ||
| 2856 | /* ICH4 can have three codecs */ | ||
| 2857 | chip->max_codecs = 3; | ||
| 2858 | chip->codec_bit = ich_codec_bits; | ||
| 2859 | chip->codec_ready_bits = ICH_PRI | ICH_SRI | ICH_TRI; | ||
| 2860 | break; | ||
| 2861 | case DEVICE_SIS: | ||
| 2862 | /* recent SIS7012 can have three codecs */ | ||
| 2863 | chip->max_codecs = 3; | ||
| 2864 | chip->codec_bit = sis_codec_bits; | ||
| 2865 | chip->codec_ready_bits = ICH_PRI | ICH_SRI | ICH_SIS_TRI; | ||
| 2866 | break; | ||
| 2867 | default: | ||
| 2868 | /* others up to two codecs */ | ||
| 2869 | chip->max_codecs = 2; | ||
| 2870 | chip->codec_bit = ich_codec_bits; | ||
| 2871 | chip->codec_ready_bits = ICH_PRI | ICH_SRI; | ||
| 2872 | break; | ||
| 2873 | } | ||
| 2874 | for (i = 0; i < chip->max_codecs; i++) | ||
| 2875 | chip->codec_isr_bits |= chip->codec_bit[i]; | ||
| 2876 | |||
| 2838 | if ((err = snd_intel8x0_chip_init(chip, 1)) < 0) { | 2877 | if ((err = snd_intel8x0_chip_init(chip, 1)) < 0) { |
| 2839 | snd_intel8x0_free(chip); | 2878 | snd_intel8x0_free(chip); |
| 2840 | return err; | 2879 | return err; |
