VServer 1.9.2 (patch-2.6.8.1-vs1.9.2.diff)
[linux-2.6.git] / drivers / media / video / cx88 / cx88-tvaudio.c
1 /*
2     cx88x-audio.c - Conexant CX23880/23881 audio downstream driver driver
3
4      (c) 2001 Michael Eskin, Tom Zakrajsek [Windows version]
5      (c) 2002 Yurij Sysoev <yurij@naturesoft.net>
6      (c) 2003 Gerd Knorr <kraxel@bytesex.org>
7
8     -----------------------------------------------------------------------
9
10     Lot of voodoo here.  Even the data sheet doesn't help to
11     understand what is going on here, the documentation for the audio
12     part of the cx2388x chip is *very* bad.
13
14     Some of this comes from party done linux driver sources I got from
15     [undocumented].
16
17     Some comes from the dscaler sources, one of the dscaler driver guy works
18     for Conexant ...
19     
20     -----------------------------------------------------------------------
21     
22     This program is free software; you can redistribute it and/or modify
23     it under the terms of the GNU General Public License as published by
24     the Free Software Foundation; either version 2 of the License, or
25     (at your option) any later version.
26
27     This program is distributed in the hope that it will be useful,
28     but WITHOUT ANY WARRANTY; without even the implied warranty of
29     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
30     GNU General Public License for more details.
31
32     You should have received a copy of the GNU General Public License
33     along with this program; if not, write to the Free Software
34     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
35 */
36
37 #include <linux/module.h>
38 #include <linux/errno.h>
39 #include <linux/kernel.h>
40 #include <linux/slab.h>
41 #include <linux/mm.h>
42 #include <linux/poll.h>
43 #include <linux/pci.h>
44 #include <linux/signal.h>
45 #include <linux/ioport.h>
46 #include <linux/sched.h>
47 #include <linux/types.h>
48 #include <linux/interrupt.h>
49 #include <linux/vmalloc.h>
50 #include <linux/init.h>
51 #include <linux/smp_lock.h>
52
53 #include "cx88.h"
54
55 static unsigned int audio_debug = 1;
56 MODULE_PARM(audio_debug,"i");
57 MODULE_PARM_DESC(audio_debug,"enable debug messages [audio]");
58
59 #define dprintk(fmt, arg...)    if (audio_debug) \
60         printk(KERN_DEBUG "%s: " fmt, dev->name , ## arg)
61
62 /* ----------------------------------------------------------- */
63
64 static char *aud_ctl_names[64] =
65 {
66         [ EN_BTSC_FORCE_MONO       ] = "BTSC_FORCE_MONO",
67         [ EN_BTSC_FORCE_STEREO     ] = "BTSC_FORCE_STEREO",
68         [ EN_BTSC_FORCE_SAP        ] = "BTSC_FORCE_SAP",
69         [ EN_BTSC_AUTO_STEREO      ] = "BTSC_AUTO_STEREO",
70         [ EN_BTSC_AUTO_SAP         ] = "BTSC_AUTO_SAP",
71         [ EN_A2_FORCE_MONO1        ] = "A2_FORCE_MONO1",
72         [ EN_A2_FORCE_MONO2        ] = "A2_FORCE_MONO2",
73         [ EN_A2_FORCE_STEREO       ] = "A2_FORCE_STEREO",
74         [ EN_A2_AUTO_MONO2         ] = "A2_AUTO_MONO2",
75         [ EN_A2_AUTO_STEREO        ] = "A2_AUTO_STEREO",
76         [ EN_EIAJ_FORCE_MONO1      ] = "EIAJ_FORCE_MONO1",
77         [ EN_EIAJ_FORCE_MONO2      ] = "EIAJ_FORCE_MONO2",
78         [ EN_EIAJ_FORCE_STEREO     ] = "EIAJ_FORCE_STEREO",
79         [ EN_EIAJ_AUTO_MONO2       ] = "EIAJ_AUTO_MONO2",
80         [ EN_EIAJ_AUTO_STEREO      ] = "EIAJ_AUTO_STEREO",
81         [ EN_NICAM_FORCE_MONO1     ] = "NICAM_FORCE_MONO1",
82         [ EN_NICAM_FORCE_MONO2     ] = "NICAM_FORCE_MONO2",
83         [ EN_NICAM_FORCE_STEREO    ] = "NICAM_FORCE_STEREO",
84         [ EN_NICAM_AUTO_MONO2      ] = "NICAM_AUTO_MONO2",
85         [ EN_NICAM_AUTO_STEREO     ] = "NICAM_AUTO_STEREO",
86         [ EN_FMRADIO_FORCE_MONO    ] = "FMRADIO_FORCE_MONO",
87         [ EN_FMRADIO_FORCE_STEREO  ] = "FMRADIO_FORCE_STEREO",
88         [ EN_FMRADIO_AUTO_STEREO   ] = "FMRADIO_AUTO_STEREO",
89 };
90
91 struct rlist {
92         u32 reg;
93         u32 val;
94 };
95
96 static void set_audio_registers(struct cx8800_dev *dev,
97                                 const struct rlist *l)
98 {
99         int i;
100
101         for (i = 0; l[i].reg; i++) {
102                 switch (l[i].reg) {
103                 case AUD_PDF_DDS_CNST_BYTE2:
104                 case AUD_PDF_DDS_CNST_BYTE1:
105                 case AUD_PDF_DDS_CNST_BYTE0:
106                 case AUD_QAM_MODE:
107                 case AUD_PHACC_FREQ_8MSB:
108                 case AUD_PHACC_FREQ_8LSB:
109                         cx_writeb(l[i].reg, l[i].val);
110                         break;
111                 default:
112                         cx_write(l[i].reg, l[i].val);
113                         break;
114                 }
115         }
116 }
117
118 static void set_audio_start(struct cx8800_dev *dev,
119                             u32 mode, u32 ctl)
120 {
121         // mute
122         cx_write(AUD_VOL_CTL,       (1 << 6));
123
124         //  increase level of input by 12dB
125         cx_write(AUD_AFE_12DB_EN,   0x0001);
126
127         // start programming
128         cx_write(AUD_CTL,           0x0000);
129         cx_write(AUD_INIT,          mode);
130         cx_write(AUD_INIT_LD,       0x0001);
131         cx_write(AUD_SOFT_RESET,    0x0001);
132
133         cx_write(AUD_CTL,           ctl);
134 }
135
136 static void set_audio_finish(struct cx8800_dev *dev)
137 {
138         u32 volume;
139
140         // finish programming
141         cx_write(AUD_SOFT_RESET, 0x0000);
142
143         // start audio processing
144         cx_set(AUD_CTL, EN_DAC_ENABLE);
145
146         // unmute
147         volume = cx_sread(SHADOW_AUD_VOL_CTL);
148         cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, volume);
149 }
150
151 /* ----------------------------------------------------------- */
152
153 static void set_audio_standard_BTSC(struct cx8800_dev *dev, unsigned int sap)
154 {
155         static const struct rlist btsc[] = {
156                 /* from dscaler */
157                 { AUD_OUT1_SEL,                0x00000013 },
158                 { AUD_OUT1_SHIFT,              0x00000000 },
159                 { AUD_POLY0_DDS_CONSTANT,      0x0012010c },
160                 { AUD_DMD_RA_DDS,              0x00c3e7aa },
161                 { AUD_DBX_IN_GAIN,             0x00004734 },
162                 { AUD_DBX_WBE_GAIN,            0x00004640 },
163                 { AUD_DBX_SE_GAIN,             0x00008d31 },
164                 { AUD_DCOC_0_SRC,              0x0000001a },
165                 { AUD_IIR1_4_SEL,              0x00000021 },
166                 { AUD_DCOC_PASS_IN,            0x00000003 },
167                 { AUD_DCOC_0_SHIFT_IN0,        0x0000000a },
168                 { AUD_DCOC_0_SHIFT_IN1,        0x00000008 },
169                 { AUD_DCOC_1_SHIFT_IN0,        0x0000000a },
170                 { AUD_DCOC_1_SHIFT_IN1,        0x00000008 },
171                 { AUD_DN0_FREQ,                0x0000283b },
172                 { AUD_DN2_SRC_SEL,             0x00000008 },
173                 { AUD_DN2_FREQ,                0x00003000 },
174                 { AUD_DN2_AFC,                 0x00000002 },
175                 { AUD_DN2_SHFT,                0x00000000 },
176                 { AUD_IIR2_2_SEL,              0x00000020 },
177                 { AUD_IIR2_2_SHIFT,            0x00000000 },
178                 { AUD_IIR2_3_SEL,              0x0000001f },
179                 { AUD_IIR2_3_SHIFT,            0x00000000 },
180                 { AUD_CRDC1_SRC_SEL,           0x000003ce },
181                 { AUD_CRDC1_SHIFT,             0x00000000 },
182                 { AUD_CORDIC_SHIFT_1,          0x00000007 },
183                 { AUD_DCOC_1_SRC,              0x0000001b },
184                 { AUD_DCOC1_SHIFT,             0x00000000 },
185                 { AUD_RDSI_SEL,                0x00000008 },
186                 { AUD_RDSQ_SEL,                0x00000008 },
187                 { AUD_RDSI_SHIFT,              0x00000000 },
188                 { AUD_RDSQ_SHIFT,              0x00000000 },
189                 { AUD_POLYPH80SCALEFAC,        0x00000003 },
190                 { /* end of list */ },
191         };
192         static const struct rlist btsc_sap[] = {
193                 { AUD_DBX_IN_GAIN,             0x00007200 },
194                 { AUD_DBX_WBE_GAIN,            0x00006200 },
195                 { AUD_DBX_SE_GAIN,             0x00006200 },
196                 { AUD_IIR1_1_SEL,              0x00000000 },
197                 { AUD_IIR1_3_SEL,              0x00000001 },
198                 { AUD_DN1_SRC_SEL,             0x00000007 },
199                 { AUD_IIR1_4_SHIFT,            0x00000006 },
200                 { AUD_IIR2_1_SHIFT,            0x00000000 },
201                 { AUD_IIR2_2_SHIFT,            0x00000000 },
202                 { AUD_IIR3_0_SHIFT,            0x00000000 },
203                 { AUD_IIR3_1_SHIFT,            0x00000000 },
204                 { AUD_IIR3_0_SEL,              0x0000000d },
205                 { AUD_IIR3_1_SEL,              0x0000000e },
206                 { AUD_DEEMPH1_SRC_SEL,         0x00000014 },
207                 { AUD_DEEMPH1_SHIFT,           0x00000000 },
208                 { AUD_DEEMPH1_G0,              0x00004000 },
209                 { AUD_DEEMPH1_A0,              0x00000000 },
210                 { AUD_DEEMPH1_B0,              0x00000000 },
211                 { AUD_DEEMPH1_A1,              0x00000000 },
212                 { AUD_DEEMPH1_B1,              0x00000000 },
213                 { AUD_OUT0_SEL,                0x0000003f },
214                 { AUD_OUT1_SEL,                0x0000003f },
215                 { AUD_DN1_AFC,                 0x00000002 },
216                 { AUD_DCOC_0_SHIFT_IN0,        0x0000000a },
217                 { AUD_DCOC_0_SHIFT_IN1,        0x00000008 },
218                 { AUD_DCOC_1_SHIFT_IN0,        0x0000000a },
219                 { AUD_DCOC_1_SHIFT_IN1,        0x00000008 },
220                 { AUD_IIR1_0_SEL,              0x0000001d },
221                 { AUD_IIR1_2_SEL,              0x0000001e },
222                 { AUD_IIR2_1_SEL,              0x00000002 },
223                 { AUD_IIR2_2_SEL,              0x00000004 },
224                 { AUD_IIR3_2_SEL,              0x0000000f },
225                 { AUD_DCOC2_SHIFT,             0x00000001 },
226                 { AUD_IIR3_2_SHIFT,            0x00000001 },
227                 { AUD_DEEMPH0_SRC_SEL,         0x00000014 },
228                 { AUD_CORDIC_SHIFT_1,          0x00000006 },
229                 { AUD_POLY0_DDS_CONSTANT,      0x000e4db2 },
230                 { AUD_DMD_RA_DDS,              0x00f696e6 },
231                 { AUD_IIR2_3_SEL,              0x00000025 },
232                 { AUD_IIR1_4_SEL,              0x00000021 },
233                 { AUD_DN1_FREQ,                0x0000c965 },
234                 { AUD_DCOC_PASS_IN,            0x00000003 },
235                 { AUD_DCOC_0_SRC,              0x0000001a },
236                 { AUD_DCOC_1_SRC,              0x0000001b },
237                 { AUD_DCOC1_SHIFT,             0x00000000 },
238                 { AUD_RDSI_SEL,                0x00000009 },
239                 { AUD_RDSQ_SEL,                0x00000009 },
240                 { AUD_RDSI_SHIFT,              0x00000000 },
241                 { AUD_RDSQ_SHIFT,              0x00000000 },
242                 { AUD_POLYPH80SCALEFAC,        0x00000003 },
243                 { /* end of list */ },
244         };
245
246         // dscaler: exactly taken from driver,
247         // dscaler: don't know why to set EN_FMRADIO_EN_RDS
248         if (sap) {
249                 dprintk("%s SAP (status: unknown)\n",__FUNCTION__);
250                 set_audio_start(dev, 0x0001,
251                                 EN_FMRADIO_EN_RDS | EN_BTSC_FORCE_SAP);
252                 set_audio_registers(dev, btsc_sap);
253         } else {
254                 dprintk("%s (status: known-good)\n",__FUNCTION__);
255                 set_audio_start(dev, 0x0001,
256                                 EN_FMRADIO_EN_RDS | EN_BTSC_AUTO_STEREO);
257                 set_audio_registers(dev, btsc);
258         }
259         set_audio_finish(dev);
260 }
261
262 static void set_audio_standard_NICAM(struct cx8800_dev *dev)
263 {
264         static const struct rlist nicam_common[] = {
265                 /* from dscaler */
266                 { AUD_RATE_ADJ1,           0x00000010 },
267                 { AUD_RATE_ADJ2,           0x00000040 },
268                 { AUD_RATE_ADJ3,           0x00000100 },
269                 { AUD_RATE_ADJ4,           0x00000400 },
270                 { AUD_RATE_ADJ5,           0x00001000 },
271     //          { AUD_DMD_RA_DDS,          0x00c0d5ce },
272
273                 // Deemphasis 1:
274                 { AUD_DEEMPHGAIN_R,        0x000023c2 },
275                 { AUD_DEEMPHNUMER1_R,      0x0002a7bc },
276                 { AUD_DEEMPHNUMER2_R,      0x0003023e },
277                 { AUD_DEEMPHDENOM1_R,      0x0000f3d0 },
278                 { AUD_DEEMPHDENOM2_R,      0x00000000 },
279
280 #if 0
281                 // Deemphasis 2: (other tv norm?)
282                 { AUD_DEEMPHGAIN_R,        0x0000c600 },
283                 { AUD_DEEMPHNUMER1_R,      0x00066738 },
284                 { AUD_DEEMPHNUMER2_R,      0x00066739 },
285                 { AUD_DEEMPHDENOM1_R,      0x0001e88c },
286                 { AUD_DEEMPHDENOM2_R,      0x0001e88c },
287 #endif
288
289                 { AUD_DEEMPHDENOM2_R,      0x00000000 },
290                 { AUD_ERRLOGPERIOD_R,      0x00000fff },
291                 { AUD_ERRINTRPTTHSHLD1_R,  0x000003ff },
292                 { AUD_ERRINTRPTTHSHLD2_R,  0x000000ff },
293                 { AUD_ERRINTRPTTHSHLD3_R,  0x0000003f },
294                 { AUD_POLYPH80SCALEFAC,    0x00000003 },
295
296                 // setup QAM registers
297                 { AUD_PDF_DDS_CNST_BYTE2,  0x06 },
298                 { AUD_PDF_DDS_CNST_BYTE1,  0x82 },
299                 { AUD_PDF_DDS_CNST_BYTE0,  0x16 },
300                 { AUD_QAM_MODE,            0x05 },
301
302                 { /* end of list */ },
303         };
304         static const struct rlist nicam_pal_i[] = {
305                 { AUD_PDF_DDS_CNST_BYTE0,  0x12 },
306                 { AUD_PHACC_FREQ_8MSB,     0x3a },
307                 { AUD_PHACC_FREQ_8LSB,     0x93 },
308
309                 { /* end of list */ },
310         };
311         static const struct rlist nicam_default[] = {
312                 { AUD_PDF_DDS_CNST_BYTE0,  0x16 },
313                 { AUD_PHACC_FREQ_8MSB,     0x34 },
314                 { AUD_PHACC_FREQ_8LSB,     0x4c },
315
316                 { /* end of list */ },
317         };
318
319         set_audio_start(dev, 0x0010,
320                         EN_DMTRX_LR | EN_DMTRX_BYPASS | EN_NICAM_AUTO_STEREO);
321         set_audio_registers(dev, nicam_common);
322         switch (dev->tvaudio) {
323         case WW_NICAM_I:
324                 dprintk("%s PAL-I NICAM (status: unknown)\n",__FUNCTION__);
325                 set_audio_registers(dev, nicam_pal_i);
326         case WW_NICAM_BGDKL:
327                 dprintk("%s PAL NICAM (status: unknown)\n",__FUNCTION__);
328                 set_audio_registers(dev, nicam_default);
329                 break;
330         };
331         set_audio_finish(dev);
332 }
333
334 static void set_audio_standard_NICAM_L(struct cx8800_dev *dev)
335 {
336         /* This is officially wierd.. register dumps indicate windows
337          * uses audio mode 4.. A2. Let's operate and find out. */
338
339         static const struct rlist nicam_l[] = {
340                 // setup QAM registers
341                 { AUD_PDF_DDS_CNST_BYTE2,          0x48 },
342                 { AUD_PDF_DDS_CNST_BYTE1,          0x3d },
343                 { AUD_PDF_DDS_CNST_BYTE0,          0xf5 },
344                 { AUD_QAM_MODE,                    0x00 },
345                 { AUD_PHACC_FREQ_8MSB,             0x3a },
346                 { AUD_PHACC_FREQ_8LSB,             0x4a },
347
348                 { AUD_POLY0_DDS_CONSTANT,          0x000e4db2 },
349                 { AUD_IIR1_0_SEL,                  0x00000000 },
350                 { AUD_IIR1_1_SEL,                  0x00000002 },
351                 { AUD_IIR1_2_SEL,                  0x00000023 },
352                 { AUD_IIR1_3_SEL,                  0x00000004 },
353                 { AUD_IIR1_4_SEL,                  0x00000005 },
354                 { AUD_IIR1_5_SEL,                  0x00000007 },
355                 { AUD_IIR1_0_SHIFT,                0x00000007 },
356                 { AUD_IIR1_1_SHIFT,                0x00000000 },
357                 { AUD_IIR1_2_SHIFT,                0x00000000 },
358                 { AUD_IIR1_3_SHIFT,                0x00000007 },
359                 { AUD_IIR1_4_SHIFT,                0x00000007 },
360                 { AUD_IIR1_5_SHIFT,                0x00000007 },
361                 { AUD_IIR2_0_SEL,                  0x00000002 },
362                 { AUD_IIR2_1_SEL,                  0x00000003 },
363                 { AUD_IIR2_2_SEL,                  0x00000004 },
364                 { AUD_IIR2_3_SEL,                  0x00000005 },
365                 { AUD_IIR3_0_SEL,                  0x00000007 },
366                 { AUD_IIR3_1_SEL,                  0x00000023 },
367                 { AUD_IIR3_2_SEL,                  0x00000016 },
368                 { AUD_IIR4_0_SHIFT,                0x00000000 },
369                 { AUD_IIR4_1_SHIFT,                0x00000000 },
370                 { AUD_IIR3_2_SHIFT,                0x00000002 },
371                 { AUD_IIR4_0_SEL,                  0x0000001d },
372                 { AUD_IIR4_1_SEL,                  0x00000019 },
373                 { AUD_IIR4_2_SEL,                  0x00000008 },
374                 { AUD_IIR4_0_SHIFT,                0x00000000 },
375                 { AUD_IIR4_1_SHIFT,                0x00000007 },
376                 { AUD_IIR4_2_SHIFT,                0x00000007 },
377                 { AUD_IIR4_0_CA0,                  0x0003e57e },
378                 { AUD_IIR4_0_CA1,                  0x00005e11 },
379                 { AUD_IIR4_0_CA2,                  0x0003a7cf },
380                 { AUD_IIR4_0_CB0,                  0x00002368 },
381                 { AUD_IIR4_0_CB1,                  0x0003bf1b },
382                 { AUD_IIR4_1_CA0,                  0x00006349 },
383                 { AUD_IIR4_1_CA1,                  0x00006f27 },
384                 { AUD_IIR4_1_CA2,                  0x0000e7a3 },
385                 { AUD_IIR4_1_CB0,                  0x00005653 },
386                 { AUD_IIR4_1_CB1,                  0x0000cf97 },
387                 { AUD_IIR4_2_CA0,                  0x00006349 },
388                 { AUD_IIR4_2_CA1,                  0x00006f27 },
389                 { AUD_IIR4_2_CA2,                  0x0000e7a3 },
390                 { AUD_IIR4_2_CB0,                  0x00005653 },
391                 { AUD_IIR4_2_CB1,                  0x0000cf97 },
392                 { AUD_HP_MD_IIR4_1,                0x00000001 },
393                 { AUD_HP_PROG_IIR4_1,              0x0000001a },
394                 { AUD_DN0_FREQ,                    0x00000000 },
395                 { AUD_DN1_FREQ,                    0x00003318 },
396                 { AUD_DN1_SRC_SEL,                 0x00000017 },
397                 { AUD_DN1_SHFT,                    0x00000007 },
398                 { AUD_DN1_AFC,                     0x00000000 },
399                 { AUD_DN1_FREQ_SHIFT,              0x00000000 },
400                 { AUD_DN2_FREQ,                    0x00003551 },
401                 { AUD_DN2_SRC_SEL,                 0x00000001 },
402                 { AUD_DN2_SHFT,                    0x00000000 },
403                 { AUD_DN2_AFC,                     0x00000002 },
404                 { AUD_DN2_FREQ_SHIFT,              0x00000000 },
405                 { AUD_PDET_SRC,                    0x00000014 },
406                 { AUD_PDET_SHIFT,                  0x00000000 },
407                 { AUD_DEEMPH0_SRC_SEL,             0x00000011 },
408                 { AUD_DEEMPH1_SRC_SEL,             0x00000011 },
409                 { AUD_DEEMPH0_SHIFT,               0x00000000 },
410                 { AUD_DEEMPH1_SHIFT,               0x00000000 },
411                 { AUD_DEEMPH0_G0,                  0x00007000 },
412                 { AUD_DEEMPH0_A0,                  0x00000000 },
413                 { AUD_DEEMPH0_B0,                  0x00000000 },
414                 { AUD_DEEMPH0_A1,                  0x00000000 },
415                 { AUD_DEEMPH0_B1,                  0x00000000 },
416                 { AUD_DEEMPH1_G0,                  0x00007000 },
417                 { AUD_DEEMPH1_A0,                  0x00000000 },
418                 { AUD_DEEMPH1_B0,                  0x00000000 },
419                 { AUD_DEEMPH1_A1,                  0x00000000 },
420                 { AUD_DEEMPH1_B1,                  0x00000000 },
421                 { AUD_DMD_RA_DDS,                  0x00f5c285 },
422                 { AUD_RATE_ADJ1,                   0x00000100 },
423                 { AUD_RATE_ADJ2,                   0x00000200 },
424                 { AUD_RATE_ADJ3,                   0x00000300 },
425                 { AUD_RATE_ADJ4,                   0x00000400 },
426                 { AUD_RATE_ADJ5,                   0x00000500 },
427                 { AUD_C2_UP_THR,                   0x00005400 },
428                 { AUD_C2_LO_THR,                   0x00003000 },
429                 { AUD_C1_UP_THR,                   0x00007000 },
430                 { AUD_C2_LO_THR,                   0x00005400 },
431                 { AUD_CTL,                         0x0000100c },
432                 { AUD_DCOC_0_SRC,                  0x00000021 },
433                 { AUD_DCOC_1_SRC,                  0x00000003 },
434                 { AUD_DCOC1_SHIFT,                 0x00000000 },
435                 { AUD_DCOC_1_SHIFT_IN0,            0x0000000a },
436                 { AUD_DCOC_1_SHIFT_IN1,            0x00000008 },
437                 { AUD_DCOC_PASS_IN,                0x00000000 },
438                 { AUD_DCOC_2_SRC,                  0x0000001b },
439                 { AUD_IIR4_0_SEL,                  0x0000001d },
440                 { AUD_POLY0_DDS_CONSTANT,          0x000e4db2 },
441                 { AUD_PHASE_FIX_CTL,               0x00000000 },
442                 { AUD_CORDIC_SHIFT_1,              0x00000007 },
443                 { AUD_PLL_EN,                      0x00000000 },
444                 { AUD_PLL_PRESCALE,                0x00000002 },
445                 { AUD_PLL_INT,                     0x0000001e },
446                 { AUD_OUT1_SHIFT,                  0x00000000 },
447
448                 { /* end of list */ },
449         };
450
451         dprintk("%s (status: unknown)\n",__FUNCTION__);
452         set_audio_start(dev, 0x0004,
453                         0 /* FIXME */);
454         set_audio_registers(dev, nicam_l);
455         set_audio_finish(dev);
456 }
457
458 static void set_audio_standard_A2(struct cx8800_dev *dev)
459 {
460         /* from dscaler cvs */
461         static const struct rlist a2_common[] = {
462                 { AUD_PDF_DDS_CNST_BYTE2,     0x06 },
463                 { AUD_PDF_DDS_CNST_BYTE1,     0x82 },
464                 { AUD_PDF_DDS_CNST_BYTE0,     0x12 },
465                 { AUD_QAM_MODE,               0x05 },
466                 { AUD_PHACC_FREQ_8MSB,        0x34 },
467                 { AUD_PHACC_FREQ_8LSB,        0x4c },
468
469                 { AUD_RATE_ADJ1,        0x00001000 },
470                 { AUD_RATE_ADJ2,        0x00002000 },
471                 { AUD_RATE_ADJ3,        0x00003000 },
472                 { AUD_RATE_ADJ4,        0x00004000 },
473                 { AUD_RATE_ADJ5,        0x00005000 },
474                 { AUD_THR_FR,           0x00000000 },
475                 { AAGC_HYST,            0x0000001a },
476                 { AUD_PILOT_BQD_1_K0,   0x0000755b },
477                 { AUD_PILOT_BQD_1_K1,   0x00551340 },
478                 { AUD_PILOT_BQD_1_K2,   0x006d30be },
479                 { AUD_PILOT_BQD_1_K3,   0xffd394af },
480                 { AUD_PILOT_BQD_1_K4,   0x00400000 },
481                 { AUD_PILOT_BQD_2_K0,   0x00040000 },
482                 { AUD_PILOT_BQD_2_K1,   0x002a4841 },
483                 { AUD_PILOT_BQD_2_K2,   0x00400000 },
484                 { AUD_PILOT_BQD_2_K3,   0x00000000 },
485                 { AUD_PILOT_BQD_2_K4,   0x00000000 },
486                 { AUD_MODE_CHG_TIMER,   0x00000040 },
487                 { AUD_START_TIMER,      0x00000200 },
488                 { AUD_AFE_12DB_EN,      0x00000000 },
489                 { AUD_CORDIC_SHIFT_0,   0x00000007 },
490                 { AUD_CORDIC_SHIFT_1,   0x00000007 },
491                 { AUD_DEEMPH0_G0,       0x00000380 },
492                 { AUD_DEEMPH1_G0,       0x00000380 },
493                 { AUD_DCOC_0_SRC,       0x0000001a },
494                 { AUD_DCOC0_SHIFT,      0x00000000 },
495                 { AUD_DCOC_0_SHIFT_IN0, 0x0000000a },
496                 { AUD_DCOC_0_SHIFT_IN1, 0x00000008 },
497                 { AUD_DCOC_PASS_IN,     0x00000003 },
498                 { AUD_IIR3_0_SEL,       0x00000021 },
499                 { AUD_DN2_AFC,          0x00000002 },
500                 { AUD_DCOC_1_SRC,       0x0000001b },
501                 { AUD_DCOC1_SHIFT,      0x00000000 },
502                 { AUD_DCOC_1_SHIFT_IN0, 0x0000000a },
503                 { AUD_DCOC_1_SHIFT_IN1, 0x00000008 },
504                 { AUD_IIR3_1_SEL,       0x00000023 },
505                 { AUD_RDSI_SEL,         0x00000017 },
506                 { AUD_RDSI_SHIFT,       0x00000000 },
507                 { AUD_RDSQ_SEL,         0x00000017 },
508                 { AUD_RDSQ_SHIFT,       0x00000000 },
509                 { AUD_POLYPH80SCALEFAC, 0x00000001 },
510
511                 { /* end of list */ },
512         };
513
514         static const struct rlist a2_table1[] = {
515                 // PAL-BG
516                 { AUD_DMD_RA_DDS,       0x002a73bd },
517                 { AUD_C1_UP_THR,        0x00007000 },
518                 { AUD_C1_LO_THR,        0x00005400 },
519                 { AUD_C2_UP_THR,        0x00005400 },
520                 { AUD_C2_LO_THR,        0x00003000 },
521                 { /* end of list */ },
522         };
523         static const struct rlist a2_table2[] = {
524                 // PAL-DK
525                 { AUD_DMD_RA_DDS,       0x002a73bd },
526                 { AUD_C1_UP_THR,        0x00007000 },
527                 { AUD_C1_LO_THR,        0x00005400 },
528                 { AUD_C2_UP_THR,        0x00005400 },
529                 { AUD_C2_LO_THR,        0x00003000 },
530                 { AUD_DN0_FREQ,         0x00003a1c },
531                 { AUD_DN2_FREQ,         0x0000d2e0 },
532                 { /* end of list */ },
533         };
534         static const struct rlist a2_table3[] = {
535                 // unknown, probably NTSC-M
536                 { AUD_DMD_RA_DDS,       0x002a2873 },
537                 { AUD_C1_UP_THR,        0x00003c00 },
538                 { AUD_C1_LO_THR,        0x00003000 },
539                 { AUD_C2_UP_THR,        0x00006000 },
540                 { AUD_C2_LO_THR,        0x00003c00 },
541                 { AUD_DN0_FREQ,         0x00002836 },
542                 { AUD_DN1_FREQ,         0x00003418 },
543                 { AUD_DN2_FREQ,         0x000029c7 },
544                 { AUD_POLY0_DDS_CONSTANT, 0x000a7540 },
545                 { /* end of list */ },
546         };
547
548         set_audio_start(dev, 0x0004, EN_DMTRX_SUMDIFF | EN_A2_AUTO_STEREO);
549         set_audio_registers(dev, a2_common);
550         switch (dev->tvaudio) {
551         case WW_A2_BG:
552                 dprintk("%s PAL-BG A2 (status: known-good)\n",__FUNCTION__);
553                 set_audio_registers(dev, a2_table1);
554                 break;
555         case WW_A2_DK:
556                 dprintk("%s PAL-DK A2 (status: known-good)\n",__FUNCTION__);
557                 set_audio_registers(dev, a2_table2);
558                 break;
559         case WW_A2_M:
560                 dprintk("%s NTSC-M A2 (status: unknown)\n",__FUNCTION__);
561                 set_audio_registers(dev, a2_table3);
562                 break;
563         };
564         set_audio_finish(dev);
565 }
566
567 static void set_audio_standard_EIAJ(struct cx8800_dev *dev)
568 {
569         static const struct rlist eiaj[] = {
570                 /* TODO: eiaj register settings are not there yet ... */
571
572                 { /* end of list */ },
573         };
574         dprintk("%s (status: unknown)\n",__FUNCTION__);
575
576         set_audio_start(dev, 0x0002, EN_EIAJ_AUTO_STEREO);
577         set_audio_registers(dev, eiaj);
578         set_audio_finish(dev);
579 }
580
581 static void set_audio_standard_FM(struct cx8800_dev *dev)
582 {
583 #if 0 /* FIXME */
584         switch (dev->audio_properties.FM_deemphasis)
585         {
586                 case WW_FM_DEEMPH_50:
587                         //Set De-emphasis filter coefficients for 50 usec
588                         cx_write(AUD_DEEMPH0_G0, 0x0C45);
589                         cx_write(AUD_DEEMPH0_A0, 0x6262);
590                         cx_write(AUD_DEEMPH0_B0, 0x1C29);
591                         cx_write(AUD_DEEMPH0_A1, 0x3FC66);
592                         cx_write(AUD_DEEMPH0_B1, 0x399A);
593
594                         cx_write(AUD_DEEMPH1_G0, 0x0D80);
595                         cx_write(AUD_DEEMPH1_A0, 0x6262);
596                         cx_write(AUD_DEEMPH1_B0, 0x1C29);
597                         cx_write(AUD_DEEMPH1_A1, 0x3FC66);
598                         cx_write(AUD_DEEMPH1_B1, 0x399A);
599                         
600                         break;
601
602                 case WW_FM_DEEMPH_75:
603                         //Set De-emphasis filter coefficients for 75 usec
604                         cx_write(AUD_DEEMPH0_G0, 0x91B );
605                         cx_write(AUD_DEEMPH0_A0, 0x6B68);
606                         cx_write(AUD_DEEMPH0_B0, 0x11EC);
607                         cx_write(AUD_DEEMPH0_A1, 0x3FC66);
608                         cx_write(AUD_DEEMPH0_B1, 0x399A);
609
610                         cx_write(AUD_DEEMPH1_G0, 0xAA0 );
611                         cx_write(AUD_DEEMPH1_A0, 0x6B68);
612                         cx_write(AUD_DEEMPH1_B0, 0x11EC);
613                         cx_write(AUD_DEEMPH1_A1, 0x3FC66);
614                         cx_write(AUD_DEEMPH1_B1, 0x399A);
615
616                         break;
617         }
618 #endif
619
620         dprintk("%s (status: unknown)\n",__FUNCTION__);
621         set_audio_start(dev, 0x0020, EN_FMRADIO_AUTO_STEREO);
622
623         // AB: 10/2/01: this register is not being reset appropriately on occasion.
624         cx_write(AUD_POLYPH80SCALEFAC,3);
625
626         set_audio_finish(dev);
627 }
628
629 /* ----------------------------------------------------------- */
630
631 void cx88_set_tvaudio(struct cx8800_dev *dev)
632 {
633         switch (dev->tvaudio) {
634         case WW_BTSC:
635                 set_audio_standard_BTSC(dev,0);
636                 break;
637         case WW_NICAM_I:
638         case WW_NICAM_BGDKL:
639                 set_audio_standard_NICAM(dev);
640                 break;
641         case WW_A2_BG:
642         case WW_A2_DK:
643         case WW_A2_M:
644                 set_audio_standard_A2(dev);
645                 break;
646         case WW_EIAJ:
647                 set_audio_standard_EIAJ(dev);
648                 break;
649         case WW_FM:
650                 set_audio_standard_FM(dev);
651                 break;
652         case WW_SYSTEM_L_AM:
653                 set_audio_standard_NICAM_L(dev);
654                 break;
655         case WW_NONE:
656         default:
657                 printk("%s: unknown tv audio mode [%d]\n",
658                        dev->name, dev->tvaudio);
659                 break;
660         }
661         return;
662 }
663
664 void cx88_get_stereo(struct cx8800_dev *dev, struct v4l2_tuner *t)
665 {
666         static char *m[] = {"stereo", "dual mono", "mono", "sap"};
667         static char *p[] = {"no pilot", "pilot c1", "pilot c2", "?"};
668         u32 reg,mode,pilot;
669
670         reg   = cx_read(AUD_STATUS);
671         mode  = reg & 0x03;
672         pilot = (reg >> 2) & 0x03;
673         dprintk("AUD_STATUS: 0x%x [%s/%s] ctl=%s\n",
674                 reg, m[mode], p[pilot],
675                 aud_ctl_names[cx_read(AUD_CTL) & 63]);
676
677         t->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_SAP |
678                 V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
679         t->rxsubchans = V4L2_TUNER_SUB_MONO;
680         t->audmode    = V4L2_TUNER_MODE_MONO;
681
682         switch (dev->tvaudio) {
683         case WW_A2_BG:
684         case WW_A2_DK:
685         case WW_A2_M:
686                 if (1 == pilot) {
687                         /* stereo */
688                         t->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
689                         if (0 == mode)
690                                 t->audmode = V4L2_TUNER_MODE_STEREO;
691                 }
692                 if (2 == pilot) {
693                         /* dual language -- FIXME */
694                         t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
695                         t->audmode = V4L2_TUNER_MODE_LANG1;
696                 }
697                 break;
698         case WW_NICAM_BGDKL:
699                 if (0 == mode)
700                         t->audmode = V4L2_TUNER_MODE_STEREO;
701                 break;
702         default:
703                 t->rxsubchans = V4L2_TUNER_SUB_MONO;
704                 t->audmode    = V4L2_TUNER_MODE_MONO;
705                 break;
706         }
707         return;
708 }
709
710 void cx88_set_stereo(struct cx8800_dev *dev, u32 mode)
711 {
712         u32 ctl  = UNSET;
713         u32 mask = UNSET;
714
715         switch (dev->tvaudio) {
716         case WW_A2_BG:
717         case WW_A2_DK:
718         case WW_A2_M:
719                 switch (mode) {
720                 case V4L2_TUNER_MODE_MONO:   
721                 case V4L2_TUNER_MODE_LANG1:
722                         ctl  = EN_A2_FORCE_MONO1;
723                         mask = 0x3f;
724                         break;
725                 case V4L2_TUNER_MODE_LANG2:
726                         ctl  = EN_A2_AUTO_MONO2;
727                         mask = 0x3f;
728                         break;
729                 case V4L2_TUNER_MODE_STEREO:
730                         ctl  = EN_A2_AUTO_STEREO | EN_DMTRX_SUMR;
731                         mask = 0x8bf;
732                         break;
733                 }
734                 break;
735         case WW_NICAM_BGDKL:
736                 switch (mode) {
737                 case V4L2_TUNER_MODE_MONO:   
738                         ctl  = EN_NICAM_FORCE_MONO1;
739                         mask = 0x3f;
740                         break;
741                 case V4L2_TUNER_MODE_LANG1:
742                         ctl  = EN_NICAM_AUTO_MONO2;
743                         mask = 0x3f;
744                         break;
745                 case V4L2_TUNER_MODE_STEREO:
746                         ctl  = EN_NICAM_FORCE_STEREO | EN_DMTRX_LR;
747                         mask = 0x93f;
748                         break;
749                 }
750                 break;  
751         case WW_FM:
752                 switch (mode) {
753                 case V4L2_TUNER_MODE_MONO:   
754                         ctl  = EN_FMRADIO_FORCE_MONO;
755                         mask = 0x3f;
756                         break;
757                 case V4L2_TUNER_MODE_STEREO:
758                         ctl  = EN_FMRADIO_AUTO_STEREO;
759                         mask = 0x3f;
760                         break;
761                 }
762                 break;  
763         }
764
765         if (UNSET != ctl) {
766                 cx_write(AUD_SOFT_RESET, 0x0001);
767                 cx_andor(AUD_CTL, mask,  ctl);
768                 cx_write(AUD_SOFT_RESET, 0x0000);
769                 dprintk("cx88_set_stereo: mask 0x%x, ctl 0x%x "
770                         "[status=0x%x,ctl=0x%x,vol=0x%x]\n",
771                         mask, ctl, cx_read(AUD_STATUS),
772                         cx_read(AUD_CTL), cx_sread(SHADOW_AUD_VOL_CTL));
773         }
774         return;
775 }
776
777 /* just monitor the audio status for now ... */
778 int cx88_audio_thread(void *data)
779 {
780         struct cx8800_dev *dev = data;
781         struct v4l2_tuner t;
782
783         daemonize("msp3400");
784         allow_signal(SIGTERM);
785         dprintk("cx88: tvaudio thread started\n");
786
787         for (;;) {
788                 set_current_state(TASK_INTERRUPTIBLE);
789                 schedule_timeout(HZ*3);
790                 if (signal_pending(current))
791                         break;
792                 if (dev->shutdown)
793                         break;
794
795                 memset(&t,0,sizeof(t));
796                 cx88_get_stereo(dev,&t);
797         }
798
799         dprintk("cx88: tvaudio thread exiting\n");
800         complete_and_exit(&dev->texit, 0);
801 }
802
803 /*
804  * Local variables:
805  * c-basic-offset: 8
806  * End:
807  */