patch-2.4.9 linux/drivers/sound/es1371.c

Next file: linux/drivers/sound/esssolo1.c
Previous file: linux/drivers/sound/es1370.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.8/linux/drivers/sound/es1371.c linux/drivers/sound/es1371.c
@@ -109,6 +109,7 @@
  *                       suggested by Stephan Müller <smueller@chronox.de>
  *    31.01.2001   0.30  Register/Unregister gameport
  *                       Fix SETTRIGGER non OSS API conformity
+ *    14.07.2001   0.31  Add list of laptops needing amplifier control
  */
 
 /*****************************************************************************/
@@ -474,6 +475,7 @@
 	} midi;
 
 	struct gameport gameport;
+	struct semaphore sem;
 };
 
 /* --------------------------------------------------------------------- */
@@ -482,7 +484,7 @@
 
 /* --------------------------------------------------------------------- */
 
-extern inline unsigned ld2(unsigned int x)
+static inline unsigned ld2(unsigned int x)
 {
 	unsigned r = 0;
 	
@@ -792,7 +794,7 @@
 
 /* --------------------------------------------------------------------- */
 
-extern inline void stop_adc(struct es1371_state *s)
+static inline void stop_adc(struct es1371_state *s)
 {
 	unsigned long flags;
 
@@ -802,7 +804,7 @@
 	spin_unlock_irqrestore(&s->lock, flags);
 }	
 
-extern inline void stop_dac1(struct es1371_state *s)
+static inline void stop_dac1(struct es1371_state *s)
 {
 	unsigned long flags;
 
@@ -812,7 +814,7 @@
 	spin_unlock_irqrestore(&s->lock, flags);
 }	
 
-extern inline void stop_dac2(struct es1371_state *s)
+static inline void stop_dac2(struct es1371_state *s)
 {
 	unsigned long flags;
 
@@ -897,7 +899,7 @@
 #define DMABUF_MINORDER 1
 
 
-extern inline void dealloc_dmabuf(struct es1371_state *s, struct dmabuf *db)
+static inline void dealloc_dmabuf(struct es1371_state *s, struct dmabuf *db)
 {
 	struct page *page, *pend;
 
@@ -965,28 +967,28 @@
 	return 0;
 }
 
-extern inline int prog_dmabuf_adc(struct es1371_state *s)
+static inline int prog_dmabuf_adc(struct es1371_state *s)
 {
 	stop_adc(s);
 	return prog_dmabuf(s, &s->dma_adc, s->adcrate, (s->sctrl >> SCTRL_SH_R1FMT) & ES1371_FMT_MASK, 
 			   ES1371_REG_ADC_FRAMEADR);
 }
 
-extern inline int prog_dmabuf_dac2(struct es1371_state *s)
+static inline int prog_dmabuf_dac2(struct es1371_state *s)
 {
 	stop_dac2(s);
 	return prog_dmabuf(s, &s->dma_dac2, s->dac2rate, (s->sctrl >> SCTRL_SH_P2FMT) & ES1371_FMT_MASK, 
 			   ES1371_REG_DAC2_FRAMEADR);
 }
 
-extern inline int prog_dmabuf_dac1(struct es1371_state *s)
+static inline int prog_dmabuf_dac1(struct es1371_state *s)
 {
 	stop_dac1(s);
 	return prog_dmabuf(s, &s->dma_dac1, s->dac1rate, (s->sctrl >> SCTRL_SH_P1FMT) & ES1371_FMT_MASK,
 			   ES1371_REG_DAC1_FRAMEADR);
 }
 
-extern inline unsigned get_hwptr(struct es1371_state *s, struct dmabuf *db, unsigned reg)
+static inline unsigned get_hwptr(struct es1371_state *s, struct dmabuf *db, unsigned reg)
 {
 	unsigned hwptr, diff;
 
@@ -997,7 +999,7 @@
 	return diff;
 }
 
-extern inline void clear_advance(void *buf, unsigned bsize, unsigned bptr, unsigned len, unsigned char c)
+static inline void clear_advance(void *buf, unsigned bsize, unsigned bptr, unsigned len, unsigned char c)
 {
 	if (bptr + len > bsize) {
 		unsigned x = bsize - bptr;
@@ -1148,13 +1150,6 @@
 
 /* --------------------------------------------------------------------- */
 
-static loff_t es1371_llseek(struct file *file, loff_t offset, int origin)
-{
-	return -ESPIPE;
-}
-
-/* --------------------------------------------------------------------- */
-
 /* Conversion table for S/PDIF PCM volume emulation through the SRC */
 /* dB-linear table of DAC vol values; -0dB to -46.5dB with mute */
 static const unsigned short DACVolTable[101] =
@@ -1268,7 +1263,7 @@
 
 static /*const*/ struct file_operations es1371_mixer_fops = {
 	owner:		THIS_MODULE,
-	llseek:		es1371_llseek,
+	llseek:		no_llseek,
 	ioctl:		es1371_ioctl_mixdev,
 	open:		es1371_open_mixdev,
 	release:	es1371_release_mixdev,
@@ -1352,7 +1347,7 @@
 {
 	struct es1371_state *s = (struct es1371_state *)file->private_data;
 	DECLARE_WAITQUEUE(wait, current);
-	ssize_t ret;
+	ssize_t ret = 0;
 	unsigned long flags;
 	unsigned swptr;
 	int cnt;
@@ -1362,11 +1357,12 @@
 		return -ESPIPE;
 	if (s->dma_adc.mapped)
 		return -ENXIO;
-	if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s)))
-		return ret;
 	if (!access_ok(VERIFY_WRITE, buffer, count))
 		return -EFAULT;
-	ret = 0;
+	down(&s->sem);
+	if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s)))
+		goto out2;
+	
 	add_wait_queue(&s->dma_adc.wait, &wait);
 	while (count > 0) {
 		spin_lock_irqsave(&s->lock, flags);
@@ -1385,20 +1381,27 @@
 			if (file->f_flags & O_NONBLOCK) {
 				if (!ret)
 					ret = -EAGAIN;
-				break;
+				goto out;
 			}
+			up(&s->sem);
 			schedule();
 			if (signal_pending(current)) {
 				if (!ret)
 					ret = -ERESTARTSYS;
-				break;
+				goto out2;
+			}
+			down(&s->sem);
+			if (s->dma_adc.mapped)
+			{
+				ret = -ENXIO;
+				goto out;
 			}
 			continue;
 		}
 		if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt)) {
 			if (!ret)
 				ret = -EFAULT;
-			break;
+			goto out;
 		}
 		swptr = (swptr + cnt) % s->dma_adc.dmasize;
 		spin_lock_irqsave(&s->lock, flags);
