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