参照元

説明

引数

返り値

参考

実装

/**
 * snd_soc_register_card - Register a card with the ASoC core
 *
 * @card: Card to register
 *
 */
int snd_soc_register_card(struct snd_soc_card *card)
{
        int i, j, ret;

        if (!card->name || !card->dev)
                return -EINVAL;

        for (i = 0; i < card->num_links; i++) {
                struct snd_soc_dai_link *link = &card->dai_link[i];
                ret = snd_soc_init_multicodec(card, link);
                if (ret) {
                        dev_err(card->dev, "ASoC: failed to init multicodec\n");
                        return ret;
                }
                for (j = 0; j < link->num_codecs; j++) {
                        /*
                         * Codec must be specified by 1 of name or OF node,
                         * not both or neither.
                         */
                        if (!!link->codecs[j].name ==
                            !!link->codecs[j].of_node) {
                                dev_err(card->dev, "ASoC: Neither/both codec name/of_node are set for %s\n",
                                        link->name);
                                return -EINVAL;
                        }
                        /* Codec DAI name must be specified */
                        if (!link->codecs[j].dai_name) {
                                dev_err(card->dev, "ASoC: codec_dai_name not set for %s\n",
                                        link->name);
                                return -EINVAL;
                        }
                }

                /*
                 * Platform may be specified by either name or OF node, but
                 * can be left unspecified, and a dummy platform will be used.
                 */
                if (link->platform_name && link->platform_of_node) {
                        dev_err(card->dev,
                                "ASoC: Both platform name/of_node are set for %s\n",
                                link->name);
                        return -EINVAL;
                }

                /*
                 * CPU device may be specified by either name or OF node, but
                 * can be left unspecified, and will be matched based on DAI
                 * name alone..
                 */
                if (link->cpu_name && link->cpu_of_node) {
                        dev_err(card->dev,
                                "ASoC: Neither/both cpu name/of_node are set for %s\n",
                                link->name);
                        return -EINVAL;
                }
                /*
                 * At least one of CPU DAI name or CPU device name/node must be
                 * specified
                 */
                if (!link->cpu_dai_name &&
                    !(link->cpu_name || link->cpu_of_node)) {
                        dev_err(card->dev,
                                "ASoC: Neither cpu_dai_name nor cpu_name/of_node are set for %s\n",
                                link->name);
                        return -EINVAL;
                }
        }

        dev_set_drvdata(card->dev, card);
        snd_soc_initialize_card_lists(card);
        card->rtd = devm_kzalloc(card->dev,
                                 sizeof(struct snd_soc_pcm_runtime) *
                                 (card->num_links + card->num_aux_devs),
                                 GFP_KERNEL);
        if (card->rtd == NULL)
                return -ENOMEM;
        card->num_rtd = 0;
        card->rtd_aux = &card->rtd[card->num_links];
        for (i = 0; i < card->num_links; i++) {
                card->rtd[i].card = card;
                card->rtd[i].dai_link = &card->dai_link[i];
                card->rtd[i].codec_dais = devm_kzalloc(card->dev,
                                        sizeof(struct snd_soc_dai *) *
                                        (card->rtd[i].dai_link->num_codecs),
                                        GFP_KERNEL);
                if (card->rtd[i].codec_dais == NULL)
                        return -ENOMEM;
        }

        for (i = 0; i < card->num_aux_devs; i++)
                card->rtd_aux[i].card = card;

        INIT_LIST_HEAD(&card->dapm_dirty);
        INIT_LIST_HEAD(&card->dobj_list);
        card->instantiated = 0;
        mutex_init(&card->mutex);
        mutex_init(&card->dapm_mutex);
        ret = snd_soc_instantiate_card(card);
        if (ret != 0)
                return ret;
        /* deactivate pins to sleep state */
        for (i = 0; i < card->num_rtd; i++) {
                struct snd_soc_pcm_runtime *rtd = &card->rtd[i];
                struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
                int j;
                for (j = 0; j < rtd->num_codecs; j++) {
                        struct snd_soc_dai *codec_dai = rtd->codec_dais[j];
                        if (!codec_dai->active)
                                pinctrl_pm_select_sleep_state(codec_dai->dev);
                }
                if (!cpu_dai->active)
                        pinctrl_pm_select_sleep_state(cpu_dai->dev);
        }

        return ret;
}

コメント


トップ   編集 凍結 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2016-02-10 (水) 13:02:20