]> git.hungrycats.org Git - linux/commitdiff
[PATCH] update emu10k1 driver (SB Live, Audigy etc)
authorAlan Cox <alan@lxorguk.ukuu.org.uk>
Fri, 21 Mar 2003 10:29:37 +0000 (02:29 -0800)
committerLinus Torvalds <torvalds@home.transmeta.com>
Fri, 21 Mar 2003 10:29:37 +0000 (02:29 -0800)
21 files changed:
sound/oss/emu10k1/audio.c
sound/oss/emu10k1/audio.h
sound/oss/emu10k1/cardwi.c
sound/oss/emu10k1/cardwi.h
sound/oss/emu10k1/cardwo.c
sound/oss/emu10k1/cardwo.h
sound/oss/emu10k1/efxmgr.c
sound/oss/emu10k1/efxmgr.h
sound/oss/emu10k1/hwaccess.c
sound/oss/emu10k1/hwaccess.h
sound/oss/emu10k1/irqmgr.c
sound/oss/emu10k1/main.c
sound/oss/emu10k1/midi.c
sound/oss/emu10k1/mixer.c
sound/oss/emu10k1/passthrough.c
sound/oss/emu10k1/recmgr.c
sound/oss/emu10k1/recmgr.h
sound/oss/emu10k1/timer.c
sound/oss/emu10k1/timer.h
sound/oss/emu10k1/voicemgr.c
sound/oss/emu10k1/voicemgr.h

index f2e6b8d5ad949c2dd8256c0a1b5772547c451b83..7ee80d12f63dd4f985437b2d8153463e83680e45 100644 (file)
@@ -30,7 +30,6 @@
  **********************************************************************
  */
 
-#define __NO_VERSION__
 #include <linux/module.h>
 #include <linux/poll.h>
 #include <linux/slab.h>
@@ -983,11 +982,11 @@ static struct page *emu10k1_mm_nopage (struct vm_area_struct * vma, unsigned lon
        unsigned long pgoff;
        int rd, wr;
 
-       DPF(4, "emu10k1_mm_nopage()\n");
-       DPD(4, "addr: %#lx\n", address);
+       DPF(3, "emu10k1_mm_nopage()\n");
+       DPD(3, "addr: %#lx\n", address);
 
        if (address > vma->vm_end) {
-               DPF(2, "EXIT, returning NOPAGE_SIGBUS\n");
+               DPF(1, "EXIT, returning NOPAGE_SIGBUS\n");
                return NOPAGE_SIGBUS; /* Disallow mremap */
        }
 
@@ -1009,14 +1008,14 @@ static struct page *emu10k1_mm_nopage (struct vm_area_struct * vma, unsigned lon
                        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]);
+                       dmapage = virt_to_page (woinst->voice[0].mem.addr[pgoff]);
        } else {
                dmapage = virt_to_page ((u8 *) wiinst->buffer.addr + pgoff * PAGE_SIZE);
        }
 
        get_page (dmapage);
 
-       DPD(4, "page: %#lx\n", dmapage);
+       DPD(3, "page: %#lx\n", (unsigned long) dmapage);
        return dmapage;
 }
 
@@ -1083,8 +1082,8 @@ static int emu10k1_audio_mmap(struct file *file, struct vm_area_struct *vma)
        n_pages = ((vma->vm_end - vma->vm_start) + PAGE_SIZE - 1) >> PAGE_SHIFT;
        pgoffset = vma->vm_pgoff;
 
-       DPD(3, "vma_start: %#lx, vma_end: %#lx, vma_offset: %d\n", vma->vm_start, vma->vm_end, pgoffset);
-       DPD(3, "n_pages: %d, max_pages: %d\n", n_pages, max_pages);
+       DPD(2, "vma_start: %#lx, vma_end: %#lx, vma_offset: %ld\n", vma->vm_start, vma->vm_end, pgoffset);
+       DPD(2, "n_pages: %ld, max_pages: %ld\n", n_pages, max_pages);
 
        if (pgoffset + n_pages > max_pages)
                return -EINVAL;
@@ -1092,7 +1091,6 @@ static int emu10k1_audio_mmap(struct file *file, struct vm_area_struct *vma)
        vma->vm_flags |= VM_RESERVED;
        vma->vm_ops = &emu10k1_mm_ops;
        vma->vm_private_data = wave_dev;
-
        return 0;
 }
 
@@ -1136,7 +1134,8 @@ match:
 
                if ((wiinst = (struct wiinst *) kmalloc(sizeof(struct wiinst), GFP_KERNEL)) == NULL) {
                        ERROR();
-                       return -ENODEV;
+                       kfree(wave_dev);
+                       return -ENOMEM;
                }
 
                wiinst->recsrc = card->wavein.recsrc;
@@ -1162,6 +1161,8 @@ match:
                        wiinst->format.channels = hweight32(wiinst->fxwc);
                        break;
                default:
+                       kfree(wave_dev);
+                       kfree(wiinst);
                        BUG();
                        break;
                }
@@ -1211,7 +1212,7 @@ match:
                woinst->num_voices = 1;
                for (i = 0; i < WAVEOUT_MAXVOICES; i++) {
                        woinst->voice[i].usage = VOICE_USAGE_FREE;
-                       woinst->buffer.mem[i].emupageindex = -1;
+                       woinst->voice[i].mem.emupageindex = -1;
                }
 
                init_waitqueue_head(&woinst->wait_queue);
@@ -1330,23 +1331,13 @@ static unsigned int emu10k1_audio_poll(struct file *file, struct poll_table_stru
        if (file->f_mode & FMODE_READ) {
                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);
-                               return (mask |= POLLERR);
-                       }
-               }
+               if (wiinst->state & WAVE_STATE_OPEN) {
+                       emu10k1_wavein_update(wave_dev->card, wiinst);
+                       emu10k1_wavein_getxfersize(wiinst, &bytestocopy);
 
-               if (!(wiinst->state & WAVE_STATE_STARTED)) {
-                       wave_dev->enablebits |= PCM_ENABLE_INPUT;
-                       emu10k1_wavein_start(wave_dev);
+                       if (bytestocopy >= wiinst->buffer.fragment_size)
+                               mask |= POLLIN | POLLRDNORM;
                }
-               emu10k1_wavein_update(wave_dev->card, wiinst);
-               emu10k1_wavein_getxfersize(wiinst, &bytestocopy);
-
-               if (bytestocopy >= wiinst->buffer.fragment_size)
-                       mask |= POLLIN | POLLRDNORM;
 
                spin_unlock_irqrestore(&wiinst->lock, flags);
        }
@@ -1376,6 +1367,13 @@ static void calculate_ofrag(struct woinst *woinst)
 
        buffer->fragment_size = 1 << buffer->ossfragshift;
 
+       while (buffer->fragment_size * WAVEOUT_MINFRAGS > WAVEOUT_MAXBUFSIZE)
+               buffer->fragment_size >>= 1;
+
+       /* now we are sure that:
+        (2^WAVEOUT_MINFRAGSHIFT) <= (fragment_size = 2^n) <= (WAVEOUT_MAXBUFSIZE / WAVEOUT_MINFRAGS)
+       */
+
        if (!buffer->numfrags) {
                u32 numfrags;
 
@@ -1390,19 +1388,14 @@ static void calculate_ofrag(struct woinst *woinst)
                }
        }
 
-       if (buffer->numfrags < MINFRAGS)
-               buffer->numfrags = MINFRAGS;
+       if (buffer->numfrags < WAVEOUT_MINFRAGS)
+               buffer->numfrags = WAVEOUT_MINFRAGS;
 
-       if (buffer->numfrags * buffer->fragment_size > WAVEOUT_MAXBUFSIZE) {
+       if (buffer->numfrags * buffer->fragment_size > WAVEOUT_MAXBUFSIZE)
                buffer->numfrags = WAVEOUT_MAXBUFSIZE / buffer->fragment_size;
 
-               if (buffer->numfrags < MINFRAGS) {
-                       buffer->numfrags = MINFRAGS;
-                       buffer->fragment_size = WAVEOUT_MAXBUFSIZE / MINFRAGS;
-               }
-
-       } else if (buffer->numfrags * buffer->fragment_size < WAVEOUT_MINBUFSIZE)
-               buffer->numfrags = WAVEOUT_MINBUFSIZE / buffer->fragment_size;
+       if (buffer->numfrags < WAVEOUT_MINFRAGS)
+               BUG();
 
        buffer->size = buffer->fragment_size * buffer->numfrags;
        buffer->pages = buffer->size / PAGE_SIZE + ((buffer->size % PAGE_SIZE) ? 1 : 0);
@@ -1436,24 +1429,29 @@ static void calculate_ifrag(struct wiinst *wiinst)
 
        buffer->fragment_size = 1 << buffer->ossfragshift;
 
+       while (buffer->fragment_size * WAVEIN_MINFRAGS > WAVEIN_MAXBUFSIZE)
+               buffer->fragment_size >>= 1;
+
+       /* now we are sure that:
+          (2^WAVEIN_MINFRAGSHIFT) <= (fragment_size = 2^n) <= (WAVEIN_MAXBUFSIZE / WAVEIN_MINFRAGS)
+        */
+
+
        if (!buffer->numfrags)
                buffer->numfrags = (wiinst->format.bytespersec * WAVEIN_DEFAULTBUFLEN) / (buffer->fragment_size * 1000) - 1;
 
-       if (buffer->numfrags < MINFRAGS)
-               buffer->numfrags = MINFRAGS;
+       if (buffer->numfrags < WAVEIN_MINFRAGS)
+               buffer->numfrags = WAVEIN_MINFRAGS;
 
