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
- Lines: 446
- Date:
Sun Aug 12 10:51:42 2001
- Orig file:
v2.4.8/linux/drivers/sound/es1371.c
- Orig date:
Tue May 22 10:23:16 2001
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)