diff options
Diffstat (limited to 'sound/soc/soc-core.c')
-rw-r--r-- | sound/soc/soc-core.c | 185 |
1 files changed, 91 insertions, 94 deletions
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 516350533e73..3c6d8aef4130 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -238,8 +238,8 @@ static inline void snd_soc_debugfs_exit(void) { } #endif -static int snd_soc_is_match_dai_args(struct of_phandle_args *args1, - struct of_phandle_args *args2) +static int snd_soc_is_match_dai_args(const struct of_phandle_args *args1, + const struct of_phandle_args *args2) { if (!args1 || !args2) return 0; @@ -283,11 +283,11 @@ static int snd_soc_is_matching_dai(const struct snd_soc_dai_link_component *dlc, /* see snd_soc_dai_name_get() */ - if (strcmp(dlc->dai_name, dai->name) == 0) + if (dai->driver->name && + strcmp(dlc->dai_name, dai->driver->name) == 0) return 1; - if (dai->driver->name && - strcmp(dai->driver->name, dlc->dai_name) == 0) + if (strcmp(dlc->dai_name, dai->name) == 0) return 1; if (dai->component->name && @@ -297,15 +297,15 @@ static int snd_soc_is_matching_dai(const struct snd_soc_dai_link_component *dlc, return 0; } -const char *snd_soc_dai_name_get(struct snd_soc_dai *dai) +const char *snd_soc_dai_name_get(const struct snd_soc_dai *dai) { /* see snd_soc_is_matching_dai() */ - if (dai->name) - return dai->name; - if (dai->driver->name) return dai->driver->name; + if (dai->name) + return dai->name; + if (dai->component->name) return dai->component->name; @@ -326,8 +326,8 @@ static int snd_soc_rtd_add_component(struct snd_soc_pcm_runtime *rtd, } /* see for_each_rtd_components */ - rtd->components[rtd->num_components] = component; - rtd->num_components++; + rtd->num_components++; // increment flex array count at first + rtd->components[rtd->num_components - 1] = component; return 0; } @@ -494,7 +494,6 @@ static struct snd_soc_pcm_runtime *soc_new_pcm_runtime( struct snd_soc_card *card, struct snd_soc_dai_link *dai_link) { struct snd_soc_pcm_runtime *rtd; - struct snd_soc_component *component; struct device *dev; int ret; int stream; @@ -521,10 +520,10 @@ static struct snd_soc_pcm_runtime *soc_new_pcm_runtime( * for rtd */ rtd = devm_kzalloc(dev, - sizeof(*rtd) + - sizeof(component) * (dai_link->num_cpus + - dai_link->num_codecs + - dai_link->num_platforms), + struct_size(rtd, components, + dai_link->num_cpus + + dai_link->num_codecs + + dai_link->num_platforms), GFP_KERNEL); if (!rtd) { device_unregister(dev); @@ -559,7 +558,7 @@ static struct snd_soc_pcm_runtime *soc_new_pcm_runtime( */ rtd->card = card; rtd->dai_link = dai_link; - rtd->num = card->num_rtd++; + rtd->id = card->num_rtd++; rtd->pmdown_time = pmdown_time; /* default power off timeout */ /* see for_each_card_rtds */ @@ -831,7 +830,8 @@ static struct device_node return of_node; } -struct of_phandle_args *snd_soc_copy_dai_args(struct device *dev, struct of_phandle_args *args) +struct of_phandle_args *snd_soc_copy_dai_args(struct device *dev, + const struct of_phandle_args *args) { struct of_phandle_args *ret = devm_kzalloc(dev, sizeof(*ret), GFP_KERNEL); @@ -1166,7 +1166,7 @@ static int snd_soc_add_pcm_runtime(struct snd_soc_card *card, struct snd_soc_pcm_runtime *rtd; struct snd_soc_dai_link_component *codec, *platform, *cpu; struct snd_soc_component *component; - int i, ret; + int i, id, ret; lockdep_assert_held(&client_mutex); @@ -1218,10 +1218,35 @@ static int snd_soc_add_pcm_runtime(struct snd_soc_card *card, if (!snd_soc_is_matching_component(platform, component)) continue; + if (snd_soc_component_is_dummy(component) && component->num_dai) + continue; + snd_soc_rtd_add_component(rtd, component); } } + /* + * Most drivers will register their PCMs using DAI link ordering but + * topology based drivers can use the DAI link id field to set PCM + * device number and then use rtd + a base offset of the BEs. + * + * FIXME + * + * This should be implemented by using "dai_link" feature instead of + * "component" feature. + */ + id = rtd->id; + for_each_rtd_components(rtd, i, component) { + if (!component->driver->use_dai_pcm_id) + continue; + + if (rtd->dai_link->no_pcm) + id += component->driver->be_pcm_base; + else + id = rtd->dai_link->id; + } + rtd->id = id; + return 0; _err_defer: @@ -1424,23 +1449,46 @@ int snd_soc_runtime_set_dai_fmt(struct snd_soc_pcm_runtime *rtd, { struct snd_soc_dai *cpu_dai; struct snd_soc_dai *codec_dai; + unsigned int ext_fmt; unsigned int i; int ret; if (!dai_fmt) return 0; + /* + * dai_fmt has 4 types + * 1. SND_SOC_DAIFMT_FORMAT_MASK + * 2. SND_SOC_DAIFMT_CLOCK + * 3. SND_SOC_DAIFMT_INV + * 4. SND_SOC_DAIFMT_CLOCK_PROVIDER + * + * 4. CLOCK_PROVIDER is set from Codec perspective in dai_fmt. So it will be flipped + * when this function calls set_fmt() for CPU (CBx_CFx -> Bx_Cx). see below. + * This mean, we can't set CPU/Codec both are clock consumer for example. + * New idea handles 4. in each dai->ext_fmt. It can keep compatibility. + * + * Legacy + * dai_fmt includes 1, 2, 3, 4 + * + * New idea + * dai_fmt includes 1, 2, 3 + * ext_fmt includes 4 + */ for_each_rtd_codec_dais(rtd, i, codec_dai) { - ret = snd_soc_dai_set_fmt(codec_dai, dai_fmt); + ext_fmt = rtd->dai_link->codecs[i].ext_fmt; + ret = snd_soc_dai_set_fmt(codec_dai, dai_fmt | ext_fmt); if (ret != 0 && ret != -ENOTSUPP) return ret; } /* Flip the polarity for the "CPU" end of link */ + /* Will effect only for 4. SND_SOC_DAIFMT_CLOCK_PROVIDER */ dai_fmt = snd_soc_daifmt_clock_provider_flipped(dai_fmt); for_each_rtd_cpu_dais(rtd, i, cpu_dai) { - ret = snd_soc_dai_set_fmt(cpu_dai, dai_fmt); + ext_fmt = rtd->dai_link->cpus[i].ext_fmt; + ret = snd_soc_dai_set_fmt(cpu_dai, dai_fmt | ext_fmt); if (ret != 0 && ret != -ENOTSUPP) return ret; } @@ -1454,8 +1502,7 @@ static int soc_init_pcm_runtime(struct snd_soc_card *card, { struct snd_soc_dai_link *dai_link = rtd->dai_link; struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); - struct snd_soc_component *component; - int ret, num, i; + int ret; /* do machine specific initialization */ ret = snd_soc_link_init(rtd); @@ -1470,30 +1517,13 @@ static int soc_init_pcm_runtime(struct snd_soc_card *card, /* add DPCM sysfs entries */ soc_dpcm_debugfs_add(rtd); - num = rtd->num; - - /* - * most drivers will register their PCMs using DAI link ordering but - * topology based drivers can use the DAI link id field to set PCM - * device number and then use rtd + a base offset of the BEs. - */ - for_each_rtd_components(rtd, i, component) { - if (!component->driver->use_dai_pcm_id) - continue; - - if (rtd->dai_link->no_pcm) - num += component->driver->be_pcm_base; - else - num = rtd->dai_link->id; - } - /* create compress_device if possible */ - ret = snd_soc_dai_compress_new(cpu_dai, rtd, num); + ret = snd_soc_dai_compress_new(cpu_dai, rtd); if (ret != -ENOTSUPP) goto err; /* create the pcm */ - ret = soc_new_pcm(rtd, num); + ret = soc_new_pcm(rtd); if (ret < 0) { dev_err(card->dev, "ASoC: can't create pcm %s :%d\n", dai_link->stream_name, ret); @@ -1637,18 +1667,8 @@ static int soc_probe_component(struct snd_soc_card *card, ret = snd_soc_dapm_add_routes(dapm, component->driver->dapm_routes, component->driver->num_dapm_routes); - if (ret < 0) { - if (card->disable_route_checks) { - dev_info(card->dev, - "%s: disable_route_checks set, ignoring errors on add_routes\n", - __func__); - } else { - dev_err(card->dev, - "%s: snd_soc_dapm_add_routes failed: %d\n", - __func__, ret); - goto err_probe; - } - } + if (ret < 0) + goto err_probe; /* see for_each_card_components */ list_add(&component->card_list, &card->component_dev_list); @@ -1996,25 +2016,7 @@ match: dai_link->platforms->name = component->name; /* convert non BE into BE */ - if (!dai_link->no_pcm) { - dai_link->no_pcm = 1; - - if (dai_link->dpcm_playback) - dev_warn(card->dev, - "invalid configuration, dailink %s has flags no_pcm=0 and dpcm_playback=1\n", - dai_link->name); - if (dai_link->dpcm_capture) - dev_warn(card->dev, - "invalid configuration, dailink %s has flags no_pcm=0 and dpcm_capture=1\n", - dai_link->name); - - /* convert normal link into DPCM one */ - if (!(dai_link->dpcm_playback || - dai_link->dpcm_capture)) { - dai_link->dpcm_playback = !dai_link->capture_only; - dai_link->dpcm_capture = !dai_link->playback_only; - } - } + dai_link->no_pcm = 1; /* * override any BE fixups @@ -2245,18 +2247,8 @@ static int snd_soc_bind_card(struct snd_soc_card *card) ret = snd_soc_dapm_add_routes(&card->dapm, card->dapm_routes, card->num_dapm_routes); - if (ret < 0) { - if (card->disable_route_checks) { - dev_info(card->dev, - "%s: disable_route_checks set, ignoring errors on add_routes\n", - __func__); - } else { - dev_err(card->dev, - "%s: snd_soc_dapm_add_routes failed: %d\n", - __func__, ret); - goto probe_end; - } - } + if (ret < 0) + goto probe_end; ret = snd_soc_dapm_add_routes(&card->dapm, card->of_dapm_routes, card->num_of_dapm_routes); @@ -2792,10 +2784,12 @@ int snd_soc_component_initialize(struct snd_soc_component *component, INIT_LIST_HEAD(&component->list); mutex_init(&component->io_mutex); - component->name = fmt_single_name(dev, &component->id); if (!component->name) { - dev_err(dev, "ASoC: Failed to allocate name\n"); - return -ENOMEM; + component->name = fmt_single_name(dev, &component->id); + if (!component->name) { + dev_err(dev, "ASoC: Failed to allocate name\n"); + return -ENOMEM; + } } component->dev = dev; @@ -3366,10 +3360,10 @@ unsigned int snd_soc_daifmt_parse_format(struct device_node *np, * SND_SOC_DAIFMT_INV_MASK area */ snprintf(prop, sizeof(prop), "%sbitclock-inversion", prefix); - bit = !!of_get_property(np, prop, NULL); + bit = of_property_read_bool(np, prop); snprintf(prop, sizeof(prop), "%sframe-inversion", prefix); - frame = !!of_get_property(np, prop, NULL); + frame = of_property_read_bool(np, prop); switch ((bit << 4) + frame) { case 0x11: @@ -3398,6 +3392,9 @@ unsigned int snd_soc_daifmt_parse_clock_provider_raw(struct device_node *np, char prop[128]; unsigned int bit, frame; + if (!np) + return 0; + if (!prefix) prefix = ""; @@ -3406,12 +3403,12 @@ unsigned int snd_soc_daifmt_parse_clock_provider_raw(struct device_node *np, * check "[prefix]frame-master" */ snprintf(prop, sizeof(prop), "%sbitclock-master", prefix); - bit = !!of_get_property(np, prop, NULL); + bit = of_property_read_bool(np, prop); if (bit && bitclkmaster) *bitclkmaster = of_parse_phandle(np, prop, 0); snprintf(prop, sizeof(prop), "%sframe-master", prefix); - frame = !!of_get_property(np, prop, NULL); + frame = of_property_read_bool(np, prop); if (frame && framemaster) *framemaster = of_parse_phandle(np, prop, 0); @@ -3424,7 +3421,7 @@ unsigned int snd_soc_daifmt_parse_clock_provider_raw(struct device_node *np, } EXPORT_SYMBOL_GPL(snd_soc_daifmt_parse_clock_provider_raw); -int snd_soc_get_stream_cpu(struct snd_soc_dai_link *dai_link, int stream) +int snd_soc_get_stream_cpu(const struct snd_soc_dai_link *dai_link, int stream) { /* * [Normal] @@ -3597,7 +3594,7 @@ int snd_soc_of_get_dai_name(struct device_node *of_node, } EXPORT_SYMBOL_GPL(snd_soc_of_get_dai_name); -struct snd_soc_dai *snd_soc_get_dai_via_args(struct of_phandle_args *dai_args) +struct snd_soc_dai *snd_soc_get_dai_via_args(const struct of_phandle_args *dai_args) { struct snd_soc_dai *dai; struct snd_soc_component *component; |