1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* cx25840 - Conexant CX25840 audio/video decoder driver |
3 | * |
4 | * Copyright (C) 2004 Ulf Eklund |
5 | * |
6 | * Based on the saa7115 driver and on the first version of Chris Kennedy's |
7 | * cx25840 driver. |
8 | * |
9 | * Changes by Tyler Trafford <tatrafford@comcast.net> |
10 | * - cleanup/rewrite for V4L2 API (2005) |
11 | * |
12 | * VBI support by Hans Verkuil <hverkuil@xs4all.nl>. |
13 | * |
14 | * NTSC sliced VBI support by Christopher Neufeld <television@cneufeld.ca> |
15 | * with additional fixes by Hans Verkuil <hverkuil@xs4all.nl>. |
16 | * |
17 | * CX23885 support by Steven Toth <stoth@linuxtv.org>. |
18 | * |
19 | * CX2388[578] IRQ handling, IO Pin mux configuration and other small fixes are |
20 | * Copyright (C) 2010 Andy Walls <awalls@md.metrocast.net> |
21 | * |
22 | * CX23888 DIF support for the HVR1850 |
23 | * Copyright (C) 2011 Steven Toth <stoth@kernellabs.com> |
24 | * |
25 | * CX2584x pin to pad mapping and output format configuration support are |
26 | * Copyright (C) 2011 Maciej S. Szmigiero <mail@maciej.szmigiero.name> |
27 | */ |
28 | |
29 | #include <linux/kernel.h> |
30 | #include <linux/module.h> |
31 | #include <linux/slab.h> |
32 | #include <linux/videodev2.h> |
33 | #include <linux/i2c.h> |
34 | #include <linux/delay.h> |
35 | #include <linux/math64.h> |
36 | #include <media/v4l2-common.h> |
37 | #include <media/drv-intf/cx25840.h> |
38 | |
39 | #include "cx25840-core.h" |
40 | |
41 | MODULE_DESCRIPTION("Conexant CX25840 audio/video decoder driver" ); |
42 | MODULE_AUTHOR("Ulf Eklund, Chris Kennedy, Hans Verkuil, Tyler Trafford" ); |
43 | MODULE_LICENSE("GPL" ); |
44 | |
45 | #define CX25840_VID_INT_STAT_REG 0x410 |
46 | #define CX25840_VID_INT_STAT_BITS 0x0000ffff |
47 | #define CX25840_VID_INT_MASK_BITS 0xffff0000 |
48 | #define CX25840_VID_INT_MASK_SHFT 16 |
49 | #define CX25840_VID_INT_MASK_REG 0x412 |
50 | |
51 | #define CX23885_AUD_MC_INT_MASK_REG 0x80c |
52 | #define CX23885_AUD_MC_INT_STAT_BITS 0xffff0000 |
53 | #define CX23885_AUD_MC_INT_CTRL_BITS 0x0000ffff |
54 | #define CX23885_AUD_MC_INT_STAT_SHFT 16 |
55 | |
56 | #define CX25840_AUD_INT_CTRL_REG 0x812 |
57 | #define CX25840_AUD_INT_STAT_REG 0x813 |
58 | |
59 | #define CX23885_PIN_CTRL_IRQ_REG 0x123 |
60 | #define CX23885_PIN_CTRL_IRQ_IR_STAT 0x40 |
61 | #define CX23885_PIN_CTRL_IRQ_AUD_STAT 0x20 |
62 | #define CX23885_PIN_CTRL_IRQ_VID_STAT 0x10 |
63 | |
64 | #define CX25840_IR_STATS_REG 0x210 |
65 | #define CX25840_IR_IRQEN_REG 0x214 |
66 | |
67 | static int cx25840_debug; |
68 | |
69 | module_param_named(debug, cx25840_debug, int, 0644); |
70 | |
71 | MODULE_PARM_DESC(debug, "Debugging messages [0=Off (default) 1=On]" ); |
72 | |
73 | /* ----------------------------------------------------------------------- */ |
74 | static void cx23888_std_setup(struct i2c_client *client); |
75 | |
76 | int cx25840_write(struct i2c_client *client, u16 addr, u8 value) |
77 | { |
78 | u8 buffer[3]; |
79 | |
80 | buffer[0] = addr >> 8; |
81 | buffer[1] = addr & 0xff; |
82 | buffer[2] = value; |
83 | return i2c_master_send(client, buf: buffer, count: 3); |
84 | } |
85 | |
86 | int cx25840_write4(struct i2c_client *client, u16 addr, u32 value) |
87 | { |
88 | u8 buffer[6]; |
89 | |
90 | buffer[0] = addr >> 8; |
91 | buffer[1] = addr & 0xff; |
92 | buffer[2] = value & 0xff; |
93 | buffer[3] = (value >> 8) & 0xff; |
94 | buffer[4] = (value >> 16) & 0xff; |
95 | buffer[5] = value >> 24; |
96 | return i2c_master_send(client, buf: buffer, count: 6); |
97 | } |
98 | |
99 | u8 cx25840_read(struct i2c_client *client, u16 addr) |
100 | { |
101 | struct i2c_msg msgs[2]; |
102 | u8 tx_buf[2], rx_buf[1]; |
103 | |
104 | /* Write register address */ |
105 | tx_buf[0] = addr >> 8; |
106 | tx_buf[1] = addr & 0xff; |
107 | msgs[0].addr = client->addr; |
108 | msgs[0].flags = 0; |
109 | msgs[0].len = 2; |
110 | msgs[0].buf = (char *)tx_buf; |
111 | |
112 | /* Read data from register */ |
113 | msgs[1].addr = client->addr; |
114 | msgs[1].flags = I2C_M_RD; |
115 | msgs[1].len = 1; |
116 | msgs[1].buf = (char *)rx_buf; |
117 | |
118 | if (i2c_transfer(adap: client->adapter, msgs, num: 2) < 2) |
119 | return 0; |
120 | |
121 | return rx_buf[0]; |
122 | } |
123 | |
124 | u32 cx25840_read4(struct i2c_client *client, u16 addr) |
125 | { |
126 | struct i2c_msg msgs[2]; |
127 | u8 tx_buf[2], rx_buf[4]; |
128 | |
129 | /* Write register address */ |
130 | tx_buf[0] = addr >> 8; |
131 | tx_buf[1] = addr & 0xff; |
132 | msgs[0].addr = client->addr; |
133 | msgs[0].flags = 0; |
134 | msgs[0].len = 2; |
135 | msgs[0].buf = (char *)tx_buf; |
136 | |
137 | /* Read data from registers */ |
138 | msgs[1].addr = client->addr; |
139 | msgs[1].flags = I2C_M_RD; |
140 | msgs[1].len = 4; |
141 | msgs[1].buf = (char *)rx_buf; |
142 | |
143 | if (i2c_transfer(adap: client->adapter, msgs, num: 2) < 2) |
144 | return 0; |
145 | |
146 | return (rx_buf[3] << 24) | (rx_buf[2] << 16) | (rx_buf[1] << 8) | |
147 | rx_buf[0]; |
148 | } |
149 | |
150 | int cx25840_and_or(struct i2c_client *client, u16 addr, unsigned int and_mask, |
151 | u8 or_value) |
152 | { |
153 | return cx25840_write(client, addr, |
154 | value: (cx25840_read(client, addr) & and_mask) | |
155 | or_value); |
156 | } |
157 | |
158 | int cx25840_and_or4(struct i2c_client *client, u16 addr, u32 and_mask, |
159 | u32 or_value) |
160 | { |
161 | return cx25840_write4(client, addr, |
162 | value: (cx25840_read4(client, addr) & and_mask) | |
163 | or_value); |
164 | } |
165 | |
166 | /* ----------------------------------------------------------------------- */ |
167 | |
168 | static int set_input(struct i2c_client *client, |
169 | enum cx25840_video_input vid_input, |
170 | enum cx25840_audio_input aud_input); |
171 | |
172 | /* ----------------------------------------------------------------------- */ |
173 | |
174 | static int cx23885_s_io_pin_config(struct v4l2_subdev *sd, size_t n, |
175 | struct v4l2_subdev_io_pin_config *p) |
176 | { |
177 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
178 | int i; |
179 | u32 pin_ctrl; |
180 | u8 gpio_oe, gpio_data, strength; |
181 | |
182 | pin_ctrl = cx25840_read4(client, addr: 0x120); |
183 | gpio_oe = cx25840_read(client, addr: 0x160); |
184 | gpio_data = cx25840_read(client, addr: 0x164); |
185 | |
186 | for (i = 0; i < n; i++) { |
187 | strength = p[i].strength; |
188 | if (strength > CX25840_PIN_DRIVE_FAST) |
189 | strength = CX25840_PIN_DRIVE_FAST; |
190 | |
191 | switch (p[i].pin) { |
192 | case CX23885_PIN_IRQ_N_GPIO16: |
193 | if (p[i].function != CX23885_PAD_IRQ_N) { |
194 | /* GPIO16 */ |
195 | pin_ctrl &= ~(0x1 << 25); |
196 | } else { |
197 | /* IRQ_N */ |
198 | if (p[i].flags & |
199 | (BIT(V4L2_SUBDEV_IO_PIN_DISABLE) | |
200 | BIT(V4L2_SUBDEV_IO_PIN_INPUT))) { |
201 | pin_ctrl &= ~(0x1 << 25); |
202 | } else { |
203 | pin_ctrl |= (0x1 << 25); |
204 | } |
205 | if (p[i].flags & |
206 | BIT(V4L2_SUBDEV_IO_PIN_ACTIVE_LOW)) { |
207 | pin_ctrl &= ~(0x1 << 24); |
208 | } else { |
209 | pin_ctrl |= (0x1 << 24); |
210 | } |
211 | } |
212 | break; |
213 | case CX23885_PIN_IR_RX_GPIO19: |
214 | if (p[i].function != CX23885_PAD_GPIO19) { |
215 | /* IR_RX */ |
216 | gpio_oe |= (0x1 << 0); |
217 | pin_ctrl &= ~(0x3 << 18); |
218 | pin_ctrl |= (strength << 18); |
219 | } else { |
220 | /* GPIO19 */ |
221 | gpio_oe &= ~(0x1 << 0); |
222 | if (p[i].flags & BIT(V4L2_SUBDEV_IO_PIN_SET_VALUE)) { |
223 | gpio_data &= ~(0x1 << 0); |
224 | gpio_data |= ((p[i].value & 0x1) << 0); |
225 | } |
226 | pin_ctrl &= ~(0x3 << 12); |
227 | pin_ctrl |= (strength << 12); |
228 | } |
229 | break; |
230 | case CX23885_PIN_IR_TX_GPIO20: |
231 | if (p[i].function != CX23885_PAD_GPIO20) { |
232 | /* IR_TX */ |
233 | gpio_oe |= (0x1 << 1); |
234 | if (p[i].flags & BIT(V4L2_SUBDEV_IO_PIN_DISABLE)) |
235 | pin_ctrl &= ~(0x1 << 10); |
236 | else |
237 | pin_ctrl |= (0x1 << 10); |
238 | pin_ctrl &= ~(0x3 << 18); |
239 | pin_ctrl |= (strength << 18); |
240 | } else { |
241 | /* GPIO20 */ |
242 | gpio_oe &= ~(0x1 << 1); |
243 | if (p[i].flags & BIT(V4L2_SUBDEV_IO_PIN_SET_VALUE)) { |
244 | gpio_data &= ~(0x1 << 1); |
245 | gpio_data |= ((p[i].value & 0x1) << 1); |
246 | } |
247 | pin_ctrl &= ~(0x3 << 12); |
248 | pin_ctrl |= (strength << 12); |
249 | } |
250 | break; |
251 | case CX23885_PIN_I2S_SDAT_GPIO21: |
252 | if (p[i].function != CX23885_PAD_GPIO21) { |
253 | /* I2S_SDAT */ |
254 | /* TODO: Input or Output config */ |
255 | gpio_oe |= (0x1 << 2); |
256 | pin_ctrl &= ~(0x3 << 22); |
257 | pin_ctrl |= (strength << 22); |
258 | } else { |
259 | /* GPIO21 */ |
260 | gpio_oe &= ~(0x1 << 2); |
261 | if (p[i].flags & BIT(V4L2_SUBDEV_IO_PIN_SET_VALUE)) { |
262 | gpio_data &= ~(0x1 << 2); |
263 | gpio_data |= ((p[i].value & 0x1) << 2); |
264 | } |
265 | pin_ctrl &= ~(0x3 << 12); |
266 | pin_ctrl |= (strength << 12); |
267 | } |
268 | break; |
269 | case CX23885_PIN_I2S_WCLK_GPIO22: |
270 | if (p[i].function != CX23885_PAD_GPIO22) { |
271 | /* I2S_WCLK */ |
272 | /* TODO: Input or Output config */ |
273 | gpio_oe |= (0x1 << 3); |
274 | pin_ctrl &= ~(0x3 << 22); |
275 | pin_ctrl |= (strength << 22); |
276 | } else { |
277 | /* GPIO22 */ |
278 | gpio_oe &= ~(0x1 << 3); |
279 | if (p[i].flags & BIT(V4L2_SUBDEV_IO_PIN_SET_VALUE)) { |
280 | gpio_data &= ~(0x1 << 3); |
281 | gpio_data |= ((p[i].value & 0x1) << 3); |
282 | } |
283 | pin_ctrl &= ~(0x3 << 12); |
284 | pin_ctrl |= (strength << 12); |
285 | } |
286 | break; |
287 | case CX23885_PIN_I2S_BCLK_GPIO23: |
288 | if (p[i].function != CX23885_PAD_GPIO23) { |
289 | /* I2S_BCLK */ |
290 | /* TODO: Input or Output config */ |
291 | gpio_oe |= (0x1 << 4); |
292 | pin_ctrl &= ~(0x3 << 22); |
293 | pin_ctrl |= (strength << 22); |
294 | } else { |
295 | /* GPIO23 */ |
296 | gpio_oe &= ~(0x1 << 4); |
297 | if (p[i].flags & BIT(V4L2_SUBDEV_IO_PIN_SET_VALUE)) { |
298 | gpio_data &= ~(0x1 << 4); |
299 | gpio_data |= ((p[i].value & 0x1) << 4); |
300 | } |
301 | pin_ctrl &= ~(0x3 << 12); |
302 | pin_ctrl |= (strength << 12); |
303 | } |
304 | break; |
305 | } |
306 | } |
307 | |
308 | cx25840_write(client, addr: 0x164, value: gpio_data); |
309 | cx25840_write(client, addr: 0x160, value: gpio_oe); |
310 | cx25840_write4(client, addr: 0x120, value: pin_ctrl); |
311 | return 0; |
312 | } |
313 | |
314 | static u8 cx25840_function_to_pad(struct i2c_client *client, u8 function) |
315 | { |
316 | if (function > CX25840_PAD_VRESET) { |
317 | v4l_err(client, "invalid function %u, assuming default\n" , |
318 | (unsigned int)function); |
319 | return 0; |
320 | } |
321 | |
322 | return function; |
323 | } |
324 | |
325 | static void cx25840_set_invert(u8 *pinctrl3, u8 *voutctrl4, u8 function, |
326 | u8 pin, bool invert) |
327 | { |
328 | switch (function) { |
329 | case CX25840_PAD_IRQ_N: |
330 | if (invert) |
331 | *pinctrl3 &= ~2; |
332 | else |
333 | *pinctrl3 |= 2; |
334 | break; |
335 | |
336 | case CX25840_PAD_ACTIVE: |
337 | if (invert) |
338 | *voutctrl4 |= BIT(2); |
339 | else |
340 | *voutctrl4 &= ~BIT(2); |
341 | break; |
342 | |
343 | case CX25840_PAD_VACTIVE: |
344 | if (invert) |
345 | *voutctrl4 |= BIT(5); |
346 | else |
347 | *voutctrl4 &= ~BIT(5); |
348 | break; |
349 | |
350 | case CX25840_PAD_CBFLAG: |
351 | if (invert) |
352 | *voutctrl4 |= BIT(4); |
353 | else |
354 | *voutctrl4 &= ~BIT(4); |
355 | break; |
356 | |
357 | case CX25840_PAD_VRESET: |
358 | if (invert) |
359 | *voutctrl4 |= BIT(0); |
360 | else |
361 | *voutctrl4 &= ~BIT(0); |
362 | break; |
363 | } |
364 | |
365 | if (function != CX25840_PAD_DEFAULT) |
366 | return; |
367 | |
368 | switch (pin) { |
369 | case CX25840_PIN_DVALID_PRGM0: |
370 | if (invert) |
371 | *voutctrl4 |= BIT(6); |
372 | else |
373 | *voutctrl4 &= ~BIT(6); |
374 | break; |
375 | |
376 | case CX25840_PIN_HRESET_PRGM2: |
377 | if (invert) |
378 | *voutctrl4 |= BIT(1); |
379 | else |
380 | *voutctrl4 &= ~BIT(1); |
381 | break; |
382 | } |
383 | } |
384 | |
385 | static int cx25840_s_io_pin_config(struct v4l2_subdev *sd, size_t n, |
386 | struct v4l2_subdev_io_pin_config *p) |
387 | { |
388 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
389 | unsigned int i; |
390 | u8 pinctrl[6], pinconf[10], voutctrl4; |
391 | |
392 | for (i = 0; i < 6; i++) |
393 | pinctrl[i] = cx25840_read(client, addr: 0x114 + i); |
394 | |
395 | for (i = 0; i < 10; i++) |
396 | pinconf[i] = cx25840_read(client, addr: 0x11c + i); |
397 | |
398 | voutctrl4 = cx25840_read(client, addr: 0x407); |
399 | |
400 | for (i = 0; i < n; i++) { |
401 | u8 strength = p[i].strength; |
402 | |
403 | if (strength != CX25840_PIN_DRIVE_SLOW && |
404 | strength != CX25840_PIN_DRIVE_MEDIUM && |
405 | strength != CX25840_PIN_DRIVE_FAST) { |
406 | v4l_err(client, |
407 | "invalid drive speed for pin %u (%u), assuming fast\n" , |
408 | (unsigned int)p[i].pin, |
409 | (unsigned int)strength); |
410 | |
411 | strength = CX25840_PIN_DRIVE_FAST; |
412 | } |
413 | |
414 | switch (p[i].pin) { |
415 | case CX25840_PIN_DVALID_PRGM0: |
416 | if (p[i].flags & BIT(V4L2_SUBDEV_IO_PIN_DISABLE)) |
417 | pinctrl[0] &= ~BIT(6); |
418 | else |
419 | pinctrl[0] |= BIT(6); |
420 | |
421 | pinconf[3] &= 0xf0; |
422 | pinconf[3] |= cx25840_function_to_pad(client, |
423 | function: p[i].function); |
424 | |
425 | cx25840_set_invert(pinctrl3: &pinctrl[3], voutctrl4: &voutctrl4, |
426 | function: p[i].function, |
427 | pin: CX25840_PIN_DVALID_PRGM0, |
428 | invert: p[i].flags & |
429 | BIT(V4L2_SUBDEV_IO_PIN_ACTIVE_LOW)); |
430 | |
431 | pinctrl[4] &= ~(3 << 2); /* CX25840_PIN_DRIVE_MEDIUM */ |
432 | switch (strength) { |
433 | case CX25840_PIN_DRIVE_SLOW: |
434 | pinctrl[4] |= 1 << 2; |
435 | break; |
436 | |
437 | case CX25840_PIN_DRIVE_FAST: |
438 | pinctrl[4] |= 2 << 2; |
439 | break; |
440 | } |
441 | |
442 | break; |
443 | |
444 | case CX25840_PIN_HRESET_PRGM2: |
445 | if (p[i].flags & BIT(V4L2_SUBDEV_IO_PIN_DISABLE)) |
446 | pinctrl[1] &= ~BIT(0); |
447 | else |
448 | pinctrl[1] |= BIT(0); |
449 | |
450 | pinconf[4] &= 0xf0; |
451 | pinconf[4] |= cx25840_function_to_pad(client, |
452 | function: p[i].function); |
453 | |
454 | cx25840_set_invert(pinctrl3: &pinctrl[3], voutctrl4: &voutctrl4, |
455 | function: p[i].function, |
456 | pin: CX25840_PIN_HRESET_PRGM2, |
457 | invert: p[i].flags & |
458 | BIT(V4L2_SUBDEV_IO_PIN_ACTIVE_LOW)); |
459 | |
460 | pinctrl[4] &= ~(3 << 2); /* CX25840_PIN_DRIVE_MEDIUM */ |
461 | switch (strength) { |
462 | case CX25840_PIN_DRIVE_SLOW: |
463 | pinctrl[4] |= 1 << 2; |
464 | break; |
465 | |
466 | case CX25840_PIN_DRIVE_FAST: |
467 | pinctrl[4] |= 2 << 2; |
468 | break; |
469 | } |
470 | |
471 | break; |
472 | |
473 | case CX25840_PIN_PLL_CLK_PRGM7: |
474 | if (p[i].flags & BIT(V4L2_SUBDEV_IO_PIN_DISABLE)) |
475 | pinctrl[2] &= ~BIT(2); |
476 | else |
477 | pinctrl[2] |= BIT(2); |
478 | |
479 | switch (p[i].function) { |
480 | case CX25840_PAD_XTI_X5_DLL: |
481 | pinconf[6] = 0; |
482 | break; |
483 | |
484 | case CX25840_PAD_AUX_PLL: |
485 | pinconf[6] = 1; |
486 | break; |
487 | |
488 | case CX25840_PAD_VID_PLL: |
489 | pinconf[6] = 5; |
490 | break; |
491 | |
492 | case CX25840_PAD_XTI: |
493 | pinconf[6] = 2; |
494 | break; |
495 | |
496 | default: |
497 | pinconf[6] = 3; |
498 | pinconf[6] |= |
499 | cx25840_function_to_pad(client, |
500 | function: p[i].function) |
501 | << 4; |
502 | } |
503 | |
504 | break; |
505 | |
506 | default: |
507 | v4l_err(client, "invalid or unsupported pin %u\n" , |
508 | (unsigned int)p[i].pin); |
509 | break; |
510 | } |
511 | } |
512 | |
513 | cx25840_write(client, addr: 0x407, value: voutctrl4); |
514 | |
515 | for (i = 0; i < 6; i++) |
516 | cx25840_write(client, addr: 0x114 + i, value: pinctrl[i]); |
517 | |
518 | for (i = 0; i < 10; i++) |
519 | cx25840_write(client, addr: 0x11c + i, value: pinconf[i]); |
520 | |
521 | return 0; |
522 | } |
523 | |
524 | static int common_s_io_pin_config(struct v4l2_subdev *sd, size_t n, |
525 | struct v4l2_subdev_io_pin_config *pincfg) |
526 | { |
527 | struct cx25840_state *state = to_state(sd); |
528 | |
529 | if (is_cx2388x(state)) |
530 | return cx23885_s_io_pin_config(sd, n, p: pincfg); |
531 | else if (is_cx2584x(state)) |
532 | return cx25840_s_io_pin_config(sd, n, p: pincfg); |
533 | return 0; |
534 | } |
535 | |
536 | /* ----------------------------------------------------------------------- */ |
537 | |
538 | static void init_dll1(struct i2c_client *client) |
539 | { |
540 | /* |
541 | * This is the Hauppauge sequence used to |
542 | * initialize the Delay Lock Loop 1 (ADC DLL). |
543 | */ |
544 | cx25840_write(client, addr: 0x159, value: 0x23); |
545 | cx25840_write(client, addr: 0x15a, value: 0x87); |
546 | cx25840_write(client, addr: 0x15b, value: 0x06); |
547 | udelay(10); |
548 | cx25840_write(client, addr: 0x159, value: 0xe1); |
549 | udelay(10); |
550 | cx25840_write(client, addr: 0x15a, value: 0x86); |
551 | cx25840_write(client, addr: 0x159, value: 0xe0); |
552 | cx25840_write(client, addr: 0x159, value: 0xe1); |
553 | cx25840_write(client, addr: 0x15b, value: 0x10); |
554 | } |
555 | |
556 | static void init_dll2(struct i2c_client *client) |
557 | { |
558 | /* |
559 | * This is the Hauppauge sequence used to |
560 | * initialize the Delay Lock Loop 2 (ADC DLL). |
561 | */ |
562 | cx25840_write(client, addr: 0x15d, value: 0xe3); |
563 | cx25840_write(client, addr: 0x15e, value: 0x86); |
564 | cx25840_write(client, addr: 0x15f, value: 0x06); |
565 | udelay(10); |
566 | cx25840_write(client, addr: 0x15d, value: 0xe1); |
567 | cx25840_write(client, addr: 0x15d, value: 0xe0); |
568 | cx25840_write(client, addr: 0x15d, value: 0xe1); |
569 | } |
570 | |
571 | static void cx25836_initialize(struct i2c_client *client) |
572 | { |
573 | /* |
574 | *reset configuration is described on page 3-77 |
575 | * of the CX25836 datasheet |
576 | */ |
577 | |
578 | /* 2. */ |
579 | cx25840_and_or(client, addr: 0x000, and_mask: ~0x01, or_value: 0x01); |
580 | cx25840_and_or(client, addr: 0x000, and_mask: ~0x01, or_value: 0x00); |
581 | /* 3a. */ |
582 | cx25840_and_or(client, addr: 0x15a, and_mask: ~0x70, or_value: 0x00); |
583 | /* 3b. */ |
584 | cx25840_and_or(client, addr: 0x15b, and_mask: ~0x1e, or_value: 0x06); |
585 | /* 3c. */ |
586 | cx25840_and_or(client, addr: 0x159, and_mask: ~0x02, or_value: 0x02); |
587 | /* 3d. */ |
588 | udelay(10); |
589 | /* 3e. */ |
590 | cx25840_and_or(client, addr: 0x159, and_mask: ~0x02, or_value: 0x00); |
591 | /* 3f. */ |
592 | cx25840_and_or(client, addr: 0x159, and_mask: ~0xc0, or_value: 0xc0); |
593 | /* 3g. */ |
594 | cx25840_and_or(client, addr: 0x159, and_mask: ~0x01, or_value: 0x00); |
595 | cx25840_and_or(client, addr: 0x159, and_mask: ~0x01, or_value: 0x01); |
596 | /* 3h. */ |
597 | cx25840_and_or(client, addr: 0x15b, and_mask: ~0x1e, or_value: 0x10); |
598 | } |
599 | |
600 | static void cx25840_work_handler(struct work_struct *work) |
601 | { |
602 | struct cx25840_state *state = container_of(work, struct cx25840_state, fw_work); |
603 | |
604 | cx25840_loadfw(client: state->c); |
605 | wake_up(&state->fw_wait); |
606 | } |
607 | |
608 | #define CX25840_VCONFIG_SET_BIT(state, opt_msk, voc, idx, bit, oneval) \ |
609 | do { \ |
610 | if ((state)->vid_config & (opt_msk)) { \ |
611 | if (((state)->vid_config & (opt_msk)) == \ |
612 | (oneval)) \ |
613 | (voc)[idx] |= BIT(bit); \ |
614 | else \ |
615 | (voc)[idx] &= ~BIT(bit); \ |
616 | } \ |
617 | } while (0) |
618 | |
619 | /* apply current vconfig to hardware regs */ |
620 | static void cx25840_vconfig_apply(struct i2c_client *client) |
621 | { |
622 | struct cx25840_state *state = to_state(sd: i2c_get_clientdata(client)); |
623 | u8 voutctrl[3]; |
624 | unsigned int i; |
625 | |
626 | for (i = 0; i < 3; i++) |
627 | voutctrl[i] = cx25840_read(client, addr: 0x404 + i); |
628 | |
629 | if (state->vid_config & CX25840_VCONFIG_FMT_MASK) |
630 | voutctrl[0] &= ~3; |
631 | switch (state->vid_config & CX25840_VCONFIG_FMT_MASK) { |
632 | case CX25840_VCONFIG_FMT_BT656: |
633 | voutctrl[0] |= 1; |
634 | break; |
635 | |
636 | case CX25840_VCONFIG_FMT_VIP11: |
637 | voutctrl[0] |= 2; |
638 | break; |
639 | |
640 | case CX25840_VCONFIG_FMT_VIP2: |
641 | voutctrl[0] |= 3; |
642 | break; |
643 | |
644 | case CX25840_VCONFIG_FMT_BT601: |
645 | /* zero */ |
646 | default: |
647 | break; |
648 | } |
649 | |
650 | CX25840_VCONFIG_SET_BIT(state, CX25840_VCONFIG_RES_MASK, voutctrl, |
651 | 0, 2, CX25840_VCONFIG_RES_10BIT); |
652 | CX25840_VCONFIG_SET_BIT(state, CX25840_VCONFIG_VBIRAW_MASK, voutctrl, |
653 | 0, 3, CX25840_VCONFIG_VBIRAW_ENABLED); |
654 | CX25840_VCONFIG_SET_BIT(state, CX25840_VCONFIG_ANCDATA_MASK, voutctrl, |
655 | 0, 4, CX25840_VCONFIG_ANCDATA_ENABLED); |
656 | CX25840_VCONFIG_SET_BIT(state, CX25840_VCONFIG_TASKBIT_MASK, voutctrl, |
657 | 0, 5, CX25840_VCONFIG_TASKBIT_ONE); |
658 | CX25840_VCONFIG_SET_BIT(state, CX25840_VCONFIG_ACTIVE_MASK, voutctrl, |
659 | 1, 2, CX25840_VCONFIG_ACTIVE_HORIZONTAL); |
660 | CX25840_VCONFIG_SET_BIT(state, CX25840_VCONFIG_VALID_MASK, voutctrl, |
661 | 1, 3, CX25840_VCONFIG_VALID_ANDACTIVE); |
662 | CX25840_VCONFIG_SET_BIT(state, CX25840_VCONFIG_HRESETW_MASK, voutctrl, |
663 | 1, 4, CX25840_VCONFIG_HRESETW_PIXCLK); |
664 | |
665 | if (state->vid_config & CX25840_VCONFIG_CLKGATE_MASK) |
666 | voutctrl[1] &= ~(3 << 6); |
667 | switch (state->vid_config & CX25840_VCONFIG_CLKGATE_MASK) { |
668 | case CX25840_VCONFIG_CLKGATE_VALID: |
669 | voutctrl[1] |= 2; |
670 | break; |
671 | |
672 | case CX25840_VCONFIG_CLKGATE_VALIDACTIVE: |
673 | voutctrl[1] |= 3; |
674 | break; |
675 | |
676 | case CX25840_VCONFIG_CLKGATE_NONE: |
677 | /* zero */ |
678 | default: |
679 | break; |
680 | } |
681 | |
682 | CX25840_VCONFIG_SET_BIT(state, CX25840_VCONFIG_DCMODE_MASK, voutctrl, |
683 | 2, 0, CX25840_VCONFIG_DCMODE_BYTES); |
684 | CX25840_VCONFIG_SET_BIT(state, CX25840_VCONFIG_IDID0S_MASK, voutctrl, |
685 | 2, 1, CX25840_VCONFIG_IDID0S_LINECNT); |
686 | CX25840_VCONFIG_SET_BIT(state, CX25840_VCONFIG_VIPCLAMP_MASK, voutctrl, |
687 | 2, 4, CX25840_VCONFIG_VIPCLAMP_ENABLED); |
688 | |
689 | for (i = 0; i < 3; i++) |
690 | cx25840_write(client, addr: 0x404 + i, value: voutctrl[i]); |
691 | } |
692 | |
693 | static void cx25840_initialize(struct i2c_client *client) |
694 | { |
695 | DEFINE_WAIT(wait); |
696 | struct cx25840_state *state = to_state(sd: i2c_get_clientdata(client)); |
697 | struct workqueue_struct *q; |
698 | |
699 | /* datasheet startup in numbered steps, refer to page 3-77 */ |
700 | /* 2. */ |
701 | cx25840_and_or(client, addr: 0x803, and_mask: ~0x10, or_value: 0x00); |
702 | /* |
703 | * The default of this register should be 4, but I get 0 instead. |
704 | * Set this register to 4 manually. |
705 | */ |
706 | cx25840_write(client, addr: 0x000, value: 0x04); |
707 | /* 3. */ |
708 | init_dll1(client); |
709 | init_dll2(client); |
710 | cx25840_write(client, addr: 0x136, value: 0x0a); |
711 | /* 4. */ |
712 | cx25840_write(client, addr: 0x13c, value: 0x01); |
713 | cx25840_write(client, addr: 0x13c, value: 0x00); |
714 | /* 5. */ |
715 | /* |
716 | * Do the firmware load in a work handler to prevent. |
717 | * Otherwise the kernel is blocked waiting for the |
718 | * bit-banging i2c interface to finish uploading the |
719 | * firmware. |
720 | */ |
721 | INIT_WORK(&state->fw_work, cx25840_work_handler); |
722 | init_waitqueue_head(&state->fw_wait); |
723 | q = create_singlethread_workqueue("cx25840_fw" ); |
724 | if (q) { |
725 | prepare_to_wait(wq_head: &state->fw_wait, wq_entry: &wait, TASK_UNINTERRUPTIBLE); |
726 | queue_work(wq: q, work: &state->fw_work); |
727 | schedule(); |
728 | finish_wait(wq_head: &state->fw_wait, wq_entry: &wait); |
729 | destroy_workqueue(wq: q); |
730 | } |
731 | |
732 | /* 6. */ |
733 | cx25840_write(client, addr: 0x115, value: 0x8c); |
734 | cx25840_write(client, addr: 0x116, value: 0x07); |
735 | cx25840_write(client, addr: 0x118, value: 0x02); |
736 | /* 7. */ |
737 | cx25840_write(client, addr: 0x4a5, value: 0x80); |
738 | cx25840_write(client, addr: 0x4a5, value: 0x00); |
739 | cx25840_write(client, addr: 0x402, value: 0x00); |
740 | /* 8. */ |
741 | cx25840_and_or(client, addr: 0x401, and_mask: ~0x18, or_value: 0); |
742 | cx25840_and_or(client, addr: 0x4a2, and_mask: ~0x10, or_value: 0x10); |
743 | /* steps 8c and 8d are done in change_input() */ |
744 | /* 10. */ |
745 | cx25840_write(client, addr: 0x8d3, value: 0x1f); |
746 | cx25840_write(client, addr: 0x8e3, value: 0x03); |
747 | |
748 | cx25840_std_setup(client); |
749 | |
750 | /* trial and error says these are needed to get audio */ |
751 | cx25840_write(client, addr: 0x914, value: 0xa0); |
752 | cx25840_write(client, addr: 0x918, value: 0xa0); |
753 | cx25840_write(client, addr: 0x919, value: 0x01); |
754 | |
755 | /* stereo preferred */ |
756 | cx25840_write(client, addr: 0x809, value: 0x04); |
757 | /* AC97 shift */ |
758 | cx25840_write(client, addr: 0x8cf, value: 0x0f); |
759 | |
760 | /* (re)set input */ |
761 | set_input(client, vid_input: state->vid_input, aud_input: state->aud_input); |
762 | |
763 | if (state->generic_mode) |
764 | cx25840_vconfig_apply(client); |
765 | |
766 | /* start microcontroller */ |
767 | cx25840_and_or(client, addr: 0x803, and_mask: ~0x10, or_value: 0x10); |
768 | } |
769 | |
770 | static void cx23885_initialize(struct i2c_client *client) |
771 | { |
772 | DEFINE_WAIT(wait); |
773 | struct cx25840_state *state = to_state(sd: i2c_get_clientdata(client)); |
774 | u32 clk_freq = 0; |
775 | struct workqueue_struct *q; |
776 | |
777 | /* cx23885 sets hostdata to clk_freq pointer */ |
778 | if (v4l2_get_subdev_hostdata(sd: &state->sd)) |
779 | clk_freq = *((u32 *)v4l2_get_subdev_hostdata(sd: &state->sd)); |
780 | |
781 | /* |
782 | * Come out of digital power down |
783 | * The CX23888, at least, needs this, otherwise registers aside from |
784 | * 0x0-0x2 can't be read or written. |
785 | */ |
786 | cx25840_write(client, addr: 0x000, value: 0); |
787 | |
788 | /* Internal Reset */ |
789 | cx25840_and_or(client, addr: 0x102, and_mask: ~0x01, or_value: 0x01); |
790 | cx25840_and_or(client, addr: 0x102, and_mask: ~0x01, or_value: 0x00); |
791 | |
792 | /* Stop microcontroller */ |
793 | cx25840_and_or(client, addr: 0x803, and_mask: ~0x10, or_value: 0x00); |
794 | |
795 | /* DIF in reset? */ |
796 | cx25840_write(client, addr: 0x398, value: 0); |
797 | |
798 | /* |
799 | * Trust the default xtal, no division |
800 | * '885: 28.636363... MHz |
801 | * '887: 25.000000 MHz |
802 | * '888: 50.000000 MHz |
803 | */ |
804 | cx25840_write(client, addr: 0x2, value: 0x76); |
805 | |
806 | /* Power up all the PLL's and DLL */ |
807 | cx25840_write(client, addr: 0x1, value: 0x40); |
808 | |
809 | /* Sys PLL */ |
810 | switch (state->id) { |
811 | case CX23888_AV: |
812 | /* |
813 | * 50.0 MHz * (0xb + 0xe8ba26/0x2000000)/4 = 5 * 28.636363 MHz |
814 | * 572.73 MHz before post divide |
815 | */ |
816 | if (clk_freq == 25000000) { |
817 | /* 888/ImpactVCBe or 25Mhz xtal */ |
818 | ; /* nothing to do */ |
819 | } else { |
820 | /* HVR1850 or 50MHz xtal */ |
821 | cx25840_write(client, addr: 0x2, value: 0x71); |
822 | } |
823 | cx25840_write4(client, addr: 0x11c, value: 0x01d1744c); |
824 | cx25840_write4(client, addr: 0x118, value: 0x00000416); |
825 | cx25840_write4(client, addr: 0x404, value: 0x0010253e); |
826 | cx25840_write4(client, addr: 0x42c, value: 0x42600000); |
827 | cx25840_write4(client, addr: 0x44c, value: 0x161f1000); |
828 | break; |
829 | case CX23887_AV: |
830 | /* |
831 | * 25.0 MHz * (0x16 + 0x1d1744c/0x2000000)/4 = 5 * 28.636363 MHz |
832 | * 572.73 MHz before post divide |
833 | */ |
834 | cx25840_write4(client, addr: 0x11c, value: 0x01d1744c); |
835 | cx25840_write4(client, addr: 0x118, value: 0x00000416); |
836 | break; |
837 | case CX23885_AV: |
838 | default: |
839 | /* |
840 | * 28.636363 MHz * (0x14 + 0x0/0x2000000)/4 = 5 * 28.636363 MHz |
841 | * 572.73 MHz before post divide |
842 | */ |
843 | cx25840_write4(client, addr: 0x11c, value: 0x00000000); |
844 | cx25840_write4(client, addr: 0x118, value: 0x00000414); |
845 | break; |
846 | } |
847 | |
848 | /* Disable DIF bypass */ |
849 | cx25840_write4(client, addr: 0x33c, value: 0x00000001); |
850 | |
851 | /* DIF Src phase inc */ |
852 | cx25840_write4(client, addr: 0x340, value: 0x0df7df83); |
853 | |
854 | /* |
855 | * Vid PLL |
856 | * Setup for a BT.656 pixel clock of 13.5 Mpixels/second |
857 | * |
858 | * 28.636363 MHz * (0xf + 0x02be2c9/0x2000000)/4 = 8 * 13.5 MHz |
859 | * 432.0 MHz before post divide |
860 | */ |
861 | |
862 | /* HVR1850 */ |
863 | switch (state->id) { |
864 | case CX23888_AV: |
865 | if (clk_freq == 25000000) { |
866 | /* 888/ImpactVCBe or 25MHz xtal */ |
867 | cx25840_write4(client, addr: 0x10c, value: 0x01b6db7b); |
868 | cx25840_write4(client, addr: 0x108, value: 0x00000512); |
869 | } else { |
870 | /* 888/HVR1250 or 50MHz xtal */ |
871 | cx25840_write4(client, addr: 0x10c, value: 0x13333333); |
872 | cx25840_write4(client, addr: 0x108, value: 0x00000515); |
873 | } |
874 | break; |
875 | default: |
876 | cx25840_write4(client, addr: 0x10c, value: 0x002be2c9); |
877 | cx25840_write4(client, addr: 0x108, value: 0x0000040f); |
878 | } |
879 | |
880 | /* Luma */ |
881 | cx25840_write4(client, addr: 0x414, value: 0x00107d12); |
882 | |
883 | /* Chroma */ |
884 | if (is_cx23888(state)) |
885 | cx25840_write4(client, addr: 0x418, value: 0x1d008282); |
886 | else |
887 | cx25840_write4(client, addr: 0x420, value: 0x3d008282); |
888 | |
889 | /* |
890 | * Aux PLL |
891 | * Initial setup for audio sample clock: |
892 | * 48 ksps, 16 bits/sample, x160 multiplier = 122.88 MHz |
893 | * Initial I2S output/master clock(?): |
894 | * 48 ksps, 16 bits/sample, x16 multiplier = 12.288 MHz |
895 | */ |
896 | switch (state->id) { |
897 | case CX23888_AV: |
898 | /* |
899 | * 50.0 MHz * (0x7 + 0x0bedfa4/0x2000000)/3 = 122.88 MHz |
900 | * 368.64 MHz before post divide |
901 | * 122.88 MHz / 0xa = 12.288 MHz |
902 | */ |
903 | /* HVR1850 or 50MHz xtal or 25MHz xtal */ |
904 | cx25840_write4(client, addr: 0x114, value: 0x017dbf48); |
905 | cx25840_write4(client, addr: 0x110, value: 0x000a030e); |
906 | break; |
907 | case CX23887_AV: |
908 | /* |
909 | * 25.0 MHz * (0xe + 0x17dbf48/0x2000000)/3 = 122.88 MHz |
910 | * 368.64 MHz before post divide |
911 | * 122.88 MHz / 0xa = 12.288 MHz |
912 | */ |
913 | cx25840_write4(client, addr: 0x114, value: 0x017dbf48); |
914 | cx25840_write4(client, addr: 0x110, value: 0x000a030e); |
915 | break; |
916 | case CX23885_AV: |
917 | default: |
918 | /* |
919 | * 28.636363 MHz * (0xc + 0x1bf0c9e/0x2000000)/3 = 122.88 MHz |
920 | * 368.64 MHz before post divide |
921 | * 122.88 MHz / 0xa = 12.288 MHz |
922 | */ |
923 | cx25840_write4(client, addr: 0x114, value: 0x01bf0c9e); |
924 | cx25840_write4(client, addr: 0x110, value: 0x000a030c); |
925 | break; |
926 | } |
927 | |
928 | /* ADC2 input select */ |
929 | cx25840_write(client, addr: 0x102, value: 0x10); |
930 | |
931 | /* VIN1 & VIN5 */ |
932 | cx25840_write(client, addr: 0x103, value: 0x11); |
933 | |
934 | /* Enable format auto detect */ |
935 | cx25840_write(client, addr: 0x400, value: 0); |
936 | /* Fast subchroma lock */ |
937 | /* White crush, Chroma AGC & Chroma Killer enabled */ |
938 | cx25840_write(client, addr: 0x401, value: 0xe8); |
939 | |
940 | /* Select AFE clock pad output source */ |
941 | cx25840_write(client, addr: 0x144, value: 0x05); |
942 | |
943 | /* Drive GPIO2 direction and values for HVR1700 |
944 | * where an onboard mux selects the output of demodulator |
945 | * vs the 417. Failure to set this results in no DTV. |
946 | * It's safe to set this across all Hauppauge boards |
947 | * currently, regardless of the board type. |
948 | */ |
949 | cx25840_write(client, addr: 0x160, value: 0x1d); |
950 | cx25840_write(client, addr: 0x164, value: 0x00); |
951 | |
952 | /* |
953 | * Do the firmware load in a work handler to prevent. |
954 | * Otherwise the kernel is blocked waiting for the |
955 | * bit-banging i2c interface to finish uploading the |
956 | * firmware. |
957 | */ |
958 | INIT_WORK(&state->fw_work, cx25840_work_handler); |
959 | init_waitqueue_head(&state->fw_wait); |
960 | q = create_singlethread_workqueue("cx25840_fw" ); |
961 | if (q) { |
962 | prepare_to_wait(wq_head: &state->fw_wait, wq_entry: &wait, TASK_UNINTERRUPTIBLE); |
963 | queue_work(wq: q, work: &state->fw_work); |
964 | schedule(); |
965 | finish_wait(wq_head: &state->fw_wait, wq_entry: &wait); |
966 | destroy_workqueue(wq: q); |
967 | } |
968 | |
969 | /* |
970 | * Call the cx23888 specific std setup func, we no longer rely on |
971 | * the generic cx24840 func. |
972 | */ |
973 | if (is_cx23888(state)) |
974 | cx23888_std_setup(client); |
975 | else |
976 | cx25840_std_setup(client); |
977 | |
978 | /* (re)set input */ |
979 | set_input(client, vid_input: state->vid_input, aud_input: state->aud_input); |
980 | |
981 | /* start microcontroller */ |
982 | cx25840_and_or(client, addr: 0x803, and_mask: ~0x10, or_value: 0x10); |
983 | |
984 | /* Disable and clear video interrupts - we don't use them */ |
985 | cx25840_write4(client, CX25840_VID_INT_STAT_REG, value: 0xffffffff); |
986 | |
987 | /* Disable and clear audio interrupts - we don't use them */ |
988 | cx25840_write(client, CX25840_AUD_INT_CTRL_REG, value: 0xff); |
989 | cx25840_write(client, CX25840_AUD_INT_STAT_REG, value: 0xff); |
990 | |
991 | /* CC raw enable */ |
992 | |
993 | /* |
994 | * - VIP 1.1 control codes - 10bit, blue field enable. |
995 | * - enable raw data during vertical blanking. |
996 | * - enable ancillary Data insertion for 656 or VIP. |
997 | */ |
998 | cx25840_write4(client, addr: 0x404, value: 0x0010253e); |
999 | |
1000 | /* CC on - VBI_LINE_CTRL3, FLD_VBI_MD_LINE12 */ |
1001 | cx25840_write(client, addr: state->vbi_regs_offset + 0x42f, value: 0x66); |
1002 | |
1003 | /* HVR-1250 / HVR1850 DIF related */ |
1004 | /* Power everything up */ |
1005 | cx25840_write4(client, addr: 0x130, value: 0x0); |
1006 | |
1007 | /* SRC_COMB_CFG */ |
1008 | if (is_cx23888(state)) |
1009 | cx25840_write4(client, addr: 0x454, value: 0x6628021F); |
1010 | else |
1011 | cx25840_write4(client, addr: 0x478, value: 0x6628021F); |
1012 | |
1013 | /* AFE_CLK_OUT_CTRL - Select the clock output source as output */ |
1014 | cx25840_write4(client, addr: 0x144, value: 0x5); |
1015 | |
1016 | /* I2C_OUT_CTL - I2S output configuration as |
1017 | * Master, Sony, Left justified, left sample on WS=1 |
1018 | */ |
1019 | cx25840_write4(client, addr: 0x918, value: 0x1a0); |
1020 | |
1021 | /* AFE_DIAG_CTRL1 */ |
1022 | cx25840_write4(client, addr: 0x134, value: 0x000a1800); |
1023 | |
1024 | /* AFE_DIAG_CTRL3 - Inverted Polarity for Audio and Video */ |
1025 | cx25840_write4(client, addr: 0x13c, value: 0x00310000); |
1026 | } |
1027 | |
1028 | /* ----------------------------------------------------------------------- */ |
1029 | |
1030 | static void cx231xx_initialize(struct i2c_client *client) |
1031 | { |
1032 | DEFINE_WAIT(wait); |
1033 | struct cx25840_state *state = to_state(sd: i2c_get_clientdata(client)); |
1034 | struct workqueue_struct *q; |
1035 | |
1036 | /* Internal Reset */ |
1037 | cx25840_and_or(client, addr: 0x102, and_mask: ~0x01, or_value: 0x01); |
1038 | cx25840_and_or(client, addr: 0x102, and_mask: ~0x01, or_value: 0x00); |
1039 | |
1040 | /* Stop microcontroller */ |
1041 | cx25840_and_or(client, addr: 0x803, and_mask: ~0x10, or_value: 0x00); |
1042 | |
1043 | /* DIF in reset? */ |
1044 | cx25840_write(client, addr: 0x398, value: 0); |
1045 | |
1046 | /* Trust the default xtal, no division */ |
1047 | /* This changes for the cx23888 products */ |
1048 | cx25840_write(client, addr: 0x2, value: 0x76); |
1049 | |
1050 | /* Bring down the regulator for AUX clk */ |
1051 | cx25840_write(client, addr: 0x1, value: 0x40); |
1052 | |
1053 | /* Disable DIF bypass */ |
1054 | cx25840_write4(client, addr: 0x33c, value: 0x00000001); |
1055 | |
1056 | /* DIF Src phase inc */ |
1057 | cx25840_write4(client, addr: 0x340, value: 0x0df7df83); |
1058 | |
1059 | /* Luma */ |
1060 | cx25840_write4(client, addr: 0x414, value: 0x00107d12); |
1061 | |
1062 | /* Chroma */ |
1063 | cx25840_write4(client, addr: 0x420, value: 0x3d008282); |
1064 | |
1065 | /* ADC2 input select */ |
1066 | cx25840_write(client, addr: 0x102, value: 0x10); |
1067 | |
1068 | /* VIN1 & VIN5 */ |
1069 | cx25840_write(client, addr: 0x103, value: 0x11); |
1070 | |
1071 | /* Enable format auto detect */ |
1072 | cx25840_write(client, addr: 0x400, value: 0); |
1073 | /* Fast subchroma lock */ |
1074 | /* White crush, Chroma AGC & Chroma Killer enabled */ |
1075 | cx25840_write(client, addr: 0x401, value: 0xe8); |
1076 | |
1077 | /* |
1078 | * Do the firmware load in a work handler to prevent. |
1079 | * Otherwise the kernel is blocked waiting for the |
1080 | * bit-banging i2c interface to finish uploading the |
1081 | * firmware. |
1082 | */ |
1083 | INIT_WORK(&state->fw_work, cx25840_work_handler); |
1084 | init_waitqueue_head(&state->fw_wait); |
1085 | q = create_singlethread_workqueue("cx25840_fw" ); |
1086 | if (q) { |
1087 | prepare_to_wait(wq_head: &state->fw_wait, wq_entry: &wait, TASK_UNINTERRUPTIBLE); |
1088 | queue_work(wq: q, work: &state->fw_work); |
1089 | schedule(); |
1090 | finish_wait(wq_head: &state->fw_wait, wq_entry: &wait); |
1091 | destroy_workqueue(wq: q); |
1092 | } |
1093 | |
1094 | cx25840_std_setup(client); |
1095 | |
1096 | /* (re)set input */ |
1097 | set_input(client, vid_input: state->vid_input, aud_input: state->aud_input); |
1098 | |
1099 | /* start microcontroller */ |
1100 | cx25840_and_or(client, addr: 0x803, and_mask: ~0x10, or_value: 0x10); |
1101 | |
1102 | /* CC raw enable */ |
1103 | cx25840_write(client, addr: 0x404, value: 0x0b); |
1104 | |
1105 | /* CC on */ |
1106 | cx25840_write(client, addr: 0x42f, value: 0x66); |
1107 | cx25840_write4(client, addr: 0x474, value: 0x1e1e601a); |
1108 | } |
1109 | |
1110 | /* ----------------------------------------------------------------------- */ |
1111 | |
1112 | void cx25840_std_setup(struct i2c_client *client) |
1113 | { |
1114 | struct cx25840_state *state = to_state(sd: i2c_get_clientdata(client)); |
1115 | v4l2_std_id std = state->std; |
1116 | int hblank, hactive, burst, vblank, vactive, sc; |
1117 | int vblank656, src_decimation; |
1118 | int luma_lpf, uv_lpf, comb; |
1119 | u32 pll_int, pll_frac, pll_post; |
1120 | |
1121 | /* datasheet startup, step 8d */ |
1122 | if (std & ~V4L2_STD_NTSC) |
1123 | cx25840_write(client, addr: 0x49f, value: 0x11); |
1124 | else |
1125 | cx25840_write(client, addr: 0x49f, value: 0x14); |
1126 | |
1127 | /* generic mode uses the values that the chip autoconfig would set */ |
1128 | if (std & V4L2_STD_625_50) { |
1129 | hblank = 132; |
1130 | hactive = 720; |
1131 | burst = 93; |
1132 | if (state->generic_mode) { |
1133 | vblank = 34; |
1134 | vactive = 576; |
1135 | vblank656 = 38; |
1136 | } else { |
1137 | vblank = 36; |
1138 | vactive = 580; |
1139 | vblank656 = 40; |
1140 | } |
1141 | src_decimation = 0x21f; |
1142 | luma_lpf = 2; |
1143 | |
1144 | if (std & V4L2_STD_SECAM) { |
1145 | uv_lpf = 0; |
1146 | comb = 0; |
1147 | sc = 0x0a425f; |
1148 | } else if (std == V4L2_STD_PAL_Nc) { |
1149 | if (state->generic_mode) { |
1150 | burst = 95; |
1151 | luma_lpf = 1; |
1152 | } |
1153 | uv_lpf = 1; |
1154 | comb = 0x20; |
1155 | sc = 556453; |
1156 | } else { |
1157 | uv_lpf = 1; |
1158 | comb = 0x20; |
1159 | sc = 688739; |
1160 | } |
1161 | } else { |
1162 | hactive = 720; |
1163 | hblank = 122; |
1164 | vactive = 487; |
1165 | luma_lpf = 1; |
1166 | uv_lpf = 1; |
1167 | if (state->generic_mode) { |
1168 | vblank = 20; |
1169 | vblank656 = 24; |
1170 | } |
1171 | |
1172 | src_decimation = 0x21f; |
1173 | if (std == V4L2_STD_PAL_60) { |
1174 | if (!state->generic_mode) { |
1175 | vblank = 26; |
1176 | vblank656 = 26; |
1177 | burst = 0x5b; |
1178 | } else { |
1179 | burst = 0x59; |
1180 | } |
1181 | luma_lpf = 2; |
1182 | comb = 0x20; |
1183 | sc = 688739; |
1184 | } else if (std == V4L2_STD_PAL_M) { |
1185 | vblank = 20; |
1186 | vblank656 = 24; |
1187 | burst = 0x61; |
1188 | comb = 0x20; |
1189 | sc = 555452; |
1190 | } else { |
1191 | if (!state->generic_mode) { |
1192 | vblank = 26; |
1193 | vblank656 = 26; |
1194 | } |
1195 | burst = 0x5b; |
1196 | comb = 0x66; |
1197 | sc = 556063; |
1198 | } |
1199 | } |
1200 | |
1201 | /* DEBUG: Displays configured PLL frequency */ |
1202 | if (!is_cx231xx(state)) { |
1203 | pll_int = cx25840_read(client, addr: 0x108); |
1204 | pll_frac = cx25840_read4(client, addr: 0x10c) & 0x1ffffff; |
1205 | pll_post = cx25840_read(client, addr: 0x109); |
1206 | v4l_dbg(1, cx25840_debug, client, |
1207 | "PLL regs = int: %u, frac: %u, post: %u\n" , |
1208 | pll_int, pll_frac, pll_post); |
1209 | |
1210 | if (pll_post) { |
1211 | int fin, fsc; |
1212 | int pll = (28636363L * ((((u64)pll_int) << 25L) + pll_frac)) >> 25L; |
1213 | |
1214 | pll /= pll_post; |
1215 | v4l_dbg(1, cx25840_debug, client, |
1216 | "PLL = %d.%06d MHz\n" , |
1217 | pll / 1000000, pll % 1000000); |
1218 | v4l_dbg(1, cx25840_debug, client, |
1219 | "PLL/8 = %d.%06d MHz\n" , |
1220 | pll / 8000000, (pll / 8) % 1000000); |
1221 | |
1222 | fin = ((u64)src_decimation * pll) >> 12; |
1223 | v4l_dbg(1, cx25840_debug, client, |
1224 | "ADC Sampling freq = %d.%06d MHz\n" , |
1225 | fin / 1000000, fin % 1000000); |
1226 | |
1227 | fsc = (((u64)sc) * pll) >> 24L; |
1228 | v4l_dbg(1, cx25840_debug, client, |
1229 | "Chroma sub-carrier freq = %d.%06d MHz\n" , |
1230 | fsc / 1000000, fsc % 1000000); |
1231 | |
1232 | v4l_dbg(1, cx25840_debug, client, |
1233 | "hblank %i, hactive %i, vblank %i, vactive %i, vblank656 %i, src_dec %i, burst 0x%02x, luma_lpf %i, uv_lpf %i, comb 0x%02x, sc 0x%06x\n" , |
1234 | hblank, hactive, vblank, vactive, vblank656, |
1235 | src_decimation, burst, luma_lpf, uv_lpf, |
1236 | comb, sc); |
1237 | } |
1238 | } |
1239 | |
1240 | /* Sets horizontal blanking delay and active lines */ |
1241 | cx25840_write(client, addr: 0x470, value: hblank); |
1242 | cx25840_write(client, addr: 0x471, |
1243 | value: (((hblank >> 8) & 0x3) | (hactive << 4)) & 0xff); |
1244 | cx25840_write(client, addr: 0x472, value: hactive >> 4); |
1245 | |
1246 | /* Sets burst gate delay */ |
1247 | cx25840_write(client, addr: 0x473, value: burst); |
1248 | |
1249 | /* Sets vertical blanking delay and active duration */ |
1250 | cx25840_write(client, addr: 0x474, value: vblank); |
1251 | cx25840_write(client, addr: 0x475, |
1252 | value: (((vblank >> 8) & 0x3) | (vactive << 4)) & 0xff); |
1253 | cx25840_write(client, addr: 0x476, value: vactive >> 4); |
1254 | cx25840_write(client, addr: 0x477, value: vblank656); |
1255 | |
1256 | /* Sets src decimation rate */ |
1257 | cx25840_write(client, addr: 0x478, value: src_decimation & 0xff); |
1258 | cx25840_write(client, addr: 0x479, value: (src_decimation >> 8) & 0xff); |
1259 | |
1260 | /* Sets Luma and UV Low pass filters */ |
1261 | cx25840_write(client, addr: 0x47a, value: luma_lpf << 6 | ((uv_lpf << 4) & 0x30)); |
1262 | |
1263 | /* Enables comb filters */ |
1264 | cx25840_write(client, addr: 0x47b, value: comb); |
1265 | |
1266 | /* Sets SC Step*/ |
1267 | cx25840_write(client, addr: 0x47c, value: sc); |
1268 | cx25840_write(client, addr: 0x47d, value: (sc >> 8) & 0xff); |
1269 | cx25840_write(client, addr: 0x47e, value: (sc >> 16) & 0xff); |
1270 | |
1271 | /* Sets VBI parameters */ |
1272 | if (std & V4L2_STD_625_50) { |
1273 | cx25840_write(client, addr: 0x47f, value: 0x01); |
1274 | state->vbi_line_offset = 5; |
1275 | } else { |
1276 | cx25840_write(client, addr: 0x47f, value: 0x00); |
1277 | state->vbi_line_offset = 8; |
1278 | } |
1279 | } |
1280 | |
1281 | /* ----------------------------------------------------------------------- */ |
1282 | |
1283 | static void input_change(struct i2c_client *client) |
1284 | { |
1285 | struct cx25840_state *state = to_state(sd: i2c_get_clientdata(client)); |
1286 | v4l2_std_id std = state->std; |
1287 | |
1288 | /* Follow step 8c and 8d of section 3.16 in the cx25840 datasheet */ |
1289 | if (std & V4L2_STD_SECAM) { |
1290 | cx25840_write(client, addr: 0x402, value: 0); |
1291 | } else { |
1292 | cx25840_write(client, addr: 0x402, value: 0x04); |
1293 | cx25840_write(client, addr: 0x49f, |
1294 | value: (std & V4L2_STD_NTSC) ? 0x14 : 0x11); |
1295 | } |
1296 | cx25840_and_or(client, addr: 0x401, and_mask: ~0x60, or_value: 0); |
1297 | cx25840_and_or(client, addr: 0x401, and_mask: ~0x60, or_value: 0x60); |
1298 | |
1299 | /* Don't write into audio registers on cx2583x chips */ |
1300 | if (is_cx2583x(state)) |
1301 | return; |
1302 | |
1303 | cx25840_and_or(client, addr: 0x810, and_mask: ~0x01, or_value: 1); |
1304 | |
1305 | if (state->radio) { |
1306 | cx25840_write(client, addr: 0x808, value: 0xf9); |
1307 | cx25840_write(client, addr: 0x80b, value: 0x00); |
1308 | } else if (std & V4L2_STD_525_60) { |
1309 | /* |
1310 | * Certain Hauppauge PVR150 models have a hardware bug |
1311 | * that causes audio to drop out. For these models the |
1312 | * audio standard must be set explicitly. |
1313 | * To be precise: it affects cards with tuner models |
1314 | * 85, 99 and 112 (model numbers from tveeprom). |
1315 | */ |
1316 | int hw_fix = state->pvr150_workaround; |
1317 | |
1318 | if (std == V4L2_STD_NTSC_M_JP) { |
1319 | /* Japan uses EIAJ audio standard */ |
1320 | cx25840_write(client, addr: 0x808, value: hw_fix ? 0x2f : 0xf7); |
1321 | } else if (std == V4L2_STD_NTSC_M_KR) { |
1322 | /* South Korea uses A2 audio standard */ |
1323 | cx25840_write(client, addr: 0x808, value: hw_fix ? 0x3f : 0xf8); |
1324 | } else { |
1325 | /* Others use the BTSC audio standard */ |
1326 | cx25840_write(client, addr: 0x808, value: hw_fix ? 0x1f : 0xf6); |
1327 | } |
1328 | cx25840_write(client, addr: 0x80b, value: 0x00); |
1329 | } else if (std & V4L2_STD_PAL) { |
1330 | /* Autodetect audio standard and audio system */ |
1331 | cx25840_write(client, addr: 0x808, value: 0xff); |
1332 | /* |
1333 | * Since system PAL-L is pretty much non-existent and |
1334 | * not used by any public broadcast network, force |
1335 | * 6.5 MHz carrier to be interpreted as System DK, |
1336 | * this avoids DK audio detection instability |
1337 | */ |
1338 | cx25840_write(client, addr: 0x80b, value: 0x00); |
1339 | } else if (std & V4L2_STD_SECAM) { |
1340 | /* Autodetect audio standard and audio system */ |
1341 | cx25840_write(client, addr: 0x808, value: 0xff); |
1342 | /* |
1343 | * If only one of SECAM-DK / SECAM-L is required, then force |
1344 | * 6.5MHz carrier, else autodetect it |
1345 | */ |
1346 | if ((std & V4L2_STD_SECAM_DK) && |
1347 | !(std & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC))) { |
1348 | /* 6.5 MHz carrier to be interpreted as System DK */ |
1349 | cx25840_write(client, addr: 0x80b, value: 0x00); |
1350 | } else if (!(std & V4L2_STD_SECAM_DK) && |
1351 | (std & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC))) { |
1352 | /* 6.5 MHz carrier to be interpreted as System L */ |
1353 | cx25840_write(client, addr: 0x80b, value: 0x08); |
1354 | } else { |
1355 | /* 6.5 MHz carrier to be autodetected */ |
1356 | cx25840_write(client, addr: 0x80b, value: 0x10); |
1357 | } |
1358 | } |
1359 | |
1360 | cx25840_and_or(client, addr: 0x810, and_mask: ~0x01, or_value: 0); |
1361 | } |
1362 | |
1363 | static int set_input(struct i2c_client *client, |
1364 | enum cx25840_video_input vid_input, |
1365 | enum cx25840_audio_input aud_input) |
1366 | { |
1367 | struct cx25840_state *state = to_state(sd: i2c_get_clientdata(client)); |
1368 | u8 is_composite = (vid_input >= CX25840_COMPOSITE1 && |
1369 | vid_input <= CX25840_COMPOSITE8); |
1370 | u8 is_component = (vid_input & CX25840_COMPONENT_ON) == |
1371 | CX25840_COMPONENT_ON; |
1372 | u8 is_dif = (vid_input & CX25840_DIF_ON) == |
1373 | CX25840_DIF_ON; |
1374 | u8 is_svideo = (vid_input & CX25840_SVIDEO_ON) == |
1375 | CX25840_SVIDEO_ON; |
1376 | int luma = vid_input & 0xf0; |
1377 | int chroma = vid_input & 0xf00; |
1378 | u8 reg; |
1379 | u32 val; |
1380 | |
1381 | v4l_dbg(1, cx25840_debug, client, |
1382 | "decoder set video input %d, audio input %d\n" , |
1383 | vid_input, aud_input); |
1384 | |
1385 | if (vid_input >= CX25840_VIN1_CH1) { |
1386 | v4l_dbg(1, cx25840_debug, client, "vid_input 0x%x\n" , |
1387 | vid_input); |
1388 | reg = vid_input & 0xff; |
1389 | is_composite = !is_component && |
1390 | ((vid_input & CX25840_SVIDEO_ON) != CX25840_SVIDEO_ON); |
1391 | |
1392 | v4l_dbg(1, cx25840_debug, client, "mux cfg 0x%x comp=%d\n" , |
1393 | reg, is_composite); |
1394 | } else if (is_composite) { |
1395 | reg = 0xf0 + (vid_input - CX25840_COMPOSITE1); |
1396 | } else { |
1397 | if ((vid_input & ~0xff0) || |
1398 | luma < CX25840_SVIDEO_LUMA1 || |
1399 | luma > CX25840_SVIDEO_LUMA8 || |
1400 | chroma < CX25840_SVIDEO_CHROMA4 || |
1401 | chroma > CX25840_SVIDEO_CHROMA8) { |
1402 | v4l_err(client, "0x%04x is not a valid video input!\n" , |
1403 | vid_input); |
1404 | return -EINVAL; |
1405 | } |
1406 | reg = 0xf0 + ((luma - CX25840_SVIDEO_LUMA1) >> 4); |
1407 | if (chroma >= CX25840_SVIDEO_CHROMA7) { |
1408 | reg &= 0x3f; |
1409 | reg |= (chroma - CX25840_SVIDEO_CHROMA7) >> 2; |
1410 | } else { |
1411 | reg &= 0xcf; |
1412 | reg |= (chroma - CX25840_SVIDEO_CHROMA4) >> 4; |
1413 | } |
1414 | } |
1415 | |
1416 | /* The caller has previously prepared the correct routing |
1417 | * configuration in reg (for the cx23885) so we have no |
1418 | * need to attempt to flip bits for earlier av decoders. |
1419 | */ |
1420 | if (!is_cx2388x(state) && !is_cx231xx(state)) { |
1421 | switch (aud_input) { |
1422 | case CX25840_AUDIO_SERIAL: |
1423 | /* do nothing, use serial audio input */ |
1424 | break; |
1425 | case CX25840_AUDIO4: |
1426 | reg &= ~0x30; |
1427 | break; |
1428 | case CX25840_AUDIO5: |
1429 | reg &= ~0x30; |
1430 | reg |= 0x10; |
1431 | break; |
1432 | case CX25840_AUDIO6: |
1433 | reg &= ~0x30; |
1434 | reg |= 0x20; |
1435 | break; |
1436 | case CX25840_AUDIO7: |
1437 | reg &= ~0xc0; |
1438 | break; |
1439 | case CX25840_AUDIO8: |
1440 | reg &= ~0xc0; |
1441 | reg |= 0x40; |
1442 | break; |
1443 | default: |
1444 | v4l_err(client, "0x%04x is not a valid audio input!\n" , |
1445 | aud_input); |
1446 | return -EINVAL; |
1447 | } |
1448 | } |
1449 | |
1450 | cx25840_write(client, addr: 0x103, value: reg); |
1451 | |
1452 | /* Set INPUT_MODE to Composite, S-Video or Component */ |
1453 | if (is_component) |
1454 | cx25840_and_or(client, addr: 0x401, and_mask: ~0x6, or_value: 0x6); |
1455 | else |
1456 | cx25840_and_or(client, addr: 0x401, and_mask: ~0x6, or_value: is_composite ? 0 : 0x02); |
1457 | |
1458 | if (is_cx2388x(state)) { |
1459 | /* Enable or disable the DIF for tuner use */ |
1460 | if (is_dif) { |
1461 | cx25840_and_or(client, addr: 0x102, and_mask: ~0x80, or_value: 0x80); |
1462 | |
1463 | /* Set of defaults for NTSC and PAL */ |
1464 | cx25840_write4(client, addr: 0x31c, value: 0xc2262600); |
1465 | cx25840_write4(client, addr: 0x320, value: 0xc2262600); |
1466 | |
1467 | /* 18271 IF - Nobody else yet uses a different |
1468 | * tuner with the DIF, so these are reasonable |
1469 | * assumptions (HVR1250 and HVR1850 specific). |
1470 | */ |
1471 | cx25840_write4(client, addr: 0x318, value: 0xda262600); |
1472 | cx25840_write4(client, addr: 0x33c, value: 0x2a24c800); |
1473 | cx25840_write4(client, addr: 0x104, value: 0x0704dd00); |
1474 | } else { |
1475 | cx25840_write4(client, addr: 0x300, value: 0x015c28f5); |
1476 | |
1477 | cx25840_and_or(client, addr: 0x102, and_mask: ~0x80, or_value: 0); |
1478 | cx25840_write4(client, addr: 0x340, value: 0xdf7df83); |
1479 | cx25840_write4(client, addr: 0x104, value: 0x0704dd80); |
1480 | cx25840_write4(client, addr: 0x314, value: 0x22400600); |
1481 | cx25840_write4(client, addr: 0x318, value: 0x40002600); |
1482 | cx25840_write4(client, addr: 0x324, value: 0x40002600); |
1483 | cx25840_write4(client, addr: 0x32c, value: 0x0250e620); |
1484 | cx25840_write4(client, addr: 0x39c, value: 0x01FF0B00); |
1485 | |
1486 | cx25840_write4(client, addr: 0x410, value: 0xffff0dbf); |
1487 | cx25840_write4(client, addr: 0x414, value: 0x00137d03); |
1488 | |
1489 | if (is_cx23888(state)) { |
1490 | /* 888 MISC_TIM_CTRL */ |
1491 | cx25840_write4(client, addr: 0x42c, value: 0x42600000); |
1492 | /* 888 FIELD_COUNT */ |
1493 | cx25840_write4(client, addr: 0x430, value: 0x0000039b); |
1494 | /* 888 VSCALE_CTRL */ |
1495 | cx25840_write4(client, addr: 0x438, value: 0x00000000); |
1496 | /* 888 DFE_CTRL1 */ |
1497 | cx25840_write4(client, addr: 0x440, value: 0xF8E3E824); |
1498 | /* 888 DFE_CTRL2 */ |
1499 | cx25840_write4(client, addr: 0x444, value: 0x401040dc); |
1500 | /* 888 DFE_CTRL3 */ |
1501 | cx25840_write4(client, addr: 0x448, value: 0xcd3f02a0); |
1502 | /* 888 PLL_CTRL */ |
1503 | cx25840_write4(client, addr: 0x44c, value: 0x161f1000); |
1504 | /* 888 HTL_CTRL */ |
1505 | cx25840_write4(client, addr: 0x450, value: 0x00000802); |
1506 | } |
1507 | cx25840_write4(client, addr: 0x91c, value: 0x01000000); |
1508 | cx25840_write4(client, addr: 0x8e0, value: 0x03063870); |
1509 | cx25840_write4(client, addr: 0x8d4, value: 0x7FFF0024); |
1510 | cx25840_write4(client, addr: 0x8d0, value: 0x00063073); |
1511 | |
1512 | cx25840_write4(client, addr: 0x8c8, value: 0x00010000); |
1513 | cx25840_write4(client, addr: 0x8cc, value: 0x00080023); |
1514 | |
1515 | /* DIF BYPASS */ |
1516 | cx25840_write4(client, addr: 0x33c, value: 0x2a04c800); |
1517 | } |
1518 | |
1519 | /* Reset the DIF */ |
1520 | cx25840_write4(client, addr: 0x398, value: 0); |
1521 | } |
1522 | |
1523 | if (!is_cx2388x(state) && !is_cx231xx(state)) { |
1524 | /* Set CH_SEL_ADC2 to 1 if input comes from CH3 */ |
1525 | cx25840_and_or(client, addr: 0x102, and_mask: ~0x2, or_value: (reg & 0x80) == 0 ? 2 : 0); |
1526 | /* Set DUAL_MODE_ADC2 to 1 if input comes from both CH2&CH3 */ |
1527 | if ((reg & 0xc0) != 0xc0 && (reg & 0x30) != 0x30) |
1528 | cx25840_and_or(client, addr: 0x102, and_mask: ~0x4, or_value: 4); |
1529 | else |
1530 | cx25840_and_or(client, addr: 0x102, and_mask: ~0x4, or_value: 0); |
1531 | } else { |
1532 | /* Set DUAL_MODE_ADC2 to 1 if component*/ |
1533 | cx25840_and_or(client, addr: 0x102, and_mask: ~0x4, or_value: is_component ? 0x4 : 0x0); |
1534 | if (is_composite) { |
1535 | /* ADC2 input select channel 2 */ |
1536 | cx25840_and_or(client, addr: 0x102, and_mask: ~0x2, or_value: 0); |
1537 | } else if (!is_component) { |
1538 | /* S-Video */ |
1539 | if (chroma >= CX25840_SVIDEO_CHROMA7) { |
1540 | /* ADC2 input select channel 3 */ |
1541 | cx25840_and_or(client, addr: 0x102, and_mask: ~0x2, or_value: 2); |
1542 | } else { |
1543 | /* ADC2 input select channel 2 */ |
1544 | cx25840_and_or(client, addr: 0x102, and_mask: ~0x2, or_value: 0); |
1545 | } |
1546 | } |
1547 | |
1548 | /* cx23885 / SVIDEO */ |
1549 | if (is_cx2388x(state) && is_svideo) { |
1550 | #define AFE_CTRL (0x104) |
1551 | #define MODE_CTRL (0x400) |
1552 | cx25840_and_or(client, addr: 0x102, and_mask: ~0x2, or_value: 0x2); |
1553 | |
1554 | val = cx25840_read4(client, MODE_CTRL); |
1555 | val &= 0xFFFFF9FF; |
1556 | |
1557 | /* YC */ |
1558 | val |= 0x00000200; |
1559 | val &= ~0x2000; |
1560 | cx25840_write4(client, MODE_CTRL, value: val); |
1561 | |
1562 | val = cx25840_read4(client, AFE_CTRL); |
1563 | |
1564 | /* Chroma in select */ |
1565 | val |= 0x00001000; |
1566 | val &= 0xfffffe7f; |
1567 | /* Clear VGA_SEL_CH2 and VGA_SEL_CH3 (bits 7 and 8). |
1568 | * This sets them to use video rather than audio. |
1569 | * Only one of the two will be in use. |
1570 | */ |
1571 | cx25840_write4(client, AFE_CTRL, value: val); |
1572 | } else { |
1573 | cx25840_and_or(client, addr: 0x102, and_mask: ~0x2, or_value: 0); |
1574 | } |
1575 | } |
1576 | |
1577 | state->vid_input = vid_input; |
1578 | state->aud_input = aud_input; |
1579 | cx25840_audio_set_path(client); |
1580 | input_change(client); |
1581 | |
1582 | if (is_cx2388x(state)) { |
1583 | /* Audio channel 1 src : Parallel 1 */ |
1584 | cx25840_write(client, addr: 0x124, value: 0x03); |
1585 | |
1586 | /* Select AFE clock pad output source */ |
1587 | cx25840_write(client, addr: 0x144, value: 0x05); |
1588 | |
1589 | /* I2S_IN_CTL: I2S_IN_SONY_MODE, LEFT SAMPLE on WS=1 */ |
1590 | cx25840_write(client, addr: 0x914, value: 0xa0); |
1591 | |
1592 | /* I2S_OUT_CTL: |
1593 | * I2S_IN_SONY_MODE, LEFT SAMPLE on WS=1 |
1594 | * I2S_OUT_MASTER_MODE = Master |
1595 | */ |
1596 | cx25840_write(client, addr: 0x918, value: 0xa0); |
1597 | cx25840_write(client, addr: 0x919, value: 0x01); |
1598 | } else if (is_cx231xx(state)) { |
1599 | /* Audio channel 1 src : Parallel 1 */ |
1600 | cx25840_write(client, addr: 0x124, value: 0x03); |
1601 | |
1602 | /* I2S_IN_CTL: I2S_IN_SONY_MODE, LEFT SAMPLE on WS=1 */ |
1603 | cx25840_write(client, addr: 0x914, value: 0xa0); |
1604 | |
1605 | /* I2S_OUT_CTL: |
1606 | * I2S_IN_SONY_MODE, LEFT SAMPLE on WS=1 |
1607 | * I2S_OUT_MASTER_MODE = Master |
1608 | */ |
1609 | cx25840_write(client, addr: 0x918, value: 0xa0); |
1610 | cx25840_write(client, addr: 0x919, value: 0x01); |
1611 | } |
1612 | |
1613 | if (is_cx2388x(state) && |
1614 | ((aud_input == CX25840_AUDIO7) || (aud_input == CX25840_AUDIO6))) { |
1615 | /* Configure audio from LR1 or LR2 input */ |
1616 | cx25840_write4(client, addr: 0x910, value: 0); |
1617 | cx25840_write4(client, addr: 0x8d0, value: 0x63073); |
1618 | } else if (is_cx2388x(state) && (aud_input == CX25840_AUDIO8)) { |
1619 | /* Configure audio from tuner/sif input */ |
1620 | cx25840_write4(client, addr: 0x910, value: 0x12b000c9); |
1621 | cx25840_write4(client, addr: 0x8d0, value: 0x1f063870); |
1622 | } |
1623 | |
1624 | if (is_cx23888(state)) { |
1625 | /* |
1626 | * HVR1850 |
1627 | * |
1628 | * AUD_IO_CTRL - I2S Input, Parallel1 |
1629 | * - Channel 1 src - Parallel1 (Merlin out) |
1630 | * - Channel 2 src - Parallel2 (Merlin out) |
1631 | * - Channel 3 src - Parallel3 (Merlin AC97 out) |
1632 | * - I2S source and dir - Merlin, output |
1633 | */ |
1634 | cx25840_write4(client, addr: 0x124, value: 0x100); |
1635 | |
1636 | if (!is_dif) { |
1637 | /* |
1638 | * Stop microcontroller if we don't need it |
1639 | * to avoid audio popping on svideo/composite use. |
1640 | */ |
1641 | cx25840_and_or(client, addr: 0x803, and_mask: ~0x10, or_value: 0x00); |
1642 | } |
1643 | } |
1644 | |
1645 | return 0; |
1646 | } |
1647 | |
1648 | /* ----------------------------------------------------------------------- */ |
1649 | |
1650 | static int set_v4lstd(struct i2c_client *client) |
1651 | { |
1652 | struct cx25840_state *state = to_state(sd: i2c_get_clientdata(client)); |
1653 | u8 fmt = 0; /* zero is autodetect */ |
1654 | u8 pal_m = 0; |
1655 | |
1656 | /* First tests should be against specific std */ |
1657 | if (state->std == V4L2_STD_NTSC_M_JP) { |
1658 | fmt = 0x2; |
1659 | } else if (state->std == V4L2_STD_NTSC_443) { |
1660 | fmt = 0x3; |
1661 | } else if (state->std == V4L2_STD_PAL_M) { |
1662 | pal_m = 1; |
1663 | fmt = 0x5; |
1664 | } else if (state->std == V4L2_STD_PAL_N) { |
1665 | fmt = 0x6; |
1666 | } else if (state->std == V4L2_STD_PAL_Nc) { |
1667 | fmt = 0x7; |
1668 | } else if (state->std == V4L2_STD_PAL_60) { |
1669 | fmt = 0x8; |
1670 | } else { |
1671 | /* Then, test against generic ones */ |
1672 | if (state->std & V4L2_STD_NTSC) |
1673 | fmt = 0x1; |
1674 | else if (state->std & V4L2_STD_PAL) |
1675 | fmt = 0x4; |
1676 | else if (state->std & V4L2_STD_SECAM) |
1677 | fmt = 0xc; |
1678 | } |
1679 | |
1680 | v4l_dbg(1, cx25840_debug, client, |
1681 | "changing video std to fmt %i\n" , fmt); |
1682 | |
1683 | /* |
1684 | * Follow step 9 of section 3.16 in the cx25840 datasheet. |
1685 | * Without this PAL may display a vertical ghosting effect. |
1686 | * This happens for example with the Yuan MPC622. |
1687 | */ |
1688 | if (fmt >= 4 && fmt < 8) { |
1689 | /* Set format to NTSC-M */ |
1690 | cx25840_and_or(client, addr: 0x400, and_mask: ~0xf, or_value: 1); |
1691 | /* Turn off LCOMB */ |
1692 | cx25840_and_or(client, addr: 0x47b, and_mask: ~6, or_value: 0); |
1693 | } |
1694 | cx25840_and_or(client, addr: 0x400, and_mask: ~0xf, or_value: fmt); |
1695 | cx25840_and_or(client, addr: 0x403, and_mask: ~0x3, or_value: pal_m); |
1696 | if (is_cx23888(state)) |
1697 | cx23888_std_setup(client); |
1698 | else |
1699 | cx25840_std_setup(client); |
1700 | if (!is_cx2583x(state)) |
1701 | input_change(client); |
1702 | return 0; |
1703 | } |
1704 | |
1705 | /* ----------------------------------------------------------------------- */ |
1706 | |
1707 | static int cx25840_s_ctrl(struct v4l2_ctrl *ctrl) |
1708 | { |
1709 | struct v4l2_subdev *sd = to_sd(ctrl); |
1710 | struct cx25840_state *state = to_state(sd); |
1711 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
1712 | |
1713 | switch (ctrl->id) { |
1714 | case V4L2_CID_BRIGHTNESS: |
1715 | cx25840_write(client, addr: 0x414, value: ctrl->val - 128); |
1716 | break; |
1717 | |
1718 | case V4L2_CID_CONTRAST: |
1719 | cx25840_write(client, addr: 0x415, value: ctrl->val << 1); |
1720 | break; |
1721 | |
1722 | case V4L2_CID_SATURATION: |
1723 | if (is_cx23888(state)) { |
1724 | cx25840_write(client, addr: 0x418, value: ctrl->val << 1); |
1725 | cx25840_write(client, addr: 0x419, value: ctrl->val << 1); |
1726 | } else { |
1727 | cx25840_write(client, addr: 0x420, value: ctrl->val << 1); |
1728 | cx25840_write(client, addr: 0x421, value: ctrl->val << 1); |
1729 | } |
1730 | break; |
1731 | |
1732 | case V4L2_CID_HUE: |
1733 | if (is_cx23888(state)) |
1734 | cx25840_write(client, addr: 0x41a, value: ctrl->val); |
1735 | else |
1736 | cx25840_write(client, addr: 0x422, value: ctrl->val); |
1737 | break; |
1738 | |
1739 | default: |
1740 | return -EINVAL; |
1741 | } |
1742 | |
1743 | return 0; |
1744 | } |
1745 | |
1746 | /* ----------------------------------------------------------------------- */ |
1747 | |
1748 | static int cx25840_set_fmt(struct v4l2_subdev *sd, |
1749 | struct v4l2_subdev_state *sd_state, |
1750 | struct v4l2_subdev_format *format) |
1751 | { |
1752 | struct v4l2_mbus_framefmt *fmt = &format->format; |
1753 | struct cx25840_state *state = to_state(sd); |
1754 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
1755 | u32 hsc, vsc, v_src, h_src, v_add; |
1756 | int filter; |
1757 | int is_50hz = !(state->std & V4L2_STD_525_60); |
1758 | |
1759 | if (format->pad || fmt->code != MEDIA_BUS_FMT_FIXED) |
1760 | return -EINVAL; |
1761 | |
1762 | fmt->field = V4L2_FIELD_INTERLACED; |
1763 | fmt->colorspace = V4L2_COLORSPACE_SMPTE170M; |
1764 | |
1765 | if (is_cx23888(state)) { |
1766 | v_src = (cx25840_read(client, addr: 0x42a) & 0x3f) << 4; |
1767 | v_src |= (cx25840_read(client, addr: 0x429) & 0xf0) >> 4; |
1768 | } else { |
1769 | v_src = (cx25840_read(client, addr: 0x476) & 0x3f) << 4; |
1770 | v_src |= (cx25840_read(client, addr: 0x475) & 0xf0) >> 4; |
1771 | } |
1772 | |
1773 | if (is_cx23888(state)) { |
1774 | h_src = (cx25840_read(client, addr: 0x426) & 0x3f) << 4; |
1775 | h_src |= (cx25840_read(client, addr: 0x425) & 0xf0) >> 4; |
1776 | } else { |
1777 | h_src = (cx25840_read(client, addr: 0x472) & 0x3f) << 4; |
1778 | h_src |= (cx25840_read(client, addr: 0x471) & 0xf0) >> 4; |
1779 | } |
1780 | |
1781 | if (!state->generic_mode) { |
1782 | v_add = is_50hz ? 4 : 7; |
1783 | |
1784 | /* |
1785 | * cx23888 in 525-line mode is programmed for 486 active lines |
1786 | * while other chips use 487 active lines. |
1787 | * |
1788 | * See reg 0x428 bits [21:12] in cx23888_std_setup() vs |
1789 | * vactive in cx25840_std_setup(). |
1790 | */ |
1791 | if (is_cx23888(state) && !is_50hz) |
1792 | v_add--; |
1793 | } else { |
1794 | v_add = 0; |
1795 | } |
1796 | |
1797 | if (h_src == 0 || |
1798 | v_src <= v_add) { |
1799 | v4l_err(client, |
1800 | "chip reported picture size (%u x %u) is far too small\n" , |
1801 | (unsigned int)h_src, (unsigned int)v_src); |
1802 | /* |
1803 | * that's the best we can do since the output picture |
1804 | * size is completely unknown in this case |
1805 | */ |
1806 | return -EINVAL; |
1807 | } |
1808 | |
1809 | fmt->width = clamp(fmt->width, (h_src + 15) / 16, h_src); |
1810 | |
1811 | if (v_add * 8 >= v_src) |
1812 | fmt->height = clamp(fmt->height, (u32)1, v_src - v_add); |
1813 | else |
1814 | fmt->height = clamp(fmt->height, (v_src - v_add * 8 + 7) / 8, |
1815 | v_src - v_add); |
1816 | |
1817 | if (format->which == V4L2_SUBDEV_FORMAT_TRY) |
1818 | return 0; |
1819 | |
1820 | hsc = (h_src * (1 << 20)) / fmt->width - (1 << 20); |
1821 | vsc = (1 << 16) - (v_src * (1 << 9) / (fmt->height + v_add) - (1 << 9)); |
1822 | vsc &= 0x1fff; |
1823 | |
1824 | if (fmt->width >= 385) |
1825 | filter = 0; |
1826 | else if (fmt->width > 192) |
1827 | filter = 1; |
1828 | else if (fmt->width > 96) |
1829 | filter = 2; |
1830 | else |
1831 | filter = 3; |
1832 | |
1833 | v4l_dbg(1, cx25840_debug, client, |
1834 | "decoder set size %u x %u with scale %x x %x\n" , |
1835 | (unsigned int)fmt->width, (unsigned int)fmt->height, |
1836 | (unsigned int)hsc, (unsigned int)vsc); |
1837 | |
1838 | /* HSCALE=hsc */ |
1839 | if (is_cx23888(state)) { |
1840 | cx25840_write4(client, addr: 0x434, value: hsc | (1 << 24)); |
1841 | /* VSCALE=vsc VS_INTRLACE=1 VFILT=filter */ |
1842 | cx25840_write4(client, addr: 0x438, value: vsc | (1 << 19) | (filter << 16)); |
1843 | } else { |
1844 | cx25840_write(client, addr: 0x418, value: hsc & 0xff); |
1845 | cx25840_write(client, addr: 0x419, value: (hsc >> 8) & 0xff); |
1846 | cx25840_write(client, addr: 0x41a, value: hsc >> 16); |
1847 | /* VSCALE=vsc */ |
1848 | cx25840_write(client, addr: 0x41c, value: vsc & 0xff); |
1849 | cx25840_write(client, addr: 0x41d, value: vsc >> 8); |
1850 | /* VS_INTRLACE=1 VFILT=filter */ |
1851 | cx25840_write(client, addr: 0x41e, value: 0x8 | filter); |
1852 | } |
1853 | return 0; |
1854 | } |
1855 | |
1856 | /* ----------------------------------------------------------------------- */ |
1857 | |
1858 | static void log_video_status(struct i2c_client *client) |
1859 | { |
1860 | static const char *const fmt_strs[] = { |
1861 | "0x0" , |
1862 | "NTSC-M" , "NTSC-J" , "NTSC-4.43" , |
1863 | "PAL-BDGHI" , "PAL-M" , "PAL-N" , "PAL-Nc" , "PAL-60" , |
1864 | "0x9" , "0xA" , "0xB" , |
1865 | "SECAM" , |
1866 | "0xD" , "0xE" , "0xF" |
1867 | }; |
1868 | |
1869 | struct cx25840_state *state = to_state(sd: i2c_get_clientdata(client)); |
1870 | u8 vidfmt_sel = cx25840_read(client, addr: 0x400) & 0xf; |
1871 | u8 gen_stat1 = cx25840_read(client, addr: 0x40d); |
1872 | u8 gen_stat2 = cx25840_read(client, addr: 0x40e); |
1873 | int vid_input = state->vid_input; |
1874 | |
1875 | v4l_info(client, "Video signal: %spresent\n" , |
1876 | (gen_stat2 & 0x20) ? "" : "not " ); |
1877 | v4l_info(client, "Detected format: %s\n" , |
1878 | fmt_strs[gen_stat1 & 0xf]); |
1879 | |
1880 | v4l_info(client, "Specified standard: %s\n" , |
1881 | vidfmt_sel ? fmt_strs[vidfmt_sel] : "automatic detection" ); |
1882 | |
1883 | if (vid_input >= CX25840_COMPOSITE1 && |
1884 | vid_input <= CX25840_COMPOSITE8) { |
1885 | v4l_info(client, "Specified video input: Composite %d\n" , |
1886 | vid_input - CX25840_COMPOSITE1 + 1); |
1887 | } else { |
1888 | v4l_info(client, |
1889 | "Specified video input: S-Video (Luma In%d, Chroma In%d)\n" , |
1890 | (vid_input & 0xf0) >> 4, (vid_input & 0xf00) >> 8); |
1891 | } |
1892 | |
1893 | v4l_info(client, "Specified audioclock freq: %d Hz\n" , |
1894 | state->audclk_freq); |
1895 | } |
1896 | |
1897 | /* ----------------------------------------------------------------------- */ |
1898 | |
1899 | static void log_audio_status(struct i2c_client *client) |
1900 | { |
1901 | struct cx25840_state *state = to_state(sd: i2c_get_clientdata(client)); |
1902 | u8 download_ctl = cx25840_read(client, addr: 0x803); |
1903 | u8 mod_det_stat0 = cx25840_read(client, addr: 0x804); |
1904 | u8 mod_det_stat1 = cx25840_read(client, addr: 0x805); |
1905 | u8 audio_config = cx25840_read(client, addr: 0x808); |
1906 | u8 pref_mode = cx25840_read(client, addr: 0x809); |
1907 | u8 afc0 = cx25840_read(client, addr: 0x80b); |
1908 | u8 mute_ctl = cx25840_read(client, addr: 0x8d3); |
1909 | int aud_input = state->aud_input; |
1910 | char *p; |
1911 | |
1912 | switch (mod_det_stat0) { |
1913 | case 0x00: |
1914 | p = "mono" ; |
1915 | break; |
1916 | case 0x01: |
1917 | p = "stereo" ; |
1918 | break; |
1919 | case 0x02: |
1920 | p = "dual" ; |
1921 | break; |
1922 | case 0x04: |
1923 | p = "tri" ; |
1924 | break; |
1925 | case 0x10: |
1926 | p = "mono with SAP" ; |
1927 | break; |
1928 | case 0x11: |
1929 | p = "stereo with SAP" ; |
1930 | break; |
1931 | case 0x12: |
1932 | p = "dual with SAP" ; |
1933 | break; |
1934 | case 0x14: |
1935 | p = "tri with SAP" ; |
1936 | break; |
1937 | case 0xfe: |
1938 | p = "forced mode" ; |
1939 | break; |
1940 | default: |
1941 | p = "not defined" ; |
1942 | } |
1943 | v4l_info(client, "Detected audio mode: %s\n" , p); |
1944 | |
1945 | switch (mod_det_stat1) { |
1946 | case 0x00: |
1947 | p = "not defined" ; |
1948 | break; |
1949 | case 0x01: |
1950 | p = "EIAJ" ; |
1951 | break; |
1952 | case 0x02: |
1953 | p = "A2-M" ; |
1954 | break; |
1955 | case 0x03: |
1956 | p = "A2-BG" ; |
1957 | break; |
1958 | case 0x04: |
1959 | p = "A2-DK1" ; |
1960 | break; |
1961 | case 0x05: |
1962 | p = "A2-DK2" ; |
1963 | break; |
1964 | case 0x06: |
1965 | p = "A2-DK3" ; |
1966 | break; |
1967 | case 0x07: |
1968 | p = "A1 (6.0 MHz FM Mono)" ; |
1969 | break; |
1970 | case 0x08: |
1971 | p = "AM-L" ; |
1972 | break; |
1973 | case 0x09: |
1974 | p = "NICAM-BG" ; |
1975 | break; |
1976 | case 0x0a: |
1977 | p = "NICAM-DK" ; |
1978 | break; |
1979 | case 0x0b: |
1980 | p = "NICAM-I" ; |
1981 | break; |
1982 | case 0x0c: |
1983 | p = "NICAM-L" ; |
1984 | break; |
1985 | case 0x0d: |
1986 | p = "BTSC/EIAJ/A2-M Mono (4.5 MHz FMMono)" ; |
1987 | break; |
1988 | case 0x0e: |
1989 | p = "IF FM Radio" ; |
1990 | break; |
1991 | case 0x0f: |
1992 | p = "BTSC" ; |
1993 | break; |
1994 | case 0x10: |
1995 | p = "high-deviation FM" ; |
1996 | break; |
1997 | case 0x11: |
1998 | p = "very high-deviation FM" ; |
1999 | break; |
2000 | case 0xfd: |
2001 | p = "unknown audio standard" ; |
2002 | break; |
2003 | case 0xfe: |
2004 | p = "forced audio standard" ; |
2005 | break; |
2006 | case 0xff: |
2007 | p = "no detected audio standard" ; |
2008 | break; |
2009 | default: |
2010 | p = "not defined" ; |
2011 | } |
2012 | v4l_info(client, "Detected audio standard: %s\n" , p); |
2013 | v4l_info(client, "Audio microcontroller: %s\n" , |
2014 | (download_ctl & 0x10) ? |
2015 | ((mute_ctl & 0x2) ? "detecting" : "running" ) : "stopped" ); |
2016 | |
2017 | switch (audio_config >> 4) { |
2018 | case 0x00: |
2019 | p = "undefined" ; |
2020 | break; |
2021 | case 0x01: |
2022 | p = "BTSC" ; |
2023 | break; |
2024 | case 0x02: |
2025 | p = "EIAJ" ; |
2026 | break; |
2027 | case 0x03: |
2028 | p = "A2-M" ; |
2029 | break; |
2030 | case 0x04: |
2031 | p = "A2-BG" ; |
2032 | break; |
2033 | case 0x05: |
2034 | p = "A2-DK1" ; |
2035 | break; |
2036 | case 0x06: |
2037 | p = "A2-DK2" ; |
2038 | break; |
2039 | case 0x07: |
2040 | p = "A2-DK3" ; |
2041 | break; |
2042 | case 0x08: |
2043 | p = "A1 (6.0 MHz FM Mono)" ; |
2044 | break; |
2045 | case 0x09: |
2046 | p = "AM-L" ; |
2047 | break; |
2048 | case 0x0a: |
2049 | p = "NICAM-BG" ; |
2050 | break; |
2051 | case 0x0b: |
2052 | p = "NICAM-DK" ; |
2053 | break; |
2054 | case 0x0c: |
2055 | p = "NICAM-I" ; |
2056 | break; |
2057 | case 0x0d: |
2058 | p = "NICAM-L" ; |
2059 | break; |
2060 | case 0x0e: |
2061 | p = "FM radio" ; |
2062 | break; |
2063 | case 0x0f: |
2064 | p = "automatic detection" ; |
2065 | break; |
2066 | default: |
2067 | p = "undefined" ; |
2068 | } |
2069 | v4l_info(client, "Configured audio standard: %s\n" , p); |
2070 | |
2071 | if ((audio_config >> 4) < 0xF) { |
2072 | switch (audio_config & 0xF) { |
2073 | case 0x00: |
2074 | p = "MONO1 (LANGUAGE A/Mono L+R channel for BTSC, EIAJ, A2)" ; |
2075 | break; |
2076 | case 0x01: |
2077 | p = "MONO2 (LANGUAGE B)" ; |
2078 | break; |
2079 | case 0x02: |
2080 | p = "MONO3 (STEREO forced MONO)" ; |
2081 | break; |
2082 | case 0x03: |
2083 | p = "MONO4 (NICAM ANALOG-Language C/Analog Fallback)" ; |
2084 | break; |
2085 | case 0x04: |
2086 | p = "STEREO" ; |
2087 | break; |
2088 | case 0x05: |
2089 | p = "DUAL1 (AB)" ; |
2090 | break; |
2091 | case 0x06: |
2092 | p = "DUAL2 (AC) (FM)" ; |
2093 | break; |
2094 | case 0x07: |
2095 | p = "DUAL3 (BC) (FM)" ; |
2096 | break; |
2097 | case 0x08: |
2098 | p = "DUAL4 (AC) (AM)" ; |
2099 | break; |
2100 | case 0x09: |
2101 | p = "DUAL5 (BC) (AM)" ; |
2102 | break; |
2103 | case 0x0a: |
2104 | p = "SAP" ; |
2105 | break; |
2106 | default: |
2107 | p = "undefined" ; |
2108 | } |
2109 | v4l_info(client, "Configured audio mode: %s\n" , p); |
2110 | } else { |
2111 | switch (audio_config & 0xF) { |
2112 | case 0x00: |
2113 | p = "BG" ; |
2114 | break; |
2115 | case 0x01: |
2116 | p = "DK1" ; |
2117 | break; |
2118 | case 0x02: |
2119 | p = "DK2" ; |
2120 | break; |
2121 | case 0x03: |
2122 | p = "DK3" ; |
2123 | break; |
2124 | case 0x04: |
2125 | p = "I" ; |
2126 | break; |
2127 | case 0x05: |
2128 | p = "L" ; |
2129 | break; |
2130 | case 0x06: |
2131 | p = "BTSC" ; |
2132 | break; |
2133 | case 0x07: |
2134 | p = "EIAJ" ; |
2135 | break; |
2136 | case 0x08: |
2137 | p = "A2-M" ; |
2138 | break; |
2139 | case 0x09: |
2140 | p = "FM Radio" ; |
2141 | break; |
2142 | case 0x0f: |
2143 | p = "automatic standard and mode detection" ; |
2144 | break; |
2145 | default: |
2146 | p = "undefined" ; |
2147 | } |
2148 | v4l_info(client, "Configured audio system: %s\n" , p); |
2149 | } |
2150 | |
2151 | if (aud_input) { |
2152 | v4l_info(client, "Specified audio input: Tuner (In%d)\n" , |
2153 | aud_input); |
2154 | } else { |
2155 | v4l_info(client, "Specified audio input: External\n" ); |
2156 | } |
2157 | |
2158 | switch (pref_mode & 0xf) { |
2159 | case 0: |
2160 | p = "mono/language A" ; |
2161 | break; |
2162 | case 1: |
2163 | p = "language B" ; |
2164 | break; |
2165 | case 2: |
2166 | p = "language C" ; |
2167 | break; |
2168 | case 3: |
2169 | p = "analog fallback" ; |
2170 | break; |
2171 | case 4: |
2172 | p = "stereo" ; |
2173 | break; |
2174 | case 5: |
2175 | p = "language AC" ; |
2176 | break; |
2177 | case 6: |
2178 | p = "language BC" ; |
2179 | break; |
2180 | case 7: |
2181 | p = "language AB" ; |
2182 | break; |
2183 | default: |
2184 | p = "undefined" ; |
2185 | } |
2186 | v4l_info(client, "Preferred audio mode: %s\n" , p); |
2187 | |
2188 | if ((audio_config & 0xf) == 0xf) { |
2189 | switch ((afc0 >> 3) & 0x3) { |
2190 | case 0: |
2191 | p = "system DK" ; |
2192 | break; |
2193 | case 1: |
2194 | p = "system L" ; |
2195 | break; |
2196 | case 2: |
2197 | p = "autodetect" ; |
2198 | break; |
2199 | default: |
2200 | p = "undefined" ; |
2201 | } |
2202 | v4l_info(client, "Selected 65 MHz format: %s\n" , p); |
2203 | |
2204 | switch (afc0 & 0x7) { |
2205 | case 0: |
2206 | p = "chroma" ; |
2207 | break; |
2208 | case 1: |
2209 | p = "BTSC" ; |
2210 | break; |
2211 | case 2: |
2212 | p = "EIAJ" ; |
2213 | break; |
2214 | case 3: |
2215 | p = "A2-M" ; |
2216 | break; |
2217 | case 4: |
2218 | p = "autodetect" ; |
2219 | break; |
2220 | default: |
2221 | p = "undefined" ; |
2222 | } |
2223 | v4l_info(client, "Selected 45 MHz format: %s\n" , p); |
2224 | } |
2225 | } |
2226 | |
2227 | #define CX25840_VCONFIG_OPTION(state, cfg_in, opt_msk) \ |
2228 | do { \ |
2229 | if ((cfg_in) & (opt_msk)) { \ |
2230 | (state)->vid_config &= ~(opt_msk); \ |
2231 | (state)->vid_config |= (cfg_in) & (opt_msk); \ |
2232 | } \ |
2233 | } while (0) |
2234 | |
2235 | /* apply incoming options to the current vconfig */ |
2236 | static void cx25840_vconfig_add(struct cx25840_state *state, u32 cfg_in) |
2237 | { |
2238 | CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_FMT_MASK); |
2239 | CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_RES_MASK); |
2240 | CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_VBIRAW_MASK); |
2241 | CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_ANCDATA_MASK); |
2242 | CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_TASKBIT_MASK); |
2243 | CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_ACTIVE_MASK); |
2244 | CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_VALID_MASK); |
2245 | CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_HRESETW_MASK); |
2246 | CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_CLKGATE_MASK); |
2247 | CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_DCMODE_MASK); |
2248 | CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_IDID0S_MASK); |
2249 | CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_VIPCLAMP_MASK); |
2250 | } |
2251 | |
2252 | /* ----------------------------------------------------------------------- */ |
2253 | |
2254 | /* |
2255 | * Initializes the device in the generic mode. |
2256 | * For cx2584x chips also adds additional video output settings provided |
2257 | * in @val parameter (CX25840_VCONFIG_*). |
2258 | * |
2259 | * The generic mode disables some of the ivtv-related hacks in this driver. |
2260 | * For cx2584x chips it also enables setting video output configuration while |
2261 | * setting it according to datasheet defaults by default. |
2262 | */ |
2263 | static int cx25840_init(struct v4l2_subdev *sd, u32 val) |
2264 | { |
2265 | struct cx25840_state *state = to_state(sd); |
2266 | |
2267 | state->generic_mode = true; |
2268 | |
2269 | if (is_cx2584x(state)) { |
2270 | /* set datasheet video output defaults */ |
2271 | state->vid_config = CX25840_VCONFIG_FMT_BT656 | |
2272 | CX25840_VCONFIG_RES_8BIT | |
2273 | CX25840_VCONFIG_VBIRAW_DISABLED | |
2274 | CX25840_VCONFIG_ANCDATA_ENABLED | |
2275 | CX25840_VCONFIG_TASKBIT_ONE | |
2276 | CX25840_VCONFIG_ACTIVE_HORIZONTAL | |
2277 | CX25840_VCONFIG_VALID_NORMAL | |
2278 | CX25840_VCONFIG_HRESETW_NORMAL | |
2279 | CX25840_VCONFIG_CLKGATE_NONE | |
2280 | CX25840_VCONFIG_DCMODE_DWORDS | |
2281 | CX25840_VCONFIG_IDID0S_NORMAL | |
2282 | CX25840_VCONFIG_VIPCLAMP_DISABLED; |
2283 | |
2284 | /* add additional settings */ |
2285 | cx25840_vconfig_add(state, cfg_in: val); |
2286 | } else { |
2287 | /* TODO: generic mode needs to be developed for other chips */ |
2288 | WARN_ON(1); |
2289 | } |
2290 | |
2291 | return 0; |
2292 | } |
2293 | |
2294 | static int cx25840_reset(struct v4l2_subdev *sd, u32 val) |
2295 | { |
2296 | struct cx25840_state *state = to_state(sd); |
2297 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
2298 | |
2299 | if (is_cx2583x(state)) |
2300 | cx25836_initialize(client); |
2301 | else if (is_cx2388x(state)) |
2302 | cx23885_initialize(client); |
2303 | else if (is_cx231xx(state)) |
2304 | cx231xx_initialize(client); |
2305 | else |
2306 | cx25840_initialize(client); |
2307 | |
2308 | state->is_initialized = 1; |
2309 | |
2310 | return 0; |
2311 | } |
2312 | |
2313 | /* |
2314 | * This load_fw operation must be called to load the driver's firmware. |
2315 | * This will load the firmware on the first invocation (further ones are NOP). |
2316 | * Without this the audio standard detection will fail and you will |
2317 | * only get mono. |
2318 | * Alternatively, you can call the reset operation instead of this one. |
2319 | * |
2320 | * Since loading the firmware is often problematic when the driver is |
2321 | * compiled into the kernel I recommend postponing calling this function |
2322 | * until the first open of the video device. Another reason for |
2323 | * postponing it is that loading this firmware takes a long time (seconds) |
2324 | * due to the slow i2c bus speed. So it will speed up the boot process if |
2325 | * you can avoid loading the fw as long as the video device isn't used. |
2326 | */ |
2327 | static int cx25840_load_fw(struct v4l2_subdev *sd) |
2328 | { |
2329 | struct cx25840_state *state = to_state(sd); |
2330 | |
2331 | if (!state->is_initialized) { |
2332 | /* initialize and load firmware */ |
2333 | cx25840_reset(sd, val: 0); |
2334 | } |
2335 | return 0; |
2336 | } |
2337 | |
2338 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
2339 | static int cx25840_g_register(struct v4l2_subdev *sd, |
2340 | struct v4l2_dbg_register *reg) |
2341 | { |
2342 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
2343 | |
2344 | reg->size = 1; |
2345 | reg->val = cx25840_read(client, addr: reg->reg & 0x0fff); |
2346 | return 0; |
2347 | } |
2348 | |
2349 | static int cx25840_s_register(struct v4l2_subdev *sd, |
2350 | const struct v4l2_dbg_register *reg) |
2351 | { |
2352 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
2353 | |
2354 | cx25840_write(client, addr: reg->reg & 0x0fff, value: reg->val & 0xff); |
2355 | return 0; |
2356 | } |
2357 | #endif |
2358 | |
2359 | static int cx25840_s_audio_stream(struct v4l2_subdev *sd, int enable) |
2360 | { |
2361 | struct cx25840_state *state = to_state(sd); |
2362 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
2363 | u8 v; |
2364 | |
2365 | if (is_cx2583x(state) || is_cx2388x(state) || is_cx231xx(state)) |
2366 | return 0; |
2367 | |
2368 | v4l_dbg(1, cx25840_debug, client, "%s audio output\n" , |
2369 | enable ? "enable" : "disable" ); |
2370 | |
2371 | if (enable) { |
2372 | v = cx25840_read(client, addr: 0x115) | 0x80; |
2373 | cx25840_write(client, addr: 0x115, value: v); |
2374 | v = cx25840_read(client, addr: 0x116) | 0x03; |
2375 | cx25840_write(client, addr: 0x116, value: v); |
2376 | } else { |
2377 | v = cx25840_read(client, addr: 0x115) & ~(0x80); |
2378 | cx25840_write(client, addr: 0x115, value: v); |
2379 | v = cx25840_read(client, addr: 0x116) & ~(0x03); |
2380 | cx25840_write(client, addr: 0x116, value: v); |
2381 | } |
2382 | return 0; |
2383 | } |
2384 | |
2385 | static int cx25840_s_stream(struct v4l2_subdev *sd, int enable) |
2386 | { |
2387 | struct cx25840_state *state = to_state(sd); |
2388 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
2389 | u8 v; |
2390 | |
2391 | v4l_dbg(1, cx25840_debug, client, "%s video output\n" , |
2392 | enable ? "enable" : "disable" ); |
2393 | |
2394 | /* |
2395 | * It's not clear what should be done for these devices. |
2396 | * The original code used the same addresses as for the cx25840, but |
2397 | * those addresses do something else entirely on the cx2388x and |
2398 | * cx231xx. Since it never did anything in the first place, just do |
2399 | * nothing. |
2400 | */ |
2401 | if (is_cx2388x(state) || is_cx231xx(state)) |
2402 | return 0; |
2403 | |
2404 | if (enable) { |
2405 | v = cx25840_read(client, addr: 0x115) | 0x0c; |
2406 | cx25840_write(client, addr: 0x115, value: v); |
2407 | v = cx25840_read(client, addr: 0x116) | 0x04; |
2408 | cx25840_write(client, addr: 0x116, value: v); |
2409 | } else { |
2410 | v = cx25840_read(client, addr: 0x115) & ~(0x0c); |
2411 | cx25840_write(client, addr: 0x115, value: v); |
2412 | v = cx25840_read(client, addr: 0x116) & ~(0x04); |
2413 | cx25840_write(client, addr: 0x116, value: v); |
2414 | } |
2415 | return 0; |
2416 | } |
2417 | |
2418 | /* Query the current detected video format */ |
2419 | static int cx25840_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) |
2420 | { |
2421 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
2422 | |
2423 | static const v4l2_std_id stds[] = { |
2424 | /* 0000 */ V4L2_STD_UNKNOWN, |
2425 | |
2426 | /* 0001 */ V4L2_STD_NTSC_M, |
2427 | /* 0010 */ V4L2_STD_NTSC_M_JP, |
2428 | /* 0011 */ V4L2_STD_NTSC_443, |
2429 | /* 0100 */ V4L2_STD_PAL, |
2430 | /* 0101 */ V4L2_STD_PAL_M, |
2431 | /* 0110 */ V4L2_STD_PAL_N, |
2432 | /* 0111 */ V4L2_STD_PAL_Nc, |
2433 | /* 1000 */ V4L2_STD_PAL_60, |
2434 | |
2435 | /* 1001 */ V4L2_STD_UNKNOWN, |
2436 | /* 1010 */ V4L2_STD_UNKNOWN, |
2437 | /* 1011 */ V4L2_STD_UNKNOWN, |
2438 | /* 1100 */ V4L2_STD_SECAM, |
2439 | /* 1101 */ V4L2_STD_UNKNOWN, |
2440 | /* 1110 */ V4L2_STD_UNKNOWN, |
2441 | /* 1111 */ V4L2_STD_UNKNOWN |
2442 | }; |
2443 | |
2444 | u32 fmt = (cx25840_read4(client, addr: 0x40c) >> 8) & 0xf; |
2445 | *std = stds[fmt]; |
2446 | |
2447 | v4l_dbg(1, cx25840_debug, client, |
2448 | "querystd fmt = %x, v4l2_std_id = 0x%x\n" , |
2449 | fmt, (unsigned int)stds[fmt]); |
2450 | |
2451 | return 0; |
2452 | } |
2453 | |
2454 | static int cx25840_g_input_status(struct v4l2_subdev *sd, u32 *status) |
2455 | { |
2456 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
2457 | |
2458 | /* |
2459 | * A limited function that checks for signal status and returns |
2460 | * the state. |
2461 | */ |
2462 | |
2463 | /* Check for status of Horizontal lock (SRC lock isn't reliable) */ |
2464 | if ((cx25840_read4(client, addr: 0x40c) & 0x00010000) == 0) |
2465 | *status |= V4L2_IN_ST_NO_SIGNAL; |
2466 | |
2467 | return 0; |
2468 | } |
2469 | |
2470 | static int cx25840_g_std(struct v4l2_subdev *sd, v4l2_std_id *std) |
2471 | { |
2472 | struct cx25840_state *state = to_state(sd); |
2473 | |
2474 | *std = state->std; |
2475 | |
2476 | return 0; |
2477 | } |
2478 | |
2479 | static int cx25840_s_std(struct v4l2_subdev *sd, v4l2_std_id std) |
2480 | { |
2481 | struct cx25840_state *state = to_state(sd); |
2482 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
2483 | |
2484 | if (state->radio == 0 && state->std == std) |
2485 | return 0; |
2486 | state->radio = 0; |
2487 | state->std = std; |
2488 | return set_v4lstd(client); |
2489 | } |
2490 | |
2491 | static int cx25840_s_radio(struct v4l2_subdev *sd) |
2492 | { |
2493 | struct cx25840_state *state = to_state(sd); |
2494 | |
2495 | state->radio = 1; |
2496 | return 0; |
2497 | } |
2498 | |
2499 | static int cx25840_s_video_routing(struct v4l2_subdev *sd, |
2500 | u32 input, u32 output, u32 config) |
2501 | { |
2502 | struct cx25840_state *state = to_state(sd); |
2503 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
2504 | |
2505 | if (is_cx23888(state)) |
2506 | cx23888_std_setup(client); |
2507 | |
2508 | if (is_cx2584x(state) && state->generic_mode && config) { |
2509 | cx25840_vconfig_add(state, cfg_in: config); |
2510 | cx25840_vconfig_apply(client); |
2511 | } |
2512 | |
2513 | return set_input(client, vid_input: input, aud_input: state->aud_input); |
2514 | } |
2515 | |
2516 | static int cx25840_s_audio_routing(struct v4l2_subdev *sd, |
2517 | u32 input, u32 output, u32 config) |
2518 | { |
2519 | struct cx25840_state *state = to_state(sd); |
2520 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
2521 | |
2522 | if (is_cx23888(state)) |
2523 | cx23888_std_setup(client); |
2524 | return set_input(client, vid_input: state->vid_input, aud_input: input); |
2525 | } |
2526 | |
2527 | static int cx25840_s_frequency(struct v4l2_subdev *sd, |
2528 | const struct v4l2_frequency *freq) |
2529 | { |
2530 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
2531 | |
2532 | input_change(client); |
2533 | return 0; |
2534 | } |
2535 | |
2536 | static int cx25840_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) |
2537 | { |
2538 | struct cx25840_state *state = to_state(sd); |
2539 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
2540 | u8 vpres = cx25840_read(client, addr: 0x40e) & 0x20; |
2541 | u8 mode; |
2542 | int val = 0; |
2543 | |
2544 | if (state->radio) |
2545 | return 0; |
2546 | |
2547 | vt->signal = vpres ? 0xffff : 0x0; |
2548 | if (is_cx2583x(state)) |
2549 | return 0; |
2550 | |
2551 | vt->capability |= V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | |
2552 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP; |
2553 | |
2554 | mode = cx25840_read(client, addr: 0x804); |
2555 | |
2556 | /* get rxsubchans and audmode */ |
2557 | if ((mode & 0xf) == 1) |
2558 | val |= V4L2_TUNER_SUB_STEREO; |
2559 | else |
2560 | val |= V4L2_TUNER_SUB_MONO; |
2561 | |
2562 | if (mode == 2 || mode == 4) |
2563 | val = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; |
2564 | |
2565 | if (mode & 0x10) |
2566 | val |= V4L2_TUNER_SUB_SAP; |
2567 | |
2568 | vt->rxsubchans = val; |
2569 | vt->audmode = state->audmode; |
2570 | return 0; |
2571 | } |
2572 | |
2573 | static int cx25840_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *vt) |
2574 | { |
2575 | struct cx25840_state *state = to_state(sd); |
2576 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
2577 | |
2578 | if (state->radio || is_cx2583x(state)) |
2579 | return 0; |
2580 | |
2581 | switch (vt->audmode) { |
2582 | case V4L2_TUNER_MODE_MONO: |
2583 | /* |
2584 | * mono -> mono |
2585 | * stereo -> mono |
2586 | * bilingual -> lang1 |
2587 | */ |
2588 | cx25840_and_or(client, addr: 0x809, and_mask: ~0xf, or_value: 0x00); |
2589 | break; |
2590 | case V4L2_TUNER_MODE_STEREO: |
2591 | case V4L2_TUNER_MODE_LANG1: |
2592 | /* |
2593 | * mono -> mono |
2594 | * stereo -> stereo |
2595 | * bilingual -> lang1 |
2596 | */ |
2597 | cx25840_and_or(client, addr: 0x809, and_mask: ~0xf, or_value: 0x04); |
2598 | break; |
2599 | case V4L2_TUNER_MODE_LANG1_LANG2: |
2600 | /* |
2601 | * mono -> mono |
2602 | * stereo -> stereo |
2603 | * bilingual -> lang1/lang2 |
2604 | */ |
2605 | cx25840_and_or(client, addr: 0x809, and_mask: ~0xf, or_value: 0x07); |
2606 | break; |
2607 | case V4L2_TUNER_MODE_LANG2: |
2608 | /* |
2609 | * mono -> mono |
2610 | * stereo -> stereo |
2611 | * bilingual -> lang2 |
2612 | */ |
2613 | cx25840_and_or(client, addr: 0x809, and_mask: ~0xf, or_value: 0x01); |
2614 | break; |
2615 | default: |
2616 | return -EINVAL; |
2617 | } |
2618 | state->audmode = vt->audmode; |
2619 | return 0; |
2620 | } |
2621 | |
2622 | static int cx25840_log_status(struct v4l2_subdev *sd) |
2623 | { |
2624 | struct cx25840_state *state = to_state(sd); |
2625 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
2626 | |
2627 | log_video_status(client); |
2628 | if (!is_cx2583x(state)) |
2629 | log_audio_status(client); |
2630 | cx25840_ir_log_status(sd); |
2631 | v4l2_ctrl_handler_log_status(hdl: &state->hdl, prefix: sd->name); |
2632 | return 0; |
2633 | } |
2634 | |
2635 | static int cx23885_irq_handler(struct v4l2_subdev *sd, u32 status, |
2636 | bool *handled) |
2637 | { |
2638 | struct cx25840_state *state = to_state(sd); |
2639 | struct i2c_client *c = v4l2_get_subdevdata(sd); |
2640 | u8 irq_stat, aud_stat, aud_en, ir_stat, ir_en; |
2641 | u32 vid_stat, aud_mc_stat; |
2642 | bool block_handled; |
2643 | int ret = 0; |
2644 | |
2645 | irq_stat = cx25840_read(client: c, CX23885_PIN_CTRL_IRQ_REG); |
2646 | v4l_dbg(2, cx25840_debug, c, "AV Core IRQ status (entry): %s %s %s\n" , |
2647 | irq_stat & CX23885_PIN_CTRL_IRQ_IR_STAT ? "ir" : " " , |
2648 | irq_stat & CX23885_PIN_CTRL_IRQ_AUD_STAT ? "aud" : " " , |
2649 | irq_stat & CX23885_PIN_CTRL_IRQ_VID_STAT ? "vid" : " " ); |
2650 | |
2651 | if ((is_cx23885(state) || is_cx23887(state))) { |
2652 | ir_stat = cx25840_read(client: c, CX25840_IR_STATS_REG); |
2653 | ir_en = cx25840_read(client: c, CX25840_IR_IRQEN_REG); |
2654 | v4l_dbg(2, cx25840_debug, c, |
2655 | "AV Core ir IRQ status: %#04x disables: %#04x\n" , |
2656 | ir_stat, ir_en); |
2657 | if (irq_stat & CX23885_PIN_CTRL_IRQ_IR_STAT) { |
2658 | block_handled = false; |
2659 | ret = cx25840_ir_irq_handler(sd, |
2660 | status, handled: &block_handled); |
2661 | if (block_handled) |
2662 | *handled = true; |
2663 | } |
2664 | } |
2665 | |
2666 | aud_stat = cx25840_read(client: c, CX25840_AUD_INT_STAT_REG); |
2667 | aud_en = cx25840_read(client: c, CX25840_AUD_INT_CTRL_REG); |
2668 | v4l_dbg(2, cx25840_debug, c, |
2669 | "AV Core audio IRQ status: %#04x disables: %#04x\n" , |
2670 | aud_stat, aud_en); |
2671 | aud_mc_stat = cx25840_read4(client: c, CX23885_AUD_MC_INT_MASK_REG); |
2672 | v4l_dbg(2, cx25840_debug, c, |
2673 | "AV Core audio MC IRQ status: %#06x enables: %#06x\n" , |
2674 | aud_mc_stat >> CX23885_AUD_MC_INT_STAT_SHFT, |
2675 | aud_mc_stat & CX23885_AUD_MC_INT_CTRL_BITS); |
2676 | if (irq_stat & CX23885_PIN_CTRL_IRQ_AUD_STAT) { |
2677 | if (aud_stat) { |
2678 | cx25840_write(client: c, CX25840_AUD_INT_STAT_REG, value: aud_stat); |
2679 | *handled = true; |
2680 | } |
2681 | } |
2682 | |
2683 | vid_stat = cx25840_read4(client: c, CX25840_VID_INT_STAT_REG); |
2684 | v4l_dbg(2, cx25840_debug, c, |
2685 | "AV Core video IRQ status: %#06x disables: %#06x\n" , |
2686 | vid_stat & CX25840_VID_INT_STAT_BITS, |
2687 | vid_stat >> CX25840_VID_INT_MASK_SHFT); |
2688 | if (irq_stat & CX23885_PIN_CTRL_IRQ_VID_STAT) { |
2689 | if (vid_stat & CX25840_VID_INT_STAT_BITS) { |
2690 | cx25840_write4(client: c, CX25840_VID_INT_STAT_REG, value: vid_stat); |
2691 | *handled = true; |
2692 | } |
2693 | } |
2694 | |
2695 | irq_stat = cx25840_read(client: c, CX23885_PIN_CTRL_IRQ_REG); |
2696 | v4l_dbg(2, cx25840_debug, c, "AV Core IRQ status (exit): %s %s %s\n" , |
2697 | irq_stat & CX23885_PIN_CTRL_IRQ_IR_STAT ? "ir" : " " , |
2698 | irq_stat & CX23885_PIN_CTRL_IRQ_AUD_STAT ? "aud" : " " , |
2699 | irq_stat & CX23885_PIN_CTRL_IRQ_VID_STAT ? "vid" : " " ); |
2700 | |
2701 | return ret; |
2702 | } |
2703 | |
2704 | static int cx25840_irq_handler(struct v4l2_subdev *sd, u32 status, |
2705 | bool *handled) |
2706 | { |
2707 | struct cx25840_state *state = to_state(sd); |
2708 | |
2709 | *handled = false; |
2710 | |
2711 | /* Only support the CX2388[578] AV Core for now */ |
2712 | if (is_cx2388x(state)) |
2713 | return cx23885_irq_handler(sd, status, handled); |
2714 | |
2715 | return -ENODEV; |
2716 | } |
2717 | |
2718 | /* ----------------------------------------------------------------------- */ |
2719 | |
2720 | #define DIF_PLL_FREQ_WORD (0x300) |
2721 | #define DIF_BPF_COEFF01 (0x348) |
2722 | #define DIF_BPF_COEFF23 (0x34c) |
2723 | #define DIF_BPF_COEFF45 (0x350) |
2724 | #define DIF_BPF_COEFF67 (0x354) |
2725 | #define DIF_BPF_COEFF89 (0x358) |
2726 | #define DIF_BPF_COEFF1011 (0x35c) |
2727 | #define DIF_BPF_COEFF1213 (0x360) |
2728 | #define DIF_BPF_COEFF1415 (0x364) |
2729 | #define DIF_BPF_COEFF1617 (0x368) |
2730 | #define DIF_BPF_COEFF1819 (0x36c) |
2731 | #define DIF_BPF_COEFF2021 (0x370) |
2732 | #define DIF_BPF_COEFF2223 (0x374) |
2733 | #define DIF_BPF_COEFF2425 (0x378) |
2734 | #define DIF_BPF_COEFF2627 (0x37c) |
2735 | #define DIF_BPF_COEFF2829 (0x380) |
2736 | #define DIF_BPF_COEFF3031 (0x384) |
2737 | #define DIF_BPF_COEFF3233 (0x388) |
2738 | #define DIF_BPF_COEFF3435 (0x38c) |
2739 | #define DIF_BPF_COEFF36 (0x390) |
2740 | |
2741 | static const u32 ifhz_coeffs[][19] = { |
2742 | { // 3.0 MHz |
2743 | 0x00000002, 0x00080012, 0x001e0024, 0x001bfff8, |
2744 | 0xffb4ff50, 0xfed8fe68, 0xfe24fe34, 0xfebaffc7, |
2745 | 0x014d031f, 0x04f0065d, 0x07010688, 0x04c901d6, |
2746 | 0xfe00f9d3, 0xf600f342, 0xf235f337, 0xf64efb22, |
2747 | 0x0105070f, 0x0c460fce, 0x110d0000, |
2748 | }, { // 3.1 MHz |
2749 | 0x00000001, 0x00070012, 0x00220032, 0x00370026, |
2750 | 0xfff0ff91, 0xff0efe7c, 0xfe01fdcc, 0xfe0afedb, |
2751 | 0x00440224, 0x0434060c, 0x0738074e, 0x06090361, |
2752 | 0xff99fb39, 0xf6fef3b6, 0xf21af2a5, 0xf573fa33, |
2753 | 0x0034067d, 0x0bfb0fb9, 0x110d0000, |
2754 | }, { // 3.2 MHz |
2755 | 0x00000000, 0x0004000e, 0x00200038, 0x004c004f, |
2756 | 0x002fffdf, 0xff5cfeb6, 0xfe0dfd92, 0xfd7ffe03, |
2757 | 0xff36010a, 0x03410575, 0x072607d2, 0x071804d5, |
2758 | 0x0134fcb7, 0xf81ff451, 0xf223f22e, 0xf4a7f94b, |
2759 | 0xff6405e8, 0x0bae0fa4, 0x110d0000, |
2760 | }, { // 3.3 MHz |
2761 | 0x0000ffff, 0x00000008, 0x001a0036, 0x0056006d, |
2762 | 0x00670030, 0xffbdff10, 0xfe46fd8d, 0xfd25fd4f, |
2763 | 0xfe35ffe0, 0x0224049f, 0x06c9080e, 0x07ef0627, |
2764 | 0x02c9fe45, 0xf961f513, 0xf250f1d2, 0xf3ecf869, |
2765 | 0xfe930552, 0x0b5f0f8f, 0x110d0000, |
2766 | }, { // 3.4 MHz |
2767 | 0xfffffffe, 0xfffd0001, 0x000f002c, 0x0054007d, |
2768 | 0x0093007c, 0x0024ff82, 0xfea6fdbb, 0xfd03fcca, |
2769 | 0xfd51feb9, 0x00eb0392, 0x06270802, 0x08880750, |
2770 | 0x044dffdb, 0xfabdf5f8, 0xf2a0f193, 0xf342f78f, |
2771 | 0xfdc404b9, 0x0b0e0f78, 0x110d0000, |
2772 | }, { // 3.5 MHz |
2773 | 0xfffffffd, 0xfffafff9, 0x0002001b, 0x0046007d, |
2774 | 0x00ad00ba, 0x00870000, 0xff26fe1a, 0xfd1bfc7e, |
2775 | 0xfc99fda4, 0xffa5025c, 0x054507ad, 0x08dd0847, |
2776 | 0x05b80172, 0xfc2ef6ff, 0xf313f170, 0xf2abf6bd, |
2777 | 0xfcf6041f, 0x0abc0f61, 0x110d0000, |
2778 | }, { // 3.6 MHz |
2779 | 0xfffffffd, 0xfff8fff3, 0xfff50006, 0x002f006c, |
2780 | 0x00b200e3, 0x00dc007e, 0xffb9fea0, 0xfd6bfc71, |
2781 | 0xfc17fcb1, 0xfe65010b, 0x042d0713, 0x08ec0906, |
2782 | 0x07020302, 0xfdaff823, 0xf3a7f16a, 0xf228f5f5, |
2783 | 0xfc2a0384, 0x0a670f4a, 0x110d0000, |
2784 | }, { // 3.7 MHz |
2785 | 0x0000fffd, 0xfff7ffef, 0xffe9fff1, 0x0010004d, |
2786 | 0x00a100f2, 0x011a00f0, 0x0053ff44, 0xfdedfca2, |
2787 | 0xfbd3fbef, 0xfd39ffae, 0x02ea0638, 0x08b50987, |
2788 | 0x08230483, 0xff39f960, 0xf45bf180, 0xf1b8f537, |
2789 | 0xfb6102e7, 0x0a110f32, 0x110d0000, |
2790 | }, { // 3.8 MHz |
2791 | 0x0000fffe, 0xfff9ffee, 0xffe1ffdd, 0xfff00024, |
2792 | 0x007c00e5, 0x013a014a, 0x00e6fff8, 0xfe98fd0f, |
2793 | 0xfbd3fb67, 0xfc32fe54, 0x01880525, 0x083909c7, |
2794 | 0x091505ee, 0x00c7fab3, 0xf52df1b4, 0xf15df484, |
2795 | 0xfa9b0249, 0x09ba0f19, 0x110d0000, |
2796 | }, { // 3.9 MHz |
2797 | 0x00000000, 0xfffbfff0, 0xffdeffcf, 0xffd1fff6, |
2798 | 0x004800be, 0x01390184, 0x016300ac, 0xff5efdb1, |
2799 | 0xfc17fb23, 0xfb5cfd0d, 0x001703e4, 0x077b09c4, |
2800 | 0x09d2073c, 0x0251fc18, 0xf61cf203, 0xf118f3dc, |
2801 | 0xf9d801aa, 0x09600eff, 0x110d0000, |
2802 | }, { // 4.0 MHz |
2803 | 0x00000001, 0xfffefff4, 0xffe1ffc8, 0xffbaffca, |
2804 | 0x000b0082, 0x01170198, 0x01c10152, 0x0030fe7b, |
2805 | 0xfc99fb24, 0xfac3fbe9, 0xfea5027f, 0x0683097f, |
2806 | 0x0a560867, 0x03d2fd89, 0xf723f26f, 0xf0e8f341, |
2807 | 0xf919010a, 0x09060ee5, 0x110d0000, |
2808 | }, { // 4.1 MHz |
2809 | 0x00010002, 0x0002fffb, 0xffe8ffca, 0xffacffa4, |
2810 | 0xffcd0036, 0x00d70184, 0x01f601dc, 0x00ffff60, |
2811 | 0xfd51fb6d, 0xfa6efaf5, 0xfd410103, 0x055708f9, |
2812 | 0x0a9e0969, 0x0543ff02, 0xf842f2f5, 0xf0cef2b2, |
2813 | 0xf85e006b, 0x08aa0ecb, 0x110d0000, |
2814 | }, { // 4.2 MHz |
2815 | 0x00010003, 0x00050003, 0xfff3ffd3, 0xffaaff8b, |
2816 | 0xff95ffe5, 0x0080014a, 0x01fe023f, 0x01ba0050, |
2817 | 0xfe35fbf8, 0xfa62fa3b, 0xfbf9ff7e, 0x04010836, |
2818 | 0x0aa90a3d, 0x069f007f, 0xf975f395, 0xf0cbf231, |
2819 | 0xf7a9ffcb, 0x084c0eaf, 0x110d0000, |
2820 | }, { // 4.3 MHz |
2821 | 0x00010003, 0x0008000a, 0x0000ffe4, 0xffb4ff81, |
2822 | 0xff6aff96, 0x001c00f0, 0x01d70271, 0x0254013b, |
2823 | 0xff36fcbd, 0xfa9ff9c5, 0xfadbfdfe, 0x028c073b, |
2824 | 0x0a750adf, 0x07e101fa, 0xfab8f44e, 0xf0ddf1be, |
2825 | 0xf6f9ff2b, 0x07ed0e94, 0x110d0000, |
2826 | }, { // 4.4 MHz |
2827 | 0x00000003, 0x0009000f, 0x000efff8, 0xffc9ff87, |
2828 | 0xff52ff54, 0xffb5007e, 0x01860270, 0x02c00210, |
2829 | 0x0044fdb2, 0xfb22f997, 0xf9f2fc90, 0x0102060f, |
2830 | 0x0a050b4c, 0x0902036e, 0xfc0af51e, 0xf106f15a, |
2831 | 0xf64efe8b, 0x078d0e77, 0x110d0000, |
2832 | }, { // 4.5 MHz |
2833 | 0x00000002, 0x00080012, 0x0019000e, 0xffe5ff9e, |
2834 | 0xff4fff25, 0xff560000, 0x0112023b, 0x02f702c0, |
2835 | 0x014dfec8, 0xfbe5f9b3, 0xf947fb41, 0xff7004b9, |
2836 | 0x095a0b81, 0x0a0004d8, 0xfd65f603, 0xf144f104, |
2837 | 0xf5aafdec, 0x072b0e5a, 0x110d0000, |
2838 | }, { // 4.6 MHz |
2839 | 0x00000001, 0x00060012, 0x00200022, 0x0005ffc1, |
2840 | 0xff61ff10, 0xff09ff82, 0x008601d7, 0x02f50340, |
2841 | 0x0241fff0, 0xfcddfa19, 0xf8e2fa1e, 0xfde30343, |
2842 | 0x08790b7f, 0x0ad50631, 0xfec7f6fc, 0xf198f0bd, |
2843 | 0xf50dfd4e, 0x06c90e3d, 0x110d0000, |
2844 | }, { // 4.7 MHz |
2845 | 0x0000ffff, 0x0003000f, 0x00220030, 0x0025ffed, |
2846 | 0xff87ff15, 0xfed6ff10, 0xffed014c, 0x02b90386, |
2847 | 0x03110119, 0xfdfefac4, 0xf8c6f92f, 0xfc6701b7, |
2848 | 0x07670b44, 0x0b7e0776, 0x002df807, 0xf200f086, |
2849 | 0xf477fcb1, 0x06650e1e, 0x110d0000, |
2850 | }, { // 4.8 MHz |
2851 | 0xfffffffe, 0xffff0009, 0x001e0038, 0x003f001b, |
2852 | 0xffbcff36, 0xfec2feb6, 0xff5600a5, 0x0248038d, |
2853 | 0x03b00232, 0xff39fbab, 0xf8f4f87f, 0xfb060020, |
2854 | 0x062a0ad2, 0x0bf908a3, 0x0192f922, 0xf27df05e, |
2855 | 0xf3e8fc14, 0x06000e00, 0x110d0000, |
2856 | }, { // 4.9 MHz |
2857 | 0xfffffffd, 0xfffc0002, 0x00160037, 0x00510046, |
2858 | 0xfff9ff6d, 0xfed0fe7c, 0xfecefff0, 0x01aa0356, |
2859 | 0x0413032b, 0x007ffcc5, 0xf96cf812, 0xf9cefe87, |
2860 | 0x04c90a2c, 0x0c4309b4, 0x02f3fa4a, 0xf30ef046, |
2861 | 0xf361fb7a, 0x059b0de0, 0x110d0000, |
2862 | }, { // 5.0 MHz |
2863 | 0xfffffffd, 0xfff9fffa, 0x000a002d, 0x00570067, |
2864 | 0x0037ffb5, 0xfefffe68, 0xfe62ff3d, 0x00ec02e3, |
2865 | 0x043503f6, 0x01befe05, 0xfa27f7ee, 0xf8c6fcf8, |
2866 | 0x034c0954, 0x0c5c0aa4, 0x044cfb7e, 0xf3b1f03f, |
2867 | 0xf2e2fae1, 0x05340dc0, 0x110d0000, |
2868 | }, { // 5.1 MHz |
2869 | 0x0000fffd, 0xfff8fff4, 0xfffd001e, 0x0051007b, |
2870 | 0x006e0006, 0xff48fe7c, 0xfe1bfe9a, 0x001d023e, |
2871 | 0x04130488, 0x02e6ff5b, 0xfb1ef812, 0xf7f7fb7f, |
2872 | 0x01bc084e, 0x0c430b72, 0x059afcba, 0xf467f046, |
2873 | 0xf26cfa4a, 0x04cd0da0, 0x110d0000, |
2874 | }, { // 5.2 MHz |
2875 | 0x0000fffe, 0xfff8ffef, 0xfff00009, 0x003f007f, |
2876 | 0x00980056, 0xffa5feb6, 0xfe00fe15, 0xff4b0170, |
2877 | 0x03b004d7, 0x03e800b9, 0xfc48f87f, 0xf768fa23, |
2878 | 0x0022071f, 0x0bf90c1b, 0x06dafdfd, 0xf52df05e, |
2879 | 0xf1fef9b5, 0x04640d7f, 0x110d0000, |
2880 | }, { // 5.3 MHz |
2881 | 0x0000ffff, 0xfff9ffee, 0xffe6fff3, 0x00250072, |
2882 | 0x00af009c, 0x000cff10, 0xfe13fdb8, 0xfe870089, |
2883 | 0x031104e1, 0x04b8020f, 0xfd98f92f, 0xf71df8f0, |
2884 | 0xfe8805ce, 0x0b7e0c9c, 0x0808ff44, 0xf603f086, |
2885 | 0xf19af922, 0x03fb0d5e, 0x110d0000, |
2886 | }, { // 5.4 MHz |
2887 | 0x00000001, 0xfffcffef, 0xffe0ffe0, 0x00050056, |
2888 | 0x00b000d1, 0x0071ff82, 0xfe53fd8c, 0xfddfff99, |
2889 | 0x024104a3, 0x054a034d, 0xff01fa1e, 0xf717f7ed, |
2890 | 0xfcf50461, 0x0ad50cf4, 0x0921008d, 0xf6e7f0bd, |
2891 | 0xf13ff891, 0x03920d3b, 0x110d0000, |
2892 | }, { // 5.5 MHz |
2893 | 0x00010002, 0xfffffff3, 0xffdeffd1, 0xffe5002f, |
2894 | 0x009c00ed, 0x00cb0000, 0xfebafd94, 0xfd61feb0, |
2895 | 0x014d0422, 0x05970464, 0x0074fb41, 0xf759f721, |
2896 | 0xfb7502de, 0x0a000d21, 0x0a2201d4, 0xf7d9f104, |
2897 | 0xf0edf804, 0x03280d19, 0x110d0000, |
2898 | }, { // 5.6 MHz |
2899 | 0x00010003, 0x0003fffa, 0xffe3ffc9, 0xffc90002, |
2900 | 0x007500ef, 0x010e007e, 0xff3dfdcf, 0xfd16fddd, |
2901 | 0x00440365, 0x059b0548, 0x01e3fc90, 0xf7dff691, |
2902 | 0xfa0f014d, 0x09020d23, 0x0b0a0318, 0xf8d7f15a, |
2903 | 0xf0a5f779, 0x02bd0cf6, 0x110d0000, |
2904 | }, { // 5.7 MHz |
2905 | 0x00010003, 0x00060001, 0xffecffc9, 0xffb4ffd4, |
2906 | 0x004000d5, 0x013600f0, 0xffd3fe39, 0xfd04fd31, |
2907 | 0xff360277, 0x055605ef, 0x033efdfe, 0xf8a5f642, |
2908 | 0xf8cbffb6, 0x07e10cfb, 0x0bd50456, 0xf9dff1be, |
2909 | 0xf067f6f2, 0x02520cd2, 0x110d0000, |
2910 | }, { // 5.8 MHz |
2911 | 0x00000003, 0x00080009, 0xfff8ffd2, 0xffaaffac, |
2912 | 0x000200a3, 0x013c014a, 0x006dfec9, 0xfd2bfcb7, |
2913 | 0xfe350165, 0x04cb0651, 0x0477ff7e, 0xf9a5f635, |
2914 | 0xf7b1fe20, 0x069f0ca8, 0x0c81058b, 0xfaf0f231, |
2915 | 0xf033f66d, 0x01e60cae, 0x110d0000, |
2916 | }, { // 5.9 MHz |
2917 | 0x00000002, 0x0009000e, 0x0005ffe1, 0xffacff90, |
2918 | 0xffc5005f, 0x01210184, 0x00fcff72, 0xfd8afc77, |
2919 | 0xfd51003f, 0x04020669, 0x05830103, 0xfad7f66b, |
2920 | 0xf6c8fc93, 0x05430c2b, 0x0d0d06b5, 0xfc08f2b2, |
2921 | 0xf00af5ec, 0x017b0c89, 0x110d0000, |
2922 | }, { // 6.0 MHz |
2923 | 0x00000001, 0x00070012, 0x0012fff5, 0xffbaff82, |
2924 | 0xff8e000f, 0x00e80198, 0x01750028, 0xfe18fc75, |
2925 | 0xfc99ff15, 0x03050636, 0x0656027f, 0xfc32f6e2, |
2926 | 0xf614fb17, 0x03d20b87, 0x0d7707d2, 0xfd26f341, |
2927 | 0xefeaf56f, 0x010f0c64, 0x110d0000, |
2928 | }, { // 6.1 MHz |
2929 | 0xffff0000, 0x00050012, 0x001c000b, 0xffd1ff84, |
2930 | 0xff66ffbe, 0x00960184, 0x01cd00da, 0xfeccfcb2, |
2931 | 0xfc17fdf9, 0x01e005bc, 0x06e703e4, 0xfdabf798, |
2932 | 0xf599f9b3, 0x02510abd, 0x0dbf08df, 0xfe48f3dc, |
2933 | 0xefd5f4f6, 0x00a20c3e, 0x110d0000, |
2934 | }, { // 6.2 MHz |
2935 | 0xfffffffe, 0x0002000f, 0x0021001f, 0xfff0ff97, |
2936 | 0xff50ff74, 0x0034014a, 0x01fa0179, 0xff97fd2a, |
2937 | 0xfbd3fcfa, 0x00a304fe, 0x07310525, 0xff37f886, |
2938 | 0xf55cf86e, 0x00c709d0, 0x0de209db, 0xff6df484, |
2939 | 0xefcbf481, 0x00360c18, 0x110d0000, |
2940 | }, { // 6.3 MHz |
2941 | 0xfffffffd, 0xfffe000a, 0x0021002f, 0x0010ffb8, |
2942 | 0xff50ff3b, 0xffcc00f0, 0x01fa01fa, 0x0069fdd4, |
2943 | 0xfbd3fc26, 0xff5d0407, 0x07310638, 0x00c9f9a8, |
2944 | 0xf55cf74e, 0xff3908c3, 0x0de20ac3, 0x0093f537, |
2945 | 0xefcbf410, 0xffca0bf2, 0x110d0000, |
2946 | }, { // 6.4 MHz |
2947 | 0xfffffffd, 0xfffb0003, 0x001c0037, 0x002fffe2, |
2948 | 0xff66ff17, 0xff6a007e, 0x01cd0251, 0x0134fea5, |
2949 | 0xfc17fb8b, 0xfe2002e0, 0x06e70713, 0x0255faf5, |
2950 | 0xf599f658, 0xfdaf0799, 0x0dbf0b96, 0x01b8f5f5, |
2951 | 0xefd5f3a3, 0xff5e0bca, 0x110d0000, |
2952 | }, { // 6.5 MHz |
2953 | 0x0000fffd, 0xfff9fffb, 0x00120037, 0x00460010, |
2954 | 0xff8eff0f, 0xff180000, 0x01750276, 0x01e8ff8d, |
2955 | 0xfc99fb31, 0xfcfb0198, 0x065607ad, 0x03cefc64, |
2956 | 0xf614f592, 0xfc2e0656, 0x0d770c52, 0x02daf6bd, |
2957 | 0xefeaf33b, 0xfef10ba3, 0x110d0000, |
2958 | }, { // 6.6 MHz |
2959 | 0x0000fffe, 0xfff7fff5, 0x0005002f, 0x0054003c, |
2960 | 0xffc5ff22, 0xfedfff82, 0x00fc0267, 0x0276007e, |
2961 | 0xfd51fb1c, 0xfbfe003e, 0x05830802, 0x0529fdec, |
2962 | 0xf6c8f4fe, 0xfabd04ff, 0x0d0d0cf6, 0x03f8f78f, |
2963 | 0xf00af2d7, 0xfe850b7b, 0x110d0000, |
2964 | }, { // 6.7 MHz |
2965 | 0x0000ffff, 0xfff8fff0, 0xfff80020, 0x00560060, |
2966 | 0x0002ff4e, 0xfec4ff10, 0x006d0225, 0x02d50166, |
2967 | 0xfe35fb4e, 0xfb35fee1, 0x0477080e, 0x065bff82, |
2968 | 0xf7b1f4a0, 0xf9610397, 0x0c810d80, 0x0510f869, |
2969 | 0xf033f278, 0xfe1a0b52, 0x110d0000, |
2970 | }, { // 6.8 MHz |
2971 | 0x00010000, 0xfffaffee, 0xffec000c, 0x004c0078, |
2972 | 0x0040ff8e, 0xfecafeb6, 0xffd301b6, 0x02fc0235, |
2973 | 0xff36fbc5, 0xfaaafd90, 0x033e07d2, 0x075b011b, |
2974 | 0xf8cbf47a, 0xf81f0224, 0x0bd50def, 0x0621f94b, |
2975 | 0xf067f21e, 0xfdae0b29, 0x110d0000, |
2976 | }, { // 6.9 MHz |
2977 | 0x00010001, 0xfffdffef, 0xffe3fff6, 0x0037007f, |
2978 | 0x0075ffdc, 0xfef2fe7c, 0xff3d0122, 0x02ea02dd, |
2979 | 0x0044fc79, 0xfa65fc5d, 0x01e3074e, 0x082102ad, |
2980 | 0xfa0ff48c, 0xf6fe00a9, 0x0b0a0e43, 0x0729fa33, |
2981 | 0xf0a5f1c9, 0xfd430b00, 0x110d0000, |
2982 | }, { // 7.0 MHz |
2983 | 0x00010002, 0x0001fff3, 0xffdeffe2, 0x001b0076, |
2984 | 0x009c002d, 0xff35fe68, 0xfeba0076, 0x029f0352, |
2985 | 0x014dfd60, 0xfa69fb53, 0x00740688, 0x08a7042d, |
2986 | 0xfb75f4d6, 0xf600ff2d, 0x0a220e7a, 0x0827fb22, |
2987 | 0xf0edf17a, 0xfcd80ad6, 0x110d0000, |
2988 | }, { // 7.1 MHz |
2989 | 0x00000003, 0x0004fff9, 0xffe0ffd2, 0xfffb005e, |
2990 | 0x00b0007a, 0xff8ffe7c, 0xfe53ffc1, 0x0221038c, |
2991 | 0x0241fe6e, 0xfab6fa80, 0xff010587, 0x08e90590, |
2992 | 0xfcf5f556, 0xf52bfdb3, 0x09210e95, 0x0919fc15, |
2993 | 0xf13ff12f, 0xfc6e0aab, 0x110d0000, |
2994 | }, { // 7.2 MHz |
2995 | 0x00000003, 0x00070000, 0xffe6ffc9, 0xffdb0039, |
2996 | 0x00af00b8, 0xfff4feb6, 0xfe13ff10, 0x01790388, |
2997 | 0x0311ff92, 0xfb48f9ed, 0xfd980453, 0x08e306cd, |
2998 | 0xfe88f60a, 0xf482fc40, 0x08080e93, 0x09fdfd0c, |
2999 | 0xf19af0ea, 0xfc050a81, 0x110d0000, |
3000 | }, { // 7.3 MHz |
3001 | 0x00000002, 0x00080008, 0xfff0ffc9, 0xffc1000d, |
3002 | 0x009800e2, 0x005bff10, 0xfe00fe74, 0x00b50345, |
3003 | 0x03b000bc, 0xfc18f9a1, 0xfc4802f9, 0x089807dc, |
3004 | 0x0022f6f0, 0xf407fada, 0x06da0e74, 0x0ad3fe06, |
3005 | 0xf1fef0ab, 0xfb9c0a55, 0x110d0000, |
3006 | }, { // 7.4 MHz |
3007 | 0x00000001, 0x0008000e, 0xfffdffd0, 0xffafffdf, |
3008 | 0x006e00f2, 0x00b8ff82, 0xfe1bfdf8, 0xffe302c8, |
3009 | 0x041301dc, 0xfd1af99e, 0xfb1e0183, 0x080908b5, |
3010 | 0x01bcf801, 0xf3bdf985, 0x059a0e38, 0x0b99ff03, |
3011 | 0xf26cf071, 0xfb330a2a, 0x110d0000, |
3012 | }, { // 7.5 MHz |
3013 | 0xffff0000, 0x00070011, 0x000affdf, 0xffa9ffb5, |
3014 | 0x003700e6, 0x01010000, 0xfe62fda8, 0xff140219, |
3015 | 0x043502e1, 0xfe42f9e6, 0xfa270000, 0x073a0953, |
3016 | 0x034cf939, 0xf3a4f845, 0x044c0de1, 0x0c4f0000, |
3017 | 0xf2e2f03c, 0xfacc09fe, 0x110d0000, |
3018 | }, { // 7.6 MHz |
3019 | 0xffffffff, 0x00040012, 0x0016fff3, 0xffafff95, |
3020 | 0xfff900c0, 0x0130007e, 0xfecefd89, 0xfe560146, |
3021 | 0x041303bc, 0xff81fa76, 0xf96cfe7d, 0x063209b1, |
3022 | 0x04c9fa93, 0xf3bdf71e, 0x02f30d6e, 0x0cf200fd, |
3023 | 0xf361f00e, 0xfa6509d1, 0x110d0000, |
3024 | }, { // 7.7 MHz |
3025 | 0xfffffffe, 0x00010010, 0x001e0008, 0xffc1ff84, |
3026 | 0xffbc0084, 0x013e00f0, 0xff56fd9f, 0xfdb8005c, |
3027 | 0x03b00460, 0x00c7fb45, 0xf8f4fd07, 0x04fa09ce, |
3028 | 0x062afc07, 0xf407f614, 0x01920ce0, 0x0d8301fa, |
3029 | 0xf3e8efe5, 0xfa0009a4, 0x110d0000, |
3030 | }, { // 7.8 MHz |
3031 | 0x0000fffd, 0xfffd000b, 0x0022001d, 0xffdbff82, |
3032 | 0xff870039, 0x012a014a, 0xffedfde7, 0xfd47ff6b, |
3033 | 0x031104c6, 0x0202fc4c, 0xf8c6fbad, 0x039909a7, |
3034 | 0x0767fd8e, 0xf482f52b, 0x002d0c39, 0x0e0002f4, |
3035 | 0xf477efc2, 0xf99b0977, 0x110d0000, |
3036 | }, { // 7.9 MHz |
3037 | 0x0000fffd, 0xfffa0004, 0x0020002d, 0xfffbff91, |
3038 | 0xff61ffe8, 0x00f70184, 0x0086fe5c, 0xfd0bfe85, |
3039 | 0x024104e5, 0x0323fd7d, 0xf8e2fa79, 0x021d093f, |
3040 | 0x0879ff22, 0xf52bf465, 0xfec70b79, 0x0e6803eb, |
3041 | 0xf50defa5, 0xf937094a, 0x110d0000, |
3042 | }, { // 8.0 MHz |
3043 | 0x0000fffe, 0xfff8fffd, 0x00190036, 0x001bffaf, |
3044 | 0xff4fff99, 0x00aa0198, 0x0112fef3, 0xfd09fdb9, |
3045 | 0x014d04be, 0x041bfecc, 0xf947f978, 0x00900897, |
3046 | 0x095a00b9, 0xf600f3c5, 0xfd650aa3, 0x0ebc04de, |
3047 | 0xf5aaef8e, 0xf8d5091c, 0x110d0000, |
3048 | }, { // 8.1 MHz |
3049 | 0x0000ffff, 0xfff7fff6, 0x000e0038, 0x0037ffd7, |
3050 | 0xff52ff56, 0x004b0184, 0x0186ffa1, 0xfd40fd16, |
3051 | 0x00440452, 0x04de0029, 0xf9f2f8b2, 0xfefe07b5, |
3052 | 0x0a05024d, 0xf6fef34d, 0xfc0a09b8, 0x0efa05cd, |
3053 | 0xf64eef7d, 0xf87308ed, 0x110d0000, |
3054 | }, { // 8.2 MHz |
3055 | 0x00010000, 0xfff8fff0, 0x00000031, 0x004c0005, |
3056 | 0xff6aff27, 0xffe4014a, 0x01d70057, 0xfdacfca6, |
3057 | 0xff3603a7, 0x05610184, 0xfadbf82e, 0xfd74069f, |
3058 | 0x0a7503d6, 0xf81ff2ff, 0xfab808b9, 0x0f2306b5, |
3059 | 0xf6f9ef72, 0xf81308bf, 0x110d0000, |
3060 | }, { // 8.3 MHz |
3061 | 0x00010001, 0xfffbffee, 0xfff30022, 0x00560032, |
3062 | 0xff95ff10, 0xff8000f0, 0x01fe0106, 0xfe46fc71, |
3063 | 0xfe3502c7, 0x059e02ce, 0xfbf9f7f2, 0xfbff055b, |
3064 | 0x0aa9054c, 0xf961f2db, 0xf97507aa, 0x0f350797, |
3065 | 0xf7a9ef6d, 0xf7b40890, 0x110d0000, |
3066 | }, { // 8.4 MHz |
3067 | 0x00010002, 0xfffeffee, 0xffe8000f, 0x00540058, |
3068 | 0xffcdff14, 0xff29007e, 0x01f6019e, 0xff01fc7c, |
3069 | 0xfd5101bf, 0x059203f6, 0xfd41f7fe, 0xfaa903f3, |
3070 | 0x0a9e06a9, 0xfabdf2e2, 0xf842068b, 0x0f320871, |
3071 | 0xf85eef6e, 0xf7560860, 0x110d0000, |
3072 | }, { // 8.5 MHz |
3073 | 0x00000003, 0x0002fff2, 0xffe1fff9, 0x00460073, |
3074 | 0x000bff34, 0xfee90000, 0x01c10215, 0xffd0fcc5, |
3075 | 0xfc99009d, 0x053d04f1, 0xfea5f853, 0xf97d0270, |
3076 | 0x0a5607e4, 0xfc2ef314, 0xf723055f, 0x0f180943, |
3077 | 0xf919ef75, 0xf6fa0830, 0x110d0000, |
3078 | }, { // 8.6 MHz |
3079 | 0x00000003, 0x0005fff8, 0xffdeffe4, 0x002f007f, |
3080 | 0x0048ff6b, 0xfec7ff82, 0x0163025f, 0x00a2fd47, |
3081 | 0xfc17ff73, 0x04a405b2, 0x0017f8ed, 0xf88500dc, |
3082 | 0x09d208f9, 0xfdaff370, 0xf61c0429, 0x0ee80a0b, |
3083 | 0xf9d8ef82, 0xf6a00800, 0x110d0000, |
3084 | }, { // 8.7 MHz |
3085 | 0x00000003, 0x0007ffff, 0xffe1ffd4, 0x0010007a, |
3086 | 0x007cffb2, 0xfec6ff10, 0x00e60277, 0x0168fdf9, |
3087 | 0xfbd3fe50, 0x03ce0631, 0x0188f9c8, 0xf7c7ff43, |
3088 | 0x091509e3, 0xff39f3f6, 0xf52d02ea, 0x0ea30ac9, |
3089 | 0xfa9bef95, 0xf64607d0, 0x110d0000, |
3090 | }, { // 8.8 MHz |
3091 | 0x00000002, 0x00090007, 0xffe9ffca, 0xfff00065, |
3092 | 0x00a10003, 0xfee6feb6, 0x0053025b, 0x0213fed0, |
3093 | 0xfbd3fd46, 0x02c70668, 0x02eafadb, 0xf74bfdae, |
3094 | 0x08230a9c, 0x00c7f4a3, 0xf45b01a6, 0x0e480b7c, |
3095 | 0xfb61efae, 0xf5ef079f, 0x110d0000, |
3096 | }, { // 8.9 MHz |
3097 | 0xffff0000, 0x0008000d, 0xfff5ffc8, 0xffd10043, |
3098 | 0x00b20053, 0xff24fe7c, 0xffb9020c, 0x0295ffbb, |
3099 | 0xfc17fc64, 0x019b0654, 0x042dfc1c, 0xf714fc2a, |
3100 | 0x07020b21, 0x0251f575, 0xf3a7005e, 0x0dd80c24, |
3101 | 0xfc2aefcd, 0xf599076e, 0x110d0000, |
3102 | }, { // 9.0 MHz |
3103 | 0xffffffff, 0x00060011, 0x0002ffcf, 0xffba0018, |
3104 | 0x00ad009a, 0xff79fe68, 0xff260192, 0x02e500ab, |
3105 | 0xfc99fbb6, 0x005b05f7, 0x0545fd81, 0xf723fabf, |
3106 | 0x05b80b70, 0x03d2f669, 0xf313ff15, 0x0d550cbf, |
3107 | 0xfcf6eff2, 0xf544073d, 0x110d0000, |
3108 | }, { // 9.1 MHz |
3109 | 0xfffffffe, 0x00030012, 0x000fffdd, 0xffacffea, |
3110 | 0x009300cf, 0xffdcfe7c, 0xfea600f7, 0x02fd0190, |
3111 | 0xfd51fb46, 0xff150554, 0x0627fefd, 0xf778f978, |
3112 | 0x044d0b87, 0x0543f77d, 0xf2a0fdcf, 0x0cbe0d4e, |
3113 | 0xfdc4f01d, 0xf4f2070b, 0x110d0000, |
3114 | }, { // 9.2 MHz |
3115 | 0x0000fffd, 0x00000010, 0x001afff0, 0xffaaffbf, |
3116 | 0x006700ed, 0x0043feb6, 0xfe460047, 0x02db0258, |
3117 | 0xfe35fb1b, 0xfddc0473, 0x06c90082, 0xf811f85e, |
3118 | 0x02c90b66, 0x069ff8ad, 0xf250fc8d, 0x0c140dcf, |
3119 | 0xfe93f04d, 0xf4a106d9, 0x110d0000, |
3120 | }, { // 9.3 MHz |
3121 | 0x0000fffd, 0xfffc000c, 0x00200006, 0xffb4ff9c, |
3122 | 0x002f00ef, 0x00a4ff10, 0xfe0dff92, 0x028102f7, |
3123 | 0xff36fb37, 0xfcbf035e, 0x07260202, 0xf8e8f778, |
3124 | 0x01340b0d, 0x07e1f9f4, 0xf223fb51, 0x0b590e42, |
3125 | 0xff64f083, 0xf45206a7, 0x110d0000, |
3126 | }, { // 9.4 MHz |
3127 | 0x0000fffd, 0xfff90005, 0x0022001a, 0xffc9ff86, |
3128 | 0xfff000d7, 0x00f2ff82, 0xfe01fee5, 0x01f60362, |
3129 | 0x0044fb99, 0xfbcc0222, 0x07380370, 0xf9f7f6cc, |
3130 | 0xff990a7e, 0x0902fb50, 0xf21afa1f, 0x0a8d0ea6, |
3131 | 0x0034f0bf, 0xf4050675, 0x110d0000, |
3132 | }, { // 9.5 MHz |
3133 | 0x0000fffe, 0xfff8fffe, 0x001e002b, 0xffe5ff81, |
3134 | 0xffb400a5, 0x01280000, 0xfe24fe50, 0x01460390, |
3135 | 0x014dfc3a, 0xfb1000ce, 0x070104bf, 0xfb37f65f, |
3136 | 0xfe0009bc, 0x0a00fcbb, 0xf235f8f8, 0x09b20efc, |
3137 | 0x0105f101, 0xf3ba0642, 0x110d0000, |
3138 | }, { // 9.6 MHz |
3139 | 0x0001ffff, 0xfff8fff7, 0x00150036, 0x0005ff8c, |
3140 | 0xff810061, 0x013d007e, 0xfe71fddf, 0x007c0380, |
3141 | 0x0241fd13, 0xfa94ff70, 0x068005e2, 0xfc9bf633, |
3142 | 0xfc7308ca, 0x0ad5fe30, 0xf274f7e0, 0x08c90f43, |
3143 | 0x01d4f147, 0xf371060f, 0x110d0000, |
3144 | }, { // 9.7 MHz |
3145 | 0x00010001, 0xfff9fff1, 0x00090038, 0x0025ffa7, |
3146 | 0xff5e0012, 0x013200f0, 0xfee3fd9b, 0xffaa0331, |
3147 | 0x0311fe15, 0xfa60fe18, 0x05bd06d1, 0xfe1bf64a, |
3148 | 0xfafa07ae, 0x0b7effab, 0xf2d5f6d7, 0x07d30f7a, |
3149 | 0x02a3f194, 0xf32905dc, 0x110d0000, |
3150 | }, { // 9.8 MHz |
3151 | 0x00010002, 0xfffcffee, 0xfffb0032, 0x003fffcd, |
3152 | 0xff4effc1, 0x0106014a, 0xff6efd8a, 0xfedd02aa, |
3153 | 0x03b0ff34, 0xfa74fcd7, 0x04bf0781, 0xffaaf6a3, |
3154 | 0xf99e066b, 0x0bf90128, 0xf359f5e1, 0x06d20fa2, |
3155 | 0x0370f1e5, 0xf2e405a8, 0x110d0000, |
3156 | }, { // 9.9 MHz |
3157 | 0x00000003, 0xffffffee, 0xffef0024, 0x0051fffa, |
3158 | 0xff54ff77, 0x00be0184, 0x0006fdad, 0xfe2701f3, |
3159 | 0x0413005e, 0xfad1fbba, 0x039007ee, 0x013bf73d, |
3160 | 0xf868050a, 0x0c4302a1, 0xf3fdf4fe, 0x05c70fba, |
3161 | 0x043bf23c, 0xf2a10575, 0x110d0000, |
3162 | }, { // 10.0 MHz |
3163 | 0x00000003, 0x0003fff1, 0xffe50011, 0x00570027, |
3164 | 0xff70ff3c, 0x00620198, 0x009efe01, 0xfd95011a, |
3165 | 0x04350183, 0xfb71fad0, 0x023c0812, 0x02c3f811, |
3166 | 0xf75e0390, 0x0c5c0411, 0xf4c1f432, 0x04b30fc1, |
3167 | 0x0503f297, 0xf2610541, 0x110d0000, |
3168 | }, { // 10.1 MHz |
3169 | 0x00000003, 0x0006fff7, 0xffdffffc, 0x00510050, |
3170 | 0xff9dff18, 0xfffc0184, 0x0128fe80, 0xfd32002e, |
3171 | 0x04130292, 0xfc4dfa21, 0x00d107ee, 0x0435f91c, |
3172 | 0xf6850205, 0x0c430573, 0xf5a1f37d, 0x03990fba, |
3173 | 0x05c7f2f8, 0xf222050d, 0x110d0000, |
3174 | }, { // 10.2 MHz |
3175 | 0x00000002, 0x0008fffe, 0xffdfffe7, 0x003f006e, |
3176 | 0xffd6ff0f, 0xff96014a, 0x0197ff1f, 0xfd05ff3e, |
3177 | 0x03b0037c, 0xfd59f9b7, 0xff5d0781, 0x0585fa56, |
3178 | 0xf5e4006f, 0x0bf906c4, 0xf69df2e0, 0x02790fa2, |
3179 | 0x0688f35d, 0xf1e604d8, 0x110d0000, |
3180 | }, { // 10.3 MHz |
3181 | 0xffff0001, 0x00090005, 0xffe4ffd6, 0x0025007e, |
3182 | 0x0014ff20, 0xff3c00f0, 0x01e1ffd0, 0xfd12fe5c, |
3183 | 0x03110433, 0xfe88f996, 0xfdf106d1, 0x06aafbb7, |
3184 | 0xf57efed8, 0x0b7e07ff, 0xf7b0f25e, 0x01560f7a, |
3185 | 0x0745f3c7, 0xf1ac04a4, 0x110d0000, |
3186 | }, { // 10.4 MHz |
3187 | 0xffffffff, 0x0008000c, 0xffedffcb, 0x0005007d, |
3188 | 0x0050ff4c, 0xfef6007e, 0x01ff0086, 0xfd58fd97, |
3189 | 0x024104ad, 0xffcaf9c0, 0xfc9905e2, 0x079afd35, |
3190 | 0xf555fd46, 0x0ad50920, 0xf8d9f1f6, 0x00310f43, |
3191 | 0x07fdf435, 0xf174046f, 0x110d0000, |
3192 | }, { // 10.5 MHz |
3193 | 0xfffffffe, 0x00050011, 0xfffaffc8, 0xffe5006b, |
3194 | 0x0082ff8c, 0xfecc0000, 0x01f00130, 0xfdd2fcfc, |
3195 | 0x014d04e3, 0x010efa32, 0xfb6404bf, 0x084efec5, |
3196 | 0xf569fbc2, 0x0a000a23, 0xfa15f1ab, 0xff0b0efc, |
3197 | 0x08b0f4a7, 0xf13f043a, 0x110d0000, |
3198 | }, { // 10.6 MHz |
3199 | 0x0000fffd, 0x00020012, 0x0007ffcd, 0xffc9004c, |
3200 | 0x00a4ffd9, 0xfec3ff82, 0x01b401c1, 0xfe76fc97, |
3201 | 0x004404d2, 0x0245fae8, 0xfa5f0370, 0x08c1005f, |
3202 | 0xf5bcfa52, 0x09020b04, 0xfb60f17b, 0xfde70ea6, |
3203 | 0x095df51e, 0xf10c0405, 0x110d0000, |
3204 | }, { // 10.7 MHz |
3205 | 0x0000fffd, 0xffff0011, 0x0014ffdb, 0xffb40023, |
3206 | 0x00b2002a, 0xfedbff10, 0x0150022d, 0xff38fc6f, |
3207 | 0xff36047b, 0x035efbda, 0xf9940202, 0x08ee01f5, |
3208 | 0xf649f8fe, 0x07e10bc2, 0xfcb6f169, 0xfcc60e42, |
3209 | 0x0a04f599, 0xf0db03d0, 0x110d0000, |
3210 | }, { // 10.8 MHz |
3211 | 0x0000fffd, 0xfffb000d, 0x001dffed, 0xffaafff5, |
3212 | 0x00aa0077, 0xff13feb6, 0x00ce026b, 0x000afc85, |
3213 | 0xfe3503e3, 0x044cfcfb, 0xf90c0082, 0x08d5037f, |
3214 | 0xf710f7cc, 0x069f0c59, 0xfe16f173, 0xfbaa0dcf, |
3215 | 0x0aa5f617, 0xf0ad039b, 0x110d0000, |
3216 | }, { // 10.9 MHz |
3217 | 0x0000fffe, 0xfff90006, 0x00210003, 0xffacffc8, |
3218 | 0x008e00b6, 0xff63fe7c, 0x003a0275, 0x00dafcda, |
3219 | 0xfd510313, 0x0501fe40, 0xf8cbfefd, 0x087604f0, |
3220 | 0xf80af6c2, 0x05430cc8, 0xff7af19a, 0xfa940d4e, |
3221 | 0x0b3ff699, 0xf0810365, 0x110d0000, |
3222 | }, { // 11.0 MHz |
3223 | 0x0001ffff, 0xfff8ffff, 0x00210018, 0xffbaffa3, |
3224 | 0x006000e1, 0xffc4fe68, 0xffa0024b, 0x019afd66, |
3225 | 0xfc990216, 0x0575ff99, 0xf8d4fd81, 0x07d40640, |
3226 | 0xf932f5e6, 0x03d20d0d, 0x00dff1de, 0xf9860cbf, |
3227 | 0x0bd1f71e, 0xf058032f, 0x110d0000, |
3228 | }, { // 11.1 MHz |
3229 | 0x00010000, 0xfff8fff8, 0x001b0029, 0xffd1ff8a, |
3230 | 0x002600f2, 0x002cfe7c, 0xff0f01f0, 0x023bfe20, |
3231 | 0xfc1700fa, 0x05a200f7, 0xf927fc1c, 0x06f40765, |
3232 | 0xfa82f53b, 0x02510d27, 0x0243f23d, 0xf8810c24, |
3233 | 0x0c5cf7a7, 0xf03102fa, 0x110d0000, |
3234 | }, { // 11.2 MHz |
3235 | 0x00010002, 0xfffafff2, 0x00110035, 0xfff0ff81, |
3236 | 0xffe700e7, 0x008ffeb6, 0xfe94016d, 0x02b0fefb, |
3237 | 0xfbd3ffd1, 0x05850249, 0xf9c1fadb, 0x05de0858, |
3238 | 0xfbf2f4c4, 0x00c70d17, 0x03a0f2b8, 0xf7870b7c, |
3239 | 0x0cdff833, 0xf00d02c4, 0x110d0000, |
3240 | }, { // 11.3 MHz |
3241 | 0x00000003, 0xfffdffee, 0x00040038, 0x0010ff88, |
3242 | 0xffac00c2, 0x00e2ff10, 0xfe3900cb, 0x02f1ffe9, |
3243 | 0xfbd3feaa, 0x05210381, 0xfa9cf9c8, 0x04990912, |
3244 | 0xfd7af484, 0xff390cdb, 0x04f4f34d, 0xf69a0ac9, |
3245 | 0x0d5af8c1, 0xefec028e, 0x110d0000, |
3246 | }, { // 11.4 MHz |
3247 | 0x00000003, 0x0000ffee, 0xfff60033, 0x002fff9f, |
3248 | 0xff7b0087, 0x011eff82, 0xfe080018, 0x02f900d8, |
3249 | 0xfc17fd96, 0x04790490, 0xfbadf8ed, 0x032f098e, |
3250 | 0xff10f47d, 0xfdaf0c75, 0x063cf3fc, 0xf5ba0a0b, |
3251 | 0x0dccf952, 0xefcd0258, 0x110d0000, |
3252 | }, { // 11.5 MHz |
3253 | 0x00000003, 0x0004fff1, 0xffea0026, 0x0046ffc3, |
3254 | 0xff5a003c, 0x013b0000, 0xfe04ff63, 0x02c801b8, |
3255 | 0xfc99fca6, 0x0397056a, 0xfcecf853, 0x01ad09c9, |
3256 | 0x00acf4ad, 0xfc2e0be7, 0x0773f4c2, 0xf4e90943, |
3257 | 0x0e35f9e6, 0xefb10221, 0x110d0000, |
3258 | }, { // 11.6 MHz |
3259 | 0x00000002, 0x0007fff6, 0xffe20014, 0x0054ffee, |
3260 | 0xff4effeb, 0x0137007e, 0xfe2efebb, 0x0260027a, |
3261 | 0xfd51fbe6, 0x02870605, 0xfe4af7fe, 0x001d09c1, |
3262 | 0x0243f515, 0xfabd0b32, 0x0897f59e, 0xf4280871, |
3263 | 0x0e95fa7c, 0xef9701eb, 0x110d0000, |
3264 | }, { // 11.7 MHz |
3265 | 0xffff0001, 0x0008fffd, 0xffdeffff, 0x0056001d, |
3266 | 0xff57ff9c, 0x011300f0, 0xfe82fe2e, 0x01ca0310, |
3267 | 0xfe35fb62, 0x0155065a, 0xffbaf7f2, 0xfe8c0977, |
3268 | 0x03cef5b2, 0xf9610a58, 0x09a5f68f, 0xf3790797, |
3269 | 0x0eebfb14, 0xef8001b5, 0x110d0000, |
3270 | }, { // 11.8 MHz |
3271 | 0xffff0000, 0x00080004, 0xffe0ffe9, 0x004c0047, |
3272 | 0xff75ff58, 0x00d1014a, 0xfef9fdc8, 0x0111036f, |
3273 | 0xff36fb21, 0x00120665, 0x012df82e, 0xfd0708ec, |
3274 | 0x0542f682, 0xf81f095c, 0x0a9af792, 0xf2db06b5, |
3275 | 0x0f38fbad, 0xef6c017e, 0x110d0000, |
3276 | }, { // 11.9 MHz |
3277 | 0xffffffff, 0x0007000b, 0xffe7ffd8, 0x00370068, |
3278 | 0xffa4ff28, 0x00790184, 0xff87fd91, 0x00430392, |
3279 | 0x0044fb26, 0xfece0626, 0x0294f8b2, 0xfb990825, |
3280 | 0x0698f77f, 0xf6fe0842, 0x0b73f8a7, 0xf25105cd, |
3281 | 0x0f7bfc48, 0xef5a0148, 0x110d0000, |
3282 | }, { // 12.0 MHz |
3283 | 0x0000fffe, 0x00050010, 0xfff2ffcc, 0x001b007b, |
3284 | 0xffdfff10, 0x00140198, 0x0020fd8e, 0xff710375, |
3285 | 0x014dfb73, 0xfd9a059f, 0x03e0f978, 0xfa4e0726, |
3286 | 0x07c8f8a7, 0xf600070c, 0x0c2ff9c9, 0xf1db04de, |
3287 | 0x0fb4fce5, 0xef4b0111, 0x110d0000, |
3288 | }, { // 12.1 MHz |
3289 | 0x0000fffd, 0x00010012, 0xffffffc8, 0xfffb007e, |
3290 | 0x001dff14, 0xffad0184, 0x00b7fdbe, 0xfea9031b, |
3291 | 0x0241fc01, 0xfc8504d6, 0x0504fa79, 0xf93005f6, |
3292 | 0x08caf9f2, 0xf52b05c0, 0x0ccbfaf9, 0xf17903eb, |
3293 | 0x0fe3fd83, 0xef3f00db, 0x110d0000, |
3294 | }, { // 12.2 MHz |
3295 | 0x0000fffd, 0xfffe0011, 0x000cffcc, 0xffdb0071, |
3296 | 0x0058ff32, 0xff4f014a, 0x013cfe1f, 0xfdfb028a, |
3297 | 0x0311fcc9, 0xfb9d03d6, 0x05f4fbad, 0xf848049d, |
3298 | 0x0999fb5b, 0xf4820461, 0x0d46fc32, 0xf12d02f4, |
3299 | 0x1007fe21, 0xef3600a4, 0x110d0000, |
3300 | }, { // 12.3 MHz |
3301 | 0x0000fffe, 0xfffa000e, 0x0017ffd9, 0xffc10055, |
3302 | 0x0088ff68, 0xff0400f0, 0x01a6fea7, 0xfd7501cc, |
3303 | 0x03b0fdc0, 0xfaef02a8, 0x06a7fd07, 0xf79d0326, |
3304 | 0x0a31fcda, 0xf40702f3, 0x0d9ffd72, 0xf0f601fa, |
3305 | 0x1021fec0, 0xef2f006d, 0x110d0000, |
3306 | }, { // 12.4 MHz |
3307 | 0x0001ffff, 0xfff80007, 0x001fffeb, 0xffaf002d, |
3308 | 0x00a8ffb0, 0xfed3007e, 0x01e9ff4c, 0xfd2000ee, |
3309 | 0x0413fed8, 0xfa82015c, 0x0715fe7d, 0xf7340198, |
3310 | 0x0a8dfe69, 0xf3bd017c, 0x0dd5feb8, 0xf0d500fd, |
3311 | 0x1031ff60, 0xef2b0037, 0x110d0000, |
3312 | }, { // 12.5 MHz |
3313 | 0x00010000, 0xfff70000, 0x00220000, 0xffa90000, |
3314 | 0x00b30000, 0xfec20000, 0x02000000, 0xfd030000, |
3315 | 0x04350000, 0xfa5e0000, 0x073b0000, 0xf7110000, |
3316 | 0x0aac0000, 0xf3a40000, 0x0de70000, 0xf0c90000, |
3317 | 0x10360000, 0xef290000, 0x110d0000, |
3318 | }, { // 12.6 MHz |
3319 | 0x00010001, 0xfff8fff9, 0x001f0015, 0xffafffd3, |
3320 | 0x00a80050, 0xfed3ff82, 0x01e900b4, 0xfd20ff12, |
3321 | 0x04130128, 0xfa82fea4, 0x07150183, 0xf734fe68, |
3322 | 0x0a8d0197, 0xf3bdfe84, 0x0dd50148, 0xf0d5ff03, |
3323 | 0x103100a0, 0xef2bffc9, 0x110d0000, |
3324 | }, { // 12.7 MHz |
3325 | 0x00000002, 0xfffafff2, 0x00170027, 0xffc1ffab, |
3326 | 0x00880098, 0xff04ff10, 0x01a60159, 0xfd75fe34, |
3327 | 0x03b00240, 0xfaeffd58, 0x06a702f9, 0xf79dfcda, |
3328 | 0x0a310326, 0xf407fd0d, 0x0d9f028e, 0xf0f6fe06, |
3329 | 0x10210140, 0xef2fff93, 0x110d0000, |
3330 | }, { // 12.8 MHz |
3331 | 0x00000003, 0xfffeffef, 0x000c0034, 0xffdbff8f, |
3332 | 0x005800ce, 0xff4ffeb6, 0x013c01e1, 0xfdfbfd76, |
3333 | 0x03110337, 0xfb9dfc2a, 0x05f40453, 0xf848fb63, |
3334 | 0x099904a5, 0xf482fb9f, 0x0d4603ce, 0xf12dfd0c, |
3335 | 0x100701df, 0xef36ff5c, 0x110d0000, |
3336 | }, { // 12.9 MHz |
3337 | 0x00000003, 0x0001ffee, 0xffff0038, 0xfffbff82, |
3338 | 0x001d00ec, 0xffadfe7c, 0x00b70242, 0xfea9fce5, |
3339 | 0x024103ff, 0xfc85fb2a, 0x05040587, 0xf930fa0a, |
3340 | 0x08ca060e, 0xf52bfa40, 0x0ccb0507, 0xf179fc15, |
3341 | 0x0fe3027d, 0xef3fff25, 0x110d0000, |
3342 | }, { // 13.0 MHz |
3343 | 0x00000002, 0x0005fff0, 0xfff20034, 0x001bff85, |
3344 | 0xffdf00f0, 0x0014fe68, 0x00200272, 0xff71fc8b, |
3345 | 0x014d048d, 0xfd9afa61, 0x03e00688, 0xfa4ef8da, |
3346 | 0x07c80759, 0xf600f8f4, 0x0c2f0637, 0xf1dbfb22, |
3347 | 0x0fb4031b, 0xef4bfeef, 0x110d0000, |
3348 | }, { // 13.1 MHz |
3349 | 0xffff0001, 0x0007fff5, 0xffe70028, 0x0037ff98, |
3350 | 0xffa400d8, 0x0079fe7c, 0xff87026f, 0x0043fc6e, |
3351 | 0x004404da, 0xfecef9da, 0x0294074e, 0xfb99f7db, |
3352 | 0x06980881, 0xf6fef7be, 0x0b730759, 0xf251fa33, |
3353 | 0x0f7b03b8, 0xef5afeb8, 0x110d0000, |
3354 | }, { // 13.2 MHz |
3355 | 0xffff0000, 0x0008fffc, 0xffe00017, 0x004cffb9, |
3356 | 0xff7500a8, 0x00d1feb6, 0xfef90238, 0x0111fc91, |
3357 | 0xff3604df, 0x0012f99b, 0x012d07d2, 0xfd07f714, |
3358 | 0x0542097e, 0xf81ff6a4, 0x0a9a086e, 0xf2dbf94b, |
3359 | 0x0f380453, 0xef6cfe82, 0x110d0000, |
3360 | }, { // 13.3 MHz |
3361 | 0xffffffff, 0x00080003, 0xffde0001, 0x0056ffe3, |
3362 | 0xff570064, 0x0113ff10, 0xfe8201d2, 0x01cafcf0, |
3363 | 0xfe35049e, 0x0155f9a6, 0xffba080e, 0xfe8cf689, |
3364 | 0x03ce0a4e, 0xf961f5a8, 0x09a50971, 0xf379f869, |
3365 | 0x0eeb04ec, 0xef80fe4b, 0x110d0000, |
3366 | }, { // 13.4 MHz |
3367 | 0x0000fffe, 0x0007000a, 0xffe2ffec, 0x00540012, |
3368 | 0xff4e0015, 0x0137ff82, 0xfe2e0145, 0x0260fd86, |
3369 | 0xfd51041a, 0x0287f9fb, 0xfe4a0802, 0x001df63f, |
3370 | 0x02430aeb, 0xfabdf4ce, 0x08970a62, 0xf428f78f, |
3371 | 0x0e950584, 0xef97fe15, 0x110d0000, |
3372 | }, { // 13.5 MHz |
3373 | 0x0000fffd, 0x0004000f, 0xffeaffda, 0x0046003d, |
3374 | 0xff5affc4, 0x013b0000, 0xfe04009d, 0x02c8fe48, |
3375 | 0xfc99035a, 0x0397fa96, 0xfcec07ad, 0x01adf637, |
3376 | 0x00ac0b53, 0xfc2ef419, 0x07730b3e, 0xf4e9f6bd, |
3377 | 0x0e35061a, 0xefb1fddf, 0x110d0000, |
3378 | }, { // 13.6 MHz |
3379 | 0x0000fffd, 0x00000012, 0xfff6ffcd, 0x002f0061, |
3380 | 0xff7bff79, 0x011e007e, 0xfe08ffe8, 0x02f9ff28, |
3381 | 0xfc17026a, 0x0479fb70, 0xfbad0713, 0x032ff672, |
3382 | 0xff100b83, 0xfdaff38b, 0x063c0c04, 0xf5baf5f5, |
3383 | 0x0dcc06ae, 0xefcdfda8, 0x110d0000, |
3384 | }, { // 13.7 MHz |
3385 | 0x0000fffd, 0xfffd0012, 0x0004ffc8, 0x00100078, |
3386 | 0xffacff3e, 0x00e200f0, 0xfe39ff35, 0x02f10017, |
3387 | 0xfbd30156, 0x0521fc7f, 0xfa9c0638, 0x0499f6ee, |
3388 | 0xfd7a0b7c, 0xff39f325, 0x04f40cb3, 0xf69af537, |
3389 | 0x0d5a073f, 0xefecfd72, 0x110d0000, |
3390 | }, { // 13.8 MHz |
3391 | 0x0001fffe, 0xfffa000e, 0x0011ffcb, 0xfff0007f, |
3392 | 0xffe7ff19, 0x008f014a, 0xfe94fe93, 0x02b00105, |
3393 | 0xfbd3002f, 0x0585fdb7, 0xf9c10525, 0x05def7a8, |
3394 | 0xfbf20b3c, 0x00c7f2e9, 0x03a00d48, 0xf787f484, |
3395 | 0x0cdf07cd, 0xf00dfd3c, 0x110d0000, |
3396 | }, { // 13.9 MHz |
3397 | 0x00010000, 0xfff80008, 0x001bffd7, 0xffd10076, |
3398 | 0x0026ff0e, 0x002c0184, 0xff0ffe10, 0x023b01e0, |
3399 | 0xfc17ff06, 0x05a2ff09, 0xf92703e4, 0x06f4f89b, |
3400 | 0xfa820ac5, 0x0251f2d9, 0x02430dc3, 0xf881f3dc, |
3401 | 0x0c5c0859, 0xf031fd06, 0x110d0000, |
3402 | }, { // 14.0 MHz |
3403 | 0x00010001, 0xfff80001, 0x0021ffe8, 0xffba005d, |
3404 | 0x0060ff1f, 0xffc40198, 0xffa0fdb5, 0x019a029a, |
3405 | 0xfc99fdea, 0x05750067, 0xf8d4027f, 0x07d4f9c0, |
3406 | 0xf9320a1a, 0x03d2f2f3, 0x00df0e22, 0xf986f341, |
3407 | 0x0bd108e2, 0xf058fcd1, 0x110d0000, |
3408 | }, { // 14.1 MHz |
3409 | 0x00000002, 0xfff9fffa, 0x0021fffd, 0xffac0038, |
3410 | 0x008eff4a, 0xff630184, 0x003afd8b, 0x00da0326, |
3411 | 0xfd51fced, 0x050101c0, 0xf8cb0103, 0x0876fb10, |
3412 | 0xf80a093e, 0x0543f338, 0xff7a0e66, 0xfa94f2b2, |
3413 | 0x0b3f0967, 0xf081fc9b, 0x110d0000, |
3414 | }, { // 14.2 MHz |
3415 | 0x00000003, 0xfffbfff3, 0x001d0013, 0xffaa000b, |
3416 | 0x00aaff89, 0xff13014a, 0x00cefd95, 0x000a037b, |
3417 | 0xfe35fc1d, 0x044c0305, 0xf90cff7e, 0x08d5fc81, |
3418 | 0xf7100834, 0x069ff3a7, 0xfe160e8d, 0xfbaaf231, |
3419 | 0x0aa509e9, 0xf0adfc65, 0x110d0000, |
3420 | }, { // 14.3 MHz |
3421 | 0x00000003, 0xffffffef, 0x00140025, 0xffb4ffdd, |
3422 | 0x00b2ffd6, 0xfedb00f0, 0x0150fdd3, 0xff380391, |
3423 | 0xff36fb85, 0x035e0426, 0xf994fdfe, 0x08eefe0b, |
3424 | 0xf6490702, 0x07e1f43e, 0xfcb60e97, 0xfcc6f1be, |
3425 | 0x0a040a67, 0xf0dbfc30, 0x110d0000, |
3426 | }, { // 14.4 MHz |
3427 | 0x00000003, 0x0002ffee, 0x00070033, 0xffc9ffb4, |
3428 | 0x00a40027, 0xfec3007e, 0x01b4fe3f, 0xfe760369, |
3429 | 0x0044fb2e, 0x02450518, 0xfa5ffc90, 0x08c1ffa1, |
3430 | 0xf5bc05ae, 0x0902f4fc, 0xfb600e85, 0xfde7f15a, |
3431 | 0x095d0ae2, 0xf10cfbfb, 0x110d0000, |
3432 | }, { // 14.5 MHz |
3433 | 0xffff0002, 0x0005ffef, 0xfffa0038, 0xffe5ff95, |
3434 | 0x00820074, 0xfecc0000, 0x01f0fed0, 0xfdd20304, |
3435 | 0x014dfb1d, 0x010e05ce, 0xfb64fb41, 0x084e013b, |
3436 | 0xf569043e, 0x0a00f5dd, 0xfa150e55, 0xff0bf104, |
3437 | 0x08b00b59, 0xf13ffbc6, 0x110d0000, |
3438 | }, { // 14.6 MHz |
3439 | 0xffff0001, 0x0008fff4, 0xffed0035, 0x0005ff83, |
3440 | 0x005000b4, 0xfef6ff82, 0x01ffff7a, 0xfd580269, |
3441 | 0x0241fb53, 0xffca0640, 0xfc99fa1e, 0x079a02cb, |
3442 | 0xf55502ba, 0x0ad5f6e0, 0xf8d90e0a, 0x0031f0bd, |
3443 | 0x07fd0bcb, 0xf174fb91, 0x110d0000, |
3444 | }, { // 14.7 MHz |
3445 | 0xffffffff, 0x0009fffb, 0xffe4002a, 0x0025ff82, |
3446 | 0x001400e0, 0xff3cff10, 0x01e10030, 0xfd1201a4, |
3447 | 0x0311fbcd, 0xfe88066a, 0xfdf1f92f, 0x06aa0449, |
3448 | 0xf57e0128, 0x0b7ef801, 0xf7b00da2, 0x0156f086, |
3449 | 0x07450c39, 0xf1acfb5c, 0x110d0000, |
3450 | }, { // 14.8 MHz |
3451 | 0x0000fffe, 0x00080002, 0xffdf0019, 0x003fff92, |
3452 | 0xffd600f1, 0xff96feb6, 0x019700e1, 0xfd0500c2, |
3453 | 0x03b0fc84, 0xfd590649, 0xff5df87f, 0x058505aa, |
3454 | 0xf5e4ff91, 0x0bf9f93c, 0xf69d0d20, 0x0279f05e, |
3455 | 0x06880ca3, 0xf1e6fb28, 0x110d0000, |
3456 | }, { // 14.9 MHz |
3457 | 0x0000fffd, 0x00060009, 0xffdf0004, 0x0051ffb0, |
3458 | 0xff9d00e8, 0xfffcfe7c, 0x01280180, 0xfd32ffd2, |
3459 | 0x0413fd6e, 0xfc4d05df, 0x00d1f812, 0x043506e4, |
3460 | 0xf685fdfb, 0x0c43fa8d, 0xf5a10c83, 0x0399f046, |
3461 | 0x05c70d08, 0xf222faf3, 0x110d0000, |
3462 | }, { // 15.0 MHz |
3463 | 0x0000fffd, 0x0003000f, 0xffe5ffef, 0x0057ffd9, |
3464 | 0xff7000c4, 0x0062fe68, 0x009e01ff, 0xfd95fee6, |
3465 | 0x0435fe7d, 0xfb710530, 0x023cf7ee, 0x02c307ef, |
3466 | 0xf75efc70, 0x0c5cfbef, 0xf4c10bce, 0x04b3f03f, |
3467 | 0x05030d69, 0xf261fabf, 0x110d0000, |
3468 | }, { // 15.1 MHz |
3469 | 0x0000fffd, 0xffff0012, 0xffefffdc, 0x00510006, |
3470 | 0xff540089, 0x00befe7c, 0x00060253, 0xfe27fe0d, |
3471 | 0x0413ffa2, 0xfad10446, 0x0390f812, 0x013b08c3, |
3472 | 0xf868faf6, 0x0c43fd5f, 0xf3fd0b02, 0x05c7f046, |
3473 | 0x043b0dc4, 0xf2a1fa8b, 0x110d0000, |
3474 | }, { // 15.2 MHz |
3475 | 0x0001fffe, 0xfffc0012, 0xfffbffce, 0x003f0033, |
3476 | 0xff4e003f, 0x0106feb6, 0xff6e0276, 0xfeddfd56, |
3477 | 0x03b000cc, 0xfa740329, 0x04bff87f, 0xffaa095d, |
3478 | 0xf99ef995, 0x0bf9fed8, 0xf3590a1f, 0x06d2f05e, |
3479 | 0x03700e1b, 0xf2e4fa58, 0x110d0000, |
3480 | }, { // 15.3 MHz |
3481 | 0x0001ffff, 0xfff9000f, 0x0009ffc8, 0x00250059, |
3482 | 0xff5effee, 0x0132ff10, 0xfee30265, 0xffaafccf, |
3483 | 0x031101eb, 0xfa6001e8, 0x05bdf92f, 0xfe1b09b6, |
3484 | 0xfafaf852, 0x0b7e0055, 0xf2d50929, 0x07d3f086, |
3485 | 0x02a30e6c, 0xf329fa24, 0x110d0000, |
3486 | }, { // 15.4 MHz |
3487 | 0x00010001, 0xfff80009, 0x0015ffca, 0x00050074, |
3488 | 0xff81ff9f, 0x013dff82, 0xfe710221, 0x007cfc80, |
3489 | 0x024102ed, 0xfa940090, 0x0680fa1e, 0xfc9b09cd, |
3490 | 0xfc73f736, 0x0ad501d0, 0xf2740820, 0x08c9f0bd, |
3491 | 0x01d40eb9, 0xf371f9f1, 0x110d0000, |
3492 | }, { // 15.5 MHz |
3493 | 0x00000002, 0xfff80002, 0x001effd5, 0xffe5007f, |
3494 | 0xffb4ff5b, 0x01280000, 0xfe2401b0, 0x0146fc70, |
3495 | 0x014d03c6, 0xfb10ff32, 0x0701fb41, 0xfb3709a1, |
3496 | 0xfe00f644, 0x0a000345, 0xf2350708, 0x09b2f104, |
3497 | 0x01050eff, 0xf3baf9be, 0x110d0000, |
3498 | }, { // 15.6 MHz |
3499 | 0x00000003, 0xfff9fffb, 0x0022ffe6, 0xffc9007a, |
3500 | 0xfff0ff29, 0x00f2007e, 0xfe01011b, 0x01f6fc9e, |
3501 | 0x00440467, 0xfbccfdde, 0x0738fc90, 0xf9f70934, |
3502 | 0xff99f582, 0x090204b0, 0xf21a05e1, 0x0a8df15a, |
3503 | 0x00340f41, 0xf405f98b, 0x110d0000, |
3504 | }, { // 15.7 MHz |
3505 | 0x00000003, 0xfffcfff4, 0x0020fffa, 0xffb40064, |
3506 | 0x002fff11, 0x00a400f0, 0xfe0d006e, 0x0281fd09, |
3507 | 0xff3604c9, 0xfcbffca2, 0x0726fdfe, 0xf8e80888, |
3508 | 0x0134f4f3, 0x07e1060c, 0xf22304af, 0x0b59f1be, |
3509 | 0xff640f7d, 0xf452f959, 0x110d0000, |
3510 | }, { // 15.8 MHz |
3511 | 0x00000003, 0x0000fff0, 0x001a0010, 0xffaa0041, |
3512 | 0x0067ff13, 0x0043014a, 0xfe46ffb9, 0x02dbfda8, |
3513 | 0xfe3504e5, 0xfddcfb8d, 0x06c9ff7e, 0xf81107a2, |
3514 | 0x02c9f49a, 0x069f0753, 0xf2500373, 0x0c14f231, |
3515 | 0xfe930fb3, 0xf4a1f927, 0x110d0000, |
3516 | }, { // 15.9 MHz |
3517 | 0xffff0002, 0x0003ffee, 0x000f0023, 0xffac0016, |
3518 | 0x0093ff31, 0xffdc0184, 0xfea6ff09, 0x02fdfe70, |
3519 | 0xfd5104ba, 0xff15faac, 0x06270103, 0xf7780688, |
3520 | 0x044df479, 0x05430883, 0xf2a00231, 0x0cbef2b2, |
3521 | 0xfdc40fe3, 0xf4f2f8f5, 0x110d0000, |
3522 | }, { // 16.0 MHz |
3523 | 0xffff0001, 0x0006ffef, 0x00020031, 0xffbaffe8, |
3524 | 0x00adff66, 0xff790198, 0xff26fe6e, 0x02e5ff55, |
3525 | 0xfc99044a, 0x005bfa09, 0x0545027f, 0xf7230541, |
3526 | 0x05b8f490, 0x03d20997, 0xf31300eb, 0x0d55f341, |
3527 | 0xfcf6100e, 0xf544f8c3, 0x110d0000, |
3528 | } |
3529 | }; |
3530 | |
3531 | static void cx23885_dif_setup(struct i2c_client *client, u32 ifHz) |
3532 | { |
3533 | u64 pll_freq; |
3534 | u32 pll_freq_word; |
3535 | const u32 *coeffs; |
3536 | |
3537 | v4l_dbg(1, cx25840_debug, client, "%s(%d)\n" , __func__, ifHz); |
3538 | |
3539 | /* Assuming TV */ |
3540 | /* Calculate the PLL frequency word based on the adjusted ifHz */ |
3541 | pll_freq = div_u64(dividend: (u64)ifHz * 268435456, divisor: 50000000); |
3542 | pll_freq_word = (u32)pll_freq; |
3543 | |
3544 | cx25840_write4(client, DIF_PLL_FREQ_WORD, value: pll_freq_word); |
3545 | |
3546 | /* Round down to the nearest 100KHz */ |
3547 | ifHz = (ifHz / 100000) * 100000; |
3548 | |
3549 | if (ifHz < 3000000) |
3550 | ifHz = 3000000; |
3551 | |
3552 | if (ifHz > 16000000) |
3553 | ifHz = 16000000; |
3554 | |
3555 | v4l_dbg(1, cx25840_debug, client, "%s(%d) again\n" , __func__, ifHz); |
3556 | |
3557 | coeffs = ifhz_coeffs[(ifHz - 3000000) / 100000]; |
3558 | cx25840_write4(client, DIF_BPF_COEFF01, value: coeffs[0]); |
3559 | cx25840_write4(client, DIF_BPF_COEFF23, value: coeffs[1]); |
3560 | cx25840_write4(client, DIF_BPF_COEFF45, value: coeffs[2]); |
3561 | cx25840_write4(client, DIF_BPF_COEFF67, value: coeffs[3]); |
3562 | cx25840_write4(client, DIF_BPF_COEFF89, value: coeffs[4]); |
3563 | cx25840_write4(client, DIF_BPF_COEFF1011, value: coeffs[5]); |
3564 | cx25840_write4(client, DIF_BPF_COEFF1213, value: coeffs[6]); |
3565 | cx25840_write4(client, DIF_BPF_COEFF1415, value: coeffs[7]); |
3566 | cx25840_write4(client, DIF_BPF_COEFF1617, value: coeffs[8]); |
3567 | cx25840_write4(client, DIF_BPF_COEFF1819, value: coeffs[9]); |
3568 | cx25840_write4(client, DIF_BPF_COEFF2021, value: coeffs[10]); |
3569 | cx25840_write4(client, DIF_BPF_COEFF2223, value: coeffs[11]); |
3570 | cx25840_write4(client, DIF_BPF_COEFF2425, value: coeffs[12]); |
3571 | cx25840_write4(client, DIF_BPF_COEFF2627, value: coeffs[13]); |
3572 | cx25840_write4(client, DIF_BPF_COEFF2829, value: coeffs[14]); |
3573 | cx25840_write4(client, DIF_BPF_COEFF3031, value: coeffs[15]); |
3574 | cx25840_write4(client, DIF_BPF_COEFF3233, value: coeffs[16]); |
3575 | cx25840_write4(client, DIF_BPF_COEFF3435, value: coeffs[17]); |
3576 | cx25840_write4(client, DIF_BPF_COEFF36, value: coeffs[18]); |
3577 | } |
3578 | |
3579 | static void cx23888_std_setup(struct i2c_client *client) |
3580 | { |
3581 | struct cx25840_state *state = to_state(sd: i2c_get_clientdata(client)); |
3582 | v4l2_std_id std = state->std; |
3583 | u32 ifHz; |
3584 | |
3585 | cx25840_write4(client, addr: 0x478, value: 0x6628021F); |
3586 | cx25840_write4(client, addr: 0x400, value: 0x0); |
3587 | cx25840_write4(client, addr: 0x4b4, value: 0x20524030); |
3588 | cx25840_write4(client, addr: 0x47c, value: 0x010a8263); |
3589 | |
3590 | if (std & V4L2_STD_525_60) { |
3591 | v4l_dbg(1, cx25840_debug, client, "%s() Selecting NTSC" , |
3592 | __func__); |
3593 | |
3594 | /* Horiz / vert timing */ |
3595 | cx25840_write4(client, addr: 0x428, value: 0x1e1e601a); |
3596 | cx25840_write4(client, addr: 0x424, value: 0x5b2d007a); |
3597 | |
3598 | /* DIF NTSC */ |
3599 | cx25840_write4(client, addr: 0x304, value: 0x6503bc0c); |
3600 | cx25840_write4(client, addr: 0x308, value: 0xbd038c85); |
3601 | cx25840_write4(client, addr: 0x30c, value: 0x1db4640a); |
3602 | cx25840_write4(client, addr: 0x310, value: 0x00008800); |
3603 | cx25840_write4(client, addr: 0x314, value: 0x44400400); |
3604 | cx25840_write4(client, addr: 0x32c, value: 0x0c800800); |
3605 | cx25840_write4(client, addr: 0x330, value: 0x27000100); |
3606 | cx25840_write4(client, addr: 0x334, value: 0x1f296e1f); |
3607 | cx25840_write4(client, addr: 0x338, value: 0x009f50c1); |
3608 | cx25840_write4(client, addr: 0x340, value: 0x1befbf06); |
3609 | cx25840_write4(client, addr: 0x344, value: 0x000035e8); |
3610 | |
3611 | /* DIF I/F */ |
3612 | ifHz = 5400000; |
3613 | |
3614 | } else { |
3615 | v4l_dbg(1, cx25840_debug, client, "%s() Selecting PAL-BG" , |
3616 | __func__); |
3617 | |
3618 | /* Horiz / vert timing */ |
3619 | cx25840_write4(client, addr: 0x428, value: 0x28244024); |
3620 | cx25840_write4(client, addr: 0x424, value: 0x5d2d0084); |
3621 | |
3622 | /* DIF */ |
3623 | cx25840_write4(client, addr: 0x304, value: 0x6503bc0c); |
3624 | cx25840_write4(client, addr: 0x308, value: 0xbd038c85); |
3625 | cx25840_write4(client, addr: 0x30c, value: 0x1db4640a); |
3626 | cx25840_write4(client, addr: 0x310, value: 0x00008800); |
3627 | cx25840_write4(client, addr: 0x314, value: 0x44400600); |
3628 | cx25840_write4(client, addr: 0x32c, value: 0x0c800800); |
3629 | cx25840_write4(client, addr: 0x330, value: 0x27000100); |
3630 | cx25840_write4(client, addr: 0x334, value: 0x213530ec); |
3631 | cx25840_write4(client, addr: 0x338, value: 0x00a65ba8); |
3632 | cx25840_write4(client, addr: 0x340, value: 0x1befbf06); |
3633 | cx25840_write4(client, addr: 0x344, value: 0x000035e8); |
3634 | |
3635 | /* DIF I/F */ |
3636 | ifHz = 6000000; |
3637 | } |
3638 | |
3639 | cx23885_dif_setup(client, ifHz); |
3640 | |
3641 | /* Explicitly ensure the inputs are reconfigured after |
3642 | * a standard change. |
3643 | */ |
3644 | set_input(client, vid_input: state->vid_input, aud_input: state->aud_input); |
3645 | } |
3646 | |
3647 | /* ----------------------------------------------------------------------- */ |
3648 | |
3649 | static const struct v4l2_ctrl_ops cx25840_ctrl_ops = { |
3650 | .s_ctrl = cx25840_s_ctrl, |
3651 | }; |
3652 | |
3653 | static const struct v4l2_subdev_core_ops cx25840_core_ops = { |
3654 | .log_status = cx25840_log_status, |
3655 | .reset = cx25840_reset, |
3656 | /* calling the (optional) init op will turn on the generic mode */ |
3657 | .init = cx25840_init, |
3658 | .load_fw = cx25840_load_fw, |
3659 | .s_io_pin_config = common_s_io_pin_config, |
3660 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
3661 | .g_register = cx25840_g_register, |
3662 | .s_register = cx25840_s_register, |
3663 | #endif |
3664 | .interrupt_service_routine = cx25840_irq_handler, |
3665 | }; |
3666 | |
3667 | static const struct v4l2_subdev_tuner_ops cx25840_tuner_ops = { |
3668 | .s_frequency = cx25840_s_frequency, |
3669 | .s_radio = cx25840_s_radio, |
3670 | .g_tuner = cx25840_g_tuner, |
3671 | .s_tuner = cx25840_s_tuner, |
3672 | }; |
3673 | |
3674 | static const struct v4l2_subdev_audio_ops cx25840_audio_ops = { |
3675 | .s_clock_freq = cx25840_s_clock_freq, |
3676 | .s_routing = cx25840_s_audio_routing, |
3677 | .s_stream = cx25840_s_audio_stream, |
3678 | }; |
3679 | |
3680 | static const struct v4l2_subdev_video_ops cx25840_video_ops = { |
3681 | .g_std = cx25840_g_std, |
3682 | .s_std = cx25840_s_std, |
3683 | .querystd = cx25840_querystd, |
3684 | .s_routing = cx25840_s_video_routing, |
3685 | .s_stream = cx25840_s_stream, |
3686 | .g_input_status = cx25840_g_input_status, |
3687 | }; |
3688 | |
3689 | static const struct v4l2_subdev_vbi_ops cx25840_vbi_ops = { |
3690 | .decode_vbi_line = cx25840_decode_vbi_line, |
3691 | .s_raw_fmt = cx25840_s_raw_fmt, |
3692 | .s_sliced_fmt = cx25840_s_sliced_fmt, |
3693 | .g_sliced_fmt = cx25840_g_sliced_fmt, |
3694 | }; |
3695 | |
3696 | static const struct v4l2_subdev_pad_ops cx25840_pad_ops = { |
3697 | .set_fmt = cx25840_set_fmt, |
3698 | }; |
3699 | |
3700 | static const struct v4l2_subdev_ops cx25840_ops = { |
3701 | .core = &cx25840_core_ops, |
3702 | .tuner = &cx25840_tuner_ops, |
3703 | .audio = &cx25840_audio_ops, |
3704 | .video = &cx25840_video_ops, |
3705 | .vbi = &cx25840_vbi_ops, |
3706 | .pad = &cx25840_pad_ops, |
3707 | .ir = &cx25840_ir_ops, |
3708 | }; |
3709 | |
3710 | /* ----------------------------------------------------------------------- */ |
3711 | |
3712 | static u32 get_cx2388x_ident(struct i2c_client *client) |
3713 | { |
3714 | u32 ret; |
3715 | |
3716 | /* Come out of digital power down */ |
3717 | cx25840_write(client, addr: 0x000, value: 0); |
3718 | |
3719 | /* |
3720 | * Detecting whether the part is cx23885/7/8 is more |
3721 | * difficult than it needs to be. No ID register. Instead we |
3722 | * probe certain registers indicated in the datasheets to look |
3723 | * for specific defaults that differ between the silicon designs. |
3724 | */ |
3725 | |
3726 | /* It's either 885/7 if the IR Tx Clk Divider register exists */ |
3727 | if (cx25840_read4(client, addr: 0x204) & 0xffff) { |
3728 | /* |
3729 | * CX23885 returns bogus repetitive byte values for the DIF, |
3730 | * which doesn't exist for it. (Ex. 8a8a8a8a or 31313131) |
3731 | */ |
3732 | ret = cx25840_read4(client, addr: 0x300); |
3733 | if (((ret & 0xffff0000) >> 16) == (ret & 0xffff)) { |
3734 | /* No DIF */ |
3735 | ret = CX23885_AV; |
3736 | } else { |
3737 | /* |
3738 | * CX23887 has a broken DIF, but the registers |
3739 | * appear valid (but unused), good enough to detect. |
3740 | */ |
3741 | ret = CX23887_AV; |
3742 | } |
3743 | } else if (cx25840_read4(client, addr: 0x300) & 0x0fffffff) { |
3744 | /* DIF PLL Freq Word reg exists; chip must be a CX23888 */ |
3745 | ret = CX23888_AV; |
3746 | } else { |
3747 | v4l_err(client, "Unable to detect h/w, assuming cx23887\n" ); |
3748 | ret = CX23887_AV; |
3749 | } |
3750 | |
3751 | /* Back into digital power down */ |
3752 | cx25840_write(client, addr: 0x000, value: 2); |
3753 | return ret; |
3754 | } |
3755 | |
3756 | static int cx25840_probe(struct i2c_client *client) |
3757 | { |
3758 | struct cx25840_state *state; |
3759 | struct v4l2_subdev *sd; |
3760 | int default_volume; |
3761 | u32 id; |
3762 | u16 device_id; |
3763 | #if defined(CONFIG_MEDIA_CONTROLLER) |
3764 | int ret; |
3765 | #endif |
3766 | |
3767 | /* Check if the adapter supports the needed features */ |
3768 | if (!i2c_check_functionality(adap: client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
3769 | return -EIO; |
3770 | |
3771 | v4l_dbg(1, cx25840_debug, client, |
3772 | "detecting cx25840 client on address 0x%x\n" , |
3773 | client->addr << 1); |
3774 | |
3775 | device_id = cx25840_read(client, addr: 0x101) << 8; |
3776 | device_id |= cx25840_read(client, addr: 0x100); |
3777 | v4l_dbg(1, cx25840_debug, client, "device_id = 0x%04x\n" , device_id); |
3778 | |
3779 | /* |
3780 | * The high byte of the device ID should be |
3781 | * 0x83 for the cx2583x and 0x84 for the cx2584x |
3782 | */ |
3783 | if ((device_id & 0xff00) == 0x8300) { |
3784 | id = CX25836 + ((device_id >> 4) & 0xf) - 6; |
3785 | } else if ((device_id & 0xff00) == 0x8400) { |
3786 | id = CX25840 + ((device_id >> 4) & 0xf); |
3787 | } else if (device_id == 0x0000) { |
3788 | id = get_cx2388x_ident(client); |
3789 | } else if ((device_id & 0xfff0) == 0x5A30) { |
3790 | /* The CX23100 (0x5A3C = 23100) doesn't have an A/V decoder */ |
3791 | id = CX2310X_AV; |
3792 | } else if ((device_id & 0xff) == (device_id >> 8)) { |
3793 | v4l_err(client, |
3794 | "likely a confused/unresponsive cx2388[578] A/V decoder found @ 0x%x (%s)\n" , |
3795 | client->addr << 1, client->adapter->name); |
3796 | v4l_err(client, |
3797 | "A method to reset it from the cx25840 driver software is not known at this time\n" ); |
3798 | return -ENODEV; |
3799 | } else { |
3800 | v4l_dbg(1, cx25840_debug, client, "cx25840 not found\n" ); |
3801 | return -ENODEV; |
3802 | } |
3803 | |
3804 | state = devm_kzalloc(dev: &client->dev, size: sizeof(*state), GFP_KERNEL); |
3805 | if (!state) |
3806 | return -ENOMEM; |
3807 | |
3808 | sd = &state->sd; |
3809 | v4l2_i2c_subdev_init(sd, client, ops: &cx25840_ops); |
3810 | #if defined(CONFIG_MEDIA_CONTROLLER) |
3811 | /* |
3812 | * TODO: add media controller support for analog video inputs like |
3813 | * composite, svideo, etc. |
3814 | * A real input pad for this analog demod would be like: |
3815 | * ___________ |
3816 | * TUNER --------> | | |
3817 | * | | |
3818 | * SVIDEO .......> | cx25840 | |
3819 | * | | |
3820 | * COMPOSITE1 ...> |_________| |
3821 | * |
3822 | * However, at least for now, there's no much gain on modelling |
3823 | * those extra inputs. So, let's add it only when needed. |
3824 | */ |
3825 | state->pads[CX25840_PAD_INPUT].flags = MEDIA_PAD_FL_SINK; |
3826 | state->pads[CX25840_PAD_INPUT].sig_type = PAD_SIGNAL_ANALOG; |
3827 | state->pads[CX25840_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE; |
3828 | state->pads[CX25840_PAD_VID_OUT].sig_type = PAD_SIGNAL_DV; |
3829 | sd->entity.function = MEDIA_ENT_F_ATV_DECODER; |
3830 | |
3831 | ret = media_entity_pads_init(entity: &sd->entity, ARRAY_SIZE(state->pads), |
3832 | pads: state->pads); |
3833 | if (ret < 0) { |
3834 | v4l_info(client, "failed to initialize media entity!\n" ); |
3835 | return ret; |
3836 | } |
3837 | #endif |
3838 | |
3839 | switch (id) { |
3840 | case CX23885_AV: |
3841 | v4l_info(client, "cx23885 A/V decoder found @ 0x%x (%s)\n" , |
3842 | client->addr << 1, client->adapter->name); |
3843 | break; |
3844 | case CX23887_AV: |
3845 | v4l_info(client, "cx23887 A/V decoder found @ 0x%x (%s)\n" , |
3846 | client->addr << 1, client->adapter->name); |
3847 | break; |
3848 | case CX23888_AV: |
3849 | v4l_info(client, "cx23888 A/V decoder found @ 0x%x (%s)\n" , |
3850 | client->addr << 1, client->adapter->name); |
3851 | break; |
3852 | case CX2310X_AV: |
3853 | v4l_info(client, "cx%d A/V decoder found @ 0x%x (%s)\n" , |
3854 | device_id, client->addr << 1, client->adapter->name); |
3855 | break; |
3856 | case CX25840: |
3857 | case CX25841: |
3858 | case CX25842: |
3859 | case CX25843: |
3860 | /* |
3861 | * Note: revision '(device_id & 0x0f) == 2' was never built. |
3862 | * The marking skips from 0x1 == 22 to 0x3 == 23. |
3863 | */ |
3864 | v4l_info(client, "cx25%3x-2%x found @ 0x%x (%s)\n" , |
3865 | (device_id & 0xfff0) >> 4, |
3866 | (device_id & 0x0f) < 3 ? (device_id & 0x0f) + 1 |
3867 | : (device_id & 0x0f), |
3868 | client->addr << 1, client->adapter->name); |
3869 | break; |
3870 | case CX25836: |
3871 | case CX25837: |
3872 | default: |
3873 | v4l_info(client, "cx25%3x-%x found @ 0x%x (%s)\n" , |
3874 | (device_id & 0xfff0) >> 4, device_id & 0x0f, |
3875 | client->addr << 1, client->adapter->name); |
3876 | break; |
3877 | } |
3878 | |
3879 | state->c = client; |
3880 | state->vid_input = CX25840_COMPOSITE7; |
3881 | state->aud_input = CX25840_AUDIO8; |
3882 | state->audclk_freq = 48000; |
3883 | state->audmode = V4L2_TUNER_MODE_LANG1; |
3884 | state->vbi_line_offset = 8; |
3885 | state->id = id; |
3886 | state->rev = device_id; |
3887 | state->vbi_regs_offset = id == CX23888_AV ? 0x500 - 0x424 : 0; |
3888 | state->std = V4L2_STD_NTSC_M; |
3889 | v4l2_ctrl_handler_init(&state->hdl, 9); |
3890 | v4l2_ctrl_new_std(hdl: &state->hdl, ops: &cx25840_ctrl_ops, |
3891 | V4L2_CID_BRIGHTNESS, min: 0, max: 255, step: 1, def: 128); |
3892 | v4l2_ctrl_new_std(hdl: &state->hdl, ops: &cx25840_ctrl_ops, |
3893 | V4L2_CID_CONTRAST, min: 0, max: 127, step: 1, def: 64); |
3894 | v4l2_ctrl_new_std(hdl: &state->hdl, ops: &cx25840_ctrl_ops, |
3895 | V4L2_CID_SATURATION, min: 0, max: 127, step: 1, def: 64); |
3896 | v4l2_ctrl_new_std(hdl: &state->hdl, ops: &cx25840_ctrl_ops, |
3897 | V4L2_CID_HUE, min: -128, max: 127, step: 1, def: 0); |
3898 | if (!is_cx2583x(state)) { |
3899 | default_volume = cx25840_read(client, addr: 0x8d4); |
3900 | /* |
3901 | * Enforce the legacy PVR-350/MSP3400 to PVR-150/CX25843 volume |
3902 | * scale mapping limits to avoid -ERANGE errors when |
3903 | * initializing the volume control |
3904 | */ |
3905 | if (default_volume > 228) { |
3906 | /* Bottom out at -96 dB, v4l2 vol range 0x2e00-0x2fff */ |
3907 | default_volume = 228; |
3908 | cx25840_write(client, addr: 0x8d4, value: 228); |
3909 | } else if (default_volume < 20) { |
3910 | /* Top out at + 8 dB, v4l2 vol range 0xfe00-0xffff */ |
3911 | default_volume = 20; |
3912 | cx25840_write(client, addr: 0x8d4, value: 20); |
3913 | } |
3914 | default_volume = (((228 - default_volume) >> 1) + 23) << 9; |
3915 | |
3916 | state->volume = v4l2_ctrl_new_std(hdl: &state->hdl, |
3917 | ops: &cx25840_audio_ctrl_ops, |
3918 | V4L2_CID_AUDIO_VOLUME, |
3919 | min: 0, max: 65535, step: 65535 / 100, |
3920 | def: default_volume); |
3921 | state->mute = v4l2_ctrl_new_std(hdl: &state->hdl, |
3922 | ops: &cx25840_audio_ctrl_ops, |
3923 | V4L2_CID_AUDIO_MUTE, |
3924 | min: 0, max: 1, step: 1, def: 0); |
3925 | v4l2_ctrl_new_std(hdl: &state->hdl, ops: &cx25840_audio_ctrl_ops, |
3926 | V4L2_CID_AUDIO_BALANCE, |
3927 | min: 0, max: 65535, step: 65535 / 100, def: 32768); |
3928 | v4l2_ctrl_new_std(hdl: &state->hdl, ops: &cx25840_audio_ctrl_ops, |
3929 | V4L2_CID_AUDIO_BASS, |
3930 | min: 0, max: 65535, step: 65535 / 100, def: 32768); |
3931 | v4l2_ctrl_new_std(hdl: &state->hdl, ops: &cx25840_audio_ctrl_ops, |
3932 | V4L2_CID_AUDIO_TREBLE, |
3933 | min: 0, max: 65535, step: 65535 / 100, def: 32768); |
3934 | } |
3935 | sd->ctrl_handler = &state->hdl; |
3936 | if (state->hdl.error) { |
3937 | int err = state->hdl.error; |
3938 | |
3939 | v4l2_ctrl_handler_free(hdl: &state->hdl); |
3940 | return err; |
3941 | } |
3942 | if (!is_cx2583x(state)) |
3943 | v4l2_ctrl_cluster(ncontrols: 2, controls: &state->volume); |
3944 | v4l2_ctrl_handler_setup(hdl: &state->hdl); |
3945 | |
3946 | if (client->dev.platform_data) { |
3947 | struct cx25840_platform_data *pdata = client->dev.platform_data; |
3948 | |
3949 | state->pvr150_workaround = pdata->pvr150_workaround; |
3950 | } |
3951 | |
3952 | cx25840_ir_probe(sd); |
3953 | return 0; |
3954 | } |
3955 | |
3956 | static void cx25840_remove(struct i2c_client *client) |
3957 | { |
3958 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
3959 | struct cx25840_state *state = to_state(sd); |
3960 | |
3961 | cx25840_ir_remove(sd); |
3962 | v4l2_device_unregister_subdev(sd); |
3963 | v4l2_ctrl_handler_free(hdl: &state->hdl); |
3964 | } |
3965 | |
3966 | static const struct i2c_device_id cx25840_id[] = { |
3967 | { "cx25840" , 0 }, |
3968 | { } |
3969 | }; |
3970 | MODULE_DEVICE_TABLE(i2c, cx25840_id); |
3971 | |
3972 | static struct i2c_driver cx25840_driver = { |
3973 | .driver = { |
3974 | .name = "cx25840" , |
3975 | }, |
3976 | .probe = cx25840_probe, |
3977 | .remove = cx25840_remove, |
3978 | .id_table = cx25840_id, |
3979 | }; |
3980 | |
3981 | module_i2c_driver(cx25840_driver); |
3982 | |