Chinaunix首页 | 论坛 | 博客
  • 博客访问: 7524
  • 博文数量: 2
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 12
  • 用 户 组: 普通用户
  • 注册时间: 2014-02-14 09:19
文章分类
文章存档

2014年(2)

我的朋友

分类:

2014-09-11 14:51:09

snd_soc_new_pcms
==> soc_new_pcm(socdev, &machine->dai_link[i], i);
    /* create the pcms */
    for(i = 0; i < machine->num_links; i++) {
        ret = soc_new_pcm(socdev, &machine->dai_link[i], i);    // 创建soc-pcm实例,一个实例对应cpu_dai和codec_dai这样一个组合.
        if (ret < 0) {
            printk(KERN_ERR "asoc: can't create pcm %s\n",
                machine->dai_link[i].stream_name);
            mutex_unlock(&codec->mutex);
            return ret;
        }
    }
==> snd_pcm_new(codec->card, new_name, codec->pcm_devs++, playback, capture, &pcm); // 执行真正的创建[luther.gliethttp]
==> snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_PLAYBACK, playback_count)  // 创建playback_count个放音stream,每个pcm可以有多个放音stream声音流通道,但我这里就1个
    snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_CAPTURE, capture_count)    // 创建capture_count个录音stream,每个pcm可以有多个录音stream声音流通道,但我这里就1个[luther.gliethttp]
/**
 * snd_pcm_new_stream - create a new PCM stream
 * @pcm: the pcm instance
 * @stream: the stream direction, SNDRV_PCM_STREAM_XXX
 * @substream_count: the number of substreams
 *
 * Creates a new stream for the pcm.
 * The corresponding stream on the pcm must have been empty before
 * calling this, i.e. zero must be given to the argument of
 * snd_pcm_new().
 *
 * Returns zero if successful, or a negative error code on failure.
 */
int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
{
    int idx, err;                                       // 为该pcm一次性创建出所有该pcm包含的stream声音流:放音和录音[luther.gliethttp]
    struct snd_pcm_str *pstr = &pcm->streams[stream];   // stream有2种值:
    struct snd_pcm_substream *substream, *prev;         // 1.SNDRV_PCM_STREAM_PLAYBACK放音
                                                        // 2.SNDRV_PCM_STREAM_CAPTURE录音
#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
    mutex_init(&pstr->oss.setup_mutex);
#endif
    pstr->stream = stream;                              // pstr为stream对应的录音或放音流的head头,后面将为该head一次性
    pstr->pcm = pcm;                                    // 追加上所有该pcm包含的相应stream声音流结构体[luther.gliethttp]
    pstr->substream_count = substream_count;            // 该pcm一共包含substream_count个放音或录音流
    if (substream_count > 0) {
        err = snd_pcm_stream_proc_init(pstr);           // 创建pcm0p和pcm0c等目录
/*
luther@gliethttp:/proc/asound/card0$ tree pcm0p/
pcm0p/
|-- info
|-- oss
`-- sub0
    |-- hw_params
    |-- info
    |-- prealloc
    |-- prealloc_max
    |-- status
    `-- sw_params

1 directory, 8 files
*/
        if (err < 0) {
            snd_printk(KERN_ERR "Error in snd_pcm_stream_proc_init\n");
            return err;
        }
    }
    prev = NULL;
    for (idx = 0, prev = NULL; idx < substream_count; idx++) {
        substream = kzalloc(sizeof(*substream), GFP_KERNEL);// 为substream创建一块新内存空间[luther.gliethttp]
        if (substream == NULL) {
            snd_printk(KERN_ERR "Cannot allocate PCM substream\n");
            return -ENOMEM;
        }
        substream->pcm = pcm;                               // 该substream所归属的pcm
        substream->pstr = pstr;                             // 该substream所归属的head头
        substream->number = idx;                            // 该substream位于head链表中的id索引值number,用来锁定本substream.
        substream->stream = stream;
        sprintf(substream->name, "subdevice #%i", idx);
        snprintf(substream->latency_id, sizeof(substream->latency_id),
             "ALSA-PCM%d-%d%c%d", pcm->card->number, pcm->device,
             (stream ? 'c' : 'p'), idx);                    // 因为该函数snd_pcm_new_stream会一次性为该pcm创建所有stream,
        substream->buffer_bytes_max = UINT_MAX;             // 所以如果prev等于NULL,那么该substream将作为head链表的头部
        if (prev == NULL)                                   // 元素,之后substream_count-1个substream都将依次以next方式
            pstr->substream = substream;                    // prev->next = substream;
        else                                                // prev = substream;这样该pcm的所有放音流或者录音流都将顺序链
            prev->next = substream;                         // 接到放音pstr和录音pstr中[luther.gliethttp].
        err = snd_pcm_substream_proc_init(substream);       // 创建/proc/asound/card0/pcm0p/sub0目录和下面具体的文件
        if (err < 0) {
            snd_printk(KERN_ERR "Error in snd_pcm_stream_proc_init\n");
            if (prev == NULL)
                pstr->substream = NULL;
            else
                prev->next = NULL;
            kfree(substream);
            return err;
        }
        substream->group = &substream->self_group;
        spin_lock_init(&substream->self_group.lock);
        INIT_LIST_HEAD(&substream->self_group.substreams);
        list_add_tail(&substream->link_list, &substream->self_group.substreams);
        spin_lock_init(&substream->timer_lock);
        atomic_set(&substream->mmap_count, 0);
        prev = substream;                                   // 该substream作为prev,等待prev->next单向链接下一个subsystem.
    }
    return 0;
}
阅读(1087) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~