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