[PATCH 2.4.20-pre2-ac4] i810_audio.c

From: Juergen Sawinski (juergen.sawinski@mpimf-heidelberg.mpg.de)
Date: Mon Aug 19 2002 - 06:57:36 EST


Changes:
-The change on NR_AC97 from 2 to 4 could cause problems with fully
 equipped ICH3 hardware: The i810_ac97_init routine will leave the
 iospace
 -> implemented some kind of "capability structure" that holds
    the maximum number of codecs
-the fact, that the codec ID and the IO range do not match on ICH4
 is now auto-detected (see comments about ICH 4 caveats inside the
 patch)
 -> option d845gbv_bug is removed
-minor cleanups

-- 
Juergen "George" Sawinski
Max-Planck Institute for Medical Research
Dept. of Biomedical Optics
Jahnstr. 29
D-69120 Heidelberg
Germany

Phone: +49-6221-486-308 Fax: +49-6221-486-325

priv. Phone: +49-6221-418 858 Mobile: +49-171-532 5302

--- linux-2.4.20-pre2-ac4/drivers/sound/i810_audio.c Mon Aug 19 12:09:45 2002 +++ jsaw/drivers/sound/i810_audio.c Mon Aug 19 13:54:22 2002 @@ -65,6 +65,17 @@ * If you need to force a specific rate set the clocking= option * * This driver is cursed. (Ben LaHaise) + * + * + * ICH 4 caveats + * + * The ICH4 has the feature, that the codec ID may not be congruent + * with the AC-link channel. + * + * Right now, the codec ID is not the real codec ID but the AC-link + * channel. A ID <-> AC-link mapping has still to be implemented. + * + * Juergen "George" Sawinski (jsaw) */ #include <linux/module.h> @@ -121,7 +132,6 @@ static int strict_clocking=0; static unsigned int clocking=0; static int spdif_locked=0; -static int d845gbv_bug=0; //#define DEBUG //#define DEBUG2 @@ -269,6 +279,25 @@ "AMD-8111 IOHub" }; +/* These are capabilities (and bugs) the chipsets _can_ have */ +static struct { + int16_t nr_ac97; +#define CAP_MMIO 0x0001 +#define CAP_20BIT_AUDIO_SUPPORT 0x0002 + u_int16_t flags; +} card_cap[] = { + { 1, 0x0000 }, /* ICH82801AA */ + { 1, 0x0000 }, /* ICH82901AB */ + { 1, 0x0000 }, /* INTEL440MX */ + { 1, 0x0000 }, /* INTELICH2 */ + { 2, 0x0000 }, /* INTELICH3 */ + { 3, 0x0003 }, /* INTELICH4 */ + /*@FIXME to be verified*/ { 2, 0x0000 }, /* SI7012 */ + /*@FIXME to be verified*/ { 2, 0x0000 }, /* NVIDIA_NFORCE */ + /*@FIXME to be verified*/ { 2, 0x0000 }, /* AMD768 */ + /*@FIXME to be verified*/ { 2, 0x0000 }, /* AMD8111 */ +}; + static struct pci_device_id i810_pci_tbl [] __initdata = { {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ICH82801AA}, @@ -378,6 +407,7 @@ /* PCI device stuff */ struct pci_dev * pci_dev; u16 pci_id; + u16 pci_id_internal; /* used to access card_cap[] */ #ifdef CONFIG_PM u16 pm_suspended; u32 pm_save_state[64/sizeof(u32)]; @@ -1898,7 +1928,8 @@ } /* ICH and ICH0 only support 2 channels */ - if ( state->card->pci_id == 0x2415 || state->card->pci_id == 0x2425 ) + if ( state->card->pci_id == PCI_DEVICE_ID_INTEL_82801 + || state->card->pci_id == PCI_DEVICE_ID_INTEL_82901) return put_user(2, (int *)arg); /* Multi-channel support was added with ICH2. Bits in */ @@ -2707,6 +2738,7 @@ { u32 reg = inl(card->iobase + GLOB_CNT); int i; + int primary_codec_id = 0; if((reg&2)==0) /* Cold required */ reg|=2; @@ -2742,15 +2774,22 @@ * See if the primary codec comes ready. This must happen * before we start doing DMA stuff */ - - reg = inl(card->iobase + GLOB_STA); - if(!(reg & 0x100)) + /* see i810_ac97_init for the next 7 lines (jsaw) */ + inw(card->ac97base); + if ((card->pci_id == PCI_DEVICE_ID_INTEL_ICH4) + && (card->use_mmio)) { + primary_codec_id = (int) readl(card->iobase_mmio + SDM) & 0x3; + printk(KERN_INFO "i810_audio: primary codec id %d\n", + primary_codec_id); + } + + if(! i810_ac97_exists(card, primary_codec_id)) { printk(KERN_INFO "i810_audio: Codec not ready.. wait.. "); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(HZ); /* actually 600mS by the spec */ - reg = inl(card->iobase + GLOB_STA); - if(reg & 0x100) + + if(i810_ac97_exists(card, primary_codec_id)) printk("OK\n"); else printk("no response.\n"); @@ -2762,8 +2801,8 @@ static int __init i810_ac97_init(struct i810_card *card) { int num_ac97 = 0; + int ac97_id; int total_channels = 0; - int ac97_count = 0; struct ac97_codec *codec; u16 eid; u32 reg; @@ -2789,31 +2828,38 @@ reg = inl(card->iobase + GLOB_CNT); outl(reg & 0xffcfffff, card->iobase + GLOB_CNT); - inw(card->ac97base); + for (num_ac97 = 0; num_ac97 < card_cap[card->pci_id_internal].nr_ac97; num_ac97++) { + card->ac97_codec[num_ac97] = NULL; + } - for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) { - - /* sigh, my mother board reports a tertiary codec (Intel D845GBV), - yet it's accessed as primary codec... (jsaw) */ - if (!d845gbv_bug) ac97_count = num_ac97; - - /* Assume codec isn't available until we go through the - * gauntlet below */ - card->ac97_codec[ac97_count] = NULL; + for (num_ac97 = 0; num_ac97 < card_cap[card->pci_id_internal].nr_ac97; num_ac97++) { + /* codec reset */ + printk(KERN_INFO "i810_audio: resetting hw channel %d\n", num_ac97); + if (card->use_mmio) readw(card->ac97base_mmio + 0x80*num_ac97); + else inw(card->ac97base + 0x80*num_ac97); + + /* If we have the SDATA_IN Map Register, as on ICH4, we + do not loop thru all possible codec IDs but thru all + possible IO channels. Bit 0:1 of SDM then holds the + last codec ID spoken to. + */ + if ((card->pci_id == PCI_DEVICE_ID_INTEL_ICH4) + && (card->use_mmio)) { + ac97_id = (int) readl(card->iobase_mmio + SDM) & 0x3; + printk(KERN_INFO "i810_audio: hw channel %d, codec id %d\n", + num_ac97, ac97_id); + } + else { + ac97_id = num_ac97; + } /* The ICH programmer's reference says you should */ /* check the ready status before probing. So we chk */ /* What do we do if it's not ready? Wait and try */ /* again, or abort? */ - if (!i810_ac97_exists(card,num_ac97)) { + if (!i810_ac97_exists(card, ac97_id)) { if(num_ac97 == 0) printk(KERN_ERR "i810_audio: Primary codec not ready.\n"); - - /*@FIXME see comment about D845GBV */ - if (d845gbv_bug) - continue; - else - break; } if ((codec = kmalloc(sizeof(struct ac97_codec), GFP_KERNEL)) == NULL) @@ -2824,8 +2870,8 @@ in ac97_probe_codec */ codec->private_data = card; - /*@FIXME see comment about D845GBV */ - codec->id = ac97_count; + /*@FIXME this will lead to problems!!! id=2 <-> io offset=0*/ + codec->id = num_ac97; if (card->use_mmio) { codec->codec_read = i810_ac97_get_mmio; @@ -2859,8 +2905,6 @@ { printk(KERN_WARNING "i810_audio: codec %d is a softmodem - skipping.\n", num_ac97); kfree(codec); - /*@FIXME see comment about D845GBV */ - if (d845gbv_bug) ac97_count++; continue; } @@ -2909,7 +2953,7 @@ total_channels += 2; if (eid & 0x0140) /* LFE and Center channels */ total_channels += 2; - printk("i810_audio: AC'97 codec %d supports AMAP, total channels = %d\n", num_ac97, total_channels); + printk("i810_audio: AC'97 codec %d supports AMAP, total channels = %d\n", ac97_id, total_channels); } else if (eid & 0x0400) { /* this only works on 2.2 compliant codecs */ eid &= 0xffcf; if((eid & 0xc000) != 0) { @@ -2931,14 +2975,14 @@ } i810_ac97_set(codec, AC97_EXTENDED_ID, eid); eid = i810_ac97_get(codec, AC97_EXTENDED_ID); - printk("i810_audio: AC'97 codec %d, new EID value = 0x%04x\n", num_ac97, eid); + printk("i810_audio: AC'97 codec %d, new EID value = 0x%04x\n", ac97_id, eid); if (eid & 0x0080) /* L/R Surround channels */ total_channels += 2; if (eid & 0x0140) /* LFE and Center channels */ total_channels += 2; - printk("i810_audio: AC'97 codec %d, DAC map configured, total channels = %d\n", num_ac97, total_channels); + printk("i810_audio: AC'97 codec %d, DAC map configured, total channels = %d\n", ac97_id, total_channels); } else { - printk("i810_audio: AC'97 codec %d Unable to map surround DAC's (or DAC's not present), total channels = %d\n", num_ac97, total_channels); + printk("i810_audio: AC'97 codec %d Unable to map surround DAC's (or DAC's not present), total channels = %d\n", ac97_id, total_channels); } if ((codec->dev_mixer = register_sound_mixer(&i810_mixer_fops, -1)) < 0) { @@ -2947,15 +2991,13 @@ break; } - card->ac97_codec[ac97_count] = codec; - /*@FIXME see comment about D845GBV */ - if (d845gbv_bug) ac97_count++; + card->ac97_codec[num_ac97] = codec; } /* pick the minimum of channels supported by ICHx or codec(s) */ card->channels = (card->channels > total_channels)?total_channels:card->channels; - return ac97_count; + return num_ac97; } static void __init i810_configure_clocking (void) @@ -3058,12 +3100,8 @@ card->ac97base = pci_resource_start (pci_dev, 0); card->iobase = pci_resource_start (pci_dev, 1); - /* - ICH4 supports/needs direct memory access - to support more than 2 codecs - (jsaw) - */ - if ((pci_id->device == PCI_DEVICE_ID_INTEL_ICH4)) { + /* if chipset could have mmio capability, check it */ + if (card_cap[pci_id->driver_data].flags & CAP_MMIO) { card->ac97base_mmio_phys = pci_resource_start (pci_dev, 2); card->iobase_mmio_phys = pci_resource_start (pci_dev, 3); @@ -3363,7 +3401,6 @@ MODULE_PARM(clocking, "i"); MODULE_PARM(strict_clocking, "i"); MODULE_PARM(spdif_locked, "i"); -MODULE_PARM(d845gbv_bug, "i"); #define I810_MODULE_NAME "intel810_audio"

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Fri Aug 23 2002 - 22:00:16 EST