@@ -1411,6 +1414,9 @@
 		if (s->dma_adc.enabled)
 			start_adc(s);
 	}
+out:
+	up(&s->sem);
+out2:
 	remove_wait_queue(&s->dma_adc.wait, &wait);
 	set_current_state(TASK_RUNNING);
 	return ret;
@@ -1430,10 +1436,11 @@
 		return -ESPIPE;
 	if (s->dma_dac2.mapped)
 		return -ENXIO;
-	if (!s->dma_dac2.ready && (ret = prog_dmabuf_dac2(s)))
-		return ret;
 	if (!access_ok(VERIFY_READ, buffer, count))
 		return -EFAULT;
+	down(&s->sem);	
+	if (!s->dma_dac2.ready && (ret = prog_dmabuf_dac2(s)))
+		goto out3;
 	ret = 0;
 	add_wait_queue(&s->dma_dac2.wait, &wait);
 	while (count > 0) {
@@ -1457,20 +1464,27 @@
 			if (file->f_flags & O_NONBLOCK) {
 				if (!ret)
 					ret = -EAGAIN;
-				break;
-			}
+				goto out;
+			}	
+			up(&s->sem);
 			schedule();
 			if (signal_pending(current)) {
 				if (!ret)
 					ret = -ERESTARTSYS;
-				break;
+				goto out2;
+			}
+			down(&s->sem);
+			if (s->dma_dac2.mapped)
+			{
+				ret = -ENXIO;
+				goto out;
 			}
 			continue;
 		}
 		if (copy_from_user(s->dma_dac2.rawbuf + swptr, buffer, cnt)) {
 			if (!ret)
 				ret = -EFAULT;
-			break;
+			goto out;
 		}
 		swptr = (swptr + cnt) % s->dma_dac2.dmasize;
 		spin_lock_irqsave(&s->lock, flags);
