X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=sound%2Fsoc%2Fsoc-core.c;h=c8d8dde7f4dde22db733245e7e6a0a6f0cb8befb;hb=5033f43c66754296dfb0ac5c895208e4a7f93aac;hp=1c8f3f507f54e7d1fc469ff03a2fdbf787640e3a;hpb=9ae21ca362679757786f5abe556c7943e9001426;p=deliverable%2Flinux.git diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 1c8f3f507f54..c8d8dde7f4dd 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -36,9 +36,11 @@ #include #include #include -#include #include +#define CREATE_TRACE_POINTS +#include + #define NAME_SIZE 32 static DEFINE_MUTEX(pcm_mutex); @@ -165,8 +167,11 @@ static ssize_t pmdown_time_set(struct device *dev, { struct snd_soc_pcm_runtime *rtd = container_of(dev, struct snd_soc_pcm_runtime, dev); + int ret; - strict_strtol(buf, 10, &rtd->pmdown_time); + ret = strict_strtol(buf, 10, &rtd->pmdown_time); + if (ret) + return ret; return count; } @@ -235,8 +240,10 @@ static const struct file_operations codec_reg_fops = { static void soc_init_codec_debugfs(struct snd_soc_codec *codec) { - codec->debugfs_codec_root = debugfs_create_dir(codec->name , - debugfs_root); + struct dentry *debugfs_card_root = codec->card->debugfs_card_root; + + codec->debugfs_codec_root = debugfs_create_dir(codec->name, + debugfs_card_root); if (!codec->debugfs_codec_root) { printk(KERN_WARNING "ASoC: Failed to create codec debugfs directory\n"); @@ -250,20 +257,13 @@ static void soc_init_codec_debugfs(struct snd_soc_codec *codec) printk(KERN_WARNING "ASoC: Failed to create codec register debugfs file\n"); - codec->debugfs_pop_time = debugfs_create_u32("dapm_pop_time", 0644, - codec->debugfs_codec_root, - &codec->pop_time); - if (!codec->debugfs_pop_time) - printk(KERN_WARNING - "Failed to create pop time debugfs file\n"); - - codec->debugfs_dapm = debugfs_create_dir("dapm", + codec->dapm.debugfs_dapm = debugfs_create_dir("dapm", codec->debugfs_codec_root); - if (!codec->debugfs_dapm) + if (!codec->dapm.debugfs_dapm) printk(KERN_WARNING "Failed to create DAPM debugfs directory\n"); - snd_soc_dapm_debugfs_init(codec); + snd_soc_dapm_debugfs_init(&codec->dapm); } static void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec) @@ -371,6 +371,29 @@ static const struct file_operations platform_list_fops = { .llseek = default_llseek,/* read accesses f_pos */ }; +static void soc_init_card_debugfs(struct snd_soc_card *card) +{ + card->debugfs_card_root = debugfs_create_dir(card->name, + debugfs_root); + if (!card->debugfs_card_root) { + dev_warn(card->dev, + "ASoC: Failed to create codec debugfs directory\n"); + return; + } + + card->debugfs_pop_time = debugfs_create_u32("dapm_pop_time", 0644, + card->debugfs_card_root, + &card->pop_time); + if (!card->debugfs_pop_time) + dev_warn(card->dev, + "Failed to create pop time debugfs file\n"); +} + +static void soc_cleanup_card_debugfs(struct snd_soc_card *card) +{ + debugfs_remove_recursive(card->debugfs_card_root); +} + #else static inline void soc_init_codec_debugfs(struct snd_soc_codec *codec) @@ -380,6 +403,14 @@ static inline void soc_init_codec_debugfs(struct snd_soc_codec *codec) static inline void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec) { } + +static inline void soc_init_card_debugfs(struct snd_soc_card *card) +{ +} + +static inline void soc_cleanup_card_debugfs(struct snd_soc_card *card) +{ +} #endif #ifdef CONFIG_SND_SOC_AC97_BUS @@ -1014,7 +1045,7 @@ static int soc_suspend(struct device *dev) /* close any waiting streams and save state */ for (i = 0; i < card->num_rtd; i++) { run_delayed_work(&card->rtd[i].delayed_work); - card->rtd[i].codec->suspend_bias_level = card->rtd[i].codec->bias_level; + card->rtd[i].codec->dapm.suspend_bias_level = card->rtd[i].codec->dapm.bias_level; } for (i = 0; i < card->num_rtd; i++) { @@ -1038,7 +1069,7 @@ static int soc_suspend(struct device *dev) /* If there are paths active then the CODEC will be held with * bias _ON and should not be suspended. */ if (!codec->suspended && codec->driver->suspend) { - switch (codec->bias_level) { + switch (codec->dapm.bias_level) { case SND_SOC_BIAS_STANDBY: case SND_SOC_BIAS_OFF: codec->driver->suspend(codec, PMSG_SUSPEND); @@ -1107,7 +1138,7 @@ static void soc_resume_deferred(struct work_struct *work) * resume. Otherwise the suspend was suppressed. */ if (codec->driver->resume && codec->suspended) { - switch (codec->bias_level) { + switch (codec->dapm.bias_level) { case SND_SOC_BIAS_STANDBY: case SND_SOC_BIAS_OFF: codec->driver->resume(codec); @@ -1343,7 +1374,7 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num) } /* Make sure all DAPM widgets are freed */ - snd_soc_dapm_free(codec); + snd_soc_dapm_free(&codec->dapm); soc_cleanup_codec_debugfs(codec); device_remove_file(&rtd->dev, &dev_attr_codec_reg); @@ -1365,6 +1396,23 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num) } } +static void soc_set_name_prefix(struct snd_soc_card *card, + struct snd_soc_codec *codec) +{ + int i; + + if (card->prefix_map == NULL) + return; + + for (i = 0; i < card->num_prefixes; i++) { + struct snd_soc_prefix_map *map = &card->prefix_map[i]; + if (map->dev_name && !strcmp(codec->name, map->dev_name)) { + codec->name_prefix = map->name_prefix; + break; + } + } +} + static void rtd_release(struct device *dev) {} static int soc_probe_dai_link(struct snd_soc_card *card, int num) @@ -1374,6 +1422,7 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num) struct snd_soc_codec *codec = rtd->codec; struct snd_soc_platform *platform = rtd->platform; struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai; + const char *temp; int ret; dev_dbg(card->dev, "probe %s dai link %d\n", card->name, num); @@ -1407,6 +1456,8 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num) /* probe the CODEC */ if (!codec->probed) { + codec->dapm.card = card; + soc_set_name_prefix(card, codec); if (codec->driver->probe) { ret = codec->driver->probe(codec); if (ret < 0) { @@ -1459,16 +1510,20 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num) /* now that all clients have probed, initialise the DAI link */ if (dai_link->init) { + /* machine controls, routes and widgets are not prefixed */ + temp = rtd->codec->name_prefix; + rtd->codec->name_prefix = NULL; ret = dai_link->init(rtd); if (ret < 0) { printk(KERN_ERR "asoc: failed to init %s\n", dai_link->stream_name); return ret; } + rtd->codec->name_prefix = temp; } /* Make sure all DAPM widgets are instantiated */ - snd_soc_dapm_new_widgets(codec); - snd_soc_dapm_sync(codec); + snd_soc_dapm_new_widgets(&codec->dapm); + snd_soc_dapm_sync(&codec->dapm); /* register the rtd device */ rtd->dev.release = rtd_release; @@ -1664,6 +1719,8 @@ static int soc_probe(struct platform_device *pdev) INIT_LIST_HEAD(&card->codec_dev_list); INIT_LIST_HEAD(&card->platform_dev_list); + soc_init_card_debugfs(card); + ret = snd_soc_register_card(card); if (ret != 0) { dev_err(&pdev->dev, "Failed to register card\n"); @@ -1691,6 +1748,8 @@ static int soc_remove(struct platform_device *pdev) for (i = 0; i < card->num_rtd; i++) soc_remove_dai_link(card, i); + soc_cleanup_card_debugfs(card); + /* remove the card */ if (card->remove) card->remove(pdev); @@ -1874,6 +1933,27 @@ void snd_soc_free_ac97_codec(struct snd_soc_codec *codec) } EXPORT_SYMBOL_GPL(snd_soc_free_ac97_codec); +unsigned int snd_soc_read(struct snd_soc_codec *codec, unsigned int reg) +{ + unsigned int ret; + + ret = codec->driver->read(codec, reg); + dev_dbg(codec->dev, "read %x => %x\n", reg, ret); + trace_snd_soc_reg_read(codec, reg, ret); + + return ret; +} +EXPORT_SYMBOL_GPL(snd_soc_read); + +unsigned int snd_soc_write(struct snd_soc_codec *codec, + unsigned int reg, unsigned int val) +{ + dev_dbg(codec->dev, "write %x = %x\n", reg, val); + trace_snd_soc_reg_write(codec, reg, val); + return codec->driver->write(codec, reg, val); +} +EXPORT_SYMBOL_GPL(snd_soc_write); + /** * snd_soc_update_bits - update codec register bits * @codec: audio codec @@ -2014,14 +2094,22 @@ int snd_soc_add_controls(struct snd_soc_codec *codec, const struct snd_kcontrol_new *controls, int num_controls) { struct snd_card *card = codec->card->snd_card; + char prefixed_name[44], *name; int err, i; for (i = 0; i < num_controls; i++) { const struct snd_kcontrol_new *control = &controls[i]; - err = snd_ctl_add(card, snd_soc_cnew(control, codec, NULL)); + if (codec->name_prefix) { + snprintf(prefixed_name, sizeof(prefixed_name), "%s %s", + codec->name_prefix, control->name); + name = prefixed_name; + } else { + name = control->name; + } + err = snd_ctl_add(card, snd_soc_cnew(control, codec, name)); if (err < 0) { dev_err(codec->dev, "%s: Failed to add %s: %d\n", - codec->name, control->name, err); + codec->name, name, err); return err; } } @@ -3040,8 +3128,10 @@ int snd_soc_register_dais(struct device *dev, for (i = 0; i < count; i++) { dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL); - if (dai == NULL) - return -ENOMEM; + if (dai == NULL) { + ret = -ENOMEM; + goto err; + } /* create DAI component name */ dai->name = fmt_multiple_name(dev, &dai_drv[i]); @@ -3214,30 +3304,25 @@ int snd_soc_register_codec(struct device *dev, return -ENOMEM; } - /* allocate CODEC register cache */ - if (codec_drv->reg_cache_size && codec_drv->reg_word_size) { - - if (codec_drv->reg_cache_default) - codec->reg_cache = kmemdup(codec_drv->reg_cache_default, - codec_drv->reg_cache_size * codec_drv->reg_word_size, GFP_KERNEL); - else - codec->reg_cache = kzalloc(codec_drv->reg_cache_size * - codec_drv->reg_word_size, GFP_KERNEL); - - if (codec->reg_cache == NULL) { - kfree(codec->name); - kfree(codec); - return -ENOMEM; - } - } - + INIT_LIST_HEAD(&codec->dapm.widgets); + INIT_LIST_HEAD(&codec->dapm.paths); + codec->dapm.bias_level = SND_SOC_BIAS_OFF; + codec->dapm.dev = dev; + codec->dapm.codec = codec; codec->dev = dev; codec->driver = codec_drv; - codec->bias_level = SND_SOC_BIAS_OFF; codec->num_dai = num_dai; mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); + + /* allocate CODEC register cache */ + if (codec_drv->reg_cache_size && codec_drv->reg_word_size) { + ret = snd_soc_cache_init(codec); + if (ret < 0) { + dev_err(codec->dev, "Failed to set cache compression type: %d\n", + ret); + goto error_cache; + } + } for (i = 0; i < num_dai; i++) { fixup_codec_formats(&dai_drv[i].playback); @@ -3248,7 +3333,7 @@ int snd_soc_register_codec(struct device *dev, if (num_dai) { ret = snd_soc_register_dais(dev, dai_drv, num_dai); if (ret < 0) - goto error; + goto error_dais; } mutex_lock(&client_mutex); @@ -3259,12 +3344,9 @@ int snd_soc_register_codec(struct device *dev, pr_debug("Registered codec '%s'\n", codec->name); return 0; -error: - for (i--; i >= 0; i--) - snd_soc_unregister_dai(dev); - - if (codec->reg_cache) - kfree(codec->reg_cache); +error_dais: + snd_soc_cache_exit(codec); +error_cache: kfree(codec->name); kfree(codec); return ret; @@ -3298,8 +3380,7 @@ found: pr_debug("Unregistered codec '%s'\n", codec->name); - if (codec->reg_cache) - kfree(codec->reg_cache); + snd_soc_cache_exit(codec); kfree(codec->name); kfree(codec); }