| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * 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 | 4 | */ |
|---|
| 8 | 5 | #include <linux/export.h> |
|---|
| 9 | 6 | #include <linux/types.h> |
|---|
| .. | .. |
|---|
| 12 | 9 | #include <sound/pcm_params.h> |
|---|
| 13 | 10 | #include <sound/pcm_iec958.h> |
|---|
| 14 | 11 | |
|---|
| 15 | | -static int create_iec958_consumer(uint rate, uint sample_width, |
|---|
| 16 | | - u8 *cs, size_t len) |
|---|
| 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) |
|---|
| 17 | 30 | { |
|---|
| 18 | | - unsigned int fs, ws; |
|---|
| 19 | | - |
|---|
| 20 | 31 | if (len < 4) |
|---|
| 21 | 32 | return -EINVAL; |
|---|
| 22 | 33 | |
|---|
| 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: |
|---|
| 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) |
|---|
| 46 | 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; |
|---|
| 47 | 85 | } |
|---|
| 48 | 86 | |
|---|
| 49 | | - if (len > 4) { |
|---|
| 87 | + if (len > 4 && |
|---|
| 88 | + (cs[4] & IEC958_AES4_CON_WORDLEN) == IEC958_AES4_CON_WORDLEN_NOTID) { |
|---|
| 89 | + unsigned int ws; |
|---|
| 90 | + |
|---|
| 50 | 91 | switch (sample_width) { |
|---|
| 51 | 92 | case 16: |
|---|
| 52 | 93 | ws = IEC958_AES4_CON_WORDLEN_20_16; |
|---|
| .. | .. |
|---|
| 67 | 108 | default: |
|---|
| 68 | 109 | return -EINVAL; |
|---|
| 69 | 110 | } |
|---|
| 111 | + |
|---|
| 112 | + cs[4] &= ~IEC958_AES4_CON_WORDLEN; |
|---|
| 113 | + cs[4] |= ws; |
|---|
| 70 | 114 | } |
|---|
| 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 | 115 | |
|---|
| 82 | 116 | return len; |
|---|
| 83 | 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); |
|---|
| 84 | 162 | |
|---|
| 85 | 163 | /** |
|---|
| 86 | 164 | * snd_pcm_create_iec958_consumer - create consumer format IEC958 channel status |
|---|
| .. | .. |
|---|
| 98 | 176 | int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs, |
|---|
| 99 | 177 | size_t len) |
|---|
| 100 | 178 | { |
|---|
| 101 | | - return create_iec958_consumer(runtime->rate, |
|---|
| 102 | | - snd_pcm_format_width(runtime->format), |
|---|
| 103 | | - cs, len); |
|---|
| 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); |
|---|
| 104 | 186 | } |
|---|
| 105 | 187 | EXPORT_SYMBOL(snd_pcm_create_iec958_consumer); |
|---|
| 106 | 188 | |
|---|
| 107 | 189 | /** |
|---|
| 108 | 190 | * snd_pcm_create_iec958_consumer_hw_params - create IEC958 channel status |
|---|
| 109 | | - * @hw_params: the hw_params instance for extracting rate and sample format |
|---|
| 191 | + * @params: the hw_params instance for extracting rate and sample format |
|---|
| 110 | 192 | * @cs: channel status buffer, at least four bytes |
|---|
| 111 | 193 | * @len: length of channel status buffer |
|---|
| 112 | 194 | * |
|---|
| .. | .. |
|---|
| 120 | 202 | int snd_pcm_create_iec958_consumer_hw_params(struct snd_pcm_hw_params *params, |
|---|
| 121 | 203 | u8 *cs, size_t len) |
|---|
| 122 | 204 | { |
|---|
| 123 | | - return create_iec958_consumer(params_rate(params), params_width(params), |
|---|
| 124 | | - cs, len); |
|---|
| 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); |
|---|
| 125 | 212 | } |
|---|
| 126 | 213 | EXPORT_SYMBOL(snd_pcm_create_iec958_consumer_hw_params); |
|---|