1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * PCM DRM helpers 4 */ 5 #include <linux/export.h> 6 #include <linux/types.h> 7 #include <sound/asoundef.h> 8 #include <sound/pcm.h> 9 #include <sound/pcm_params.h> 10 #include <sound/pcm_iec958.h> 11 12 /** 13 * snd_pcm_create_iec958_consumer_default - create default consumer format IEC958 channel status 14 * @cs: channel status buffer, at least four bytes 15 * @len: length of channel status buffer 16 * 17 * Create the consumer format channel status data in @cs of maximum size 18 * @len. When relevant, the configuration-dependant bits will be set as 19 * unspecified. 20 * 21 * Drivers should then call einter snd_pcm_fill_iec958_consumer() or 22 * snd_pcm_fill_iec958_consumer_hw_params() to replace these unspecified 23 * bits by their actual values. 24 * 25 * Drivers may wish to tweak the contents of the buffer after creation. 26 * 27 * Returns: length of buffer, or negative error code if something failed. 28 */ 29 int snd_pcm_create_iec958_consumer_default(u8 *cs, size_t len) 30 { 31 if (len < 4) 32 return -EINVAL; 33 34 memset(cs, 0, len); 35 36 cs[0] = IEC958_AES0_CON_NOT_COPYRIGHT | IEC958_AES0_CON_EMPHASIS_NONE; 37 cs[1] = IEC958_AES1_CON_GENERAL; 38 cs[2] = IEC958_AES2_CON_SOURCE_UNSPEC | IEC958_AES2_CON_CHANNEL_UNSPEC; 39 cs[3] = IEC958_AES3_CON_CLOCK_1000PPM | IEC958_AES3_CON_FS_NOTID; 40 41 if (len > 4) 42 cs[4] = IEC958_AES4_CON_WORDLEN_NOTID; 43 44 return len; 45 } 46 EXPORT_SYMBOL_GPL(snd_pcm_create_iec958_consumer_default); 47 48 static int fill_iec958_consumer(uint rate, uint sample_width, 49 u8 *cs, size_t len) 50 { 51 if (len < 4) 52 return -EINVAL; 53 54 if ((cs[3] & IEC958_AES3_CON_FS) == IEC958_AES3_CON_FS_NOTID) { 55 unsigned int fs; 56 57 switch (rate) { 58 case 32000: 59 fs = IEC958_AES3_CON_FS_32000; 60 break; 61 case 44100: 62 fs = IEC958_AES3_CON_FS_44100; 63 break; 64 case 48000: 65 fs = IEC958_AES3_CON_FS_48000; 66 break; 67 case 88200: 68 fs = IEC958_AES3_CON_FS_88200; 69 break; 70 case 96000: 71 fs = IEC958_AES3_CON_FS_96000; 72 break; 73 case 176400: 74 fs = IEC958_AES3_CON_FS_176400; 75 break; 76 case 192000: 77 fs = IEC958_AES3_CON_FS_192000; 78 break; 79 default: 80 return -EINVAL; 81 } 82 83 cs[3] &= ~IEC958_AES3_CON_FS; 84 cs[3] |= fs; 85 } 86 87 if (len > 4 && 88 (cs[4] & IEC958_AES4_CON_WORDLEN) == IEC958_AES4_CON_WORDLEN_NOTID) { 89 unsigned int ws; 90 91 switch (sample_width) { 92 case 16: 93 ws = IEC958_AES4_CON_WORDLEN_20_16; 94 break; 95 case 18: 96 ws = IEC958_AES4_CON_WORDLEN_22_18; 97 break; 98 case 20: 99 ws = IEC958_AES4_CON_WORDLEN_20_16 | 100 IEC958_AES4_CON_MAX_WORDLEN_24; 101 break; 102 case 24: 103 case 32: /* Assume 24-bit width for 32-bit samples. */ 104 ws = IEC958_AES4_CON_WORDLEN_24_20 | 105 IEC958_AES4_CON_MAX_WORDLEN_24; 106 break; 107 108 default: 109 return -EINVAL; 110 } 111 112 cs[4] &= ~IEC958_AES4_CON_WORDLEN; 113 cs[4] |= ws; 114 } 115 116 return len; 117 } 118 119 /** 120 * snd_pcm_fill_iec958_consumer - Fill consumer format IEC958 channel status 121 * @runtime: pcm runtime structure with ->rate filled in 122 * @cs: channel status buffer, at least four bytes 123 * @len: length of channel status buffer 124 * 125 * Fill the unspecified bits in an IEC958 status bits array using the 126 * parameters of the PCM runtime @runtime. 127 * 128 * Drivers may wish to tweak the contents of the buffer after its been 129 * filled. 130 * 131 * Returns: length of buffer, or negative error code if something failed. 132 */ 133 int snd_pcm_fill_iec958_consumer(struct snd_pcm_runtime *runtime, 134 u8 *cs, size_t len) 135 { 136 return fill_iec958_consumer(runtime->rate, 137 snd_pcm_format_width(runtime->format), 138 cs, len); 139 } 140 EXPORT_SYMBOL_GPL(snd_pcm_fill_iec958_consumer); 141 142 /** 143 * snd_pcm_fill_iec958_consumer_hw_params - Fill consumer format IEC958 channel status 144 * @params: the hw_params instance for extracting rate and sample format 145 * @cs: channel status buffer, at least four bytes 146 * @len: length of channel status buffer 147 * 148 * Fill the unspecified bits in an IEC958 status bits array using the 149 * parameters of the PCM hardware parameters @params. 150 * 151 * Drivers may wish to tweak the contents of the buffer after its been 152 * filled.. 153 * 154 * Returns: length of buffer, or negative error code if something failed. 155 */ 156 int snd_pcm_fill_iec958_consumer_hw_params(struct snd_pcm_hw_params *params, 157 u8 *cs, size_t len) 158 { 159 return fill_iec958_consumer(params_rate(params), params_width(params), cs, len); 160 } 161 EXPORT_SYMBOL_GPL(snd_pcm_fill_iec958_consumer_hw_params); 162 163 /** 164 * snd_pcm_create_iec958_consumer - create consumer format IEC958 channel status 165 * @runtime: pcm runtime structure with ->rate filled in 166 * @cs: channel status buffer, at least four bytes 167 * @len: length of channel status buffer 168 * 169 * Create the consumer format channel status data in @cs of maximum size 170 * @len corresponding to the parameters of the PCM runtime @runtime. 171 * 172 * Drivers may wish to tweak the contents of the buffer after creation. 173 * 174 * Returns: length of buffer, or negative error code if something failed. 175 */ 176 int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs, 177 size_t len) 178 { 179 int ret; 180 181 ret = snd_pcm_create_iec958_consumer_default(cs, len); 182 if (ret < 0) 183 return ret; 184 185 return snd_pcm_fill_iec958_consumer(runtime, cs, len); 186 } 187 EXPORT_SYMBOL(snd_pcm_create_iec958_consumer); 188 189 /** 190 * snd_pcm_create_iec958_consumer_hw_params - create IEC958 channel status 191 * @params: the hw_params instance for extracting rate and sample format 192 * @cs: channel status buffer, at least four bytes 193 * @len: length of channel status buffer 194 * 195 * Create the consumer format channel status data in @cs of maximum size 196 * @len corresponding to the parameters of the PCM runtime @runtime. 197 * 198 * Drivers may wish to tweak the contents of the buffer after creation. 199 * 200 * Returns: length of buffer, or negative error code if something failed. 201 */ 202 int snd_pcm_create_iec958_consumer_hw_params(struct snd_pcm_hw_params *params, 203 u8 *cs, size_t len) 204 { 205 int ret; 206 207 ret = snd_pcm_create_iec958_consumer_default(cs, len); 208 if (ret < 0) 209 return ret; 210 211 return fill_iec958_consumer(params_rate(params), params_width(params), cs, len); 212 } 213 EXPORT_SYMBOL(snd_pcm_create_iec958_consumer_hw_params); 214