Chinaunix首页 | 论坛 | 博客
  • 博客访问: 319200
  • 博文数量: 68
  • 博客积分: 1501
  • 博客等级: 上尉
  • 技术积分: 1010
  • 用 户 组: 普通用户
  • 注册时间: 2008-12-30 09:52
文章分类

全部博文(68)

文章存档

2010年(1)

2009年(67)

我的朋友

分类:

2009-01-19 14:26:06

===================================================================
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 int __init audio_init_dma(audio_stream_t * s, char *desc)
{
       int ret ;
       s3c2410_dmasrc_t source;
       int hwcfg;
       unsigned long devaddr;
       dmach_t channel;
       int dcon;
       unsigned int flags = 0;

       if(s->dma_ch == DMA_CH2){
              channel = 2;
              source = S3C2410_DMASRC_MEM;
              hwcfg = 3;
              devaddr = 0x55000010;
              dcon = 0xa0800000;
              flags = S3C2410_DMAF_AUTOSTART;

              ret = s3c2410_dma_request(s->dma_ch, &s3c2410iis_dma_out, NULL);
              s3c2410_dma_devconfig(channel, source, hwcfg, devaddr);
              s3c2410_dma_config(channel, 2, dcon);
              s3c2410_dma_set_buffdone_fn(channel, audio_dmaout_done_callback);
              s3c2410_dma_setflags(channel, flags);
              s->dma_ok = 1;
              return ret;
       }
       else if(s->dma_ch == DMA_CH1){
              channel =1;
              source =S3C2410_DMASRC_HW;
              hwcfg =3;
              devaddr = 0x55000010;
              dcon = 0xa2900000;
              flags = S3C2410_DMAF_AUTOSTART;

              ret = s3c2410_dma_request(s->dma_ch, &s3c2410iis_dma_in, NULL);
              s3c2410_dma_devconfig(channel, source, hwcfg, devaddr);
              s3c2410_dma_config(channel, 2, dcon);
              s3c2410_dma_set_buffdone_fn(channel, audio_dmain_done_callback);
              s3c2410_dma_setflags(channel, flags);
              s->dma_ok =1;
              return ret ;
       }
else
return 1;
}

   小弟搞uda1341的录音部分已多时,现在终于可以正常播音、录音了,现把驱程公开,希望对正在为此问题烦恼的朋友有所帮助^_^

   首先说明一下:

1、 驱程源于中国linux公社->嵌入式linux2.6内核专题:

上的牛貼,稍加修改就可以使用madplay正常播放mp3,但它提供的源码录音部分没做好。

2、 小弟参考网上其它大虾的讨论和三星、uda1341的datasheet修改了驱动程序(见红色部分),其中smdk2410_audio_read函数中注释了:
if (ppos != &file->f_pos)
return -ESPIPE;
部分是因为此处会造成死锁的现象,也就是经常在网上看到的:
cat: Read error: Illegal seek

3、 按照第2步修改了驱动程序后还是不行,出现:
   dma1: loadbuffer:timeout loading buffer
的错误,一直没搞清楚为什么。
   最后,参考华恒提供的uda13800驱程,修改了dcon寄存器的配置(如蓝色部分),困扰了我一个月的问题终于解决了^_^

阅读(1083) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~