@@ -1484,7 +1498,11 @@
 		if (s->dma_dac2.enabled)
 			start_dac2(s);
 	}
+out:
+	up(&s->sem);
+out2:
 	remove_wait_queue(&s->dma_dac2.wait, &wait);
+out3:	
 	set_current_state(TASK_RUNNING);
 	return ret;
 }
@@ -1530,43 +1548,45 @@
 {
 	struct es1371_state *s = (struct es1371_state *)file->private_data;
 	struct dmabuf *db;
-	int ret;
+	int ret = 0;
 	unsigned long size;
 
 	VALIDATE_STATE(s);
 	lock_kernel();
+	down(&s->sem);
+	
 	if (vma->vm_flags & VM_WRITE) {
 		if ((ret = prog_dmabuf_dac2(s)) != 0) {
-			unlock_kernel();
-			return ret;
+			goto out;
 		}
 		db = &s->dma_dac2;
 	} else if (vma->vm_flags & VM_READ) {
 		if ((ret = prog_dmabuf_adc(s)) != 0) {
-			unlock_kernel();
-			return ret;
+			goto out;
 		}
 		db = &s->dma_adc;
 	} else {
-		unlock_kernel();
-		return -EINVAL;
+		ret = -EINVAL;
+		goto out;
 	}
 	if (vma->vm_pgoff != 0) {
-		unlock_kernel();
-		return -EINVAL;
+		ret = -EINVAL;
+		goto out;
 	}
 	size = vma->vm_end - vma->vm_start;
 	if (size > (PAGE_SIZE << db->buforder)) {
-		unlock_kernel();
-		return -EINVAL;
+		ret = -EINVAL;
+		goto out;
 	}
 	if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot)) {
-		unlock_kernel();
-		return -EAGAIN;
+		ret = -EAGAIN;
+		goto out;
 	}
 	db->mapped = 1;
+out:
+	up(&s->sem);
 	unlock_kernel();
-	return 0;
+	return ret;
 }
 
 static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
@@ -1970,6 +1990,7 @@
 	spin_unlock_irqrestore(&s->lock, flags);
 	s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
 	up(&s->open_sem);
+	init_MUTEX(&s->sem);
 	return 0;
 }
 
