Chinaunix首页 | 论坛 | 博客
  • 博客访问: 15482910
  • 博文数量: 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-13 11:32:57

浅析uda134x声卡驱动probe的精简步骤

《浅析打开/dev/dsp设备节点代码流程》
《浅析放音模式--向/dev/dsp设备write写入音频数据的代码流
《浅析alsa声卡放音模式时s3c24xx处理器DMA中断如何建立和处理》
<基于linux-2.6.31.5内核[luther.gliethttp]>
s3c24xx_uda134x_probe
==> platform_device_alloc("soc-audio", -1);
==> platform_set_drvdata(s3c24xx_uda134x_snd_device, &s3c24xx_uda134x_snd_devdata);
==> soc_driver中的soc_probe
==> 调用codec_dev->probe也就是下面的uda134x_soc_probe
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,
};
// 下面是生成的唯一一个PCM实例对应的DAI接口
static struct snd_soc_dai_link s3c24xx_uda134x_dai_link = {
    .name = "UDA134X",
    .stream_name = "UDA134X",
    .codec_dai = &uda134x_dai,
    .cpu_dai = &s3c24xx_i2s_dai,
    .ops = &s3c24xx_uda134x_ops,
};
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为每个card->dai_link[i]组合创建一个pcm实例也就是为s3c24xx_uda134x_dai_link
    唯一对应的一个DAI生成唯一的一个PCM实例[luther.gliethttp]
==> snd_soc_init_card
==> snd_card_register注册声卡[card和pcm]
==> snd_device_register_all调用dev->ops->dev_register(dev)注册card->devices
    链表上的所有设备,当然包括snd_soc_new_pcms中创建的pcm实例[luther.gliethttp]
==> snd_pcm_dev_register
==> 调用snd_pcm_notify_list链表上的snd_pcm_oss_register_minor
==> snd_pcm_oss_register_minor
==> register_oss_dsp(pcm, 0);创建/dev/dsp设备节点[luther.gliethttp]
    同时设置/dev/dsp设备节点的操作方法集为snd_pcm_oss_f_reg
==> snd_pcm_oss_f_reg为/dev/dsp设备节点soundcore_open后的替代fops
    这样当应用程序打开/dev/dsp之后,snd_pcm_oss_f_reg将作为该应用程序的默认方法集
==> file->f_op = fops_get(snd_pcm_oss_f_reg);
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_open
// ==> snd_pcm_oss_open_file
// ==> snd_pcm_oss_init_substream
// ==> runtime->oss.rate = 8000;

s3c24xx_pcm_open
==> snd_soc_set_runtime_hwparams(substream, &s3c24xx_pcm_hardware);
static const struct snd_pcm_hardware s3c24xx_pcm_hardware = {
    .info            = SNDRV_PCM_INFO_INTERLEAVED |
                    SNDRV_PCM_INFO_BLOCK_TRANSFER |
                    SNDRV_PCM_INFO_MMAP |
                    SNDRV_PCM_INFO_MMAP_VALID |
                    SNDRV_PCM_INFO_PAUSE |
                    SNDRV_PCM_INFO_RESUME,
    .formats        = SNDRV_PCM_FMTBIT_S16_LE |
                    SNDRV_PCM_FMTBIT_U16_LE |
                    SNDRV_PCM_FMTBIT_U8 |
                    SNDRV_PCM_FMTBIT_S8,
    .channels_min        = 2,
    .channels_max        = 2,
    .buffer_bytes_max    = 128*1024,
    .period_bytes_min    = PAGE_SIZE,
    .period_bytes_max    = PAGE_SIZE*2,
    .periods_min        = 2,
    .periods_max        = 128,
    .fifo_size        = 32,
};
int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,
    const struct snd_pcm_hardware *hw)
{
    struct snd_pcm_runtime *runtime = substream->runtime;
    runtime->hw.info = hw->info;
    runtime->hw.formats = hw->formats;
    runtime->hw.period_bytes_min = hw->period_bytes_min;
    runtime->hw.period_bytes_max = hw->period_bytes_max;
    runtime->hw.periods_min = hw->periods_min;
    runtime->hw.periods_max = hw->periods_max;
    runtime->hw.buffer_bytes_max = hw->buffer_bytes_max;
    runtime->hw.fifo_size = hw->fifo_size;
    return 0;
}


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