aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>2017-10-10 21:38:29 -0400
committerMark Brown <broonie@kernel.org>2017-10-23 05:38:59 -0400
commit273d778ef38a8861f880e9df5799029dc82bd55d (patch)
treefa55ea50808e9515c9c2cb6cfc73b7575bfa438e
parentfbb16563c6c2b7fc4944adc49f93c1dc6fe25770 (diff)
ASoC: snd_soc_component_driver has endianness
Codec will be replaced into Component, then Codec side only needs to call fixup_codec_formats() at this point. This patch adds new endianness flag on Component driver and call convert_endianness_formats() (= was fixup_codec_format()) if endianness was true. When Codec is replaced into Component, Codec driver needs to have endianness = 1 flags. Existing CPU side of course doesn't have this flag, thus CPU doesn't call it. Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--include/sound/soc.h1
-rw-r--r--sound/soc/soc-core.c80
2 files changed, 46 insertions, 35 deletions
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 44fab951b686..747d080a0853 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -837,6 +837,7 @@ struct snd_soc_component_driver {
837 unsigned int idle_bias_on:1; 837 unsigned int idle_bias_on:1;
838 unsigned int suspend_bias_off:1; 838 unsigned int suspend_bias_off:1;
839 unsigned int pmdown_time:1; /* care pmdown_time at stop */ 839 unsigned int pmdown_time:1; /* care pmdown_time at stop */
840 unsigned int endianness:1;
840}; 841};
841 842
842struct snd_soc_component { 843struct snd_soc_component {
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index a3dcf14befd8..61c3d3649914 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -3404,6 +3404,41 @@ static void snd_soc_component_del_unlocked(struct snd_soc_component *component)
3404 list_del(&component->list); 3404 list_del(&component->list);
3405} 3405}
3406 3406
3407#define ENDIANNESS_MAP(name) \
3408 (SNDRV_PCM_FMTBIT_##name##LE | SNDRV_PCM_FMTBIT_##name##BE)
3409static u64 endianness_format_map[] = {
3410 ENDIANNESS_MAP(S16_),
3411 ENDIANNESS_MAP(U16_),
3412 ENDIANNESS_MAP(S24_),
3413 ENDIANNESS_MAP(U24_),
3414 ENDIANNESS_MAP(S32_),
3415 ENDIANNESS_MAP(U32_),
3416 ENDIANNESS_MAP(S24_3),
3417 ENDIANNESS_MAP(U24_3),
3418 ENDIANNESS_MAP(S20_3),
3419 ENDIANNESS_MAP(U20_3),
3420 ENDIANNESS_MAP(S18_3),
3421 ENDIANNESS_MAP(U18_3),
3422 ENDIANNESS_MAP(FLOAT_),
3423 ENDIANNESS_MAP(FLOAT64_),
3424 ENDIANNESS_MAP(IEC958_SUBFRAME_),
3425};
3426
3427/*
3428 * Fix up the DAI formats for endianness: codecs don't actually see
3429 * the endianness of the data but we're using the CPU format
3430 * definitions which do need to include endianness so we ensure that
3431 * codec DAIs always have both big and little endian variants set.
3432 */
3433static void convert_endianness_formats(struct snd_soc_pcm_stream *stream)
3434{
3435 int i;
3436
3437 for (i = 0; i < ARRAY_SIZE(endianness_format_map); i++)
3438 if (stream->formats & endianness_format_map[i])
3439 stream->formats |= endianness_format_map[i];
3440}
3441
3407int snd_soc_add_component(struct device *dev, 3442int snd_soc_add_component(struct device *dev,
3408 struct snd_soc_component *component, 3443 struct snd_soc_component *component,
3409 const struct snd_soc_component_driver *component_driver, 3444 const struct snd_soc_component_driver *component_driver,
@@ -3411,6 +3446,7 @@ int snd_soc_add_component(struct device *dev,
3411 int num_dai) 3446 int num_dai)
3412{ 3447{
3413 int ret; 3448 int ret;
3449 int i;
3414 3450
3415 ret = snd_soc_component_initialize(component, component_driver, dev); 3451 ret = snd_soc_component_initialize(component, component_driver, dev);
3416 if (ret) 3452 if (ret)
@@ -3419,6 +3455,13 @@ int snd_soc_add_component(struct device *dev,
3419 component->ignore_pmdown_time = true; 3455 component->ignore_pmdown_time = true;
3420 component->registered_as_component = true; 3456 component->registered_as_component = true;
3421 3457
3458 if (component_driver->endianness) {
3459 for (i = 0; i < num_dai; i++) {
3460 convert_endianness_formats(&dai_drv[i].playback);
3461 convert_endianness_formats(&dai_drv[i].capture);
3462 }
3463 }
3464
3422 ret = snd_soc_register_dais(component, dai_drv, num_dai, true); 3465 ret = snd_soc_register_dais(component, dai_drv, num_dai, true);
3423 if (ret < 0) { 3466 if (ret < 0) {
3424 dev_err(dev, "ASoC: Failed to register DAIs: %d\n", ret); 3467 dev_err(dev, "ASoC: Failed to register DAIs: %d\n", ret);
@@ -3675,39 +3718,6 @@ void snd_soc_unregister_platform(struct device *dev)
3675} 3718}
3676EXPORT_SYMBOL_GPL(snd_soc_unregister_platform); 3719EXPORT_SYMBOL_GPL(snd_soc_unregister_platform);
3677 3720
3678static u64 codec_format_map[] = {
3679 SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE,
3680 SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE,
3681 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE,
3682 SNDRV_PCM_FMTBIT_U24_LE | SNDRV_PCM_FMTBIT_U24_BE,
3683 SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE,
3684 SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_U32_BE,
3685 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_U24_3BE,
3686 SNDRV_PCM_FMTBIT_U24_3LE | SNDRV_PCM_FMTBIT_U24_3BE,
3687 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE,
3688 SNDRV_PCM_FMTBIT_U20_3LE | SNDRV_PCM_FMTBIT_U20_3BE,
3689 SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S18_3BE,
3690 SNDRV_PCM_FMTBIT_U18_3LE | SNDRV_PCM_FMTBIT_U18_3BE,
3691 SNDRV_PCM_FMTBIT_FLOAT_LE | SNDRV_PCM_FMTBIT_FLOAT_BE,
3692 SNDRV_PCM_FMTBIT_FLOAT64_LE | SNDRV_PCM_FMTBIT_FLOAT64_BE,
3693 SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE
3694 | SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE,
3695};
3696
3697/* Fix up the DAI formats for endianness: codecs don't actually see
3698 * the endianness of the data but we're using the CPU format
3699 * definitions which do need to include endianness so we ensure that
3700 * codec DAIs always have both big and little endian variants set.
3701 */
3702static void fixup_codec_formats(struct snd_soc_pcm_stream *stream)
3703{
3704 int i;
3705
3706 for (i = 0; i < ARRAY_SIZE(codec_format_map); i++)
3707 if (stream->formats & codec_format_map[i])
3708 stream->formats |= codec_format_map[i];
3709}
3710
3711static int snd_soc_codec_drv_probe(struct snd_soc_component *component) 3721static int snd_soc_codec_drv_probe(struct snd_soc_component *component)
3712{ 3722{
3713 struct snd_soc_codec *codec = snd_soc_component_to_codec(component); 3723 struct snd_soc_codec *codec = snd_soc_component_to_codec(component);
@@ -3858,8 +3868,8 @@ int snd_soc_register_codec(struct device *dev,
3858 codec->component.regmap = codec_drv->get_regmap(dev); 3868 codec->component.regmap = codec_drv->get_regmap(dev);
3859 3869
3860 for (i = 0; i < num_dai; i++) { 3870 for (i = 0; i < num_dai; i++) {
3861 fixup_codec_formats(&dai_drv[i].playback); 3871 convert_endianness_formats(&dai_drv[i].playback);
3862 fixup_codec_formats(&dai_drv[i].capture); 3872 convert_endianness_formats(&dai_drv[i].capture);
3863 } 3873 }
3864 3874
3865 ret = snd_soc_register_dais(&codec->component, dai_drv, num_dai, false); 3875 ret = snd_soc_register_dais(&codec->component, dai_drv, num_dai, false);