Merge branch 'for-2.6.38' into for-2.6.39
authorMark Brown <broonie@opensource.wolfsonmicro.com>
Thu, 27 Jan 2011 15:16:52 +0000 (15:16 +0000)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Thu, 27 Jan 2011 15:16:52 +0000 (15:16 +0000)
1  2 
sound/soc/soc-core.c

diff --combined sound/soc/soc-core.c
index 8af47f7a8fcbe6367ed360327a30d62288310b05,c4b60610beb002b04f1e8d81aeb12bc8c9f2b82c..e9f81c551e5e5ca3594153354fe4b4f3d58ce48f
@@@ -48,8 -48,7 +48,8 @@@ static DEFINE_MUTEX(pcm_mutex)
  static DECLARE_WAIT_QUEUE_HEAD(soc_pm_waitq);
  
  #ifdef CONFIG_DEBUG_FS
 -static struct dentry *debugfs_root;
 +struct dentry *snd_soc_debugfs_root;
 +EXPORT_SYMBOL_GPL(snd_soc_debugfs_root);
  #endif
  
  static DEFINE_MUTEX(client_mutex);
@@@ -58,6 -57,8 +58,6 @@@ static LIST_HEAD(dai_list)
  static LIST_HEAD(platform_list);
  static LIST_HEAD(codec_list);
  
 -static int snd_soc_register_card(struct snd_soc_card *card);
 -static int snd_soc_unregister_card(struct snd_soc_card *card);
  static int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num);
  
  /*
@@@ -82,7 -83,7 +82,7 @@@ static ssize_t soc_codec_reg_show(struc
  
        count += sprintf(buf, "%s registers\n", codec->name);
        for (i = 0; i < codec->driver->reg_cache_size; i += step) {
 -              if (codec->driver->readable_register && !codec->driver->readable_register(i))
 +              if (codec->readable_register && !codec->readable_register(codec, i))
                        continue;
  
                count += sprintf(buf + count, "%2x: ", i);
@@@ -208,10 -209,6 +208,10 @@@ static ssize_t codec_reg_write_file(str
                start++;
        if (strict_strtoul(start, 16, &value))
                return -EINVAL;
 +
 +      /* Userspace has been fiddling around behind the kernel's back */
 +      add_taint(TAINT_USER);
 +
        snd_soc_write(codec, reg, value);
        return buf_size;
  }
@@@ -235,11 -232,6 +235,11 @@@ static void soc_init_codec_debugfs(stru
                return;
        }
  
 +      debugfs_create_bool("cache_sync", 0444, codec->debugfs_codec_root,
 +                          &codec->cache_sync);
 +      debugfs_create_bool("cache_only", 0444, codec->debugfs_codec_root,
 +                          &codec->cache_only);
 +
        codec->debugfs_reg = debugfs_create_file("codec_reg", 0644,
                                                 codec->debugfs_codec_root,
                                                 codec, &codec_reg_fops);
