diff options
author | Takashi Iwai <tiwai@suse.de> | 2006-01-12 05:47:32 -0500 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2006-03-22 04:22:46 -0500 |
commit | 84a43bd523a63f1b53fd734c3798d71b7b53f123 (patch) | |
tree | 63a47c220f57b802fe58b9d70e49835c9f15af40 | |
parent | 15f500a6994e552b7772d8b8459ee3114c47897d (diff) |
[ALSA] intel8x0 - Fix/cleanup detection of codecs on SIS7012
Modules: Intel8x0 driver
Fix the detection of tertriary codec on SIS7012, including clean-ups
of relevant codes.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r-- | sound/pci/intel8x0.c | 138 |
1 files changed, 84 insertions, 54 deletions
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 174237f4a22c..da024ffe96c2 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); |
@@ -2447,7 +2439,7 @@ static int intel8x0_suspend(struct pci_dev *pci, pm_message_t state) | |||
2447 | } | 2439 | } |
2448 | } | 2440 | } |
2449 | } | 2441 | } |
2450 | for (i = 0; i < 3; i++) | 2442 | for (i = 0; i < chip->ncodecs; i++) |
2451 | snd_ac97_suspend(chip->ac97[i]); | 2443 | snd_ac97_suspend(chip->ac97[i]); |
2452 | if (chip->device_type == DEVICE_INTEL_ICH4) | 2444 | if (chip->device_type == DEVICE_INTEL_ICH4) |
2453 | chip->sdm_saved = igetbyte(chip, ICHREG(SDM)); | 2445 | chip->sdm_saved = igetbyte(chip, ICHREG(SDM)); |
@@ -2488,7 +2480,7 @@ static int intel8x0_resume(struct pci_dev *pci) | |||
2488 | if (chip->fix_nocache) | 2480 | if (chip->fix_nocache) |
2489 | fill_nocache(chip->bdbars.area, chip->bdbars.bytes, 1); | 2481 | fill_nocache(chip->bdbars.area, chip->bdbars.bytes, 1); |
2490 | 2482 | ||
2491 | for (i = 0; i < 3; i++) | 2483 | for (i = 0; i < chip->ncodecs; i++) |
2492 | snd_ac97_resume(chip->ac97[i]); | 2484 | snd_ac97_resume(chip->ac97[i]); |
2493 | 2485 | ||
2494 | /* refill nocache */ | 2486 | /* refill nocache */ |
@@ -2619,12 +2611,20 @@ static void snd_intel8x0_proc_read(struct snd_info_entry * entry, | |||
2619 | snd_iprintf(buffer, "Global status : 0x%08x\n", tmp); | 2611 | snd_iprintf(buffer, "Global status : 0x%08x\n", tmp); |
2620 | if (chip->device_type == DEVICE_INTEL_ICH4) | 2612 | if (chip->device_type == DEVICE_INTEL_ICH4) |
2621 | snd_iprintf(buffer, "SDM : 0x%08x\n", igetdword(chip, ICHREG(SDM))); | 2613 | snd_iprintf(buffer, "SDM : 0x%08x\n", igetdword(chip, ICHREG(SDM))); |
2622 | snd_iprintf(buffer, "AC'97 codecs ready :%s%s%s%s\n", | 2614 | snd_iprintf(buffer, "AC'97 codecs ready :"); |
2623 | tmp & ICH_PCR ? " primary" : "", | 2615 | if (tmp & chip->codec_isr_bits) { |
2624 | tmp & ICH_SCR ? " secondary" : "", | 2616 | int i; |
2625 | tmp & ICH_TCR ? " tertiary" : "", | 2617 | static const char *codecs[3] = { |
2626 | (tmp & (ICH_PCR | ICH_SCR | ICH_TCR)) == 0 ? " none" : ""); | 2618 | "primary", "secondary", "tertiary" |
2627 | if (chip->device_type == DEVICE_INTEL_ICH4) | 2619 | }; |
2620 | for (i = 0; i < chip->max_codecs; i++) | ||
2621 | if (tmp & chip->codec_bit[i]) | ||
2622 | snd_iprintf(buffer, " %s", codecs[i]); | ||
2623 | } else | ||
2624 | snd_iprintf(buffer, " none"); | ||
2625 | snd_iprintf(buffer, "\n"); | ||
2626 | if (chip->device_type == DEVICE_INTEL_ICH4 || | ||
2627 | chip->device_type == DEVICE_SIS) | ||
2628 | snd_iprintf(buffer, "AC'97 codecs SDIN : %i %i %i\n", | 2628 | snd_iprintf(buffer, "AC'97 codecs SDIN : %i %i %i\n", |
2629 | chip->ac97_sdin[0], | 2629 | chip->ac97_sdin[0], |
2630 | chip->ac97_sdin[1], | 2630 | chip->ac97_sdin[1], |
@@ -2653,6 +2653,13 @@ struct ich_reg_info { | |||
2653 | unsigned int offset; | 2653 | unsigned int offset; |
2654 | }; | 2654 | }; |
2655 | 2655 | ||
2656 | static unsigned int ich_codec_bits[3] = { | ||
2657 | ICH_PCR, ICH_SCR, ICH_TCR | ||
2658 | }; | ||
2659 | static unsigned int sis_codec_bits[3] = { | ||
2660 | ICH_PCR, ICH_SCR, ICH_SIS_TCR | ||
2661 | }; | ||
2662 | |||
2656 | static int __devinit snd_intel8x0_create(struct snd_card *card, | 2663 | static int __devinit snd_intel8x0_create(struct snd_card *card, |
2657 | struct pci_dev *pci, | 2664 | struct pci_dev *pci, |
2658 | unsigned long device_type, | 2665 | unsigned long device_type, |
@@ -2835,6 +2842,29 @@ static int __devinit snd_intel8x0_create(struct snd_card *card, | |||
2835 | pci_set_master(pci); | 2842 | pci_set_master(pci); |
2836 | synchronize_irq(chip->irq); | 2843 | synchronize_irq(chip->irq); |
2837 | 2844 | ||
2845 | switch(chip->device_type) { | ||
2846 | case DEVICE_INTEL_ICH4: | ||
2847 | /* ICH4 can have three codecs */ | ||
2848 | chip->max_codecs = 3; | ||
2849 | chip->codec_bit = ich_codec_bits; | ||
2850 | chip->codec_ready_bits = ICH_PRI | ICH_SRI | ICH_TRI; | ||
2851 | break; | ||
2852 | case DEVICE_SIS: | ||
2853 | /* recent SIS7012 can have three codecs */ | ||
2854 | chip->max_codecs = 3; | ||
2855 | chip->codec_bit = sis_codec_bits; | ||
2856 | chip->codec_ready_bits = ICH_PRI | ICH_SRI | ICH_SIS_TRI; | ||
2857 | break; | ||
2858 | default: | ||
2859 | /* others up to two codecs */ | ||
2860 | chip->max_codecs = 2; | ||
2861 | chip->codec_bit = ich_codec_bits; | ||
2862 | chip->codec_ready_bits = ICH_PRI | ICH_SRI; | ||
2863 | break; | ||
2864 | } | ||
2865 | for (i = 0; i < chip->max_codecs; i++) | ||
2866 | chip->codec_isr_bits |= chip->codec_bit[i]; | ||
2867 | |||
2838 | if ((err = snd_intel8x0_chip_init(chip, 1)) < 0) { | 2868 | if ((err = snd_intel8x0_chip_init(chip, 1)) < 0) { |
2839 | snd_intel8x0_free(chip); | 2869 | snd_intel8x0_free(chip); |
2840 | return err; | 2870 | return err; |