lkml.org 
[lkml]   [2002]   [Aug]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Subject[PATCH 2.4.20-pre2-ac4] i810_audio.c
From
Date
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"
\
 
 \ /
  Last update: 2005-03-22 13:28    [W:0.075 / U:0.196 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site