1*1a59d1b8SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-or-later */ 21da177e4SLinus Torvalds #ifndef __SOUND_CS8403_H 31da177e4SLinus Torvalds #define __SOUND_CS8403_H 41da177e4SLinus Torvalds 51da177e4SLinus Torvalds /* 61da177e4SLinus Torvalds * Routines for Cirrus Logic CS8403/CS8404A IEC958 (S/PDIF) Transmitter 7c1017a4cSJaroslav Kysela * Copyright (c) by Jaroslav Kysela <perex@perex.cz>, 81da177e4SLinus Torvalds * Takashi Iwai <tiwai@suse.de> 91da177e4SLinus Torvalds */ 101da177e4SLinus Torvalds 111da177e4SLinus Torvalds #ifdef SND_CS8403 121da177e4SLinus Torvalds 131da177e4SLinus Torvalds #ifndef SND_CS8403_DECL 141da177e4SLinus Torvalds #define SND_CS8403_DECL static 151da177e4SLinus Torvalds #endif 161da177e4SLinus Torvalds #ifndef SND_CS8403_DECODE 171da177e4SLinus Torvalds #define SND_CS8403_DECODE snd_cs8403_decode_spdif_bits 181da177e4SLinus Torvalds #endif 191da177e4SLinus Torvalds #ifndef SND_CS8403_ENCODE 201da177e4SLinus Torvalds #define SND_CS8403_ENCODE snd_cs8403_encode_spdif_bits 211da177e4SLinus Torvalds #endif 221da177e4SLinus Torvalds 231da177e4SLinus Torvalds SND_CS8403_DECODE(struct snd_aes_iec958 * diga,unsigned char bits)2497f02e05STakashi IwaiSND_CS8403_DECL void SND_CS8403_DECODE(struct snd_aes_iec958 *diga, unsigned char bits) 251da177e4SLinus Torvalds { 261da177e4SLinus Torvalds if (bits & 0x01) { /* consumer */ 271da177e4SLinus Torvalds if (!(bits & 0x02)) 281da177e4SLinus Torvalds diga->status[0] |= IEC958_AES0_NONAUDIO; 291da177e4SLinus Torvalds if (!(bits & 0x08)) 301da177e4SLinus Torvalds diga->status[0] |= IEC958_AES0_CON_NOT_COPYRIGHT; 311da177e4SLinus Torvalds switch (bits & 0x10) { 321da177e4SLinus Torvalds case 0x10: diga->status[0] |= IEC958_AES0_CON_EMPHASIS_NONE; break; 331da177e4SLinus Torvalds case 0x00: diga->status[0] |= IEC958_AES0_CON_EMPHASIS_5015; break; 341da177e4SLinus Torvalds } 351da177e4SLinus Torvalds if (!(bits & 0x80)) 361da177e4SLinus Torvalds diga->status[1] |= IEC958_AES1_CON_ORIGINAL; 371da177e4SLinus Torvalds switch (bits & 0x60) { 381da177e4SLinus Torvalds case 0x00: diga->status[1] |= IEC958_AES1_CON_MAGNETIC_ID; break; 391da177e4SLinus Torvalds case 0x20: diga->status[1] |= IEC958_AES1_CON_DIGDIGCONV_ID; break; 401da177e4SLinus Torvalds case 0x40: diga->status[1] |= IEC958_AES1_CON_LASEROPT_ID; break; 411da177e4SLinus Torvalds case 0x60: diga->status[1] |= IEC958_AES1_CON_GENERAL; break; 421da177e4SLinus Torvalds } 431da177e4SLinus Torvalds switch (bits & 0x06) { 441da177e4SLinus Torvalds case 0x00: diga->status[3] |= IEC958_AES3_CON_FS_44100; break; 451da177e4SLinus Torvalds case 0x02: diga->status[3] |= IEC958_AES3_CON_FS_48000; break; 461da177e4SLinus Torvalds case 0x04: diga->status[3] |= IEC958_AES3_CON_FS_32000; break; 471da177e4SLinus Torvalds } 481da177e4SLinus Torvalds } else { 491da177e4SLinus Torvalds diga->status[0] = IEC958_AES0_PROFESSIONAL; 501da177e4SLinus Torvalds switch (bits & 0x18) { 511da177e4SLinus Torvalds case 0x00: diga->status[0] |= IEC958_AES0_PRO_FS_32000; break; 521da177e4SLinus Torvalds case 0x10: diga->status[0] |= IEC958_AES0_PRO_FS_44100; break; 531da177e4SLinus Torvalds case 0x08: diga->status[0] |= IEC958_AES0_PRO_FS_48000; break; 541da177e4SLinus Torvalds case 0x18: diga->status[0] |= IEC958_AES0_PRO_FS_NOTID; break; 551da177e4SLinus Torvalds } 561da177e4SLinus Torvalds switch (bits & 0x60) { 571da177e4SLinus Torvalds case 0x20: diga->status[0] |= IEC958_AES0_PRO_EMPHASIS_NONE; break; 581da177e4SLinus Torvalds case 0x40: diga->status[0] |= IEC958_AES0_PRO_EMPHASIS_5015; break; 591da177e4SLinus Torvalds case 0x00: diga->status[0] |= IEC958_AES0_PRO_EMPHASIS_CCITT; break; 601da177e4SLinus Torvalds case 0x60: diga->status[0] |= IEC958_AES0_PRO_EMPHASIS_NOTID; break; 611da177e4SLinus Torvalds } 621da177e4SLinus Torvalds if (bits & 0x80) 631da177e4SLinus Torvalds diga->status[1] |= IEC958_AES1_PRO_MODE_STEREOPHONIC; 641da177e4SLinus Torvalds } 651da177e4SLinus Torvalds } 661da177e4SLinus Torvalds SND_CS8403_ENCODE(struct snd_aes_iec958 * diga)6797f02e05STakashi IwaiSND_CS8403_DECL unsigned char SND_CS8403_ENCODE(struct snd_aes_iec958 *diga) 681da177e4SLinus Torvalds { 691da177e4SLinus Torvalds unsigned char bits; 701da177e4SLinus Torvalds 711da177e4SLinus Torvalds if (!(diga->status[0] & IEC958_AES0_PROFESSIONAL)) { 721da177e4SLinus Torvalds bits = 0x01; /* consumer mode */ 731da177e4SLinus Torvalds if (diga->status[0] & IEC958_AES0_NONAUDIO) 741da177e4SLinus Torvalds bits &= ~0x02; 751da177e4SLinus Torvalds else 761da177e4SLinus Torvalds bits |= 0x02; 771da177e4SLinus Torvalds if (diga->status[0] & IEC958_AES0_CON_NOT_COPYRIGHT) 781da177e4SLinus Torvalds bits &= ~0x08; 791da177e4SLinus Torvalds else 801da177e4SLinus Torvalds bits |= 0x08; 811da177e4SLinus Torvalds switch (diga->status[0] & IEC958_AES0_CON_EMPHASIS) { 821da177e4SLinus Torvalds default: 831da177e4SLinus Torvalds case IEC958_AES0_CON_EMPHASIS_NONE: bits |= 0x10; break; 841da177e4SLinus Torvalds case IEC958_AES0_CON_EMPHASIS_5015: bits |= 0x00; break; 851da177e4SLinus Torvalds } 861da177e4SLinus Torvalds if (diga->status[1] & IEC958_AES1_CON_ORIGINAL) 871da177e4SLinus Torvalds bits &= ~0x80; 881da177e4SLinus Torvalds else 891da177e4SLinus Torvalds bits |= 0x80; 901da177e4SLinus Torvalds if ((diga->status[1] & IEC958_AES1_CON_CATEGORY) == IEC958_AES1_CON_GENERAL) 911da177e4SLinus Torvalds bits |= 0x60; 921da177e4SLinus Torvalds else { 931da177e4SLinus Torvalds switch(diga->status[1] & IEC958_AES1_CON_MAGNETIC_MASK) { 941da177e4SLinus Torvalds case IEC958_AES1_CON_MAGNETIC_ID: 951da177e4SLinus Torvalds bits |= 0x00; break; 961da177e4SLinus Torvalds case IEC958_AES1_CON_DIGDIGCONV_ID: 971da177e4SLinus Torvalds bits |= 0x20; break; 981da177e4SLinus Torvalds default: 991da177e4SLinus Torvalds case IEC958_AES1_CON_LASEROPT_ID: 1001da177e4SLinus Torvalds bits |= 0x40; break; 1011da177e4SLinus Torvalds } 1021da177e4SLinus Torvalds } 1031da177e4SLinus Torvalds switch (diga->status[3] & IEC958_AES3_CON_FS) { 1041da177e4SLinus Torvalds default: 1051da177e4SLinus Torvalds case IEC958_AES3_CON_FS_44100: bits |= 0x00; break; 1061da177e4SLinus Torvalds case IEC958_AES3_CON_FS_48000: bits |= 0x02; break; 1071da177e4SLinus Torvalds case IEC958_AES3_CON_FS_32000: bits |= 0x04; break; 1081da177e4SLinus Torvalds } 1091da177e4SLinus Torvalds } else { 1101da177e4SLinus Torvalds bits = 0x00; /* professional mode */ 1111da177e4SLinus Torvalds if (diga->status[0] & IEC958_AES0_NONAUDIO) 1121da177e4SLinus Torvalds bits &= ~0x02; 1131da177e4SLinus Torvalds else 1141da177e4SLinus Torvalds bits |= 0x02; 1151da177e4SLinus Torvalds /* CHECKME: I'm not sure about the bit order in val here */ 1161da177e4SLinus Torvalds switch (diga->status[0] & IEC958_AES0_PRO_FS) { 1171da177e4SLinus Torvalds case IEC958_AES0_PRO_FS_32000: bits |= 0x00; break; 1181da177e4SLinus Torvalds case IEC958_AES0_PRO_FS_44100: bits |= 0x10; break; /* 44.1kHz */ 1191da177e4SLinus Torvalds case IEC958_AES0_PRO_FS_48000: bits |= 0x08; break; /* 48kHz */ 1201da177e4SLinus Torvalds default: 1211da177e4SLinus Torvalds case IEC958_AES0_PRO_FS_NOTID: bits |= 0x18; break; 1221da177e4SLinus Torvalds } 1231da177e4SLinus Torvalds switch (diga->status[0] & IEC958_AES0_PRO_EMPHASIS) { 1241da177e4SLinus Torvalds case IEC958_AES0_PRO_EMPHASIS_NONE: bits |= 0x20; break; 1251da177e4SLinus Torvalds case IEC958_AES0_PRO_EMPHASIS_5015: bits |= 0x40; break; 1261da177e4SLinus Torvalds case IEC958_AES0_PRO_EMPHASIS_CCITT: bits |= 0x00; break; 1271da177e4SLinus Torvalds default: 1281da177e4SLinus Torvalds case IEC958_AES0_PRO_EMPHASIS_NOTID: bits |= 0x60; break; 1291da177e4SLinus Torvalds } 1301da177e4SLinus Torvalds switch (diga->status[1] & IEC958_AES1_PRO_MODE) { 1311da177e4SLinus Torvalds case IEC958_AES1_PRO_MODE_TWO: 1321da177e4SLinus Torvalds case IEC958_AES1_PRO_MODE_STEREOPHONIC: bits |= 0x00; break; 1331da177e4SLinus Torvalds default: bits |= 0x80; break; 1341da177e4SLinus Torvalds } 1351da177e4SLinus Torvalds } 1361da177e4SLinus Torvalds return bits; 1371da177e4SLinus Torvalds } 1381da177e4SLinus Torvalds 1391da177e4SLinus Torvalds #endif /* SND_CS8403 */ 1401da177e4SLinus Torvalds 1411da177e4SLinus Torvalds #ifdef SND_CS8404 1421da177e4SLinus Torvalds 1431da177e4SLinus Torvalds #ifndef SND_CS8404_DECL 1441da177e4SLinus Torvalds #define SND_CS8404_DECL static 1451da177e4SLinus Torvalds #endif 1461da177e4SLinus Torvalds #ifndef SND_CS8404_DECODE 1471da177e4SLinus Torvalds #define SND_CS8404_DECODE snd_cs8404_decode_spdif_bits 1481da177e4SLinus Torvalds #endif 1491da177e4SLinus Torvalds #ifndef SND_CS8404_ENCODE 1501da177e4SLinus Torvalds #define SND_CS8404_ENCODE snd_cs8404_encode_spdif_bits 1511da177e4SLinus Torvalds #endif 1521da177e4SLinus Torvalds 1531da177e4SLinus Torvalds SND_CS8404_DECODE(struct snd_aes_iec958 * diga,unsigned char bits)15497f02e05STakashi IwaiSND_CS8404_DECL void SND_CS8404_DECODE(struct snd_aes_iec958 *diga, unsigned char bits) 1551da177e4SLinus Torvalds { 1561da177e4SLinus Torvalds if (bits & 0x10) { /* consumer */ 1571da177e4SLinus Torvalds if (!(bits & 0x20)) 1581da177e4SLinus Torvalds diga->status[0] |= IEC958_AES0_CON_NOT_COPYRIGHT; 1591da177e4SLinus Torvalds if (!(bits & 0x40)) 1601da177e4SLinus Torvalds diga->status[0] |= IEC958_AES0_CON_EMPHASIS_5015; 1611da177e4SLinus Torvalds if (!(bits & 0x80)) 1621da177e4SLinus Torvalds diga->status[1] |= IEC958_AES1_CON_ORIGINAL; 1631da177e4SLinus Torvalds switch (bits & 0x03) { 1641da177e4SLinus Torvalds case 0x00: diga->status[1] |= IEC958_AES1_CON_DAT; break; 1651da177e4SLinus Torvalds case 0x03: diga->status[1] |= IEC958_AES1_CON_GENERAL; break; 1661da177e4SLinus Torvalds } 1671da177e4SLinus Torvalds switch (bits & 0x06) { 1681da177e4SLinus Torvalds case 0x02: diga->status[3] |= IEC958_AES3_CON_FS_32000; break; 1691da177e4SLinus Torvalds case 0x04: diga->status[3] |= IEC958_AES3_CON_FS_48000; break; 1701da177e4SLinus Torvalds case 0x06: diga->status[3] |= IEC958_AES3_CON_FS_44100; break; 1711da177e4SLinus Torvalds } 1721da177e4SLinus Torvalds } else { 1731da177e4SLinus Torvalds diga->status[0] = IEC958_AES0_PROFESSIONAL; 1741da177e4SLinus Torvalds if (!(bits & 0x04)) 1751da177e4SLinus Torvalds diga->status[0] |= IEC958_AES0_NONAUDIO; 1761da177e4SLinus Torvalds switch (bits & 0x60) { 1771da177e4SLinus Torvalds case 0x00: diga->status[0] |= IEC958_AES0_PRO_FS_32000; break; 1781da177e4SLinus Torvalds case 0x40: diga->status[0] |= IEC958_AES0_PRO_FS_44100; break; 1791da177e4SLinus Torvalds case 0x20: diga->status[0] |= IEC958_AES0_PRO_FS_48000; break; 1801da177e4SLinus Torvalds case 0x60: diga->status[0] |= IEC958_AES0_PRO_FS_NOTID; break; 1811da177e4SLinus Torvalds } 1821da177e4SLinus Torvalds switch (bits & 0x03) { 1831da177e4SLinus Torvalds case 0x02: diga->status[0] |= IEC958_AES0_PRO_EMPHASIS_NONE; break; 1841da177e4SLinus Torvalds case 0x01: diga->status[0] |= IEC958_AES0_PRO_EMPHASIS_5015; break; 1851da177e4SLinus Torvalds case 0x00: diga->status[0] |= IEC958_AES0_PRO_EMPHASIS_CCITT; break; 1861da177e4SLinus Torvalds case 0x03: diga->status[0] |= IEC958_AES0_PRO_EMPHASIS_NOTID; break; 1871da177e4SLinus Torvalds } 1881da177e4SLinus Torvalds if (!(bits & 0x80)) 1891da177e4SLinus Torvalds diga->status[1] |= IEC958_AES1_PRO_MODE_STEREOPHONIC; 1901da177e4SLinus Torvalds } 1911da177e4SLinus Torvalds } 1921da177e4SLinus Torvalds SND_CS8404_ENCODE(struct snd_aes_iec958 * diga)19397f02e05STakashi IwaiSND_CS8404_DECL unsigned char SND_CS8404_ENCODE(struct snd_aes_iec958 *diga) 1941da177e4SLinus Torvalds { 1951da177e4SLinus Torvalds unsigned char bits; 1961da177e4SLinus Torvalds 1971da177e4SLinus Torvalds if (!(diga->status[0] & IEC958_AES0_PROFESSIONAL)) { 1981da177e4SLinus Torvalds bits = 0x10; /* consumer mode */ 1991da177e4SLinus Torvalds if (!(diga->status[0] & IEC958_AES0_CON_NOT_COPYRIGHT)) 2001da177e4SLinus Torvalds bits |= 0x20; 2011da177e4SLinus Torvalds if ((diga->status[0] & IEC958_AES0_CON_EMPHASIS) == IEC958_AES0_CON_EMPHASIS_NONE) 2021da177e4SLinus Torvalds bits |= 0x40; 2031da177e4SLinus Torvalds if (!(diga->status[1] & IEC958_AES1_CON_ORIGINAL)) 2041da177e4SLinus Torvalds bits |= 0x80; 2051da177e4SLinus Torvalds if ((diga->status[1] & IEC958_AES1_CON_CATEGORY) == IEC958_AES1_CON_GENERAL) 2061da177e4SLinus Torvalds bits |= 0x03; 2071da177e4SLinus Torvalds switch (diga->status[3] & IEC958_AES3_CON_FS) { 2081da177e4SLinus Torvalds default: 2091da177e4SLinus Torvalds case IEC958_AES3_CON_FS_44100: bits |= 0x06; break; 2101da177e4SLinus Torvalds case IEC958_AES3_CON_FS_48000: bits |= 0x04; break; 2111da177e4SLinus Torvalds case IEC958_AES3_CON_FS_32000: bits |= 0x02; break; 2121da177e4SLinus Torvalds } 2131da177e4SLinus Torvalds } else { 2141da177e4SLinus Torvalds bits = 0x00; /* professional mode */ 2151da177e4SLinus Torvalds if (!(diga->status[0] & IEC958_AES0_NONAUDIO)) 2161da177e4SLinus Torvalds bits |= 0x04; 2171da177e4SLinus Torvalds switch (diga->status[0] & IEC958_AES0_PRO_FS) { 2181da177e4SLinus Torvalds case IEC958_AES0_PRO_FS_32000: bits |= 0x00; break; 2191da177e4SLinus Torvalds case IEC958_AES0_PRO_FS_44100: bits |= 0x40; break; /* 44.1kHz */ 2201da177e4SLinus Torvalds case IEC958_AES0_PRO_FS_48000: bits |= 0x20; break; /* 48kHz */ 2211da177e4SLinus Torvalds default: 2221da177e4SLinus Torvalds case IEC958_AES0_PRO_FS_NOTID: bits |= 0x00; break; 2231da177e4SLinus Torvalds } 2241da177e4SLinus Torvalds switch (diga->status[0] & IEC958_AES0_PRO_EMPHASIS) { 2251da177e4SLinus Torvalds case IEC958_AES0_PRO_EMPHASIS_NONE: bits |= 0x02; break; 2261da177e4SLinus Torvalds case IEC958_AES0_PRO_EMPHASIS_5015: bits |= 0x01; break; 2271da177e4SLinus Torvalds case IEC958_AES0_PRO_EMPHASIS_CCITT: bits |= 0x00; break; 2281da177e4SLinus Torvalds default: 2291da177e4SLinus Torvalds case IEC958_AES0_PRO_EMPHASIS_NOTID: bits |= 0x03; break; 2301da177e4SLinus Torvalds } 2311da177e4SLinus Torvalds switch (diga->status[1] & IEC958_AES1_PRO_MODE) { 2321da177e4SLinus Torvalds case IEC958_AES1_PRO_MODE_TWO: 2331da177e4SLinus Torvalds case IEC958_AES1_PRO_MODE_STEREOPHONIC: bits |= 0x00; break; 2341da177e4SLinus Torvalds default: bits |= 0x80; break; 2351da177e4SLinus Torvalds } 2361da177e4SLinus Torvalds } 2371da177e4SLinus Torvalds return bits; 2381da177e4SLinus Torvalds } 2391da177e4SLinus Torvalds 2401da177e4SLinus Torvalds #endif /* SND_CS8404 */ 2411da177e4SLinus Torvalds 2421da177e4SLinus Torvalds #endif /* __SOUND_CS8403_H */ 243