linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* PATCH: update the i810 audio driver
@ 2003-07-11 18:14 Alan Cox
  2003-07-12  3:44 ` Linus Torvalds
  0 siblings, 1 reply; 5+ messages in thread
From: Alan Cox @ 2003-07-11 18:14 UTC (permalink / raw)
  To: linux-kernel, torvalds

diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.5.75/sound/oss/i810_audio.c linux-2.5.75-ac1/sound/oss/i810_audio.c
--- linux-2.5.75/sound/oss/i810_audio.c	2003-07-10 21:12:55.000000000 +0100
+++ linux-2.5.75-ac1/sound/oss/i810_audio.c	2003-07-11 17:34:21.000000000 +0100
@@ -117,6 +117,9 @@
 #ifndef PCI_DEVICE_ID_INTEL_ICH4
 #define PCI_DEVICE_ID_INTEL_ICH4	0x24c5
 #endif
+#ifndef PCI_DEVICE_ID_INTEL_ICH5
+#define PCI_DEVICE_ID_INTEL_ICH5	0x24d5
+#endif
 #ifndef PCI_DEVICE_ID_INTEL_440MX
 #define PCI_DEVICE_ID_INTEL_440MX	0x7195
 #endif
@@ -178,7 +181,7 @@
 struct i810_channel 
 {
 	/* these sg guys should probably be allocated
-	   separately as nocache. Must be 8 byte aligned */
+	   seperately as nocache. Must be 8 byte aligned */
 	struct sg_item sg[SG_LEN];	/* 32*8 */
 	u32 offset;			/* 4 */
 	u32 port;			/* 4 */
@@ -187,7 +190,7 @@
 };
 
 /*
- * we have 3 separate dma engines.  pcm in, pcm out, and mic.
+ * we have 3 seperate dma engines.  pcm in, pcm out, and mic.
  * each dma engine has controlling registers.  These goofy
  * names are from the datasheet, but make it easy to write
  * code while leafing through it.
@@ -272,6 +275,7 @@
 	INTELICH2,
 	INTELICH3,
 	INTELICH4,
+	INTELICH5,
 	SI7012,
 	NVIDIA_NFORCE,
 	AMD768,
@@ -285,6 +289,7 @@
 	"Intel ICH2",
 	"Intel ICH3",
 	"Intel ICH4",
+	"Intel ICH5",
 	"SiS 7012",
 	"NVIDIA nForce Audio",
 	"AMD 768",
@@ -303,7 +308,8 @@
 	{  1, 0x0000 }, /* INTEL440MX */
 	{  1, 0x0000 }, /* INTELICH2 */
 	{  2, 0x0000 }, /* INTELICH3 */
-        {  3, 0x0003 }, /* INTELICH4 */
+ 	{  3, 0x0003 }, /* INTELICH4 */
+	{  3, 0x0003 }, /* INTELICH5 */
 	/*@FIXME to be verified*/	{  2, 0x0000 }, /* SI7012 */
 	/*@FIXME to be verified*/	{  2, 0x0000 }, /* NVIDIA_NFORCE */
 	/*@FIXME to be verified*/	{  2, 0x0000 }, /* AMD768 */
@@ -323,6 +329,8 @@
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH3},
 	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH4,
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH4},
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH5,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH5},
 	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7012,
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, SI7012},
 	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_MCP1_AUDIO,
@@ -419,6 +427,9 @@
 	/* The i810 has a certain amount of cross channel interaction
 	   so we use a single per card lock */
 	spinlock_t lock;
+	
+	/* Control AC97 access serialization */
+	spinlock_t ac97_lock;
 
 	/* PCI device stuff */
 	struct pci_dev * pci_dev;
@@ -547,80 +558,42 @@
  *     The DSP sample rate must already be set to a supported
  *     S/PDIF rate (32kHz, 44.1kHz, or 48kHz) or we abort.
  */
-static void i810_set_spdif_output(struct i810_state *state, int slots, int rate)
+static int i810_set_spdif_output(struct i810_state *state, int slots, int rate)
 {
 	int	vol;
 	int	aud_reg;
+	int	r = 0;
 	struct ac97_codec *codec = state->card->ac97_codec[0];
 
-	if(!(state->card->ac97_features & 4)) {
-#ifdef DEBUG
-		printk(KERN_WARNING "i810_audio: S/PDIF transmitter not available.\n");
-#endif
+	if(!codec->codec_ops->digital) {
 		state->card->ac97_status &= ~SPDIF_ON;
 	} else {
 		if ( slots == -1 ) { /* Turn off S/PDIF */
-			aud_reg = i810_ac97_get(codec, AC97_EXTENDED_STATUS);
-			i810_ac97_set(codec, AC97_EXTENDED_STATUS, (aud_reg & ~AC97_EA_SPDIF));
-
+			codec->codec_ops->digital(codec, 0, 0, 0);
 			/* If the volume wasn't muted before we turned on S/PDIF, unmute it */
 			if ( !(state->card->ac97_status & VOL_MUTED) ) {
 				aud_reg = i810_ac97_get(codec, AC97_MASTER_VOL_STEREO);
 				i810_ac97_set(codec, AC97_MASTER_VOL_STEREO, (aud_reg & ~VOL_MUTED));
 			}
 			state->card->ac97_status &= ~(VOL_MUTED | SPDIF_ON);
-			return;
+			return 0;
 		}
 
 		vol = i810_ac97_get(codec, AC97_MASTER_VOL_STEREO);
 		state->card->ac97_status = vol & VOL_MUTED;
-
-		/* Set S/PDIF transmitter sample rate */
-		aud_reg = i810_ac97_get(codec, AC97_SPDIF_CONTROL);
-		switch ( rate ) {
-			case 32000:
-				aud_reg = (aud_reg & AC97_SC_SPSR_MASK) | AC97_SC_SPSR_32K; 
-				break;
-			 case 44100:
-			 	aud_reg = (aud_reg & AC97_SC_SPSR_MASK) | AC97_SC_SPSR_44K; 
-				break;
-			case 48000:
-			 	aud_reg = (aud_reg & AC97_SC_SPSR_MASK) | AC97_SC_SPSR_48K; 
-				break;
-			default:
-#ifdef DEBUG
-				printk(KERN_WARNING "i810_audio: %d sample rate not supported by S/PDIF.\n", rate);
-#endif
-				/* turn off S/PDIF */
-				aud_reg = i810_ac97_get(codec, AC97_EXTENDED_STATUS);
-				i810_ac97_set(codec, AC97_EXTENDED_STATUS, (aud_reg & ~AC97_EA_SPDIF));
-				state->card->ac97_status &= ~SPDIF_ON;
-				return;
-		}
-
-		i810_ac97_set(codec, AC97_SPDIF_CONTROL, aud_reg);
 		
-		aud_reg = i810_ac97_get(codec, AC97_EXTENDED_STATUS);
-		aud_reg = (aud_reg & AC97_EA_SLOT_MASK) | slots | AC97_EA_VRA | AC97_EA_SPDIF;
-		i810_ac97_set(codec, AC97_EXTENDED_STATUS, aud_reg);
-		state->card->ac97_status |= SPDIF_ON;
-
-		/* Check to make sure the configuration is valid */
-		aud_reg = i810_ac97_get(codec, AC97_EXTENDED_STATUS);
-		if ( ! (aud_reg & 0x0400) ) {
-#ifdef DEBUG
-			printk(KERN_WARNING "i810_audio: S/PDIF transmitter configuration not valid (0x%04x).\n", aud_reg);
-#endif
+		r = codec->codec_ops->digital(codec, slots, rate, 0);
 
-			/* turn off S/PDIF */
-			i810_ac97_set(codec, AC97_EXTENDED_STATUS, (aud_reg & ~AC97_EA_SPDIF));
+		if(r)
+			state->card->ac97_status |= SPDIF_ON;
+		else
 			state->card->ac97_status &= ~SPDIF_ON;
-			return;
-		}
+
 		/* Mute the analog output */
 		/* Should this only mute the PCM volume??? */
 		i810_ac97_set(codec, AC97_MASTER_VOL_STEREO, (vol | VOL_MUTED));
 	}
+	return r;
 }
 
 /* i810_set_dac_channels
@@ -642,8 +615,9 @@
 {
 	int	aud_reg;
 	struct ac97_codec *codec = state->card->ac97_codec[0];
-
+	
 	/* No codec, no setup */
+	
 	if(codec == NULL)
 		return;
 
@@ -905,7 +879,7 @@
 #define DMABUF_DEFAULTORDER (16-PAGE_SHIFT)
 #define DMABUF_MINORDER 1
 
-/* allocate DMA buffer, playback and recording buffer should be allocated separately */
+/* allocate DMA buffer, playback and recording buffer should be allocated seperately */
 static int alloc_dmabuf(struct i810_state *state)
 {
 	struct dmabuf *dmabuf = &state->dmabuf;
@@ -1835,6 +1809,7 @@
 		}
 
 		spin_unlock_irqrestore(&state->card->lock, flags);
+		synchronize_irq(state->card->pci_dev->irq);
 		dmabuf->ready = 0;
 		dmabuf->swptr = dmabuf->hwptr = 0;
 		dmabuf->count = dmabuf->total_bytes = 0;
@@ -2493,11 +2468,9 @@
 	}
 	if(file->f_mode & FMODE_WRITE) {
 		if((dmabuf->write_channel = card->alloc_pcm_channel(card)) == NULL) {
-			/* free any read channel allocated earlier */
+			/* make sure we free the record channel allocated above */
 			if(file->f_mode & FMODE_READ)
-				card->free_pcm_channel(card,
-						dmabuf->read_channel->num);
-
+				card->free_pcm_channel(card,dmabuf->read_channel->num);
 			kfree (card->states[i]);
 			card->states[i] = NULL;;
 			return -EBUSY;
@@ -2641,23 +2614,32 @@
 static u16 i810_ac97_get(struct ac97_codec *dev, u8 reg)
 {
 	struct i810_card *card = dev->private_data;
+	u16 ret;
+	
+	spin_lock(&card->ac97_lock);
 	if (card->use_mmio) {
-		return i810_ac97_get_mmio(dev, reg);
+		ret = i810_ac97_get_mmio(dev, reg);
 	}
 	else {
-		return i810_ac97_get_io(dev, reg);
+		ret = i810_ac97_get_io(dev, reg);
 	}
+	spin_unlock(&card->ac97_lock);
+	
+	return ret;
 }
 
 static void i810_ac97_set(struct ac97_codec *dev, u8 reg, u16 data)
 {
 	struct i810_card *card = dev->private_data;
+	
+	spin_lock(&card->ac97_lock);
 	if (card->use_mmio) {
 		i810_ac97_set_mmio(dev, reg, data);
 	}
 	else {
 		i810_ac97_set_io(dev, reg, data);
 	}
+	spin_unlock(&card->ac97_lock);
 }
 
 
@@ -2803,7 +2785,7 @@
 	 */	
 	/* see i810_ac97_init for the next 7 lines (jsaw) */
 	inw(card->ac97base);
-	if ((card->pci_id == PCI_DEVICE_ID_INTEL_ICH4)
+	if ((card->pci_id == PCI_DEVICE_ID_INTEL_ICH4 || card->pci_id == PCI_DEVICE_ID_INTEL_ICH5)
 	    && (card->use_mmio)) {
 		primary_codec_id = (int) readl(card->iobase_mmio + SDM) & 0x3;
 		printk(KERN_INFO "i810_audio: Primary codec has ID %d\n",
@@ -2873,7 +2855,7 @@
 		   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)
+		if ((card->pci_id == PCI_DEVICE_ID_INTEL_ICH4 || card->pci_id == PCI_DEVICE_ID_INTEL_ICH5)
 		    && (card->use_mmio)) {
 			ac97_id = (int) readl(card->iobase_mmio + SDM) & 0x3;
 			printk(KERN_INFO "i810_audio: Connection %d with codec id %d\n",
@@ -2892,9 +2874,8 @@
 				printk(KERN_ERR "i810_audio: Primary codec not ready.\n");
 		}
 		
-		if ((codec = kmalloc(sizeof(struct ac97_codec), GFP_KERNEL)) == NULL)
+		if ((codec = ac97_alloc_codec()) == NULL)
 			return -ENOMEM;
-		memset(codec, 0, sizeof(struct ac97_codec));
 
 		/* initialize some basic codec information, other fields will be filled
 		   in ac97_probe_codec */
@@ -2913,7 +2894,7 @@
 	
 		if(!i810_ac97_probe_and_powerup(card,codec)) {
 			printk(KERN_ERR "i810_audio: timed out waiting for codec %d analog ready.\n", ac97_id);
-			kfree(codec);
+			ac97_release_codec(codec);
 			break;	/* it didn't work */
 		}
 		/* Store state information about S/PDIF transmitter */
@@ -2922,32 +2903,22 @@
 		/* Don't attempt to get eid until powerup is complete */
 		eid = i810_ac97_get(codec, AC97_EXTENDED_ID);
 
-		if(eid==0xFFFFFF)
+		if(eid==0xFFFF)
 		{
 			printk(KERN_WARNING "i810_audio: no codec attached ?\n");
-			kfree(codec);
+			ac97_release_codec(codec);
 			break;
 		}
 		
 		/* Check for an AC97 1.0 soft modem (ID1) */
 		
-		if(codec->codec_read(codec, AC97_RESET) & 2)
+		if(codec->modem)
 		{
-			printk(KERN_WARNING "i810_audio: codec %d is an AC97 1.0 softmodem - skipping.\n", ac97_id);
-			kfree(codec);
+			printk(KERN_WARNING "i810_audio: codec %d is a softmodem - skipping.\n", ac97_id);
+			ac97_release_codec(codec);
 			continue;
 		}
 		
-		/* Check for an AC97 2.x soft modem */
-		
-		codec->codec_write(codec, AC97_EXTENDED_MODEM_ID, 0L);
-		if(codec->codec_read(codec, AC97_EXTENDED_MODEM_ID) & 1)
-		{
-			printk(KERN_WARNING "i810_audio: codec %d is an AC97 2.x softmodem - skipping.\n", ac97_id);
-			kfree(codec);
-			continue;
-		}
-	
 		card->ac97_features = eid;
 
 		/* Now check the codec for useful features to make up for
@@ -3027,7 +2998,7 @@
 
 		if ((codec->dev_mixer = register_sound_mixer(&i810_mixer_fops, -1)) < 0) {
 			printk(KERN_ERR "i810_audio: couldn't register mixer!\n");
-			kfree(codec);
+			ac97_release_codec(codec);
 			break;
 		}
 
@@ -3158,6 +3129,7 @@
 	card->pm_suspended=0;
 #endif
 	spin_lock_init(&card->lock);
+	spin_lock_init(&card->ac97_lock);
 	devs = card;
 
 	pci_set_master(pci_dev);
@@ -3253,7 +3225,7 @@
 		for (i = 0; i < NR_AC97; i++)
 		if (card->ac97_codec[i] != NULL) {
 			unregister_sound_mixer(card->ac97_codec[i]->dev_mixer);
-			kfree (card->ac97_codec[i]);
+			ac97_release_codec(card->ac97_codec[i]);
 		}
 		goto out_iospace;
 	}
@@ -3297,7 +3269,7 @@
 	for (i = 0; i < NR_AC97; i++)
 		if (card->ac97_codec[i] != NULL) {
 			unregister_sound_mixer(card->ac97_codec[i]->dev_mixer);
-			kfree (card->ac97_codec[i]);
+			ac97_release_codec(card->ac97_codec[i]);
 			card->ac97_codec[i] = NULL;
 		}
 	unregister_sound_dsp(card->dev_audio);

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: PATCH: update the i810 audio driver
  2003-07-11 18:14 PATCH: update the i810 audio driver Alan Cox
@ 2003-07-12  3:44 ` Linus Torvalds
  2003-07-13  8:08   ` Alan Cox
  0 siblings, 1 reply; 5+ messages in thread
From: Linus Torvalds @ 2003-07-12  3:44 UTC (permalink / raw)
  To: Alan Cox; +Cc: Kernel Mailing List


On Fri, 11 Jul 2003, Alan Cox wrote:
> -	   separately as nocache. Must be 8 byte aligned */
> +	   seperately as nocache. Must be 8 byte aligned */

Ok, Alan, spot the problem.

		Linus


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: PATCH: update the i810 audio driver
  2003-07-12  3:44 ` Linus Torvalds
