1/* 2 * PCM DRM helpers 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 as 6 * published by the Free Software Foundation. 7 */ 8#include <linux/export.h> 9#include <linux/types.h> 10#include <sound/asoundef.h> 11#include <sound/pcm.h> 12#include <sound/pcm_iec958.h> 13 14/** 15 * snd_pcm_create_iec958_consumer - create consumer format IEC958 channel status 16 * @runtime: pcm runtime structure with ->rate filled in 17 * @cs: channel status buffer, at least four bytes 18 * @len: length of channel status buffer 19 * 20 * Create the consumer format channel status data in @cs of maximum size 21 * @len corresponding to the parameters of the PCM runtime @runtime. 22 * 23 * Drivers may wish to tweak the contents of the buffer after creation. 24 * 25 * Returns: length of buffer, or negative error code if something failed. 26 */ 27int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs, 28 size_t len) 29{ 30 unsigned int fs, ws; 31 32 if (len < 4) 33 return -EINVAL; 34 35 switch (runtime->rate) { 36 case 32000: 37 fs = IEC958_AES3_CON_FS_32000; 38 break; 39 case 44100: 40 fs = IEC958_AES3_CON_FS_44100; 41 break; 42 case 48000: 43 fs = IEC958_AES3_CON_FS_48000; 44 break; 45 case 88200: 46 fs = IEC958_AES3_CON_FS_88200; 47 break; 48 case 96000: 49 fs = IEC958_AES3_CON_FS_96000; 50 break; 51 case 176400: 52 fs = IEC958_AES3_CON_FS_176400; 53 break; 54 case 192000: 55 fs = IEC958_AES3_CON_FS_192000; 56 break; 57 default: 58 return -EINVAL; 59 } 60 61 if (len > 4) { 62 switch (snd_pcm_format_width(runtime->format)) { 63 case 16: 64 ws = IEC958_AES4_CON_WORDLEN_20_16; 65 break; 66 case 18: 67 ws = IEC958_AES4_CON_WORDLEN_22_18; 68 break; 69 case 20: 70 ws = IEC958_AES4_CON_WORDLEN_20_16 | 71 IEC958_AES4_CON_MAX_WORDLEN_24; 72 break; 73 case 24: 74 ws = IEC958_AES4_CON_WORDLEN_24_20 | 75 IEC958_AES4_CON_MAX_WORDLEN_24; 76 break; 77 78 default: 79 return -EINVAL; 80 } 81 } 82 83 memset(cs, 0, len); 84 85 cs[0] = IEC958_AES0_CON_NOT_COPYRIGHT | IEC958_AES0_CON_EMPHASIS_NONE; 86 cs[1] = IEC958_AES1_CON_GENERAL; 87 cs[2] = IEC958_AES2_CON_SOURCE_UNSPEC | IEC958_AES2_CON_CHANNEL_UNSPEC; 88 cs[3] = IEC958_AES3_CON_CLOCK_1000PPM | fs; 89 90 if (len > 4) 91 cs[4] = ws; 92 93 return len; 94} 95EXPORT_SYMBOL(snd_pcm_create_iec958_consumer); 96