162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
262306a36Sopenharmony_ci#ifndef __SOUND_CS8403_H
362306a36Sopenharmony_ci#define __SOUND_CS8403_H
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci/*
662306a36Sopenharmony_ci *  Routines for Cirrus Logic CS8403/CS8404A IEC958 (S/PDIF) Transmitter
762306a36Sopenharmony_ci *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>,
862306a36Sopenharmony_ci *		     Takashi Iwai <tiwai@suse.de>
962306a36Sopenharmony_ci */
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#ifdef SND_CS8403
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#ifndef SND_CS8403_DECL
1462306a36Sopenharmony_ci#define SND_CS8403_DECL static
1562306a36Sopenharmony_ci#endif
1662306a36Sopenharmony_ci#ifndef SND_CS8403_DECODE
1762306a36Sopenharmony_ci#define SND_CS8403_DECODE snd_cs8403_decode_spdif_bits
1862306a36Sopenharmony_ci#endif
1962306a36Sopenharmony_ci#ifndef SND_CS8403_ENCODE
2062306a36Sopenharmony_ci#define SND_CS8403_ENCODE snd_cs8403_encode_spdif_bits
2162306a36Sopenharmony_ci#endif
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ciSND_CS8403_DECL void SND_CS8403_DECODE(struct snd_aes_iec958 *diga, unsigned char bits)
2562306a36Sopenharmony_ci{
2662306a36Sopenharmony_ci	if (bits & 0x01) {	/* consumer */
2762306a36Sopenharmony_ci		if (!(bits & 0x02))
2862306a36Sopenharmony_ci			diga->status[0] |= IEC958_AES0_NONAUDIO;
2962306a36Sopenharmony_ci		if (!(bits & 0x08))
3062306a36Sopenharmony_ci			diga->status[0] |= IEC958_AES0_CON_NOT_COPYRIGHT;
3162306a36Sopenharmony_ci		switch (bits & 0x10) {
3262306a36Sopenharmony_ci		case 0x10: diga->status[0] |= IEC958_AES0_CON_EMPHASIS_NONE; break;
3362306a36Sopenharmony_ci		case 0x00: diga->status[0] |= IEC958_AES0_CON_EMPHASIS_5015; break;
3462306a36Sopenharmony_ci		}
3562306a36Sopenharmony_ci		if (!(bits & 0x80))
3662306a36Sopenharmony_ci			diga->status[1] |= IEC958_AES1_CON_ORIGINAL;
3762306a36Sopenharmony_ci		switch (bits & 0x60) {
3862306a36Sopenharmony_ci		case 0x00: diga->status[1] |= IEC958_AES1_CON_MAGNETIC_ID; break;
3962306a36Sopenharmony_ci		case 0x20: diga->status[1] |= IEC958_AES1_CON_DIGDIGCONV_ID; break;
4062306a36Sopenharmony_ci		case 0x40: diga->status[1] |= IEC958_AES1_CON_LASEROPT_ID; break;
4162306a36Sopenharmony_ci		case 0x60: diga->status[1] |= IEC958_AES1_CON_GENERAL; break;
4262306a36Sopenharmony_ci		}
4362306a36Sopenharmony_ci		switch (bits & 0x06) {
4462306a36Sopenharmony_ci		case 0x00: diga->status[3] |= IEC958_AES3_CON_FS_44100; break;
4562306a36Sopenharmony_ci		case 0x02: diga->status[3] |= IEC958_AES3_CON_FS_48000; break;
4662306a36Sopenharmony_ci		case 0x04: diga->status[3] |= IEC958_AES3_CON_FS_32000; break;
4762306a36Sopenharmony_ci		}
4862306a36Sopenharmony_ci	} else {
4962306a36Sopenharmony_ci		diga->status[0] = IEC958_AES0_PROFESSIONAL;
5062306a36Sopenharmony_ci		switch (bits & 0x18) {
5162306a36Sopenharmony_ci		case 0x00: diga->status[0] |= IEC958_AES0_PRO_FS_32000; break;
5262306a36Sopenharmony_ci		case 0x10: diga->status[0] |= IEC958_AES0_PRO_FS_44100; break;
5362306a36Sopenharmony_ci		case 0x08: diga->status[0] |= IEC958_AES0_PRO_FS_48000; break;
5462306a36Sopenharmony_ci		case 0x18: diga->status[0] |= IEC958_AES0_PRO_FS_NOTID; break;
5562306a36Sopenharmony_ci		}
5662306a36Sopenharmony_ci		switch (bits & 0x60) {
5762306a36Sopenharmony_ci		case 0x20: diga->status[0] |= IEC958_AES0_PRO_EMPHASIS_NONE; break;
5862306a36Sopenharmony_ci		case 0x40: diga->status[0] |= IEC958_AES0_PRO_EMPHASIS_5015; break;
5962306a36Sopenharmony_ci		case 0x00: diga->status[0] |= IEC958_AES0_PRO_EMPHASIS_CCITT; break;
6062306a36Sopenharmony_ci		case 0x60: diga->status[0] |= IEC958_AES0_PRO_EMPHASIS_NOTID; break;
6162306a36Sopenharmony_ci		}
6262306a36Sopenharmony_ci		if (bits & 0x80)
6362306a36Sopenharmony_ci			diga->status[1] |= IEC958_AES1_PRO_MODE_STEREOPHONIC;
6462306a36Sopenharmony_ci	}
6562306a36Sopenharmony_ci}
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ciSND_CS8403_DECL unsigned char SND_CS8403_ENCODE(struct snd_aes_iec958 *diga)
6862306a36Sopenharmony_ci{
6962306a36Sopenharmony_ci	unsigned char bits;
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci	if (!(diga->status[0] & IEC958_AES0_PROFESSIONAL)) {
7262306a36Sopenharmony_ci		bits = 0x01;	/* consumer mode */
7362306a36Sopenharmony_ci		if (diga->status[0] & IEC958_AES0_NONAUDIO)
7462306a36Sopenharmony_ci			bits &= ~0x02;
7562306a36Sopenharmony_ci		else
7662306a36Sopenharmony_ci			bits |= 0x02;
7762306a36Sopenharmony_ci		if (diga->status[0] & IEC958_AES0_CON_NOT_COPYRIGHT)
7862306a36Sopenharmony_ci			bits &= ~0x08;
7962306a36Sopenharmony_ci		else
8062306a36Sopenharmony_ci			bits |= 0x08;
8162306a36Sopenharmony_ci		switch (diga->status[0] & IEC958_AES0_CON_EMPHASIS) {
8262306a36Sopenharmony_ci		default:
8362306a36Sopenharmony_ci		case IEC958_AES0_CON_EMPHASIS_NONE: bits |= 0x10; break;
8462306a36Sopenharmony_ci		case IEC958_AES0_CON_EMPHASIS_5015: bits |= 0x00; break;
8562306a36Sopenharmony_ci		}
8662306a36Sopenharmony_ci		if (diga->status[1] & IEC958_AES1_CON_ORIGINAL)
8762306a36Sopenharmony_ci			bits &= ~0x80;
8862306a36Sopenharmony_ci		else
8962306a36Sopenharmony_ci			bits |= 0x80;
9062306a36Sopenharmony_ci		if ((diga->status[1] & IEC958_AES1_CON_CATEGORY) == IEC958_AES1_CON_GENERAL)
9162306a36Sopenharmony_ci			bits |= 0x60;
9262306a36Sopenharmony_ci		else {
9362306a36Sopenharmony_ci			switch(diga->status[1] & IEC958_AES1_CON_MAGNETIC_MASK) {
9462306a36Sopenharmony_ci			case IEC958_AES1_CON_MAGNETIC_ID:
9562306a36Sopenharmony_ci				bits |= 0x00; break;
9662306a36Sopenharmony_ci			case IEC958_AES1_CON_DIGDIGCONV_ID:
9762306a36Sopenharmony_ci				bits |= 0x20; break;
9862306a36Sopenharmony_ci			default:
9962306a36Sopenharmony_ci			case IEC958_AES1_CON_LASEROPT_ID:
10062306a36Sopenharmony_ci				bits |= 0x40; break;
10162306a36Sopenharmony_ci			}
10262306a36Sopenharmony_ci		}
10362306a36Sopenharmony_ci		switch (diga->status[3] & IEC958_AES3_CON_FS) {
10462306a36Sopenharmony_ci		default:
10562306a36Sopenharmony_ci		case IEC958_AES3_CON_FS_44100: bits |= 0x00; break;
10662306a36Sopenharmony_ci		case IEC958_AES3_CON_FS_48000: bits |= 0x02; break;
10762306a36Sopenharmony_ci		case IEC958_AES3_CON_FS_32000: bits |= 0x04; break;
10862306a36Sopenharmony_ci		}
10962306a36Sopenharmony_ci	} else {
11062306a36Sopenharmony_ci		bits = 0x00;	/* professional mode */
11162306a36Sopenharmony_ci		if (diga->status[0] & IEC958_AES0_NONAUDIO)
11262306a36Sopenharmony_ci			bits &= ~0x02;
11362306a36Sopenharmony_ci		else
11462306a36Sopenharmony_ci			bits |= 0x02;
11562306a36Sopenharmony_ci		/* CHECKME: I'm not sure about the bit order in val here */
11662306a36Sopenharmony_ci		switch (diga->status[0] & IEC958_AES0_PRO_FS) {
11762306a36Sopenharmony_ci		case IEC958_AES0_PRO_FS_32000:	bits |= 0x00; break;
11862306a36Sopenharmony_ci		case IEC958_AES0_PRO_FS_44100:	bits |= 0x10; break;	/* 44.1kHz */
11962306a36Sopenharmony_ci		case IEC958_AES0_PRO_FS_48000:	bits |= 0x08; break;	/* 48kHz */
12062306a36Sopenharmony_ci		default:
12162306a36Sopenharmony_ci		case IEC958_AES0_PRO_FS_NOTID: bits |= 0x18; break;
12262306a36Sopenharmony_ci		}
12362306a36Sopenharmony_ci		switch (diga->status[0] & IEC958_AES0_PRO_EMPHASIS) {
12462306a36Sopenharmony_ci		case IEC958_AES0_PRO_EMPHASIS_NONE: bits |= 0x20; break;
12562306a36Sopenharmony_ci		case IEC958_AES0_PRO_EMPHASIS_5015: bits |= 0x40; break;
12662306a36Sopenharmony_ci		case IEC958_AES0_PRO_EMPHASIS_CCITT: bits |= 0x00; break;
12762306a36Sopenharmony_ci		default:
12862306a36Sopenharmony_ci		case IEC958_AES0_PRO_EMPHASIS_NOTID: bits |= 0x60; break;
12962306a36Sopenharmony_ci		}
13062306a36Sopenharmony_ci		switch (diga->status[1] & IEC958_AES1_PRO_MODE) {
13162306a36Sopenharmony_ci		case IEC958_AES1_PRO_MODE_TWO:
13262306a36Sopenharmony_ci		case IEC958_AES1_PRO_MODE_STEREOPHONIC: bits |= 0x00; break;
13362306a36Sopenharmony_ci		default: bits |= 0x80; break;
13462306a36Sopenharmony_ci		}
13562306a36Sopenharmony_ci	}
13662306a36Sopenharmony_ci	return bits;
13762306a36Sopenharmony_ci}
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci#endif /* SND_CS8403 */
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci#ifdef SND_CS8404
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci#ifndef SND_CS8404_DECL
14462306a36Sopenharmony_ci#define SND_CS8404_DECL static
14562306a36Sopenharmony_ci#endif
14662306a36Sopenharmony_ci#ifndef SND_CS8404_DECODE
14762306a36Sopenharmony_ci#define SND_CS8404_DECODE snd_cs8404_decode_spdif_bits
14862306a36Sopenharmony_ci#endif
14962306a36Sopenharmony_ci#ifndef SND_CS8404_ENCODE
15062306a36Sopenharmony_ci#define SND_CS8404_ENCODE snd_cs8404_encode_spdif_bits
15162306a36Sopenharmony_ci#endif
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ciSND_CS8404_DECL void SND_CS8404_DECODE(struct snd_aes_iec958 *diga, unsigned char bits)
15562306a36Sopenharmony_ci{
15662306a36Sopenharmony_ci	if (bits & 0x10) {	/* consumer */
15762306a36Sopenharmony_ci		if (!(bits & 0x20))
15862306a36Sopenharmony_ci			diga->status[0] |= IEC958_AES0_CON_NOT_COPYRIGHT;
15962306a36Sopenharmony_ci		if (!(bits & 0x40))
16062306a36Sopenharmony_ci			diga->status[0] |= IEC958_AES0_CON_EMPHASIS_5015;
16162306a36Sopenharmony_ci		if (!(bits & 0x80))
16262306a36Sopenharmony_ci			diga->status[1] |= IEC958_AES1_CON_ORIGINAL;
16362306a36Sopenharmony_ci		switch (bits & 0x03) {
16462306a36Sopenharmony_ci		case 0x00: diga->status[1] |= IEC958_AES1_CON_DAT; break;
16562306a36Sopenharmony_ci		case 0x03: diga->status[1] |= IEC958_AES1_CON_GENERAL; break;
16662306a36Sopenharmony_ci		}
16762306a36Sopenharmony_ci		switch (bits & 0x06) {
16862306a36Sopenharmony_ci		case 0x02: diga->status[3] |= IEC958_AES3_CON_FS_32000; break;
16962306a36Sopenharmony_ci		case 0x04: diga->status[3] |= IEC958_AES3_CON_FS_48000; break;
17062306a36Sopenharmony_ci		case 0x06: diga->status[3] |= IEC958_AES3_CON_FS_44100; break;
17162306a36Sopenharmony_ci		}
17262306a36Sopenharmony_ci	} else {
17362306a36Sopenharmony_ci		diga->status[0] = IEC958_AES0_PROFESSIONAL;
17462306a36Sopenharmony_ci		if (!(bits & 0x04))
17562306a36Sopenharmony_ci			diga->status[0] |= IEC958_AES0_NONAUDIO;
17662306a36Sopenharmony_ci		switch (bits & 0x60) {
17762306a36Sopenharmony_ci		case 0x00: diga->status[0] |= IEC958_AES0_PRO_FS_32000; break;
17862306a36Sopenharmony_ci		case 0x40: diga->status[0] |= IEC958_AES0_PRO_FS_44100; break;
17962306a36Sopenharmony_ci		case 0x20: diga->status[0] |= IEC958_AES0_PRO_FS_48000; break;
18062306a36Sopenharmony_ci		case 0x60: diga->status[0] |= IEC958_AES0_PRO_FS_NOTID; break;
18162306a36Sopenharmony_ci		}
18262306a36Sopenharmony_ci		switch (bits & 0x03) {
18362306a36Sopenharmony_ci		case 0x02: diga->status[0] |= IEC958_AES0_PRO_EMPHASIS_NONE; break;
18462306a36Sopenharmony_ci		case 0x01: diga->status[0] |= IEC958_AES0_PRO_EMPHASIS_5015; break;
18562306a36Sopenharmony_ci		case 0x00: diga->status[0] |= IEC958_AES0_PRO_EMPHASIS_CCITT; break;
18662306a36Sopenharmony_ci		case 0x03: diga->status[0] |= IEC958_AES0_PRO_EMPHASIS_NOTID; break;
18762306a36Sopenharmony_ci		}
18862306a36Sopenharmony_ci		if (!(bits & 0x80))
18962306a36Sopenharmony_ci			diga->status[1] |= IEC958_AES1_PRO_MODE_STEREOPHONIC;
19062306a36Sopenharmony_ci	}
19162306a36Sopenharmony_ci}
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ciSND_CS8404_DECL unsigned char SND_CS8404_ENCODE(struct snd_aes_iec958 *diga)
19462306a36Sopenharmony_ci{
19562306a36Sopenharmony_ci	unsigned char bits;
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci	if (!(diga->status[0] & IEC958_AES0_PROFESSIONAL)) {
19862306a36Sopenharmony_ci		bits = 0x10;	/* consumer mode */
19962306a36Sopenharmony_ci		if (!(diga->status[0] & IEC958_AES0_CON_NOT_COPYRIGHT))
20062306a36Sopenharmony_ci			bits |= 0x20;
20162306a36Sopenharmony_ci		if ((diga->status[0] & IEC958_AES0_CON_EMPHASIS) == IEC958_AES0_CON_EMPHASIS_NONE)
20262306a36Sopenharmony_ci			bits |= 0x40;
20362306a36Sopenharmony_ci		if (!(diga->status[1] & IEC958_AES1_CON_ORIGINAL))
20462306a36Sopenharmony_ci			bits |= 0x80;
20562306a36Sopenharmony_ci		if ((diga->status[1] & IEC958_AES1_CON_CATEGORY) == IEC958_AES1_CON_GENERAL)
20662306a36Sopenharmony_ci			bits |= 0x03;
20762306a36Sopenharmony_ci		switch (diga->status[3] & IEC958_AES3_CON_FS) {
20862306a36Sopenharmony_ci		default:
20962306a36Sopenharmony_ci		case IEC958_AES3_CON_FS_44100: bits |= 0x06; break;
21062306a36Sopenharmony_ci		case IEC958_AES3_CON_FS_48000: bits |= 0x04; break;
21162306a36Sopenharmony_ci		case IEC958_AES3_CON_FS_32000: bits |= 0x02; break;
21262306a36Sopenharmony_ci		}
21362306a36Sopenharmony_ci	} else {
21462306a36Sopenharmony_ci		bits = 0x00;	/* professional mode */
21562306a36Sopenharmony_ci		if (!(diga->status[0] & IEC958_AES0_NONAUDIO))
21662306a36Sopenharmony_ci			bits |= 0x04;
21762306a36Sopenharmony_ci		switch (diga->status[0] & IEC958_AES0_PRO_FS) {
21862306a36Sopenharmony_ci		case IEC958_AES0_PRO_FS_32000:	bits |= 0x00; break;
21962306a36Sopenharmony_ci		case IEC958_AES0_PRO_FS_44100:	bits |= 0x40; break;	/* 44.1kHz */
22062306a36Sopenharmony_ci		case IEC958_AES0_PRO_FS_48000:	bits |= 0x20; break;	/* 48kHz */
22162306a36Sopenharmony_ci		default:
22262306a36Sopenharmony_ci		case IEC958_AES0_PRO_FS_NOTID:	bits |= 0x00; break;
22362306a36Sopenharmony_ci		}
22462306a36Sopenharmony_ci		switch (diga->status[0] & IEC958_AES0_PRO_EMPHASIS) {
22562306a36Sopenharmony_ci		case IEC958_AES0_PRO_EMPHASIS_NONE: bits |= 0x02; break;
22662306a36Sopenharmony_ci		case IEC958_AES0_PRO_EMPHASIS_5015: bits |= 0x01; break;
22762306a36Sopenharmony_ci		case IEC958_AES0_PRO_EMPHASIS_CCITT: bits |= 0x00; break;
22862306a36Sopenharmony_ci		default:
22962306a36Sopenharmony_ci		case IEC958_AES0_PRO_EMPHASIS_NOTID: bits |= 0x03; break;
23062306a36Sopenharmony_ci		}
23162306a36Sopenharmony_ci		switch (diga->status[1] & IEC958_AES1_PRO_MODE) {
23262306a36Sopenharmony_ci		case IEC958_AES1_PRO_MODE_TWO:
23362306a36Sopenharmony_ci		case IEC958_AES1_PRO_MODE_STEREOPHONIC: bits |= 0x00; break;
23462306a36Sopenharmony_ci		default: bits |= 0x80; break;
23562306a36Sopenharmony_ci		}
23662306a36Sopenharmony_ci	}
23762306a36Sopenharmony_ci	return bits;
23862306a36Sopenharmony_ci}
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci#endif /* SND_CS8404 */
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_ci#endif /* __SOUND_CS8403_H */
243