• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/media/video/cx88/
1/*
2
3    cx88x-audio.c - Conexant CX23880/23881 audio downstream driver driver
4
5     (c) 2001 Michael Eskin, Tom Zakrajsek [Windows version]
6     (c) 2002 Yurij Sysoev <yurij@naturesoft.net>
7     (c) 2003 Gerd Knorr <kraxel@bytesex.org>
8
9    -----------------------------------------------------------------------
10
11    Lot of voodoo here.  Even the data sheet doesn't help to
12    understand what is going on here, the documentation for the audio
13    part of the cx2388x chip is *very* bad.
14
15    Some of this comes from party done linux driver sources I got from
16    [undocumented].
17
18    Some comes from the dscaler sources, one of the dscaler driver guy works
19    for Conexant ...
20
21    -----------------------------------------------------------------------
22
23    This program is free software; you can redistribute it and/or modify
24    it under the terms of the GNU General Public License as published by
25    the Free Software Foundation; either version 2 of the License, or
26    (at your option) any later version.
27
28    This program is distributed in the hope that it will be useful,
29    but WITHOUT ANY WARRANTY; without even the implied warranty of
30    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
31    GNU General Public License for more details.
32
33    You should have received a copy of the GNU General Public License
34    along with this program; if not, write to the Free Software
35    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
36*/
37
38#include <linux/module.h>
39#include <linux/errno.h>
40#include <linux/freezer.h>
41#include <linux/kernel.h>
42#include <linux/mm.h>
43#include <linux/poll.h>
44#include <linux/signal.h>
45#include <linux/ioport.h>
46#include <linux/types.h>
47#include <linux/interrupt.h>
48#include <linux/vmalloc.h>
49#include <linux/init.h>
50#include <linux/delay.h>
51#include <linux/kthread.h>
52
53#include "cx88.h"
54
55static unsigned int audio_debug;
56module_param(audio_debug, int, 0644);
57MODULE_PARM_DESC(audio_debug, "enable debug messages [audio]");
58
59static unsigned int always_analog;
60module_param(always_analog,int,0644);
61MODULE_PARM_DESC(always_analog,"force analog audio out");
62
63static unsigned int radio_deemphasis;
64module_param(radio_deemphasis,int,0644);
65MODULE_PARM_DESC(radio_deemphasis, "Radio deemphasis time constant, "
66		 "0=None, 1=50us (elsewhere), 2=75us (USA)");
67
68#define dprintk(fmt, arg...)	if (audio_debug) \
69	printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg)
70
71/* ----------------------------------------------------------- */
72
73static char *aud_ctl_names[64] = {
74	[EN_BTSC_FORCE_MONO] = "BTSC_FORCE_MONO",
75	[EN_BTSC_FORCE_STEREO] = "BTSC_FORCE_STEREO",
76	[EN_BTSC_FORCE_SAP] = "BTSC_FORCE_SAP",
77	[EN_BTSC_AUTO_STEREO] = "BTSC_AUTO_STEREO",
78	[EN_BTSC_AUTO_SAP] = "BTSC_AUTO_SAP",
79	[EN_A2_FORCE_MONO1] = "A2_FORCE_MONO1",
80	[EN_A2_FORCE_MONO2] = "A2_FORCE_MONO2",
81	[EN_A2_FORCE_STEREO] = "A2_FORCE_STEREO",
82	[EN_A2_AUTO_MONO2] = "A2_AUTO_MONO2",
83	[EN_A2_AUTO_STEREO] = "A2_AUTO_STEREO",
84	[EN_EIAJ_FORCE_MONO1] = "EIAJ_FORCE_MONO1",
85	[EN_EIAJ_FORCE_MONO2] = "EIAJ_FORCE_MONO2",
86	[EN_EIAJ_FORCE_STEREO] = "EIAJ_FORCE_STEREO",
87	[EN_EIAJ_AUTO_MONO2] = "EIAJ_AUTO_MONO2",
88	[EN_EIAJ_AUTO_STEREO] = "EIAJ_AUTO_STEREO",
89	[EN_NICAM_FORCE_MONO1] = "NICAM_FORCE_MONO1",
90	[EN_NICAM_FORCE_MONO2] = "NICAM_FORCE_MONO2",
91	[EN_NICAM_FORCE_STEREO] = "NICAM_FORCE_STEREO",
92	[EN_NICAM_AUTO_MONO2] = "NICAM_AUTO_MONO2",
93	[EN_NICAM_AUTO_STEREO] = "NICAM_AUTO_STEREO",
94	[EN_FMRADIO_FORCE_MONO] = "FMRADIO_FORCE_MONO",
95	[EN_FMRADIO_FORCE_STEREO] = "FMRADIO_FORCE_STEREO",
96	[EN_FMRADIO_AUTO_STEREO] = "FMRADIO_AUTO_STEREO",
97};
98
99struct rlist {
100	u32 reg;
101	u32 val;
102};
103
104static void set_audio_registers(struct cx88_core *core, const struct rlist *l)
105{
106	int i;
107
108	for (i = 0; l[i].reg; i++) {
109		switch (l[i].reg) {
110		case AUD_PDF_DDS_CNST_BYTE2:
111		case AUD_PDF_DDS_CNST_BYTE1:
112		case AUD_PDF_DDS_CNST_BYTE0:
113		case AUD_QAM_MODE:
114		case AUD_PHACC_FREQ_8MSB:
115		case AUD_PHACC_FREQ_8LSB:
116			cx_writeb(l[i].reg, l[i].val);
117			break;
118		default:
119			cx_write(l[i].reg, l[i].val);
120			break;
121		}
122	}
123}
124
125static void set_audio_start(struct cx88_core *core, u32 mode)
126{
127	/* mute */
128	cx_write(AUD_VOL_CTL, (1 << 6));
129
130	/* start programming */
131	cx_write(AUD_INIT, mode);
132	cx_write(AUD_INIT_LD, 0x0001);
133	cx_write(AUD_SOFT_RESET, 0x0001);
134}
135
136static void set_audio_finish(struct cx88_core *core, u32 ctl)
137{
138	u32 volume;
139
140	/* restart dma; This avoids buzz in NICAM and is good in others  */
141	cx88_stop_audio_dma(core);
142	cx_write(AUD_RATE_THRES_DMD, 0x000000C0);
143	cx88_start_audio_dma(core);
144
145	if (core->board.mpeg & CX88_MPEG_BLACKBIRD) {
146		cx_write(AUD_I2SINPUTCNTL, 4);
147		cx_write(AUD_BAUDRATE, 1);
148		/* 'pass-thru mode': this enables the i2s output to the mpeg encoder */
149		cx_set(AUD_CTL, EN_I2SOUT_ENABLE);
150		cx_write(AUD_I2SOUTPUTCNTL, 1);
151		cx_write(AUD_I2SCNTL, 0);
152		/* cx_write(AUD_APB_IN_RATE_ADJ, 0); */
153	}
154	if ((always_analog) || (!(core->board.mpeg & CX88_MPEG_BLACKBIRD))) {
155		ctl |= EN_DAC_ENABLE;
156		cx_write(AUD_CTL, ctl);
157	}
158
159	/* finish programming */
160	cx_write(AUD_SOFT_RESET, 0x0000);
161
162	/* unmute */
163	volume = cx_sread(SHADOW_AUD_VOL_CTL);
164	cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, volume);
165
166	core->last_change = jiffies;
167}
168
169/* ----------------------------------------------------------- */
170
171static void set_audio_standard_BTSC(struct cx88_core *core, unsigned int sap,
172				    u32 mode)
173{
174	static const struct rlist btsc[] = {
175		{AUD_AFE_12DB_EN, 0x00000001},
176		{AUD_OUT1_SEL, 0x00000013},
177		{AUD_OUT1_SHIFT, 0x00000000},
178		{AUD_POLY0_DDS_CONSTANT, 0x0012010c},
179		{AUD_DMD_RA_DDS, 0x00c3e7aa},
180		{AUD_DBX_IN_GAIN, 0x00004734},
181		{AUD_DBX_WBE_GAIN, 0x00004640},
182		{AUD_DBX_SE_GAIN, 0x00008d31},
183		{AUD_DCOC_0_SRC, 0x0000001a},
184		{AUD_IIR1_4_SEL, 0x00000021},
185		{AUD_DCOC_PASS_IN, 0x00000003},
186		{AUD_DCOC_0_SHIFT_IN0, 0x0000000a},
187		{AUD_DCOC_0_SHIFT_IN1, 0x00000008},
188		{AUD_DCOC_1_SHIFT_IN0, 0x0000000a},
189		{AUD_DCOC_1_SHIFT_IN1, 0x00000008},
190		{AUD_DN0_FREQ, 0x0000283b},
191		{AUD_DN2_SRC_SEL, 0x00000008},
192		{AUD_DN2_FREQ, 0x00003000},
193		{AUD_DN2_AFC, 0x00000002},
194		{AUD_DN2_SHFT, 0x00000000},
195		{AUD_IIR2_2_SEL, 0x00000020},
196		{AUD_IIR2_2_SHIFT, 0x00000000},
197		{AUD_IIR2_3_SEL, 0x0000001f},
198		{AUD_IIR2_3_SHIFT, 0x00000000},
199		{AUD_CRDC1_SRC_SEL, 0x000003ce},
200		{AUD_CRDC1_SHIFT, 0x00000000},
201		{AUD_CORDIC_SHIFT_1, 0x00000007},
202		{AUD_DCOC_1_SRC, 0x0000001b},
203		{AUD_DCOC1_SHIFT, 0x00000000},
204		{AUD_RDSI_SEL, 0x00000008},
205		{AUD_RDSQ_SEL, 0x00000008},
206		{AUD_RDSI_SHIFT, 0x00000000},
207		{AUD_RDSQ_SHIFT, 0x00000000},
208		{AUD_POLYPH80SCALEFAC, 0x00000003},
209		{ /* end of list */ },
210	};
211	static const struct rlist btsc_sap[] = {
212		{AUD_AFE_12DB_EN, 0x00000001},
213		{AUD_DBX_IN_GAIN, 0x00007200},
214		{AUD_DBX_WBE_GAIN, 0x00006200},
215		{AUD_DBX_SE_GAIN, 0x00006200},
216		{AUD_IIR1_1_SEL, 0x00000000},
217		{AUD_IIR1_3_SEL, 0x00000001},
218		{AUD_DN1_SRC_SEL, 0x00000007},
219		{AUD_IIR1_4_SHIFT, 0x00000006},
220		{AUD_IIR2_1_SHIFT, 0x00000000},
221		{AUD_IIR2_2_SHIFT, 0x00000000},
222		{AUD_IIR3_0_SHIFT, 0x00000000},
223		{AUD_IIR3_1_SHIFT, 0x00000000},
224		{AUD_IIR3_0_SEL, 0x0000000d},
225		{AUD_IIR3_1_SEL, 0x0000000e},
226		{AUD_DEEMPH1_SRC_SEL, 0x00000014},
227		{AUD_DEEMPH1_SHIFT, 0x00000000},
228		{AUD_DEEMPH1_G0, 0x00004000},
229		{AUD_DEEMPH1_A0, 0x00000000},
230		{AUD_DEEMPH1_B0, 0x00000000},
231		{AUD_DEEMPH1_A1, 0x00000000},
232		{AUD_DEEMPH1_B1, 0x00000000},
233		{AUD_OUT0_SEL, 0x0000003f},
234		{AUD_OUT1_SEL, 0x0000003f},
235		{AUD_DN1_AFC, 0x00000002},
236		{AUD_DCOC_0_SHIFT_IN0, 0x0000000a},
237		{AUD_DCOC_0_SHIFT_IN1, 0x00000008},
238		{AUD_DCOC_1_SHIFT_IN0, 0x0000000a},
239		{AUD_DCOC_1_SHIFT_IN1, 0x00000008},
240		{AUD_IIR1_0_SEL, 0x0000001d},
241		{AUD_IIR1_2_SEL, 0x0000001e},
242		{AUD_IIR2_1_SEL, 0x00000002},
243		{AUD_IIR2_2_SEL, 0x00000004},
244		{AUD_IIR3_2_SEL, 0x0000000f},
245		{AUD_DCOC2_SHIFT, 0x00000001},
246		{AUD_IIR3_2_SHIFT, 0x00000001},
247		{AUD_DEEMPH0_SRC_SEL, 0x00000014},
248		{AUD_CORDIC_SHIFT_1, 0x00000006},
249		{AUD_POLY0_DDS_CONSTANT, 0x000e4db2},
250		{AUD_DMD_RA_DDS, 0x00f696e6},
251		{AUD_IIR2_3_SEL, 0x00000025},
252		{AUD_IIR1_4_SEL, 0x00000021},
253		{AUD_DN1_FREQ, 0x0000c965},
254		{AUD_DCOC_PASS_IN, 0x00000003},
255		{AUD_DCOC_0_SRC, 0x0000001a},
256		{AUD_DCOC_1_SRC, 0x0000001b},
257		{AUD_DCOC1_SHIFT, 0x00000000},
258		{AUD_RDSI_SEL, 0x00000009},
259		{AUD_RDSQ_SEL, 0x00000009},
260		{AUD_RDSI_SHIFT, 0x00000000},
261		{AUD_RDSQ_SHIFT, 0x00000000},
262		{AUD_POLYPH80SCALEFAC, 0x00000003},
263		{ /* end of list */ },
264	};
265
266	mode |= EN_FMRADIO_EN_RDS;
267
268	if (sap) {
269		dprintk("%s SAP (status: unknown)\n", __func__);
270		set_audio_start(core, SEL_SAP);
271		set_audio_registers(core, btsc_sap);
272		set_audio_finish(core, mode);
273	} else {
274		dprintk("%s (status: known-good)\n", __func__);
275		set_audio_start(core, SEL_BTSC);
276		set_audio_registers(core, btsc);
277		set_audio_finish(core, mode);
278	}
279}
280
281static void set_audio_standard_NICAM(struct cx88_core *core, u32 mode)
282{
283	static const struct rlist nicam_l[] = {
284		{AUD_AFE_12DB_EN, 0x00000001},
285		{AUD_RATE_ADJ1, 0x00000060},
286		{AUD_RATE_ADJ2, 0x000000F9},
287		{AUD_RATE_ADJ3, 0x000001CC},
288		{AUD_RATE_ADJ4, 0x000002B3},
289		{AUD_RATE_ADJ5, 0x00000726},
290		{AUD_DEEMPHDENOM1_R, 0x0000F3D0},
291		{AUD_DEEMPHDENOM2_R, 0x00000000},
292		{AUD_ERRLOGPERIOD_R, 0x00000064},
293		{AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF},
294		{AUD_ERRINTRPTTHSHLD2_R, 0x0000001F},
295		{AUD_ERRINTRPTTHSHLD3_R, 0x0000000F},
296		{AUD_POLYPH80SCALEFAC, 0x00000003},
297		{AUD_DMD_RA_DDS, 0x00C00000},
298		{AUD_PLL_INT, 0x0000001E},
299		{AUD_PLL_DDS, 0x00000000},
300		{AUD_PLL_FRAC, 0x0000E542},
301		{AUD_START_TIMER, 0x00000000},
302		{AUD_DEEMPHNUMER1_R, 0x000353DE},
303		{AUD_DEEMPHNUMER2_R, 0x000001B1},
304		{AUD_PDF_DDS_CNST_BYTE2, 0x06},
305		{AUD_PDF_DDS_CNST_BYTE1, 0x82},
306		{AUD_PDF_DDS_CNST_BYTE0, 0x12},
307		{AUD_QAM_MODE, 0x05},
308		{AUD_PHACC_FREQ_8MSB, 0x34},
309		{AUD_PHACC_FREQ_8LSB, 0x4C},
310		{AUD_DEEMPHGAIN_R, 0x00006680},
311		{AUD_RATE_THRES_DMD, 0x000000C0},
312		{ /* end of list */ },
313	};
314
315	static const struct rlist nicam_bgdki_common[] = {
316		{AUD_AFE_12DB_EN, 0x00000001},
317		{AUD_RATE_ADJ1, 0x00000010},
318		{AUD_RATE_ADJ2, 0x00000040},
319		{AUD_RATE_ADJ3, 0x00000100},
320		{AUD_RATE_ADJ4, 0x00000400},
321		{AUD_RATE_ADJ5, 0x00001000},
322		{AUD_ERRLOGPERIOD_R, 0x00000fff},
323		{AUD_ERRINTRPTTHSHLD1_R, 0x000003ff},
324		{AUD_ERRINTRPTTHSHLD2_R, 0x000000ff},
325		{AUD_ERRINTRPTTHSHLD3_R, 0x0000003f},
326		{AUD_POLYPH80SCALEFAC, 0x00000003},
327		{AUD_DEEMPHGAIN_R, 0x000023c2},
328		{AUD_DEEMPHNUMER1_R, 0x0002a7bc},
329		{AUD_DEEMPHNUMER2_R, 0x0003023e},
330		{AUD_DEEMPHDENOM1_R, 0x0000f3d0},
331		{AUD_DEEMPHDENOM2_R, 0x00000000},
332		{AUD_PDF_DDS_CNST_BYTE2, 0x06},
333		{AUD_PDF_DDS_CNST_BYTE1, 0x82},
334		{AUD_QAM_MODE, 0x05},
335		{ /* end of list */ },
336	};
337
338	static const struct rlist nicam_i[] = {
339		{AUD_PDF_DDS_CNST_BYTE0, 0x12},
340		{AUD_PHACC_FREQ_8MSB, 0x3a},
341		{AUD_PHACC_FREQ_8LSB, 0x93},
342		{ /* end of list */ },
343	};
344
345	static const struct rlist nicam_default[] = {
346		{AUD_PDF_DDS_CNST_BYTE0, 0x16},
347		{AUD_PHACC_FREQ_8MSB, 0x34},
348		{AUD_PHACC_FREQ_8LSB, 0x4c},
349		{ /* end of list */ },
350	};
351
352	set_audio_start(core,SEL_NICAM);
353	switch (core->tvaudio) {
354	case WW_L:
355		dprintk("%s SECAM-L NICAM (status: devel)\n", __func__);
356		set_audio_registers(core, nicam_l);
357		break;
358	case WW_I:
359		dprintk("%s PAL-I NICAM (status: known-good)\n", __func__);
360		set_audio_registers(core, nicam_bgdki_common);
361		set_audio_registers(core, nicam_i);
362		break;
363	default:
364		dprintk("%s PAL-BGDK NICAM (status: known-good)\n", __func__);
365		set_audio_registers(core, nicam_bgdki_common);
366		set_audio_registers(core, nicam_default);
367		break;
368	};
369
370	mode |= EN_DMTRX_LR | EN_DMTRX_BYPASS;
371	set_audio_finish(core, mode);
372}
373
374static void set_audio_standard_A2(struct cx88_core *core, u32 mode)
375{
376	static const struct rlist a2_bgdk_common[] = {
377		{AUD_ERRLOGPERIOD_R, 0x00000064},
378		{AUD_ERRINTRPTTHSHLD1_R, 0x00000fff},
379		{AUD_ERRINTRPTTHSHLD2_R, 0x0000001f},
380		{AUD_ERRINTRPTTHSHLD3_R, 0x0000000f},
381		{AUD_PDF_DDS_CNST_BYTE2, 0x06},
382		{AUD_PDF_DDS_CNST_BYTE1, 0x82},
383		{AUD_PDF_DDS_CNST_BYTE0, 0x12},
384		{AUD_QAM_MODE, 0x05},
385		{AUD_PHACC_FREQ_8MSB, 0x34},
386		{AUD_PHACC_FREQ_8LSB, 0x4c},
387		{AUD_RATE_ADJ1, 0x00000100},
388		{AUD_RATE_ADJ2, 0x00000200},
389		{AUD_RATE_ADJ3, 0x00000300},
390		{AUD_RATE_ADJ4, 0x00000400},
391		{AUD_RATE_ADJ5, 0x00000500},
392		{AUD_THR_FR, 0x00000000},
393		{AAGC_HYST, 0x0000001a},
394		{AUD_PILOT_BQD_1_K0, 0x0000755b},
395		{AUD_PILOT_BQD_1_K1, 0x00551340},
396		{AUD_PILOT_BQD_1_K2, 0x006d30be},
397		{AUD_PILOT_BQD_1_K3, 0xffd394af},
398		{AUD_PILOT_BQD_1_K4, 0x00400000},
399		{AUD_PILOT_BQD_2_K0, 0x00040000},
400		{AUD_PILOT_BQD_2_K1, 0x002a4841},
401		{AUD_PILOT_BQD_2_K2, 0x00400000},
402		{AUD_PILOT_BQD_2_K3, 0x00000000},
403		{AUD_PILOT_BQD_2_K4, 0x00000000},
404		{AUD_MODE_CHG_TIMER, 0x00000040},
405		{AUD_AFE_12DB_EN, 0x00000001},
406		{AUD_CORDIC_SHIFT_0, 0x00000007},
407		{AUD_CORDIC_SHIFT_1, 0x00000007},
408		{AUD_DEEMPH0_G0, 0x00000380},
409		{AUD_DEEMPH1_G0, 0x00000380},
410		{AUD_DCOC_0_SRC, 0x0000001a},
411		{AUD_DCOC0_SHIFT, 0x00000000},
412		{AUD_DCOC_0_SHIFT_IN0, 0x0000000a},
413		{AUD_DCOC_0_SHIFT_IN1, 0x00000008},
414		{AUD_DCOC_PASS_IN, 0x00000003},
415		{AUD_IIR3_0_SEL, 0x00000021},
416		{AUD_DN2_AFC, 0x00000002},
417		{AUD_DCOC_1_SRC, 0x0000001b},
418		{AUD_DCOC1_SHIFT, 0x00000000},
419		{AUD_DCOC_1_SHIFT_IN0, 0x0000000a},
420		{AUD_DCOC_1_SHIFT_IN1, 0x00000008},
421		{AUD_IIR3_1_SEL, 0x00000023},
422		{AUD_RDSI_SEL, 0x00000017},
423		{AUD_RDSI_SHIFT, 0x00000000},
424		{AUD_RDSQ_SEL, 0x00000017},
425		{AUD_RDSQ_SHIFT, 0x00000000},
426		{AUD_PLL_INT, 0x0000001e},
427		{AUD_PLL_DDS, 0x00000000},
428		{AUD_PLL_FRAC, 0x0000e542},
429		{AUD_POLYPH80SCALEFAC, 0x00000001},
430		{AUD_START_TIMER, 0x00000000},
431		{ /* end of list */ },
432	};
433
434	static const struct rlist a2_bg[] = {
435		{AUD_DMD_RA_DDS, 0x002a4f2f},
436		{AUD_C1_UP_THR, 0x00007000},
437		{AUD_C1_LO_THR, 0x00005400},
438		{AUD_C2_UP_THR, 0x00005400},
439		{AUD_C2_LO_THR, 0x00003000},
440		{ /* end of list */ },
441	};
442
443	static const struct rlist a2_dk[] = {
444		{AUD_DMD_RA_DDS, 0x002a4f2f},
445		{AUD_C1_UP_THR, 0x00007000},
446		{AUD_C1_LO_THR, 0x00005400},
447		{AUD_C2_UP_THR, 0x00005400},
448		{AUD_C2_LO_THR, 0x00003000},
449		{AUD_DN0_FREQ, 0x00003a1c},
450		{AUD_DN2_FREQ, 0x0000d2e0},
451		{ /* end of list */ },
452	};
453
454	static const struct rlist a1_i[] = {
455		{AUD_ERRLOGPERIOD_R, 0x00000064},
456		{AUD_ERRINTRPTTHSHLD1_R, 0x00000fff},
457		{AUD_ERRINTRPTTHSHLD2_R, 0x0000001f},
458		{AUD_ERRINTRPTTHSHLD3_R, 0x0000000f},
459		{AUD_PDF_DDS_CNST_BYTE2, 0x06},
460		{AUD_PDF_DDS_CNST_BYTE1, 0x82},
461		{AUD_PDF_DDS_CNST_BYTE0, 0x12},
462		{AUD_QAM_MODE, 0x05},
463		{AUD_PHACC_FREQ_8MSB, 0x3a},
464		{AUD_PHACC_FREQ_8LSB, 0x93},
465		{AUD_DMD_RA_DDS, 0x002a4f2f},
466		{AUD_PLL_INT, 0x0000001e},
467		{AUD_PLL_DDS, 0x00000004},
468		{AUD_PLL_FRAC, 0x0000e542},
469		{AUD_RATE_ADJ1, 0x00000100},
470		{AUD_RATE_ADJ2, 0x00000200},
471		{AUD_RATE_ADJ3, 0x00000300},
472		{AUD_RATE_ADJ4, 0x00000400},
473		{AUD_RATE_ADJ5, 0x00000500},
474		{AUD_THR_FR, 0x00000000},
475		{AUD_PILOT_BQD_1_K0, 0x0000755b},
476		{AUD_PILOT_BQD_1_K1, 0x00551340},
477		{AUD_PILOT_BQD_1_K2, 0x006d30be},
478		{AUD_PILOT_BQD_1_K3, 0xffd394af},
479		{AUD_PILOT_BQD_1_K4, 0x00400000},
480		{AUD_PILOT_BQD_2_K0, 0x00040000},
481		{AUD_PILOT_BQD_2_K1, 0x002a4841},
482		{AUD_PILOT_BQD_2_K2, 0x00400000},
483		{AUD_PILOT_BQD_2_K3, 0x00000000},
484		{AUD_PILOT_BQD_2_K4, 0x00000000},
485		{AUD_MODE_CHG_TIMER, 0x00000060},
486		{AUD_AFE_12DB_EN, 0x00000001},
487		{AAGC_HYST, 0x0000000a},
488		{AUD_CORDIC_SHIFT_0, 0x00000007},
489		{AUD_CORDIC_SHIFT_1, 0x00000007},
490		{AUD_C1_UP_THR, 0x00007000},
491		{AUD_C1_LO_THR, 0x00005400},
492		{AUD_C2_UP_THR, 0x00005400},
493		{AUD_C2_LO_THR, 0x00003000},
494		{AUD_DCOC_0_SRC, 0x0000001a},
495		{AUD_DCOC0_SHIFT, 0x00000000},
496		{AUD_DCOC_0_SHIFT_IN0, 0x0000000a},
497		{AUD_DCOC_0_SHIFT_IN1, 0x00000008},
498		{AUD_DCOC_PASS_IN, 0x00000003},
499		{AUD_IIR3_0_SEL, 0x00000021},
500		{AUD_DN2_AFC, 0x00000002},
501		{AUD_DCOC_1_SRC, 0x0000001b},
502		{AUD_DCOC1_SHIFT, 0x00000000},
503		{AUD_DCOC_1_SHIFT_IN0, 0x0000000a},
504		{AUD_DCOC_1_SHIFT_IN1, 0x00000008},
505		{AUD_IIR3_1_SEL, 0x00000023},
506		{AUD_DN0_FREQ, 0x000035a3},
507		{AUD_DN2_FREQ, 0x000029c7},
508		{AUD_CRDC0_SRC_SEL, 0x00000511},
509		{AUD_IIR1_0_SEL, 0x00000001},
510		{AUD_IIR1_1_SEL, 0x00000000},
511		{AUD_IIR3_2_SEL, 0x00000003},
512		{AUD_IIR3_2_SHIFT, 0x00000000},
513		{AUD_IIR3_0_SEL, 0x00000002},
514		{AUD_IIR2_0_SEL, 0x00000021},
515		{AUD_IIR2_0_SHIFT, 0x00000002},
516		{AUD_DEEMPH0_SRC_SEL, 0x0000000b},
517		{AUD_DEEMPH1_SRC_SEL, 0x0000000b},
518		{AUD_POLYPH80SCALEFAC, 0x00000001},
519		{AUD_START_TIMER, 0x00000000},
520		{ /* end of list */ },
521	};
522
523	static const struct rlist am_l[] = {
524		{AUD_ERRLOGPERIOD_R, 0x00000064},
525		{AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF},
526		{AUD_ERRINTRPTTHSHLD2_R, 0x0000001F},
527		{AUD_ERRINTRPTTHSHLD3_R, 0x0000000F},
528		{AUD_PDF_DDS_CNST_BYTE2, 0x48},
529		{AUD_PDF_DDS_CNST_BYTE1, 0x3D},
530		{AUD_QAM_MODE, 0x00},
531		{AUD_PDF_DDS_CNST_BYTE0, 0xf5},
532		{AUD_PHACC_FREQ_8MSB, 0x3a},
533		{AUD_PHACC_FREQ_8LSB, 0x4a},
534		{AUD_DEEMPHGAIN_R, 0x00006680},
535		{AUD_DEEMPHNUMER1_R, 0x000353DE},
536		{AUD_DEEMPHNUMER2_R, 0x000001B1},
537		{AUD_DEEMPHDENOM1_R, 0x0000F3D0},
538		{AUD_DEEMPHDENOM2_R, 0x00000000},
539		{AUD_FM_MODE_ENABLE, 0x00000007},
540		{AUD_POLYPH80SCALEFAC, 0x00000003},
541		{AUD_AFE_12DB_EN, 0x00000001},
542		{AAGC_GAIN, 0x00000000},
543		{AAGC_HYST, 0x00000018},
544		{AAGC_DEF, 0x00000020},
545		{AUD_DN0_FREQ, 0x00000000},
546		{AUD_POLY0_DDS_CONSTANT, 0x000E4DB2},
547		{AUD_DCOC_0_SRC, 0x00000021},
548		{AUD_IIR1_0_SEL, 0x00000000},
549		{AUD_IIR1_0_SHIFT, 0x00000007},
550		{AUD_IIR1_1_SEL, 0x00000002},
551		{AUD_IIR1_1_SHIFT, 0x00000000},
552		{AUD_DCOC_1_SRC, 0x00000003},
553		{AUD_DCOC1_SHIFT, 0x00000000},
554		{AUD_DCOC_PASS_IN, 0x00000000},
555		{AUD_IIR1_2_SEL, 0x00000023},
556		{AUD_IIR1_2_SHIFT, 0x00000000},
557		{AUD_IIR1_3_SEL, 0x00000004},
558		{AUD_IIR1_3_SHIFT, 0x00000007},
559		{AUD_IIR1_4_SEL, 0x00000005},
560		{AUD_IIR1_4_SHIFT, 0x00000007},
561		{AUD_IIR3_0_SEL, 0x00000007},
562		{AUD_IIR3_0_SHIFT, 0x00000000},
563		{AUD_DEEMPH0_SRC_SEL, 0x00000011},
564		{AUD_DEEMPH0_SHIFT, 0x00000000},
565		{AUD_DEEMPH0_G0, 0x00007000},
566		{AUD_DEEMPH0_A0, 0x00000000},
567		{AUD_DEEMPH0_B0, 0x00000000},
568		{AUD_DEEMPH0_A1, 0x00000000},
569		{AUD_DEEMPH0_B1, 0x00000000},
570		{AUD_DEEMPH1_SRC_SEL, 0x00000011},
571		{AUD_DEEMPH1_SHIFT, 0x00000000},
572		{AUD_DEEMPH1_G0, 0x00007000},
573		{AUD_DEEMPH1_A0, 0x00000000},
574		{AUD_DEEMPH1_B0, 0x00000000},
575		{AUD_DEEMPH1_A1, 0x00000000},
576		{AUD_DEEMPH1_B1, 0x00000000},
577		{AUD_OUT0_SEL, 0x0000003F},
578		{AUD_OUT1_SEL, 0x0000003F},
579		{AUD_DMD_RA_DDS, 0x00F5C285},
580		{AUD_PLL_INT, 0x0000001E},
581		{AUD_PLL_DDS, 0x00000000},
582		{AUD_PLL_FRAC, 0x0000E542},
583		{AUD_RATE_ADJ1, 0x00000100},
584		{AUD_RATE_ADJ2, 0x00000200},
585		{AUD_RATE_ADJ3, 0x00000300},
586		{AUD_RATE_ADJ4, 0x00000400},
587		{AUD_RATE_ADJ5, 0x00000500},
588		{AUD_RATE_THRES_DMD, 0x000000C0},
589		{ /* end of list */ },
590	};
591
592	static const struct rlist a2_deemph50[] = {
593		{AUD_DEEMPH0_G0, 0x00000380},
594		{AUD_DEEMPH1_G0, 0x00000380},
595		{AUD_DEEMPHGAIN_R, 0x000011e1},
596		{AUD_DEEMPHNUMER1_R, 0x0002a7bc},
597		{AUD_DEEMPHNUMER2_R, 0x0003023c},
598		{ /* end of list */ },
599	};
600
601	set_audio_start(core, SEL_A2);
602	switch (core->tvaudio) {
603	case WW_BG:
604		dprintk("%s PAL-BG A1/2 (status: known-good)\n", __func__);
605		set_audio_registers(core, a2_bgdk_common);
606		set_audio_registers(core, a2_bg);
607		set_audio_registers(core, a2_deemph50);
608		break;
609	case WW_DK:
610		dprintk("%s PAL-DK A1/2 (status: known-good)\n", __func__);
611		set_audio_registers(core, a2_bgdk_common);
612		set_audio_registers(core, a2_dk);
613		set_audio_registers(core, a2_deemph50);
614		break;
615	case WW_I:
616		dprintk("%s PAL-I A1 (status: known-good)\n", __func__);
617		set_audio_registers(core, a1_i);
618		set_audio_registers(core, a2_deemph50);
619		break;
620	case WW_L:
621		dprintk("%s AM-L (status: devel)\n", __func__);
622		set_audio_registers(core, am_l);
623		break;
624	default:
625		dprintk("%s Warning: wrong value\n", __func__);
626		return;
627		break;
628	};
629
630	mode |= EN_FMRADIO_EN_RDS | EN_DMTRX_SUMDIFF;
631	set_audio_finish(core, mode);
632}
633
634static void set_audio_standard_EIAJ(struct cx88_core *core)
635{
636	static const struct rlist eiaj[] = {
637		/* TODO: eiaj register settings are not there yet ... */
638
639		{ /* end of list */ },
640	};
641	dprintk("%s (status: unknown)\n", __func__);
642
643	set_audio_start(core, SEL_EIAJ);
644	set_audio_registers(core, eiaj);
645	set_audio_finish(core, EN_EIAJ_AUTO_STEREO);
646}
647
648static void set_audio_standard_FM(struct cx88_core *core,
649				  enum cx88_deemph_type deemph)
650{
651	static const struct rlist fm_deemph_50[] = {
652		{AUD_DEEMPH0_G0, 0x0C45},
653		{AUD_DEEMPH0_A0, 0x6262},
654		{AUD_DEEMPH0_B0, 0x1C29},
655		{AUD_DEEMPH0_A1, 0x3FC66},
656		{AUD_DEEMPH0_B1, 0x399A},
657
658		{AUD_DEEMPH1_G0, 0x0D80},
659		{AUD_DEEMPH1_A0, 0x6262},
660		{AUD_DEEMPH1_B0, 0x1C29},
661		{AUD_DEEMPH1_A1, 0x3FC66},
662		{AUD_DEEMPH1_B1, 0x399A},
663
664		{AUD_POLYPH80SCALEFAC, 0x0003},
665		{ /* end of list */ },
666	};
667	static const struct rlist fm_deemph_75[] = {
668		{AUD_DEEMPH0_G0, 0x091B},
669		{AUD_DEEMPH0_A0, 0x6B68},
670		{AUD_DEEMPH0_B0, 0x11EC},
671		{AUD_DEEMPH0_A1, 0x3FC66},
672		{AUD_DEEMPH0_B1, 0x399A},
673
674		{AUD_DEEMPH1_G0, 0x0AA0},
675		{AUD_DEEMPH1_A0, 0x6B68},
676		{AUD_DEEMPH1_B0, 0x11EC},
677		{AUD_DEEMPH1_A1, 0x3FC66},
678		{AUD_DEEMPH1_B1, 0x399A},
679
680		{AUD_POLYPH80SCALEFAC, 0x0003},
681		{ /* end of list */ },
682	};
683
684	/* It is enough to leave default values? */
685	/* No, it's not!  The deemphasis registers are reset to the 75us
686	 * values by default.  Analyzing the spectrum of the decoded audio
687	 * reveals that "no deemphasis" is the same as 75 us, while the 50 us
688	 * setting results in less deemphasis.  */
689	static const struct rlist fm_no_deemph[] = {
690
691		{AUD_POLYPH80SCALEFAC, 0x0003},
692		{ /* end of list */ },
693	};
694
695	dprintk("%s (status: unknown)\n", __func__);
696	set_audio_start(core, SEL_FMRADIO);
697
698	switch (deemph) {
699	default:
700	case FM_NO_DEEMPH:
701		set_audio_registers(core, fm_no_deemph);
702		break;
703
704	case FM_DEEMPH_50:
705		set_audio_registers(core, fm_deemph_50);
706		break;
707
708	case FM_DEEMPH_75:
709		set_audio_registers(core, fm_deemph_75);
710		break;
711	}
712
713	set_audio_finish(core, EN_FMRADIO_AUTO_STEREO);
714}
715
716/* ----------------------------------------------------------- */
717
718static int cx88_detect_nicam(struct cx88_core *core)
719{
720	int i, j = 0;
721
722	dprintk("start nicam autodetect.\n");
723
724	for (i = 0; i < 6; i++) {
725		/* if bit1=1 then nicam is detected */
726		j += ((cx_read(AUD_NICAM_STATUS2) & 0x02) >> 1);
727
728		if (j == 1) {
729			dprintk("nicam is detected.\n");
730			return 1;
731		}
732
733		/* wait a little bit for next reading status */
734		msleep(10);
735	}
736
737	dprintk("nicam is not detected.\n");
738	return 0;
739}
740
741void cx88_set_tvaudio(struct cx88_core *core)
742{
743	switch (core->tvaudio) {
744	case WW_BTSC:
745		set_audio_standard_BTSC(core, 0, EN_BTSC_AUTO_STEREO);
746		break;
747	case WW_BG:
748	case WW_DK:
749	case WW_M:
750	case WW_I:
751	case WW_L:
752		/* prepare all dsp registers */
753		set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
754
755		/* set nicam mode - otherwise
756		   AUD_NICAM_STATUS2 contains wrong values */
757		set_audio_standard_NICAM(core, EN_NICAM_AUTO_STEREO);
758		if (0 == cx88_detect_nicam(core)) {
759			/* fall back to fm / am mono */
760			set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
761			core->audiomode_current = V4L2_TUNER_MODE_MONO;
762			core->use_nicam = 0;
763		} else {
764			core->use_nicam = 1;
765		}
766		break;
767	case WW_EIAJ:
768		set_audio_standard_EIAJ(core);
769		break;
770	case WW_FM:
771		set_audio_standard_FM(core, radio_deemphasis);
772		break;
773	case WW_I2SADC:
774		set_audio_start(core, 0x01);
775		/* Slave/Philips/Autobaud */
776		cx_write(AUD_I2SINPUTCNTL, 0);
777		/* Switch to "I2S ADC mode" */
778		cx_write(AUD_I2SCNTL, 0x1);
779		set_audio_finish(core, EN_I2SIN_ENABLE);
780		break;
781	case WW_NONE:
782	default:
783		printk("%s/0: unknown tv audio mode [%d]\n",
784		       core->name, core->tvaudio);
785		break;
786	}
787	return;
788}
789
790void cx88_newstation(struct cx88_core *core)
791{
792	core->audiomode_manual = UNSET;
793	core->last_change = jiffies;
794}
795
796void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t)
797{
798	static char *m[] = { "stereo", "dual mono", "mono", "sap" };
799	static char *p[] = { "no pilot", "pilot c1", "pilot c2", "?" };
800	u32 reg, mode, pilot;
801
802	reg = cx_read(AUD_STATUS);
803	mode = reg & 0x03;
804	pilot = (reg >> 2) & 0x03;
805
806	if (core->astat != reg)
807		dprintk("AUD_STATUS: 0x%x [%s/%s] ctl=%s\n",
808			reg, m[mode], p[pilot],
809			aud_ctl_names[cx_read(AUD_CTL) & 63]);
810	core->astat = reg;
811
812	t->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_SAP |
813	    V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
814	t->rxsubchans = UNSET;
815	t->audmode = V4L2_TUNER_MODE_MONO;
816
817	switch (mode) {
818	case 0:
819		t->audmode = V4L2_TUNER_MODE_STEREO;
820		break;
821	case 1:
822		t->audmode = V4L2_TUNER_MODE_LANG2;
823		break;
824	case 2:
825		t->audmode = V4L2_TUNER_MODE_MONO;
826		break;
827	case 3:
828		t->audmode = V4L2_TUNER_MODE_SAP;
829		break;
830	}
831
832	switch (core->tvaudio) {
833	case WW_BTSC:
834	case WW_BG:
835	case WW_DK:
836	case WW_M:
837	case WW_EIAJ:
838		if (!core->use_nicam) {
839			t->rxsubchans = cx88_dsp_detect_stereo_sap(core);
840			break;
841		}
842		break;
843	default:
844		/* nothing */
845		break;
846	}
847
848	/* If software stereo detection is not supported... */
849	if (UNSET == t->rxsubchans) {
850		t->rxsubchans = V4L2_TUNER_SUB_MONO;
851		/* If the hardware itself detected stereo, also return
852		   stereo as an available subchannel */
853		if (V4L2_TUNER_MODE_STEREO == t->audmode)
854			t->rxsubchans |= V4L2_TUNER_SUB_STEREO;
855	}
856	return;
857}
858
859void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual)
860{
861	u32 ctl = UNSET;
862	u32 mask = UNSET;
863
864	if (manual) {
865		core->audiomode_manual = mode;
866	} else {
867		if (UNSET != core->audiomode_manual)
868			return;
869	}
870	core->audiomode_current = mode;
871
872	switch (core->tvaudio) {
873	case WW_BTSC:
874		switch (mode) {
875		case V4L2_TUNER_MODE_MONO:
876			set_audio_standard_BTSC(core, 0, EN_BTSC_FORCE_MONO);
877			break;
878		case V4L2_TUNER_MODE_LANG1:
879			set_audio_standard_BTSC(core, 0, EN_BTSC_AUTO_STEREO);
880			break;
881		case V4L2_TUNER_MODE_LANG2:
882			set_audio_standard_BTSC(core, 1, EN_BTSC_FORCE_SAP);
883			break;
884		case V4L2_TUNER_MODE_STEREO:
885		case V4L2_TUNER_MODE_LANG1_LANG2:
886			set_audio_standard_BTSC(core, 0, EN_BTSC_FORCE_STEREO);
887			break;
888		}
889		break;
890	case WW_BG:
891	case WW_DK:
892	case WW_M:
893	case WW_I:
894	case WW_L:
895		if (1 == core->use_nicam) {
896			switch (mode) {
897			case V4L2_TUNER_MODE_MONO:
898			case V4L2_TUNER_MODE_LANG1:
899				set_audio_standard_NICAM(core,
900							 EN_NICAM_FORCE_MONO1);
901				break;
902			case V4L2_TUNER_MODE_LANG2:
903				set_audio_standard_NICAM(core,
904							 EN_NICAM_FORCE_MONO2);
905				break;
906			case V4L2_TUNER_MODE_STEREO:
907			case V4L2_TUNER_MODE_LANG1_LANG2:
908				set_audio_standard_NICAM(core,
909							 EN_NICAM_FORCE_STEREO);
910				break;
911			}
912		} else {
913			if ((core->tvaudio == WW_I) || (core->tvaudio == WW_L)) {
914				/* fall back to fm / am mono */
915				set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
916			} else {
917				/* TODO: Add A2 autodection */
918				mask = 0x3f;
919				switch (mode) {
920				case V4L2_TUNER_MODE_MONO:
921				case V4L2_TUNER_MODE_LANG1:
922					ctl = EN_A2_FORCE_MONO1;
923					break;
924				case V4L2_TUNER_MODE_LANG2:
925					ctl = EN_A2_FORCE_MONO2;
926					break;
927				case V4L2_TUNER_MODE_STEREO:
928				case V4L2_TUNER_MODE_LANG1_LANG2:
929					ctl = EN_A2_FORCE_STEREO;
930					break;
931				}
932			}
933		}
934		break;
935	case WW_FM:
936		switch (mode) {
937		case V4L2_TUNER_MODE_MONO:
938			ctl = EN_FMRADIO_FORCE_MONO;
939			mask = 0x3f;
940			break;
941		case V4L2_TUNER_MODE_STEREO:
942			ctl = EN_FMRADIO_AUTO_STEREO;
943			mask = 0x3f;
944			break;
945		}
946		break;
947	case WW_I2SADC:
948		/* DO NOTHING */
949		break;
950	}
951
952	if (UNSET != ctl) {
953		dprintk("cx88_set_stereo: mask 0x%x, ctl 0x%x "
954			"[status=0x%x,ctl=0x%x,vol=0x%x]\n",
955			mask, ctl, cx_read(AUD_STATUS),
956			cx_read(AUD_CTL), cx_sread(SHADOW_AUD_VOL_CTL));
957		cx_andor(AUD_CTL, mask, ctl);
958	}
959	return;
960}
961
962int cx88_audio_thread(void *data)
963{
964	struct cx88_core *core = data;
965	struct v4l2_tuner t;
966	u32 mode = 0;
967
968	dprintk("cx88: tvaudio thread started\n");
969	set_freezable();
970	for (;;) {
971		msleep_interruptible(1000);
972		if (kthread_should_stop())
973			break;
974		try_to_freeze();
975
976		switch (core->tvaudio) {
977		case WW_BG:
978		case WW_DK:
979		case WW_M:
980		case WW_I:
981		case WW_L:
982			if (core->use_nicam)
983				goto hw_autodetect;
984
985			/* just monitor the audio status for now ... */
986			memset(&t, 0, sizeof(t));
987			cx88_get_stereo(core, &t);
988
989			if (UNSET != core->audiomode_manual)
990				/* manually set, don't do anything. */
991				continue;
992
993			/* monitor signal and set stereo if available */
994			if (t.rxsubchans & V4L2_TUNER_SUB_STEREO)
995				mode = V4L2_TUNER_MODE_STEREO;
996			else
997				mode = V4L2_TUNER_MODE_MONO;
998			if (mode == core->audiomode_current)
999				continue;
1000			/* automatically switch to best available mode */
1001			cx88_set_stereo(core, mode, 0);
1002			break;
1003		default:
1004hw_autodetect:
1005			/* stereo autodetection is supported by hardware so
1006			   we don't need to do it manually. Do nothing. */
1007			break;
1008		}
1009	}
1010
1011	dprintk("cx88: tvaudio thread exiting\n");
1012	return 0;
1013}
1014
1015/* ----------------------------------------------------------- */
1016
1017EXPORT_SYMBOL(cx88_set_tvaudio);
1018EXPORT_SYMBOL(cx88_newstation);
1019EXPORT_SYMBOL(cx88_set_stereo);
1020EXPORT_SYMBOL(cx88_get_stereo);
1021EXPORT_SYMBOL(cx88_audio_thread);
1022
1023/*
1024 * Local variables:
1025 * c-basic-offset: 8
1026 * End:
1027 * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
1028 */
1029