Skip to contentSkip to conversation

fix broken i810_audio DMA (?)

PATCH New Juergen Sawinski 3 participants 5 messages Aug 29, 2002

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 fix broken i810_audio DMA (?)

Changes:
-remove dma reset in stop_{dac,adc}
(from ICH4 manual: contents of all Bus master related registers to be
reset; so, probably some registers are not re-initilized properly on consecutive re-opening of /dev/dsp ???)
-remove writes to OFF_CIV, instead set LVI relative to CIV

and some stuff that was already in the last diff I send to the list:
-implement a codec ID <-> IO register offset mapping
-in i810_ioctl, case SNDCTL_DSP_CHANNELS: only touch bits 20:21
off GLOB_CNT (multichannel capabilities)
-AMD 8111 has 6 hw channels so I must have mmio (but I don't have
any docs to verify this)
-minor fixes

Signature · 13 lines
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
#1 lore raw

PATCH 1/1 fix broken i810_audio DMA (?)

F*ck. This time the patch attached.
Thanx Jim.

George

Quoted 36 lines · Juergen Sawinski

Changes:

(quoted diff) +0 -2
-remove dma reset in stop_{dac,adc}
 (from ICH4 manual: contents of all Bus master related registers to be
  reset; so, probably some registers are not re-initilized properly on
  consecutive re-opening of /dev/dsp ???)
-remove writes to OFF_CIV, instead set LVI relative to CIV

and some stuff that was already in the last diff I send to the list:

(quoted diff) +0 -4
-implement a codec ID <-> IO register offset mapping
-in i810_ioctl, case SNDCTL_DSP_CHANNELS: only touch bits 20:21
 off GLOB_CNT (multichannel capabilities)
-AMD 8111 has 6 hw channels so I must have mmio (but I don't have
 any docs to verify this)
-minor fixes
Signature · 21 lines
-- 
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


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/
Signature · 13 lines
Juergen "George" Sawinski
Max-Planck-Institute for Medical Research
Dept. of Biomedical Optics
Jahnstr. 29
D-69120 Heidelberg
Germany

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

priv.
Phone:  +49-6221-418 848
Mobile: +49-171-532 5302
drivers/sound/i810_audio.c +42 -41
@@ -69,12 +69,12 @@
  *
  *  ICH 4 caveats
  *
- *      The ICH4 has the feature, that the codec ID may not be congruent 
- *      with the AC-link channel.
+ *      The ICH4 has the feature, that the codec ID doesn't have to be 
+ *      congruent with the IO connection.
  * 
- *      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.
- *      
+ *      Therefore, from driver version 0.23 on, there is a "codec ID" <->
+ *      "IO register base offset" mapping (card->ac97_id_map) field.
+ *   
  *      Juergen "George" Sawinski (jsaw) 
  */
  
@@ -207,7 +207,7 @@
 	CAS	 = 	0x34			/* Codec Write Semaphore Register */
 };
 
-ENUM_ENGINE(MC2,4);     /* Mic. 2 */
+ENUM_ENGINE(MC2,4);     /* Mic In 2 */
 ENUM_ENGINE(PI2,5);     /* PCM In 2 */
 ENUM_ENGINE(SP,6);      /* S/PDIF */
 
@@ -234,8 +234,7 @@
 #define INT_GPI		(1<<0)
 #define INT_MASK (INT_SEC|INT_PRI|INT_MC|INT_PO|INT_PI|INT_MO|INT_NI|INT_GPI)
 
-
-#define DRIVER_VERSION "0.22"
+#define DRIVER_VERSION "0.23"
 
 /* magic numbers to protect our data structures */
 #define I810_CARD_MAGIC		0x5072696E /* "Prin" */
@@ -295,7 +294,7 @@
 	/*@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 */
+	/*@FIXME to be verified*/	{  3, 0x0001 }, /* AMD8111 */
 };
 
 static struct pci_device_id i810_pci_tbl [] __initdata = {
@@ -417,6 +416,7 @@
 	int dev_audio;
 
 	/* structures for abstraction of hardware facilities, codecs, banks and channels*/
+	u16    ac97_id_map[NR_AC97];
 	struct ac97_codec *ac97_codec[NR_AC97];
 	struct i810_state *states[NR_HW_CH];
 	struct i810_channel *channel;	/* 1:1 to states[] but diff. lifetime */
@@ -449,6 +449,12 @@
 	int initializing;
 };
 
+/* extract register offset from codec struct */
+#define IO_REG_OFF(codec) (((struct i810_card *) codec->private_data)->ac97_id_map[codec->id])
+
+/* set LVI from CIV */
+#define CIV_TO_LVI(port, off) outb((inb(port+OFF_CIV)+off) & 31, port+OFF_LVI)
+
 static struct i810_card *devs = NULL;
 
 static int i810_open_mixdev(struct inode *inode, struct file *file);