@@ -1999,7 +2020,7 @@
 
 static /*const*/ struct file_operations es1371_audio_fops = {
 	owner:		THIS_MODULE,
-	llseek:		es1371_llseek,
+	llseek:		no_llseek,
 	read:		es1371_read,
 	write:		es1371_write,
 	poll:		es1371_poll,
@@ -2411,7 +2432,7 @@
 
 static /*const*/ struct file_operations es1371_dac_fops = {
 	owner:		THIS_MODULE,
-	llseek:		es1371_llseek,
+	llseek:		no_llseek,
 	write:		es1371_write_dac,
 	poll:		es1371_poll_dac,
 	ioctl:		es1371_ioctl_dac,
@@ -2683,7 +2704,7 @@
 
 static /*const*/ struct file_operations es1371_midi_fops = {
 	owner:		THIS_MODULE,
-	llseek:		es1371_llseek,
+	llseek:		no_llseek,
 	read:		es1371_midi_read,
 	write:		es1371_midi_write,
 	poll:		es1371_midi_poll,
@@ -2739,6 +2760,7 @@
 static int nomix[NR_DEVICE] = { 0, };
 
 static unsigned int devindex = 0;
+static int amplifier = 0;
 
 MODULE_PARM(joystick, "1-" __MODULE_STRING(NR_DEVICE) "i");
 MODULE_PARM_DESC(joystick, "sets address and enables joystick interface (still need separate driver)");
@@ -2746,6 +2768,8 @@
 MODULE_PARM_DESC(spdif, "if 1 the output is in S/PDIF digital mode");
 MODULE_PARM(nomix, "1-" __MODULE_STRING(NR_DEVICE) "i");
 MODULE_PARM_DESC(nomix, "if 1 no analog audio is mixed to the digital output");
+MODULE_PARM(amplifier, "i");
+MODULE_PARM_DESC(amplifier, "Set to 1 if the machine needs the amp control enabling (many laptops)");
 
 MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");
 MODULE_DESCRIPTION("ES1371 AudioPCI97 Driver");
@@ -2771,11 +2795,25 @@
 	{ SOUND_MIXER_WRITE_IGAIN, 0x4040 }
 };
 
+static struct
+{
+	short svid, sdid;
+} amplifier_needed[] = 
+{
+	{ 0x107B, 0x2150 },		/* Gateway Solo 2150 */
+	{ 0x13BD, 0x100C },		/* Mebius PC-MJ100V */
+	{ 0x1102, 0x5938 },		/* Targa Xtender 300 */
+	{ 0x1102, 0x8938 },		/* IPC notebook */
+	{ PCI_ANY_ID, PCI_ANY_ID }
+};
+
+
 static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid)
 {
 	struct es1371_state *s;
 	mm_segment_t fs;
 	int i, val, res = -1;
+	int idx;
 	unsigned long tmo;
 	signed long tmo2;
 	unsigned int cssr;
@@ -2845,25 +2883,33 @@
 	
 	/* initialize codec registers */
 	s->ctrl = 0;
-	if (pcidev->subsystem_vendor == 0x107b && pcidev->subsystem_device == 0x2150) {
+
+	/* Check amplifier requirements */
+	
+	if(amplifier)
 		s->ctrl |= CTRL_GPIO_OUT0;
-		printk(KERN_INFO PFX "Running On Gateway 2000 Solo 2510 - Amp On \n");
-	}	
-	s->gameport.io = s->gameport.size = 0;
+	else for(idx = 0; amplifier_needed[idx].svid != PCI_ANY_ID; idx++)
+	{
+		if(pcidev->subsystem_vendor == amplifier_needed[idx].svid &&
+		   pcidev->subsystem_device == amplifier_needed[idx].sdid)
+		{
+                    	s->ctrl |= CTRL_GPIO_OUT0;   /* turn internal amplifier on */
+                    	printk(KERN_INFO PFX "Enabling internal amplifier.\n");
+		}
+	}
+	s->gameport.io = 0;
 	if ((joystick[devindex] & ~0x18) == 0x200) {
 		if (!request_region(joystick[devindex], JOY_EXTENT, "es1371"))
 			printk(KERN_ERR PFX "joystick address 0x%x already in use\n", joystick[devindex]);
 		else {
 			s->ctrl |= CTRL_JYSTK_EN | (((joystick[devindex] >> 3) & CTRL_JOY_MASK) << CTRL_JOY_SHIFT);
 			s->gameport.io = joystick[devindex];
-			s->gameport.size = JOY_EXTENT;
 		}
 	} else if (joystick[devindex] == 1) {
 		for (i = 0x218; i >= 0x200; i -= 0x08) {
 			if (request_region(i, JOY_EXTENT, "es1371")) {
 				s->ctrl |= CTRL_JYSTK_EN | (((i >> 3) & CTRL_JOY_MASK) << CTRL_JOY_SHIFT);
 				s->gameport.io = i;
-				s->gameport.size = JOY_EXTENT;
 				break;
 			}
 		}
@@ -2951,7 +2997,7 @@
 
  err_gp:
 	if (s->gameport.io)
-		release_region(s->gameport.io, s->gameport.size);
+		release_region(s->gameport.io, JOY_EXTENT);
  err_dev4:
 	unregister_sound_dsp(s->dev_dac);
  err_dev3:
@@ -2985,7 +3031,7 @@
 	free_irq(s->irq, s);
 	if (s->gameport.io) {
 		gameport_unregister_port(&s->gameport);
-		release_region(s->gameport.io, s->gameport.size);
+		release_region(s->gameport.io, JOY_EXTENT);
 	}
 	release_region(s->io, ES1371_EXTENT);
 	unregister_sound_dsp(s->dev_audio);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)