diff options
Diffstat (limited to 'sound/soc/soc-core.c')
-rw-r--r-- | sound/soc/soc-core.c | 380 |
1 files changed, 157 insertions, 223 deletions
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index a66783e..1a38be0 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -662,8 +662,6 @@ int snd_soc_suspend(struct device *dev) codec->cache_sync = 1; if (codec->using_regmap) regcache_mark_dirty(codec->control_data); - /* deactivate pins to sleep state */ - pinctrl_pm_select_sleep_state(codec->dev); break; default: dev_dbg(codec->dev, @@ -681,9 +679,6 @@ int snd_soc_suspend(struct device *dev) if (cpu_dai->driver->suspend && cpu_dai->driver->ac97_control) cpu_dai->driver->suspend(cpu_dai); - - /* deactivate pins to sleep state */ - pinctrl_pm_select_sleep_state(cpu_dai->dev); } if (card->suspend_post) @@ -812,16 +807,6 @@ int snd_soc_resume(struct device *dev) if (list_empty(&card->codec_dev_list)) return 0; - /* activate pins from sleep state */ - for (i = 0; i < card->num_rtd; i++) { - struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; - struct snd_soc_dai *codec_dai = card->rtd[i].codec_dai; - if (cpu_dai->active) - pinctrl_pm_select_default_state(cpu_dai->dev); - if (codec_dai->active) - pinctrl_pm_select_default_state(codec_dai->dev); - } - /* AC97 devices might have other drivers hanging off them so * need to resume immediately. Other drivers don't have that * problem and may take a substantial amount of time to resume @@ -1604,13 +1589,17 @@ static void soc_remove_aux_dev(struct snd_soc_card *card, int num) soc_remove_codec(codec); } -static int snd_soc_init_codec_cache(struct snd_soc_codec *codec) +static int snd_soc_init_codec_cache(struct snd_soc_codec *codec, + enum snd_soc_compress_type compress_type) { int ret; if (codec->cache_init) return 0; + /* override the compress_type if necessary */ + if (compress_type && codec->compress_type != compress_type) + codec->compress_type = compress_type; ret = snd_soc_cache_init(codec); if (ret < 0) { dev_err(codec->dev, @@ -1625,6 +1614,8 @@ static int snd_soc_init_codec_cache(struct snd_soc_codec *codec) static int snd_soc_instantiate_card(struct snd_soc_card *card) { struct snd_soc_codec *codec; + struct snd_soc_codec_conf *codec_conf; + enum snd_soc_compress_type compress_type; struct snd_soc_dai_link *dai_link; int ret, i, order, dai_fmt; @@ -1648,7 +1639,19 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) list_for_each_entry(codec, &codec_list, list) { if (codec->cache_init) continue; - ret = snd_soc_init_codec_cache(codec); + /* 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) goto base_error; } @@ -1944,14 +1947,6 @@ int snd_soc_poweroff(struct device *dev) snd_soc_dapm_shutdown(card); - /* deactivate pins to sleep state */ - for (i = 0; i < card->num_rtd; i++) { - struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; - struct snd_soc_dai *codec_dai = card->rtd[i].codec_dai; - pinctrl_pm_select_sleep_state(codec_dai->dev); - pinctrl_pm_select_sleep_state(cpu_dai->dev); - } - return 0; } EXPORT_SYMBOL_GPL(snd_soc_poweroff); @@ -2302,6 +2297,13 @@ unsigned int snd_soc_write(struct snd_soc_codec *codec, } EXPORT_SYMBOL_GPL(snd_soc_write); +unsigned int snd_soc_bulk_write_raw(struct snd_soc_codec *codec, + unsigned int reg, const void *data, size_t len) +{ + return codec->bulk_write_raw(codec, reg, data, len); +} +EXPORT_SYMBOL_GPL(snd_soc_bulk_write_raw); + /** * snd_soc_update_bits - update codec register bits * @codec: audio codec @@ -2574,9 +2576,8 @@ int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol, if (uinfo->value.enumerated.item > e->max - 1) uinfo->value.enumerated.item = e->max - 1; - strlcpy(uinfo->value.enumerated.name, - e->texts[uinfo->value.enumerated.item], - sizeof(uinfo->value.enumerated.name)); + strcpy(uinfo->value.enumerated.name, + e->texts[uinfo->value.enumerated.item]); return 0; } EXPORT_SYMBOL_GPL(snd_soc_info_enum_double); @@ -3212,11 +3213,11 @@ int snd_soc_bytes_get(struct snd_kcontrol *kcontrol, break; case 2: ((u16 *)(&ucontrol->value.bytes.data))[0] - &= cpu_to_be16(~params->mask); + &= ~params->mask; break; case 4: ((u32 *)(&ucontrol->value.bytes.data))[0] - &= cpu_to_be32(~params->mask); + &= ~params->mask; break; default: return -EINVAL; @@ -3575,22 +3576,6 @@ int snd_soc_codec_set_pll(struct snd_soc_codec *codec, int pll_id, int source, EXPORT_SYMBOL_GPL(snd_soc_codec_set_pll); /** - * snd_soc_dai_set_bclk_ratio - configure BCLK to sample rate ratio. - * @dai: DAI - * @ratio Ratio of BCLK to Sample rate. - * - * Configures the DAI for a preset BCLK to sample rate ratio. - */ -int snd_soc_dai_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio) -{ - if (dai->driver && dai->driver->ops->set_bclk_ratio) - return dai->driver->ops->set_bclk_ratio(dai, ratio); - else - return -EINVAL; -} -EXPORT_SYMBOL_GPL(snd_soc_dai_set_bclk_ratio); - -/** * snd_soc_dai_set_fmt - configure DAI hardware audio format. * @dai: DAI * @fmt: SND_SOC_DAIFMT_ format value. @@ -3790,16 +3775,6 @@ int snd_soc_register_card(struct snd_soc_card *card) if (ret != 0) soc_cleanup_card_debugfs(card); - /* deactivate pins to sleep state */ - for (i = 0; i < card->num_rtd; i++) { - struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; - struct snd_soc_dai *codec_dai = card->rtd[i].codec_dai; - if (!codec_dai->active) - pinctrl_pm_select_sleep_state(codec_dai->dev); - if (!cpu_dai->active) - pinctrl_pm_select_sleep_state(cpu_dai->dev); - } - return ret; } EXPORT_SYMBOL_GPL(snd_soc_register_card); @@ -4045,113 +4020,6 @@ static void snd_soc_unregister_dais(struct device *dev, size_t count) } /** - * snd_soc_register_component - Register a component with the ASoC core - * - */ -static int -__snd_soc_register_component(struct device *dev, - struct snd_soc_component *cmpnt, - const struct snd_soc_component_driver *cmpnt_drv, - struct snd_soc_dai_driver *dai_drv, - int num_dai, bool allow_single_dai) -{ - int ret; - - dev_dbg(dev, "component register %s\n", dev_name(dev)); - - if (!cmpnt) { - dev_err(dev, "ASoC: Failed to connecting component\n"); - return -ENOMEM; - } - - cmpnt->name = fmt_single_name(dev, &cmpnt->id); - if (!cmpnt->name) { - dev_err(dev, "ASoC: Failed to simplifying name\n"); - return -ENOMEM; - } - - cmpnt->dev = dev; - cmpnt->driver = cmpnt_drv; - cmpnt->dai_drv = dai_drv; - cmpnt->num_dai = num_dai; - - /* - * snd_soc_register_dai() uses fmt_single_name(), and - * snd_soc_register_dais() uses fmt_multiple_name() - * for dai->name which is used for name based matching - * - * this function is used from cpu/codec. - * allow_single_dai flag can ignore "codec" driver reworking - * since it had been used snd_soc_register_dais(), - */ - if ((1 == num_dai) && allow_single_dai) - ret = snd_soc_register_dai(dev, dai_drv); - else - ret = snd_soc_register_dais(dev, dai_drv, num_dai); - if (ret < 0) { - dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret); - goto error_component_name; - } - - mutex_lock(&client_mutex); - list_add(&cmpnt->list, &component_list); - mutex_unlock(&client_mutex); - - dev_dbg(cmpnt->dev, "ASoC: Registered component '%s'\n", cmpnt->name); - - return ret; - -error_component_name: - kfree(cmpnt->name); - - return ret; -} - -int snd_soc_register_component(struct device *dev, - const struct snd_soc_component_driver *cmpnt_drv, - struct snd_soc_dai_driver *dai_drv, - int num_dai) -{ - struct snd_soc_component *cmpnt; - - cmpnt = devm_kzalloc(dev, sizeof(*cmpnt), GFP_KERNEL); - if (!cmpnt) { - dev_err(dev, "ASoC: Failed to allocate memory\n"); - return -ENOMEM; - } - - return __snd_soc_register_component(dev, cmpnt, cmpnt_drv, - dai_drv, num_dai, true); -} -EXPORT_SYMBOL_GPL(snd_soc_register_component); - -/** - * snd_soc_unregister_component - Unregister a component from the ASoC core - * - */ -void snd_soc_unregister_component(struct device *dev) -{ - struct snd_soc_component *cmpnt; - - list_for_each_entry(cmpnt, &component_list, list) { - if (dev == cmpnt->dev) - goto found; - } - return; - -found: - snd_soc_unregister_dais(dev, cmpnt->num_dai); - - mutex_lock(&client_mutex); - list_del(&cmpnt->list); - mutex_unlock(&client_mutex); - - dev_dbg(dev, "ASoC: Unregistered component '%s'\n", cmpnt->name); - kfree(cmpnt->name); -} -EXPORT_SYMBOL_GPL(snd_soc_unregister_component); - -/** * snd_soc_add_platform - Add a platform to the ASoC core * @dev: The parent device for the platform * @platform: The platform to add @@ -4297,6 +4165,7 @@ int snd_soc_register_codec(struct device *dev, struct snd_soc_dai_driver *dai_drv, int num_dai) { + size_t reg_size; struct snd_soc_codec *codec; int ret, i; @@ -4313,6 +4182,11 @@ int snd_soc_register_codec(struct device *dev, goto fail_codec; } + if (codec_drv->compress_type) + codec->compress_type = codec_drv->compress_type; + else + codec->compress_type = SND_SOC_FLAT_COMPRESSION; + codec->write = codec_drv->write; codec->read = codec_drv->read; codec->volatile_register = codec_drv->volatile_register; @@ -4329,6 +4203,35 @@ int snd_soc_register_codec(struct device *dev, codec->num_dai = num_dai; mutex_init(&codec->mutex); + /* 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 the + * kernel might have freed the array by the time we initialize + * the cache. + */ + 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_codec_name; + } + } + } + + 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; + if (!codec->writable_register) + codec->writable_register = snd_soc_default_writable_register; + } + for (i = 0; i < num_dai; i++) { fixup_codec_formats(&dai_drv[i].playback); fixup_codec_formats(&dai_drv[i].capture); @@ -4338,12 +4241,10 @@ int snd_soc_register_codec(struct device *dev, list_add(&codec->list, &codec_list); mutex_unlock(&client_mutex); - /* register component */ - ret = __snd_soc_register_component(dev, &codec->component, - &codec_drv->component_driver, - dai_drv, num_dai, false); + /* register any DAIs */ + ret = snd_soc_register_dais(dev, dai_drv, num_dai); if (ret < 0) { - dev_err(codec->dev, "ASoC: Failed to regster component: %d\n", ret); + dev_err(codec->dev, "ASoC: Failed to regster DAIs: %d\n", ret); goto fail_codec_name; } @@ -4378,7 +4279,7 @@ void snd_soc_unregister_codec(struct device *dev) return; found: - snd_soc_unregister_component(dev); + snd_soc_unregister_dais(dev, codec->num_dai); mutex_lock(&client_mutex); list_del(&codec->list); @@ -4387,11 +4288,98 @@ found: dev_dbg(codec->dev, "ASoC: Unregistered codec '%s'\n", codec->name); snd_soc_cache_exit(codec); + kfree(codec->reg_def_copy); kfree(codec->name); kfree(codec); } EXPORT_SYMBOL_GPL(snd_soc_unregister_codec); + +/** + * snd_soc_register_component - Register a component with the ASoC core + * + */ +int snd_soc_register_component(struct device *dev, + const struct snd_soc_component_driver *cmpnt_drv, + struct snd_soc_dai_driver *dai_drv, + int num_dai) +{ + struct snd_soc_component *cmpnt; + int ret; + + dev_dbg(dev, "component register %s\n", dev_name(dev)); + + cmpnt = devm_kzalloc(dev, sizeof(*cmpnt), GFP_KERNEL); + if (!cmpnt) { + dev_err(dev, "ASoC: Failed to allocate memory\n"); + return -ENOMEM; + } + + cmpnt->name = fmt_single_name(dev, &cmpnt->id); + if (!cmpnt->name) { + dev_err(dev, "ASoC: Failed to simplifying name\n"); + return -ENOMEM; + } + + cmpnt->dev = dev; + cmpnt->driver = cmpnt_drv; + cmpnt->num_dai = num_dai; + + /* + * snd_soc_register_dai() uses fmt_single_name(), and + * snd_soc_register_dais() uses fmt_multiple_name() + * for dai->name which is used for name based matching + */ + if (1 == num_dai) + ret = snd_soc_register_dai(dev, dai_drv); + else + ret = snd_soc_register_dais(dev, dai_drv, num_dai); + if (ret < 0) { + dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret); + goto error_component_name; + } + + mutex_lock(&client_mutex); + list_add(&cmpnt->list, &component_list); + mutex_unlock(&client_mutex); + + dev_dbg(cmpnt->dev, "ASoC: Registered component '%s'\n", cmpnt->name); + + return ret; + +error_component_name: + kfree(cmpnt->name); + + return ret; +} +EXPORT_SYMBOL_GPL(snd_soc_register_component); + +/** + * snd_soc_unregister_component - Unregister a component from the ASoC core + * + */ +void snd_soc_unregister_component(struct device *dev) +{ + struct snd_soc_component *cmpnt; + + list_for_each_entry(cmpnt, &component_list, list) { + if (dev == cmpnt->dev) + goto found; + } + return; + +found: + snd_soc_unregister_dais(dev, cmpnt->num_dai); + + mutex_lock(&client_mutex); + list_del(&cmpnt->list); + mutex_unlock(&client_mutex); + + dev_dbg(dev, "ASoC: Unregistered component '%s'\n", cmpnt->name); + kfree(cmpnt->name); +} +EXPORT_SYMBOL_GPL(snd_soc_unregister_component); + /* Retrieve a card's name from device tree */ int snd_soc_of_parse_card_name(struct snd_soc_card *card, const char *propname) @@ -4579,60 +4567,6 @@ unsigned int snd_soc_of_parse_daifmt(struct device_node *np, } EXPORT_SYMBOL_GPL(snd_soc_of_parse_daifmt); -int snd_soc_of_get_dai_name(struct device_node *of_node, - const char **dai_name) -{ - struct snd_soc_component *pos; - struct of_phandle_args args; - int ret; - - ret = of_parse_phandle_with_args(of_node, "sound-dai", - "#sound-dai-cells", 0, &args); - if (ret) - return ret; - - ret = -EPROBE_DEFER; - - mutex_lock(&client_mutex); - list_for_each_entry(pos, &component_list, list) { - if (pos->dev->of_node != args.np) - continue; - - if (pos->driver->of_xlate_dai_name) { - ret = pos->driver->of_xlate_dai_name(pos, &args, dai_name); - } else { - int id = -1; - - switch (args.args_count) { - case 0: - id = 0; /* same as dai_drv[0] */ - break; - case 1: - id = args.args[0]; - break; - default: - /* not supported */ - break; - } - - if (id < 0 || id >= pos->num_dai) { - ret = -EINVAL; - } else { - *dai_name = pos->dai_drv[id].name; - ret = 0; - } - } - - break; - } - mutex_unlock(&client_mutex); - - of_node_put(args.np); - - return ret; -} -EXPORT_SYMBOL_GPL(snd_soc_of_get_dai_name); - static int __init snd_soc_init(void) { #ifdef CONFIG_DEBUG_FS |