}
component->init = aux_dev->init;
----- component->auxiliary = 1;
++ ++ list_add(&component->card_aux_list, &card->aux_comp_list);
return 0;
for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST;
order++) {
-- -- list_for_each_entry(comp, &card->component_dev_list, card_list) {
-- -- if (!comp->auxiliary)
-- -- continue;
-- --
- list_for_each_entry_safe(comp, tmp, &card->aux_comp_list,
- card_aux_list) {
+++++ list_for_each_entry(comp, &card->aux_comp_list, card_aux_list) {
if (comp->driver->probe_order == order) {
ret = soc_probe_component(card, comp);
if (ret < 0) {
}
EXPORT_SYMBOL_GPL(snd_soc_runtime_set_dai_fmt);
++ ++
+++++#ifdef CONFIG_DMI
++ ++/* Trim special characters, and replace '-' with '_' since '-' is used to
++ ++ * separate different DMI fields in the card long name. Only number and
++ ++ * alphabet characters and a few separator characters are kept.
++ ++ */
++ ++static void cleanup_dmi_name(char *name)
++ ++{
++ ++ int i, j = 0;
++ ++
++ ++ for (i = 0; name[i]; i++) {
++ ++ if (isalnum(name[i]) || (name[i] == '.')
++ ++ || (name[i] == '_'))
++ ++ name[j++] = name[i];
++ ++ else if (name[i] == '-')
++ ++ name[j++] = '_';
++ ++ }
++ ++
++ ++ name[j] = '\0';
++ ++}
++ ++
++ ++/**
++ ++ * snd_soc_set_dmi_name() - Register DMI names to card
++ ++ * @card: The card to register DMI names
++ ++ * @flavour: The flavour "differentiator" for the card amongst its peers.
++ ++ *
++ ++ * An Intel machine driver may be used by many different devices but are
++ ++ * difficult for userspace to differentiate, since machine drivers ususally
++ ++ * use their own name as the card short name and leave the card long name
++ ++ * blank. To differentiate such devices and fix bugs due to lack of
++ ++ * device-specific configurations, this function allows DMI info to be used
++ ++ * as the sound card long name, in the format of
++ ++ * "vendor-product-version-board"
++ ++ * (Character '-' is used to separate different DMI fields here).
++ ++ * This will help the user space to load the device-specific Use Case Manager
++ ++ * (UCM) configurations for the card.
++ ++ *
++ ++ * Possible card long names may be:
++ ++ * DellInc.-XPS139343-01-0310JH
++ ++ * ASUSTeKCOMPUTERINC.-T100TA-1.0-T100TA
++ ++ * Circuitco-MinnowboardMaxD0PLATFORM-D0-MinnowBoardMAX
++ ++ *
++ ++ * This function also supports flavoring the card longname to provide
++ ++ * the extra differentiation, like "vendor-product-version-board-flavor".
++ ++ *
++ ++ * We only keep number and alphabet characters and a few separator characters
++ ++ * in the card long name since UCM in the user space uses the card long names
++ ++ * as card configuration directory names and AudoConf cannot support special
++ ++ * charactors like SPACE.
++ ++ *
++ ++ * Returns 0 on success, otherwise a negative error code.
++ ++ */
++ ++int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour)
++ ++{
++ ++ const char *vendor, *product, *product_version, *board;
++ ++ size_t longname_buf_size = sizeof(card->snd_card->longname);
++ ++ size_t len;
++ ++
++ ++ if (card->long_name)
++ ++ return 0; /* long name already set by driver or from DMI */
++ ++
++ ++ /* make up dmi long name as: vendor.product.version.board */
++ ++ vendor = dmi_get_system_info(DMI_BOARD_VENDOR);
++ ++ if (!vendor) {
++ ++ dev_warn(card->dev, "ASoC: no DMI vendor name!\n");
++ ++ return 0;
++ ++ }
++ ++
++ ++ snprintf(card->dmi_longname, sizeof(card->snd_card->longname),
++ ++ "%s", vendor);
++ ++ cleanup_dmi_name(card->dmi_longname);
++ ++
++ ++ product = dmi_get_system_info(DMI_PRODUCT_NAME);
++ ++ if (product) {
++ ++ len = strlen(card->dmi_longname);
++ ++ snprintf(card->dmi_longname + len,
++ ++ longname_buf_size - len,
++ ++ "-%s", product);
++ ++
++ ++ len++; /* skip the separator "-" */
++ ++ if (len < longname_buf_size)
++ ++ cleanup_dmi_name(card->dmi_longname + len);
++ ++
++ ++ /* some vendors like Lenovo may only put a self-explanatory
++ ++ * name in the product version field
++ ++ */
++ ++ product_version = dmi_get_system_info(DMI_PRODUCT_VERSION);
++ ++ if (product_version) {
++ ++ len = strlen(card->dmi_longname);
++ ++ snprintf(card->dmi_longname + len,
++ ++ longname_buf_size - len,
++ ++ "-%s", product_version);
++ ++
++ ++ len++;
++ ++ if (len < longname_buf_size)
++ ++ cleanup_dmi_name(card->dmi_longname + len);
++ ++ }
++ ++ }
++ ++
++ ++ board = dmi_get_system_info(DMI_BOARD_NAME);
++ ++ if (board) {
++ ++ len = strlen(card->dmi_longname);
++ ++ snprintf(card->dmi_longname + len,
++ ++ longname_buf_size - len,
++ ++ "-%s", board);
++ ++
++ ++ len++;
++ ++ if (len < longname_buf_size)
++ ++ cleanup_dmi_name(card->dmi_longname + len);
++ ++ } else if (!product) {
++ ++ /* fall back to using legacy name */
++ ++ dev_warn(card->dev, "ASoC: no DMI board/product name!\n");
++ ++ return 0;
++ ++ }
++ ++
++ ++ /* Add flavour to dmi long name */
++ ++ if (flavour) {
++ ++ len = strlen(card->dmi_longname);
++ ++ snprintf(card->dmi_longname + len,
++ ++ longname_buf_size - len,
++ ++ "-%s", flavour);
++ ++
++ ++ len++;
++ ++ if (len < longname_buf_size)
++ ++ cleanup_dmi_name(card->dmi_longname + len);
++ ++ }
++ ++
++ ++ /* set the card long name */
++ ++ card->long_name = card->dmi_longname;
++ ++
++ ++ return 0;
++ ++}
++ ++EXPORT_SYMBOL_GPL(snd_soc_set_dmi_name);
+++++#endif /* CONFIG_DMI */
++ ++
static int snd_soc_instantiate_card(struct snd_soc_card *card)
{
struct snd_soc_codec *codec;
component->remove = component->driver->remove;
component->suspend = component->driver->suspend;
component->resume = component->driver->resume;
- component->pcm_free= component->driver->pcm_free;
++ ++ component->pcm_new = component->driver->pcm_new;
+++++ component->pcm_free = component->driver->pcm_free;
dapm = &component->dapm;
dapm->dev = dev;
platform->driver->remove(platform);
}
- return platform->driver->pcm_new(rtd);
++ ++static int snd_soc_platform_drv_pcm_new(struct snd_soc_pcm_runtime *rtd)
++ ++{
++ ++ struct snd_soc_platform *platform = rtd->platform;
++ ++
- platform->driver->pcm_free(pcm);
+++++ if (platform->driver->pcm_new)
+++++ return platform->driver->pcm_new(rtd);
+++++ else
+++++ return 0;
++ ++}
++ ++
++ ++static void snd_soc_platform_drv_pcm_free(struct snd_pcm *pcm)
++ ++{
++ ++ struct snd_soc_pcm_runtime *rtd = pcm->private_data;
++ ++ struct snd_soc_platform *platform = rtd->platform;
++ ++
+++++ if (platform->driver->pcm_free)
+++++ platform->driver->pcm_free(pcm);
++ ++}
++ ++
/**
* snd_soc_add_platform - Add a platform to the ASoC core
* @dev: The parent device for the platform