Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/media/video/cx18/cx18-av-audio.c
17778 views
1
/*
2
* cx18 ADEC audio functions
3
*
4
* Derived from cx25840-audio.c
5
*
6
* Copyright (C) 2007 Hans Verkuil <[email protected]>
7
* Copyright (C) 2008 Andy Walls <[email protected]>
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
27
static 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
303
void 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
345
static void set_volume(struct cx18 *cx, int volume)
346
{
347
/* First convert the volume to msp3400 values (0-127) */
348
int vol = volume >> 9;
349
/* now scale it up to cx18_av values
350
* -114dB to -96dB maps to 0
351
* this should be 19, but in my testing that was 4dB too loud */
352
if (vol <= 23)
353
vol = 0;
354
else
355
vol -= 23;
356
357
/* PATH1_VOLUME */
358
cx18_av_write(cx, 0x8d4, 228 - (vol * 2));
359
}
360
361
static void set_bass(struct cx18 *cx, int bass)
362
{
363
/* PATH1_EQ_BASS_VOL */
364
cx18_av_and_or(cx, 0x8d9, ~0x3f, 48 - (bass * 48 / 0xffff));
365
}
366
367
static void set_treble(struct cx18 *cx, int treble)
368
{
369
/* PATH1_EQ_TREBLE_VOL */
370
cx18_av_and_or(cx, 0x8db, ~0x3f, 48 - (treble * 48 / 0xffff));
371
}
372
373
static void set_balance(struct cx18 *cx, int balance)
374
{
375
int bal = balance >> 8;
376
if (bal > 0x80) {
377
/* PATH1_BAL_LEFT */
378
cx18_av_and_or(cx, 0x8d5, 0x7f, 0x80);
379
/* PATH1_BAL_LEVEL */
380
cx18_av_and_or(cx, 0x8d5, ~0x7f, bal & 0x7f);
381
} else {
382
/* PATH1_BAL_LEFT */
383
cx18_av_and_or(cx, 0x8d5, 0x7f, 0x00);
384
/* PATH1_BAL_LEVEL */
385
cx18_av_and_or(cx, 0x8d5, ~0x7f, 0x80 - bal);
386
}
387
}
388
389
static void set_mute(struct cx18 *cx, int mute)
390
{
391
struct cx18_av_state *state = &cx->av_state;
392
u8 v;
393
394
if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
395
/* Must turn off microcontroller in order to mute sound.
396
* Not sure if this is the best method, but it does work.
397
* If the microcontroller is running, then it will undo any
398
* changes to the mute register. */
399
v = cx18_av_read(cx, 0x803);
400
if (mute) {
401
/* disable microcontroller */
402
v &= ~0x10;
403
cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
404
cx18_av_write(cx, 0x8d3, 0x1f);
405
} else {
406
/* enable microcontroller */
407
v |= 0x10;
408
cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
409
}
410
} else {
411
/* SRC1_MUTE_EN */
412
cx18_av_and_or(cx, 0x8d3, ~0x2, mute ? 0x02 : 0x00);
413
}
414
}
415
416
int cx18_av_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
417
{
418
struct cx18 *cx = v4l2_get_subdevdata(sd);
419
struct cx18_av_state *state = &cx->av_state;
420
int retval;
421
u8 v;
422
423
if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
424
v = cx18_av_read(cx, 0x803) & ~0x10;
425
cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
426
cx18_av_write(cx, 0x8d3, 0x1f);
427
}
428
v = cx18_av_read(cx, 0x810) | 0x1;
429
cx18_av_write_expect(cx, 0x810, v, v, 0x0f);
430
431
retval = set_audclk_freq(cx, freq);
432
433
v = cx18_av_read(cx, 0x810) & ~0x1;
434
cx18_av_write_expect(cx, 0x810, v, v, 0x0f);
435
if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
436
v = cx18_av_read(cx, 0x803) | 0x10;
437
cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
438
}
439
return retval;
440
}
441
442
static int cx18_av_audio_s_ctrl(struct v4l2_ctrl *ctrl)
443
{
444
struct v4l2_subdev *sd = to_sd(ctrl);
445
struct cx18 *cx = v4l2_get_subdevdata(sd);
446
447
switch (ctrl->id) {
448
case V4L2_CID_AUDIO_VOLUME:
449
set_volume(cx, ctrl->val);
450
break;
451
case V4L2_CID_AUDIO_BASS:
452
set_bass(cx, ctrl->val);
453
break;
454
case V4L2_CID_AUDIO_TREBLE:
455
set_treble(cx, ctrl->val);
456
break;
457
case V4L2_CID_AUDIO_BALANCE:
458
set_balance(cx, ctrl->val);
459
break;
460
case V4L2_CID_AUDIO_MUTE:
461
set_mute(cx, ctrl->val);
462
break;
463
default:
464
return -EINVAL;
465
}
466
return 0;
467
}
468
469
const struct v4l2_ctrl_ops cx18_av_audio_ctrl_ops = {
470
.s_ctrl = cx18_av_audio_s_ctrl,
471
};
472
473