• 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/cx18/
1/*
2 *  cx18 ADEC audio functions
3 *
4 *  Derived from cx25840-audio.c
5 *
6 *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
7 *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
8 *
9 *  This program is free software; you can redistribute it and/or
10 *  modify it under the terms of the GNU General Public License
11 *  as published by the Free Software Foundation; either version 2
12 *  of the License, or (at your option) any later version.
13 *
14 *  This program is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this program; if not, write to the Free Software
21 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 *  02110-1301, USA.
23 */
24
25#include "cx18-driver.h"
26
27static int set_audclk_freq(struct cx18 *cx, u32 freq)
28{
29	struct cx18_av_state *state = &cx->av_state;
30
31	if (freq != 32000 && freq != 44100 && freq != 48000)
32		return -EINVAL;
33
34	/*
35	 * The PLL parameters are based on the external crystal frequency that
36	 * would ideally be:
37	 *
38	 * NTSC Color subcarrier freq * 8 =
39	 * 	4.5 MHz/286 * 455/2 * 8 = 28.63636363... MHz
40	 *
41	 * The accidents of history and rationale that explain from where this
42	 * combination of magic numbers originate can be found in:
43	 *
44	 * [1] Abrahams, I. C., "Choice of Chrominance Subcarrier Frequency in
45	 * the NTSC Standards", Proceedings of the I-R-E, January 1954, pp 79-80
46	 *
47	 * [2] Abrahams, I. C., "The 'Frequency Interleaving' Principle in the
48	 * NTSC Standards", Proceedings of the I-R-E, January 1954, pp 81-83
49	 *
50	 * As Mike Bradley has rightly pointed out, it's not the exact crystal
51	 * frequency that matters, only that all parts of the driver and
52	 * firmware are using the same value (close to the ideal value).
53	 *
54	 * Since I have a strong suspicion that, if the firmware ever assumes a
55	 * crystal value at all, it will assume 28.636360 MHz, the crystal
56	 * freq used in calculations in this driver will be:
57	 *
58	 *	xtal_freq = 28.636360 MHz
59	 *
60	 * an error of less than 0.13 ppm which is way, way better than any off
61	 * the shelf crystal will have for accuracy anyway.
62	 *
63	 * Below I aim to run the PLLs' VCOs near 400 MHz to minimze error.
64	 *
65	 * Many thanks to Jeff Campbell and Mike Bradley for their extensive
66	 * investigation, experimentation, testing, and suggested solutions of
67	 * of audio/video sync problems with SVideo and CVBS captures.
68	 */
69
70	if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
71		switch (freq) {
72		case 32000:
73			/*
74			 * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
75			 * AUX_PLL Integer = 0x0d, AUX PLL Post Divider = 0x20
76			 */
77			cx18_av_write4(cx, 0x108, 0x200d040f);
78
79			/* VID_PLL Fraction = 0x2be2fe */
80			/* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/
81			cx18_av_write4(cx, 0x10c, 0x002be2fe);
82
83			/* AUX_PLL Fraction = 0x176740c */
84			/* xtal * 0xd.bb3a060/0x20 = 32000 * 384: 393 MHz p-pd*/
85			cx18_av_write4(cx, 0x110, 0x0176740c);
86
87			/* src3/4/6_ctl */
88			/* 0x1.f77f = (4 * xtal/8*2/455) / 32000 */
89			cx18_av_write4(cx, 0x900, 0x0801f77f);
90			cx18_av_write4(cx, 0x904, 0x0801f77f);
91			cx18_av_write4(cx, 0x90c, 0x0801f77f);
92
93			/* SA_MCLK_SEL=1, SA_MCLK_DIV=0x20 */
94			cx18_av_write(cx, 0x127, 0x60);
95
96			/* AUD_COUNT = 0x2fff = 8 samples * 4 * 384 - 1 */
97			cx18_av_write4(cx, 0x12c, 0x11202fff);
98
99			/*
100			 * EN_AV_LOCK = 0
101			 * VID_COUNT = 0x0d2ef8 = 107999.000 * 8 =
102			 *  ((8 samples/32,000) * (13,500,000 * 8) * 4 - 1) * 8
103			 */
104			cx18_av_write4(cx, 0x128, 0xa00d2ef8);
105			break;
106
107		case 44100:
108			/*
109			 * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
110			 * AUX_PLL Integer = 0x0e, AUX PLL Post Divider = 0x18
111			 */
112			cx18_av_write4(cx, 0x108, 0x180e040f);
113
114			/* VID_PLL Fraction = 0x2be2fe */
115			/* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/
116			cx18_av_write4(cx, 0x10c, 0x002be2fe);
117
118			/* AUX_PLL Fraction = 0x062a1f2 */
119			/* xtal * 0xe.3150f90/0x18 = 44100 * 384: 406 MHz p-pd*/
120			cx18_av_write4(cx, 0x110, 0x0062a1f2);
121
122			/* src3/4/6_ctl */
123			/* 0x1.6d59 = (4 * xtal/8*2/455) / 44100 */
124			cx18_av_write4(cx, 0x900, 0x08016d59);
125			cx18_av_write4(cx, 0x904, 0x08016d59);
126			cx18_av_write4(cx, 0x90c, 0x08016d59);
127
128			/* SA_MCLK_SEL=1, SA_MCLK_DIV=0x18 */
129			cx18_av_write(cx, 0x127, 0x58);
130
131			/* AUD_COUNT = 0x92ff = 49 samples * 2 * 384 - 1 */
132			cx18_av_write4(cx, 0x12c, 0x112092ff);
133
134			/*
135			 * EN_AV_LOCK = 0
136			 * VID_COUNT = 0x1d4bf8 = 239999.000 * 8 =
137			 *  ((49 samples/44,100) * (13,500,000 * 8) * 2 - 1) * 8
138			 */
139			cx18_av_write4(cx, 0x128, 0xa01d4bf8);
140			break;
141
142		case 48000:
143			/*
144			 * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
145			 * AUX_PLL Integer = 0x0e, AUX PLL Post Divider = 0x16
146			 */
147			cx18_av_write4(cx, 0x108, 0x160e040f);
148
149			/* VID_PLL Fraction = 0x2be2fe */
150			/* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/
151			cx18_av_write4(cx, 0x10c, 0x002be2fe);
152
153			/* AUX_PLL Fraction = 0x05227ad */
154			/* xtal * 0xe.2913d68/0x16 = 48000 * 384: 406 MHz p-pd*/
155			cx18_av_write4(cx, 0x110, 0x005227ad);
156
157			/* src3/4/6_ctl */
158			/* 0x1.4faa = (4 * xtal/8*2/455) / 48000 */
159			cx18_av_write4(cx, 0x900, 0x08014faa);
160			cx18_av_write4(cx, 0x904, 0x08014faa);
161			cx18_av_write4(cx, 0x90c, 0x08014faa);
162
163			/* SA_MCLK_SEL=1, SA_MCLK_DIV=0x16 */
164			cx18_av_write(cx, 0x127, 0x56);
165
166			/* AUD_COUNT = 0x5fff = 4 samples * 16 * 384 - 1 */
167			cx18_av_write4(cx, 0x12c, 0x11205fff);
168
169			/*
170			 * EN_AV_LOCK = 0
171			 * VID_COUNT = 0x1193f8 = 143999.000 * 8 =
172			 *  ((4 samples/48,000) * (13,500,000 * 8) * 16 - 1) * 8
173			 */
174			cx18_av_write4(cx, 0x128, 0xa01193f8);
175			break;
176		}
177	} else {
178		switch (freq) {
179		case 32000:
180			/*
181			 * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
182			 * AUX_PLL Integer = 0x0d, AUX PLL Post Divider = 0x30
183			 */
184			cx18_av_write4(cx, 0x108, 0x300d040f);
185
186			/* VID_PLL Fraction = 0x2be2fe */
187			/* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/
188			cx18_av_write4(cx, 0x10c, 0x002be2fe);
189
190			/* AUX_PLL Fraction = 0x176740c */
191			/* xtal * 0xd.bb3a060/0x30 = 32000 * 256: 393 MHz p-pd*/
192			cx18_av_write4(cx, 0x110, 0x0176740c);
193
194			/* src1_ctl */
195			/* 0x1.0000 = 32000/32000 */
196			cx18_av_write4(cx, 0x8f8, 0x08010000);
197
198			/* src3/4/6_ctl */
199			/* 0x2.0000 = 2 * (32000/32000) */
200			cx18_av_write4(cx, 0x900, 0x08020000);
201			cx18_av_write4(cx, 0x904, 0x08020000);
202			cx18_av_write4(cx, 0x90c, 0x08020000);
203
204			/* SA_MCLK_SEL=1, SA_MCLK_DIV=0x30 */
205			cx18_av_write(cx, 0x127, 0x70);
206
207			/* AUD_COUNT = 0x1fff = 8 samples * 4 * 256 - 1 */
208			cx18_av_write4(cx, 0x12c, 0x11201fff);
209
210			/*
211			 * EN_AV_LOCK = 0
212			 * VID_COUNT = 0x0d2ef8 = 107999.000 * 8 =
213			 *  ((8 samples/32,000) * (13,500,000 * 8) * 4 - 1) * 8
214			 */
215			cx18_av_write4(cx, 0x128, 0xa00d2ef8);
216			break;
217
218		case 44100:
219			/*
220			 * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
221			 * AUX_PLL Integer = 0x0e, AUX PLL Post Divider = 0x24
222			 */
223			cx18_av_write4(cx, 0x108, 0x240e040f);
224
225			/* VID_PLL Fraction = 0x2be2fe */
226			/* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/
227			cx18_av_write4(cx, 0x10c, 0x002be2fe);
228
229			/* AUX_PLL Fraction = 0x062a1f2 */
230			/* xtal * 0xe.3150f90/0x24 = 44100 * 256: 406 MHz p-pd*/
231			cx18_av_write4(cx, 0x110, 0x0062a1f2);
232
233			/* src1_ctl */
234			/* 0x1.60cd = 44100/32000 */
235			cx18_av_write4(cx, 0x8f8, 0x080160cd);
236
237			/* src3/4/6_ctl */
238			/* 0x1.7385 = 2 * (32000/44100) */
239			cx18_av_write4(cx, 0x900, 0x08017385);
240			cx18_av_write4(cx, 0x904, 0x08017385);
241			cx18_av_write4(cx, 0x90c, 0x08017385);
242
243			/* SA_MCLK_SEL=1, SA_MCLK_DIV=0x24 */
244			cx18_av_write(cx, 0x127, 0x64);
245
246			/* AUD_COUNT = 0x61ff = 49 samples * 2 * 256 - 1 */
247			cx18_av_write4(cx, 0x12c, 0x112061ff);
248
249			/*
250			 * EN_AV_LOCK = 0
251			 * VID_COUNT = 0x1d4bf8 = 239999.000 * 8 =
252			 *  ((49 samples/44,100) * (13,500,000 * 8) * 2 - 1) * 8
253			 */
254			cx18_av_write4(cx, 0x128, 0xa01d4bf8);
255			break;
256
257		case 48000:
258			/*
259			 * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
260			 * AUX_PLL Integer = 0x0d, AUX PLL Post Divider = 0x20
261			 */
262			cx18_av_write4(cx, 0x108, 0x200d040f);
263
264			/* VID_PLL Fraction = 0x2be2fe */
265			/* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/
266			cx18_av_write4(cx, 0x10c, 0x002be2fe);
267
268			/* AUX_PLL Fraction = 0x176740c */
269			/* xtal * 0xd.bb3a060/0x20 = 48000 * 256: 393 MHz p-pd*/
270			cx18_av_write4(cx, 0x110, 0x0176740c);
271
272			/* src1_ctl */
273			/* 0x1.8000 = 48000/32000 */
274			cx18_av_write4(cx, 0x8f8, 0x08018000);
275
276			/* src3/4/6_ctl */
277			/* 0x1.5555 = 2 * (32000/48000) */
278			cx18_av_write4(cx, 0x900, 0x08015555);
279			cx18_av_write4(cx, 0x904, 0x08015555);
280			cx18_av_write4(cx, 0x90c, 0x08015555);
281
282			/* SA_MCLK_SEL=1, SA_MCLK_DIV=0x20 */
283			cx18_av_write(cx, 0x127, 0x60);
284
285			/* AUD_COUNT = 0x3fff = 4 samples * 16 * 256 - 1 */
286			cx18_av_write4(cx, 0x12c, 0x11203fff);
287
288			/*
289			 * EN_AV_LOCK = 0
290			 * VID_COUNT = 0x1193f8 = 143999.000 * 8 =
291			 *  ((4 samples/48,000) * (13,500,000 * 8) * 16 - 1) * 8
292			 */
293			cx18_av_write4(cx, 0x128, 0xa01193f8);
294			break;
295		}
296	}
297
298	state->audclk_freq = freq;
299
300	return 0;
301}
302
303void cx18_av_audio_set_path(struct cx18 *cx)
304{
305	struct cx18_av_state *state = &cx->av_state;
306	u8 v;
307
308	/* stop microcontroller */
309	v = cx18_av_read(cx, 0x803) & ~0x10;
310	cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
311
312	/* assert soft reset */
313	v = cx18_av_read(cx, 0x810) | 0x01;
314	cx18_av_write_expect(cx, 0x810, v, v, 0x0f);
315
316	/* Mute everything to prevent the PFFT! */
317	cx18_av_write(cx, 0x8d3, 0x1f);
318
319	if (state->aud_input <= CX18_AV_AUDIO_SERIAL2) {
320		/* Set Path1 to Serial Audio Input */
321		cx18_av_write4(cx, 0x8d0, 0x01011012);
322
323		/* The microcontroller should not be started for the
324		 * non-tuner inputs: autodetection is specific for
325		 * TV audio. */
326	} else {
327		/* Set Path1 to Analog Demod Main Channel */
328		cx18_av_write4(cx, 0x8d0, 0x1f063870);
329	}
330
331	set_audclk_freq(cx, state->audclk_freq);
332
333	/* deassert soft reset */
334	v = cx18_av_read(cx, 0x810) & ~0x01;
335	cx18_av_write_expect(cx, 0x810, v, v, 0x0f);
336
337	if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
338		/* When the microcontroller detects the
339		 * audio format, it will unmute the lines */
340		v = cx18_av_read(cx, 0x803) | 0x10;
341		cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
342	}
343}
344
345static int get_volume(struct cx18 *cx)
346{
347	/* Volume runs +18dB to -96dB in 1/2dB steps
348	 * change to fit the msp3400 -114dB to +12dB range */
349
350	/* check PATH1_VOLUME */
351	int vol = 228 - cx18_av_read(cx, 0x8d4);
352	vol = (vol / 2) + 23;
353	return vol << 9;
354}
355
356static void set_volume(struct cx18 *cx, int volume)
357{
358	/* First convert the volume to msp3400 values (0-127) */
359	int vol = volume >> 9;
360	/* now scale it up to cx18_av values
361	 * -114dB to -96dB maps to 0
362	 * this should be 19, but in my testing that was 4dB too loud */
363	if (vol <= 23)
364		vol = 0;
365	else
366		vol -= 23;
367
368	/* PATH1_VOLUME */
369	cx18_av_write(cx, 0x8d4, 228 - (vol * 2));
370}
371
372static int get_bass(struct cx18 *cx)
373{
374	/* bass is 49 steps +12dB to -12dB */
375
376	/* check PATH1_EQ_BASS_VOL */
377	int bass = cx18_av_read(cx, 0x8d9) & 0x3f;
378	bass = (((48 - bass) * 0xffff) + 47) / 48;
379	return bass;
380}
381
382static void set_bass(struct cx18 *cx, int bass)
383{
384	/* PATH1_EQ_BASS_VOL */
385	cx18_av_and_or(cx, 0x8d9, ~0x3f, 48 - (bass * 48 / 0xffff));
386}
387
388static int get_treble(struct cx18 *cx)
389{
390	/* treble is 49 steps +12dB to -12dB */
391
392	/* check PATH1_EQ_TREBLE_VOL */
393	int treble = cx18_av_read(cx, 0x8db) & 0x3f;
394	treble = (((48 - treble) * 0xffff) + 47) / 48;
395	return treble;
396}
397
398static void set_treble(struct cx18 *cx, int treble)
399{
400	/* PATH1_EQ_TREBLE_VOL */
401	cx18_av_and_or(cx, 0x8db, ~0x3f, 48 - (treble * 48 / 0xffff));
402}
403
404static int get_balance(struct cx18 *cx)
405{
406	/* balance is 7 bit, 0 to -96dB */
407
408	/* check PATH1_BAL_LEVEL */
409	int balance = cx18_av_read(cx, 0x8d5) & 0x7f;
410	/* check PATH1_BAL_LEFT */
411	if ((cx18_av_read(cx, 0x8d5) & 0x80) == 0)
412		balance = 0x80 - balance;
413	else
414		balance = 0x80 + balance;
415	return balance << 8;
416}
417
418static void set_balance(struct cx18 *cx, int balance)
419{
420	int bal = balance >> 8;
421	if (bal > 0x80) {
422		/* PATH1_BAL_LEFT */
423		cx18_av_and_or(cx, 0x8d5, 0x7f, 0x80);
424		/* PATH1_BAL_LEVEL */
425		cx18_av_and_or(cx, 0x8d5, ~0x7f, bal & 0x7f);
426	} else {
427		/* PATH1_BAL_LEFT */
428		cx18_av_and_or(cx, 0x8d5, 0x7f, 0x00);
429		/* PATH1_BAL_LEVEL */
430		cx18_av_and_or(cx, 0x8d5, ~0x7f, 0x80 - bal);
431	}
432}
433
434static int get_mute(struct cx18 *cx)
435{
436	/* check SRC1_MUTE_EN */
437	return cx18_av_read(cx, 0x8d3) & 0x2 ? 1 : 0;
438}
439
440static void set_mute(struct cx18 *cx, int mute)
441{
442	struct cx18_av_state *state = &cx->av_state;
443	u8 v;
444
445	if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
446		/* Must turn off microcontroller in order to mute sound.
447		 * Not sure if this is the best method, but it does work.
448		 * If the microcontroller is running, then it will undo any
449		 * changes to the mute register. */
450		v = cx18_av_read(cx, 0x803);
451		if (mute) {
452			/* disable microcontroller */
453			v &= ~0x10;
454			cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
455			cx18_av_write(cx, 0x8d3, 0x1f);
456		} else {
457			/* enable microcontroller */
458			v |= 0x10;
459			cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
460		}
461	} else {
462		/* SRC1_MUTE_EN */
463		cx18_av_and_or(cx, 0x8d3, ~0x2, mute ? 0x02 : 0x00);
464	}
465}
466
467int cx18_av_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
468{
469	struct cx18 *cx = v4l2_get_subdevdata(sd);
470	struct cx18_av_state *state = &cx->av_state;
471	int retval;
472	u8 v;
473
474	if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
475		v = cx18_av_read(cx, 0x803) & ~0x10;
476		cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
477		cx18_av_write(cx, 0x8d3, 0x1f);
478	}
479	v = cx18_av_read(cx, 0x810) | 0x1;
480	cx18_av_write_expect(cx, 0x810, v, v, 0x0f);
481
482	retval = set_audclk_freq(cx, freq);
483
484	v = cx18_av_read(cx, 0x810) & ~0x1;
485	cx18_av_write_expect(cx, 0x810, v, v, 0x0f);
486	if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
487		v = cx18_av_read(cx, 0x803) | 0x10;
488		cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
489	}
490	return retval;
491}
492
493int cx18_av_audio_g_ctrl(struct cx18 *cx, struct v4l2_control *ctrl)
494{
495	switch (ctrl->id) {
496	case V4L2_CID_AUDIO_VOLUME:
497		ctrl->value = get_volume(cx);
498		break;
499	case V4L2_CID_AUDIO_BASS:
500		ctrl->value = get_bass(cx);
501		break;
502	case V4L2_CID_AUDIO_TREBLE:
503		ctrl->value = get_treble(cx);
504		break;
505	case V4L2_CID_AUDIO_BALANCE:
506		ctrl->value = get_balance(cx);
507		break;
508	case V4L2_CID_AUDIO_MUTE:
509		ctrl->value = get_mute(cx);
510		break;
511	default:
512		return -EINVAL;
513	}
514	return 0;
515}
516
517int cx18_av_audio_s_ctrl(struct cx18 *cx, struct v4l2_control *ctrl)
518{
519	switch (ctrl->id) {
520	case V4L2_CID_AUDIO_VOLUME:
521		set_volume(cx, ctrl->value);
522		break;
523	case V4L2_CID_AUDIO_BASS:
524		set_bass(cx, ctrl->value);
525		break;
526	case V4L2_CID_AUDIO_TREBLE:
527		set_treble(cx, ctrl->value);
528		break;
529	case V4L2_CID_AUDIO_BALANCE:
530		set_balance(cx, ctrl->value);
531		break;
532	case V4L2_CID_AUDIO_MUTE:
533		set_mute(cx, ctrl->value);
534		break;
535	default:
536		return -EINVAL;
537	}
538	return 0;
539}
540