-       if (buffer->numfrags * buffer->fragment_size > WAVEIN_MAXBUFSIZE) {
+       if (buffer->numfrags * buffer->fragment_size > WAVEIN_MAXBUFSIZE)
                buffer->numfrags = WAVEIN_MAXBUFSIZE / buffer->fragment_size;
 
-               if (buffer->numfrags < MINFRAGS) {
-                       buffer->numfrags = MINFRAGS;
-                       buffer->fragment_size = WAVEIN_MAXBUFSIZE / MINFRAGS;
-               }
-       } else if (buffer->numfrags * buffer->fragment_size < WAVEIN_MINBUFSIZE)
-               buffer->numfrags = WAVEIN_MINBUFSIZE / buffer->fragment_size;
+       if (buffer->numfrags < WAVEIN_MINFRAGS)
+               BUG();
 
        bufsize = buffer->fragment_size * buffer->numfrags;
 
+       /* the buffer size for recording is restricted to certain values, adjust it now */
        if (bufsize >= 0x10000) {
                buffer->size = 0x10000;
                buffer->sizeregval = 0x1f;
@@ -1479,10 +1477,12 @@ static void calculate_ifrag(struct wiinst *wiinst)
                }
        }
 
+       /* adjust the fragment size so that buffer size is an integer multiple */
+       while (buffer->size % buffer->fragment_size)
+               buffer->fragment_size >>= 1;
+
        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);
index 2f0464c211a0448f5456b70b39471c31ddda1135..5b2f104780ac163dbce38895fe82a56dbda24703 100644 (file)
@@ -33,8 +33,6 @@
 #ifndef _AUDIO_H
 #define _AUDIO_H
 
-#define MINFRAGS       2       /* _don't_ got bellow 2 */
-
 struct emu10k1_wavedevice
 {
         struct emu10k1_card *card;
index a3e7e4b57c30d2a70ab26ee082099e765f92d5ad..552d2112509fa06808a2cedbafe941e1df707cee 100644 (file)
@@ -96,6 +96,7 @@ void query_format(int recsrc, struct wave_format *wave_fmt)
        wave_fmt->bytesperchannel = wave_fmt->bitsperchannel >> 3;
        wave_fmt->bytespersample = wave_fmt->channels * wave_fmt->bytesperchannel;
        wave_fmt->bytespersec = wave_fmt->bytespersample * wave_fmt->samplingrate;
+       wave_fmt->bytespervoicesample = wave_fmt->bytespersample;
 }
 
 static int alloc_buffer(struct emu10k1_card *card, struct wavein_buffer *buffer)
@@ -120,7 +121,7 @@ int emu10k1_wavein_open(struct emu10k1_wavedevice *wave_dev)
        struct emu10k1_card *card = wave_dev->card;
        struct wiinst *wiinst = wave_dev->wiinst;
        struct wiinst **wiinst_tmp = NULL;
-       u32 delay;
+       u16 delay;
        unsigned long flags;
 
        DPF(2, "emu10k1_wavein_open()\n");
@@ -169,6 +170,12 @@ int emu10k1_wavein_open(struct emu10k1_wavedevice *wave_dev)
 
        emu10k1_set_record_src(card, wiinst);
 
+       emu10k1_reset_record(card, &wiinst->buffer);
+
+       wiinst->buffer.hw_pos = 0;
+       wiinst->buffer.pos = 0;
+       wiinst->buffer.bytestocopy = 0;
+
        delay = (48000 * wiinst->buffer.fragment_size) / wiinst->format.bytespersec;
 
        emu10k1_timer_install(card, &wiinst->timer, delay / 2);
@@ -222,10 +229,6 @@ void emu10k1_wavein_start(struct emu10k1_wavedevice *wave_dev)
        emu10k1_start_record(card, &wiinst->buffer);
        emu10k1_timer_enable(wave_dev->card, &wiinst->timer);
 
-       wiinst->buffer.hw_pos = 0;
-       wiinst->buffer.pos = 0;
-       wiinst->buffer.bytestocopy = 0;
-
        wiinst->state |= WAVE_STATE_STARTED;
 }
 