@ 2003-07-13  8:08   ` Alan Cox
  2003-07-13 18:25     ` Linus Torvalds
  2003-07-13 21:01     ` Johannes Ruscheinski
  0 siblings, 2 replies; 5+ messages in thread
From: Alan Cox @ 2003-07-13  8:08 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Linux Kernel Mailing List

On Sad, 2003-07-12 at 04:44, Linus Torvalds (compiled with -pedantic)
wrote:
> On Fri, 11 Jul 2003, Alan Cox wrote:
> > -	   separately as nocache. Must be 8 byte aligned */
> > +	   seperately as nocache. Must be 8 byte aligned */
> 
> Ok, Alan, spot the problem.

Ok so I can't spell, I never claimed to be able to. The rest should
be fine however.

Alan
--


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: PATCH: update the i810 audio driver
  2003-07-13  8:08   ` Alan Cox
@ 2003-07-13 18:25     ` Linus Torvalds
  2003-07-13 21:01     ` Johannes Ruscheinski
  1 sibling, 0 replies; 5+ messages in thread
From: Linus Torvalds @ 2003-07-13 18:25 UTC (permalink / raw)
  To: Alan Cox; +Cc: Linux Kernel Mailing List


On 13 Jul 2003, Alan Cox wrote:
> 
> Ok so I can't spell, I never claimed to be able to.