@@@ -364,7 -356,7 +364,7 @@@ static const struct file_operations pla
  static void soc_init_card_debugfs(struct snd_soc_card *card)
  {
        card->debugfs_card_root = debugfs_create_dir(card->name,
 -                                                   debugfs_root);
 +                                                   snd_soc_debugfs_root);
        if (!card->debugfs_card_root) {
                dev_warn(card->dev,
                         "ASoC: Failed to create codec debugfs directory\n");
@@@ -970,11 -962,12 +970,11 @@@ static struct snd_pcm_ops soc_pcm_ops 
        .pointer        = soc_pcm_pointer,
  };
  
 -#ifdef CONFIG_PM
 +#ifdef CONFIG_PM_SLEEP
  /* powers down audio subsystem for suspend */
 -static int soc_suspend(struct device *dev)
 +int snd_soc_suspend(struct device *dev)
  {
 -      struct platform_device *pdev = to_platform_device(dev);
 -      struct snd_soc_card *card = platform_get_drvdata(pdev);
 +      struct snd_soc_card *card = dev_get_drvdata(dev);
        struct snd_soc_codec *codec;
        int i;
  
        }
  
        if (card->suspend_pre)
 -              card->suspend_pre(pdev, PMSG_SUSPEND);
 +              card->suspend_pre(card);
  
        for (i = 0; i < card->num_rtd; i++) {
                struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai;
        }
  
        if (card->suspend_post)
 -              card->suspend_post(pdev, PMSG_SUSPEND);
 +              card->suspend_post(card);
  
        return 0;
  }
 +EXPORT_SYMBOL_GPL(snd_soc_suspend);
  
  /* deferred resume work, so resume can complete before we finished
   * setting our codec back up, which can be very slow on I2C
@@@ -1095,6 -1087,7 +1095,6 @@@ static void soc_resume_deferred(struct 
  {
        struct snd_soc_card *card =
                        container_of(work, struct snd_soc_card, deferred_resume_work);
 -      struct platform_device *pdev = to_platform_device(card->dev);
        struct snd_soc_codec *codec;
        int i;
  
        snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D2);
  
        if (card->resume_pre)
 -              card->resume_pre(pdev);
 +              card->resume_pre(card);
  
        /* resume AC97 DAIs */
        for (i = 0; i < card->num_rtd; i++) {
        }
  
        if (card->resume_post)
 -              card->resume_post(pdev);
 +              card->resume_post(card);
  
        dev_dbg(card->dev, "resume work completed\n");
  
  }
  
  /* powers up audio subsystem after a suspend */
 -static int soc_resume(struct device *dev)
 +int snd_soc_resume(struct device *dev)
  {
 -      struct platform_device *pdev = to_platform_device(dev);
 -      struct snd_soc_card *card = platform_get_drvdata(pdev);
 +      struct snd_soc_card *card = dev_get_drvdata(dev);
        int i;
  
        /* AC97 devices might have other drivers hanging off them so
  
        return 0;
  }
 +EXPORT_SYMBOL_GPL(snd_soc_resume);
  #else
 -#define soc_suspend   NULL
 -#define soc_resume    NULL
 +#define snd_soc_suspend NULL
 +#define snd_soc_resume NULL
  #endif
  
  static struct snd_soc_dai_ops null_dai_ops = {
@@@ -1474,6 -1467,7 +1474,6 @@@ static int soc_post_component_init(stru
  
        /* Make sure all DAPM widgets are instantiated */
        snd_soc_dapm_new_widgets(&codec->dapm);
 -      snd_soc_dapm_sync(&codec->dapm);
  
        /* register the rtd device */
        rtd->codec = codec;
@@@ -1670,9 -1664,6 +1670,6 @@@ static int soc_probe_aux_dev(struct snd
        goto out;
  
  found:
-       if (!try_module_get(codec->dev->driver->owner))
-               return -ENODEV;
        ret = soc_probe_codec(card, codec);
        if (ret < 0)
                return ret;
@@@ -1722,6 -1713,7 +1719,6 @@@ static int snd_soc_init_codec_cache(str
  
  static void snd_soc_instantiate_card(struct snd_soc_card *card)
  {
 -      struct platform_device *pdev = to_platform_device(card->dev);
        struct snd_soc_codec *codec;
        struct snd_soc_codec_conf *codec_conf;
        enum snd_soc_compress_type compress_type;
        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];
                                        break;
                        }
                }
 -              if (i == card->num_configs) {
 -                      /* no need to override the compress_type so
 -                       * go ahead and do the standard thing */
 -                      ret = snd_soc_init_codec_cache(codec, 0);
 -                      if (ret < 0) {
 -                              mutex_unlock(&card->mutex);
 -                              return;
 -                      }
 -                      continue;
 -              }
 -              /* override the compress_type with the one supplied in
 -               * the machine driver */
                ret = snd_soc_init_codec_cache(codec, compress_type);
                if (ret < 0) {
                        mutex_unlock(&card->mutex);
  
        /* initialise the sound card only once */
        if (card->probe) {
 -              ret = card->probe(pdev);
 +              ret = card->probe(card);
                if (ret < 0)
                        goto card_probe_error;
        }
@@@ -1846,7 -1848,7 +1843,7 @@@ probe_dai_err
  
  card_probe_error:
        if (card->remove)
 -              card->remove(pdev);
 +              card->remove(card);
  
        snd_card_free(card->snd_card);
  
@@@ -1870,16 -1872,16 +1867,16 @@@ static int soc_probe(struct platform_de
        struct snd_soc_card *card = platform_get_drvdata(pdev);
        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;
 -      INIT_LIST_HEAD(&card->dai_dev_list);
 -      INIT_LIST_HEAD(&card->codec_dev_list);
 -      INIT_LIST_HEAD(&card->platform_dev_list);
 -      INIT_LIST_HEAD(&card->widgets);
 -      INIT_LIST_HEAD(&card->paths);
 -      INIT_LIST_HEAD(&card->dapm_list);
 -
 -      soc_init_card_debugfs(card);
 +      snd_soc_initialize_card_lists(card);
  
        ret = snd_soc_register_card(card);
        if (ret != 0) {
        return 0;
  }
  
 -/* removes a socdev */
 -static int soc_remove(struct platform_device *pdev)
 +static int soc_cleanup_card_resources(struct snd_soc_card *card)
  {
 -      struct snd_soc_card *card = platform_get_drvdata(pdev);
        int i;
  
 -              if (card->instantiated) {
 +      /* make sure any delayed work runs */
 +      for (i = 0; i < card->num_rtd; i++) {
 +              struct snd_soc_pcm_runtime *rtd = &card->rtd[i];
 +              flush_delayed_work_sync(&rtd->delayed_work);
 +      }
  
 -              /* make sure any delayed work runs */
 -              for (i = 0; i < card->num_rtd; i++) {
 -                      struct snd_soc_pcm_runtime *rtd = &card->rtd[i];
 -                      flush_delayed_work_sync(&rtd->delayed_work);
 -              }
 +      /* remove auxiliary devices */
 +      for (i = 0; i < card->num_aux_devs; i++)
 +              soc_remove_aux_dev(card, i);
  
 -              /* remove auxiliary devices */
 -              for (i = 0; i < card->num_aux_devs; i++)
 -                      soc_remove_aux_dev(card, i);
 +      /* remove and free each DAI */
 +      for (i = 0; i < card->num_rtd; i++)
 +              soc_remove_dai_link(card, i);
  
 -              /* remove and free each DAI */
 -              for (i = 0; i < card->num_rtd; i++)
 -                      soc_remove_dai_link(card, i);
 +      soc_cleanup_card_debugfs(card);
  
 -              soc_cleanup_card_debugfs(card);
 +      /* remove the card */
 +      if (card->remove)
 +              card->remove(card);
  
 -              /* remove the card */
 -              if (card->remove)
 -                      card->remove(pdev);
 +      kfree(card->rtd);
 +      snd_card_free(card->snd_card);
 +      return 0;
 +
 +}
 +
 +/* removes a socdev */
 +static int soc_remove(struct platform_device *pdev)
 +{
 +      struct snd_soc_card *card = platform_get_drvdata(pdev);
  
 -              kfree(card->rtd);
 -              snd_card_free(card->snd_card);
 -      }
        snd_soc_unregister_card(card);
        return 0;
  }
  
 -static int soc_poweroff(struct device *dev)
 +int snd_soc_poweroff(struct device *dev)
  {
 -      struct platform_device *pdev = to_platform_device(dev);
 -      struct snd_soc_card *card = platform_get_drvdata(pdev);
 +      struct snd_soc_card *card = dev_get_drvdata(dev);
        int i;
  
        if (!card->instantiated)
  
        return 0;
  }
 +EXPORT_SYMBOL_GPL(snd_soc_poweroff);
  
 -static const struct dev_pm_ops soc_pm_ops = {
 -      .suspend = soc_suspend,
 -      .resume = soc_resume,
 -      .poweroff = soc_poweroff,
 +const struct dev_pm_ops snd_soc_pm_ops = {
 +      .suspend = snd_soc_suspend,
 +      .resume = snd_soc_resume,
 +      .poweroff = snd_soc_poweroff,
  };
  
  /* ASoC platform driver */
@@@ -1961,7 -1959,7 +1958,7 @@@ static struct platform_driver soc_drive
        .driver         = {
                .name           = "soc-audio",
                .owner          = THIS_MODULE,
 -              .pm             = &soc_pm_ops,
 +              .pm             = &snd_soc_pm_ops,
        },
        .probe          = soc_probe,
        .remove         = soc_remove,
@@@ -2031,11 -2029,10 +2028,11 @@@ static int soc_new_pcm(struct snd_soc_p
   *
   * Boolean function indiciating if a CODEC register is volatile.
   */
 -int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, int reg)
 +int snd_soc_codec_volatile_register(struct snd_soc_codec *codec,
 +                                  unsigned int reg)
  {
 -      if (codec->driver->volatile_register)
 -              return codec->driver->volatile_register(reg);
 +      if (codec->volatile_register)
 +              return codec->volatile_register(codec, reg);
        else
                return 0;
  }
@@@ -2132,27 -2129,19 +2129,27 @@@ EXPORT_SYMBOL_GPL(snd_soc_write)
   *
   * Writes new register value.
   *
 - * Returns 1 for change else 0.
 + * Returns 1 for change, 0 for no change, or negative error code.
   */
  int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg,
                                unsigned int mask, unsigned int value)
  {
        int change;
        unsigned int old, new;
 +      int ret;
  
 -      old = snd_soc_read(codec, reg);
 +      ret = snd_soc_read(codec, reg);
 +      if (ret < 0)
 +              return ret;
 +
 +      old = ret;
        new = (old & ~mask) | value;
        change = old != new;
 -      if (change)
 -              snd_soc_write(codec, reg, new);
 +      if (change) {
 +              ret = snd_soc_write(codec, reg, new);
 +              if (ret < 0)
 +                      return ret;
 +      }
  
        return change;
  }
@@@ -3112,16 -3101,17 +3109,16 @@@ EXPORT_SYMBOL_GPL(snd_soc_dai_digital_m
   *
   * @card: Card to register
   *
 - * Note that currently this is an internal only function: it will be
 - * exposed to machine drivers after further backporting of ASoC v2
 - * registration APIs.
   */
 -static int snd_soc_register_card(struct snd_soc_card *card)
 +int snd_soc_register_card(struct snd_soc_card *card)
  {
        int i;
  
        if (!card->name || !card->dev)
                return -EINVAL;
  
 +      soc_init_card_debugfs(card);
 +
        card->rtd = kzalloc(sizeof(struct snd_soc_pcm_runtime) *
                            (card->num_links + card->num_aux_devs),
                            GFP_KERNEL);
  
        return 0;
  }
 +EXPORT_SYMBOL_GPL(snd_soc_register_card);
  
  /**
   * snd_soc_unregister_card - Unregister a card with the ASoC core
   *
   * @card: Card to unregister
   *
 - * Note that currently this is an internal only function: it will be
 - * exposed to machine drivers after further backporting of ASoC v2
 - * registration APIs.
   */
 -static int snd_soc_unregister_card(struct snd_soc_card *card)
 +int snd_soc_unregister_card(struct snd_soc_card *card)
  {
 +      if (card->instantiated)
 +              soc_cleanup_card_resources(card);
        mutex_lock(&client_mutex);
        list_del(&card->list);
        mutex_unlock(&client_mutex);
  
        return 0;
  }
 +EXPORT_SYMBOL_GPL(snd_soc_unregister_card);
  
  /*
   * Simplify DAI link configuration by removing ".-1" from device names
@@@ -3494,12 -3483,9 +3491,12 @@@ int snd_soc_register_codec(struct devic
  
        codec->write = codec_drv->write;
        codec->read = codec_drv->read;
 +      codec->volatile_register = codec_drv->volatile_register;
 +      codec->readable_register = codec_drv->readable_register;
        codec->dapm.bias_level = SND_SOC_BIAS_OFF;
        codec->dapm.dev = dev;
        codec->dapm.codec = codec;
 +      codec->dapm.seq_notifier = codec_drv->seq_notifier;
        codec->dev = dev;
        codec->driver = codec_drv;
        codec->num_dai = num_dai;
        /* allocate CODEC register cache */
        if (codec_drv->reg_cache_size && codec_drv->reg_word_size) {
                reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size;
 +              codec->reg_size = reg_size;
                /* it is necessary to make a copy of the default register cache
                 * because in the case of using a compression type that requires
                 * the default register cache to be marked as __devinitconst the
                 * kernel might have freed the array by the time we initialize
                 * the cache.
                 */
 -              codec->reg_def_copy = kmemdup(codec_drv->reg_cache_default,
 -                                            reg_size, GFP_KERNEL);
 -              if (!codec->reg_def_copy) {
 -                      ret = -ENOMEM;
 -                      goto fail;
 +              if (codec_drv->reg_cache_default) {
 +                      codec->reg_def_copy = kmemdup(codec_drv->reg_cache_default,
 +                                                    reg_size, GFP_KERNEL);
 +                      if (!codec->reg_def_copy) {
 +                              ret = -ENOMEM;
 +                              goto fail;
 +                      }
                }
        }
  
 +      if (codec_drv->reg_access_size && codec_drv->reg_access_default) {
 +              if (!codec->volatile_register)
 +                      codec->volatile_register = snd_soc_default_volatile_register;
 +              if (!codec->readable_register)
 +                      codec->readable_register = snd_soc_default_readable_register;
 +      }
 +
        for (i = 0; i < num_dai; i++) {
                fixup_codec_formats(&dai_drv[i].playback);
                fixup_codec_formats(&dai_drv[i].capture);
@@@ -3598,22 -3574,22 +3595,22 @@@ EXPORT_SYMBOL_GPL(snd_soc_unregister_co
  static int __init snd_soc_init(void)
  {
  #ifdef CONFIG_DEBUG_FS
 -      debugfs_root = debugfs_create_dir("asoc", NULL);
 -      if (IS_ERR(debugfs_root) || !debugfs_root) {
 +      snd_soc_debugfs_root = debugfs_create_dir("asoc", NULL);
 +      if (IS_ERR(snd_soc_debugfs_root) || !snd_soc_debugfs_root) {
                printk(KERN_WARNING
                       "ASoC: Failed to create debugfs directory\n");
 -              debugfs_root = NULL;
 +              snd_soc_debugfs_root = NULL;
        }
  
 -      if (!debugfs_create_file("codecs", 0444, debugfs_root, NULL,
 +      if (!debugfs_create_file("codecs", 0444, snd_soc_debugfs_root, NULL,
                                 &codec_list_fops))
                pr_warn("ASoC: Failed to create CODEC list debugfs file\n");
  
 -      if (!debugfs_create_file("dais", 0444, debugfs_root, NULL,
 +      if (!debugfs_create_file("dais", 0444, snd_soc_debugfs_root, NULL,
                                 &dai_list_fops))
                pr_warn("ASoC: Failed to create DAI list debugfs file\n");
  
 -      if (!debugfs_create_file("platforms", 0444, debugfs_root, NULL,
 +      if (!debugfs_create_file("platforms", 0444, snd_soc_debugfs_root, NULL,
                                 &platform_list_fops))
                pr_warn("ASoC: Failed to create platform list debugfs file\n");
  #endif
@@@ -3625,7 -3601,7 +3622,7 @@@ module_init(snd_soc_init)
  static void __exit snd_soc_exit(void)
  {
  #ifdef CONFIG_DEBUG_FS
 -      debugfs_remove_recursive(debugfs_root);
 +      debugfs_remove_recursive(snd_soc_debugfs_root);
  #endif
        platform_driver_unregister(&soc_driver);
  }