参照元

説明

引数

返り値

参考

実装

/* create a new pcm */
int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
{
        struct snd_soc_platform *platform = rtd->platform;
        struct snd_soc_dai *codec_dai;
        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        struct snd_pcm *pcm;
        char new_name[64];
        int ret = 0, playback = 0, capture = 0;
        int i;

        if (rtd->dai_link->dynamic || rtd->dai_link->no_pcm) {
                playback = rtd->dai_link->dpcm_playback;
                capture = rtd->dai_link->dpcm_capture;
        } else {
                for (i = 0; i < rtd->num_codecs; i++) {
                        codec_dai = rtd->codec_dais[i];
                        if (codec_dai->driver->playback.channels_min)
                                playback = 1;
                        if (codec_dai->driver->capture.channels_min)
                                capture = 1;
                }

                capture = capture && cpu_dai->driver->capture.channels_min;
                playback = playback && cpu_dai->driver->playback.channels_min;
        }

        if (rtd->dai_link->playback_only) {
                playback = 1;
                capture = 0;
        }

        if (rtd->dai_link->capture_only) {
                playback = 0;
                capture = 1;
        }

        /* create the PCM */
        if (rtd->dai_link->no_pcm) {
                snprintf(new_name, sizeof(new_name), "(%s)",
                        rtd->dai_link->stream_name);

                ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num,
                                playback, capture, &pcm);
        } else {
                if (rtd->dai_link->dynamic)
                        snprintf(new_name, sizeof(new_name), "%s (*)",
                                rtd->dai_link->stream_name);
                else
                        snprintf(new_name, sizeof(new_name), "%s %s-%d",
                                rtd->dai_link->stream_name,
                                (rtd->num_codecs > 1) ?
                                "multicodec" : rtd->codec_dai->name, num);

                ret = snd_pcm_new(rtd->card->snd_card, new_name, num, playback,
                        capture, &pcm);
        }
        if (ret < 0) {
                dev_err(rtd->card->dev, "ASoC: can't create pcm for %s\n",
                        rtd->dai_link->name);
                return ret;
        }
        dev_dbg(rtd->card->dev, "ASoC: registered pcm #%d %s\n",num, new_name);

        /* DAPM dai link stream work */
        INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);

        pcm->nonatomic = rtd->dai_link->nonatomic;
        rtd->pcm = pcm;
        pcm->private_data = rtd;

        if (rtd->dai_link->no_pcm) {
                if (playback)
                        pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd;
                if (capture)
                        pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd;
                goto out;
        }

        /* ASoC PCM operations */
        if (rtd->dai_link->dynamic) {
                rtd->ops.open           = dpcm_fe_dai_open;
                rtd->ops.hw_params      = dpcm_fe_dai_hw_params;
                rtd->ops.prepare        = dpcm_fe_dai_prepare;
                rtd->ops.trigger        = dpcm_fe_dai_trigger;
                rtd->ops.hw_free        = dpcm_fe_dai_hw_free;
                rtd->ops.close          = dpcm_fe_dai_close;
                rtd->ops.pointer        = soc_pcm_pointer;
                rtd->ops.ioctl          = soc_pcm_ioctl;
        } else {
                rtd->ops.open           = soc_pcm_open;
                rtd->ops.hw_params      = soc_pcm_hw_params;
                rtd->ops.prepare        = soc_pcm_prepare;
                rtd->ops.trigger        = soc_pcm_trigger;
                rtd->ops.hw_free        = soc_pcm_hw_free;
                rtd->ops.close          = soc_pcm_close;
                rtd->ops.pointer        = soc_pcm_pointer;
                rtd->ops.ioctl          = soc_pcm_ioctl;
        }

        if (platform->driver->ops) {
                rtd->ops.ack            = platform->driver->ops->ack;
                rtd->ops.copy           = platform->driver->ops->copy;
                rtd->ops.silence        = platform->driver->ops->silence;
                rtd->ops.page           = platform->driver->ops->page;
                rtd->ops.mmap           = platform->driver->ops->mmap;
        }

        if (playback)
                snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &rtd->ops);

        if (capture)
                snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &rtd->ops);

        if (platform->driver->pcm_new) {
                ret = platform->driver->pcm_new(rtd);
                if (ret < 0) {
                        dev_err(platform->dev,
                                "ASoC: pcm constructor failed: %d\n",
                                ret);
                        return ret;
                }
        }

        pcm->private_free = platform->driver->pcm_free;
out:
        dev_info(rtd->card->dev, "%s <-> %s mapping ok\n",
                 (rtd->num_codecs > 1) ? "multicodec" : rtd->codec_dai->name,
                 cpu_dai->name);
        return ret;
}

コメント


トップ   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS