summaryrefslogtreecommitdiffstats
path: root/sound/soc
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2009-05-09 16:22:58 +0100
committerMark Brown <broonie@opensource.wolfsonmicro.com>2009-05-09 16:35:21 +0100
commit151ab22cf71b7a1b9dd696d65a1a41e13d90cd00 (patch)
tree8e0bdcb4b35408563915625eed7685f2d66765bf /sound/soc
parentb4df0a6c9d88cfff77c73d33873cd60f9ab909b6 (diff)
ASoC: Fix up CODEC DAI formats for big endian CPUs
ASoC uses the standard ALSA data format definitions to specify the wire format used between the CPU and CODEC. Since the ALSA data formats all include the endianess of the data but this information is not relevant by the time the data has been encoded onto the serial link to the CODEC this means that either all the CODEC drivers need to declare both big and little endian variants or the core needs to fix up the format constraints specified by CODEC drivers. For now take the latter approach - this will need to be revisited if any CODECs are endianness dependant. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/soc-core.c40
1 files changed, 40 insertions, 0 deletions
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index af11791a3b8..6ac68e47b3a 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -2387,6 +2387,39 @@ void snd_soc_unregister_platform(struct snd_soc_platform *platform)
}
EXPORT_SYMBOL_GPL(snd_soc_unregister_platform);
+static u64 codec_format_map[] = {
+ SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE,
+ SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE,
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE,
+ SNDRV_PCM_FMTBIT_U24_LE | SNDRV_PCM_FMTBIT_U24_BE,
+ SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE,
+ SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_U32_BE,
+ SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_U24_3BE,
+ SNDRV_PCM_FMTBIT_U24_3LE | SNDRV_PCM_FMTBIT_U24_3BE,
+ SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE,
+ SNDRV_PCM_FMTBIT_U20_3LE | SNDRV_PCM_FMTBIT_U20_3BE,
+ SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S18_3BE,
+ SNDRV_PCM_FMTBIT_U18_3LE | SNDRV_PCM_FMTBIT_U18_3BE,
+ SNDRV_PCM_FMTBIT_FLOAT_LE | SNDRV_PCM_FMTBIT_FLOAT_BE,
+ SNDRV_PCM_FMTBIT_FLOAT64_LE | SNDRV_PCM_FMTBIT_FLOAT64_BE,
+ SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE
+ | SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE,
+};
+
+/* Fix up the DAI formats for endianness: codecs don't actually see
+ * the endianness of the data but we're using the CPU format
+ * definitions which do need to include endianness so we ensure that
+ * codec DAIs always have both big and little endian variants set.
+ */
+static void fixup_codec_formats(struct snd_soc_pcm_stream *stream)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(codec_format_map); i++)
+ if (stream->formats & codec_format_map[i])
+ stream->formats |= codec_format_map[i];
+}
+
/**
* snd_soc_register_codec - Register a codec with the ASoC core
*
@@ -2394,6 +2427,8 @@ EXPORT_SYMBOL_GPL(snd_soc_unregister_platform);
*/
int snd_soc_register_codec(struct snd_soc_codec *codec)
{
+ int i;
+
if (!codec->name)
return -EINVAL;
@@ -2403,6 +2438,11 @@ int snd_soc_register_codec(struct snd_soc_codec *codec)
INIT_LIST_HEAD(&codec->list);
+ for (i = 0; i < codec->num_dai; i++) {
+ fixup_codec_formats(&codec->dai[i].playback);
+ fixup_codec_formats(&codec->dai[i].capture);
+ }
+
mutex_lock(&client_mutex);
list_add(&codec->list, &codec_list);
snd_soc_instantiate_cards();