xref: /linux/include/sound/cs8403.h (revision bd628c1bed7902ec1f24ba0fe70758949146abbe)
1 #ifndef __SOUND_CS8403_H
2 #define __SOUND_CS8403_H
3 
4 /*
5  *  Routines for Cirrus Logic CS8403/CS8404A IEC958 (S/PDIF) Transmitter
6  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>,
7  *		     Takashi Iwai <tiwai@suse.de>
8  *
9  *
10  *   This program is free software; you can redistribute it and/or modify
11  *   it under the terms of the GNU General Public License as published by
12  *   the Free Software Foundation; either version 2 of the License, or
13  *   (at your option) any later version.
14  *
15  *   This program is distributed in the hope that it will be useful,
16  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *   GNU General Public License for more details.
19  *
20  *   You should have received a copy of the GNU General Public License
21  *   along with this program; if not, write to the Free Software
22  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
23  *
24  */
25 
26 #ifdef SND_CS8403
27 
28 #ifndef SND_CS8403_DECL
29 #define SND_CS8403_DECL static
30 #endif
31 #ifndef SND_CS8403_DECODE
32 #define SND_CS8403_DECODE snd_cs8403_decode_spdif_bits
33 #endif
34 #ifndef SND_CS8403_ENCODE
35 #define SND_CS8403_ENCODE snd_cs8403_encode_spdif_bits
36 #endif
37 
38 
39 SND_CS8403_DECL void SND_CS8403_DECODE(struct snd_aes_iec958 *diga, unsigned char bits)
40 {
41 	if (bits & 0x01) {	/* consumer */
42 		if (!(bits & 0x02))
43 			diga->status[0] |= IEC958_AES0_NONAUDIO;
44 		if (!(bits & 0x08))
45 			diga->status[0] |= IEC958_AES0_CON_NOT_COPYRIGHT;
46 		switch (bits & 0x10) {
47 		case 0x10: diga->status[0] |= IEC958_AES0_CON_EMPHASIS_NONE; break;
48 		case 0x00: diga->status[0] |= IEC958_AES0_CON_EMPHASIS_5015; break;
49 		}
50 		if (!(bits & 0x80))
51 			diga->status[1] |= IEC958_AES1_CON_ORIGINAL;
52 		switch (bits & 0x60) {
53 		case 0x00: diga->status[1] |= IEC958_AES1_CON_MAGNETIC_ID; break;
54 		case 0x20: diga->status[1] |= IEC958_AES1_CON_DIGDIGCONV_ID; break;
55 		case 0x40: diga->status[1] |= IEC958_AES1_CON_LASEROPT_ID; break;
56 		case 0x60: diga->status[1] |= IEC958_AES1_CON_GENERAL; break;
57 		}
58 		switch (bits & 0x06) {
59 		case 0x00: diga->status[3] |= IEC958_AES3_CON_FS_44100; break;
60 		case 0x02: diga->status[3] |= IEC958_AES3_CON_FS_48000; break;
61 		case 0x04: diga->status[3] |= IEC958_AES3_CON_FS_32000; break;
62 		}
63 	} else {
64 		diga->status[0] = IEC958_AES0_PROFESSIONAL;
65 		switch (bits & 0x18) {
66 		case 0x00: diga->status[0] |= IEC958_AES0_PRO_FS_32000; break;
67 		case 0x10: diga->status[0] |= IEC958_AES0_PRO_FS_44100; break;
68 		case 0x08: diga->status[0] |= IEC958_AES0_PRO_FS_48000; break;
69 		case 0x18: diga->status[0] |= IEC958_AES0_PRO_FS_NOTID; break;
70 		}
71 		switch (bits & 0x60) {
72 		case 0x20: diga->status[0] |= IEC958_AES0_PRO_EMPHASIS_NONE; break;
73 		case 0x40: diga->status[0] |= IEC958_AES0_PRO_EMPHASIS_5015; break;
74 		case 0x00: diga->status[0] |= IEC958_AES0_PRO_EMPHASIS_CCITT; break;
75 		case 0x60: diga->status[0] |= IEC958_AES0_PRO_EMPHASIS_NOTID; break;
76 		}
77 		if (bits & 0x80)
78 			diga->status[1] |= IEC958_AES1_PRO_MODE_STEREOPHONIC;
79 	}
80 }
81 
82 SND_CS8403_DECL unsigned char SND_CS8403_ENCODE(struct snd_aes_iec958 *diga)
83 {
84 	unsigned char bits;
85 
86 	if (!(diga->status[0] & IEC958_AES0_PROFESSIONAL)) {
87 		bits = 0x01;	/* consumer mode */
88 		if (diga->status[0] & IEC958_AES0_NONAUDIO)
89 			bits &= ~0x02;
90 		else
91 			bits |= 0x02;
92 		if (diga->status[0] & IEC958_AES0_CON_NOT_COPYRIGHT)
93 			bits &= ~0x08;
94 		else
95 			bits |= 0x08;
96 		switch (diga->status[0] & IEC958_AES0_CON_EMPHASIS) {
97 		default:
98 		case IEC958_AES0_CON_EMPHASIS_NONE: bits |= 0x10; break;
99 		case IEC958_AES0_CON_EMPHASIS_5015: bits |= 0x00; break;
100 		}
101 		if (diga->status[1] & IEC958_AES1_CON_ORIGINAL)
102 			bits &= ~0x80;
103 		else
104 			bits |= 0x80;
105 		if ((diga->status[1] & IEC958_AES1_CON_CATEGORY) == IEC958_AES1_CON_GENERAL)
106 			bits |= 0x60;
107 		else {
108 			switch(diga->status[1] & IEC958_AES1_CON_MAGNETIC_MASK) {
109 			case IEC958_AES1_CON_MAGNETIC_ID:
110 				bits |= 0x00; break;
111 			case IEC958_AES1_CON_DIGDIGCONV_ID:
112 				bits |= 0x20; break;
113 			default:
114 			case IEC958_AES1_CON_LASEROPT_ID:
115 				bits |= 0x40; break;
116 			}
117 		}
118 		switch (diga->status[3] & IEC958_AES3_CON_FS) {
119 		default:
120 		case IEC958_AES3_CON_FS_44100: bits |= 0x00; break;
121 		case IEC958_AES3_CON_FS_48000: bits |= 0x02; break;
122 		case IEC958_AES3_CON_FS_32000: bits |= 0x04; break;
123 		}
124 	} else {
125 		bits = 0x00;	/* professional mode */
126 		if (diga->status[0] & IEC958_AES0_NONAUDIO)
127 			bits &= ~0x02;
128 		else
129 			bits |= 0x02;
130 		/* CHECKME: I'm not sure about the bit order in val here */
131 		switch (diga->status[0] & IEC958_AES0_PRO_FS) {
132 		case IEC958_AES0_PRO_FS_32000:	bits |= 0x00; break;
133 		case IEC958_AES0_PRO_FS_44100:	bits |= 0x10; break;	/* 44.1kHz */
134 		case IEC958_AES0_PRO_FS_48000:	bits |= 0x08; break;	/* 48kHz */
135 		default:
136 		case IEC958_AES0_PRO_FS_NOTID: bits |= 0x18; break;
137 		}
138 		switch (diga->status[0] & IEC958_AES0_PRO_EMPHASIS) {
139 		case IEC958_AES0_PRO_EMPHASIS_NONE: bits |= 0x20; break;
140 		case IEC958_AES0_PRO_EMPHASIS_5015: bits |= 0x40; break;
141 		case IEC958_AES0_PRO_EMPHASIS_CCITT: bits |= 0x00; break;
142 		default:
143 		case IEC958_AES0_PRO_EMPHASIS_NOTID: bits |= 0x60; break;
144 		}
145 		switch (diga->status[1] & IEC958_AES1_PRO_MODE) {
146 		case IEC958_AES1_PRO_MODE_TWO:
147 		case IEC958_AES1_PRO_MODE_STEREOPHONIC: bits |= 0x00; break;
148 		default: bits |= 0x80; break;
149 		}
150 	}
151 	return bits;
152 }
153 
154 #endif /* SND_CS8403 */
155 
156 #ifdef SND_CS8404
157 
158 #ifndef SND_CS8404_DECL
159 #define SND_CS8404_DECL static
160 #endif
161 #ifndef SND_CS8404_DECODE
162 #define SND_CS8404_DECODE snd_cs8404_decode_spdif_bits
163 #endif
164 #ifndef SND_CS8404_ENCODE
165 #define SND_CS8404_ENCODE snd_cs8404_encode_spdif_bits
166 #endif
167 
168 
169 SND_CS8404_DECL void SND_CS8404_DECODE(struct snd_aes_iec958 *diga, unsigned char bits)
170 {
171 	if (bits & 0x10) {	/* consumer */
172 		if (!(bits & 0x20))
173 			diga->status[0] |= IEC958_AES0_CON_NOT_COPYRIGHT;
174 		if (!(bits & 0x40))
175 			diga->status[0] |= IEC958_AES0_CON_EMPHASIS_5015;
176 		if (!(bits & 0x80))
177 			diga->status[1] |= IEC958_AES1_CON_ORIGINAL;
178 		switch (bits & 0x03) {
179 		case 0x00: diga->status[1] |= IEC958_AES1_CON_DAT; break;
180 		case 0x03: diga->status[1] |= IEC958_AES1_CON_GENERAL; break;
181 		}
182 		switch (bits & 0x06) {
183 		case 0x02: diga->status[3] |= IEC958_AES3_CON_FS_32000; break;
184 		case 0x04: diga->status[3] |= IEC958_AES3_CON_FS_48000; break;
185 		case 0x06: diga->status[3] |= IEC958_AES3_CON_FS_44100; break;
186 		}
187 	} else {
188 		diga->status[0] = IEC958_AES0_PROFESSIONAL;
189 		if (!(bits & 0x04))
190 			diga->status[0] |= IEC958_AES0_NONAUDIO;
191 		switch (bits & 0x60) {
192 		case 0x00: diga->status[0] |= IEC958_AES0_PRO_FS_32000; break;
193 		case 0x40: diga->status[0] |= IEC958_AES0_PRO_FS_44100; break;
194 		case 0x20: diga->status[0] |= IEC958_AES0_PRO_FS_48000; break;
195 		case 0x60: diga->status[0] |= IEC958_AES0_PRO_FS_NOTID; break;
196 		}
197 		switch (bits & 0x03) {
198 		case 0x02: diga->status[0] |= IEC958_AES0_PRO_EMPHASIS_NONE; break;
199 		case 0x01: diga->status[0] |= IEC958_AES0_PRO_EMPHASIS_5015; break;
200 		case 0x00: diga->status[0] |= IEC958_AES0_PRO_EMPHASIS_CCITT; break;
201 		case 0x03: diga->status[0] |= IEC958_AES0_PRO_EMPHASIS_NOTID; break;
202 		}
203 		if (!(bits & 0x80))
204 			diga->status[1] |= IEC958_AES1_PRO_MODE_STEREOPHONIC;
205 	}
206 }
207 
208 SND_CS8404_DECL unsigned char SND_CS8404_ENCODE(struct snd_aes_iec958 *diga)
209 {
210 	unsigned char bits;
211 
212 	if (!(diga->status[0] & IEC958_AES0_PROFESSIONAL)) {
213 		bits = 0x10;	/* consumer mode */
214 		if (!(diga->status[0] & IEC958_AES0_CON_NOT_COPYRIGHT))
215 			bits |= 0x20;
216 		if ((diga->status[0] & IEC958_AES0_CON_EMPHASIS) == IEC958_AES0_CON_EMPHASIS_NONE)
217 			bits |= 0x40;
218 		if (!(diga->status[1] & IEC958_AES1_CON_ORIGINAL))
219 			bits |= 0x80;
220 		if ((diga->status[1] & IEC958_AES1_CON_CATEGORY) == IEC958_AES1_CON_GENERAL)
221 			bits |= 0x03;
222 		switch (diga->status[3] & IEC958_AES3_CON_FS) {
223 		default:
224 		case IEC958_AES3_CON_FS_44100: bits |= 0x06; break;
225 		case IEC958_AES3_CON_FS_48000: bits |= 0x04; break;
226 		case IEC958_AES3_CON_FS_32000: bits |= 0x02; break;
227 		}
228 	} else {
229 		bits = 0x00;	/* professional mode */
230 		if (!(diga->status[0] & IEC958_AES0_NONAUDIO))
231 			bits |= 0x04;
232 		switch (diga->status[0] & IEC958_AES0_PRO_FS) {
233 		case IEC958_AES0_PRO_FS_32000:	bits |= 0x00; break;
234 		case IEC958_AES0_PRO_FS_44100:	bits |= 0x40; break;	/* 44.1kHz */
235 		case IEC958_AES0_PRO_FS_48000:	bits |= 0x20; break;	/* 48kHz */
236 		default:
237 		case IEC958_AES0_PRO_FS_NOTID:	bits |= 0x00; break;
238 		}
239 		switch (diga->status[0] & IEC958_AES0_PRO_EMPHASIS) {
240 		case IEC958_AES0_PRO_EMPHASIS_NONE: bits |= 0x02; break;
241 		case IEC958_AES0_PRO_EMPHASIS_5015: bits |= 0x01; break;
242 		case IEC958_AES0_PRO_EMPHASIS_CCITT: bits |= 0x00; break;
243 		default:
244 		case IEC958_AES0_PRO_EMPHASIS_NOTID: bits |= 0x03; break;
245 		}
246 		switch (diga->status[1] & IEC958_AES1_PRO_MODE) {
247 		case IEC958_AES1_PRO_MODE_TWO:
248 		case IEC958_AES1_PRO_MODE_STEREOPHONIC: bits |= 0x00; break;
249 		default: bits |= 0x80; break;
250 		}
251 	}
252 	return bits;
253 }
254 
255 #endif /* SND_CS8404 */
256 
257 #endif /* __SOUND_CS8403_H */
258