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_params.h> 13 #include <sound/pcm_iec958.h> 14 15 static int create_iec958_consumer(uint rate, uint sample_width, 16 u8 *cs, size_t len) 17 { 18 unsigned int fs, ws; 19 20 if (len < 4) 21 return -EINVAL; 22 23 switch (rate) { 24 case 32000: 25 fs = IEC958_AES3_CON_FS_32000; 26 break; 27 case 44100: 28 fs = IEC958_AES3_CON_FS_44100; 29 break; 30 case 48000: 31 fs = IEC958_AES3_CON_FS_48000; 32 break; 33 case 88200: 34 fs = IEC958_AES3_CON_FS_88200; 35 break; 36 case 96000: 37 fs = IEC958_AES3_CON_FS_96000; 38 break; 39 case 176400: 40 fs = IEC958_AES3_CON_FS_176400; 41 break; 42 case 192000: 43 fs = IEC958_AES3_CON_FS_192000; 44 break; 45 default: 46 return -EINVAL; 47 } 48 49 if (len > 4) { 50 switch (sample_width) { 51 case 16: 52 ws = IEC958_AES4_CON_WORDLEN_20_16; 53 break; 54 case 18: 55 ws = IEC958_AES4_CON_WORDLEN_22_18; 56 break; 57 case 20: 58 ws = IEC958_AES4_CON_WORDLEN_20_16 | 59 IEC958_AES4_CON_MAX_WORDLEN_24; 60 break; 61 case 24: 62 case 32: /* Assume 24-bit width for 32-bit samples. */ 63 ws = IEC958_AES4_CON_WORDLEN_24_20 | 64 IEC958_AES4_CON_MAX_WORDLEN_24; 65 break; 66 67 default: 68 return -EINVAL; 69 } 70 } 71 72 memset(cs, 0, len); 73 74 cs[0] = IEC958_AES0_CON_NOT_COPYRIGHT | IEC958_AES0_CON_EMPHASIS_NONE; 75 cs[1] = IEC958_AES1_CON_GENERAL; 76 cs[2] = IEC958_AES2_CON_SOURCE_UNSPEC | IEC958_AES2_CON_CHANNEL_UNSPEC; 77 cs[3] = IEC958_AES3_CON_CLOCK_1000PPM | fs; 78 79 if (len > 4) 80 cs[4] = ws; 81 82 return len; 83 } 84 85 /** 86 * snd_pcm_create_iec958_consumer - create consumer format IEC958 channel status 87 * @runtime: pcm runtime structure with ->rate filled in 88 * @cs: channel status buffer, at least four bytes 89 * @len: length of channel status buffer 90 * 91 * Create the consumer format channel status data in @cs of maximum size 92 * @len corresponding to the parameters of the PCM runtime @runtime. 93 * 94 * Drivers may wish to tweak the contents of the buffer after creation. 95 * 96 * Returns: length of buffer, or negative error code if something failed. 97 */ 98 int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs, 99 size_t len) 100 { 101 return create_iec958_consumer(runtime->rate, 102 snd_pcm_format_width(runtime->format), 103 cs, len); 104 } 105 EXPORT_SYMBOL(snd_pcm_create_iec958_consumer); 106 107 /** 108 * snd_pcm_create_iec958_consumer_hw_params - create IEC958 channel status 109 * @hw_params: the hw_params instance for extracting rate and sample format 110 * @cs: channel status buffer, at least four bytes 111 * @len: length of channel status buffer 112 * 113 * Create the consumer format channel status data in @cs of maximum size 114 * @len corresponding to the parameters of the PCM runtime @runtime. 115 * 116 * Drivers may wish to tweak the contents of the buffer after creation. 117 * 118 * Returns: length of buffer, or negative error code if something failed. 119 */ 120 int snd_pcm_create_iec958_consumer_hw_params(struct snd_pcm_hw_params *params, 121 u8 *cs, size_t len) 122 { 123 return create_iec958_consumer(params_rate(params), params_width(params), 124 cs, len); 125 } 126 EXPORT_SYMBOL(snd_pcm_create_iec958_consumer_hw_params); 127