Chinaunix首页 | 论坛 | 博客
  • 博客访问: 15502879
  • 博文数量: 2005
  • 博客积分: 11986
  • 博客等级: 上将
  • 技术积分: 22535
  • 用 户 组: 普通用户
  • 注册时间: 2007-05-17 13:56
文章分类

全部博文(2005)

文章存档

2014年(2)

2013年(2)

2012年(16)

2011年(66)

2010年(368)

2009年(743)

2008年(491)

2007年(317)

分类: LINUX

2009-11-19 16:31:57

浅析alsa声卡放音模式时s3c24xx处理器DMA中断如何建立和处理

浅析uda134x声卡驱动probe的精简步骤
《浅析打开/dev/dsp设备节点代码流程》
《浅析放音模式--向/dev/dsp设备write写入音频数据的代码流

1.登记soc_pcm_ops中的soc_pcm_hw_params到substream->ops中
static struct snd_soc_device s3c24xx_uda134x_snd_devdata = {
    .card = &snd_soc_s3c24xx_uda134x,
    .codec_dev = &soc_codec_dev_uda134x, // 核心在于执行它的uda134x_soc_probe
    .codec_data = &s3c24xx_uda134x,
};
struct snd_soc_codec_device soc_codec_dev_uda134x = {
    .probe =        uda134x_soc_probe,
    .remove =       uda134x_soc_remove,
    .suspend =      uda134x_soc_suspend,
    .resume =       uda134x_soc_resume,
};
==> uda134x_soc_probe
==> snd_soc_new_pcms
==> soc_new_pcm
==> 设置substream->ops = soc_pcm_ops;
/* ASoC PCM operations */
static struct snd_pcm_ops soc_pcm_ops = {
    .open        = soc_pcm_open,
    .close        = soc_codec_close,
    .hw_params    = soc_pcm_hw_params,
    .hw_free    = soc_pcm_hw_free,
    .prepare    = soc_pcm_prepare,
    .trigger    = soc_pcm_trigger,
};
2.引用soc_pcm_hw_params
static const struct file_operations snd_pcm_oss_f_reg =
{
    .owner =    THIS_MODULE,
    .read =        snd_pcm_oss_read,
    .write =    snd_pcm_oss_write,
    .open =        snd_pcm_oss_open,
    .release =    snd_pcm_oss_release,
    .poll =        snd_pcm_oss_poll,
    .unlocked_ioctl =    snd_pcm_oss_ioctl,
    .compat_ioctl =    snd_pcm_oss_ioctl_compat,
    .mmap =        snd_pcm_oss_mmap,
};
snd_pcm_oss_f_reg
==> snd_pcm_oss_write
==> snd_pcm_oss_write1
==> snd_pcm_oss_make_ready 《浅析alsa声卡驱动snd_pcm_oss_make_ready函数》
==> snd_pcm_oss_change_params 《浅析alsa声卡驱动snd_pcm_oss_change_params函数》
==> snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_HW_PARAMS, sparams) // 执行硬件参数配置函数 《浅析alsa声卡驱动snd_pcm_kernel_ioctl函数》
==> snd_pcm_playback_ioctl1或者snd_pcm_capture_ioctl1
==> snd_pcm_common_ioctl1
    case SNDRV_PCM_IOCTL_HW_PARAMS:
        return snd_pcm_hw_params_user(substream, arg);
==> snd_pcm_hw_params_user
==> snd_pcm_hw_params
==> snd_pcm_hw_params
==> substream->ops->hw_params(substream, params);即soc_pcm_ops的soc_pcm_hw_params
==> soc_pcm_hw_params
==> platform->pcm_ops->hw_params(substream, params);即s3c24xx_pcm_hw_params
struct snd_soc_platform s3c24xx_soc_platform = {
    .name        = "s3c24xx-audio",
    .pcm_ops     = &s3c24xx_pcm_ops,
    .pcm_new    = s3c24xx_pcm_new,
    .pcm_free    = s3c24xx_pcm_free_dma_buffers,
};
s3c24xx_pcm_ops
static struct snd_pcm_ops s3c24xx_pcm_ops = {
    .open        = s3c24xx_pcm_open,
    .close        = s3c24xx_pcm_close,
    .ioctl        = snd_pcm_lib_ioctl,
    .hw_params    = s3c24xx_pcm_hw_params,
    .hw_free    = s3c24xx_pcm_hw_free,
    .prepare    = s3c24xx_pcm_prepare,
    .trigger    = s3c24xx_pcm_trigger,
    .pointer    = s3c24xx_pcm_pointer,
    .mmap        = s3c24xx_pcm_mmap,
};
==> s3c24xx_pcm_hw_params
==> s3c2410_dma_request(prtd->params->channel, prtd->params->client, NULL);
    设置dma完成之后的函数为s3c24xx_audio_buffdone
    s3c2410_dma_set_buffdone_fn(prtd->params->channel, s3c24xx_audio_buffdone);
==> request_irq(chan->irq, s3c2410_dma_irq, IRQF_DISABLED,
                  client->name, (void *)chan);
登记注册dma数据传输完毕的irq中断函数s3c2410_dma_irq
s3c2410_dma_irq
==> s3c2410_dma_buffdone(chan, buf, S3C2410_RES_OK);
static inline void
s3c2410_dma_buffdone(struct s3c2410_dma_chan *chan, struct s3c2410_dma_buf *buf,
             enum s3c2410_dma_buffresult result)
{
#if 0
    pr_debug("callback_fn=%p, buf=%p, id=%p, size=%d, result=%d\n",
         chan->callback_fn, buf, buf->id, buf->size, result);
#endif

    if (chan->callback_fn != NULL) {
        (chan->callback_fn)(chan, buf->id, buf->size, result); // 执行s3c24xx_audio_buffdone完成audio音频数据发送工作
    }
}
阅读(2191) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~