;)

I applied the patch after doing a manual search-and-replace.

		Linus


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: PATCH: update the i810 audio driver
  2003-07-13  8:08   ` Alan Cox
  2003-07-13 18:25     ` Linus Torvalds
@ 2003-07-13 21:01     ` Johannes Ruscheinski
  1 sibling, 0 replies; 5+ messages in thread
From: Johannes Ruscheinski @ 2003-07-13 21:01 UTC (permalink / raw)
  To: Alan Cox; +Cc: Linus Torvalds, Linux Kernel Mailing List

Also sprach Alan Cox:
> On Sad, 2003-07-12 at 04:44, Linus Torvalds (compiled with -pedantic)
> wrote:
> > On Fri, 11 Jul 2003, Alan Cox wrote:
> > > -	   separately as nocache. Must be 8 byte aligned */
> > > +	   seperately as nocache. Must be 8 byte aligned */
> > 
> > Ok, Alan, spot the problem.
> 
> Ok so I can't spell, I never claimed to be able to. The rest should
> be fine however.
> 
> Alan
> --
> 
> -
> 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/

As a -pedantic German I'd just like to point out that both the Oxford English
Dictionary and Webster's dictionary agree that "separately" is the correct
spelling.  The OED further lists "seperately" as an obsolete form!
-- 
Johannes
--
Dr. Johannes Ruscheinski
EMail:    ruschein_AT_infomine.ucr.edu ***          Linux                  ***
Location: science library, room G40    *** The Choice Of A GNU Generation! ***
Phone:    (909) 787-2279

"There are already a million monkeys on a million typewriters, and Usenet is
 NOTHING like Shakespeare."
                                                           -- Blair Houghton

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2003-07-13 20:46 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-07-11 18:14 PATCH: update the i810 audio driver Alan Cox
2003-07-12  3:44 ` Linus Torvalds
2003-07-13  8:08   ` Alan Cox
2003-07-13 18:25     ` Linus Torvalds
2003-07-13 21:01     ` Johannes Ruscheinski

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).