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