ASoC: Fix up CODEC DAI formats for big endian CPUs
authorMark Brown <broonie@opensource.wolfsonmicro.com>
Sat, 9 May 2009 15:22:58 +0000 (16:22 +0100)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Sat, 9 May 2009 15:35:21 +0000 (16:35 +0100)
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>
sound/soc/soc-core.c

index af11791a3b8c2625975fb4e30fadac1e7ef29eb3..6ac68e47b3a64279749fcbf3e6a3d65537f1bf0d 100644 (file)
@@ -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();