@@ -786,8 +792,6 @@
 	outb(0, card->iobase + PI_CR);
 	// wait for the card to acknowledge shutdown
 	while( inb(card->iobase + PI_CR) != 0 ) ;
-	// reset the dma engine now
-	outb(0x02, card->iobase + PI_CR);
 	// now clear any latent interrupt bits (like the halt bit)
 	if(card->pci_id == PCI_DEVICE_ID_SI_7012)
 		outb( inb(card->iobase + PI_PICB), card->iobase + PI_PICB );
@@ -838,8 +842,6 @@
 	outb(0, card->iobase + PO_CR);
 	// wait for the card to acknowledge shutdown
 	while( inb(card->iobase + PO_CR) != 0 ) ;
-	// reset the dma engine now
-	outb(0x02, card->iobase + PO_CR);
 	// now clear any latent interrupt bits (like the halt bit)
 	if(card->pci_id == PCI_DEVICE_ID_SI_7012)
 		outb( inb(card->iobase + PO_PICB), card->iobase + PO_PICB );
@@ -1033,11 +1035,11 @@
 		}
 		spin_lock_irqsave(&state->card->lock, flags);
 		outb(2, state->card->iobase+c->port+OFF_CR);   /* reset DMA machine */
+		while( inb(state->card->iobase+c->port+OFF_CR) & 0x02 ) ;
 		outl((u32)state->card->chandma +
 		    c->num*sizeof(struct i810_channel),
 		    state->card->iobase+c->port+OFF_BDBAR);
-		outb(0, state->card->iobase+c->port+OFF_CIV);
-		outb(0, state->card->iobase+c->port+OFF_LVI);
+		CIV_TO_LVI(state->card->iobase+c->port, 0);
 
 		spin_unlock_irqrestore(&state->card->lock, flags);
 
@@ -1083,13 +1085,13 @@
 		if(rec && dmabuf->count < dmabuf->dmasize &&
 		   (dmabuf->trigger & PCM_ENABLE_INPUT))
 		{
-			outb((inb(port+OFF_CIV)+1)&31, port+OFF_LVI);
+			CIV_TO_LVI(port, 1);
 			__start_adc(state);
 			while( !(inb(port + OFF_CR) & ((1<<4) | (1<<2))) ) ;
 		} else if (!rec && dmabuf->count &&
 			   (dmabuf->trigger & PCM_ENABLE_OUTPUT))
 		{
-			outb((inb(port+OFF_CIV)+1)&31, port+OFF_LVI);
+			CIV_TO_LVI(port, 1);
 			__start_dac(state);
 			while( !(inb(port + OFF_CR) & ((1<<4) | (1<<2))) ) ;
 		}
@@ -1802,11 +1804,11 @@
 		}
 		if (c != NULL) {
 			outb(2, state->card->iobase+c->port+OFF_CR);   /* reset DMA machine */
+			while ( inb(state->card->iobase+c->port+OFF_CR) & 2 );
 			outl((u32)state->card->chandma +
 			    c->num*sizeof(struct i810_channel),
 			    state->card->iobase+c->port+OFF_BDBAR);
-			outb(0, state->card->iobase+c->port+OFF_CIV);
-			outb(0, state->card->iobase+c->port+OFF_LVI);
+			CIV_TO_LVI(state->card->iobase+c->port, 0);
 		}
 
 		spin_unlock_irqrestore(&state->card->lock, flags);
