]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/commitdiff
Merge remote-tracking branches 'asoc/topic/uda1380', 'asoc/topic/unregister', 'asoc...
authorMark Brown <broonie@kernel.org>
Sun, 30 Apr 2017 13:16:41 +0000 (22:16 +0900)
committerMark Brown <broonie@kernel.org>
Sun, 30 Apr 2017 13:16:41 +0000 (22:16 +0900)
1  2  3  4  5  6 
sound/soc/soc-core.c

diff --combined sound/soc/soc-core.c
index f45748ef9f13a8e805b72f9b90025fe83dedf73e,f1901bb1466ec67b12189713c66ad040f1ae75c7,de6d5609c2525b9b2b1330c80d84bbdf0c4d61fc,6dca408faae334d223494c33e14d503518b497d7,f1901bb1466ec67b12189713c66ad040f1ae75c7,f1901bb1466ec67b12189713c66ad040f1ae75c7..525f2f397b4c225208a6b82c94ae8c1addd2eeaf
      #include <linux/ctype.h>
      #include <linux/slab.h>
      #include <linux/of.h>
 ++ ++#include <linux/dmi.h>
      #include <sound/core.h>
      #include <sound/jack.h>
      #include <sound/pcm.h>
@@@@@@@ -980,7 -979,7 -979,7 -980,7 -979,7 -979,7 +980,7 @@@@@@@ EXPORT_SYMBOL_GPL(snd_soc_find_dai)
       * @card: soc card
       * @id: DAI link ID to match
       * @name: DAI link name to match, optional
 -- -- * @stream name: DAI link stream name to match, optional
 ++ ++ * @stream_name: DAI link stream name to match, optional
       *
       * This function will search all existing DAI links of the soc card to
       * find the link of the same ID. Since DAI links may not have their
@@@@@@@ -1594,27 -1593,6 -1593,6 -1594,27 -1593,6 -1593,6 +1594,27 @@@@@@@ static int soc_probe_dai(struct snd_soc
        return 0;
      }
      
 ++ ++static int soc_link_dai_pcm_new(struct snd_soc_dai **dais, int num_dais,
 ++ ++                          struct snd_soc_pcm_runtime *rtd)
 ++ ++{
 ++ ++  int i, ret = 0;
 ++ ++
 ++ ++  for (i = 0; i < num_dais; ++i) {
 ++ ++          struct snd_soc_dai_driver *drv = dais[i]->driver;
 ++ ++
 ++ ++          if (!rtd->dai_link->no_pcm && drv->pcm_new)
 ++ ++                  ret = drv->pcm_new(rtd, dais[i]);
 ++ ++          if (ret < 0) {
 ++ ++                  dev_err(dais[i]->dev,
 ++ ++                          "ASoC: Failed to bind %s with pcm device\n",
 ++ ++                          dais[i]->name);
 ++ ++                  return ret;
 ++ ++          }
 ++ ++  }
 ++ ++
 ++ ++  return 0;
 ++ ++}
 ++ ++
      static int soc_link_dai_widgets(struct snd_soc_card *card,
                                struct snd_soc_dai_link *dai_link,
                                struct snd_soc_pcm_runtime *rtd)
@@@@@@@ -1726,13 -1704,6 -1704,6 -1726,13 -1704,6 -1704,6 +1726,13 @@@@@@@ static int soc_probe_link_dais(struct s
                                       dai_link->stream_name, ret);
                                return ret;
                        }
 ++ ++                  ret = soc_link_dai_pcm_new(&cpu_dai, 1, rtd);
 ++ ++                  if (ret < 0)
 ++ ++                          return ret;
 ++ ++                  ret = soc_link_dai_pcm_new(rtd->codec_dais,
 ++ ++                                             rtd->num_codecs, rtd);
 ++ ++                  if (ret < 0)
 ++ ++                          return ret;
                } else {
                        INIT_DELAYED_WORK(&rtd->delayed_work,
                                                codec2codec_close_delayed_work);
@@@@@@@ -1776,7 -1747,7 -1747,7 -1776,8 -1747,7 -1747,7 +1776,7 @@@@@@@ static int soc_bind_aux_dev(struct snd_
        }
      
        component->init = aux_dev->init;
 -----  component->auxiliary = 1;
 ++ ++  list_add(&component->card_aux_list, &card->aux_comp_list);
      
        return 0;
      
      
      static int soc_probe_aux_devices(struct snd_soc_card *card)
      {
   -    struct snd_soc_component *comp, *tmp;
   +    struct snd_soc_component *comp;
        int order;
        int ret;
      
        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) {
                                                comp->name, ret);
                                        return ret;
                                }
   -                            list_del(&comp->card_aux_list);
                        }
                }
        }
