s3c2410-uda1341_c.txt

来自「2410uda1341的测试代码」· 文本 代码 · 共 1,285 行 · 第 1/4 页

TXT
1,285
字号

        for (frag = 0; frag < s->nbfrags; frag++) {
                audio_buf_t *b = &s->buffers[frag];

                if (!dmasize) {
                        dmasize = (s->nbfrags - frag) * s->fragsize;
                        do {
                                dmabuf = dma_alloc_coherent(NULL, dmasize, &dmaphys, GFP_KERNEL|GFP_DMA);
                                if (!dmabuf)
                                            dmasize -= s->fragsize;
                        } while (!dmabuf && dmasize);
                        if (!dmabuf)
                                goto err;
                        b->master = dmasize;
                }

                b->start = dmabuf;
                b->dma_addr = dmaphys;
                sema_init(&b->sem, 1);
                DPRINTK("buf %d: start %p dma %d\n", frag, b->start, b->dma_addr);

                dmabuf += s->fragsize;
                dmaphys += s->fragsize;
                dmasize -= s->fragsize;
        }

        s->buf_idx = 0;
        s->buf = &s->buffers[0];
        return 0;

      err:
        printk(AUDIO_NAME ": unable to allocate audio memory\n ");
        audio_clear_buf(s);
        return -ENOMEM;
}

static void audio_dmaout_done_callback(s3c2410_dma_chan_t *ch, void *buf, int size,
                                   s3c2410_dma_buffresult_t result)
{
        audio_buf_t *b = (audio_buf_t *) buf;
        up(&b->sem);
        wake_up(&b->sem.wait);
}

static void audio_dmain_done_callback(s3c2410_dma_chan_t *ch, void *buf, int size,
                                   s3c2410_dma_buffresult_t result)
{
        audio_buf_t *b = (audio_buf_t *) buf;
          b->size = size;
        up(&b->sem);
        wake_up(&b->sem.wait);               
}
/* using when write */
static int audio_sync(struct file *file)
{
        audio_stream_t *s = &output_stream;
        audio_buf_t *b = s->buf;

        DPRINTK("audio_sync\n");

        if (!s->buffers)
                return 0;

        if (b->size != 0) {
                down(&b->sem);
                s3c2410_dma_enqueue(s->dma_ch, (void *) b, b->dma_addr, b->size);
                b->size = 0;
                NEXT_BUF(s, buf);
        }

        b = s->buffers + ((s->nbfrags + s->buf_idx - 1) % s->nbfrags);
        if (down_interruptible(&b->sem))
                return -EINTR;
        up(&b->sem);

        return 0;
}

static inline int copy_from_user_mono_stereo(char *to, const char *from, int count)
{
        u_int *dst = (u_int *)to;
        const char *end = from + count;

        if (access_ok(VERIFY_READ, from, count))
                return -EFAULT;

        if ((int)from & 0x2) {
                u_int v;
                __get_user(v, (const u_short *)from); from += 2;
                *dst++ = v | (v << 16);
        }

        while (from < end-2) {
                u_int v, x, y;
                __get_user(v, (const u_int *)from); from += 4;
                x = v << 16;
                x |= x >> 16;
                y = v >> 16;
                y |= y << 16;
                *dst++ = x;
                *dst++ = y;
        }

        if (from < end) {
                u_int v;
                __get_user(v, (const u_short *)from);
                *dst = v | (v << 16);
        }

        return 0;
}


static ssize_t smdk2410_audio_write(struct file *file, const char *buffer,
                                    size_t count, loff_t * ppos)
{
        const char *buffer0 = buffer;
        audio_stream_t *s = &output_stream;
        int chunksize, ret = 0;

        DPRINTK("audio_write : start count=%d\n", count);

        switch (file->f_flags & O_ACCMODE) {
                  case O_WRONLY:
                  case O_RDWR:
                        break;
                  default:
                          return -EPERM;
        }

        if (!s->buffers && audio_setup_buf(s))
                return -ENOMEM;

        count &= ~0x03;

        while (count > 0) {
                audio_buf_t *b = s->buf;

                if (file->f_flags & O_NONBLOCK) {
                        ret = -EAGAIN;
                        if (down_trylock(&b->sem))
                                break;
                } else {
                        ret = -ERESTARTSYS;
                        if (down_interruptible(&b->sem))
                                break;
                }

                if (audio_channels == 2) {
                        chunksize = s->fragsize - b->size;
                        if (chunksize > count)
                                chunksize = count;
                        DPRINTK("write %d to %d\n", chunksize, s->buf_idx);
                        if (copy_from_user(b->start + b->size, buffer, chunksize)) {
                                up(&b->sem);
                                return -EFAULT;
                        }
                        b->size += chunksize;
                } else {
                        chunksize = (s->fragsize - b->size) >> 1;

                        if (chunksize > count)
                                chunksize = count;
                        DPRINTK("write %d to %d\n", chunksize*2, s->buf_idx);
                        if (copy_from_user_mono_stereo(b->start + b->size,
                                                           buffer, chunksize)) {
                                up(&b->sem);
                                return -EFAULT;
                        }

                        b->size += chunksize*2;
                }

                buffer += chunksize;
                count -= chunksize;
                if (b->size < s->fragsize) {
                        up(&b->sem);
                        break;
                }

                if((ret = s3c2410_dma_enqueue(s->dma_ch, (void *) b, b->dma_addr, b->size))) {
                        printk(PFX"dma enqueue failed.\n");
                        return ret;
                }
                b->size = 0;
                NEXT_BUF(s, buf);
        }

        if ((buffer - buffer0))
                ret = buffer - buffer0;

        DPRINTK("audio_write : end count=%d\n\n", ret);

        return ret;
}