@@ -1948,13 +1950,13 @@
 
 		switch ( val ) {
 			case 2: /* 2 channels is always supported */
-				outl(i_glob_cnt & 0xcfffff,
+				outl(i_glob_cnt & 0xffcfffff,
 				     state->card->iobase + GLOB_CNT);
 				/* Do we need to change mixer settings????  */
 				break;
 			case 4: /* Supported on some chipsets, better check first */
 				if ( state->card->channels >= 4 ) {
-					outl((i_glob_cnt & 0xcfffff) | 0x100000,
+					outl((i_glob_cnt & 0xffcfffff) | 0x100000,
 					      state->card->iobase + GLOB_CNT);
 					/* Do we need to change mixer settings??? */
 				} else {
@@ -1963,7 +1965,7 @@
 				break;
 			case 6: /* Supported on some chipsets, better check first */
 				if ( state->card->channels >= 6 ) {
-					outl((i_glob_cnt & 0xcfffff) | 0x200000,
+					outl((i_glob_cnt & 0xffcfffff) | 0x200000,
 					      state->card->iobase + GLOB_CNT);
 					/* Do we need to change mixer settings??? */
 				} else {
@@ -2553,8 +2555,7 @@
 {
 	struct i810_card *card = dev->private_data;
 	int count = 100;
-	u16 reg_set = ((u16) reg) & 0x7f;
-	reg_set |= ((u16) dev->id) << 7;
+	u16 reg_set = IO_REG_OFF(dev) | (reg&0x7f);
 	
 	while(count-- && (readb(card->iobase_mmio + CAS) & 1)) 
 		udelay(1);
@@ -2574,7 +2575,7 @@
 {
 	struct i810_card *card = dev->private_data;
 	int count = 100;
-	u8 reg_set = ((dev->id)?((reg&0x7f)|0x80):(reg&0x7f));
+	u16 reg_set = IO_REG_OFF(dev) | (reg&0x7f);
 	
 	while(count-- && (inb(card->iobase + CAS) & 1)) 
 		udelay(1);
@@ -2586,8 +2587,7 @@
 {
 	struct i810_card *card = dev->private_data;
 	int count = 100;
-	u16 reg_set = ((u16) reg) & 0x7f;
-	reg_set |= ((u16) dev->id) << 7;
+	u16 reg_set = IO_REG_OFF(dev) | (reg&0x7f);
 	
 	while(count-- && (readb(card->iobase_mmio + CAS) & 1)) 
 		udelay(1);
@@ -2603,7 +2603,7 @@
 {
 	struct i810_card *card = dev->private_data;
 	int count = 100;
-	u8 reg_set = ((dev->id)?((reg&0x7f)|0x80):(reg&0x7f));
+	u16 reg_set = IO_REG_OFF(dev) | (reg&0x7f);
 	
 	while(count-- && (inb(card->iobase + CAS) & 1)) 
 		udelay(1);
@@ -2779,7 +2779,7 @@
 	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",
+		printk(KERN_INFO "i810_audio: Primary codec has ID %d\n",
 		       primary_codec_id);
 	}
 
@@ -2803,6 +2803,7 @@
 	int num_ac97 = 0;
 	int ac97_id;
 	int total_channels = 0;
+	int nr_ac97_max = card_cap[card->pci_id_internal].nr_ac97;
 	struct ac97_codec *codec;
 	u16 eid;
 	u32 reg;
@@ -2828,13 +2829,15 @@
 	reg = inl(card->iobase + GLOB_CNT);
 	outl(reg & 0xffcfffff, card->iobase + GLOB_CNT);
 		
-	for (num_ac97 = 0; num_ac97 < card_cap[card->pci_id_internal].nr_ac97; num_ac97++) {
+	for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) 
 		card->ac97_codec[num_ac97] = NULL;
-	}
 
-	for (num_ac97 = 0; num_ac97 < card_cap[card->pci_id_internal].nr_ac97; num_ac97++) {
+	/*@FIXME I don't know, if I'm playing to safe here... (jsaw) */
+	if ((nr_ac97_max > 2) && !card->use_mmio) nr_ac97_max = 2;
+
+	for (num_ac97 = 0; num_ac97 < nr_ac97_max; num_ac97++) {
 		/* codec reset */
-		printk(KERN_INFO "i810_audio: resetting hw channel %d\n", num_ac97);
+		printk(KERN_INFO "i810_audio: Resetting connection %d\n", num_ac97);
 		if (card->use_mmio) readw(card->ac97base_mmio + 0x80*num_ac97);
 		else inw(card->ac97base + 0x80*num_ac97);
 
@@ -2846,7 +2849,7 @@
 		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",
+			printk(KERN_INFO "i810_audio: Connection %d with codec id %d\n",
 			       num_ac97, ac97_id);
 		}
 		else {
@@ -2869,9 +2872,8 @@
 		/* initialize some basic codec information, other fields will be filled
 		   in ac97_probe_codec */
 		codec->private_data = card;
-
-		/*@FIXME this will lead to problems!!! id=2 <-> io offset=0*/
-		codec->id = num_ac97;
+		codec->id = ac97_id;
+		card->ac97_id_map[ac97_id] = num_ac97 * 0x80;
 
 		if (card->use_mmio) {	
 			codec->codec_read = i810_ac97_get_mmio;
@@ -2883,7 +2885,7 @@
 		}
 	
 		if(!i810_ac97_probe_and_powerup(card,codec)) {
-			printk(KERN_ERR "i810_audio: timed out waiting for codec %d analog ready.\n", num_ac97);
+			printk(KERN_ERR "i810_audio: timed out waiting for codec %d analog ready.\n", ac97_id);
 			kfree(codec);
 			break;	/* it didn't work */
 		}
@@ -2903,7 +2905,7 @@
 		codec->codec_write(codec, AC97_EXTENDED_MODEM_ID, 0L);
 		if(codec->codec_read(codec, AC97_EXTENDED_MODEM_ID))
 		{
-			printk(KERN_WARNING "i810_audio: codec %d is a softmodem - skipping.\n", num_ac97);
+			printk(KERN_WARNING "i810_audio: codec %d is a softmodem - skipping.\n", ac97_id);
 			kfree(codec);
 			continue;
 		}
@@ -3042,8 +3044,7 @@
 		}
 		dmabuf->count = dmabuf->dmasize;
 		stop_dac(state);
-		outb(0,card->iobase+dmabuf->write_channel->port+OFF_CIV);
-		outb(31,card->iobase+dmabuf->write_channel->port+OFF_LVI);
+		CIV_TO_LVI(card->iobase+dmabuf->write_channel->port, -1);
 		save_flags(flags);
 		cli();
 		start_dac(state);
#2 lore raw
Quoted 2 lines · Juergen Sawinski

F*ck. This time the patch attached.
Thanx Jim.

Thanks. It works for me (both from KDE-3.1-beta1 and RealPlayer).

Andris

Quoted 19 lines

George

Quoted 15 lines · Juergen Sawinski

Changes:

(quoted diff) +0 -2
-remove dma reset in stop_{dac,adc}
 (from ICH4 manual: contents of all Bus master related registers to be
  reset; so, probably some registers are not re-initilized properly on
  consecutive re-opening of /dev/dsp ???)
-remove writes to OFF_CIV, instead set LVI relative to CIV

and some stuff that was already in the last diff I send to the list:

(quoted diff) +0 -4
-implement a codec ID <-> IO register offset mapping
-in i810_ioctl, case SNDCTL_DSP_CHANNELS: only touch bits 20:21
 off GLOB_CNT (multichannel capabilities)
-AMD 8111 has 6 hw channels so I must have mmio (but I don't have
 any docs to verify this)
-minor fixes
#3 lore raw
In reply to Juergen Sawinski
Quoted 2 lines · Juergen Sawinski

F*ck. This time the patch attached.
Thanx Jim.

You're welcome.

It works better, but it's not fixed.

o Playing through oss directly works like before
o No more scratchy sound on artsd startup.
o Playing one song at a time through artsd works.
o Giving two songs to ogg123 to play through artsd works until you Ctrl-C to skip to the next song. It then hangs (like before, but with no dmesg output)

Thanks,
-Jim

Quoted 15 lines · Juergen Sawinski
Quoted 14 lines

Changes:

(quoted diff) +0 -2
-remove dma reset in stop_{dac,adc}
 (from ICH4 manual: contents of all Bus master related registers to be
  reset; so, probably some registers are not re-initilized properly on
  consecutive re-opening of /dev/dsp ???)
-remove writes to OFF_CIV, instead set LVI relative to CIV

and some stuff that was already in the last diff I send to the list:

(quoted diff) +0 -4
-implement a codec ID <-> IO register offset mapping
-in i810_ioctl, case SNDCTL_DSP_CHANNELS: only touch bits 20:21
 off GLOB_CNT (multichannel capabilities)
-AMD 8111 has 6 hw channels so I must have mmio (but I don't have
 any docs to verify this)
-minor fixes
#4 lore raw
Quoted 6 lines · Jim Radford
Quoted 2 lines · Juergen Sawinski

F*ck. This time the patch attached.
Thanx Jim.

You're welcome.

Quoted 8 lines

It works better, but it's not fixed.

o Playing through oss directly works like before
o No more scratchy sound on artsd startup.
o Playing one song at a time through artsd works.
o Giving two songs to ogg123 to play through artsd works until you Ctrl-C to skip to the next song. It then hangs (like before, but with no dmesg output)

Can you uncomment the DEBUG defines and try the ogg123 thing again?

Quoted 18 lines

Thanks,
-Jim

Quoted 15 lines · Juergen Sawinski
Quoted 14 lines

Changes:

(quoted diff) +0 -2
-remove dma reset in stop_{dac,adc}
 (from ICH4 manual: contents of all Bus master related registers to be
  reset; so, probably some registers are not re-initilized properly on
  consecutive re-opening of /dev/dsp ???)
-remove writes to OFF_CIV, instead set LVI relative to CIV

and some stuff that was already in the last diff I send to the list:

(quoted diff) +0 -4
-implement a codec ID <-> IO register offset mapping
-in i810_ioctl, case SNDCTL_DSP_CHANNELS: only touch bits 20:21
 off GLOB_CNT (multichannel capabilities)
-AMD 8111 has 6 hw channels so I must have mmio (but I don't have
 any docs to verify this)
-minor fixes
Signature · 13 lines
Juergen "George" Sawinski
Max-Planck-Institute for Medical Research
Dept. of Biomedical Optics
Jahnstr. 29
D-69120 Heidelberg
Germany

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

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