/* probes a new socdev */ static int soc_probe(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev);//从platform_device参数中取出snd_soc_card int ret = 0;
/* * no card, so machine driver should be registering card * we should not be here in that case so ret error */ if (!card) return -EINVAL;
/* Bodge while we unpick instantiation */ card->dev = &pdev->dev;
ret = snd_soc_register_card(card);//为snd_soc_pcm_runtime数组申请内存 if (ret != 0) { dev_err(&pdev->dev, "Failed to register card\n"); return ret; }
/** * 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;
/* * Attempt to initialise any uninitialised cards. Must be called with * client_mutex. */ static void snd_soc_instantiate_cards(void) { struct snd_soc_card *card; list_for_each_entry(card, &card_list, list) snd_soc_instantiate_card(card); }
/* initialize the register cache for each available codec */ list_for_each_entry(codec, &codec_list, list) { if (codec->cache_init) continue; /* by default we don't override the compress_type */ compress_type = 0; /* check to see if we need to override the compress_type */ for (i = 0; i < card->num_configs; ++i) { codec_conf = &card->codec_conf[i]; if (!strcmp(codec->name, codec_conf->dev_name)) { compress_type = codec_conf->compress_type; if (compress_type && compress_type != codec->compress_type) break; } } ret = snd_soc_init_codec_cache(codec, compress_type); if (ret < 0) { mutex_unlock(&card->mutex); return; } }
/* card bind complete so register a sound card */ ret = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, card->owner, 0, &card->snd_card); if (ret < 0) { printk(KERN_ERR "asoc: can't create sound card for card %s\n", card->name); mutex_unlock(&card->mutex); return; } card->snd_card->dev = card->dev;
#ifdef CONFIG_PM_SLEEP /* deferred resume work */ INIT_WORK(&card->deferred_resume_work, soc_resume_deferred); #endif
if (card->dapm_widgets) snd_soc_dapm_new_controls(&card->dapm, card->dapm_widgets, card->num_dapm_widgets);
/* initialise the sound card only once */ if (card->probe) { ret = card->probe(card); if (ret < 0) goto card_probe_error; }
for (i = 0; i < card->num_links; i++) { ret = soc_probe_dai_link(card, i); if (ret < 0) { pr_err("asoc: failed to instantiate card %s: %d\n", card->name, ret); goto probe_dai_err; } }
for (i = 0; i < card->num_aux_devs; i++) { ret = soc_probe_aux_dev(card, i); if (ret < 0) { pr_err("asoc: failed to add auxiliary devices %s: %d\n", card->name, ret); goto probe_aux_dev_err; } }
/* We should have a non-codec control add function but we don't */ if (card->controls) snd_soc_add_controls(list_first_entry(&card->codec_dev_list, struct snd_soc_codec, card_list), card->controls, card->num_controls);
if (card->dapm_routes) snd_soc_dapm_add_routes(&card->dapm, card->dapm_routes, card->num_dapm_routes);
snprintf(card->snd_card->shortname, sizeof(card->snd_card->shortname), "%s", card->name); snprintf(card->snd_card->longname, sizeof(card->snd_card->longname), "%s", card->long_name ? card->long_name : card->name); snprintf(card->snd_card->driver, sizeof(card->snd_card->driver), "%s", card->driver_name ? card->driver_name : card->name); for (i = 0; i < ARRAY_SIZE(card->snd_card->driver); i++) { switch (card->snd_card->driver[i]) { case '_': case '-': case '\0': break; default: if (!isalnum(card->snd_card->driver[i])) card->snd_card->driver[i] = '_'; break; } }
if (card->late_probe) { ret = card->late_probe(card); if (ret < 0) { dev_err(card->dev, "%s late_probe() failed: %d\n", card->name, ret); goto probe_aux_dev_err; } }
ret = snd_card_register(card->snd_card); if (ret < 0) { printk(KERN_ERR "asoc: failed to register soundcard for %s\n", card->name); goto probe_aux_dev_err; }
#ifdef CONFIG_SND_SOC_AC97_BUS /* register any AC97 codecs */ for (i = 0; i < card->num_rtd; i++) { ret = soc_register_ac97_dai_link(&card->rtd[i]); if (ret < 0) { printk(KERN_ERR "asoc: failed to register AC97 %s\n", card->name); while (--i >= 0) soc_unregister_ac97_dai_link(card->rtd[i].codec); goto probe_aux_dev_err; } } #endif
static int soc_probe_dai_link(struct snd_soc_card *card, int num) { ... /* set default power off timeout */ rtd->pmdown_time = pmdown_time;
/* probe the cpu_dai */ if (!cpu_dai->probed) { if (cpu_dai->driver->probe) { ret = cpu_dai->driver->probe(cpu_dai); } cpu_dai->probed = 1; /* mark cpu_dai as probed and add to card cpu_dai list */ list_add(&cpu_dai->card_list, &card->dai_dev_list); }
/* probe the CODEC */ if (!codec->probed) { ret = soc_probe_codec(card, codec); }
/* probe the platform */ if (!platform->probed) { if (platform->driver->probe) { ret = platform->driver->probe(platform); } /* mark platform as probed and add to card platform list */ platform->probed = 1; list_add(&platform->card_list, &card->platform_dev_list); }
/* probe the CODEC DAI */ if (!codec_dai->probed) { if (codec_dai->driver->probe) { ret = codec_dai->driver->probe(codec_dai); }
/* mark cpu_dai as probed and add to card cpu_dai list */ codec_dai->probed = 1; list_add(&codec_dai->card_list, &card->dai_dev_list); }
/* DAPM dai link stream work */ INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
ret = soc_post_component_init(card, codec, num, 0); if (ret) return ret;
ret = device_create_file(&rtd->dev, &dev_attr_pmdown_time);
/* create the pcm */ ret = soc_new_pcm(rtd, num);
/* add platform data for AC97 devices */ if (rtd->codec_dai->driver->ac97_control) snd_ac97_dev_add_pdata(codec->ac97, rtd->cpu_dai->ac97_pdata);
if (card->late_probe) { ret = card->late_probe(card); if (ret < 0) { dev_err(card->dev, "%s late_probe() failed: %d\n", card->name, ret); goto probe_aux_dev_err; } }
ret = snd_card_register(card->snd_card); if (ret < 0) { printk(KERN_ERR "asoc: failed to register soundcard for %s\n", card->name); goto probe_aux_dev_err; }