GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / drivers / media / video / cx25840 / cx25840-audio.c
blob0052d6a0d9406ea9b1d2c70bce07482dcbc16173
1 /* cx25840 audio functions
3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU General Public License
5 * as published by the Free Software Foundation; either version 2
6 * of the License, or (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 #include <linux/videodev2.h>
20 #include <linux/i2c.h>
21 #include <media/v4l2-common.h>
22 #include <media/cx25840.h>
24 #include "cx25840-core.h"
27 * Note: The PLL and SRC parameters are based on a reference frequency that
28 * would ideally be:
30 * NTSC Color subcarrier freq * 8 = 4.5 MHz/286 * 455/2 * 8 = 28.63636363... MHz
32 * However, it's not the exact reference frequency that matters, only that the
33 * firmware and modules that comprise the driver for a particular board all
34 * use the same value (close to the ideal value).
36 * Comments below will note which reference frequency is assumed for various
37 * parameters. They will usually be one of
39 * ref_freq = 28.636360 MHz
40 * or
41 * ref_freq = 28.636363 MHz
44 static int cx25840_set_audclk_freq(struct i2c_client *client, u32 freq)
46 struct cx25840_state *state = to_state(i2c_get_clientdata(client));
48 if (state->aud_input != CX25840_AUDIO_SERIAL) {
49 switch (freq) {
50 case 32000:
52 * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
53 * AUX_PLL Integer = 0x06, AUX PLL Post Divider = 0x10
55 cx25840_write4(client, 0x108, 0x1006040f);
58 * VID_PLL Fraction (register 0x10c) = 0x2be2fe
59 * 28636360 * 0xf.15f17f0/4 = 108 MHz
60 * 432 MHz pre-postdivide
63 cx25840_write4(client, 0x110, 0x01bb39ee);
66 * SA_MCLK_SEL = 1
67 * SA_MCLK_DIV = 0x10 = 384/384 * AUX_PLL post dvivider
69 cx25840_write(client, 0x127, 0x50);
71 if (is_cx2583x(state))
72 break;
74 /* src3/4/6_ctl */
75 /* 0x1.f77f = (4 * 28636360/8 * 2/455) / 32000 */
76 cx25840_write4(client, 0x900, 0x0801f77f);
77 cx25840_write4(client, 0x904, 0x0801f77f);
78 cx25840_write4(client, 0x90c, 0x0801f77f);
79 break;
81 case 44100:
83 * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
84 * AUX_PLL Integer = 0x09, AUX PLL Post Divider = 0x10
86 cx25840_write4(client, 0x108, 0x1009040f);
89 * VID_PLL Fraction (register 0x10c) = 0x2be2fe
90 * 28636360 * 0xf.15f17f0/4 = 108 MHz
91 * 432 MHz pre-postdivide
94 cx25840_write4(client, 0x110, 0x00ec6bd6);
97 * SA_MCLK_SEL = 1
98 * SA_MCLK_DIV = 0x10 = 384/384 * AUX_PLL post dvivider
100 cx25840_write(client, 0x127, 0x50);
102 if (is_cx2583x(state))
103 break;
105 /* src3/4/6_ctl */
106 /* 0x1.6d59 = (4 * 28636360/8 * 2/455) / 44100 */
107 cx25840_write4(client, 0x900, 0x08016d59);
108 cx25840_write4(client, 0x904, 0x08016d59);
109 cx25840_write4(client, 0x90c, 0x08016d59);
110 break;
112 case 48000:
114 * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
115 * AUX_PLL Integer = 0x0a, AUX PLL Post Divider = 0x10
117 cx25840_write4(client, 0x108, 0x100a040f);
120 * VID_PLL Fraction (register 0x10c) = 0x2be2fe
121 * 28636360 * 0xf.15f17f0/4 = 108 MHz
122 * 432 MHz pre-postdivide
125 cx25840_write4(client, 0x110, 0x0098d6e5);
128 * SA_MCLK_SEL = 1
129 * SA_MCLK_DIV = 0x10 = 384/384 * AUX_PLL post dvivider
131 cx25840_write(client, 0x127, 0x50);
133 if (is_cx2583x(state))
134 break;
136 /* src3/4/6_ctl */
137 /* 0x1.4faa = (4 * 28636360/8 * 2/455) / 48000 */
138 cx25840_write4(client, 0x900, 0x08014faa);
139 cx25840_write4(client, 0x904, 0x08014faa);
140 cx25840_write4(client, 0x90c, 0x08014faa);
141 break;
143 } else {
144 switch (freq) {
145 case 32000:
147 * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
148 * AUX_PLL Integer = 0x08, AUX PLL Post Divider = 0x1e
150 cx25840_write4(client, 0x108, 0x1e08040f);
153 * VID_PLL Fraction (register 0x10c) = 0x2be2fe
154 * 28636360 * 0xf.15f17f0/4 = 108 MHz
155 * 432 MHz pre-postdivide
158 cx25840_write4(client, 0x110, 0x012a0869);
161 * SA_MCLK_SEL = 1
162 * SA_MCLK_DIV = 0x14 = 256/384 * AUX_PLL post dvivider
164 cx25840_write(client, 0x127, 0x54);
166 if (is_cx2583x(state))
167 break;
169 /* src1_ctl */
170 /* 0x1.0000 = 32000/32000 */
171 cx25840_write4(client, 0x8f8, 0x08010000);
173 /* src3/4/6_ctl */
174 /* 0x2.0000 = 2 * (32000/32000) */
175 cx25840_write4(client, 0x900, 0x08020000);
176 cx25840_write4(client, 0x904, 0x08020000);
177 cx25840_write4(client, 0x90c, 0x08020000);
178 break;
180 case 44100:
182 * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
183 * AUX_PLL Integer = 0x09, AUX PLL Post Divider = 0x18
185 cx25840_write4(client, 0x108, 0x1809040f);
188 * VID_PLL Fraction (register 0x10c) = 0x2be2fe
189 * 28636360 * 0xf.15f17f0/4 = 108 MHz
190 * 432 MHz pre-postdivide
193 cx25840_write4(client, 0x110, 0x00ec6bd6);
196 * SA_MCLK_SEL = 1
197 * SA_MCLK_DIV = 0x10 = 256/384 * AUX_PLL post dvivider
199 cx25840_write(client, 0x127, 0x50);
201 if (is_cx2583x(state))
202 break;
204 /* src1_ctl */
205 /* 0x1.60cd = 44100/32000 */
206 cx25840_write4(client, 0x8f8, 0x080160cd);
208 /* src3/4/6_ctl */
209 /* 0x1.7385 = 2 * (32000/44100) */
210 cx25840_write4(client, 0x900, 0x08017385);
211 cx25840_write4(client, 0x904, 0x08017385);
212 cx25840_write4(client, 0x90c, 0x08017385);
213 break;
215 case 48000:
217 * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
218 * AUX_PLL Integer = 0x0a, AUX PLL Post Divider = 0x18
220 cx25840_write4(client, 0x108, 0x180a040f);
223 * VID_PLL Fraction (register 0x10c) = 0x2be2fe
224 * 28636360 * 0xf.15f17f0/4 = 108 MHz
225 * 432 MHz pre-postdivide
228 cx25840_write4(client, 0x110, 0x0098d6e5);
231 * SA_MCLK_SEL = 1
232 * SA_MCLK_DIV = 0x10 = 256/384 * AUX_PLL post dvivider
234 cx25840_write(client, 0x127, 0x50);
236 if (is_cx2583x(state))
237 break;
239 /* src1_ctl */
240 /* 0x1.8000 = 48000/32000 */
241 cx25840_write4(client, 0x8f8, 0x08018000);
243 /* src3/4/6_ctl */
244 /* 0x1.5555 = 2 * (32000/48000) */
245 cx25840_write4(client, 0x900, 0x08015555);
246 cx25840_write4(client, 0x904, 0x08015555);
247 cx25840_write4(client, 0x90c, 0x08015555);
248 break;
252 state->audclk_freq = freq;
254 return 0;
257 static inline int cx25836_set_audclk_freq(struct i2c_client *client, u32 freq)
259 return cx25840_set_audclk_freq(client, freq);
262 static int cx23885_set_audclk_freq(struct i2c_client *client, u32 freq)
264 struct cx25840_state *state = to_state(i2c_get_clientdata(client));
266 if (state->aud_input != CX25840_AUDIO_SERIAL) {
267 switch (freq) {
268 case 32000:
269 case 44100:
270 case 48000:
271 /* We don't have register values
272 * so avoid destroying registers. */
273 break;
275 } else {
276 switch (freq) {
277 case 32000:
278 case 44100:
279 /* We don't have register values
280 * so avoid destroying registers. */
281 break;
283 case 48000:
284 /* src1_ctl */
285 /* 0x1.867c = 48000 / (2 * 28636360/8 * 2/455) */
286 cx25840_write4(client, 0x8f8, 0x0801867c);
288 /* src3/4/6_ctl */
289 /* 0x1.4faa = (4 * 28636360/8 * 2/455) / 48000 */
290 cx25840_write4(client, 0x900, 0x08014faa);
291 cx25840_write4(client, 0x904, 0x08014faa);
292 cx25840_write4(client, 0x90c, 0x08014faa);
293 break;
297 state->audclk_freq = freq;
299 return 0;
302 static int cx231xx_set_audclk_freq(struct i2c_client *client, u32 freq)
304 struct cx25840_state *state = to_state(i2c_get_clientdata(client));
306 if (state->aud_input != CX25840_AUDIO_SERIAL) {
307 switch (freq) {
308 case 32000:
309 /* src3/4/6_ctl */
310 /* 0x1.f77f = (4 * 28636360/8 * 2/455) / 32000 */
311 cx25840_write4(client, 0x900, 0x0801f77f);
312 cx25840_write4(client, 0x904, 0x0801f77f);
313 cx25840_write4(client, 0x90c, 0x0801f77f);
314 break;
316 case 44100:
317 /* src3/4/6_ctl */
318 /* 0x1.6d59 = (4 * 28636360/8 * 2/455) / 44100 */
319 cx25840_write4(client, 0x900, 0x08016d59);
320 cx25840_write4(client, 0x904, 0x08016d59);
321 cx25840_write4(client, 0x90c, 0x08016d59);
322 break;
324 case 48000:
325 /* src3/4/6_ctl */
326 /* 0x1.4faa = (4 * 28636360/8 * 2/455) / 48000 */
327 cx25840_write4(client, 0x900, 0x08014faa);
328 cx25840_write4(client, 0x904, 0x08014faa);
329 cx25840_write4(client, 0x90c, 0x08014faa);
330 break;
332 } else {
333 switch (freq) {
334 case 32000:
335 /* src1_ctl */
336 /* 0x1.0000 = 32000/32000 */
337 cx25840_write4(client, 0x8f8, 0x08010000);
339 /* src3/4/6_ctl */
340 /* 0x2.0000 = 2 * (32000/32000) */
341 cx25840_write4(client, 0x900, 0x08020000);
342 cx25840_write4(client, 0x904, 0x08020000);
343 cx25840_write4(client, 0x90c, 0x08020000);
344 break;
346 case 44100:
347 /* src1_ctl */
348 /* 0x1.60cd = 44100/32000 */
349 cx25840_write4(client, 0x8f8, 0x080160cd);
351 /* src3/4/6_ctl */
352 /* 0x1.7385 = 2 * (32000/44100) */
353 cx25840_write4(client, 0x900, 0x08017385);
354 cx25840_write4(client, 0x904, 0x08017385);
355 cx25840_write4(client, 0x90c, 0x08017385);
356 break;
358 case 48000:
359 /* src1_ctl */
360 /* 0x1.867c = 48000 / (2 * 28636360/8 * 2/455) */
361 cx25840_write4(client, 0x8f8, 0x0801867c);
363 /* src3/4/6_ctl */
364 /* 0x1.4faa = (4 * 28636360/8 * 2/455) / 48000 */
365 cx25840_write4(client, 0x900, 0x08014faa);
366 cx25840_write4(client, 0x904, 0x08014faa);
367 cx25840_write4(client, 0x90c, 0x08014faa);
368 break;
372 state->audclk_freq = freq;
374 return 0;
377 static int set_audclk_freq(struct i2c_client *client, u32 freq)
379 struct cx25840_state *state = to_state(i2c_get_clientdata(client));
381 if (freq != 32000 && freq != 44100 && freq != 48000)
382 return -EINVAL;
384 if (is_cx231xx(state))
385 return cx231xx_set_audclk_freq(client, freq);
387 if (is_cx2388x(state))
388 return cx23885_set_audclk_freq(client, freq);
390 if (is_cx2583x(state))
391 return cx25836_set_audclk_freq(client, freq);
393 return cx25840_set_audclk_freq(client, freq);
396 void cx25840_audio_set_path(struct i2c_client *client)
398 struct cx25840_state *state = to_state(i2c_get_clientdata(client));
400 /* assert soft reset */
401 cx25840_and_or(client, 0x810, ~0x1, 0x01);
403 /* stop microcontroller */
404 cx25840_and_or(client, 0x803, ~0x10, 0);
406 /* Mute everything to prevent the PFFT! */
407 cx25840_write(client, 0x8d3, 0x1f);
409 if (state->aud_input == CX25840_AUDIO_SERIAL) {
410 /* Set Path1 to Serial Audio Input */
411 cx25840_write4(client, 0x8d0, 0x01011012);
413 /* The microcontroller should not be started for the
414 * non-tuner inputs: autodetection is specific for
415 * TV audio. */
416 } else {
417 /* Set Path1 to Analog Demod Main Channel */
418 cx25840_write4(client, 0x8d0, 0x1f063870);
421 set_audclk_freq(client, state->audclk_freq);
423 if (state->aud_input != CX25840_AUDIO_SERIAL) {
424 /* When the microcontroller detects the
425 * audio format, it will unmute the lines */
426 cx25840_and_or(client, 0x803, ~0x10, 0x10);
429 /* deassert soft reset */
430 cx25840_and_or(client, 0x810, ~0x1, 0x00);
432 /* Ensure the controller is running when we exit */
433 if (is_cx2388x(state) || is_cx231xx(state))
434 cx25840_and_or(client, 0x803, ~0x10, 0x10);
437 static void set_volume(struct i2c_client *client, int volume)
439 int vol;
441 /* Convert the volume to msp3400 values (0-127) */
442 vol = volume >> 9;
444 /* now scale it up to cx25840 values
445 * -114dB to -96dB maps to 0
446 * this should be 19, but in my testing that was 4dB too loud */
447 if (vol <= 23) {
448 vol = 0;
449 } else {
450 vol -= 23;
453 /* PATH1_VOLUME */
454 cx25840_write(client, 0x8d4, 228 - (vol * 2));
457 static void set_balance(struct i2c_client *client, int balance)
459 int bal = balance >> 8;
460 if (bal > 0x80) {
461 /* PATH1_BAL_LEFT */
462 cx25840_and_or(client, 0x8d5, 0x7f, 0x80);
463 /* PATH1_BAL_LEVEL */
464 cx25840_and_or(client, 0x8d5, ~0x7f, bal & 0x7f);
465 } else {
466 /* PATH1_BAL_LEFT */
467 cx25840_and_or(client, 0x8d5, 0x7f, 0x00);
468 /* PATH1_BAL_LEVEL */
469 cx25840_and_or(client, 0x8d5, ~0x7f, 0x80 - bal);
473 int cx25840_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
475 struct i2c_client *client = v4l2_get_subdevdata(sd);
476 struct cx25840_state *state = to_state(sd);
477 int retval;
479 if (!is_cx2583x(state))
480 cx25840_and_or(client, 0x810, ~0x1, 1);
481 if (state->aud_input != CX25840_AUDIO_SERIAL) {
482 cx25840_and_or(client, 0x803, ~0x10, 0);
483 cx25840_write(client, 0x8d3, 0x1f);
485 retval = set_audclk_freq(client, freq);
486 if (state->aud_input != CX25840_AUDIO_SERIAL)
487 cx25840_and_or(client, 0x803, ~0x10, 0x10);
488 if (!is_cx2583x(state))
489 cx25840_and_or(client, 0x810, ~0x1, 0);
490 return retval;
493 static int cx25840_audio_s_ctrl(struct v4l2_ctrl *ctrl)
495 struct v4l2_subdev *sd = to_sd(ctrl);
496 struct cx25840_state *state = to_state(sd);
497 struct i2c_client *client = v4l2_get_subdevdata(sd);
499 switch (ctrl->id) {
500 case V4L2_CID_AUDIO_VOLUME:
501 if (state->mute->val)
502 set_volume(client, 0);
503 else
504 set_volume(client, state->volume->val);
505 break;
506 case V4L2_CID_AUDIO_BASS:
507 /* PATH1_EQ_BASS_VOL */
508 cx25840_and_or(client, 0x8d9, ~0x3f,
509 48 - (ctrl->val * 48 / 0xffff));
510 break;
511 case V4L2_CID_AUDIO_TREBLE:
512 /* PATH1_EQ_TREBLE_VOL */
513 cx25840_and_or(client, 0x8db, ~0x3f,
514 48 - (ctrl->val * 48 / 0xffff));
515 break;
516 case V4L2_CID_AUDIO_BALANCE:
517 set_balance(client, ctrl->val);
518 break;
519 default:
520 return -EINVAL;
522 return 0;
525 const struct v4l2_ctrl_ops cx25840_audio_ctrl_ops = {
526 .s_ctrl = cx25840_audio_s_ctrl,