@@@@@@@ -1817,12 -1791,14 -1791,14 -1820,14 -1791,14 -1791,14 +1817,12 @@@@@@@ static void soc_remove_aux_devices(stru
        for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST;
                order++) {
                list_for_each_entry_safe(comp, _comp,
 -----                  &card->component_dev_list, card_list) {
 -----
 -----                  if (!comp->auxiliary)
 -----                          continue;
 +++++                  &card->aux_comp_list, card_aux_list) {
      
                        if (comp->driver->remove_order == order) {
                                soc_remove_component(comp);
 -----                          comp->auxiliary = 0;
 +++++                          /* remove it from the card's aux_comp_list */
 +++++                          list_del(&comp->card_aux_list);
                        }
                }
        }
@@@@@@@ -1912,141 -1888,6 -1888,6 -1917,139 -1888,6 -1888,6 +1912,141 @@@@@@@ int snd_soc_runtime_set_dai_fmt(struct 
      }
      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;
                snd_soc_dapm_add_routes(&card->dapm, card->of_dapm_routes,
                                        card->num_of_dapm_routes);
      
 +++++  /* try to set some sane longname if DMI is available */
 +++++  snd_soc_set_dmi_name(card, NULL);
 +++++
        snprintf(card->snd_card->shortname, sizeof(card->snd_card->shortname),
                 "%s", card->name);
        snprintf(card->snd_card->longname, sizeof(card->snd_card->longname),
@@@@@@@ -3041,7 -2879,7 -2879,7 -3041,7 -2879,7 -2879,7 +3041,7 @@@@@@@ static int snd_soc_register_dais(struc
        unsigned int i;
        int ret;
      
 -- --  dev_dbg(dev, "ASoC: dai register %s #%Zu\n", dev_name(dev), count);
 ++ ++  dev_dbg(dev, "ASoC: dai register %s #%zu\n", dev_name(dev), count);
      
        component->dai_drv = dai_drv;
      
@@@@@@@ -3138,8 -2976,6 -2976,6 -3138,8 -2976,6 -2976,6 +3138,8 @@@@@@@ static int snd_soc_component_initialize
        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;
@@@@@@@ -3240,6 -3076,6 -3076,11 -3240,6 -3076,6 -3076,6 +3240,11 @@@@@@@ static void snd_soc_component_cleanup(s
      
      static void snd_soc_component_del_unlocked(struct snd_soc_component *component)
      {
++ +++  struct snd_soc_card *card = component->card;
++ +++
++ +++  if (card)
++ +++          snd_soc_unregister_card(card);
++ +++
        list_del(&component->list);
      }
      
@@@@@@@ -3322,25 -3158,6 -3163,6 -3322,21 -3158,6 -3158,6 +3327,25 @@@@@@@ static void snd_soc_platform_drv_remove
        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
@@@@@@@ -3364,10 -3181,6 -3186,6 -3360,10 -3181,6 -3181,6 +3369,10 @@@@@@@ int snd_soc_add_platform(struct device 
                platform->component.probe = snd_soc_platform_drv_probe;
        if (platform_drv->remove)
                platform->component.remove = snd_soc_platform_drv_remove;
 ++ ++  if (platform_drv->pcm_new)
 ++ ++          platform->component.pcm_new = snd_soc_platform_drv_pcm_new;
 ++ ++  if (platform_drv->pcm_free)
 ++ ++          platform->component.pcm_free = snd_soc_platform_drv_pcm_free;
      
      #ifdef CONFIG_DEBUG_FS
        platform->component.debugfs_prefix = "platform";
      EXPORT_SYMBOL_GPL(snd_soc_unregister_codec);
      
      /* Retrieve a card's name from device tree */
 -- --int snd_soc_of_parse_card_name_from_node(struct snd_soc_card *card,
 -- --                                   struct device_node *np,
 -- --                                   const char *propname)
 ++ ++int snd_soc_of_parse_card_name(struct snd_soc_card *card,
 ++ ++                         const char *propname)
      {
 ++ ++  struct device_node *np;
        int ret;
      
        if (!card->dev) {
                return -EINVAL;
        }
      
 -- --  if (!np)
 -- --          np = card->dev->of_node;
 ++ ++  np = card->dev->of_node;
      
        ret = of_property_read_string_index(np, propname, 0, &card->name);
        /*
      
        return 0;
      }
 -- --EXPORT_SYMBOL_GPL(snd_soc_of_parse_card_name_from_node);
 ++ ++EXPORT_SYMBOL_GPL(snd_soc_of_parse_card_name);
      
      static const struct snd_soc_dapm_widget simple_widgets[] = {
        SND_SOC_DAPM_MIC("Microphone", NULL),
        SND_SOC_DAPM_SPK("Speaker", NULL),
      };
      
 -- --int snd_soc_of_parse_audio_simple_widgets_from_node(struct snd_soc_card *card,
 -- --                                    struct device_node *np,
 ++ ++int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card,
                                          const char *propname)
      {
 ++ ++  struct device_node *np = card->dev->of_node;
        struct snd_soc_dapm_widget *widgets;
        const char *template, *wname;
        int i, j, num_widgets, ret;
      
 -- --  if (!np)
 -- --          np = card->dev->of_node;
 -- --
        num_widgets = of_property_count_strings(np, propname);
        if (num_widgets < 0) {
                dev_err(card->dev,
      
        return 0;
      }
 -- --EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_simple_widgets_from_node);
 ++ ++EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_simple_widgets);
      
      static int snd_soc_of_get_slot_mask(struct device_node *np,
                                    const char *prop_name,
@@@@@@@ -3850,15 -3667,18 -3672,18 -3846,15 -3667,18 -3667,18 +3855,15 @@@@@@@ int snd_soc_of_parse_tdm_slot(struct de
      }
      EXPORT_SYMBOL_GPL(snd_soc_of_parse_tdm_slot);
      
 -- --void snd_soc_of_parse_audio_prefix_from_node(struct snd_soc_card *card,
 -- --                             struct device_node *np,
 ++ ++void snd_soc_of_parse_audio_prefix(struct snd_soc_card *card,
                                   struct snd_soc_codec_conf *codec_conf,
                                   struct device_node *of_node,
                                   const char *propname)
      {
 ++ ++  struct device_node *np = card->dev->of_node;
        const char *str;
        int ret;
      
 -- --  if (!np)
 -- --          np = card->dev->of_node;
 -- --
        ret = of_property_read_string(np, propname, &str);
        if (ret < 0) {
                /* no prefix is not error */
        codec_conf->of_node     = of_node;
        codec_conf->name_prefix = str;
      }
 -- --EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_prefix_from_node);
 ++ ++EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_prefix);
      
 -- --int snd_soc_of_parse_audio_routing_from_node(struct snd_soc_card *card,
 -- --                             struct device_node *np,
 ++ ++int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
                                   const char *propname)
      {
 ++ ++  struct device_node *np = card->dev->of_node;
        int num_routes;
        struct snd_soc_dapm_route *routes;
        int i, ret;
      
 -- --  if (!np)
 -- --          np = card->dev->of_node;
 -- --
        num_routes = of_property_count_strings(np, propname);
        if (num_routes < 0 || num_routes & 1) {
                dev_err(card->dev,
      
        return 0;
      }
 -- --EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_routing_from_node);
 ++ ++EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_routing);
      
      unsigned int snd_soc_of_parse_daifmt(struct device_node *np,
                                     const char *prefix,
@@@@@@@ -4197,6 -4020,8 -4025,8 -4193,6 -4020,8 -4020,8 +4202,6 @@@@@@@ static void __exit snd_soc_exit(void
        snd_soc_util_exit();
        snd_soc_debugfs_exit();
      
 -- --#ifdef CONFIG_DEBUG_FS
 -- --#endif
        platform_driver_unregister(&soc_driver);
      }
      module_exit(snd_soc_exit);