static ssize_t smdk2410_audio_read(struct file *file, char *buffer,
                                        size_t count, loff_t * ppos)
{
        const char *buffer0 = buffer;
        audio_stream_t *s = &input_stream;
        int chunksize, ret = 0;

        DPRINTK("audio_read: count=%d\n", count);

        if (ppos != &file->f_pos)
                return -ESPIPE;

        if (!s->buffers) {
                int i;

                 if (audio_setup_buf(s))
                         return -ENOMEM;

                 for (i = 0; i < s->nbfrags; i++) {
                         audio_buf_t *b = s->buf;
                         down(&b->sem);
                         s3c2410_dma_enqueue(s->dma_ch, (void *) b, b->dma_addr, s->fragsize);
                         NEXT_BUF(s, buf);
                 }
         }
       
        while (count > 0) {
                audio_buf_t *b = s->buf;

                /* Wait for a buffer to become full */
                if (file->f_flags & O_NONBLOCK) {
                        ret = -EAGAIN;
                        if (down_trylock(&b->sem))
                                break;
                } else {
                        ret = -ERESTARTSYS;
                        if (down_interruptible(&b->sem))
                                break;
                }

                chunksize = b->size;
                if (chunksize > count)
                        chunksize = count;
                DPRINTK("read %d from %d\n", chunksize, s->buf_idx);
                if (copy_to_user(buffer, b->start + s->fragsize - b->size,
                                               chunksize)) {
                        up(&b->sem);
                        return -EFAULT;
                }
               
                b->size -= chunksize;

                buffer += chunksize;
                count -= chunksize;
                if (b->size > 0) {
                        up(&b->sem);
                        break;
                }

                /* Make current buffer available for DMA again */
                s3c2410_dma_enqueue(s->dma_ch, (void *) b, b->dma_addr, s->fragsize);

                NEXT_BUF(s, buf);
        }
       
        if ((buffer - buffer0))
                ret = buffer - buffer0;

     //   DPRINTK("audio_read: return=%d\n", ret);

        return ret;
}


static unsigned int smdk2410_audio_poll(struct file *file,
                                        struct poll_table_struct *wait)
{
        unsigned int mask = 0;
        int i;

        DPRINTK("audio_poll(): mode=%s\n",
                (file->f_mode & FMODE_WRITE) ? "w" : "");

        if (file->f_mode & FMODE_READ) {
                if (!input_stream.buffers && audio_setup_buf(&input_stream))
                        return -ENOMEM;
                poll_wait(file, &input_stream.buf->sem.wait, wait);

                for (i = 0; i < input_stream.nbfrags; i++) {
                        if (atomic_read(&input_stream.buffers[i].sem.count) > 0)
                                mask |= POLLIN | POLLWRNORM;
                                break;
                }
        }


        if (file->f_mode & FMODE_WRITE) {
                if (!output_stream.buffers && audio_setup_buf(&output_stream))
                        return -ENOMEM;
                poll_wait(file, &output_stream.buf->sem.wait, wait);

                for (i = 0; i < output_stream.nbfrags; i++) {
                        if (atomic_read(&output_stream.buffers[i].sem.count) > 0)
                                mask |= POLLOUT | POLLWRNORM;
                                break;
                }
        }

        DPRINTK("audio_poll() returned mask of %s\n",
                (mask & POLLOUT) ? "w" : "");

        return mask;
}


static loff_t smdk2410_audio_llseek(struct file *file, loff_t offset,
                                    int origin)
{
            return -ESPIPE;
}


static int smdk2410_mixer_ioctl(struct inode *inode, struct file *file,
                                unsigned int cmd, unsigned long arg)
{

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?