From 9203dd016a5d8ffb2eb6acdca60cd0b5dfe38c2b Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 9 May 2015 11:26:47 +0100 Subject: ALSA: pcm: add IEC958 channel status helper Add a helper to create the IEC958 channel status from an ALSA snd_pcm_runtime structure, taking account of the sample rate and sample size. Signed-off-by: Russell King Reviwed-by: Mark Brown Signed-off-by: Takashi Iwai --- sound/core/pcm_iec958.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 sound/core/pcm_iec958.c (limited to 'sound/core/pcm_iec958.c') diff --git a/sound/core/pcm_iec958.c b/sound/core/pcm_iec958.c new file mode 100644 index 000000000000..36b2d7aca1bd --- /dev/null +++ b/sound/core/pcm_iec958.c @@ -0,0 +1,95 @@ +/* + * PCM DRM helpers + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include + +/** + * snd_pcm_create_iec958_consumer - create consumer format IEC958 channel status + * @runtime: pcm runtime structure with ->rate filled in + * @cs: channel status buffer, at least four bytes + * @len: length of channel status buffer + * + * Create the consumer format channel status data in @cs of maximum size + * @len corresponding to the parameters of the PCM runtime @runtime. + * + * Drivers may wish to tweak the contents of the buffer after creation. + * + * Returns: length of buffer, or negative error code if something failed. + */ +int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs, + size_t len) +{ + unsigned int fs, ws; + + if (len < 4) + return -EINVAL; + + switch (runtime->rate) { + case 32000: + fs = IEC958_AES3_CON_FS_32000; + break; + case 44100: + fs = IEC958_AES3_CON_FS_44100; + break; + case 48000: + fs = IEC958_AES3_CON_FS_48000; + break; + case 88200: + fs = IEC958_AES3_CON_FS_88200; + break; + case 96000: + fs = IEC958_AES3_CON_FS_96000; + break; + case 176400: + fs = IEC958_AES3_CON_FS_176400; + break; + case 192000: + fs = IEC958_AES3_CON_FS_192000; + break; + default: + return -EINVAL; + } + + if (len > 4) { + switch (snd_pcm_format_width(runtime->format)) { + case 16: + ws = IEC958_AES4_CON_WORDLEN_20_16; + break; + case 18: + ws = IEC958_AES4_CON_WORDLEN_22_18; + break; + case 20: + ws = IEC958_AES4_CON_WORDLEN_20_16 | + IEC958_AES4_CON_MAX_WORDLEN_24; + break; + case 24: + ws = IEC958_AES4_CON_WORDLEN_24_20 | + IEC958_AES4_CON_MAX_WORDLEN_24; + break; + + default: + return -EINVAL; + } + } + + memset(cs, 0, len); + + cs[0] = IEC958_AES0_CON_NOT_COPYRIGHT | IEC958_AES0_CON_EMPHASIS_NONE; + cs[1] = IEC958_AES1_CON_GENERAL; + cs[2] = IEC958_AES2_CON_SOURCE_UNSPEC | IEC958_AES2_CON_CHANNEL_UNSPEC; + cs[3] = IEC958_AES3_CON_CLOCK_1000PPM | fs; + + if (len > 4) + cs[4] = ws; + + return len; +} +EXPORT_SYMBOL(snd_pcm_create_iec958_consumer); -- cgit v1.2.3