X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=sound%2Fpci%2Fintel8x0.c;h=0df7602568e2a8cb73054c1bb7730f0425300d34;hb=a5370553952a9a414860d878b67c49eff11313bd;hp=5466b1fa0cd58d7baaead97bad5d8eac6355447a;hpb=37ef4399a6bb265d3035e6d6e45f7677b132a3ba;p=linux-2.6-omap-h63xx.git diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 5466b1fa0cd..0df7602568e 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -178,6 +178,8 @@ DEFINE_REGSET(SP, 0x60); /* SPDIF out */ #define ICH_SAMPLE_CAP 0x00c00000 /* ICH4: sample capability bits (RO) */ #define ICH_SAMPLE_16_20 0x00400000 /* ICH4: 16- and 20-bit samples */ #define ICH_MULTICHAN_CAP 0x00300000 /* ICH4: multi-channel capability bits (RO) */ +#define ICH_SIS_TRI 0x00080000 /* SIS: tertiary resume irq */ +#define ICH_SIS_TCR 0x00040000 /* SIS: tertiary codec ready */ #define ICH_MD3 0x00020000 /* modem power down semaphore */ #define ICH_AD3 0x00010000 /* audio power down semaphore */ #define ICH_RCS 0x00008000 /* read completion status */ @@ -398,6 +400,10 @@ struct intel8x0 { struct snd_ac97_bus *ac97_bus; struct snd_ac97 *ac97[3]; unsigned int ac97_sdin[3]; + unsigned int max_codecs, ncodecs; + unsigned int *codec_bit; + unsigned int codec_isr_bits; + unsigned int codec_ready_bits; spinlock_t reg_lock; @@ -407,7 +413,7 @@ struct intel8x0 { u32 int_sta_mask; /* interrupt status mask */ }; -static struct pci_device_id snd_intel8x0_ids[] = { +static struct pci_device_id snd_intel8x0_ids[] __devinitdata = { { 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 */ @@ -427,6 +433,7 @@ static struct pci_device_id snd_intel8x0_ids[] = { { 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 */ @@ -515,18 +522,6 @@ static void iaputword(struct intel8x0 *chip, u32 offset, u16 val) * access to AC97 codec via normal i/o (for ICH and SIS7012) */ -/* return the GLOB_STA bit for the corresponding codec */ -static unsigned int get_ich_codec_bit(struct intel8x0 *chip, unsigned int codec) -{ - static unsigned int codec_bit[3] = { - ICH_PCR, ICH_SCR, ICH_TCR - }; - snd_assert(codec < 3, return ICH_PCR); - if (chip->device_type == DEVICE_INTEL_ICH4) - codec = chip->ac97_sdin[codec]; - return codec_bit[codec]; -} - static int snd_intel8x0_codec_semaphore(struct intel8x0 *chip, unsigned int codec) { int time; @@ -536,9 +531,9 @@ static int snd_intel8x0_codec_semaphore(struct intel8x0 *chip, unsigned int code if (chip->in_sdin_init) { /* we don't know the ready bit assignment at the moment */ /* so we check any */ - codec = ICH_PCR | ICH_SCR | ICH_TCR; + codec = chip->codec_isr_bits; } else { - codec = get_ich_codec_bit(chip, codec); + codec = chip->codec_bit[chip->ac97_sdin[codec]]; } /* codec ready ? */ @@ -595,7 +590,7 @@ static unsigned short snd_intel8x0_codec_read(struct snd_ac97 *ac97, if ((tmp = igetdword(chip, ICHREG(GLOB_STA))) & ICH_RCS) { /* reset RCS and preserve other R/WC bits */ iputdword(chip, ICHREG(GLOB_STA), tmp & - ~(ICH_SRI|ICH_PRI|ICH_TRI|ICH_GSCI)); + ~(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); res = 0xffff; @@ -604,7 +599,8 @@ static unsigned short snd_intel8x0_codec_read(struct snd_ac97 *ac97, return res; } -static void snd_intel8x0_codec_read_test(struct intel8x0 *chip, unsigned int codec) +static void __devinit snd_intel8x0_codec_read_test(struct intel8x0 *chip, + unsigned int codec) { unsigned int tmp; @@ -613,7 +609,7 @@ static void snd_intel8x0_codec_read_test(struct intel8x0 *chip, unsigned int cod if ((tmp = igetdword(chip, ICHREG(GLOB_STA))) & ICH_RCS) { /* reset RCS and preserve other R/WC bits */ iputdword(chip, ICHREG(GLOB_STA), tmp & - ~(ICH_SRI|ICH_PRI|ICH_TRI|ICH_GSCI)); + ~(chip->codec_ready_bits | ICH_GSCI)); } } } @@ -1297,6 +1293,7 @@ static int snd_intel8x0_ali_ac97spdifout_close(struct snd_pcm_substream *substre return 0; } +#if 0 // NYI static int snd_intel8x0_ali_spdifin_open(struct snd_pcm_substream *substream) { struct intel8x0 *chip = snd_pcm_substream_chip(substream); @@ -1312,7 +1309,6 @@ static int snd_intel8x0_ali_spdifin_close(struct snd_pcm_substream *substream) return 0; } -#if 0 // NYI static int snd_intel8x0_ali_spdifout_open(struct snd_pcm_substream *substream) { struct intel8x0 *chip = snd_pcm_substream_chip(substream); @@ -1439,6 +1435,7 @@ static struct snd_pcm_ops snd_intel8x0_ali_ac97spdifout_ops = { .pointer = snd_intel8x0_pcm_pointer, }; +#if 0 // NYI static struct snd_pcm_ops snd_intel8x0_ali_spdifin_ops = { .open = snd_intel8x0_ali_spdifin_open, .close = snd_intel8x0_ali_spdifin_close, @@ -1450,7 +1447,6 @@ static struct snd_pcm_ops snd_intel8x0_ali_spdifin_ops = { .pointer = snd_intel8x0_pcm_pointer, }; -#if 0 // NYI static struct snd_pcm_ops snd_intel8x0_ali_spdifout_ops = { .open = snd_intel8x0_ali_spdifout_open, .close = snd_intel8x0_ali_spdifout_close, @@ -1586,7 +1582,7 @@ static struct ich_pcm_table ali_pcms[] __devinitdata = { { .suffix = "IEC958", .playback_ops = &snd_intel8x0_ali_ac97spdifout_ops, - .capture_ops = &snd_intel8x0_ali_spdifin_ops, + /* .capture_ops = &snd_intel8x0_ali_spdifin_ops, */ .prealloc_size = 64 * 1024, .prealloc_max_size = 128 * 1024, .ac97_idx = ALID_AC97SPDIFOUT, @@ -1803,6 +1799,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { .name = "Dell", /* which model? AD1981B*/ .type = AC97_TUNE_HP_ONLY }, + { + .subvendor = 0x1028, + .subdevice = 0x0151, + .name = "Dell Optiplex GX270", /* AD1981B */ + .type = AC97_TUNE_HP_ONLY + }, { .subvendor = 0x1028, .subdevice = 0x0163, @@ -1845,12 +1847,6 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { .name = "HP nx8220", .type = AC97_TUNE_MUTE_LED }, - { - .subvendor = 0x103c, - .subdevice = 0x099c, - .name = "HP nx6110", /* AD1981B */ - .type = AC97_TUNE_HP_ONLY - }, { .subvendor = 0x103c, .subdevice = 0x129d, @@ -1866,7 +1862,7 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { { .subvendor = 0x103c, .subdevice = 0x099c, - .name = "HP nc6120", + .name = "HP nx6110/nc6120", .type = AC97_TUNE_HP_MUTE_LED }, { @@ -2077,23 +2073,24 @@ static int __devinit snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock, if (chip->device_type != DEVICE_ALI) { glob_sta = igetdword(chip, ICHREG(GLOB_STA)); ops = &standard_bus_ops; - if (chip->device_type == DEVICE_INTEL_ICH4) { - codecs = 0; - if (glob_sta & ICH_PCR) - codecs++; - if (glob_sta & ICH_SCR) - codecs++; - if (glob_sta & ICH_TCR) - codecs++; - chip->in_sdin_init = 1; - for (i = 0; i < codecs; i++) { - snd_intel8x0_codec_read_test(chip, i); - chip->ac97_sdin[i] = igetbyte(chip, ICHREG(SDM)) & ICH_LDI_MASK; - } - chip->in_sdin_init = 0; - } else { - codecs = glob_sta & ICH_SCR ? 2 : 1; + chip->in_sdin_init = 1; + codecs = 0; + for (i = 0; i < chip->max_codecs; i++) { + if (! (glob_sta & chip->codec_bit[i])) + continue; + if (chip->device_type == DEVICE_INTEL_ICH4) { + 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); + } else + chip->ac97_sdin[codecs] = i; + codecs++; } + chip->in_sdin_init = 0; + if (! codecs) + codecs = 1; } else { ops = &ali_bus_ops; codecs = 1; @@ -2119,6 +2116,7 @@ static int __devinit snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock, else pbus->dra = 1; chip->ac97_bus = pbus; + chip->ncodecs = codecs; ac97.pci = chip->pci; for (i = 0; i < codecs; i++) { @@ -2263,7 +2261,7 @@ static int snd_intel8x0_ich_chip_init(struct intel8x0 *chip, int probing) end_time = jiffies + HZ; do { status = igetdword(chip, ICHREG(GLOB_STA)) & - (ICH_PCR | ICH_SCR | ICH_TCR); + chip->codec_isr_bits; if (status) break; schedule_timeout_uninterruptible(1); @@ -2275,32 +2273,27 @@ static int snd_intel8x0_ich_chip_init(struct intel8x0 *chip, int probing) return -EIO; } - if (chip->device_type == DEVICE_INTEL_ICH4) - /* ICH4 can have three codecs */ - nstatus = ICH_PCR | ICH_SCR | ICH_TCR; - else - /* others up to two codecs */ - nstatus = ICH_PCR | ICH_SCR; - /* wait for other codecs ready status. */ end_time = jiffies + HZ / 4; - while (status != nstatus && time_after_eq(end_time, jiffies)) { + while (status != chip->codec_isr_bits && + time_after_eq(end_time, jiffies)) { schedule_timeout_uninterruptible(1); - status |= igetdword(chip, ICHREG(GLOB_STA)) & nstatus; + status |= igetdword(chip, ICHREG(GLOB_STA)) & + chip->codec_isr_bits; } } else { /* resume phase */ int i; status = 0; - for (i = 0; i < 3; i++) + for (i = 0; i < chip->ncodecs; i++) if (chip->ac97[i]) - status |= get_ich_codec_bit(chip, i); + status |= chip->codec_bit[chip->ac97_sdin[i]]; /* wait until all the probed codecs are ready */ end_time = jiffies + HZ; do { nstatus = igetdword(chip, ICHREG(GLOB_STA)) & - (ICH_PCR | ICH_SCR | ICH_TCR); + chip->codec_isr_bits; if (status == nstatus) break; schedule_timeout_uninterruptible(1); @@ -2358,7 +2351,7 @@ static int snd_intel8x0_ali_chip_init(struct intel8x0 *chip, int probing) static int snd_intel8x0_chip_init(struct intel8x0 *chip, int probing) { - unsigned int i; + unsigned int i, timeout; int err; if (chip->device_type != DEVICE_ALI) { @@ -2376,6 +2369,15 @@ static int snd_intel8x0_chip_init(struct intel8x0 *chip, int probing) /* reset channels */ for (i = 0; i < chip->bdbars_count; i++) iputbyte(chip, ICH_REG_OFF_CR + chip->ichd[i].reg_offset, ICH_RESETREGS); + for (i = 0; i < chip->bdbars_count; i++) { + timeout = 100000; + while (--timeout != 0) { + if ((igetbyte(chip, ICH_REG_OFF_CR + chip->ichd[i].reg_offset) & ICH_RESETREGS) == 0) + break; + } + if (timeout == 0) + printk(KERN_ERR "intel8x0: reset of registers failed?\n"); + } /* initialize Buffer Descriptor Lists */ for (i = 0; i < chip->bdbars_count; i++) iputdword(chip, ICH_REG_OFF_BDBAR + chip->ichd[i].reg_offset, @@ -2446,7 +2448,7 @@ static int intel8x0_suspend(struct pci_dev *pci, pm_message_t state) } } } - for (i = 0; i < 3; i++) + for (i = 0; i < chip->ncodecs; i++) snd_ac97_suspend(chip->ac97[i]); if (chip->device_type == DEVICE_INTEL_ICH4) chip->sdm_saved = igetbyte(chip, ICHREG(SDM)); @@ -2487,7 +2489,7 @@ static int intel8x0_resume(struct pci_dev *pci) if (chip->fix_nocache) fill_nocache(chip->bdbars.area, chip->bdbars.bytes, 1); - for (i = 0; i < 3; i++) + for (i = 0; i < chip->ncodecs; i++) snd_ac97_resume(chip->ac97[i]); /* refill nocache */ @@ -2618,12 +2620,20 @@ static void snd_intel8x0_proc_read(struct snd_info_entry * entry, snd_iprintf(buffer, "Global status : 0x%08x\n", tmp); if (chip->device_type == DEVICE_INTEL_ICH4) snd_iprintf(buffer, "SDM : 0x%08x\n", igetdword(chip, ICHREG(SDM))); - snd_iprintf(buffer, "AC'97 codecs ready :%s%s%s%s\n", - tmp & ICH_PCR ? " primary" : "", - tmp & ICH_SCR ? " secondary" : "", - tmp & ICH_TCR ? " tertiary" : "", - (tmp & (ICH_PCR | ICH_SCR | ICH_TCR)) == 0 ? " none" : ""); - if (chip->device_type == DEVICE_INTEL_ICH4) + snd_iprintf(buffer, "AC'97 codecs ready :"); + if (tmp & chip->codec_isr_bits) { + int i; + static const char *codecs[3] = { + "primary", "secondary", "tertiary" + }; + for (i = 0; i < chip->max_codecs; i++) + if (tmp & chip->codec_bit[i]) + snd_iprintf(buffer, " %s", codecs[i]); + } else + snd_iprintf(buffer, " none"); + snd_iprintf(buffer, "\n"); + if (chip->device_type == DEVICE_INTEL_ICH4 || + chip->device_type == DEVICE_SIS) snd_iprintf(buffer, "AC'97 codecs SDIN : %i %i %i\n", chip->ac97_sdin[0], chip->ac97_sdin[1], @@ -2652,6 +2662,13 @@ struct ich_reg_info { unsigned int offset; }; +static unsigned int ich_codec_bits[3] = { + ICH_PCR, ICH_SCR, ICH_TCR +}; +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, @@ -2834,6 +2851,29 @@ static int __devinit snd_intel8x0_create(struct snd_card *card, pci_set_master(pci); synchronize_irq(chip->irq); + switch(chip->device_type) { + case DEVICE_INTEL_ICH4: + /* ICH4 can have three codecs */ + chip->max_codecs = 3; + chip->codec_bit = ich_codec_bits; + chip->codec_ready_bits = ICH_PRI | ICH_SRI | ICH_TRI; + break; + case DEVICE_SIS: + /* recent SIS7012 can have three codecs */ + chip->max_codecs = 3; + chip->codec_bit = sis_codec_bits; + chip->codec_ready_bits = ICH_PRI | ICH_SRI | ICH_SIS_TRI; + break; + default: + /* others up to two codecs */ + chip->max_codecs = 2; + chip->codec_bit = ich_codec_bits; + chip->codec_ready_bits = ICH_PRI | ICH_SRI; + break; + } + for (i = 0; i < chip->max_codecs; i++) + chip->codec_isr_bits |= chip->codec_bit[i]; + if ((err = snd_intel8x0_chip_init(chip, 1)) < 0) { snd_intel8x0_free(chip); return err;