1 /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 #ifndef __SOUND_CS8403_H 3 #define __SOUND_CS8403_H 4 5 /* 6 * Routines for Cirrus Logic CS8403/CS8404A IEC958 (S/PDIF) Transmitter 7 * Copyright (c) by Jaroslav Kysela <perex@perex.cz>, 8 * Takashi Iwai <tiwai@suse.de> 9 */ 10 11 #ifdef SND_CS8403 12 13 #ifndef SND_CS8403_DECL 14 #define SND_CS8403_DECL static 15 #endif 16 #ifndef SND_CS8403_DECODE 17 #define SND_CS8403_DECODE snd_cs8403_decode_spdif_bits 18 #endif 19 #ifndef SND_CS8403_ENCODE 20 #define SND_CS8403_ENCODE snd_cs8403_encode_spdif_bits 21 #endif 22 23 24 SND_CS8403_DECL void SND_CS8403_DECODE(struct snd_aes_iec958 *diga, unsigned char bits) 25 { 26 if (bits & 0x01) { /* consumer */ 27 if (!(bits & 0x02)) 28 diga->status[0] |= IEC958_AES0_NONAUDIO; 29 if (!(bits & 0x08)) 30 diga->status[0] |= IEC958_AES0_CON_NOT_COPYRIGHT; 31 switch (bits & 0x10) { 32 case 0x10: diga->status[0] |= IEC958_AES0_CON_EMPHASIS_NONE; break; 33 case 0x00: diga->status[0] |= IEC958_AES0_CON_EMPHASIS_5015; break; 34 } 35 if (!(bits & 0x80)) 36 diga->status[1] |= IEC958_AES1_CON_ORIGINAL; 37 switch (bits & 0x60) { 38 case 0x00: diga->status[1] |= IEC958_AES1_CON_MAGNETIC_ID; break; 39 case 0x20: diga->status[1] |= IEC958_AES1_CON_DIGDIGCONV_ID; break; 40 case 0x40: diga->status[1] |= IEC958_AES1_CON_LASEROPT_ID; break; 41 case 0x60: diga->status[1] |= IEC958_AES1_CON_GENERAL; break; 42 } 43 switch (bits & 0x06) { 44 case 0x00: diga->status[3] |= IEC958_AES3_CON_FS_44100; break; 45 case 0x02: diga->status[3] |= IEC958_AES3_CON_FS_48000; break; 46 case 0x04: diga->status[3] |= IEC958_AES3_CON_FS_32000; break; 47 } 48 } else { 49 diga->status[0] = IEC958_AES0_PROFESSIONAL; 50 switch (bits & 0x18) { 51 case 0x00: diga->status[0] |= IEC958_AES0_PRO_FS_32000; break; 52 case 0x10: diga->status[0] |= IEC958_AES0_PRO_FS_44100; break; 53 case 0x08: diga->status[0] |= IEC958_AES0_PRO_FS_48000; break; 54 case 0x18: diga->status[0] |= IEC958_AES0_PRO_FS_NOTID; break; 55 } 56 switch (bits & 0x60) { 57 case 0x20: diga->status[0] |= IEC958_AES0_PRO_EMPHASIS_NONE; break; 58 case 0x40: diga->status[0] |= IEC958_AES0_PRO_EMPHASIS_5015; break; 59 case 0x00: diga->status[0] |= IEC958_AES0_PRO_EMPHASIS_CCITT; break; 60 case 0x60: diga->status[0] |= IEC958_AES0_PRO_EMPHASIS_NOTID; break; 61 } 62 if (bits & 0x80) 63 diga->status[1] |= IEC958_AES1_PRO_MODE_STEREOPHONIC; 64 } 65 } 66 67 SND_CS8403_DECL unsigned char SND_CS8403_ENCODE(struct snd_aes_iec958 *diga) 68 { 69 unsigned char bits; 70 71 if (!(diga->status[0] & IEC958_AES0_PROFESSIONAL)) { 72 bits = 0x01; /* consumer mode */ 73 if (diga->status[0] & IEC958_AES0_NONAUDIO) 74 bits &= ~0x02; 75 else 76 bits |= 0x02; 77 if (diga->status[0] & IEC958_AES0_CON_NOT_COPYRIGHT) 78 bits &= ~0x08; 79 else 80 bits |= 0x08; 81 switch (diga->status[0] & IEC958_AES0_CON_EMPHASIS) { 82 default: 83 case IEC958_AES0_CON_EMPHASIS_NONE: bits |= 0x10; break; 84 case IEC958_AES0_CON_EMPHASIS_5015: bits |= 0x00; break; 85 } 86 if (diga->status[1] & IEC958_AES1_CON_ORIGINAL) 87 bits &= ~0x80; 88 else 89 bits |= 0x80; 90 if ((diga->status[1] & IEC958_AES1_CON_CATEGORY) == IEC958_AES1_CON_GENERAL) 91 bits |= 0x60; 92 else { 93 switch(diga->status[1] & IEC958_AES1_CON_MAGNETIC_MASK) { 94 case IEC958_AES1_CON_MAGNETIC_ID: 95 bits |= 0x00; break; 96 case IEC958_AES1_CON_DIGDIGCONV_ID: 97 bits |= 0x20; break; 98 default: 99 case IEC958_AES1_CON_LASEROPT_ID: 100 bits |= 0x40; break; 101 } 102 } 103 switch (diga->status[3] & IEC958_AES3_CON_FS) { 104 default: 105 case IEC958_AES3_CON_FS_44100: bits |= 0x00; break; 106 case IEC958_AES3_CON_FS_48000: bits |= 0x02; break; 107 case IEC958_AES3_CON_FS_32000: bits |= 0x04; break; 108 } 109 } else { 110 bits = 0x00; /* professional mode */ 111 if (diga->status[0] & IEC958_AES0_NONAUDIO) 112 bits &= ~0x02; 113 else 114 bits |= 0x02; 115 /* CHECKME: I'm not sure about the bit order in val here */ 116 switch (diga->status[0] & IEC958_AES0_PRO_FS) { 117 case IEC958_AES0_PRO_FS_32000: bits |= 0x00; break; 118 case IEC958_AES0_PRO_FS_44100: bits |= 0x10; break; /* 44.1kHz */ 119 case IEC958_AES0_PRO_FS_48000: bits |= 0x08; break; /* 48kHz */ 120 default: 121 case IEC958_AES0_PRO_FS_NOTID: bits |= 0x18; break; 122 } 123 switch (diga->status[0] & IEC958_AES0_PRO_EMPHASIS) { 124 case IEC958_AES0_PRO_EMPHASIS_NONE: bits |= 0x20; break; 125 case IEC958_AES0_PRO_EMPHASIS_5015: bits |= 0x40; break; 126 case IEC958_AES0_PRO_EMPHASIS_CCITT: bits |= 0x00; break; 127 default: 128 case IEC958_AES0_PRO_EMPHASIS_NOTID: bits |= 0x60; break; 129 } 130 switch (diga->status[1] & IEC958_AES1_PRO_MODE) { 131 case IEC958_AES1_PRO_MODE_TWO: 132 case IEC958_AES1_PRO_MODE_STEREOPHONIC: bits |= 0x00; break; 133 default: bits |= 0x80; break; 134 } 135 } 136 return bits; 137 } 138 139 #endif /* SND_CS8403 */ 140 141 #ifdef SND_CS8404 142 143 #ifndef SND_CS8404_DECL 144 #define SND_CS8404_DECL static 145 #endif 146 #ifndef SND_CS8404_DECODE 147 #define SND_CS8404_DECODE snd_cs8404_decode_spdif_bits 148 #endif 149 #ifndef SND_CS8404_ENCODE 150 #define SND_CS8404_ENCODE snd_cs8404_encode_spdif_bits 151 #endif 152 153 154 SND_CS8404_DECL void SND_CS8404_DECODE(struct snd_aes_iec958 *diga, unsigned char bits) 155 { 156 if (bits & 0x10) { /* consumer */ 157 if (!(bits & 0x20)) 158 diga->status[0] |= IEC958_AES0_CON_NOT_COPYRIGHT; 159 if (!(bits & 0x40)) 160 diga->status[0] |= IEC958_AES0_CON_EMPHASIS_5015; 161 if (!(bits & 0x80)) 162 diga->status[1] |= IEC958_AES1_CON_ORIGINAL; 163 switch (bits & 0x03) { 164 case 0x00: diga->status[1] |= IEC958_AES1_CON_DAT; break; 165 case 0x03: diga->status[1] |= IEC958_AES1_CON_GENERAL; break; 166 } 167 switch (bits & 0x06) { 168 case 0x02: diga->status[3] |= IEC958_AES3_CON_FS_32000; break; 169 case 0x04: diga->status[3] |= IEC958_AES3_CON_FS_48000; break; 170 case 0x06: diga->status[3] |= IEC958_AES3_CON_FS_44100; break; 171 } 172 } else { 173 diga->status[0] = IEC958_AES0_PROFESSIONAL; 174 if (!(bits & 0x04)) 175 diga->status[0] |= IEC958_AES0_NONAUDIO; 176 switch (bits & 0x60) { 177 case 0x00: diga->status[0] |= IEC958_AES0_PRO_FS_32000; break; 178 case 0x40: diga->status[0] |= IEC958_AES0_PRO_FS_44100; break; 179 case 0x20: diga->status[0] |= IEC958_AES0_PRO_FS_48000; break; 180 case 0x60: diga->status[0] |= IEC958_AES0_PRO_FS_NOTID; break; 181 } 182 switch (bits & 0x03) { 183 case 0x02: diga->status[0] |= IEC958_AES0_PRO_EMPHASIS_NONE; break; 184 case 0x01: diga->status[0] |= IEC958_AES0_PRO_EMPHASIS_5015; break; 185 case 0x00: diga->status[0] |= IEC958_AES0_PRO_EMPHASIS_CCITT; break; 186 case 0x03: diga->status[0] |= IEC958_AES0_PRO_EMPHASIS_NOTID; break; 187 } 188 if (!(bits & 0x80)) 189 diga->status[1] |= IEC958_AES1_PRO_MODE_STEREOPHONIC; 190 } 191 } 192 193 SND_CS8404_DECL unsigned char SND_CS8404_ENCODE(struct snd_aes_iec958 *diga) 194 { 195 unsigned char bits; 196 197 if (!(diga->status[0] & IEC958_AES0_PROFESSIONAL)) { 198 bits = 0x10; /* consumer mode */ 199 if (!(diga->status[0] & IEC958_AES0_CON_NOT_COPYRIGHT)) 200 bits |= 0x20; 201 if ((diga->status[0] & IEC958_AES0_CON_EMPHASIS) == IEC958_AES0_CON_EMPHASIS_NONE) 202 bits |= 0x40; 203 if (!(diga->status[1] & IEC958_AES1_CON_ORIGINAL)) 204 bits |= 0x80; 205 if ((diga->status[1] & IEC958_AES1_CON_CATEGORY) == IEC958_AES1_CON_GENERAL) 206 bits |= 0x03; 207 switch (diga->status[3] & IEC958_AES3_CON_FS) { 208 default: 209 case IEC958_AES3_CON_FS_44100: bits |= 0x06; break; 210 case IEC958_AES3_CON_FS_48000: bits |= 0x04; break; 211 case IEC958_AES3_CON_FS_32000: bits |= 0x02; break; 212 } 213 } else { 214 bits = 0x00; /* professional mode */ 215 if (!(diga->status[0] & IEC958_AES0_NONAUDIO)) 216 bits |= 0x04; 217 switch (diga->status[0] & IEC958_AES0_PRO_FS) { 218 case IEC958_AES0_PRO_FS_32000: bits |= 0x00; break; 219 case IEC958_AES0_PRO_FS_44100: bits |= 0x40; break; /* 44.1kHz */ 220 case IEC958_AES0_PRO_FS_48000: bits |= 0x20; break; /* 48kHz */ 221 default: 222 case IEC958_AES0_PRO_FS_NOTID: bits |= 0x00; break; 223 } 224 switch (diga->status[0] & IEC958_AES0_PRO_EMPHASIS) { 225 case IEC958_AES0_PRO_EMPHASIS_NONE: bits |= 0x02; break; 226 case IEC958_AES0_PRO_EMPHASIS_5015: bits |= 0x01; break; 227 case IEC958_AES0_PRO_EMPHASIS_CCITT: bits |= 0x00; break; 228 default: 229 case IEC958_AES0_PRO_EMPHASIS_NOTID: bits |= 0x03; break; 230 } 231 switch (diga->status[1] & IEC958_AES1_PRO_MODE) { 232 case IEC958_AES1_PRO_MODE_TWO: 233 case IEC958_AES1_PRO_MODE_STEREOPHONIC: bits |= 0x00; break; 234 default: bits |= 0x80; break; 235 } 236 } 237 return bits; 238 } 239 240 #endif /* SND_CS8404 */ 241 242 #endif /* __SOUND_CS8403_H */ 243