patch-2.4.8 linux/drivers/sound/emu10k1/audio.c
Next file: linux/drivers/sound/emu10k1/cardmi.c
Previous file: linux/drivers/sound/emu10k1/Makefile
Back to the patch index
Back to the overall index
- Lines: 803
- Date:
Fri Aug 10 21:02:18 2001
- Orig file:
v2.4.7/linux/drivers/sound/emu10k1/audio.c
- Orig date:
Tue Jul 3 17:08:21 2001
diff -u --recursive --new-file v2.4.7/linux/drivers/sound/emu10k1/audio.c linux/drivers/sound/emu10k1/audio.c
@@ -48,6 +48,8 @@
#include "recmgr.h"
#include "irqmgr.h"
#include "audio.h"
+#include "8010.h"
+#include "passthrough.h"
static void calculate_ofrag(struct woinst *);
static void calculate_ifrag(struct wiinst *);
@@ -167,6 +169,18 @@
return -ENXIO;
}
+ if (woinst->format.passthrough) {
+ int r;
+
+ woinst->buffer.ossfragshift = PT_BLOCKSIZE_LOG2;
+ woinst->buffer.numfrags = PT_BLOCKCOUNT;
+ calculate_ofrag(woinst);
+
+ r = emu10k1_pt_write(file, buffer, count);
+ spin_unlock_irqrestore(&woinst->lock, flags);
+ return r;
+ }
+
if (woinst->state == WAVE_STATE_CLOSED) {
calculate_ofrag(woinst);
@@ -188,6 +202,11 @@
spin_unlock_irqrestore(&woinst->lock, flags);
ret = 0;
+ if (count % woinst->format.bytespersample)
+ return -EINVAL;
+
+ count /= woinst->num_voices;
+
while (count > 0) {
u32 bytestocopy;
@@ -206,8 +225,8 @@
emu10k1_waveout_xferdata(woinst, (u8 *) buffer, &bytestocopy);
count -= bytestocopy;
- buffer += bytestocopy;
- ret += bytestocopy;
+ buffer += bytestocopy * woinst->num_voices;
+ ret += bytestocopy * woinst->num_voices;
spin_lock_irqsave(&woinst->lock, flags);
woinst->total_copied += bytestocopy;
@@ -267,14 +286,6 @@
spin_lock_irqsave(&woinst->lock, flags);
if (woinst->state & WAVE_STATE_OPEN) {
- if (woinst->mmapped) {
- int i;
-
- /* Undo marking the pages as reserved */
- for (i = 0; i < woinst->buffer.pages; i++)
- mem_map_unreserve(virt_to_page(woinst->buffer.addr[i]));
- }
-
emu10k1_waveout_close(wave_dev);
}
@@ -289,8 +300,9 @@
if (file->f_mode & FMODE_READ) {
spin_lock_irqsave(&wiinst->lock, flags);
- if (wiinst->state & WAVE_STATE_OPEN)
+ if (wiinst->state & WAVE_STATE_OPEN) {
emu10k1_wavein_close(wave_dev);
+ }
wiinst->mmapped = 0;
wiinst->total_recorded = 0;
@@ -316,15 +328,6 @@
interruptible_sleep_on(&woinst->wait_queue);
spin_lock_irqsave(&woinst->lock, flags);
}
-
- if (woinst->mmapped) {
- int i;
-
- /* Undo marking the pages as reserved */
- for (i = 0; i < woinst->buffer.pages; i++)
- mem_map_unreserve(virt_to_page(woinst->buffer.addr[i]));
- }
-
emu10k1_waveout_close(wave_dev);
}
@@ -339,8 +342,9 @@
if (file->f_mode & FMODE_READ) {
spin_lock_irqsave(&wiinst->lock, flags);
- if (wiinst->state & WAVE_STATE_OPEN)
+ if (wiinst->state & WAVE_STATE_OPEN) {
emu10k1_wavein_close(wave_dev);
+ }
wiinst->mmapped = 0;
wiinst->total_recorded = 0;
@@ -490,7 +494,6 @@
spin_unlock_irqrestore(&wiinst->lock, flags);
return -EINVAL;
}
-
val = wiinst->format.channels;
spin_unlock_irqrestore(&wiinst->lock, flags);
@@ -532,9 +535,13 @@
if (file->f_mode & FMODE_READ)
val = AFMT_S16_LE;
- else if (file->f_mode & FMODE_WRITE)
+ else if (file->f_mode & FMODE_WRITE) {
val = AFMT_S16_LE | AFMT_U8;
-
+ if (emu10k1_find_control_gpr(&wave_dev->card->mgr,
+ wave_dev->card->pt.patch_name,
+ wave_dev->card->pt.enable_gpr_name) >= 0)
+ val |= AFMT_AC3;
+ }
return put_user(val, (int *) arg);
case SNDCTL_DSP_SETFMT: /* Same as SNDCTL_DSP_SAMPLESIZE */
@@ -552,17 +559,17 @@
spin_lock_irqsave(&wiinst->lock, flags);
format = wiinst->format;
- format.bitsperchannel = val;
+ format.id = val;
if (emu10k1_wavein_setformat(wave_dev, &format) < 0) {
spin_unlock_irqrestore(&wiinst->lock, flags);
return -EINVAL;
}
- val = wiinst->format.bitsperchannel;
+ val = wiinst->format.id;
spin_unlock_irqrestore(&wiinst->lock, flags);
- DPD(2, "set recording sample size -> %d\n", val);
+ DPD(2, "set recording format -> %d\n", val);
}
if (file->f_mode & FMODE_WRITE) {
@@ -571,27 +578,27 @@
spin_lock_irqsave(&woinst->lock, flags);
format = woinst->format;
- format.bitsperchannel = val;
+ format.id = val;
if (emu10k1_waveout_setformat(wave_dev, &format) < 0) {
spin_unlock_irqrestore(&woinst->lock, flags);
return -EINVAL;
}
- val = woinst->format.bitsperchannel;
+ val = woinst->format.id;
spin_unlock_irqrestore(&woinst->lock, flags);
- DPD(2, "set playback sample size -> %d\n", val);
+ DPD(2, "set playback format -> %d\n", val);
}
- return put_user((val == 16) ? AFMT_S16_LE : AFMT_U8, (int *) arg);
+ return put_user(val, (int *) arg);
} else {
if (file->f_mode & FMODE_READ)
- val = wiinst->format.bitsperchannel;
+ val = wiinst->format.id;
else if (file->f_mode & FMODE_WRITE)
- val = woinst->format.bitsperchannel;
+ val = woinst->format.id;
- return put_user((val == 16) ? AFMT_S16_LE : AFMT_U8, (int *) arg);
+ return put_user(val, (int *) arg);
}
break;
@@ -602,7 +609,7 @@
else if (file->f_mode & FMODE_WRITE)
val = woinst->format.bitsperchannel;
- return put_user((val == 16) ? AFMT_S16_LE : AFMT_U8, (int *) arg);
+ return put_user(val, (int *) arg);
case SOUND_PCM_READ_RATE:
@@ -705,9 +712,10 @@
}
spin_unlock_irqrestore(&woinst->lock, flags);
- info.fragstotal = woinst->buffer.numfrags;
- info.fragments = info.bytes / woinst->buffer.fragment_size;
- info.fragsize = woinst->buffer.fragment_size;
+ info.bytes *= woinst->num_voices;
+ info.fragsize = woinst->buffer.fragment_size * woinst->num_voices;
+ info.fragstotal = woinst->buffer.numfrags * woinst->num_voices;
+ info.fragments = info.bytes / info.fragsize;
if (copy_to_user((int *) arg, &info, sizeof(info)))
return -EFAULT;
@@ -763,6 +771,7 @@
} else
val = 0;
+ val *= woinst->num_voices;
spin_unlock_irqrestore(&woinst->lock, flags);
return put_user(val, (int *) arg);
@@ -790,6 +799,9 @@
cinfo.blocks = 0;
}
+ if(wiinst->mmapped)
+ wiinst->buffer.bytestocopy %= wiinst->buffer.fragment_size;
+
spin_unlock_irqrestore(&wiinst->lock, flags);
if (copy_to_user((void *) arg, &cinfo, sizeof(cinfo)))
@@ -808,19 +820,31 @@
spin_lock_irqsave(&woinst->lock, flags);
- if (woinst->state & WAVE_STATE_OPEN) {
- emu10k1_waveout_update(woinst);
+ if (woinst->state & WAVE_STATE_OPEN ||
+ (woinst->format.passthrough && wave_dev->card->pt.state)) {
+ int num_fragments;
+ if (woinst->format.passthrough) {
+ emu10k1_pt_waveout_update(wave_dev);
+ cinfo.bytes = woinst->total_played;
+ } else {
+ emu10k1_waveout_update(woinst);
+ cinfo.bytes = woinst->total_played;
+ }
cinfo.ptr = woinst->buffer.hw_pos;
- cinfo.bytes = cinfo.ptr + woinst->total_played - woinst->total_played % woinst->buffer.size;
- cinfo.blocks = cinfo.bytes / woinst->buffer.fragment_size - woinst->blocks;
- woinst->blocks = cinfo.bytes / woinst->buffer.fragment_size;
+ num_fragments = cinfo.bytes / woinst->buffer.fragment_size;
+ cinfo.blocks = num_fragments - woinst->blocks;
+ woinst->blocks = num_fragments;
+
+ cinfo.bytes *= woinst->num_voices;
+ cinfo.ptr *= woinst->num_voices;
} else {
cinfo.ptr = 0;
cinfo.bytes = 0;
cinfo.blocks = 0;
}
- if(woinst->mmapped)
- woinst->buffer.bytestocopy %= woinst->buffer.fragment_size;
+
+ if (woinst->mmapped)
+ woinst->buffer.free_bytes %= woinst->buffer.fragment_size;
spin_unlock_irqrestore(&woinst->lock, flags);
@@ -836,7 +860,7 @@
spin_lock_irqsave(&woinst->lock, flags);
calculate_ofrag(woinst);
- val = woinst->buffer.fragment_size;
+ val = woinst->buffer.fragment_size * woinst->num_voices;
spin_unlock_irqrestore(&woinst->lock, flags);
}
@@ -878,13 +902,14 @@
if (get_user(val, (int *) arg))
return -EFAULT;
- DPD(2, "val is 0x%x\n", val);
+ DPD(2, "val is %#x\n", val);
if (val == 0)
return -EIO;
if (file->f_mode & FMODE_WRITE) {
- if (woinst->state & WAVE_STATE_OPEN)
+ /* digital pass-through fragment count and size are fixed values */
+ if (woinst->state & WAVE_STATE_OPEN || woinst->format.passthrough)
return -EINVAL; /* too late to change */
woinst->buffer.ossfragshift = val & 0xffff;
@@ -905,126 +930,175 @@
{
copr_buffer *buf;
u32 i;
- int ret = -EFAULT;
- DPF(2, "SNDCTL_COPR_LOAD:\n");
-
+ DPF(4, "SNDCTL_COPR_LOAD:\n");
+
buf = kmalloc(sizeof(copr_buffer), GFP_KERNEL);
- if(buf == NULL)
+ if (!buf)
return -ENOMEM;
- if (copy_from_user(buf, (copr_buffer *) arg, sizeof(buf)))
- goto fail;
+ if (copy_from_user(buf, (copr_buffer *) arg, sizeof(copr_buffer))) {
+ kfree (buf);
+ return -EFAULT;
+ }
- if ((buf->command != 1) && (buf->command != 2))
- {
- ret = -EINVAL;
- goto fail;
- }
-
- if ((buf->offs < 0x100)
- || (buf->offs < 0x000)
- || (buf->offs + buf->len > 0x800) || (buf->len > 1000))
- {
- ret = -EINVAL;
- goto fail;
+ if ((buf->command != CMD_READ) && (buf->command != CMD_WRITE)) {
+ kfree (buf);
+ return -EINVAL;
+ }
+#ifdef DBGEMU
+ if ( (buf->offs < 0) || (buf->offs + buf->len > 0x800) || (buf->len > 1000)) {
+#else
+ if ( ((buf->offs < 0x100 ) || (buf->offs + buf->len > 0x800) || (buf->len > 1000))
+ && !( ( buf->offs == DBG) && (buf->len ==1) )){
+#endif
+ kfree(buf);
+ return -EINVAL;
}
- if (buf->command == 1) {
+
+ if (buf->command == CMD_READ) {
for (i = 0; i < buf->len; i++)
((u32 *) buf->data)[i] = sblive_readptr(wave_dev->card, buf->offs + i, 0);
- if (copy_to_user((copr_buffer *) arg, buf, sizeof(buf)))
- goto fail;
+ if (copy_to_user((copr_buffer *) arg, buf, sizeof(copr_buffer))) {
+ kfree(buf);
+ return -EFAULT;
+ }
} else {
for (i = 0; i < buf->len; i++)
sblive_writeptr(wave_dev->card, buf->offs + i, 0, ((u32 *) buf->data)[i]);
}
- ret = 0;
- fail:
- kfree(buf);
- return ret;
+
+ kfree (buf);
+ break;
}
default: /* Default is unrecognized command */
- DPD(2, "default: 0x%x\n", cmd);
+ DPD(2, "default: %#x\n", cmd);
return -EINVAL;
}
return 0;
}
+static struct page *emu10k1_mm_nopage (struct vm_area_struct * vma, unsigned long address, int write_access)
+{
+ struct emu10k1_wavedevice *wave_dev = vma->vm_private_data;
+ struct woinst *woinst = wave_dev->woinst;
+ struct wiinst *wiinst = wave_dev->wiinst;
+ struct page *dmapage;
+ unsigned long pgoff;
+ int rd, wr;
+
+ if (address > vma->vm_end) {
+ DPF(2, "EXIT, returning NOPAGE_SIGBUS\n");
+ return NOPAGE_SIGBUS; /* Disallow mremap */
+ }
+
+ pgoff = vma->vm_pgoff + ((address - vma->vm_start) >> PAGE_SHIFT);
+ if (woinst != NULL)
+ wr = woinst->mmapped;
+ else
+ wr = 0;
+
+ if (wiinst != NULL)
+ rd = wiinst->mmapped;
+ else
+ rd = 0;
+
+ /* if full-duplex (read+write) and we have two sets of bufs,
+ * then the playback buffers come first, sez soundcard.c */
+ if (wr) {
+ if (pgoff >= woinst->buffer.pages) {
+ pgoff -= woinst->buffer.pages;
+ dmapage = virt_to_page ((u8 *) wiinst->buffer.addr + pgoff * PAGE_SIZE);
+ } else
+ dmapage = virt_to_page (woinst->buffer.mem[0].addr[pgoff]);
+ } else {
+ dmapage = virt_to_page ((u8 *) wiinst->buffer.addr + pgoff * PAGE_SIZE);
+ }
+
+ get_page (dmapage);
+ return dmapage;
+}
+
+struct vm_operations_struct emu10k1_mm_ops = {
+ nopage: emu10k1_mm_nopage,
+};
+
static int emu10k1_audio_mmap(struct file *file, struct vm_area_struct *vma)
{
struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data;
+ unsigned long maxsize, size, offset, pgoffset;
+ struct woinst *woinst = NULL;
+ struct wiinst *wiinst = NULL;
+ unsigned long flags;
DPF(2, "emu10k1_audio_mmap()\n");
- if (vma_get_pgoff(vma) != 0)
- return -ENXIO;
-
- lock_kernel();
-
+ maxsize = 0;
if (vma->vm_flags & VM_WRITE) {
- struct woinst *woinst = wave_dev->woinst;
- u32 size;
- unsigned long flags;
- int i;
+ woinst = wave_dev->woinst;
spin_lock_irqsave(&woinst->lock, flags);
+ /* No m'mapping possible for multichannel */
+ if (woinst->num_voices > 1) {
+ spin_unlock_irqrestore(&woinst->lock, flags);
+ return -EINVAL;
+ }
+
if (woinst->state == WAVE_STATE_CLOSED) {
calculate_ofrag(woinst);
if (emu10k1_waveout_open(wave_dev) < 0) {
spin_unlock_irqrestore(&woinst->lock, flags);
ERROR();
- unlock_kernel();
return -EINVAL;
}
-
- /* Now mark the pages as reserved, otherwise remap_page_range doesn't do what we want */
- for (i = 0; i < woinst->buffer.pages; i++)
- mem_map_reserve(virt_to_page(woinst->buffer.addr[i]));
- }
-
- size = vma->vm_end - vma->vm_start;
-
- if (size > (PAGE_SIZE * woinst->buffer.pages)) {
- spin_unlock_irqrestore(&woinst->lock, flags);
- unlock_kernel();
- return -EINVAL;
- }
-
- for (i = 0; i < woinst->buffer.pages; i++) {
- if (remap_page_range(vma->vm_start + (i * PAGE_SIZE), virt_to_phys(woinst->buffer.addr[i]), PAGE_SIZE, vma->vm_page_prot)) {
- spin_unlock_irqrestore(&woinst->lock, flags);
- unlock_kernel();
- return -EAGAIN;
- }
}
woinst->mmapped = 1;
-
+ maxsize += woinst->buffer.pages * PAGE_SIZE;
spin_unlock_irqrestore(&woinst->lock, flags);
}
if (vma->vm_flags & VM_READ) {
- struct wiinst *wiinst = wave_dev->wiinst;
- unsigned long flags;
+ wiinst = wave_dev->wiinst;
spin_lock_irqsave(&wiinst->lock, flags);
+ if (wiinst->state == WAVE_STATE_CLOSED) {
+ calculate_ifrag(wiinst);
+
+ if (emu10k1_wavein_open(wave_dev) < 0) {
+ spin_unlock_irqrestore(&wiinst->lock, flags);
+ ERROR();
+ return -EINVAL;
+ }
+ }
+
wiinst->mmapped = 1;
+ maxsize += wiinst->buffer.pages * PAGE_SIZE;
spin_unlock_irqrestore(&wiinst->lock, flags);
}
- unlock_kernel();
+ size = vma->vm_end - vma->vm_start;
+ pgoffset = vma->vm_pgoff;
+ offset = pgoffset << PAGE_SHIFT;
+ if (offset + size > maxsize)
+ return -EINVAL;
+
+ vma->vm_flags |= VM_RESERVED;
+ vma->vm_ops = &emu10k1_mm_ops;
+ vma->vm_private_data = wave_dev;
+
return 0;
}
static int emu10k1_audio_open(struct inode *inode, struct file *file)
{
int minor = MINOR(inode->i_rdev);
- struct emu10k1_card *card=NULL;
+ struct emu10k1_card *card = NULL;
struct list_head *entry;
struct emu10k1_wavedevice *wave_dev;
@@ -1035,17 +1109,19 @@
list_for_each(entry, &emu10k1_devs) {
card = list_entry(entry, struct emu10k1_card, list);
- if (!((card->audio_num ^ minor) & ~0xf) || !((card->audio1_num ^ minor) & ~0xf))
- break;
+ if (!((card->audio_dev ^ minor) & ~0xf) || !((card->audio_dev1 ^ minor) & ~0xf))
+ goto match;
}
- if (entry == &emu10k1_devs)
- return -ENODEV;
+ return -ENODEV;
+
+match:
- if ((wave_dev = (struct emu10k1_wavedevice *)
- kmalloc(sizeof(struct emu10k1_wavedevice), GFP_KERNEL)) == NULL) {
+ wave_dev = (struct emu10k1_wavedevice *) kmalloc(sizeof(struct emu10k1_wavedevice), GFP_KERNEL);
+
+ if (wave_dev == NULL) {
ERROR();
- return -EINVAL;
+ return -ENOMEM;
}
wave_dev->card = card;
@@ -1067,16 +1143,19 @@
switch (wiinst->recsrc) {
case WAVERECORD_AC97:
+ wiinst->format.id = AFMT_S16_LE;
wiinst->format.samplingrate = 8000;
wiinst->format.bitsperchannel = 16;
wiinst->format.channels = 1;
break;
case WAVERECORD_MIC:
+ wiinst->format.id = AFMT_S16_LE;
wiinst->format.samplingrate = 8000;
wiinst->format.bitsperchannel = 16;
wiinst->format.channels = 1;
break;
case WAVERECORD_FX:
+ wiinst->format.id = AFMT_S16_LE;
wiinst->format.samplingrate = 48000;
wiinst->format.bitsperchannel = 16;
wiinst->format.channels = hweight32(wiinst->fxwc);
@@ -1105,6 +1184,7 @@
if (file->f_mode & FMODE_WRITE) {
struct woinst *woinst;
+ int i;
if ((woinst = (struct woinst *) kmalloc(sizeof(struct woinst), GFP_KERNEL)) == NULL) {
ERROR();
@@ -1114,6 +1194,7 @@
if (wave_dev->wiinst != NULL) {
woinst->format = wave_dev->wiinst->format;
} else {
+ woinst->format.id = AFMT_U8;
woinst->format.samplingrate = 8000;
woinst->format.bitsperchannel = 8;
woinst->format.channels = 1;
@@ -1124,7 +1205,13 @@
woinst->buffer.fragment_size = 0;
woinst->buffer.ossfragshift = 0;
woinst->buffer.numfrags = 0;
- woinst->device = (card->audio1_num == minor);
+ woinst->device = (card->audio_dev1 == minor);
+ woinst->timer.state = TIMER_STATE_UNINSTALLED;
+ woinst->num_voices = 1;
+ for (i = 0; i < WAVEOUT_MAXVOICES; i++) {
+ woinst->voice[i].usage = VOICE_USAGE_FREE;
+ woinst->buffer.mem[i].emupageindex = -1;
+ }
init_waitqueue_head(&woinst->wait_queue);
@@ -1137,45 +1224,6 @@
wave_dev->woinst = woinst;
emu10k1_waveout_setformat(wave_dev, &woinst->format);
-#ifdef PRIVATE_PCM_VOLUME
- {
- int i;
- int j = -1;
-
- /*
- * find out if we've already been in this table
- * xmms reopens dsp on every move of slider
- * this way we keep the same local pcm for such
- * process
- */
- for (i = 0; i < MAX_PCM_CHANNELS; i++) {
- if (sblive_pcm_volume[i].files == current->files)
- break;
- // here we should select last used memeber
- // improve me in case its not sufficient
- if (j < 0 && !sblive_pcm_volume[i].opened)
- j = i;
- }
- // current task not found
- if (i == MAX_PCM_CHANNELS) {
- // add new entry
- if (j < 0)
- printk(KERN_WARNING "emu10k1: too many writters!\n");
- i = (j >= 0) ? j : 0;
- DPD(2, "new pcm private %p\n", current->files);
- sblive_pcm_volume[i].files = current->files;
- sblive_pcm_volume[i].mixer = pcm_last_mixer;
- sblive_pcm_volume[i].attn_l = 0;
- sblive_pcm_volume[i].attn_r = 0;
- sblive_pcm_volume[i].channel_l = NUM_G;
- sblive_pcm_volume[i].channel_r = NUM_G;
- } else
- DPD(2, "old pcm private %p 0x%x\n", current->files,
- sblive_pcm_volume[i].mixer);
-
- sblive_pcm_volume[i].opened++;
- }
-#endif
}
file->private_data = (void *) wave_dev;
@@ -1189,7 +1237,6 @@
struct emu10k1_card *card;
unsigned long flags;
- lock_kernel();
card = wave_dev->card;
DPF(2, "emu10k1_audio_release()\n");
@@ -1199,6 +1246,9 @@
spin_lock_irqsave(&woinst->lock, flags);
+ if (woinst->format.passthrough && card->pt.state != PT_STATE_INACTIVE)
+ emu10k1_pt_stop(card);
+
if (woinst->state & WAVE_STATE_OPEN) {
if (woinst->state & WAVE_STATE_STARTED) {
if (!(file->f_flags & O_NONBLOCK)) {
@@ -1211,31 +1261,9 @@
}
}
}
-
- if (woinst->mmapped) {
- int i;
-
- /* Undo marking the pages as reserved */
- for (i = 0; i < woinst->buffer.pages; i++)
- mem_map_unreserve(virt_to_page(woinst->buffer.addr[i]));
- }
-
emu10k1_waveout_close(wave_dev);
}
-#ifdef PRIVATE_PCM_VOLUME
- {
- int i;
- /* mark as closed
- * NOTE: structure remains unchanged for next reopen */
- for (i = 0; i < MAX_PCM_CHANNELS; i++) {
- if (sblive_pcm_volume[i].files == current->files) {
- sblive_pcm_volume[i].opened--;
- break;
- }
- }
- }
-#endif
spin_unlock_irqrestore(&woinst->lock, flags);
/* wait for the tasklet (bottom-half) to finish */
tasklet_unlock_wait(&woinst->timer.tasklet);
@@ -1247,8 +1275,9 @@
spin_lock_irqsave(&wiinst->lock, flags);
- if (wiinst->state & WAVE_STATE_OPEN)
+ if (wiinst->state & WAVE_STATE_OPEN) {
emu10k1_wavein_close(wave_dev);
+ }
spin_unlock_irqrestore(&wiinst->lock, flags);
tasklet_unlock_wait(&wiinst->timer.tasklet);
@@ -1257,12 +1286,13 @@
kfree(wave_dev);
- wake_up_interruptible(&card->open_wait);
- unlock_kernel();
+ if (waitqueue_active(&card->open_wait))
+ wake_up_interruptible(&card->open_wait);
return 0;
}
+/* FIXME sort out poll() + mmap() */
static unsigned int emu10k1_audio_poll(struct file *file, struct poll_table_struct *wait)
{
struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data;
@@ -1292,11 +1322,6 @@
} else
mask |= POLLOUT | POLLWRNORM;
- if(woinst->mmapped) {
- spin_unlock_irqrestore(&woinst->lock, flags);
- return mask;
- }
-
spin_unlock_irqrestore(&woinst->lock, flags);
}
@@ -1336,7 +1361,7 @@
return;
if (!buffer->ossfragshift) {
- fragsize = (woinst->format.bytespersec * WAVEOUT_DEFAULTFRAGLEN) / 1000 - 1;
+ fragsize = (woinst->format.bytespervoicesample * woinst->format.samplingrate * WAVEOUT_DEFAULTFRAGLEN) / 1000 - 1;
while (fragsize) {
fragsize >>= 1;
@@ -1352,7 +1377,8 @@
if (!buffer->numfrags) {
u32 numfrags;
- numfrags = (woinst->format.bytespersec * WAVEOUT_DEFAULTBUFLEN) / (buffer->fragment_size * 1000) - 1;
+ numfrags = (woinst->format.bytespervoicesample * woinst->format.samplingrate * WAVEOUT_DEFAULTBUFLEN) /
+ (buffer->fragment_size * 1000) - 1;
buffer->numfrags = 1;
@@ -1452,13 +1478,13 @@
}
buffer->numfrags = buffer->size / buffer->fragment_size;
-
+ buffer->pages = buffer->size / PAGE_SIZE + ((buffer->size % PAGE_SIZE) ? 1 : 0);
if (buffer->size % buffer->fragment_size)
BUG();
DPD(2, " calculated recording fragment_size -> %d\n", buffer->fragment_size);
DPD(2, " calculated recording numfrags -> %d\n", buffer->numfrags);
- DPD(2, " buffer size register -> 0x%2x\n", buffer->sizeregval);
+ DPD(2, " buffer size register -> %#04x\n", buffer->sizeregval);
return;
}
@@ -1478,17 +1504,11 @@
}
emu10k1_wavein_update(wave_dev->card, wiinst);
-
- if (wiinst->mmapped) {
- spin_unlock_irqrestore(&wiinst->lock, flags);
- return;
- }
-
emu10k1_wavein_getxfersize(wiinst, &bytestocopy);
spin_unlock_irqrestore(&wiinst->lock, flags);
- if (bytestocopy >= wiinst->buffer.fragment_size)
+ if (bytestocopy >= wiinst->buffer.fragment_size && waitqueue_active(&wiinst->wait_queue))
wake_up_interruptible(&wiinst->wait_queue);
else
DPD(3, "Not enough transfer size, %d\n", bytestocopy);
@@ -1519,7 +1539,7 @@
} else
spin_unlock_irqrestore(&woinst->lock, flags);
- if (bytestocopy >= woinst->buffer.fragment_size)
+ if (bytestocopy >= woinst->buffer.fragment_size && waitqueue_active(&woinst->wait_queue))
wake_up_interruptible(&woinst->wait_queue);
else
DPD(3, "Not enough transfer size -> %d\n", bytestocopy);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)