243 lines · c
1/* SPDX-License-Identifier: GPL-2.0-or-later */2#ifndef __SOUND_CS8403_H3#define __SOUND_CS8403_H4 5/*6 * Routines for Cirrus Logic CS8403/CS8404A IEC958 (S/PDIF) Transmitter7 * Copyright (c) by Jaroslav Kysela <perex@perex.cz>,8 * Takashi Iwai <tiwai@suse.de>9 */10 11#ifdef SND_CS840312 13#ifndef SND_CS8403_DECL14#define SND_CS8403_DECL static15#endif16#ifndef SND_CS8403_DECODE17#define SND_CS8403_DECODE snd_cs8403_decode_spdif_bits18#endif19#ifndef SND_CS8403_ENCODE20#define SND_CS8403_ENCODE snd_cs8403_encode_spdif_bits21#endif22 23 24SND_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 67SND_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 else76 bits |= 0x02;77 if (diga->status[0] & IEC958_AES0_CON_NOT_COPYRIGHT)78 bits &= ~0x08;79 else80 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 else89 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 else114 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_CS8404142 143#ifndef SND_CS8404_DECL144#define SND_CS8404_DECL static145#endif146#ifndef SND_CS8404_DECODE147#define SND_CS8404_DECODE snd_cs8404_decode_spdif_bits148#endif149#ifndef SND_CS8404_ENCODE150#define SND_CS8404_ENCODE snd_cs8404_encode_spdif_bits151#endif152 153 154SND_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 193SND_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