1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#include <linux/videodev2.h>
20#include <linux/i2c.h>
21#include <media/v4l2-common.h>
22#include <media/cx25840.h>
23
24#include "cx25840-core.h"
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44static int cx25840_set_audclk_freq(struct i2c_client *client, u32 freq)
45{
46 struct cx25840_state *state = to_state(i2c_get_clientdata(client));
47
48 if (state->aud_input != CX25840_AUDIO_SERIAL) {
49 switch (freq) {
50 case 32000:
51
52
53
54
55 cx25840_write4(client, 0x108, 0x1006040f);
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70 cx25840_write4(client, 0x110, 0x01bb39ee);
71
72
73
74
75
76 cx25840_write(client, 0x127, 0x50);
77
78 if (is_cx2583x(state))
79 break;
80
81
82
83 cx25840_write4(client, 0x900, 0x0801f77f);
84 cx25840_write4(client, 0x904, 0x0801f77f);
85 cx25840_write4(client, 0x90c, 0x0801f77f);
86 break;
87
88 case 44100:
89
90
91
92
93 cx25840_write4(client, 0x108, 0x1009040f);
94
95
96
97
98
99
100
101
102
103
104
105
106
107 cx25840_write4(client, 0x110, 0x00ec6bd6);
108
109
110
111
112
113 cx25840_write(client, 0x127, 0x50);
114
115 if (is_cx2583x(state))
116 break;
117
118
119
120 cx25840_write4(client, 0x900, 0x08016d59);
121 cx25840_write4(client, 0x904, 0x08016d59);
122 cx25840_write4(client, 0x90c, 0x08016d59);
123 break;
124
125 case 48000:
126
127
128
129
130 cx25840_write4(client, 0x108, 0x100a040f);
131
132
133
134
135
136
137
138
139
140
141
142
143
144 cx25840_write4(client, 0x110, 0x0098d6e5);
145
146
147
148
149
150 cx25840_write(client, 0x127, 0x50);
151
152 if (is_cx2583x(state))
153 break;
154
155
156
157 cx25840_write4(client, 0x900, 0x08014faa);
158 cx25840_write4(client, 0x904, 0x08014faa);
159 cx25840_write4(client, 0x90c, 0x08014faa);
160 break;
161 }
162 } else {
163 switch (freq) {
164 case 32000:
165
166
167
168
169 cx25840_write4(client, 0x108, 0x1e08040f);
170
171
172
173
174
175
176
177
178
179
180
181
182
183 cx25840_write4(client, 0x110, 0x012a0869);
184
185
186
187
188
189 cx25840_write(client, 0x127, 0x54);
190
191 if (is_cx2583x(state))
192 break;
193
194
195
196 cx25840_write4(client, 0x8f8, 0x08010000);
197
198
199
200 cx25840_write4(client, 0x900, 0x08020000);
201 cx25840_write4(client, 0x904, 0x08020000);
202 cx25840_write4(client, 0x90c, 0x08020000);
203 break;
204
205 case 44100:
206
207
208
209
210 cx25840_write4(client, 0x108, 0x1809040f);
211
212
213
214
215
216
217
218
219
220
221
222
223
224 cx25840_write4(client, 0x110, 0x00ec6bd6);
225
226
227
228
229
230 cx25840_write(client, 0x127, 0x50);
231
232 if (is_cx2583x(state))
233 break;
234
235
236
237 cx25840_write4(client, 0x8f8, 0x080160cd);
238
239
240
241 cx25840_write4(client, 0x900, 0x08017385);
242 cx25840_write4(client, 0x904, 0x08017385);
243 cx25840_write4(client, 0x90c, 0x08017385);
244 break;
245
246 case 48000:
247
248
249
250
251 cx25840_write4(client, 0x108, 0x180a040f);
252
253
254
255
256
257
258
259
260
261
262
263
264
265 cx25840_write4(client, 0x110, 0x0098d6e5);
266
267
268
269
270
271 cx25840_write(client, 0x127, 0x50);
272
273 if (is_cx2583x(state))
274 break;
275
276
277
278 cx25840_write4(client, 0x8f8, 0x08018000);
279
280
281
282 cx25840_write4(client, 0x900, 0x08015555);
283 cx25840_write4(client, 0x904, 0x08015555);
284 cx25840_write4(client, 0x90c, 0x08015555);
285 break;
286 }
287 }
288
289 state->audclk_freq = freq;
290
291 return 0;
292}
293
294static inline int cx25836_set_audclk_freq(struct i2c_client *client, u32 freq)
295{
296 return cx25840_set_audclk_freq(client, freq);
297}
298
299static int cx23885_set_audclk_freq(struct i2c_client *client, u32 freq)
300{
301 struct cx25840_state *state = to_state(i2c_get_clientdata(client));
302
303 if (state->aud_input != CX25840_AUDIO_SERIAL) {
304 switch (freq) {
305 case 32000:
306 case 44100:
307 case 48000:
308
309
310
311 break;
312 }
313 } else {
314 switch (freq) {
315 case 32000:
316 case 44100:
317
318
319
320 break;
321
322 case 48000:
323
324
325 cx25840_write4(client, 0x8f8, 0x0801867c);
326
327
328
329 cx25840_write4(client, 0x900, 0x08014faa);
330 cx25840_write4(client, 0x904, 0x08014faa);
331 cx25840_write4(client, 0x90c, 0x08014faa);
332 break;
333 }
334 }
335
336 state->audclk_freq = freq;
337
338 return 0;
339}
340
341static int cx231xx_set_audclk_freq(struct i2c_client *client, u32 freq)
342{
343 struct cx25840_state *state = to_state(i2c_get_clientdata(client));
344
345 if (state->aud_input != CX25840_AUDIO_SERIAL) {
346 switch (freq) {
347 case 32000:
348
349
350 cx25840_write4(client, 0x900, 0x0801f77f);
351 cx25840_write4(client, 0x904, 0x0801f77f);
352 cx25840_write4(client, 0x90c, 0x0801f77f);
353 break;
354
355 case 44100:
356
357
358 cx25840_write4(client, 0x900, 0x08016d59);
359 cx25840_write4(client, 0x904, 0x08016d59);
360 cx25840_write4(client, 0x90c, 0x08016d59);
361 break;
362
363 case 48000:
364
365
366 cx25840_write4(client, 0x900, 0x08014faa);
367 cx25840_write4(client, 0x904, 0x08014faa);
368 cx25840_write4(client, 0x90c, 0x08014faa);
369 break;
370 }
371 } else {
372 switch (freq) {
373
374 case 32000:
375
376
377 cx25840_write4(client, 0x8f8, 0x08010000);
378
379
380
381 cx25840_write4(client, 0x900, 0x08020000);
382 cx25840_write4(client, 0x904, 0x08020000);
383 cx25840_write4(client, 0x90c, 0x08020000);
384 break;
385
386 case 44100:
387
388
389 cx25840_write4(client, 0x8f8, 0x080160cd);
390
391
392
393 cx25840_write4(client, 0x900, 0x08017385);
394 cx25840_write4(client, 0x904, 0x08017385);
395 cx25840_write4(client, 0x90c, 0x08017385);
396 break;
397
398 case 48000:
399
400
401 cx25840_write4(client, 0x8f8, 0x0801867c);
402
403
404
405 cx25840_write4(client, 0x900, 0x08014faa);
406 cx25840_write4(client, 0x904, 0x08014faa);
407 cx25840_write4(client, 0x90c, 0x08014faa);
408 break;
409 }
410 }
411
412 state->audclk_freq = freq;
413
414 return 0;
415}
416
417static int set_audclk_freq(struct i2c_client *client, u32 freq)
418{
419 struct cx25840_state *state = to_state(i2c_get_clientdata(client));
420
421 if (freq != 32000 && freq != 44100 && freq != 48000)
422 return -EINVAL;
423
424 if (is_cx231xx(state))
425 return cx231xx_set_audclk_freq(client, freq);
426
427 if (is_cx2388x(state))
428 return cx23885_set_audclk_freq(client, freq);
429
430 if (is_cx2583x(state))
431 return cx25836_set_audclk_freq(client, freq);
432
433 return cx25840_set_audclk_freq(client, freq);
434}
435
436void cx25840_audio_set_path(struct i2c_client *client)
437{
438 struct cx25840_state *state = to_state(i2c_get_clientdata(client));
439
440
441 cx25840_and_or(client, 0x810, ~0x1, 0x01);
442
443
444 cx25840_and_or(client, 0x803, ~0x10, 0);
445
446
447 cx25840_write(client, 0x8d3, 0x1f);
448
449 if (state->aud_input == CX25840_AUDIO_SERIAL) {
450
451 cx25840_write4(client, 0x8d0, 0x01011012);
452
453
454
455
456 } else {
457
458 cx25840_write4(client, 0x8d0, 0x1f063870);
459 }
460
461 set_audclk_freq(client, state->audclk_freq);
462
463 if (state->aud_input != CX25840_AUDIO_SERIAL) {
464
465
466 cx25840_and_or(client, 0x803, ~0x10, 0x10);
467 }
468
469
470 cx25840_and_or(client, 0x810, ~0x1, 0x00);
471
472
473 if (is_cx2388x(state) || is_cx231xx(state))
474 cx25840_and_or(client, 0x803, ~0x10, 0x10);
475}
476
477static int get_volume(struct i2c_client *client)
478{
479 struct cx25840_state *state = to_state(i2c_get_clientdata(client));
480 int vol;
481
482 if (state->unmute_volume >= 0)
483 return state->unmute_volume;
484
485
486
487
488
489 vol = 228 - cx25840_read(client, 0x8d4);
490 vol = (vol / 2) + 23;
491 return vol << 9;
492}
493
494static void set_volume(struct i2c_client *client, int volume)
495{
496 struct cx25840_state *state = to_state(i2c_get_clientdata(client));
497 int vol;
498
499 if (state->unmute_volume >= 0) {
500 state->unmute_volume = volume;
501 return;
502 }
503
504
505 vol = volume >> 9;
506
507
508
509
510 if (vol <= 23) {
511 vol = 0;
512 } else {
513 vol -= 23;
514 }
515
516
517 cx25840_write(client, 0x8d4, 228 - (vol * 2));
518}
519
520static int get_bass(struct i2c_client *client)
521{
522
523
524
525 int bass = cx25840_read(client, 0x8d9) & 0x3f;
526 bass = (((48 - bass) * 0xffff) + 47) / 48;
527 return bass;
528}
529
530static void set_bass(struct i2c_client *client, int bass)
531{
532
533 cx25840_and_or(client, 0x8d9, ~0x3f, 48 - (bass * 48 / 0xffff));
534}
535
536static int get_treble(struct i2c_client *client)
537{
538
539
540
541 int treble = cx25840_read(client, 0x8db) & 0x3f;
542 treble = (((48 - treble) * 0xffff) + 47) / 48;
543 return treble;
544}
545
546static void set_treble(struct i2c_client *client, int treble)
547{
548
549 cx25840_and_or(client, 0x8db, ~0x3f, 48 - (treble * 48 / 0xffff));
550}
551
552static int get_balance(struct i2c_client *client)
553{
554
555
556
557 int balance = cx25840_read(client, 0x8d5) & 0x7f;
558
559 if ((cx25840_read(client, 0x8d5) & 0x80) == 0)
560 balance = 0x80 - balance;
561 else
562 balance = 0x80 + balance;
563 return balance << 8;
564}
565
566static void set_balance(struct i2c_client *client, int balance)
567{
568 int bal = balance >> 8;
569 if (bal > 0x80) {
570
571 cx25840_and_or(client, 0x8d5, 0x7f, 0x80);
572
573 cx25840_and_or(client, 0x8d5, ~0x7f, bal & 0x7f);
574 } else {
575
576 cx25840_and_or(client, 0x8d5, 0x7f, 0x00);
577
578 cx25840_and_or(client, 0x8d5, ~0x7f, 0x80 - bal);
579 }
580}
581
582static int get_mute(struct i2c_client *client)
583{
584 struct cx25840_state *state = to_state(i2c_get_clientdata(client));
585
586 return state->unmute_volume >= 0;
587}
588
589static void set_mute(struct i2c_client *client, int mute)
590{
591 struct cx25840_state *state = to_state(i2c_get_clientdata(client));
592
593 if (mute && state->unmute_volume == -1) {
594 int vol = get_volume(client);
595
596 set_volume(client, 0);
597 state->unmute_volume = vol;
598 }
599 else if (!mute && state->unmute_volume != -1) {
600 int vol = state->unmute_volume;
601
602 state->unmute_volume = -1;
603 set_volume(client, vol);
604 }
605}
606
607int cx25840_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
608{
609 struct i2c_client *client = v4l2_get_subdevdata(sd);
610 struct cx25840_state *state = to_state(sd);
611 int retval;
612
613 if (!is_cx2583x(state))
614 cx25840_and_or(client, 0x810, ~0x1, 1);
615 if (state->aud_input != CX25840_AUDIO_SERIAL) {
616 cx25840_and_or(client, 0x803, ~0x10, 0);
617 cx25840_write(client, 0x8d3, 0x1f);
618 }
619 retval = set_audclk_freq(client, freq);
620 if (state->aud_input != CX25840_AUDIO_SERIAL)
621 cx25840_and_or(client, 0x803, ~0x10, 0x10);
622 if (!is_cx2583x(state))
623 cx25840_and_or(client, 0x810, ~0x1, 0);
624 return retval;
625}
626
627int cx25840_audio_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
628{
629 struct i2c_client *client = v4l2_get_subdevdata(sd);
630
631 switch (ctrl->id) {
632 case V4L2_CID_AUDIO_VOLUME:
633 ctrl->value = get_volume(client);
634 break;
635 case V4L2_CID_AUDIO_BASS:
636 ctrl->value = get_bass(client);
637 break;
638 case V4L2_CID_AUDIO_TREBLE:
639 ctrl->value = get_treble(client);
640 break;
641 case V4L2_CID_AUDIO_BALANCE:
642 ctrl->value = get_balance(client);
643 break;
644 case V4L2_CID_AUDIO_MUTE:
645 ctrl->value = get_mute(client);
646 break;
647 default:
648 return -EINVAL;
649 }
650 return 0;
651}
652
653int cx25840_audio_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
654{
655 struct i2c_client *client = v4l2_get_subdevdata(sd);
656
657 switch (ctrl->id) {
658 case V4L2_CID_AUDIO_VOLUME:
659 set_volume(client, ctrl->value);
660 break;
661 case V4L2_CID_AUDIO_BASS:
662 set_bass(client, ctrl->value);
663 break;
664 case V4L2_CID_AUDIO_TREBLE:
665 set_treble(client, ctrl->value);
666 break;
667 case V4L2_CID_AUDIO_BALANCE:
668 set_balance(client, ctrl->value);
669 break;
670 case V4L2_CID_AUDIO_MUTE:
671 set_mute(client, ctrl->value);
672 break;
673 default:
674 return -EINVAL;
675 }
676 return 0;
677}
678