[go: nahoru, domu]

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 const char * const 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	case WW_NONE:
364	case WW_BTSC:
365	case WW_BG:
366	case WW_DK:
367	case WW_EIAJ:
368	case WW_I2SPT:
369	case WW_FM:
370	case WW_I2SADC:
371	case WW_M:
372		dprintk("%s PAL-BGDK NICAM (status: known-good)\n", __func__);
373		set_audio_registers(core, nicam_bgdki_common);
374		set_audio_registers(core, nicam_default);
375		break;
376	}
377
378	mode |= EN_DMTRX_LR | EN_DMTRX_BYPASS;
379	set_audio_finish(core, mode);
380}
381
382static void set_audio_standard_A2(struct cx88_core *core, u32 mode)
383{
384	static const struct rlist a2_bgdk_common[] = {
385		{AUD_ERRLOGPERIOD_R, 0x00000064},
386		{AUD_ERRINTRPTTHSHLD1_R, 0x00000fff},
387		{AUD_ERRINTRPTTHSHLD2_R, 0x0000001f},
388		{AUD_ERRINTRPTTHSHLD3_R, 0x0000000f},
389		{AUD_PDF_DDS_CNST_BYTE2, 0x06},
390		{AUD_PDF_DDS_CNST_BYTE1, 0x82},
391		{AUD_PDF_DDS_CNST_BYTE0, 0x12},
392		{AUD_QAM_MODE, 0x05},
393		{AUD_PHACC_FREQ_8MSB, 0x34},
394		{AUD_PHACC_FREQ_8LSB, 0x4c},
395		{AUD_RATE_ADJ1, 0x00000100},
396		{AUD_RATE_ADJ2, 0x00000200},
397		{AUD_RATE_ADJ3, 0x00000300},
398		{AUD_RATE_ADJ4, 0x00000400},
399		{AUD_RATE_ADJ5, 0x00000500},
400		{AUD_THR_FR, 0x00000000},
401		{AAGC_HYST, 0x0000001a},
402		{AUD_PILOT_BQD_1_K0, 0x0000755b},
403		{AUD_PILOT_BQD_1_K1, 0x00551340},
404		{AUD_PILOT_BQD_1_K2, 0x006d30be},
405		{AUD_PILOT_BQD_1_K3, 0xffd394af},
406		{AUD_PILOT_BQD_1_K4, 0x00400000},
407		{AUD_PILOT_BQD_2_K0, 0x00040000},
408		{AUD_PILOT_BQD_2_K1, 0x002a4841},
409		{AUD_PILOT_BQD_2_K2, 0x00400000},
410		{AUD_PILOT_BQD_2_K3, 0x00000000},
411		{AUD_PILOT_BQD_2_K4, 0x00000000},
412		{AUD_MODE_CHG_TIMER, 0x00000040},
413		{AUD_AFE_12DB_EN, 0x00000001},
414		{AUD_CORDIC_SHIFT_0, 0x00000007},
415		{AUD_CORDIC_SHIFT_1, 0x00000007},
416		{AUD_DEEMPH0_G0, 0x00000380},
417		{AUD_DEEMPH1_G0, 0x00000380},
418		{AUD_DCOC_0_SRC, 0x0000001a},
419		{AUD_DCOC0_SHIFT, 0x00000000},
420		{AUD_DCOC_0_SHIFT_IN0, 0x0000000a},
421		{AUD_DCOC_0_SHIFT_IN1, 0x00000008},
422		{AUD_DCOC_PASS_IN, 0x00000003},
423		{AUD_IIR3_0_SEL, 0x00000021},
424		{AUD_DN2_AFC, 0x00000002},
425		{AUD_DCOC_1_SRC, 0x0000001b},
426		{AUD_DCOC1_SHIFT, 0x00000000},
427		{AUD_DCOC_1_SHIFT_IN0, 0x0000000a},
428		{AUD_DCOC_1_SHIFT_IN1, 0x00000008},
429		{AUD_IIR3_1_SEL, 0x00000023},
430		{AUD_RDSI_SEL, 0x00000017},
431		{AUD_RDSI_SHIFT, 0x00000000},
432		{AUD_RDSQ_SEL, 0x00000017},
433		{AUD_RDSQ_SHIFT, 0x00000000},
434		{AUD_PLL_INT, 0x0000001e},
435		{AUD_PLL_DDS, 0x00000000},
436		{AUD_PLL_FRAC, 0x0000e542},
437		{AUD_POLYPH80SCALEFAC, 0x00000001},
438		{AUD_START_TIMER, 0x00000000},
439		{ /* end of list */ },
440	};
441
442	static const struct rlist a2_bg[] = {
443		{AUD_DMD_RA_DDS, 0x002a4f2f},
444		{AUD_C1_UP_THR, 0x00007000},
445		{AUD_C1_LO_THR, 0x00005400},
446		{AUD_C2_UP_THR, 0x00005400},
447		{AUD_C2_LO_THR, 0x00003000},
448		{ /* end of list */ },
449	};
450
451	static const struct rlist a2_dk[] = {
452		{AUD_DMD_RA_DDS, 0x002a4f2f},
453		{AUD_C1_UP_THR, 0x00007000},
454		{AUD_C1_LO_THR, 0x00005400},
455		{AUD_C2_UP_THR, 0x00005400},
456		{AUD_C2_LO_THR, 0x00003000},
457		{AUD_DN0_FREQ, 0x00003a1c},
458		{AUD_DN2_FREQ, 0x0000d2e0},
459		{ /* end of list */ },
460	};
461
462	static const struct rlist a1_i[] = {
463		{AUD_ERRLOGPERIOD_R, 0x00000064},
464		{AUD_ERRINTRPTTHSHLD1_R, 0x00000fff},
465		{AUD_ERRINTRPTTHSHLD2_R, 0x0000001f},
466		{AUD_ERRINTRPTTHSHLD3_R, 0x0000000f},
467		{AUD_PDF_DDS_CNST_BYTE2, 0x06},
468		{AUD_PDF_DDS_CNST_BYTE1, 0x82},
469		{AUD_PDF_DDS_CNST_BYTE0, 0x12},
470		{AUD_QAM_MODE, 0x05},
471		{AUD_PHACC_FREQ_8MSB, 0x3a},
472		{AUD_PHACC_FREQ_8LSB, 0x93},
473		{AUD_DMD_RA_DDS, 0x002a4f2f},
474		{AUD_PLL_INT, 0x0000001e},
475		{AUD_PLL_DDS, 0x00000004},
476		{AUD_PLL_FRAC, 0x0000e542},
477		{AUD_RATE_ADJ1, 0x00000100},
478		{AUD_RATE_ADJ2, 0x00000200},
479		{AUD_RATE_ADJ3, 0x00000300},
480		{AUD_RATE_ADJ4, 0x00000400},
481		{AUD_RATE_ADJ5, 0x00000500},
482		{AUD_THR_FR, 0x00000000},
483		{AUD_PILOT_BQD_1_K0, 0x0000755b},
484		{AUD_PILOT_BQD_1_K1, 0x00551340},
485		{AUD_PILOT_BQD_1_K2, 0x006d30be},
486		{AUD_PILOT_BQD_1_K3, 0xffd394af},
487		{AUD_PILOT_BQD_1_K4, 0x00400000},
488		{AUD_PILOT_BQD_2_K0, 0x00040000},
489		{AUD_PILOT_BQD_2_K1, 0x002a4841},
490		{AUD_PILOT_BQD_2_K2, 0x00400000},
491		{AUD_PILOT_BQD_2_K3, 0x00000000},
492		{AUD_PILOT_BQD_2_K4, 0x00000000},
493		{AUD_MODE_CHG_TIMER, 0x00000060},
494		{AUD_AFE_12DB_EN, 0x00000001},
495		{AAGC_HYST, 0x0000000a},
496		{AUD_CORDIC_SHIFT_0, 0x00000007},
497		{AUD_CORDIC_SHIFT_1, 0x00000007},
498		{AUD_C1_UP_THR, 0x00007000},
499		{AUD_C1_LO_THR, 0x00005400},
500		{AUD_C2_UP_THR, 0x00005400},
501		{AUD_C2_LO_THR, 0x00003000},
502		{AUD_DCOC_0_SRC, 0x0000001a},
503		{AUD_DCOC0_SHIFT, 0x00000000},
504		{AUD_DCOC_0_SHIFT_IN0, 0x0000000a},
505		{AUD_DCOC_0_SHIFT_IN1, 0x00000008},
506		{AUD_DCOC_PASS_IN, 0x00000003},
507		{AUD_IIR3_0_SEL, 0x00000021},
508		{AUD_DN2_AFC, 0x00000002},
509		{AUD_DCOC_1_SRC, 0x0000001b},
510		{AUD_DCOC1_SHIFT, 0x00000000},
511		{AUD_DCOC_1_SHIFT_IN0, 0x0000000a},
512		{AUD_DCOC_1_SHIFT_IN1, 0x00000008},
513		{AUD_IIR3_1_SEL, 0x00000023},
514		{AUD_DN0_FREQ, 0x000035a3},
515		{AUD_DN2_FREQ, 0x000029c7},
516		{AUD_CRDC0_SRC_SEL, 0x00000511},
517		{AUD_IIR1_0_SEL, 0x00000001},
518		{AUD_IIR1_1_SEL, 0x00000000},
519		{AUD_IIR3_2_SEL, 0x00000003},
520		{AUD_IIR3_2_SHIFT, 0x00000000},
521		{AUD_IIR3_0_SEL, 0x00000002},
522		{AUD_IIR2_0_SEL, 0x00000021},
523		{AUD_IIR2_0_SHIFT, 0x00000002},
524		{AUD_DEEMPH0_SRC_SEL, 0x0000000b},
525		{AUD_DEEMPH1_SRC_SEL, 0x0000000b},
526		{AUD_POLYPH80SCALEFAC, 0x00000001},
527		{AUD_START_TIMER, 0x00000000},
528		{ /* end of list */ },
529	};
530
531	static const struct rlist am_l[] = {
532		{AUD_ERRLOGPERIOD_R, 0x00000064},
533		{AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF},
534		{AUD_ERRINTRPTTHSHLD2_R, 0x0000001F},
535		{AUD_ERRINTRPTTHSHLD3_R, 0x0000000F},
536		{AUD_PDF_DDS_CNST_BYTE2, 0x48},
537		{AUD_PDF_DDS_CNST_BYTE1, 0x3D},
538		{AUD_QAM_MODE, 0x00},
539		{AUD_PDF_DDS_CNST_BYTE0, 0xf5},
540		{AUD_PHACC_FREQ_8MSB, 0x3a},
541		{AUD_PHACC_FREQ_8LSB, 0x4a},
542		{AUD_DEEMPHGAIN_R, 0x00006680},
543		{AUD_DEEMPHNUMER1_R, 0x000353DE},
544		{AUD_DEEMPHNUMER2_R, 0x000001B1},
545		{AUD_DEEMPHDENOM1_R, 0x0000F3D0},
546		{AUD_DEEMPHDENOM2_R, 0x00000000},
547		{AUD_FM_MODE_ENABLE, 0x00000007},
548		{AUD_POLYPH80SCALEFAC, 0x00000003},
549		{AUD_AFE_12DB_EN, 0x00000001},
550		{AAGC_GAIN, 0x00000000},
551		{AAGC_HYST, 0x00000018},
552		{AAGC_DEF, 0x00000020},
553		{AUD_DN0_FREQ, 0x00000000},
554		{AUD_POLY0_DDS_CONSTANT, 0x000E4DB2},
555		{AUD_DCOC_0_SRC, 0x00000021},
556		{AUD_IIR1_0_SEL, 0x00000000},
557		{AUD_IIR1_0_SHIFT, 0x00000007},
558		{AUD_IIR1_1_SEL, 0x00000002},
559		{AUD_IIR1_1_SHIFT, 0x00000000},
560		{AUD_DCOC_1_SRC, 0x00000003},
561		{AUD_DCOC1_SHIFT, 0x00000000},
562		{AUD_DCOC_PASS_IN, 0x00000000},
563		{AUD_IIR1_2_SEL, 0x00000023},
564		{AUD_IIR1_2_SHIFT, 0x00000000},
565		{AUD_IIR1_3_SEL, 0x00000004},
566		{AUD_IIR1_3_SHIFT, 0x00000007},
567		{AUD_IIR1_4_SEL, 0x00000005},
568		{AUD_IIR1_4_SHIFT, 0x00000007},
569		{AUD_IIR3_0_SEL, 0x00000007},
570		{AUD_IIR3_0_SHIFT, 0x00000000},
571		{AUD_DEEMPH0_SRC_SEL, 0x00000011},
572		{AUD_DEEMPH0_SHIFT, 0x00000000},
573		{AUD_DEEMPH0_G0, 0x00007000},
574		{AUD_DEEMPH0_A0, 0x00000000},
575		{AUD_DEEMPH0_B0, 0x00000000},
576		{AUD_DEEMPH0_A1, 0x00000000},
577		{AUD_DEEMPH0_B1, 0x00000000},
578		{AUD_DEEMPH1_SRC_SEL, 0x00000011},
579		{AUD_DEEMPH1_SHIFT, 0x00000000},
580		{AUD_DEEMPH1_G0, 0x00007000},
581		{AUD_DEEMPH1_A0, 0x00000000},
582		{AUD_DEEMPH1_B0, 0x00000000},
583		{AUD_DEEMPH1_A1, 0x00000000},
584		{AUD_DEEMPH1_B1, 0x00000000},
585		{AUD_OUT0_SEL, 0x0000003F},
586		{AUD_OUT1_SEL, 0x0000003F},
587		{AUD_DMD_RA_DDS, 0x00F5C285},
588		{AUD_PLL_INT, 0x0000001E},
589		{AUD_PLL_DDS, 0x00000000},
590		{AUD_PLL_FRAC, 0x0000E542},
591		{AUD_RATE_ADJ1, 0x00000100},
592		{AUD_RATE_ADJ2, 0x00000200},
593		{AUD_RATE_ADJ3, 0x00000300},
594		{AUD_RATE_ADJ4, 0x00000400},
595		{AUD_RATE_ADJ5, 0x00000500},
596		{AUD_RATE_THRES_DMD, 0x000000C0},
597		{ /* end of list */ },
598	};
599
600	static const struct rlist a2_deemph50[] = {
601		{AUD_DEEMPH0_G0, 0x00000380},
602		{AUD_DEEMPH1_G0, 0x00000380},
603		{AUD_DEEMPHGAIN_R, 0x000011e1},
604		{AUD_DEEMPHNUMER1_R, 0x0002a7bc},
605		{AUD_DEEMPHNUMER2_R, 0x0003023c},
606		{ /* end of list */ },
607	};
608
609	set_audio_start(core, SEL_A2);
610	switch (core->tvaudio) {
611	case WW_BG:
612		dprintk("%s PAL-BG A1/2 (status: known-good)\n", __func__);
613		set_audio_registers(core, a2_bgdk_common);
614		set_audio_registers(core, a2_bg);
615		set_audio_registers(core, a2_deemph50);
616		break;
617	case WW_DK:
618		dprintk("%s PAL-DK A1/2 (status: known-good)\n", __func__);
619		set_audio_registers(core, a2_bgdk_common);
620		set_audio_registers(core, a2_dk);
621		set_audio_registers(core, a2_deemph50);
622		break;
623	case WW_I:
624		dprintk("%s PAL-I A1 (status: known-good)\n", __func__);
625		set_audio_registers(core, a1_i);
626		set_audio_registers(core, a2_deemph50);
627		break;
628	case WW_L:
629		dprintk("%s AM-L (status: devel)\n", __func__);
630		set_audio_registers(core, am_l);
631		break;
632	case WW_NONE:
633	case WW_BTSC:
634	case WW_EIAJ:
635	case WW_I2SPT:
636	case WW_FM:
637	case WW_I2SADC:
638	case WW_M:
639		dprintk("%s Warning: wrong value\n", __func__);
640		return;
641		break;
642	}
643
644	mode |= EN_FMRADIO_EN_RDS | EN_DMTRX_SUMDIFF;
645	set_audio_finish(core, mode);
646}
647
648static void set_audio_standard_EIAJ(struct cx88_core *core)
649{
650	static const struct rlist eiaj[] = {
651		/* TODO: eiaj register settings are not there yet ... */
652
653		{ /* end of list */ },
654	};
655	dprintk("%s (status: unknown)\n", __func__);
656
657	set_audio_start(core, SEL_EIAJ);
658	set_audio_registers(core, eiaj);
659	set_audio_finish(core, EN_EIAJ_AUTO_STEREO);
660}
661
662static void set_audio_standard_FM(struct cx88_core *core,
663				  enum cx88_deemph_type deemph)
664{
665	static const struct rlist fm_deemph_50[] = {
666		{AUD_DEEMPH0_G0, 0x0C45},
667		{AUD_DEEMPH0_A0, 0x6262},
668		{AUD_DEEMPH0_B0, 0x1C29},
669		{AUD_DEEMPH0_A1, 0x3FC66},
670		{AUD_DEEMPH0_B1, 0x399A},
671
672		{AUD_DEEMPH1_G0, 0x0D80},
673		{AUD_DEEMPH1_A0, 0x6262},
674		{AUD_DEEMPH1_B0, 0x1C29},
675		{AUD_DEEMPH1_A1, 0x3FC66},
676		{AUD_DEEMPH1_B1, 0x399A},
677
678		{AUD_POLYPH80SCALEFAC, 0x0003},
679		{ /* end of list */ },
680	};
681	static const struct rlist fm_deemph_75[] = {
682		{AUD_DEEMPH0_G0, 0x091B},
683		{AUD_DEEMPH0_A0, 0x6B68},
684		{AUD_DEEMPH0_B0, 0x11EC},
685		{AUD_DEEMPH0_A1, 0x3FC66},
686		{AUD_DEEMPH0_B1, 0x399A},
687
688		{AUD_DEEMPH1_G0, 0x0AA0},
689		{AUD_DEEMPH1_A0, 0x6B68},
690		{AUD_DEEMPH1_B0, 0x11EC},
691		{AUD_DEEMPH1_A1, 0x3FC66},
692		{AUD_DEEMPH1_B1, 0x399A},
693
694		{AUD_POLYPH80SCALEFAC, 0x0003},
695		{ /* end of list */ },
696	};
697
698	/* It is enough to leave default values? */
699	/* No, it's not!  The deemphasis registers are reset to the 75us
700	 * values by default.  Analyzing the spectrum of the decoded audio
701	 * reveals that "no deemphasis" is the same as 75 us, while the 50 us
702	 * setting results in less deemphasis.  */
703	static const struct rlist fm_no_deemph[] = {
704
705		{AUD_POLYPH80SCALEFAC, 0x0003},
706		{ /* end of list */ },
707	};
708
709	dprintk("%s (status: unknown)\n", __func__);
710	set_audio_start(core, SEL_FMRADIO);
711
712	switch (deemph) {
713	default:
714	case FM_NO_DEEMPH:
715		set_audio_registers(core, fm_no_deemph);
716		break;
717
718	case FM_DEEMPH_50:
719		set_audio_registers(core, fm_deemph_50);
720		break;
721
722	case FM_DEEMPH_75:
723		set_audio_registers(core, fm_deemph_75);
724		break;
725	}
726
727	set_audio_finish(core, EN_FMRADIO_AUTO_STEREO);
728}
729
730/* ----------------------------------------------------------- */
731
732static int cx88_detect_nicam(struct cx88_core *core)
733{
734	int i, j = 0;
735
736	dprintk("start nicam autodetect.\n");
737
738	for (i = 0; i < 6; i++) {
739		/* if bit1=1 then nicam is detected */
740		j += ((cx_read(AUD_NICAM_STATUS2) & 0x02) >> 1);
741
742		if (j == 1) {
743			dprintk("nicam is detected.\n");
744			return 1;
745		}
746
747		/* wait a little bit for next reading status */
748		msleep(10);
749	}
750
751	dprintk("nicam is not detected.\n");
752	return 0;
753}
754
755void cx88_set_tvaudio(struct cx88_core *core)
756{
757	switch (core->tvaudio) {
758	case WW_BTSC:
759		set_audio_standard_BTSC(core, 0, EN_BTSC_AUTO_STEREO);
760		break;
761	case WW_BG:
762	case WW_DK:
763	case WW_M:
764	case WW_I:
765	case WW_L:
766		/* prepare all dsp registers */
767		set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
768
769		/* set nicam mode - otherwise
770		   AUD_NICAM_STATUS2 contains wrong values */
771		set_audio_standard_NICAM(core, EN_NICAM_AUTO_STEREO);
772		if (0 == cx88_detect_nicam(core)) {
773			/* fall back to fm / am mono */
774			set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
775			core->audiomode_current = V4L2_TUNER_MODE_MONO;
776			core->use_nicam = 0;
777		} else {
778			core->use_nicam = 1;
779		}
780		break;
781	case WW_EIAJ:
782		set_audio_standard_EIAJ(core);
783		break;
784	case WW_FM:
785		set_audio_standard_FM(core, radio_deemphasis);
786		break;
787	case WW_I2SADC:
788		set_audio_start(core, 0x01);
789		/*
790		 * Slave/Philips/Autobaud
791		 * NB on Nova-S bit1 NPhilipsSony appears to be inverted:
792		 *	0= Sony, 1=Philips
793		 */
794		cx_write(AUD_I2SINPUTCNTL, core->board.i2sinputcntl);
795		/* Switch to "I2S ADC mode" */
796		cx_write(AUD_I2SCNTL, 0x1);
797		set_audio_finish(core, EN_I2SIN_ENABLE);
798		break;
799	case WW_NONE:
800	case WW_I2SPT:
801		printk("%s/0: unknown tv audio mode [%d]\n",
802		       core->name, core->tvaudio);
803		break;
804	}
805	return;
806}
807
808void cx88_newstation(struct cx88_core *core)
809{
810	core->audiomode_manual = UNSET;
811	core->last_change = jiffies;
812}
813
814void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t)
815{
816	static const char * const m[] = { "stereo", "dual mono", "mono", "sap" };
817	static const char * const p[] = { "no pilot", "pilot c1", "pilot c2", "?" };
818	u32 reg, mode, pilot;
819
820	reg = cx_read(AUD_STATUS);
821	mode = reg & 0x03;
822	pilot = (reg >> 2) & 0x03;
823
824	if (core->astat != reg)
825		dprintk("AUD_STATUS: 0x%x [%s/%s] ctl=%s\n",
826			reg, m[mode], p[pilot],
827			aud_ctl_names[cx_read(AUD_CTL) & 63]);
828	core->astat = reg;
829
830	t->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_SAP |
831	    V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
832	t->rxsubchans = UNSET;
833	t->audmode = V4L2_TUNER_MODE_MONO;
834
835	switch (mode) {
836	case 0:
837		t->audmode = V4L2_TUNER_MODE_STEREO;
838		break;
839	case 1:
840		t->audmode = V4L2_TUNER_MODE_LANG2;
841		break;
842	case 2:
843		t->audmode = V4L2_TUNER_MODE_MONO;
844		break;
845	case 3:
846		t->audmode = V4L2_TUNER_MODE_SAP;
847		break;
848	}
849
850	switch (core->tvaudio) {
851	case WW_BTSC:
852	case WW_BG:
853	case WW_DK:
854	case WW_M:
855	case WW_EIAJ:
856		if (!core->use_nicam) {
857			t->rxsubchans = cx88_dsp_detect_stereo_sap(core);
858			break;
859		}
860		break;
861	case WW_NONE:
862	case WW_I:
863	case WW_L:
864	case WW_I2SPT:
865	case WW_FM:
866	case WW_I2SADC:
867		/* nothing */
868		break;
869	}
870
871	/* If software stereo detection is not supported... */
872	if (UNSET == t->rxsubchans) {
873		t->rxsubchans = V4L2_TUNER_SUB_MONO;
874		/* If the hardware itself detected stereo, also return
875		   stereo as an available subchannel */
876		if (V4L2_TUNER_MODE_STEREO == t->audmode)
877			t->rxsubchans |= V4L2_TUNER_SUB_STEREO;
878	}
879	return;
880}
881
882void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual)
883{
884	u32 ctl = UNSET;
885	u32 mask = UNSET;
886
887	if (manual) {
888		core->audiomode_manual = mode;
889	} else {
890		if (UNSET != core->audiomode_manual)
891			return;
892	}
893	core->audiomode_current = mode;
894
895	switch (core->tvaudio) {
896	case WW_BTSC:
897		switch (mode) {
898		case V4L2_TUNER_MODE_MONO:
899			set_audio_standard_BTSC(core, 0, EN_BTSC_FORCE_MONO);
900			break;
901		case V4L2_TUNER_MODE_LANG1:
902			set_audio_standard_BTSC(core, 0, EN_BTSC_AUTO_STEREO);
903			break;
904		case V4L2_TUNER_MODE_LANG2:
905			set_audio_standard_BTSC(core, 1, EN_BTSC_FORCE_SAP);
906			break;
907		case V4L2_TUNER_MODE_STEREO:
908		case V4L2_TUNER_MODE_LANG1_LANG2:
909			set_audio_standard_BTSC(core, 0, EN_BTSC_FORCE_STEREO);
910			break;
911		}
912		break;
913	case WW_BG:
914	case WW_DK:
915	case WW_M:
916	case WW_I:
917	case WW_L:
918		if (1 == core->use_nicam) {
919			switch (mode) {
920			case V4L2_TUNER_MODE_MONO:
921			case V4L2_TUNER_MODE_LANG1:
922				set_audio_standard_NICAM(core,
923							 EN_NICAM_FORCE_MONO1);
924				break;
925			case V4L2_TUNER_MODE_LANG2:
926				set_audio_standard_NICAM(core,
927							 EN_NICAM_FORCE_MONO2);
928				break;
929			case V4L2_TUNER_MODE_STEREO:
930			case V4L2_TUNER_MODE_LANG1_LANG2:
931				set_audio_standard_NICAM(core,
932							 EN_NICAM_FORCE_STEREO);
933				break;
934			}
935		} else {
936			if ((core->tvaudio == WW_I) || (core->tvaudio == WW_L)) {
937				/* fall back to fm / am mono */
938				set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
939			} else {
940				/* TODO: Add A2 autodection */
941				mask = 0x3f;
942				switch (mode) {
943				case V4L2_TUNER_MODE_MONO:
944				case V4L2_TUNER_MODE_LANG1:
945					ctl = EN_A2_FORCE_MONO1;
946					break;
947				case V4L2_TUNER_MODE_LANG2:
948					ctl = EN_A2_FORCE_MONO2;
949					break;
950				case V4L2_TUNER_MODE_STEREO:
951				case V4L2_TUNER_MODE_LANG1_LANG2:
952					ctl = EN_A2_FORCE_STEREO;
953					break;
954				}
955			}
956		}
957		break;
958	case WW_FM:
959		switch (mode) {
960		case V4L2_TUNER_MODE_MONO:
961			ctl = EN_FMRADIO_FORCE_MONO;
962			mask = 0x3f;
963			break;
964		case V4L2_TUNER_MODE_STEREO:
965			ctl = EN_FMRADIO_AUTO_STEREO;
966			mask = 0x3f;
967			break;
968		}
969		break;
970	case WW_I2SADC:
971	case WW_NONE:
972	case WW_EIAJ:
973	case WW_I2SPT:
974		/* DO NOTHING */
975		break;
976	}
977
978	if (UNSET != ctl) {
979		dprintk("cx88_set_stereo: mask 0x%x, ctl 0x%x "
980			"[status=0x%x,ctl=0x%x,vol=0x%x]\n",
981			mask, ctl, cx_read(AUD_STATUS),
982			cx_read(AUD_CTL), cx_sread(SHADOW_AUD_VOL_CTL));
983		cx_andor(AUD_CTL, mask, ctl);
984	}
985	return;
986}
987
988int cx88_audio_thread(void *data)
989{
990	struct cx88_core *core = data;
991	struct v4l2_tuner t;
992	u32 mode = 0;
993
994	dprintk("cx88: tvaudio thread started\n");
995	set_freezable();
996	for (;;) {
997		msleep_interruptible(1000);
998		if (kthread_should_stop())
999			break;
1000		try_to_freeze();
1001
1002		switch (core->tvaudio) {
1003		case WW_BG:
1004		case WW_DK:
1005		case WW_M:
1006		case WW_I:
1007		case WW_L:
1008			if (core->use_nicam)
1009				goto hw_autodetect;
1010
1011			/* just monitor the audio status for now ... */
1012			memset(&t, 0, sizeof(t));
1013			cx88_get_stereo(core, &t);
1014
1015			if (UNSET != core->audiomode_manual)
1016				/* manually set, don't do anything. */
1017				continue;
1018
1019			/* monitor signal and set stereo if available */
1020			if (t.rxsubchans & V4L2_TUNER_SUB_STEREO)
1021				mode = V4L2_TUNER_MODE_STEREO;
1022			else
1023				mode = V4L2_TUNER_MODE_MONO;
1024			if (mode == core->audiomode_current)
1025				continue;
1026			/* automatically switch to best available mode */
1027			cx88_set_stereo(core, mode, 0);
1028			break;
1029		case WW_NONE:
1030		case WW_BTSC:
1031		case WW_EIAJ:
1032		case WW_I2SPT:
1033		case WW_FM:
1034		case WW_I2SADC:
1035hw_autodetect:
1036			/* stereo autodetection is supported by hardware so
1037			   we don't need to do it manually. Do nothing. */
1038			break;
1039		}
1040	}
1041
1042	dprintk("cx88: tvaudio thread exiting\n");
1043	return 0;
1044}
1045
1046/* ----------------------------------------------------------- */
1047
1048EXPORT_SYMBOL(cx88_set_tvaudio);
1049EXPORT_SYMBOL(cx88_newstation);
1050EXPORT_SYMBOL(cx88_set_stereo);
1051EXPORT_SYMBOL(cx88_get_stereo);
1052EXPORT_SYMBOL(cx88_audio_thread);
1053
1054/*
1055 * Local variables:
1056 * c-basic-offset: 8
1057 * End:
1058 * 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
1059 */
1060