@@ -249,7 +252,7 @@ int emu10k1_wavein_setformat(struct emu10k1_wavedevice *wave_dev, struct wave_fo
 {
        struct emu10k1_card *card = wave_dev->card;
        struct wiinst *wiinst = wave_dev->wiinst;
-       u32 delay;
+       u16 delay;
 
        DPF(2, "emu10k1_wavein_setformat()\n");
 
@@ -304,10 +307,9 @@ void emu10k1_wavein_getxfersize(struct wiinst *wiinst, u32 * size)
 
 static void copy_block(u8 *dst, u8 * src, u32 str, u32 len, u8 cov)
 {
-       if (cov == 1) {
-               if (__copy_to_user(dst, src + str, len))
-                       return;
-       } else {
+       if (cov == 1)
+               __copy_to_user(dst, src + str, len);
+       else {
                u8 byte;
                u32 i;
 
@@ -315,8 +317,7 @@ static void copy_block(u8 *dst, u8 * src, u32 str, u32 len, u8 cov)
 
                for (i = 0; i < len; i++) {
                        byte = src[2 * i] ^ 0x80;
-                       if (__copy_to_user(dst + i, &byte, 1))
-                               return;
+                       __copy_to_user(dst + i, &byte, 1);
                }
        }
 }
index 525493c3a4e4835c94352b20e60ede51d11122f8..c08e53b0e5908ec8e7ac266d49408c04593c98a1 100644 (file)
@@ -69,13 +69,14 @@ struct wiinst
        u16 fxwc;
 };
 
-#define WAVEIN_MAXBUFSIZE         65536
-#define WAVEIN_MINBUFSIZE        368
+#define WAVEIN_MAXBUFSIZE      65536
+#define WAVEIN_MINBUFSIZE      368
 
-#define WAVEIN_DEFAULTFRAGLEN     100 
-#define WAVEIN_DEFAULTBUFLEN      1000
+#define WAVEIN_DEFAULTFRAGLEN  100 
+#define WAVEIN_DEFAULTBUFLEN   1000
 
-#define WAVEIN_MINFRAGSHIFT      8 
+#define WAVEIN_MINFRAGSHIFT    8 
+#define WAVEIN_MINFRAGS                2
 
 int emu10k1_wavein_open(struct emu10k1_wavedevice *);
 void emu10k1_wavein_close(struct emu10k1_wavedevice *);
index 006e1fb935593529ffcbdc01de5ab20e9486598c..f8ecc39de26f22224725d051b869c94feb1300db 100644 (file)
@@ -108,95 +108,20 @@ static void query_format(struct emu10k1_wavedevice *wave_dev, struct wave_format
        }
 
        wave_fmt->bytesperchannel = wave_fmt->bitsperchannel >> 3;
+       wave_fmt->bytespersample = wave_fmt->channels * wave_fmt->bytesperchannel;
+       wave_fmt->bytespersec = wave_fmt->bytespersample * wave_fmt->samplingrate;
 
        if (wave_fmt->channels == 2)
                wave_fmt->bytespervoicesample = wave_fmt->channels * wave_fmt->bytesperchannel;
        else
                wave_fmt->bytespervoicesample = wave_fmt->bytesperchannel;
-
-       wave_fmt->bytespersample = wave_fmt->channels * wave_fmt->bytesperchannel;
-       wave_fmt->bytespersec = wave_fmt->bytespersample * wave_fmt->samplingrate;
-}
-
-/**
- * alloc_buffer -
- *
- * allocates the memory buffer for a voice. Two page tables are kept for each buffer.
- * One (dma_handle) keeps track of the host memory pages used and the other (virtualpagetable)
- * is passed to the device so that it can do DMA to host memory. 
- *
- */
-static int alloc_buffer(struct emu10k1_card *card, struct waveout_buffer *buffer, unsigned int voicenum)
-{
-       u32 pageindex, pagecount;
-       unsigned long busaddx;
-       int i;
-
-       DPD(2, "requested pages is: %d\n", buffer->pages);
-
-       if ((buffer->mem[voicenum].emupageindex =
-        emu10k1_addxmgr_alloc(buffer->pages * PAGE_SIZE, card)) < 0)
-               return -1;
-
-       /* Fill in virtual memory table */
-       for (pagecount = 0; pagecount < buffer->pages; pagecount++) {
-               if ((buffer->mem[voicenum].addr[pagecount] =
-                pci_alloc_consistent(card->pci_dev, PAGE_SIZE,
-                &buffer->mem[voicenum].dma_handle[pagecount])) == NULL) {
-                       buffer->pages = pagecount;
-                       return -1;
-               }
-
-               DPD(2, "Virtual Addx: %p\n", buffer->mem[voicenum].addr[pagecount]);
-
-               for (i = 0; i < PAGE_SIZE / EMUPAGESIZE; i++) {
-                       busaddx = buffer->mem[voicenum].dma_handle[pagecount] + i * EMUPAGESIZE;
-
-                       DPD(3, "Bus Addx: %#lx\n", busaddx);
-
-                       pageindex = buffer->mem[voicenum].emupageindex + pagecount * PAGE_SIZE / EMUPAGESIZE + i;
-
-                       ((u32 *) card->virtualpagetable.addr)[pageindex] = cpu_to_le32((busaddx * 2) | pageindex);
-               }
-       }
-
-       return 0;
-}
-
-/**
- * free_buffer -
- *
- * frees the memory buffer for a voice.
- */
-static void free_buffer(struct emu10k1_card *card, struct waveout_buffer *buffer, unsigned int voicenum)
-{
-       u32 pagecount, pageindex;
-       int i;
-
-       if (buffer->mem[voicenum].emupageindex < 0)
-               return;
-
-       for (pagecount = 0; pagecount < buffer->pages; pagecount++) {
-               pci_free_consistent(card->pci_dev, PAGE_SIZE,
-                buffer->mem[voicenum].addr[pagecount],
-                buffer->mem[voicenum].dma_handle[pagecount]);
-
-               for (i = 0; i < PAGE_SIZE / EMUPAGESIZE; i++) {
-                       pageindex = buffer->mem[voicenum].emupageindex + pagecount * PAGE_SIZE / EMUPAGESIZE + i;
-                       ((u32 *) card->virtualpagetable.addr)[pageindex] =
-                        cpu_to_le32((card->silentpage.dma_handle * 2) | pageindex);
-               }
-       }
-
-       emu10k1_addxmgr_free(card, buffer->mem[voicenum].emupageindex);
-       buffer->mem[voicenum].emupageindex = -1;
 }
 
 static int get_voice(struct emu10k1_card *card, struct woinst *woinst, unsigned int voicenum)
 {
        struct emu_voice *voice = &woinst->voice[voicenum];
-       /* Allocate voices here, if no voices available, return error.
-        * Init voice_allocdesc first.*/
+
+       /* Allocate voices here, if no voices available, return error. */
 
        voice->usage = VOICE_USAGE_PLAYBACK;
 
@@ -219,7 +144,7 @@ static int get_voice(struct emu10k1_card *card, struct woinst *woinst, unsigned
 
        DPD(2, "Initial pitch --> %#x\n", voice->initial_pitch);
 
-       voice->startloop = (woinst->buffer.mem[voicenum].emupageindex << 12) /
+       voice->startloop = (voice->mem.emupageindex << 12) /
         woinst->format.bytespervoicesample;
        voice->endloop = voice->startloop + woinst->buffer.size / woinst->format.bytespervoicesample;
        voice->start = voice->startloop;
@@ -297,12 +222,12 @@ int emu10k1_waveout_open(struct emu10k1_wavedevice *wave_dev)
        struct woinst *woinst = wave_dev->woinst;
        struct waveout_buffer *buffer = &woinst->buffer;
        unsigned int voicenum;
-       u32 delay;
+       u16 delay;
 
        DPF(2, "emu10k1_waveout_open()\n");
 
        for (voicenum = 0; voicenum < woinst->num_voices; voicenum++) {
-               if (alloc_buffer(card, buffer, voicenum) < 0) {
+               if (emu10k1_voice_alloc_buffer(card, &woinst->voice[voicenum].mem, woinst->buffer.pages) < 0) {
                        ERROR();
                        emu10k1_waveout_close(wave_dev);
                        return -1;
@@ -324,7 +249,7 @@ int emu10k1_waveout_open(struct emu10k1_wavedevice *wave_dev)
        delay = (48000 * woinst->buffer.fragment_size) /
                 (woinst->format.samplingrate * woinst->format.bytespervoicesample);
 
-       emu10k1_timer_install(card, &woinst->timer, delay / 2);
+       emu10k1_timer_install(card, &woinst->timer, delay);
 
        woinst->state = WAVE_STATE_OPEN;
 
@@ -345,7 +270,7 @@ void emu10k1_waveout_close(struct emu10k1_wavedevice *wave_dev)
 
        for (voicenum = 0; voicenum < woinst->num_voices; voicenum++) {
                emu10k1_voice_free(&woinst->voice[voicenum]);
-               free_buffer(card, &woinst->buffer, voicenum);
+               emu10k1_voice_free_buffer(card, &woinst->voice[voicenum].mem);
        }
 
        woinst->state = WAVE_STATE_CLOSED;
@@ -371,7 +296,7 @@ int emu10k1_waveout_setformat(struct emu10k1_wavedevice *wave_dev, struct wave_f
        struct emu10k1_card *card = wave_dev->card;
        struct woinst *woinst = wave_dev->woinst;
        unsigned int voicenum;
-       u32 delay;
+       u16 delay;
 
        DPF(2, "emu10k1_waveout_setformat()\n");
 
@@ -404,7 +329,7 @@ int emu10k1_waveout_setformat(struct emu10k1_wavedevice *wave_dev, struct wave_f
                delay = (48000 * woinst->buffer.fragment_size) /
                         (woinst->format.samplingrate * woinst->format.bytespervoicesample);
 
-               emu10k1_timer_install(card, &woinst->timer, delay / 2);
+               emu10k1_timer_install(card, &woinst->timer, delay);
        }
 
        return 0;
@@ -449,7 +374,7 @@ void emu10k1_waveout_getxfersize(struct woinst *woinst, u32 *total_free_bytes)
 
        pending_bytes = buffer->size - buffer->free_bytes;
 
-       buffer->fill_silence = (pending_bytes < (signed) buffer->fragment_size) ? 1 : 0;
+       buffer->fill_silence = (pending_bytes < (signed) buffer->fragment_size * 2) ? 1 : 0;
 
        if (pending_bytes > (signed) buffer->silence_bytes) {
                *total_free_bytes = (buffer->free_bytes + buffer->silence_bytes);
@@ -483,17 +408,14 @@ static void copy_block(void **dst, u32 str, u8 *src, u32 len)
 
        if (len > PAGE_SIZE - pgoff) {
                k = PAGE_SIZE - pgoff;
-               if (__copy_from_user((u8 *)dst[pg] + pgoff, src, k))
-                       return;
+               __copy_from_user((u8 *)dst[pg] + pgoff, src, k);
                len -= k;
                while (len > PAGE_SIZE) {
-                       if (__copy_from_user(dst[++pg], src + k, PAGE_SIZE))
-                               return;
+                       __copy_from_user(dst[++pg], src + k, PAGE_SIZE);
                        k += PAGE_SIZE;
                        len -= PAGE_SIZE;
                }
-               if (__copy_from_user(dst[++pg], src + k, len))
-                       return;
+               __copy_from_user(dst[++pg], src + k, len);
 
        } else
                __copy_from_user((u8 *)dst[pg] + pgoff, src, len);
@@ -511,15 +433,14 @@ static void copy_ilv_block(struct woinst *woinst, u32 str, u8 *src, u32 len)
         unsigned int pg;
        unsigned int pgoff;
        unsigned int voice_num;
-       struct waveout_mem *mem = woinst->buffer.mem;
+       struct emu_voice *voice = woinst->voice;
 
        pg = str / PAGE_SIZE;
        pgoff = str % PAGE_SIZE;
 
        while (len) { 
                for (voice_num = 0; voice_num < woinst->num_voices; voice_num++) {
-                       if (__copy_from_user((u8 *)(mem[voice_num].addr[pg]) + pgoff, src, woinst->format.bytespervoicesample))
-                               return;
+                       __copy_from_user((u8 *)(voice[voice_num].mem.addr[pg]) + pgoff, src, woinst->format.bytespervoicesample);
                        src += woinst->format.bytespervoicesample;
                }
 
@@ -544,7 +465,7 @@ static void fill_block(struct woinst *woinst, u32 str, u8 data, u32 len)
        unsigned int pg;
        unsigned int pgoff;
        unsigned int voice_num;
-        struct waveout_mem *mem = woinst->buffer.mem;
+        struct emu_voice *voice = woinst->voice;
        unsigned int  k;
 
        pg = str / PAGE_SIZE;
@@ -553,22 +474,22 @@ static void fill_block(struct woinst *woinst, u32 str, u8 data, u32 len)
        if (len > PAGE_SIZE - pgoff) {
                k = PAGE_SIZE - pgoff;
                for (voice_num = 0; voice_num < woinst->num_voices; voice_num++)
-                       memset((u8 *)mem[voice_num].addr[pg] + pgoff, data, k);
+                       memset((u8 *)voice[voice_num].mem.addr[pg] + pgoff, data, k);
                len -= k;
                while (len > PAGE_SIZE) {
                        pg++;
                        for (voice_num = 0; voice_num < woinst->num_voices; voice_num++)
-                               memset(mem[voice_num].addr[pg], data, PAGE_SIZE);
+                               memset(voice[voice_num].mem.addr[pg], data, PAGE_SIZE);
 
                        len -= PAGE_SIZE;
                }
                pg++;
                for (voice_num = 0; voice_num < woinst->num_voices; voice_num++)
-                       memset(mem[voice_num].addr[pg], data, len);
+                       memset(voice[voice_num].mem.addr[pg], data, len);
 
        } else {
                for (voice_num = 0; voice_num < woinst->num_voices; voice_num++)
-                       memset((u8 *)mem[voice_num].addr[pg] + pgoff, data, len);
+                       memset((u8 *)voice[voice_num].mem.addr[pg] + pgoff, data, len);
        }
 }
 
@@ -582,6 +503,7 @@ static void fill_block(struct woinst *woinst, u32 str, u8 data, u32 len)
 void emu10k1_waveout_xferdata(struct woinst *woinst, u8 *data, u32 *size)
 {
        struct waveout_buffer *buffer = &woinst->buffer;
+       struct voice_mem *mem = &woinst->voice[0].mem;
        u32 sizetocopy, sizetocopy_now, start;
        unsigned long flags;
 
@@ -610,14 +532,14 @@ void emu10k1_waveout_xferdata(struct woinst *woinst, u8 *data, u32 *size)
                        copy_ilv_block(woinst, start, data, sizetocopy_now);
                        copy_ilv_block(woinst, 0, data + sizetocopy_now * woinst->num_voices, sizetocopy);
                } else {
-                       copy_block(buffer->mem[0].addr, start, data, sizetocopy_now);
-                       copy_block(buffer->mem[0].addr, 0, data + sizetocopy_now, sizetocopy);
+                       copy_block(mem->addr, start, data, sizetocopy_now);
+                       copy_block(mem->addr, 0, data + sizetocopy_now, sizetocopy);
                }
        } else {
                if (woinst->num_voices > 1)
                        copy_ilv_block(woinst, start, data, sizetocopy);
                else
-                       copy_block(buffer->mem[0].addr, start, data, sizetocopy);
+                       copy_block(mem->addr, start, data, sizetocopy);
        }
 }
 
@@ -674,7 +596,7 @@ void emu10k1_waveout_update(struct woinst *woinst)
 {
        u32 hw_pos;
        u32 diff;
-       
+
        /* There is no actual start yet */
        if (!(woinst->state & WAVE_STATE_STARTED)) {
                hw_pos = woinst->buffer.hw_pos;
index b68139fbfa607d8d520e76a1d2c21bd68b1cbf9a..70eb9a3f7cd32b2776c5ad2748bbe5902cfd69cb 100644 (file)
 
 /* setting this to other than a power of two may break some applications */
 #define WAVEOUT_MAXBUFSIZE     MAXBUFSIZE
-#define WAVEOUT_MINBUFSIZE     64
 
 #define WAVEOUT_DEFAULTFRAGLEN 20 /* Time to play a fragment in ms (latency) */
 #define WAVEOUT_DEFAULTBUFLEN  500 /* Time to play the entire buffer in ms */
 
-#define WAVEOUT_MINFRAGSHIFT   6
-#define WAVEOUT_MAXVOICES 6
-
-/* waveout_mem is cardwo internal */
-struct waveout_mem {
-       int emupageindex;
-       void *addr[BUFMAXPAGES];
-       dma_addr_t dma_handle[BUFMAXPAGES];
-};
+#define WAVEOUT_MINFRAGSHIFT   6 /* Minimum fragment size in bytes is 2^6 */
+#define WAVEOUT_MINFRAGS       3 /* _don't_ go bellow 3, it would break silence filling */
+#define WAVEOUT_MAXVOICES      6
 
 struct waveout_buffer {
        u16 ossfragshift;
@@ -60,7 +53,6 @@ struct waveout_buffer {
        u32 fragment_size;      /* in bytes units */
        u32 size;               /* in bytes units */
        u32 pages;              /* buffer size in page units*/
-       struct waveout_mem mem[WAVEOUT_MAXVOICES];
        u32 silence_pos;        /* software cursor position (including silence bytes) */
        u32 hw_pos;             /* hardware cursor position */
        u32 free_bytes;         /* free bytes available on the buffer (not including silence bytes) */
index 8eac2edb259f2bdded27325de321f88b315fea9a..b8352613cb0a52c2f812d40a0798aedb3f8eb59e 100644 (file)
@@ -38,7 +38,7 @@ int emu10k1_find_control_gpr(struct patch_manager *mgr, const char *patch_name,
         struct dsp_patch *patch;
        struct dsp_rpatch *rpatch;
        char s[PATCH_NAME_SIZE + 4];
-       u32 *gpr_used;
+       unsigned long *gpr_used;
        int i;
 
        DPD(2, "emu10k1_find_control_gpr(): %s %s\n", patch_name, gpr_name);
@@ -103,7 +103,7 @@ void emu10k1_set_oss_vol(struct emu10k1_card *card, int oss_mixer,
 
        card->ac97.mixer_state[oss_mixer] = (right << 8) | left;
 
-       if (!card->isaps)
+       if (!card->is_aps)
                card->ac97.write_mixer(&card->ac97, oss_mixer, left, right);
        
        emu10k1_set_volume_gpr(card, card->mgr.ctrl_gpr[oss_mixer][0], left,
@@ -171,9 +171,8 @@ void emu10k1_set_volume_gpr(struct emu10k1_card *card, int addr, s32 vol, int sc
 {
        struct patch_manager *mgr = &card->mgr;
        unsigned long flags;
-       int muting;
 
-       const s32 log2lin[5] ={                  //  attenuation (dB)
+       static const s32 log2lin[4] ={           //  attenuation (dB)
                0x7fffffff,                      //       0.0         
                0x7fffffff * 0.840896415253715 , //       1.5          
                0x7fffffff * 0.707106781186548,  //       3.0
@@ -183,12 +182,10 @@ void emu10k1_set_volume_gpr(struct emu10k1_card *card, int addr, s32 vol, int sc
        if (addr < 0)
                return;
 
-       muting = (scale == 0x10) ? 0x7f: scale;
-       
        vol = (100 - vol ) * scale / 100;
 
        // Thanks to the comp.dsp newsgroup for this neat trick:
-       vol = (vol >= muting) ? 0 : (log2lin[vol & 3] >> (vol >> 2));
+       vol = (vol >= scale) ? 0 : (log2lin[vol & 3] >> (vol >> 2));
 
        spin_lock_irqsave(&mgr->lock, flags);
        emu10k1_set_control_gpr(card, addr, vol, 0);
index a9e32792c30453b81334714ef981ad9a7335f12d..59abc8af7754db1606a9001c80c9ee4578357332 100644 (file)
@@ -35,9 +35,9 @@
 #define WRITE_EFX(a, b, c) sblive_writeptr((a), MICROCODEBASE + (b), 0, (c))
 
 #define OP(op, z, w, x, y) \
-        do { WRITE_EFX(card, (pc) * 2, ((x) << 10) | (y)); \
-        WRITE_EFX(card, (pc) * 2 + 1, ((op) << 20) | ((z) << 10) | (w)); \
-        ++pc; } while (0)
+       do { WRITE_EFX(card, (pc) * 2, ((x) << 10) | (y)); \
+       WRITE_EFX(card, (pc) * 2 + 1, ((op) << 20) | ((z) << 10) | (w)); \
+       ++pc; } while (0)
 
 #define NUM_INPUTS 0x20
 #define NUM_OUTPUTS 0x20
 
 struct dsp_rpatch {
        char name[PATCH_NAME_SIZE];
-        u16 code_start;
-        u16 code_size;
+       u16 code_start;
+       u16 code_size;
 
-        u32 gpr_used[NUM_GPRS / 32];
-        u32 gpr_input[NUM_GPRS / 32];
-        u32 route[NUM_OUTPUTS];
-        u32 route_v[NUM_OUTPUTS];
+       unsigned long gpr_used[NUM_GPRS / (sizeof(unsigned long) * 8) + 1];
+       unsigned long gpr_input[NUM_GPRS / (sizeof(unsigned long) * 8) + 1];
+       unsigned long route[NUM_OUTPUTS];
+       unsigned long route_v[NUM_OUTPUTS];
 };
 
 struct dsp_patch {
-        char name[PATCH_NAME_SIZE];
-        u8 id;
-        u32 input;                      /* bitmap of the lines used as inputs */
-       u32 output;                     /* bitmap of the lines used as outputs */
-        u16 code_start;
-        u16 code_size;
-
-        u32 gpr_used[NUM_GPRS / 32];    /* bitmap of used gprs */
-        u32 gpr_input[NUM_GPRS / 32];
-        u8 traml_istart;  /* starting address of the internal tram lines used */
-        u8 traml_isize;   /* number of internal tram lines used */
-
-        u8 traml_estart;
-        u8 traml_esize;
-
-        u16 tramb_istart;        /* starting address of the internal tram memory used */
-        u16 tramb_isize;         /* amount of internal memory used */
-        u32 tramb_estart;
-        u32 tramb_esize;
+       char name[PATCH_NAME_SIZE];
+       u8 id;
+       unsigned long input;    /* bitmap of the lines used as inputs */
+       unsigned long output;   /* bitmap of the lines used as outputs */
+       u16 code_start;
+       u16 code_size;
+
+       unsigned long gpr_used[NUM_GPRS / (sizeof(unsigned long) * 8) + 1];     /* bitmap of used gprs */
+       unsigned long gpr_input[NUM_GPRS / (sizeof(unsigned long) * 8) + 1];
+       u8 traml_istart;        /* starting address of the internal tram lines used */
+       u8 traml_isize;         /* number of internal tram lines used */
+
+       u8 traml_estart;
+       u8 traml_esize;
+
+       u16 tramb_istart;        /* starting address of the internal tram memory used */
+       u16 tramb_isize;         /* amount of internal memory used */
+       u32 tramb_estart;
+       u32 tramb_esize;
 };
 
 struct dsp_gpr {
-        u8 type;                      /* gpr type, STATIC, DYNAMIC, INPUT, OUTPUT, CONTROL */
-        char name[GPR_NAME_SIZE];       /* gpr value, only valid for control gprs */
-        s32 min, max;         /* value range for this gpr, only valid for control gprs */
-        u8 line;                    /* which input/output line is the gpr attached, only valid for input/output gprs */
-        u8 usage;
+       u8 type;                        /* gpr type, STATIC, DYNAMIC, INPUT, OUTPUT, CONTROL */
+       char name[GPR_NAME_SIZE];       /* gpr value, only valid for control gprs */
+       s32 min, max;                   /* value range for this gpr, only valid for control gprs */
+       u8 line;                        /* which input/output line is the gpr attached, only valid for input/output gprs */
+       u8 usage;
 };
 
 enum {
-        GPR_TYPE_NULL = 0,
-        GPR_TYPE_IO,
-        GPR_TYPE_STATIC,
-        GPR_TYPE_DYNAMIC,
-        GPR_TYPE_CONTROL,
-        GPR_TYPE_CONSTANT
+       GPR_TYPE_NULL = 0,
+       GPR_TYPE_IO,
+       GPR_TYPE_STATIC,
+       GPR_TYPE_DYNAMIC,
+       GPR_TYPE_CONTROL,
+       GPR_TYPE_CONSTANT
 };
 
 #define GPR_BASE 0x100
@@ -101,15 +101,14 @@ enum {
 #define MAX_PATCHES_PAGES 32
 
 struct patch_manager {
-        void *patch[MAX_PATCHES_PAGES];
+       void *patch[MAX_PATCHES_PAGES];
        int current_pages;
-        struct dsp_rpatch rpatch;
-        struct dsp_gpr gpr[NUM_GPRS];   /* gpr usage table */
+       struct dsp_rpatch rpatch;
+       struct dsp_gpr gpr[NUM_GPRS];   /* gpr usage table */
        spinlock_t lock;
        s16 ctrl_gpr[SOUND_MIXER_NRDEVICES][2];
 };
 
-
 #define PATCHES_PER_PAGE (PAGE_SIZE / sizeof(struct dsp_patch))
 
 #define PATCH(mgr, i) ((struct dsp_patch *) (mgr)->patch[(i) / PATCHES_PER_PAGE] + (i) % PATCHES_PER_PAGE)
index ca51bf2393678d75bfc30ab28149eab33f972956..04f6a9a43cf1f563042a14a46417f317bd3fdc51 100644 (file)
@@ -187,6 +187,15 @@ u32 emu10k1_readfn0(struct emu10k1_card * card, u32 reg)
        }
 }
 
+void emu10k1_timer_set(struct emu10k1_card * card, u16 data)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&card->lock, flags);
+       outw(data & TIMER_RATE_MASK, card->iobase + TIMER);
+       spin_unlock_irqrestore(&card->lock, flags);
+}
+
 /************************************************************************
 * write/read Emu10k1 pointer-offset register set, accessed through      *
 *  the PTR and DATA registers                                           *
index d7a78565ec869ae3bb3c5b7b91ba29ab93338b07..fde1fd44ce06c0a950b3dc1ed0d12dd83b339677 100644 (file)
@@ -126,6 +126,7 @@ struct mixer_private_ioctl {
 #define CMD_SETMCH_FX          _IOW('D', 17, struct mixer_private_ioctl)
 #define CMD_SETPASSTHROUGH     _IOW('D', 18, struct mixer_private_ioctl)
 #define CMD_PRIVATE3_VERSION   _IOW('D', 19, struct mixer_private_ioctl)
+#define CMD_AC97_BOOST         _IOW('D', 20, struct mixer_private_ioctl)
 
 //up this number when breaking compatibility
 #define PRIVATE3_VERSION 1
@@ -144,7 +145,7 @@ struct emu10k1_card
        u16                     emupagetable[MAXPAGES];
 
        struct list_head        timers;
-       unsigned                timer_delay;
+       u16                     timer_delay;
        spinlock_t              timer_lock;
 
        struct pci_dev          *pci_dev;
@@ -181,7 +182,7 @@ struct emu10k1_card
 
        u8 chiprev;                    /* Chip revision                */
 
-       int isaps;
+       u8 is_aps;
 
        struct patch_manager mgr;
        struct pt_data pt;
@@ -190,8 +191,6 @@ struct emu10k1_card
 int emu10k1_addxmgr_alloc(u32, struct emu10k1_card *);
 void emu10k1_addxmgr_free(struct emu10k1_card *, int);
 
-
-
 int emu10k1_find_control_gpr(struct patch_manager *, const char *, const char *);
 void emu10k1_set_control_gpr(struct emu10k1_card *, int , s32, int );
 
@@ -211,12 +210,14 @@ extern struct list_head emu10k1_devs;
 
 /* Hardware Abstraction Layer access functions */
 
-void emu10k1_writefn0(struct emu10k1_card *, u32 , u32 );
-u32 emu10k1_readfn0(struct emu10k1_card *, u32 );
+void emu10k1_writefn0(struct emu10k1_card *, u32, u32);
+u32 emu10k1_readfn0(struct emu10k1_card *, u32);
+
+void emu10k1_timer_set(struct emu10k1_card *, u16);
 
-void sblive_writeptr(struct emu10k1_card *, u32 , u32 , u32 );
-void sblive_writeptr_tag(struct emu10k1_card *card, u32 channel, ...);
-#define TAGLIST_END 0
+void sblive_writeptr(struct emu10k1_card *, u32, u32, u32);
+void sblive_writeptr_tag(struct emu10k1_card *, u32, ...);
+#define TAGLIST_END    0
 
 u32 sblive_readptr(struct emu10k1_card *, u32 , u32 );
 
index bbbd59d589e03256f603698cbcbc34bea8567e8a..876216a796992ad78b787c508b3f9c696dfc2e7d 100644 (file)
@@ -1,4 +1,3 @@
-
 /*
  **********************************************************************
  *     irqmgr.c - IRQ manager for emu10k1 driver
@@ -41,7 +40,7 @@
 void emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
        struct emu10k1_card *card = (struct emu10k1_card *) dev_id;
-       u32 irqstatus;
+       u32 irqstatus, irqstatus_tmp;
 
        DPD(4, "emu10k1_interrupt called, irq =  %u\n", irq);
 
@@ -60,8 +59,7 @@ void emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
        while ((irqstatus = inl(card->iobase + IPR))) {
                DPD(4, "irq status %#x\n", irqstatus);
 
-               /* acknowledge interrupt */
-               outl(irqstatus, card->iobase + IPR);
+               irqstatus_tmp = irqstatus;
 
                if (irqstatus & IRQTYPE_TIMER) {
                        emu10k1_timer_irqhandler(card);
@@ -98,7 +96,15 @@ void emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                        irqstatus &=~IPR_VOLDECR;
                }
 
-               if (irqstatus)
-                       emu10k1_irq_disable(card, irqstatus);
+               if (irqstatus){
+                       printk(KERN_ERR "emu10k1: Warning, unhandled interrupt: %#08x\n", irqstatus);
+                       //make sure any interrupts we don't handle are disabled:
+                       emu10k1_irq_disable(card, ~(INTE_MIDIRXENABLE | INTE_MIDITXENABLE | INTE_INTERVALTIMERENB |
+                                               INTE_VOLDECRENABLE | INTE_VOLINCRENABLE | INTE_MUTEENABLE |
+                                               INTE_FXDSPENABLE));
+               }
+
+               /* acknowledge interrupt */
+                outl(irqstatus_tmp, card->iobase + IPR);
        }
 }
index 69f192c8dce8462bec99a01a36f6383462b449d8..db02261f4ef3cf2eb76a9ee4dc5c780093e7f12a 100644 (file)
@@ -1,4 +1,4 @@
-/*
+ /*
  **********************************************************************
  *     main.c - Creative EMU10K1 audio driver
  *     Copyright 1999, 2000 Creative Labs, Inc.
  *     0.16 Mixer improvements, added old treble/bass support (Daniel Bertrand)
  *          Small code format cleanup.
  *          Deadlock bug fix for emu10k1_volxxx_irqhandler().
- *
+ *     0.17 Fix for mixer SOUND_MIXER_INFO ioctl.
+ *         Fix for HIGHMEM machines (emu10k1 can only do 31 bit bus master) 
+ *         midi poll initial implementation.
+ *         Small mixer fixes/cleanups.
+ *         Improved support for 5.1 cards.
+ *     0.18 Fix for possible leak in pci_alloc_consistent()
+ *          Cleaned up poll() functions (audio and midi). Don't start input.
+ *         Restrict DMA pages used to 512Mib range.
+ *         New AC97_BOOST mixer ioctl.
+ *     0.19 Real fix for kernel with highmem support (cast dma_handle to u32).
+ *         Fix recording buffering parameters calculation.
+ *         Use unsigned long for variables in bit ops.
+ *     0.20 Fixed recording startup
+ *         Fixed timer rate setting (it's a 16-bit register)
  *********************************************************************/
 
 /* These are only included once per module */
 #define SNDCARD_EMU10K1 46
 #endif
  
-#define DRIVER_VERSION "0.16"
+#define DRIVER_VERSION "0.20"
 
-/* FIXME: is this right? */
-/* does the card support 32 bit bus master?*/
-#define EMU10K1_DMA_MASK                0xffffffff     /* DMA buffer mask for pci_alloc_consist */
+/* the emu10k1 _seems_ to only supports 29 bit (512MiB) bit bus master */
+#define EMU10K1_DMA_MASK                0x1fffffff     /* DMA buffer mask for pci_alloc_consist */
 
 #ifndef PCI_VENDOR_ID_CREATIVE
 #define PCI_VENDOR_ID_CREATIVE 0x1102
@@ -188,7 +200,7 @@ static int __devinit emu10k1_audio_init(struct emu10k1_card *card)
 
        /* Assign default recording parameters */
        /* FIXME */
-       if(card->isaps)
+       if (card->is_aps)
                card->wavein.recsrc = WAVERECORD_FX;
        else
                card->wavein.recsrc = WAVERECORD_AC97;
@@ -211,6 +223,8 @@ static void __devinit emu10k1_audio_cleanup(struct emu10k1_card *card)
 static int __devinit emu10k1_mixer_init(struct emu10k1_card *card)
 {
        char s[32];
+
+       struct ac97_codec *codec = &card->ac97;
        card->ac97.dev_mixer = register_sound_mixer(&emu10k1_mixer_fops, -1);
        if (card->ac97.dev_mixer < 0) {
                printk(KERN_ERR "emu10k1: cannot register mixer device\n");
@@ -219,7 +233,7 @@ static int __devinit emu10k1_mixer_init(struct emu10k1_card *card)
 
        card->ac97.private_data = card;
 
-       if (!card->isaps) {
+       if (!card->is_aps) {
                card->ac97.id = 0;
                card->ac97.codec_read = emu10k1_ac97_read;
                card->ac97.codec_write = emu10k1_ac97_write;
@@ -228,11 +242,14 @@ static int __devinit emu10k1_mixer_init(struct emu10k1_card *card)
                        printk(KERN_ERR "emu10k1: unable to probe AC97 codec\n");
                        goto err_out;
                }
-               /* 5.1: Enable the additional AC97 Slots. If the emu10k1 version
-                       does not support this, it shouldn't do any harm */
-               sblive_writeptr(card, AC97SLOT, 0, AC97SLOT_CNTR | AC97SLOT_LFE);
+               /* 5.1: Enable the additional AC97 Slots and unmute extra channels on AC97 codec */
+               if (codec->codec_read(codec, AC97_EXTENDED_ID) & 0x0080){
+                       printk(KERN_INFO "emu10k1: SBLive! 5.1 card detected\n"); 
+                       sblive_writeptr(card, AC97SLOT, 0, AC97SLOT_CNTR | AC97SLOT_LFE);
+                       codec->codec_write(codec, AC97_SURROUND_MASTER, 0x0);
+               }
 
-               // Force 5bit
+               // Force 5bit:              
                //card->ac97.bit_resolution=5;
 
                if (!proc_mkdir ("driver/emu10k1", 0)) {
@@ -274,7 +291,7 @@ static void __devinit emu10k1_mixer_cleanup(struct emu10k1_card *card)
 {
        char s[32];
 
-       if (!card->isaps) {
+       if (!card->is_aps) {
                sprintf(s, "driver/emu10k1/%s/ac97", card->pci_dev->slot_name);
                remove_proc_entry(s, NULL);
 
@@ -586,15 +603,15 @@ static int __devinit fx_init(struct emu10k1_card *card)
        CONNECT(PCM1_IN_R, ANALOG_REAR_R);
 
        /* Digital In + PCM + AC97 In + MULTI_FRONT --> Digital out */
-       OP(6, 0x10b, 0x100, 0x102, 0x10c);
-       OP(6, 0x10b, 0x10b, 0x113, 0x40);
+       OP(6, 0x10a, 0x100, 0x102, 0x10c);
+       OP(6, 0x10a, 0x10a, 0x113, 0x40);
 
        CONNECT(MULTI_FRONT_L, DIGITAL_OUT_L);
        CONNECT(PCM_IN_L, DIGITAL_OUT_L);
        CONNECT(AC97_IN_L, DIGITAL_OUT_L);
        CONNECT(SPDIF_CD_L, DIGITAL_OUT_L);
 
-       OP(6, 0x10a, 0x101, 0x103, 0x10e);
+       OP(6, 0x10b, 0x101, 0x103, 0x10e);
        OP(6, 0x10b, 0x10b, 0x114, 0x40);
 
        CONNECT(MULTI_FRONT_R, DIGITAL_OUT_R);
@@ -768,7 +785,7 @@ static int __devinit hw_init(struct emu10k1_card *card)
                                    VTFT, 0xffff,
                                    CVCF, 0xffff,
                                    PTRX, 0,
-                                   CPF, 0,
+                                   //CPF, 0,
                                    CCR, 0,
 
                                    PSST, 0,
@@ -794,7 +811,9 @@ static int __devinit hw_init(struct emu10k1_card *card)
                                    ENVVOL, 0,
                                    ENVVAL, 0,
                                     TAGLIST_END);
+               sblive_writeptr(card, CPF, nCh, 0);
        }
+       
 
        /*
         ** Init to 0x02109204 :
@@ -852,19 +871,19 @@ static int __devinit hw_init(struct emu10k1_card *card)
        }
 
        for (pagecount = 0; pagecount < MAXPAGES; pagecount++)
-               ((u32 *) card->virtualpagetable.addr)[pagecount] = cpu_to_le32((card->silentpage.dma_handle * 2) | pagecount);
+               ((u32 *) card->virtualpagetable.addr)[pagecount] = cpu_to_le32(((u32) card->silentpage.dma_handle * 2) | pagecount);
 
        /* Init page table & tank memory base register */
        sblive_writeptr_tag(card, 0,
-                           PTB, card->virtualpagetable.dma_handle,
+                           PTB, (u32) card->virtualpagetable.dma_handle,
                            TCB, 0,
                            TCBS, 0,
                            TAGLIST_END);
 
        for (nCh = 0; nCh < NUM_G; nCh++) {
                sblive_writeptr_tag(card, nCh,
-                                   MAPA, MAP_PTI_MASK | (card->silentpage.dma_handle * 2),
-                                   MAPB, MAP_PTI_MASK | (card->silentpage.dma_handle * 2),
+                                   MAPA, MAP_PTI_MASK | ((u32) card->silentpage.dma_handle * 2),
+                                   MAPB, MAP_PTI_MASK | ((u32) card->silentpage.dma_handle * 2),
                                    TAGLIST_END);
        }
 
@@ -951,8 +970,9 @@ static void __devinit emu10k1_cleanup(struct emu10k1_card *card)
                                    VTFT, 0,
                                    CVCF, 0,
                                    PTRX, 0,
-                                   CPF, 0,
+                                   //CPF, 0,
                                    TAGLIST_END);
+               sblive_writeptr(card, CPF, ch, 0);
        }
 
        /* Disable audio and lock cache */
@@ -999,7 +1019,7 @@ static int __devinit emu10k1_probe(struct pci_dev *pci_dev, const struct pci_dev
        int ret;
 
        if (pci_set_dma_mask(pci_dev, EMU10K1_DMA_MASK)) {
-               printk(KERN_ERR "emu10k1: architecture does not support 32bit PCI busmaster DMA\n");
+               printk(KERN_ERR "emu10k1: architecture does not support 29bit PCI busmaster DMA\n");
                return -ENODEV;
        }
 
@@ -1038,12 +1058,12 @@ static int __devinit emu10k1_probe(struct pci_dev *pci_dev, const struct pci_dev
        pci_read_config_byte(pci_dev, PCI_REVISION_ID, &card->chiprev);
        pci_read_config_word(pci_dev, PCI_SUBSYSTEM_ID, &card->model);
 
-       printk(KERN_INFO "emu10k1: %s rev %d model 0x%x found, IO at 0x%04lx-0x%04lx, IRQ %d\n",
+       printk(KERN_INFO "emu10k1: %s rev %d model %#04x found, IO at %#04lx-%#04lx, IRQ %d\n",
                card_names[pci_id->driver_data], card->chiprev, card->model, card->iobase,
                card->iobase + card->length - 1, card->irq);
 
        pci_read_config_dword(pci_dev, PCI_SUBSYSTEM_VENDOR_ID, &subsysvid);
-       card->isaps = (subsysvid == EMU_APS_SUBID);
+       card->is_aps = (subsysvid == EMU_APS_SUBID);
 
        spin_lock_init(&card->lock);
        init_MUTEX(&card->open_sem);
@@ -1074,7 +1094,7 @@ static int __devinit emu10k1_probe(struct pci_dev *pci_dev, const struct pci_dev
                goto err_emu10k1_init;
        }
 
-       if (card->isaps)
+       if (card->is_aps)
                emu10k1_ecard_init(card);
 
        list_add(&card->list, &emu10k1_devs);
@@ -1119,7 +1139,7 @@ static void __devexit emu10k1_remove(struct pci_dev *pci_dev)
        pci_set_drvdata(pci_dev, NULL);
 }
 
-MODULE_AUTHOR("Bertrand Lee, Cai Ying. (Email to: emu10k1-devel@opensource.creative.com)");
+MODULE_AUTHOR("Bertrand Lee, Cai Ying. (Email to: emu10k1-devel@lists.sourceforge.net)");
 MODULE_DESCRIPTION("Creative EMU10K1 PCI Audio Driver v" DRIVER_VERSION "\nCopyright (C) 1999 Creative Technology Ltd.");
 MODULE_LICENSE("GPL");
 
index b67349ba47e1f32e358127df41b200288cd123c1..fbdd6a43a5f877954a9be0300c286c0a03ea790a 100644 (file)
@@ -29,8 +29,8 @@
  **********************************************************************
  */
 
-#define __NO_VERSION__
 #include <linux/module.h>
+#include <linux/poll.h>
 #include <linux/slab.h>
 #include <linux/version.h>
 #include <linux/sched.h>
@@ -371,8 +371,32 @@ static ssize_t emu10k1_midi_write(struct file *file, const char *buffer, size_t
 
 static unsigned int emu10k1_midi_poll(struct file *file, struct poll_table_struct *wait)
 {
+       struct emu10k1_mididevice *midi_dev = (struct emu10k1_mididevice *) file->private_data;
+       unsigned long flags;
+       unsigned int mask = 0;
+
        DPF(4, "emu10k1_midi_poll() called\n");
-       return 0;
+
+       if (file->f_mode & FMODE_WRITE)
+               poll_wait(file, &midi_dev->oWait, wait);
+
+       if (file->f_mode & FMODE_READ)
+               poll_wait(file, &midi_dev->iWait, wait);
+
+       spin_lock_irqsave(&midi_spinlock, flags);
+
+       if (file->f_mode & FMODE_WRITE)
+               mask |= POLLOUT | POLLWRNORM;
+
+       if (file->f_mode & FMODE_READ) {
+               if (midi_dev->mistate == MIDIIN_STATE_STARTED)
+                       if (midi_dev->icnt > 0)
+                               mask |= POLLIN | POLLRDNORM;
+       }
+
+       spin_unlock_irqrestore(&midi_spinlock, flags);
+
+       return mask;
 }
 
 int emu10k1_midi_callback(unsigned long msg, unsigned long refdata, unsigned long *pmsg)
index d8f82941746f989113ee217d5097a15421191801..e3590551cc94634ddc8412ab934a6ab04cdc884b 100644 (file)
@@ -30,7 +30,6 @@
  **********************************************************************
  */
 
-#define __NO_VERSION__         /* Kernel version only defined once */
 #include <linux/module.h>
 #include <linux/version.h>
 #include <asm/uaccess.h>
@@ -251,7 +250,7 @@ static int emu10k1_private_mixer(struct emu10k1_card *card, unsigned int cmd, un
                case CMD_SETRECSRC:
                        switch (ctl->val[0]) {
                        case WAVERECORD_AC97:
-                               if (card->isaps) {
+                               if (card->is_aps) {
                                        ret = -EINVAL;
                                        break;
                                }
@@ -444,6 +443,7 @@ static int emu10k1_private_mixer(struct emu10k1_card *card, unsigned int cmd, un
 
                case CMD_SETGPR2OSS:
                        id = ctl->val[0];
+                       /* 0 == left, 1 == right */
                        ch = ctl->val[1];
                        addr = ctl->val[2];
 
@@ -454,19 +454,19 @@ static int emu10k1_private_mixer(struct emu10k1_card *card, unsigned int cmd, un
 
                        card->mgr.ctrl_gpr[id][ch] = addr;
 
-                       if (card->isaps)
+                       if (card->is_aps)
                                break;
 
                        if (addr >= 0) {
                                unsigned int state = card->ac97.mixer_state[id];
 
-                               if (ch) {
+                               if (ch == 1) {
                                        state >>= 8;
                                        card->ac97.stereo_mixers |= (1 << id);
-                               } else {
-                                       card->ac97.supported_mixers |= (1 << id);
                                }
 
+                               card->ac97.supported_mixers |= (1 << id);
+
                                if (id == SOUND_MIXER_TREBLE) {
                                        set_treble(card, card->ac97.mixer_state[id] & 0xff, (card->ac97.mixer_state[id] >> 8) & 0xff);
                                } else if (id == SOUND_MIXER_BASS) {
@@ -475,10 +475,10 @@ static int emu10k1_private_mixer(struct emu10k1_card *card, unsigned int cmd, un
                                        emu10k1_set_volume_gpr(card, addr, state & 0xff,
                                                               volume_params[id]);
                        } else {
-                               if (ch) {
-                                       card->ac97.stereo_mixers &= ~(1 << id);
-                                       card->ac97.stereo_mixers |= card->ac97_stereo_mixers;
-                               } else {
+                               card->ac97.stereo_mixers &= ~(1 << id);
+                               card->ac97.stereo_mixers |= card->ac97_stereo_mixers;
+
+                               if (ch == 0) {
                                        card->ac97.supported_mixers &= ~(1 << id);
                                        card->ac97.supported_mixers |= card->ac97_supported_mixers;
                                }
@@ -499,6 +499,12 @@ static int emu10k1_private_mixer(struct emu10k1_card *card, unsigned int cmd, un
                                ret = -EFAULT;
                        break;
 
+               case CMD_AC97_BOOST:
+                       if(ctl->val[0])
+                               emu10k1_ac97_write(&card->ac97, 0x18, 0x0);     
+                       else
+                               emu10k1_ac97_write(&card->ac97, 0x18, 0x0808);
+                       break;
                default:
                        ret = -EINVAL;
                        break;
@@ -551,7 +557,7 @@ static int emu10k1_private_mixer(struct emu10k1_card *card, unsigned int cmd, un
 
                                card->tankmem.size = size;
 
-                               sblive_writeptr_tag(card, 0, TCB, card->tankmem.dma_handle, TCBS, size_reg, TAGLIST_END);
+                               sblive_writeptr_tag(card, 0, TCB, (u32) card->tankmem.dma_handle, TCBS, size_reg, TAGLIST_END);
 
                                emu10k1_writefn0(card, HCFG_LOCKTANKCACHE, 0);
                        }
@@ -572,6 +578,8 @@ static int emu10k1_dsp_mixer(struct emu10k1_card *card, unsigned int oss_mixer,
        int val;
        int scale;
 
+       card->ac97.modcnt++;
+
        if (get_user(val, (int *)arg))
                return -EFAULT;
 
@@ -612,7 +620,7 @@ static int emu10k1_mixer_ioctl(struct inode *inode, struct file *file, unsigned
        unsigned int oss_mixer = _IOC_NR(cmd);
        
        ret = -EINVAL;
-       if (!card->isaps) {
+       if (!card->is_aps) {
                if (cmd == SOUND_MIXER_INFO) {
                        mixer_info info;
 
@@ -626,7 +634,7 @@ static int emu10k1_mixer_ioctl(struct inode *inode, struct file *file, unsigned
                        return 0;
                }
 
-               if ((_IOC_DIR(cmd) == (_IOC_WRITE|_IOC_READ)) && oss_mixer <= SOUND_MIXER_NRDEVICES)
+               if ((_SIOC_DIR(cmd) == (_SIOC_WRITE|_SIOC_READ)) && oss_mixer <= SOUND_MIXER_NRDEVICES)
                        ret = emu10k1_dsp_mixer(card, oss_mixer, arg);
                else
                        ret = card->ac97.mixer_ioctl(&card->ac97, cmd, arg);
index 57690753d955c8c17ab343af0fffa4ea9ef3a01e..0fa31ec0f86b806bed5cf27917fb7ee33faba18c 100644 (file)
@@ -29,7 +29,6 @@
  **********************************************************************
  */
                        
-#define __NO_VERSION__
 #include <linux/module.h>
 #include <linux/poll.h>
 #include <linux/slab.h>
@@ -165,15 +164,12 @@ ssize_t emu10k1_pt_write(struct file *file, const char *buffer, size_t count)
 
                DPD(3, "prepend size %d, prepending %d bytes\n", pt->prepend_size, needed);
                if (count < needed) {
-                       if (copy_from_user(pt->buf + pt->prepend_size, buffer,
-                                          count))
-                               return -EFAULT;
+                       copy_from_user(pt->buf + pt->prepend_size, buffer, count);
                        pt->prepend_size += count;
                        DPD(3, "prepend size now %d\n", pt->prepend_size);
                        return count;
                }
-               if (copy_from_user(pt->buf + pt->prepend_size, buffer, needed))
-                       return -EFAULT;
+               copy_from_user(pt->buf + pt->prepend_size, buffer, needed);
                r = pt_putblock(wave_dev, (u16 *) pt->buf, nonblock);
                if (r)
                        return r;
@@ -184,8 +180,7 @@ ssize_t emu10k1_pt_write(struct file *file, const char *buffer, size_t count)
        blocks_copied = 0;
        while (blocks > 0) {
                u16 *bufptr = (u16 *) buffer + (bytes_copied/2);
-               if (copy_from_user(pt->buf, bufptr, PT_BLOCKSIZE))
-                       return -EFAULT;
+               copy_from_user(pt->buf, bufptr, PT_BLOCKSIZE);
                bufptr = (u16 *) pt->buf;
                r = pt_putblock(wave_dev, bufptr, nonblock);
                if (r) {
@@ -201,8 +196,7 @@ ssize_t emu10k1_pt_write(struct file *file, const char *buffer, size_t count)
        i = count - bytes_copied;
        if (i) {
                pt->prepend_size = i;
-               if (copy_from_user(pt->buf, buffer + bytes_copied, i))
-                       return -EFAULT;
+               copy_from_user(pt->buf, buffer + bytes_copied, i);
                bytes_copied += i;
                DPD(3, "filling prepend buffer with %d bytes", i);
        }
index 73513b6d56b41e8678231061779b99c39e72b5d6..2f6265fd00dc229a8dca447c3f6a29f9e8dbe810 100644 (file)
  **********************************************************************
  */
 
+#include <asm/delay.h>
 #include "8010.h"
 #include "recmgr.h"
 
+void emu10k1_reset_record(struct emu10k1_card *card, struct wavein_buffer *buffer)
+{
+       DPF(2, "emu10k1_reset_record()\n");
+
+       sblive_writeptr(card, buffer->sizereg, 0, ADCBS_BUFSIZE_NONE);
+
+       sblive_writeptr(card, buffer->sizereg, 0, buffer->sizeregval);  
+
+       while (sblive_readptr(card, buffer->idxreg, 0))
+               udelay(5);
+}
+
 void emu10k1_start_record(struct emu10k1_card *card, struct wavein_buffer *buffer)
 {
        DPF(2, "emu10k1_start_record()\n");
 
-       sblive_writeptr(card, buffer->sizereg, 0, buffer->sizeregval);
-
        if (buffer->adcctl)
                sblive_writeptr(card, ADCCR, 0, buffer->adcctl);
-
-       return;
 }
 
 void emu10k1_stop_record(struct emu10k1_card *card, struct wavein_buffer *buffer)
@@ -51,10 +60,6 @@ void emu10k1_stop_record(struct emu10k1_card *card, struct wavein_buffer *buffer
        /* Disable record transfer */
        if (buffer->adcctl)
                sblive_writeptr(card, ADCCR, 0, 0);
-
-       sblive_writeptr(card, buffer->sizereg, 0, ADCBS_BUFSIZE_NONE);
-
-       return;
 }
 
 void emu10k1_set_record_src(struct emu10k1_card *card, struct wiinst *wiinst)
@@ -130,9 +135,7 @@ void emu10k1_set_record_src(struct emu10k1_card *card, struct wiinst *wiinst)
                break;
        }
 
-       DPD(2, "bus addx: %#x\n", buffer->dma_handle);
-
-       sblive_writeptr(card, buffer->addrreg, 0, buffer->dma_handle);
+       DPD(2, "bus addx: %#lx\n", (unsigned long) buffer->dma_handle);
 
-       return;
+       sblive_writeptr(card, buffer->addrreg, 0, (u32)buffer->dma_handle);
 }
index 6ee3f7795a21e76913008f30e7aa598c191cdc3f..a68766ac4fd5d51062e3a1202574255ec1a57374 100644 (file)
@@ -40,9 +40,9 @@
 #define WAVERECORD_MIC         0x02
 #define WAVERECORD_FX          0x03
 
+void emu10k1_reset_record(struct emu10k1_card *card, struct wavein_buffer *buffer);
 void emu10k1_start_record(struct emu10k1_card *, struct wavein_buffer *);
 void emu10k1_stop_record(struct emu10k1_card *, struct wavein_buffer *);
 void emu10k1_set_record_src(struct emu10k1_card *, struct wiinst *wiinst);
 
-
 #endif /* _RECORDMGR_H */
index 8167010bd7d5fa976b2a56614a9026c41da6eb7d..d10d30739f41f49206b8e69b71dfafab8abd91bb 100644 (file)
@@ -59,7 +59,7 @@ void emu10k1_timer_irqhandler(struct emu10k1_card *card)
        return;
 }
 
-void emu10k1_timer_install(struct emu10k1_card *card, struct emu_timer *timer, u32 delay)
+void emu10k1_timer_install(struct emu10k1_card *card, struct emu_timer *timer, u16 delay)
 {
        struct emu_timer *t;
        struct list_head *entry;
@@ -85,7 +85,7 @@ void emu10k1_timer_install(struct emu10k1_card *card, struct emu_timer *timer, u
                card->timer_delay = delay;
                delay = (delay < 1024 ? delay : 1024);
 
-               emu10k1_writefn0(card, TIMER_RATE, delay);
+               emu10k1_timer_set(card, delay);
 
                list_for_each(entry, &card->timers) {
                        t = list_entry(entry, struct emu_timer, list);
@@ -108,7 +108,7 @@ void emu10k1_timer_uninstall(struct emu10k1_card *card, struct emu_timer *timer)
 {
        struct emu_timer *t;
        struct list_head *entry;
-       u32 delay = TIMER_STOPPED;
+       u16 delay = TIMER_STOPPED;
        unsigned long flags;
 
        if (timer->state == TIMER_STATE_UNINSTALLED)
@@ -133,7 +133,7 @@ void emu10k1_timer_uninstall(struct emu10k1_card *card, struct emu_timer *timer)
                else {
                        delay = (delay < 1024 ? delay : 1024);
 
-                       emu10k1_writefn0(card, TIMER_RATE, delay);
+                       emu10k1_timer_set(card, delay);
 
                        list_for_each(entry, &card->timers) {
                                t = list_entry(entry, struct emu_timer, list);
index 693e91f4520075051d469c3ce491c23a5d5097d2..b2543b4d53a843838be6c8fd4e0e55622bdcc4ba 100644 (file)
@@ -36,17 +36,17 @@ struct emu_timer
        struct list_head list;
        struct tasklet_struct tasklet;
        u8 state; 
-       u32 count;                              /* current number of interrupts */
-       u32 count_max;                          /* number of interrupts needed to schedule the bh */
-       u32 delay;                              /* timer delay */
+       u16 count;                              /* current number of interrupts */
+       u16 count_max;                          /* number of interrupts needed to schedule the bh */
+       u16 delay;                              /* timer delay */
 };
 
-void emu10k1_timer_install(struct emu10k1_card *, struct emu_timer *, u32);
+void emu10k1_timer_install(struct emu10k1_card *, struct emu_timer *, u16);
 void emu10k1_timer_uninstall(struct emu10k1_card *, struct emu_timer *);
 void emu10k1_timer_enable(struct emu10k1_card *, struct emu_timer *);
 void emu10k1_timer_disable(struct emu10k1_card *, struct emu_timer *);
 
-#define TIMER_STOPPED                  0xffffffff 
+#define TIMER_STOPPED                  0xffff 
 #define TIMER_STATE_INSTALLED          0x01
 #define TIMER_STATE_ACTIVE             0x02
 #define TIMER_STATE_UNINSTALLED        0x04
index e0465f0efa91f366691d7cbc9dab3fa32ce7e20e..1ed8b087c5c9c375ea3d6d2f7a3e1090efa637d4 100644 (file)
 #include "voicemgr.h"
 #include "8010.h"
 
+/**
+ * emu10k1_voice_alloc_buffer -
+ *
+ * allocates the memory buffer for a voice. Two page tables are kept for each buffer.
+ * One (dma_handle) keeps track of the host memory pages used and the other (virtualpagetable)
+ * is passed to the device so that it can do DMA to host memory.
+ *
+ */
+int emu10k1_voice_alloc_buffer(struct emu10k1_card *card, struct voice_mem *mem, u32 pages)
+{
+       u32 pageindex, pagecount;
+       u32 busaddx;
+       int i;
+
+       DPD(2, "requested pages is: %d\n", pages);
+
+       if ((mem->emupageindex = emu10k1_addxmgr_alloc(pages * PAGE_SIZE, card)) < 0)
+       {
+               DPF(1, "couldn't allocate emu10k1 address space\n");
+               return -1;
+       }
+
+       /* Fill in virtual memory table */
+       for (pagecount = 0; pagecount < pages; pagecount++) {
+               if ((mem->addr[pagecount] = pci_alloc_consistent(card->pci_dev, PAGE_SIZE, &mem->dma_handle[pagecount]))
+                       == NULL) {
+                       mem->pages = pagecount;
+                       DPF(1, "couldn't allocate dma memory\n");
+                       return -1;
+               }
+
+               DPD(2, "Virtual Addx: %p\n", mem->addr[pagecount]);
+
+               for (i = 0; i < PAGE_SIZE / EMUPAGESIZE; i++) {
+                       busaddx = (u32) mem->dma_handle[pagecount] + i * EMUPAGESIZE;
+
+                       DPD(3, "Bus Addx: %#x\n", busaddx);
+
+                       pageindex = mem->emupageindex + pagecount * PAGE_SIZE / EMUPAGESIZE + i;
+
+                       ((u32 *) card->virtualpagetable.addr)[pageindex] = cpu_to_le32((busaddx * 2) | pageindex);
+               }
+       }
+
+       mem->pages = pagecount;
+
+       return 0;
+}
+
+/**
+ * emu10k1_voice_free_buffer -
+ *
+ * frees the memory buffer for a voice.
+ */
+void emu10k1_voice_free_buffer(struct emu10k1_card *card, struct voice_mem *mem)
+{
+       u32 pagecount, pageindex;
+       int i;
+
+       if (mem->emupageindex < 0)
+               return;
+
+       for (pagecount = 0; pagecount < mem->pages; pagecount++) {
+               pci_free_consistent(card->pci_dev, PAGE_SIZE,
+                                       mem->addr[pagecount],
+                                       mem->dma_handle[pagecount]);
+
+               for (i = 0; i < PAGE_SIZE / EMUPAGESIZE; i++) {
+                       pageindex = mem->emupageindex + pagecount * PAGE_SIZE / EMUPAGESIZE + i;
+                       ((u32 *) card->virtualpagetable.addr)[pageindex] =
+                               cpu_to_le32(((u32) card->silentpage.dma_handle * 2) | pageindex);
+               }
+       }
+
+       emu10k1_addxmgr_free(card, mem->emupageindex);
+       mem->emupageindex = -1;
+}
+
 int emu10k1_voice_alloc(struct emu10k1_card *card, struct emu_voice *voice)
 {
        u8 *voicetable = card->voicetable;
@@ -96,8 +174,10 @@ void emu10k1_voice_free(struct emu_voice *voice)
                                                        VTFT, 0x0000ffff,
                                                        PTRX_PITCHTARGET, 0,
                                                        CVCF, 0x0000ffff,
-                                                       CPF, 0,
+                                                       //CPF, 0,
                                                        TAGLIST_END);
+               
+               sblive_writeptr(card, CPF, voice->num + i, 0);
        }
 
        voice->usage = VOICE_USAGE_FREE;
@@ -151,8 +231,8 @@ void emu10k1_voice_playback_setup(struct emu_voice *voice)
                                    Z1, 0,
                                    Z2, 0,
                                    /* Invalidate maps */
-                                   MAPA, MAP_PTI_MASK | (card->silentpage.dma_handle * 2),
-                                   MAPB, MAP_PTI_MASK | (card->silentpage.dma_handle * 2),
+                                   MAPA, MAP_PTI_MASK | ((u32) card->silentpage.dma_handle * 2),
+                                   MAPB, MAP_PTI_MASK | ((u32) card->silentpage.dma_handle * 2),
                                /* modulation envelope */
                                    CVCF, 0x0000ffff,
                                    VTFT, 0x0000ffff,
index f4bdb78dd5641397da65a06b85bc723afeadf2fa..0c60a6de45b40ca5c6595e8ce5672a1349311961 100644 (file)
@@ -64,6 +64,12 @@ struct voice_param
        u32 byampl_env_decay;
 };
 
+struct voice_mem {
+       int emupageindex;
+       void *addr[BUFMAXPAGES];
+       dma_addr_t dma_handle[BUFMAXPAGES];
+       u32 pages;
+};
 
 struct emu_voice
 {
@@ -72,16 +78,20 @@ struct emu_voice
        u8 num;                 /* Voice ID */
        u8 flags;               /* Stereo/mono, 8/16 bit */
 
-        u32 startloop;
-        u32 endloop;
+       u32 startloop;
+       u32 endloop;
        u32 start;
 
        u32 initial_pitch;
        u32 pitch_target;
 
        struct voice_param params[2];
+
+       struct voice_mem mem;
 };
 
+int emu10k1_voice_alloc_buffer(struct emu10k1_card *, struct voice_mem *, u32);
+void emu10k1_voice_free_buffer(struct emu10k1_card *, struct voice_mem *);
 int emu10k1_voice_alloc(struct emu10k1_card *, struct emu_voice *);
 void emu10k1_voice_free(struct emu_voice *);
 void emu10k1_voice_playback_setup(struct emu_voice *);