diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-02-26 20:16:20 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-02-26 20:16:20 -0500 |
commit | 2b8c70b2174402ca3dec13310ce56597233392d7 (patch) | |
tree | 0aed464521a2a671cbb7b4302b55fe72abc95d3d /drivers | |
parent | 29e1fa3565a7951cc415c634eb2b78dbdbee151d (diff) | |
parent | 3621263a4d9679726b7bc1e2546c1c03941a59b4 (diff) |
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6
* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (362 commits)
V4L-DVB: cx88-dvb: remove extra attribution for core
V4L/DVB: v4l: soc_camera: fix bound checking of mbus_fmt[] index
V4L/DVB: Add support for SMT7020 to cx88
V4L/DVB: radio-si470x: Use UTF-8 encoding on a comment
V4L/DVB: MAINTAINERS: Telegent tlg2300 section fix
V4L/DVB: gspca_stv06xx: Add support for camera button
V4L/DVB: gspca_ov519: add support for the button on ov511 based cams
V4L/DVB: gspca_ov519: Add support for the button on ov518 based cams
V4L/DVB: gspca_ov519: add support for the button on ov519 based cams
V4L/DVB: gspca_main: Fix a compile error when CONFIG_INPUT is not set
V4L/DVB: gspca_main: some input error handling fixes
V4L/DVB: gspca_main: Allow use of input device creation code for non int. inputs
V4L/DVB: gspca_pac7302: much improved exposure control
V4L/DVB: gspca_sonixb: Make sonixb driver handle pas106 and pas202 cameras
V4L/DVB: gspca_sonixb: pas106: fixup bright ctrl and add gain and exposure ctrls
V4L/DVB: Documentation: gspca.txt: update known mr97310a cams
V4L/DVB: gspca_mr97310a: add support for the Sakar 1638x CyberPix
V4L/DVB: gscpa_sonixb: limit ov7630 max framerate at 640x480
V4L/DVB: gspca_sonixb: pas202: fixup brightness ctrl and add gain and exposure ctrls
V4L/DVB: gscpa_sonixb: Differentiate between sensors with a coarse and fine expo ctrl
...
Diffstat (limited to 'drivers')
257 files changed, 26403 insertions, 4585 deletions
diff --git a/drivers/media/IR/Makefile b/drivers/media/IR/Makefile index df5ddb4bbbf7..171890e7a41d 100644 --- a/drivers/media/IR/Makefile +++ b/drivers/media/IR/Makefile | |||
@@ -1,5 +1,5 @@ | |||
1 | ir-common-objs := ir-functions.o ir-keymaps.o | 1 | ir-common-objs := ir-functions.o ir-keymaps.o |
2 | ir-core-objs := ir-keytable.o | 2 | ir-core-objs := ir-keytable.o ir-sysfs.o |
3 | 3 | ||
4 | obj-$(CONFIG_IR_CORE) += ir-core.o | 4 | obj-$(CONFIG_IR_CORE) += ir-core.o |
5 | obj-$(CONFIG_VIDEO_IR) += ir-common.o | 5 | obj-$(CONFIG_VIDEO_IR) += ir-common.o |
diff --git a/drivers/media/IR/ir-functions.c b/drivers/media/IR/ir-functions.c index 776a136616d6..ab06919ad5fc 100644 --- a/drivers/media/IR/ir-functions.c +++ b/drivers/media/IR/ir-functions.c | |||
@@ -52,7 +52,7 @@ static void ir_input_key_event(struct input_dev *dev, struct ir_input_state *ir) | |||
52 | /* -------------------------------------------------------------------------- */ | 52 | /* -------------------------------------------------------------------------- */ |
53 | 53 | ||
54 | int ir_input_init(struct input_dev *dev, struct ir_input_state *ir, | 54 | int ir_input_init(struct input_dev *dev, struct ir_input_state *ir, |
55 | int ir_type) | 55 | const u64 ir_type) |
56 | { | 56 | { |
57 | ir->ir_type = ir_type; | 57 | ir->ir_type = ir_type; |
58 | 58 | ||
diff --git a/drivers/media/IR/ir-keymaps.c b/drivers/media/IR/ir-keymaps.c index 9bbe6b1e9871..0efdefe75f32 100644 --- a/drivers/media/IR/ir-keymaps.c +++ b/drivers/media/IR/ir-keymaps.c | |||
@@ -3393,3 +3393,102 @@ struct ir_scancode_table ir_codes_nec_terratec_cinergy_xs_table = { | |||
3393 | }; | 3393 | }; |
3394 | EXPORT_SYMBOL_GPL(ir_codes_nec_terratec_cinergy_xs_table); | 3394 | EXPORT_SYMBOL_GPL(ir_codes_nec_terratec_cinergy_xs_table); |
3395 | 3395 | ||
3396 | |||
3397 | /* Leadtek Winfast TV USB II Deluxe remote | ||
3398 | Magnus Alm <magnus.alm@gmail.com> | ||
3399 | */ | ||
3400 | static struct ir_scancode ir_codes_winfast_usbii_deluxe[] = { | ||
3401 | { 0x62, KEY_0}, | ||
3402 | { 0x75, KEY_1}, | ||
3403 | { 0x76, KEY_2}, | ||
3404 | { 0x77, KEY_3}, | ||
3405 | { 0x79, KEY_4}, | ||
3406 | { 0x7a, KEY_5}, | ||
3407 | { 0x7b, KEY_6}, | ||
3408 | { 0x7d, KEY_7}, | ||
3409 | { 0x7e, KEY_8}, | ||
3410 | { 0x7f, KEY_9}, | ||
3411 | |||
3412 | { 0x38, KEY_CAMERA}, /* SNAPSHOT */ | ||
3413 | { 0x37, KEY_RECORD}, /* RECORD */ | ||
3414 | { 0x35, KEY_TIME}, /* TIMESHIFT */ | ||
3415 | |||
3416 | { 0x74, KEY_VOLUMEUP}, /* VOLUMEUP */ | ||
3417 | { 0x78, KEY_VOLUMEDOWN}, /* VOLUMEDOWN */ | ||
3418 | { 0x64, KEY_MUTE}, /* MUTE */ | ||
3419 | |||
3420 | { 0x21, KEY_CHANNEL}, /* SURF */ | ||
3421 | { 0x7c, KEY_CHANNELUP}, /* CHANNELUP */ | ||
3422 | { 0x60, KEY_CHANNELDOWN}, /* CHANNELDOWN */ | ||
3423 | { 0x61, KEY_LAST}, /* LAST CHANNEL (RECALL) */ | ||
3424 | |||
3425 | { 0x72, KEY_VIDEO}, /* INPUT MODES (TV/FM) */ | ||
3426 | |||
3427 | { 0x70, KEY_POWER2}, /* TV ON/OFF */ | ||
3428 | |||
3429 | { 0x39, KEY_CYCLEWINDOWS}, /* MINIMIZE (BOSS) */ | ||
3430 | { 0x3a, KEY_NEW}, /* PIP */ | ||
3431 | { 0x73, KEY_ZOOM}, /* FULLSECREEN */ | ||
3432 | |||
3433 | { 0x66, KEY_INFO}, /* OSD (DISPLAY) */ | ||
3434 | |||
3435 | { 0x31, KEY_DOT}, /* '.' */ | ||
3436 | { 0x63, KEY_ENTER}, /* ENTER */ | ||
3437 | |||
3438 | }; | ||
3439 | struct ir_scancode_table ir_codes_winfast_usbii_deluxe_table = { | ||
3440 | .scan = ir_codes_winfast_usbii_deluxe, | ||
3441 | .size = ARRAY_SIZE(ir_codes_winfast_usbii_deluxe), | ||
3442 | }; | ||
3443 | EXPORT_SYMBOL_GPL(ir_codes_winfast_usbii_deluxe_table); | ||
3444 | |||
3445 | /* Kworld 315U | ||
3446 | */ | ||
3447 | static struct ir_scancode ir_codes_kworld_315u[] = { | ||
3448 | { 0x6143, KEY_POWER }, | ||
3449 | { 0x6101, KEY_TUNER }, /* source */ | ||
3450 | { 0x610b, KEY_ZOOM }, | ||
3451 | { 0x6103, KEY_POWER2 }, /* shutdown */ | ||
3452 | |||
3453 | { 0x6104, KEY_1 }, | ||
3454 | { 0x6108, KEY_2 }, | ||
3455 | { 0x6102, KEY_3 }, | ||
3456 | { 0x6109, KEY_CHANNELUP }, | ||
3457 | |||
3458 | { 0x610f, KEY_4 }, | ||
3459 | { 0x6105, KEY_5 }, | ||
3460 | { 0x6106, KEY_6 }, | ||
3461 | { 0x6107, KEY_CHANNELDOWN }, | ||
3462 | |||
3463 | { 0x610c, KEY_7 }, | ||
3464 | { 0x610d, KEY_8 }, | ||
3465 | { 0x610a, KEY_9 }, | ||
3466 | { 0x610e, KEY_VOLUMEUP }, | ||
3467 | |||
3468 | { 0x6110, KEY_LAST }, | ||
3469 | { 0x6111, KEY_0 }, | ||
3470 | { 0x6112, KEY_ENTER }, | ||
3471 | { 0x6113, KEY_VOLUMEDOWN }, | ||
3472 | |||
3473 | { 0x6114, KEY_RECORD }, | ||
3474 | { 0x6115, KEY_STOP }, | ||
3475 | { 0x6116, KEY_PLAY }, | ||
3476 | { 0x6117, KEY_MUTE }, | ||
3477 | |||
3478 | { 0x6118, KEY_UP }, | ||
3479 | { 0x6119, KEY_DOWN }, | ||
3480 | { 0x611a, KEY_LEFT }, | ||
3481 | { 0x611b, KEY_RIGHT }, | ||
3482 | |||
3483 | { 0x611c, KEY_RED }, | ||
3484 | { 0x611d, KEY_GREEN }, | ||
3485 | { 0x611e, KEY_YELLOW }, | ||
3486 | { 0x611f, KEY_BLUE }, | ||
3487 | }; | ||
3488 | |||
3489 | struct ir_scancode_table ir_codes_kworld_315u_table = { | ||
3490 | .scan = ir_codes_kworld_315u, | ||
3491 | .size = ARRAY_SIZE(ir_codes_kworld_315u), | ||
3492 | .ir_type = IR_TYPE_NEC, | ||
3493 | }; | ||
3494 | EXPORT_SYMBOL_GPL(ir_codes_kworld_315u_table); | ||
diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c index b521ed9d6e2e..0903f539bf68 100644 --- a/drivers/media/IR/ir-keytable.c +++ b/drivers/media/IR/ir-keytable.c | |||
@@ -65,7 +65,7 @@ exit: | |||
65 | * In order to reduce the quantity of table resizes, it has a minimum | 65 | * In order to reduce the quantity of table resizes, it has a minimum |
66 | * table size of IR_TAB_MIN_SIZE. | 66 | * table size of IR_TAB_MIN_SIZE. |
67 | */ | 67 | */ |
68 | int ir_roundup_tablesize(int n_elems) | 68 | static int ir_roundup_tablesize(int n_elems) |
69 | { | 69 | { |
70 | size_t size; | 70 | size_t size; |
71 | 71 | ||
@@ -81,7 +81,6 @@ int ir_roundup_tablesize(int n_elems) | |||
81 | 81 | ||
82 | return n_elems; | 82 | return n_elems; |
83 | } | 83 | } |
84 | EXPORT_SYMBOL_GPL(ir_roundup_tablesize); | ||
85 | 84 | ||
86 | /** | 85 | /** |
87 | * ir_copy_table() - copies a keytable, discarding the unused entries | 86 | * ir_copy_table() - copies a keytable, discarding the unused entries |
@@ -89,9 +88,11 @@ EXPORT_SYMBOL_GPL(ir_roundup_tablesize); | |||
89 | * @origin: origin table | 88 | * @origin: origin table |
90 | * | 89 | * |
91 | * Copies all entries where the keycode is not KEY_UNKNOWN/KEY_RESERVED | 90 | * Copies all entries where the keycode is not KEY_UNKNOWN/KEY_RESERVED |
91 | * Also copies table size and table protocol. | ||
92 | * NOTE: It shouldn't copy the lock field | ||
92 | */ | 93 | */ |
93 | 94 | ||
94 | int ir_copy_table(struct ir_scancode_table *destin, | 95 | static int ir_copy_table(struct ir_scancode_table *destin, |
95 | const struct ir_scancode_table *origin) | 96 | const struct ir_scancode_table *origin) |
96 | { | 97 | { |
97 | int i, j = 0; | 98 | int i, j = 0; |
@@ -105,12 +106,12 @@ int ir_copy_table(struct ir_scancode_table *destin, | |||
105 | j++; | 106 | j++; |
106 | } | 107 | } |
107 | destin->size = j; | 108 | destin->size = j; |
109 | destin->ir_type = origin->ir_type; | ||
108 | 110 | ||
109 | IR_dprintk(1, "Copied %d scancodes to the new keycode table\n", destin->size); | 111 | IR_dprintk(1, "Copied %d scancodes to the new keycode table\n", destin->size); |
110 | 112 | ||
111 | return 0; | 113 | return 0; |
112 | } | 114 | } |
113 | EXPORT_SYMBOL_GPL(ir_copy_table); | ||
114 | 115 | ||
115 | /** | 116 | /** |
116 | * ir_getkeycode() - get a keycode at the evdev scancode ->keycode table | 117 | * ir_getkeycode() - get a keycode at the evdev scancode ->keycode table |
@@ -184,18 +185,14 @@ static void ir_delete_key(struct ir_scancode_table *rc_tab, int elem) | |||
184 | int newsize = rc_tab->size - 1; | 185 | int newsize = rc_tab->size - 1; |
185 | int resize = ir_is_resize_needed(rc_tab, newsize); | 186 | int resize = ir_is_resize_needed(rc_tab, newsize); |
186 | struct ir_scancode *oldkeymap = rc_tab->scan; | 187 | struct ir_scancode *oldkeymap = rc_tab->scan; |
187 | struct ir_scancode *newkeymap; | 188 | struct ir_scancode *newkeymap = NULL; |
188 | 189 | ||
189 | if (resize) { | 190 | if (resize) |
190 | newkeymap = kzalloc(ir_roundup_tablesize(newsize) * | 191 | newkeymap = kzalloc(ir_roundup_tablesize(newsize) * |
191 | sizeof(*newkeymap), GFP_ATOMIC); | 192 | sizeof(*newkeymap), GFP_ATOMIC); |
192 | 193 | ||
193 | /* There's no memory for resize. Keep the old table */ | 194 | /* There's no memory for resize. Keep the old table */ |
194 | if (!newkeymap) | 195 | if (!resize || !newkeymap) { |
195 | resize = 0; | ||
196 | } | ||
197 | |||
198 | if (!resize) { | ||
199 | newkeymap = oldkeymap; | 196 | newkeymap = oldkeymap; |
200 | 197 | ||
201 | /* We'll modify the live table. Lock it */ | 198 | /* We'll modify the live table. Lock it */ |
@@ -399,12 +396,14 @@ EXPORT_SYMBOL_GPL(ir_g_keycode_from_table); | |||
399 | * @input_dev: the struct input_dev descriptor of the device | 396 | * @input_dev: the struct input_dev descriptor of the device |
400 | * @rc_tab: the struct ir_scancode_table table of scancode/keymap | 397 | * @rc_tab: the struct ir_scancode_table table of scancode/keymap |
401 | * | 398 | * |
402 | * This routine is used to initialize the input infrastructure to work with | 399 | * This routine is used to initialize the input infrastructure |
403 | * an IR. | 400 | * to work with an IR. |
404 | * It should be called before registering the IR device. | 401 | * It will register the input/evdev interface for the device and |
402 | * register the syfs code for IR class | ||
405 | */ | 403 | */ |
406 | int ir_input_register(struct input_dev *input_dev, | 404 | int ir_input_register(struct input_dev *input_dev, |
407 | struct ir_scancode_table *rc_tab) | 405 | const struct ir_scancode_table *rc_tab, |
406 | const struct ir_dev_props *props) | ||
408 | { | 407 | { |
409 | struct ir_input_dev *ir_dev; | 408 | struct ir_input_dev *ir_dev; |
410 | struct ir_scancode *keymap = rc_tab->scan; | 409 | struct ir_scancode *keymap = rc_tab->scan; |
@@ -417,19 +416,22 @@ int ir_input_register(struct input_dev *input_dev, | |||
417 | if (!ir_dev) | 416 | if (!ir_dev) |
418 | return -ENOMEM; | 417 | return -ENOMEM; |
419 | 418 | ||
420 | spin_lock_init(&rc_tab->lock); | 419 | spin_lock_init(&ir_dev->rc_tab.lock); |
421 | 420 | ||
422 | ir_dev->rc_tab.size = ir_roundup_tablesize(rc_tab->size); | 421 | ir_dev->rc_tab.size = ir_roundup_tablesize(rc_tab->size); |
423 | ir_dev->rc_tab.scan = kzalloc(ir_dev->rc_tab.size * | 422 | ir_dev->rc_tab.scan = kzalloc(ir_dev->rc_tab.size * |
424 | sizeof(struct ir_scancode), GFP_KERNEL); | 423 | sizeof(struct ir_scancode), GFP_KERNEL); |
425 | if (!ir_dev->rc_tab.scan) | 424 | if (!ir_dev->rc_tab.scan) { |
425 | kfree(ir_dev); | ||
426 | return -ENOMEM; | 426 | return -ENOMEM; |
427 | } | ||
427 | 428 | ||
428 | IR_dprintk(1, "Allocated space for %d keycode entries (%zd bytes)\n", | 429 | IR_dprintk(1, "Allocated space for %d keycode entries (%zd bytes)\n", |
429 | ir_dev->rc_tab.size, | 430 | ir_dev->rc_tab.size, |
430 | ir_dev->rc_tab.size * sizeof(ir_dev->rc_tab.scan)); | 431 | ir_dev->rc_tab.size * sizeof(ir_dev->rc_tab.scan)); |
431 | 432 | ||
432 | ir_copy_table(&ir_dev->rc_tab, rc_tab); | 433 | ir_copy_table(&ir_dev->rc_tab, rc_tab); |
434 | ir_dev->props = props; | ||
433 | 435 | ||
434 | /* set the bits for the keys */ | 436 | /* set the bits for the keys */ |
435 | IR_dprintk(1, "key map size: %d\n", rc_tab->size); | 437 | IR_dprintk(1, "key map size: %d\n", rc_tab->size); |
@@ -447,16 +449,31 @@ int ir_input_register(struct input_dev *input_dev, | |||
447 | input_set_drvdata(input_dev, ir_dev); | 449 | input_set_drvdata(input_dev, ir_dev); |
448 | 450 | ||
449 | rc = input_register_device(input_dev); | 451 | rc = input_register_device(input_dev); |
452 | if (rc < 0) | ||
453 | goto err; | ||
454 | |||
455 | rc = ir_register_class(input_dev); | ||
450 | if (rc < 0) { | 456 | if (rc < 0) { |
451 | kfree(rc_tab->scan); | 457 | input_unregister_device(input_dev); |
452 | kfree(ir_dev); | 458 | goto err; |
453 | input_set_drvdata(input_dev, NULL); | ||
454 | } | 459 | } |
455 | 460 | ||
461 | return 0; | ||
462 | |||
463 | err: | ||
464 | kfree(rc_tab->scan); | ||
465 | kfree(ir_dev); | ||
466 | input_set_drvdata(input_dev, NULL); | ||
456 | return rc; | 467 | return rc; |
457 | } | 468 | } |
458 | EXPORT_SYMBOL_GPL(ir_input_register); | 469 | EXPORT_SYMBOL_GPL(ir_input_register); |
459 | 470 | ||
471 | /** | ||
472 | * ir_input_unregister() - unregisters IR and frees resources | ||
473 | * @input_dev: the struct input_dev descriptor of the device | ||
474 | |||
475 | * This routine is used to free memory and de-register interfaces. | ||
476 | */ | ||
460 | void ir_input_unregister(struct input_dev *dev) | 477 | void ir_input_unregister(struct input_dev *dev) |
461 | { | 478 | { |
462 | struct ir_input_dev *ir_dev = input_get_drvdata(dev); | 479 | struct ir_input_dev *ir_dev = input_get_drvdata(dev); |
@@ -472,6 +489,8 @@ void ir_input_unregister(struct input_dev *dev) | |||
472 | kfree(rc_tab->scan); | 489 | kfree(rc_tab->scan); |
473 | rc_tab->scan = NULL; | 490 | rc_tab->scan = NULL; |
474 | 491 | ||
492 | ir_unregister_class(dev); | ||
493 | |||
475 | kfree(ir_dev); | 494 | kfree(ir_dev); |
476 | input_unregister_device(dev); | 495 | input_unregister_device(dev); |
477 | } | 496 | } |
diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c new file mode 100644 index 000000000000..bf5fbcd84238 --- /dev/null +++ b/drivers/media/IR/ir-sysfs.c | |||
@@ -0,0 +1,211 @@ | |||
1 | /* ir-register.c - handle IR scancode->keycode tables | ||
2 | * | ||
3 | * Copyright (C) 2009 by Mauro Carvalho Chehab <mchehab@redhat.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation version 2 of the License. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | */ | ||
14 | |||
15 | #include <linux/input.h> | ||
16 | #include <linux/device.h> | ||
17 | #include <media/ir-core.h> | ||
18 | |||
19 | #define IRRCV_NUM_DEVICES 256 | ||
20 | |||
21 | /* bit array to represent IR sysfs device number */ | ||
22 | static unsigned long ir_core_dev_number; | ||
23 | |||
24 | /* class for /sys/class/irrcv */ | ||
25 | static struct class *ir_input_class; | ||
26 | |||
27 | /** | ||
28 | * show_protocol() - shows the current IR protocol | ||
29 | * @d: the device descriptor | ||
30 | * @mattr: the device attribute struct (unused) | ||
31 | * @buf: a pointer to the output buffer | ||
32 | * | ||
33 | * This routine is a callback routine for input read the IR protocol type. | ||
34 | * it is trigged by reading /sys/class/irrcv/irrcv?/current_protocol. | ||
35 | * It returns the protocol name, as understood by the driver. | ||
36 | */ | ||
37 | static ssize_t show_protocol(struct device *d, | ||
38 | struct device_attribute *mattr, char *buf) | ||
39 | { | ||
40 | char *s; | ||
41 | struct ir_input_dev *ir_dev = dev_get_drvdata(d); | ||
42 | u64 ir_type = ir_dev->rc_tab.ir_type; | ||
43 | |||
44 | IR_dprintk(1, "Current protocol is %lld\n", (long long)ir_type); | ||
45 | |||
46 | /* FIXME: doesn't support multiple protocols at the same time */ | ||
47 | if (ir_type == IR_TYPE_UNKNOWN) | ||
48 | s = "Unknown"; | ||
49 | else if (ir_type == IR_TYPE_RC5) | ||
50 | s = "RC-5"; | ||
51 | else if (ir_type == IR_TYPE_PD) | ||
52 | s = "Pulse/distance"; | ||
53 | else if (ir_type == IR_TYPE_NEC) | ||
54 | s = "NEC"; | ||
55 | else | ||
56 | s = "Other"; | ||
57 | |||
58 | return sprintf(buf, "%s\n", s); | ||
59 | } | ||
60 | |||
61 | /** | ||
62 | * store_protocol() - shows the current IR protocol | ||
63 | * @d: the device descriptor | ||
64 | * @mattr: the device attribute struct (unused) | ||
65 | * @buf: a pointer to the input buffer | ||
66 | * @len: length of the input buffer | ||
67 | * | ||
68 | * This routine is a callback routine for changing the IR protocol type. | ||
69 | * it is trigged by reading /sys/class/irrcv/irrcv?/current_protocol. | ||
70 | * It changes the IR the protocol name, if the IR type is recognized | ||
71 | * by the driver. | ||
72 | * If an unknown protocol name is used, returns -EINVAL. | ||
73 | */ | ||
74 | static ssize_t store_protocol(struct device *d, | ||
75 | struct device_attribute *mattr, | ||
76 | const char *data, | ||
77 | size_t len) | ||
78 | { | ||
79 | struct ir_input_dev *ir_dev = dev_get_drvdata(d); | ||
80 | u64 ir_type = IR_TYPE_UNKNOWN; | ||
81 | int rc = -EINVAL; | ||
82 | unsigned long flags; | ||
83 | char *buf; | ||
84 | |||
85 | buf = strsep((char **) &data, "\n"); | ||
86 | |||
87 | if (!strcasecmp(buf, "rc-5")) | ||
88 | ir_type = IR_TYPE_RC5; | ||
89 | else if (!strcasecmp(buf, "pd")) | ||
90 | ir_type = IR_TYPE_PD; | ||
91 | else if (!strcasecmp(buf, "nec")) | ||
92 | ir_type = IR_TYPE_NEC; | ||
93 | |||
94 | if (ir_type == IR_TYPE_UNKNOWN) { | ||
95 | IR_dprintk(1, "Error setting protocol to %lld\n", | ||
96 | (long long)ir_type); | ||
97 | return -EINVAL; | ||
98 | } | ||
99 | |||
100 | if (ir_dev->props && ir_dev->props->change_protocol) | ||
101 | rc = ir_dev->props->change_protocol(ir_dev->props->priv, | ||
102 | ir_type); | ||
103 | |||
104 | if (rc < 0) { | ||
105 | IR_dprintk(1, "Error setting protocol to %lld\n", | ||
106 | (long long)ir_type); | ||
107 | return -EINVAL; | ||
108 | } | ||
109 | |||
110 | spin_lock_irqsave(&ir_dev->rc_tab.lock, flags); | ||
111 | ir_dev->rc_tab.ir_type = ir_type; | ||
112 | spin_unlock_irqrestore(&ir_dev->rc_tab.lock, flags); | ||
113 | |||
114 | IR_dprintk(1, "Current protocol is %lld\n", | ||
115 | (long long)ir_type); | ||
116 | |||
117 | return len; | ||
118 | } | ||
119 | |||
120 | /* | ||
121 | * Static device attribute struct with the sysfs attributes for IR's | ||
122 | */ | ||
123 | static DEVICE_ATTR(current_protocol, S_IRUGO | S_IWUSR, | ||
124 | show_protocol, store_protocol); | ||
125 | |||
126 | static struct attribute *ir_dev_attrs[] = { | ||
127 | &dev_attr_current_protocol.attr, | ||
128 | NULL, | ||
129 | }; | ||
130 | |||
131 | /** | ||
132 | * ir_register_class() - creates the sysfs for /sys/class/irrcv/irrcv? | ||
133 | * @input_dev: the struct input_dev descriptor of the device | ||
134 | * | ||
135 | * This routine is used to register the syfs code for IR class | ||
136 | */ | ||
137 | int ir_register_class(struct input_dev *input_dev) | ||
138 | { | ||
139 | int rc; | ||
140 | struct kobject *kobj; | ||
141 | |||
142 | struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); | ||
143 | int devno = find_first_zero_bit(&ir_core_dev_number, | ||
144 | IRRCV_NUM_DEVICES); | ||
145 | |||
146 | if (unlikely(devno < 0)) | ||
147 | return devno; | ||
148 | |||
149 | ir_dev->attr.attrs = ir_dev_attrs; | ||
150 | ir_dev->class_dev = device_create(ir_input_class, NULL, | ||
151 | input_dev->dev.devt, ir_dev, | ||
152 | "irrcv%d", devno); | ||
153 | kobj = &ir_dev->class_dev->kobj; | ||
154 | |||
155 | printk(KERN_WARNING "Creating IR device %s\n", kobject_name(kobj)); | ||
156 | rc = sysfs_create_group(kobj, &ir_dev->attr); | ||
157 | if (unlikely(rc < 0)) { | ||
158 | device_destroy(ir_input_class, input_dev->dev.devt); | ||
159 | return -ENOMEM; | ||
160 | } | ||
161 | |||
162 | ir_dev->devno = devno; | ||
163 | set_bit(devno, &ir_core_dev_number); | ||
164 | |||
165 | return 0; | ||
166 | }; | ||
167 | |||
168 | /** | ||
169 | * ir_unregister_class() - removes the sysfs for sysfs for | ||
170 | * /sys/class/irrcv/irrcv? | ||
171 | * @input_dev: the struct input_dev descriptor of the device | ||
172 | * | ||
173 | * This routine is used to unregister the syfs code for IR class | ||
174 | */ | ||
175 | void ir_unregister_class(struct input_dev *input_dev) | ||
176 | { | ||
177 | struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); | ||
178 | struct kobject *kobj; | ||
179 | |||
180 | clear_bit(ir_dev->devno, &ir_core_dev_number); | ||
181 | |||
182 | kobj = &ir_dev->class_dev->kobj; | ||
183 | |||
184 | sysfs_remove_group(kobj, &ir_dev->attr); | ||
185 | device_destroy(ir_input_class, input_dev->dev.devt); | ||
186 | |||
187 | kfree(ir_dev->attr.name); | ||
188 | } | ||
189 | |||
190 | /* | ||
191 | * Init/exit code for the module. Basically, creates/removes /sys/class/irrcv | ||
192 | */ | ||
193 | |||
194 | static int __init ir_core_init(void) | ||
195 | { | ||
196 | ir_input_class = class_create(THIS_MODULE, "irrcv"); | ||
197 | if (IS_ERR(ir_input_class)) { | ||
198 | printk(KERN_ERR "ir_core: unable to register irrcv class\n"); | ||
199 | return PTR_ERR(ir_input_class); | ||
200 | } | ||
201 | |||
202 | return 0; | ||
203 | } | ||
204 | |||
205 | static void __exit ir_core_exit(void) | ||
206 | { | ||
207 | class_destroy(ir_input_class); | ||
208 | } | ||
209 | |||
210 | module_init(ir_core_init); | ||
211 | module_exit(ir_core_exit); | ||
diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c index 7364b9642d00..fd8e1f45be36 100644 --- a/drivers/media/common/saa7146_fops.c +++ b/drivers/media/common/saa7146_fops.c | |||
@@ -423,14 +423,15 @@ static void vv_callback(struct saa7146_dev *dev, unsigned long status) | |||
423 | } | 423 | } |
424 | } | 424 | } |
425 | 425 | ||
426 | int saa7146_vv_devinit(struct saa7146_dev *dev) | ||
427 | { | ||
428 | return v4l2_device_register(&dev->pci->dev, &dev->v4l2_dev); | ||
429 | } | ||
430 | EXPORT_SYMBOL_GPL(saa7146_vv_devinit); | ||
431 | |||
426 | int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv) | 432 | int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv) |
427 | { | 433 | { |
428 | struct saa7146_vv *vv; | 434 | struct saa7146_vv *vv; |
429 | int err; | ||
430 | |||
431 | err = v4l2_device_register(&dev->pci->dev, &dev->v4l2_dev); | ||
432 | if (err) | ||
433 | return err; | ||
434 | 435 | ||
435 | vv = kzalloc(sizeof(struct saa7146_vv), GFP_KERNEL); | 436 | vv = kzalloc(sizeof(struct saa7146_vv), GFP_KERNEL); |
436 | if (vv == NULL) { | 437 | if (vv == NULL) { |
diff --git a/drivers/media/common/tuners/tuner-types.c b/drivers/media/common/tuners/tuner-types.c index 2b876f3988c1..d9aaaca620c9 100644 --- a/drivers/media/common/tuners/tuner-types.c +++ b/drivers/media/common/tuners/tuner-types.c | |||
@@ -1337,6 +1337,22 @@ static struct tuner_params tuner_philips_cu1216l_params[] = { | |||
1337 | }, | 1337 | }, |
1338 | }; | 1338 | }; |
1339 | 1339 | ||
1340 | /* ---------------------- TUNER_SONY_BTF_PXN01Z ------------------------ */ | ||
1341 | |||
1342 | static struct tuner_range tuner_sony_btf_pxn01z_ranges[] = { | ||
1343 | { 16 * 137.25 /*MHz*/, 0x8e, 0x01, }, | ||
1344 | { 16 * 367.25 /*MHz*/, 0x8e, 0x02, }, | ||
1345 | { 16 * 999.99 , 0x8e, 0x04, }, | ||
1346 | }; | ||
1347 | |||
1348 | static struct tuner_params tuner_sony_btf_pxn01z_params[] = { | ||
1349 | { | ||
1350 | .type = TUNER_PARAM_TYPE_NTSC, | ||
1351 | .ranges = tuner_sony_btf_pxn01z_ranges, | ||
1352 | .count = ARRAY_SIZE(tuner_sony_btf_pxn01z_ranges), | ||
1353 | }, | ||
1354 | }; | ||
1355 | |||
1340 | /* --------------------------------------------------------------------- */ | 1356 | /* --------------------------------------------------------------------- */ |
1341 | 1357 | ||
1342 | struct tunertype tuners[] = { | 1358 | struct tunertype tuners[] = { |
@@ -1805,6 +1821,11 @@ struct tunertype tuners[] = { | |||
1805 | .name = "NXP TDA18271", | 1821 | .name = "NXP TDA18271", |
1806 | /* see tda18271-fe.c for details */ | 1822 | /* see tda18271-fe.c for details */ |
1807 | }, | 1823 | }, |
1824 | [TUNER_SONY_BTF_PXN01Z] = { | ||
1825 | .name = "Sony BTF-Pxn01Z", | ||
1826 | .params = tuner_sony_btf_pxn01z_params, | ||
1827 | .count = ARRAY_SIZE(tuner_sony_btf_pxn01z_params), | ||
1828 | }, | ||
1808 | }; | 1829 | }; |
1809 | EXPORT_SYMBOL(tuners); | 1830 | EXPORT_SYMBOL(tuners); |
1810 | 1831 | ||
diff --git a/drivers/media/common/tuners/tuner-xc2028.c b/drivers/media/common/tuners/tuner-xc2028.c index f270e605da83..be51c294b375 100644 --- a/drivers/media/common/tuners/tuner-xc2028.c +++ b/drivers/media/common/tuners/tuner-xc2028.c | |||
@@ -917,30 +917,68 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */, | |||
917 | * that xc2028 will be in a safe state. | 917 | * that xc2028 will be in a safe state. |
918 | * Maybe this might also be needed for DTV. | 918 | * Maybe this might also be needed for DTV. |
919 | */ | 919 | */ |
920 | if (new_mode == T_ANALOG_TV) | 920 | if (new_mode == T_ANALOG_TV) { |
921 | rc = send_seq(priv, {0x00, 0x00}); | 921 | rc = send_seq(priv, {0x00, 0x00}); |
922 | 922 | ||
923 | /* | 923 | /* Analog modes require offset = 0 */ |
924 | * Digital modes require an offset to adjust to the | 924 | } else { |
925 | * proper frequency. | 925 | /* |
926 | * Analog modes require offset = 0 | 926 | * Digital modes require an offset to adjust to the |
927 | */ | 927 | * proper frequency. The offset depends on what |
928 | if (new_mode == T_DIGITAL_TV) { | 928 | * firmware version is used. |
929 | /* Sets the offset according with firmware */ | 929 | */ |
930 | |||
931 | /* | ||
932 | * Adjust to the center frequency. This is calculated by the | ||
933 | * formula: offset = 1.25MHz - BW/2 | ||
934 | * For DTV 7/8, the firmware uses BW = 8000, so it needs a | ||
935 | * further adjustment to get the frequency center on VHF | ||
936 | */ | ||
930 | if (priv->cur_fw.type & DTV6) | 937 | if (priv->cur_fw.type & DTV6) |
931 | offset = 1750000; | 938 | offset = 1750000; |
932 | else if (priv->cur_fw.type & DTV7) | 939 | else if (priv->cur_fw.type & DTV7) |
933 | offset = 2250000; | 940 | offset = 2250000; |
934 | else /* DTV8 or DTV78 */ | 941 | else /* DTV8 or DTV78 */ |
935 | offset = 2750000; | 942 | offset = 2750000; |
943 | if ((priv->cur_fw.type & DTV78) && freq < 470000000) | ||
944 | offset -= 500000; | ||
936 | 945 | ||
937 | /* | 946 | /* |
938 | * We must adjust the offset by 500kHz when | 947 | * xc3028 additional "magic" |
939 | * tuning a 7MHz VHF channel with DTV78 firmware | 948 | * Depending on the firmware version, it needs some adjustments |
940 | * (used in Australia, Italy and Germany) | 949 | * to properly centralize the frequency. This seems to be |
950 | * needed to compensate the SCODE table adjustments made by | ||
951 | * newer firmwares | ||
941 | */ | 952 | */ |
942 | if ((priv->cur_fw.type & DTV78) && freq < 470000000) | 953 | |
943 | offset -= 500000; | 954 | #if 1 |
955 | /* | ||
956 | * The proper adjustment would be to do it at s-code table. | ||
957 | * However, this didn't work, as reported by | ||
958 | * Robert Lowery <rglowery@exemail.com.au> | ||
959 | */ | ||
960 | |||
961 | if (priv->cur_fw.type & DTV7) | ||
962 | offset += 500000; | ||
963 | |||
964 | #else | ||
965 | /* | ||
966 | * Still need tests for XC3028L (firmware 3.2 or upper) | ||
967 | * So, for now, let's just comment the per-firmware | ||
968 | * version of this change. Reports with xc3028l working | ||
969 | * with and without the lines bellow are welcome | ||
970 | */ | ||
971 | |||
972 | if (priv->firm_version < 0x0302) { | ||
973 | if (priv->cur_fw.type & DTV7) | ||
974 | offset += 500000; | ||
975 | } else { | ||
976 | if (priv->cur_fw.type & DTV7) | ||
977 | offset -= 300000; | ||
978 | else if (type != ATSC) /* DVB @6MHz, DTV 8 and DTV 7/8 */ | ||
979 | offset += 200000; | ||
980 | } | ||
981 | #endif | ||
944 | } | 982 | } |
945 | 983 | ||
946 | div = (freq - offset + DIV / 2) / DIV; | 984 | div = (freq - offset + DIV / 2) / DIV; |
@@ -1097,17 +1135,24 @@ static int xc2028_set_params(struct dvb_frontend *fe, | |||
1097 | 1135 | ||
1098 | /* All S-code tables need a 200kHz shift */ | 1136 | /* All S-code tables need a 200kHz shift */ |
1099 | if (priv->ctrl.demod) { | 1137 | if (priv->ctrl.demod) { |
1100 | demod = priv->ctrl.demod + 200; | 1138 | demod = priv->ctrl.demod; |
1139 | |||
1140 | /* | ||
1141 | * Newer firmwares require a 200 kHz offset only for ATSC | ||
1142 | */ | ||
1143 | if (type == ATSC || priv->firm_version < 0x0302) | ||
1144 | demod += 200; | ||
1101 | /* | 1145 | /* |
1102 | * The DTV7 S-code table needs a 700 kHz shift. | 1146 | * The DTV7 S-code table needs a 700 kHz shift. |
1103 | * Thanks to Terry Wu <terrywu2009@gmail.com> for reporting this | ||
1104 | * | 1147 | * |
1105 | * DTV7 is only used in Australia. Germany or Italy may also | 1148 | * DTV7 is only used in Australia. Germany or Italy may also |
1106 | * use this firmware after initialization, but a tune to a UHF | 1149 | * use this firmware after initialization, but a tune to a UHF |
1107 | * channel should then cause DTV78 to be used. | 1150 | * channel should then cause DTV78 to be used. |
1151 | * | ||
1152 | * Unfortunately, on real-field tests, the s-code offset | ||
1153 | * didn't work as expected, as reported by | ||
1154 | * Robert Lowery <rglowery@exemail.com.au> | ||
1108 | */ | 1155 | */ |
1109 | if (type & DTV7) | ||
1110 | demod += 500; | ||
1111 | } | 1156 | } |
1112 | 1157 | ||
1113 | return generic_set_freq(fe, p->frequency, | 1158 | return generic_set_freq(fe, p->frequency, |
diff --git a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig index cf8f65f309da..161ccfd471cb 100644 --- a/drivers/media/dvb/Kconfig +++ b/drivers/media/dvb/Kconfig | |||
@@ -76,6 +76,10 @@ comment "Supported Mantis Adapters" | |||
76 | depends on DVB_CORE && PCI && I2C | 76 | depends on DVB_CORE && PCI && I2C |
77 | source "drivers/media/dvb/mantis/Kconfig" | 77 | source "drivers/media/dvb/mantis/Kconfig" |
78 | 78 | ||
79 | comment "Supported nGene Adapters" | ||
80 | depends on DVB_CORE && PCI && I2C | ||
81 | source "drivers/media/dvb/ngene/Kconfig" | ||
82 | |||
79 | comment "Supported DVB Frontends" | 83 | comment "Supported DVB Frontends" |
80 | depends on DVB_CORE | 84 | depends on DVB_CORE |
81 | source "drivers/media/dvb/frontends/Kconfig" | 85 | source "drivers/media/dvb/frontends/Kconfig" |
diff --git a/drivers/media/dvb/Makefile b/drivers/media/dvb/Makefile index c12922c3659b..a1a08758a6f2 100644 --- a/drivers/media/dvb/Makefile +++ b/drivers/media/dvb/Makefile | |||
@@ -14,6 +14,7 @@ obj-y := dvb-core/ \ | |||
14 | siano/ \ | 14 | siano/ \ |
15 | dm1105/ \ | 15 | dm1105/ \ |
16 | pt1/ \ | 16 | pt1/ \ |
17 | mantis/ | 17 | mantis/ \ |
18 | ngene/ | ||
18 | 19 | ||
19 | obj-$(CONFIG_DVB_FIREDTV) += firewire/ | 20 | obj-$(CONFIG_DVB_FIREDTV) += firewire/ |
diff --git a/drivers/media/dvb/bt8xx/bt878.c b/drivers/media/dvb/bt8xx/bt878.c index a24c125331f0..99d62094f908 100644 --- a/drivers/media/dvb/bt8xx/bt878.c +++ b/drivers/media/dvb/bt8xx/bt878.c | |||
@@ -576,43 +576,30 @@ static struct pci_driver bt878_pci_driver = { | |||
576 | .remove = __devexit_p(bt878_remove), | 576 | .remove = __devexit_p(bt878_remove), |
577 | }; | 577 | }; |
578 | 578 | ||
579 | static int bt878_pci_driver_registered; | ||
580 | |||
581 | /*******************************/ | 579 | /*******************************/ |
582 | /* Module management functions */ | 580 | /* Module management functions */ |
583 | /*******************************/ | 581 | /*******************************/ |
584 | 582 | ||
585 | static int bt878_init_module(void) | 583 | static int __init bt878_init_module(void) |
586 | { | 584 | { |
587 | bt878_num = 0; | 585 | bt878_num = 0; |
588 | bt878_pci_driver_registered = 0; | ||
589 | 586 | ||
590 | printk(KERN_INFO "bt878: AUDIO driver version %d.%d.%d loaded\n", | 587 | printk(KERN_INFO "bt878: AUDIO driver version %d.%d.%d loaded\n", |
591 | (BT878_VERSION_CODE >> 16) & 0xff, | 588 | (BT878_VERSION_CODE >> 16) & 0xff, |
592 | (BT878_VERSION_CODE >> 8) & 0xff, | 589 | (BT878_VERSION_CODE >> 8) & 0xff, |
593 | BT878_VERSION_CODE & 0xff); | 590 | BT878_VERSION_CODE & 0xff); |
594 | /* | 591 | |
595 | bt878_check_chipset(); | ||
596 | */ | ||
597 | /* later we register inside of bt878_find_audio_dma() | ||
598 | * because we may want to ignore certain cards */ | ||
599 | bt878_pci_driver_registered = 1; | ||
600 | return pci_register_driver(&bt878_pci_driver); | 592 | return pci_register_driver(&bt878_pci_driver); |
601 | } | 593 | } |
602 | 594 | ||
603 | static void bt878_cleanup_module(void) | 595 | static void __exit bt878_cleanup_module(void) |
604 | { | 596 | { |
605 | if (bt878_pci_driver_registered) { | 597 | pci_unregister_driver(&bt878_pci_driver); |
606 | bt878_pci_driver_registered = 0; | ||
607 | pci_unregister_driver(&bt878_pci_driver); | ||
608 | } | ||
609 | return; | ||
610 | } | 598 | } |
611 | 599 | ||
612 | module_init(bt878_init_module); | 600 | module_init(bt878_init_module); |
613 | module_exit(bt878_cleanup_module); | 601 | module_exit(bt878_cleanup_module); |
614 | 602 | ||
615 | //MODULE_AUTHOR("XXX"); | ||
616 | MODULE_LICENSE("GPL"); | 603 | MODULE_LICENSE("GPL"); |
617 | 604 | ||
618 | /* | 605 | /* |
diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c index 91353a6faf1d..8b0cde38984d 100644 --- a/drivers/media/dvb/bt8xx/dst.c +++ b/drivers/media/dvb/bt8xx/dst.c | |||
@@ -1352,8 +1352,7 @@ static int dst_get_tuna(struct dst_state *state) | |||
1352 | return retval; | 1352 | return retval; |
1353 | } | 1353 | } |
1354 | if ((state->type_flags & DST_TYPE_HAS_VLF) && | 1354 | if ((state->type_flags & DST_TYPE_HAS_VLF) && |
1355 | !(state->dst_type == DST_TYPE_IS_CABLE) && | 1355 | !(state->dst_type == DST_TYPE_IS_ATSC)) { |
1356 | !(state->dst_type == DST_TYPE_IS_ATSC)) { | ||
1357 | 1356 | ||
1358 | if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[0], 9)) { | 1357 | if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[0], 9)) { |
1359 | dprintk(verbose, DST_INFO, 1, "checksum failure ? "); | 1358 | dprintk(verbose, DST_INFO, 1, "checksum failure ? "); |
@@ -1820,8 +1819,13 @@ static struct dvb_frontend_ops dst_dvbc_ops = { | |||
1820 | .frequency_max = 858000000, | 1819 | .frequency_max = 858000000, |
1821 | .symbol_rate_min = 1000000, | 1820 | .symbol_rate_min = 1000000, |
1822 | .symbol_rate_max = 45000000, | 1821 | .symbol_rate_max = 45000000, |
1823 | /* . symbol_rate_tolerance = ???,*/ | 1822 | .caps = FE_CAN_FEC_AUTO | |
1824 | .caps = FE_CAN_FEC_AUTO | FE_CAN_QAM_AUTO | 1823 | FE_CAN_QAM_AUTO | |
1824 | FE_CAN_QAM_16 | | ||
1825 | FE_CAN_QAM_32 | | ||
1826 | FE_CAN_QAM_64 | | ||
1827 | FE_CAN_QAM_128 | | ||
1828 | FE_CAN_QAM_256 | ||
1825 | }, | 1829 | }, |
1826 | 1830 | ||
1827 | .release = dst_release, | 1831 | .release = dst_release, |
diff --git a/drivers/media/dvb/dm1105/Kconfig b/drivers/media/dvb/dm1105/Kconfig index de3eeb0a8d6e..695239227cb7 100644 --- a/drivers/media/dvb/dm1105/Kconfig +++ b/drivers/media/dvb/dm1105/Kconfig | |||
@@ -8,6 +8,7 @@ config DVB_DM1105 | |||
8 | select DVB_STB6000 if !DVB_FE_CUSTOMISE | 8 | select DVB_STB6000 if !DVB_FE_CUSTOMISE |
9 | select DVB_CX24116 if !DVB_FE_CUSTOMISE | 9 | select DVB_CX24116 if !DVB_FE_CUSTOMISE |
10 | select DVB_SI21XX if !DVB_FE_CUSTOMISE | 10 | select DVB_SI21XX if !DVB_FE_CUSTOMISE |
11 | select DVB_DS3000 if !DVB_FE_CUSTOMISE | ||
11 | select VIDEO_IR | 12 | select VIDEO_IR |
12 | help | 13 | help |
13 | Support for cards based on the SDMC DM1105 PCI chip like | 14 | Support for cards based on the SDMC DM1105 PCI chip like |
diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c index f0f483ac8b89..383cca378b8c 100644 --- a/drivers/media/dvb/dm1105/dm1105.c +++ b/drivers/media/dvb/dm1105/dm1105.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include "si21xx.h" | 43 | #include "si21xx.h" |
44 | #include "cx24116.h" | 44 | #include "cx24116.h" |
45 | #include "z0194a.h" | 45 | #include "z0194a.h" |
46 | #include "ds3000.h" | ||
46 | 47 | ||
47 | #define UNSET (-1U) | 48 | #define UNSET (-1U) |
48 | 49 | ||
@@ -269,7 +270,7 @@ struct infrared { | |||
269 | u32 ir_command; | 270 | u32 ir_command; |
270 | }; | 271 | }; |
271 | 272 | ||
272 | struct dm1105dvb { | 273 | struct dm1105_dev { |
273 | /* pci */ | 274 | /* pci */ |
274 | struct pci_dev *pdev; | 275 | struct pci_dev *pdev; |
275 | u8 __iomem *io_mem; | 276 | u8 __iomem *io_mem; |
@@ -308,31 +309,47 @@ struct dm1105dvb { | |||
308 | spinlock_t lock; | 309 | spinlock_t lock; |
309 | }; | 310 | }; |
310 | 311 | ||
311 | #define dm_io_mem(reg) ((unsigned long)(&dm1105dvb->io_mem[reg])) | 312 | #define dm_io_mem(reg) ((unsigned long)(&dev->io_mem[reg])) |
313 | |||
314 | #define dm_readb(reg) inb(dm_io_mem(reg)) | ||
315 | #define dm_writeb(reg, value) outb((value), (dm_io_mem(reg))) | ||
316 | |||
317 | #define dm_readw(reg) inw(dm_io_mem(reg)) | ||
318 | #define dm_writew(reg, value) outw((value), (dm_io_mem(reg))) | ||
319 | |||
320 | #define dm_readl(reg) inl(dm_io_mem(reg)) | ||
321 | #define dm_writel(reg, value) outl((value), (dm_io_mem(reg))) | ||
322 | |||
323 | #define dm_andorl(reg, mask, value) \ | ||
324 | outl((inl(dm_io_mem(reg)) & ~(mask)) |\ | ||
325 | ((value) & (mask)), (dm_io_mem(reg))) | ||
326 | |||
327 | #define dm_setl(reg, bit) dm_andorl((reg), (bit), (bit)) | ||
328 | #define dm_clearl(reg, bit) dm_andorl((reg), (bit), 0) | ||
312 | 329 | ||
313 | static int dm1105_i2c_xfer(struct i2c_adapter *i2c_adap, | 330 | static int dm1105_i2c_xfer(struct i2c_adapter *i2c_adap, |
314 | struct i2c_msg *msgs, int num) | 331 | struct i2c_msg *msgs, int num) |
315 | { | 332 | { |
316 | struct dm1105dvb *dm1105dvb ; | 333 | struct dm1105_dev *dev ; |
317 | 334 | ||
318 | int addr, rc, i, j, k, len, byte, data; | 335 | int addr, rc, i, j, k, len, byte, data; |
319 | u8 status; | 336 | u8 status; |
320 | 337 | ||
321 | dm1105dvb = i2c_adap->algo_data; | 338 | dev = i2c_adap->algo_data; |
322 | for (i = 0; i < num; i++) { | 339 | for (i = 0; i < num; i++) { |
323 | outb(0x00, dm_io_mem(DM1105_I2CCTR)); | 340 | dm_writeb(DM1105_I2CCTR, 0x00); |
324 | if (msgs[i].flags & I2C_M_RD) { | 341 | if (msgs[i].flags & I2C_M_RD) { |
325 | /* read bytes */ | 342 | /* read bytes */ |
326 | addr = msgs[i].addr << 1; | 343 | addr = msgs[i].addr << 1; |
327 | addr |= 1; | 344 | addr |= 1; |
328 | outb(addr, dm_io_mem(DM1105_I2CDAT)); | 345 | dm_writeb(DM1105_I2CDAT, addr); |
329 | for (byte = 0; byte < msgs[i].len; byte++) | 346 | for (byte = 0; byte < msgs[i].len; byte++) |
330 | outb(0, dm_io_mem(DM1105_I2CDAT + byte + 1)); | 347 | dm_writeb(DM1105_I2CDAT + byte + 1, 0); |
331 | 348 | ||
332 | outb(0x81 + msgs[i].len, dm_io_mem(DM1105_I2CCTR)); | 349 | dm_writeb(DM1105_I2CCTR, 0x81 + msgs[i].len); |
333 | for (j = 0; j < 55; j++) { | 350 | for (j = 0; j < 55; j++) { |
334 | mdelay(10); | 351 | mdelay(10); |
335 | status = inb(dm_io_mem(DM1105_I2CSTS)); | 352 | status = dm_readb(DM1105_I2CSTS); |
336 | if ((status & 0xc0) == 0x40) | 353 | if ((status & 0xc0) == 0x40) |
337 | break; | 354 | break; |
338 | } | 355 | } |
@@ -340,56 +357,54 @@ static int dm1105_i2c_xfer(struct i2c_adapter *i2c_adap, | |||
340 | return -1; | 357 | return -1; |
341 | 358 | ||
342 | for (byte = 0; byte < msgs[i].len; byte++) { | 359 | for (byte = 0; byte < msgs[i].len; byte++) { |
343 | rc = inb(dm_io_mem(DM1105_I2CDAT + byte + 1)); | 360 | rc = dm_readb(DM1105_I2CDAT + byte + 1); |
344 | if (rc < 0) | 361 | if (rc < 0) |
345 | goto err; | 362 | goto err; |
346 | msgs[i].buf[byte] = rc; | 363 | msgs[i].buf[byte] = rc; |
347 | } | 364 | } |
348 | } else { | 365 | } else if ((msgs[i].buf[0] == 0xf7) && (msgs[i].addr == 0x55)) { |
349 | if ((msgs[i].buf[0] == 0xf7) && (msgs[i].addr == 0x55)) { | 366 | /* prepaired for cx24116 firmware */ |
350 | /* prepaired for cx24116 firmware */ | 367 | /* Write in small blocks */ |
351 | /* Write in small blocks */ | 368 | len = msgs[i].len - 1; |
352 | len = msgs[i].len - 1; | 369 | k = 1; |
353 | k = 1; | 370 | do { |
354 | do { | 371 | dm_writeb(DM1105_I2CDAT, msgs[i].addr << 1); |
355 | outb(msgs[i].addr << 1, dm_io_mem(DM1105_I2CDAT)); | 372 | dm_writeb(DM1105_I2CDAT + 1, 0xf7); |
356 | outb(0xf7, dm_io_mem(DM1105_I2CDAT + 1)); | 373 | for (byte = 0; byte < (len > 48 ? 48 : len); byte++) { |
357 | for (byte = 0; byte < (len > 48 ? 48 : len); byte++) { | 374 | data = msgs[i].buf[k + byte]; |
358 | data = msgs[i].buf[k+byte]; | 375 | dm_writeb(DM1105_I2CDAT + byte + 2, data); |
359 | outb(data, dm_io_mem(DM1105_I2CDAT + byte + 2)); | ||
360 | } | ||
361 | outb(0x82 + (len > 48 ? 48 : len), dm_io_mem(DM1105_I2CCTR)); | ||
362 | for (j = 0; j < 25; j++) { | ||
363 | mdelay(10); | ||
364 | status = inb(dm_io_mem(DM1105_I2CSTS)); | ||
365 | if ((status & 0xc0) == 0x40) | ||
366 | break; | ||
367 | } | ||
368 | |||
369 | if (j >= 25) | ||
370 | return -1; | ||
371 | |||
372 | k += 48; | ||
373 | len -= 48; | ||
374 | } while (len > 0); | ||
375 | } else { | ||
376 | /* write bytes */ | ||
377 | outb(msgs[i].addr<<1, dm_io_mem(DM1105_I2CDAT)); | ||
378 | for (byte = 0; byte < msgs[i].len; byte++) { | ||
379 | data = msgs[i].buf[byte]; | ||
380 | outb(data, dm_io_mem(DM1105_I2CDAT + byte + 1)); | ||
381 | } | 376 | } |
382 | outb(0x81 + msgs[i].len, dm_io_mem(DM1105_I2CCTR)); | 377 | dm_writeb(DM1105_I2CCTR, 0x82 + (len > 48 ? 48 : len)); |
383 | for (j = 0; j < 25; j++) { | 378 | for (j = 0; j < 25; j++) { |
384 | mdelay(10); | 379 | mdelay(10); |
385 | status = inb(dm_io_mem(DM1105_I2CSTS)); | 380 | status = dm_readb(DM1105_I2CSTS); |
386 | if ((status & 0xc0) == 0x40) | 381 | if ((status & 0xc0) == 0x40) |
387 | break; | 382 | break; |
388 | } | 383 | } |
389 | 384 | ||
390 | if (j >= 25) | 385 | if (j >= 25) |
391 | return -1; | 386 | return -1; |
387 | |||
388 | k += 48; | ||
389 | len -= 48; | ||
390 | } while (len > 0); | ||
391 | } else { | ||
392 | /* write bytes */ | ||
393 | dm_writeb(DM1105_I2CDAT, msgs[i].addr << 1); | ||
394 | for (byte = 0; byte < msgs[i].len; byte++) { | ||
395 | data = msgs[i].buf[byte]; | ||
396 | dm_writeb(DM1105_I2CDAT + byte + 1, data); | ||
392 | } | 397 | } |
398 | dm_writeb(DM1105_I2CCTR, 0x81 + msgs[i].len); | ||
399 | for (j = 0; j < 25; j++) { | ||
400 | mdelay(10); | ||
401 | status = dm_readb(DM1105_I2CSTS); | ||
402 | if ((status & 0xc0) == 0x40) | ||
403 | break; | ||
404 | } | ||
405 | |||
406 | if (j >= 25) | ||
407 | return -1; | ||
393 | } | 408 | } |
394 | } | 409 | } |
395 | return num; | 410 | return num; |
@@ -407,22 +422,22 @@ static struct i2c_algorithm dm1105_algo = { | |||
407 | .functionality = functionality, | 422 | .functionality = functionality, |
408 | }; | 423 | }; |
409 | 424 | ||
410 | static inline struct dm1105dvb *feed_to_dm1105dvb(struct dvb_demux_feed *feed) | 425 | static inline struct dm1105_dev *feed_to_dm1105_dev(struct dvb_demux_feed *feed) |
411 | { | 426 | { |
412 | return container_of(feed->demux, struct dm1105dvb, demux); | 427 | return container_of(feed->demux, struct dm1105_dev, demux); |
413 | } | 428 | } |
414 | 429 | ||
415 | static inline struct dm1105dvb *frontend_to_dm1105dvb(struct dvb_frontend *fe) | 430 | static inline struct dm1105_dev *frontend_to_dm1105_dev(struct dvb_frontend *fe) |
416 | { | 431 | { |
417 | return container_of(fe->dvb, struct dm1105dvb, dvb_adapter); | 432 | return container_of(fe->dvb, struct dm1105_dev, dvb_adapter); |
418 | } | 433 | } |
419 | 434 | ||
420 | static int dm1105dvb_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) | 435 | static int dm1105_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) |
421 | { | 436 | { |
422 | struct dm1105dvb *dm1105dvb = frontend_to_dm1105dvb(fe); | 437 | struct dm1105_dev *dev = frontend_to_dm1105_dev(fe); |
423 | u32 lnb_mask, lnb_13v, lnb_18v, lnb_off; | 438 | u32 lnb_mask, lnb_13v, lnb_18v, lnb_off; |
424 | 439 | ||
425 | switch (dm1105dvb->boardnr) { | 440 | switch (dev->boardnr) { |
426 | case DM1105_BOARD_AXESS_DM05: | 441 | case DM1105_BOARD_AXESS_DM05: |
427 | lnb_mask = DM05_LNB_MASK; | 442 | lnb_mask = DM05_LNB_MASK; |
428 | lnb_off = DM05_LNB_OFF; | 443 | lnb_off = DM05_LNB_OFF; |
@@ -438,62 +453,67 @@ static int dm1105dvb_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t volta | |||
438 | lnb_18v = DM1105_LNB_18V; | 453 | lnb_18v = DM1105_LNB_18V; |
439 | } | 454 | } |
440 | 455 | ||
441 | outl(lnb_mask, dm_io_mem(DM1105_GPIOCTR)); | 456 | dm_writel(DM1105_GPIOCTR, lnb_mask); |
442 | if (voltage == SEC_VOLTAGE_18) | 457 | if (voltage == SEC_VOLTAGE_18) |
443 | outl(lnb_18v , dm_io_mem(DM1105_GPIOVAL)); | 458 | dm_writel(DM1105_GPIOVAL, lnb_18v); |
444 | else if (voltage == SEC_VOLTAGE_13) | 459 | else if (voltage == SEC_VOLTAGE_13) |
445 | outl(lnb_13v, dm_io_mem(DM1105_GPIOVAL)); | 460 | dm_writel(DM1105_GPIOVAL, lnb_13v); |
446 | else | 461 | else |
447 | outl(lnb_off, dm_io_mem(DM1105_GPIOVAL)); | 462 | dm_writel(DM1105_GPIOVAL, lnb_off); |
448 | 463 | ||
449 | return 0; | 464 | return 0; |
450 | } | 465 | } |
451 | 466 | ||
452 | static void dm1105dvb_set_dma_addr(struct dm1105dvb *dm1105dvb) | 467 | static void dm1105_set_dma_addr(struct dm1105_dev *dev) |
453 | { | 468 | { |
454 | outl(cpu_to_le32(dm1105dvb->dma_addr), dm_io_mem(DM1105_STADR)); | 469 | dm_writel(DM1105_STADR, cpu_to_le32(dev->dma_addr)); |
455 | } | 470 | } |
456 | 471 | ||
457 | static int __devinit dm1105dvb_dma_map(struct dm1105dvb *dm1105dvb) | 472 | static int __devinit dm1105_dma_map(struct dm1105_dev *dev) |
458 | { | 473 | { |
459 | dm1105dvb->ts_buf = pci_alloc_consistent(dm1105dvb->pdev, 6*DM1105_DMA_BYTES, &dm1105dvb->dma_addr); | 474 | dev->ts_buf = pci_alloc_consistent(dev->pdev, |
475 | 6 * DM1105_DMA_BYTES, | ||
476 | &dev->dma_addr); | ||
460 | 477 | ||
461 | return !dm1105dvb->ts_buf; | 478 | return !dev->ts_buf; |
462 | } | 479 | } |
463 | 480 | ||
464 | static void dm1105dvb_dma_unmap(struct dm1105dvb *dm1105dvb) | 481 | static void dm1105_dma_unmap(struct dm1105_dev *dev) |
465 | { | 482 | { |
466 | pci_free_consistent(dm1105dvb->pdev, 6*DM1105_DMA_BYTES, dm1105dvb->ts_buf, dm1105dvb->dma_addr); | 483 | pci_free_consistent(dev->pdev, |
484 | 6 * DM1105_DMA_BYTES, | ||
485 | dev->ts_buf, | ||
486 | dev->dma_addr); | ||
467 | } | 487 | } |
468 | 488 | ||
469 | static void dm1105dvb_enable_irqs(struct dm1105dvb *dm1105dvb) | 489 | static void dm1105_enable_irqs(struct dm1105_dev *dev) |
470 | { | 490 | { |
471 | outb(INTMAK_ALLMASK, dm_io_mem(DM1105_INTMAK)); | 491 | dm_writeb(DM1105_INTMAK, INTMAK_ALLMASK); |
472 | outb(1, dm_io_mem(DM1105_CR)); | 492 | dm_writeb(DM1105_CR, 1); |
473 | } | 493 | } |
474 | 494 | ||
475 | static void dm1105dvb_disable_irqs(struct dm1105dvb *dm1105dvb) | 495 | static void dm1105_disable_irqs(struct dm1105_dev *dev) |
476 | { | 496 | { |
477 | outb(INTMAK_IRM, dm_io_mem(DM1105_INTMAK)); | 497 | dm_writeb(DM1105_INTMAK, INTMAK_IRM); |
478 | outb(0, dm_io_mem(DM1105_CR)); | 498 | dm_writeb(DM1105_CR, 0); |
479 | } | 499 | } |
480 | 500 | ||
481 | static int dm1105dvb_start_feed(struct dvb_demux_feed *f) | 501 | static int dm1105_start_feed(struct dvb_demux_feed *f) |
482 | { | 502 | { |
483 | struct dm1105dvb *dm1105dvb = feed_to_dm1105dvb(f); | 503 | struct dm1105_dev *dev = feed_to_dm1105_dev(f); |
484 | 504 | ||
485 | if (dm1105dvb->full_ts_users++ == 0) | 505 | if (dev->full_ts_users++ == 0) |
486 | dm1105dvb_enable_irqs(dm1105dvb); | 506 | dm1105_enable_irqs(dev); |
487 | 507 | ||
488 | return 0; | 508 | return 0; |
489 | } | 509 | } |
490 | 510 | ||
491 | static int dm1105dvb_stop_feed(struct dvb_demux_feed *f) | 511 | static int dm1105_stop_feed(struct dvb_demux_feed *f) |
492 | { | 512 | { |
493 | struct dm1105dvb *dm1105dvb = feed_to_dm1105dvb(f); | 513 | struct dm1105_dev *dev = feed_to_dm1105_dev(f); |
494 | 514 | ||
495 | if (--dm1105dvb->full_ts_users == 0) | 515 | if (--dev->full_ts_users == 0) |
496 | dm1105dvb_disable_irqs(dm1105dvb); | 516 | dm1105_disable_irqs(dev); |
497 | 517 | ||
498 | return 0; | 518 | return 0; |
499 | } | 519 | } |
@@ -517,68 +537,64 @@ static void dm1105_emit_key(struct work_struct *work) | |||
517 | /* work handler */ | 537 | /* work handler */ |
518 | static void dm1105_dmx_buffer(struct work_struct *work) | 538 | static void dm1105_dmx_buffer(struct work_struct *work) |
519 | { | 539 | { |
520 | struct dm1105dvb *dm1105dvb = | 540 | struct dm1105_dev *dev = container_of(work, struct dm1105_dev, work); |
521 | container_of(work, struct dm1105dvb, work); | ||
522 | unsigned int nbpackets; | 541 | unsigned int nbpackets; |
523 | u32 oldwrp = dm1105dvb->wrp; | 542 | u32 oldwrp = dev->wrp; |
524 | u32 nextwrp = dm1105dvb->nextwrp; | 543 | u32 nextwrp = dev->nextwrp; |
525 | 544 | ||
526 | if (!((dm1105dvb->ts_buf[oldwrp] == 0x47) && | 545 | if (!((dev->ts_buf[oldwrp] == 0x47) && |
527 | (dm1105dvb->ts_buf[oldwrp + 188] == 0x47) && | 546 | (dev->ts_buf[oldwrp + 188] == 0x47) && |
528 | (dm1105dvb->ts_buf[oldwrp + 188 * 2] == 0x47))) { | 547 | (dev->ts_buf[oldwrp + 188 * 2] == 0x47))) { |
529 | dm1105dvb->PacketErrorCount++; | 548 | dev->PacketErrorCount++; |
530 | /* bad packet found */ | 549 | /* bad packet found */ |
531 | if ((dm1105dvb->PacketErrorCount >= 2) && | 550 | if ((dev->PacketErrorCount >= 2) && |
532 | (dm1105dvb->dmarst == 0)) { | 551 | (dev->dmarst == 0)) { |
533 | outb(1, dm_io_mem(DM1105_RST)); | 552 | dm_writeb(DM1105_RST, 1); |
534 | dm1105dvb->wrp = 0; | 553 | dev->wrp = 0; |
535 | dm1105dvb->PacketErrorCount = 0; | 554 | dev->PacketErrorCount = 0; |
536 | dm1105dvb->dmarst = 0; | 555 | dev->dmarst = 0; |
537 | return; | 556 | return; |
538 | } | 557 | } |
539 | } | 558 | } |
540 | 559 | ||
541 | if (nextwrp < oldwrp) { | 560 | if (nextwrp < oldwrp) { |
542 | memcpy(dm1105dvb->ts_buf + dm1105dvb->buffer_size, | 561 | memcpy(dev->ts_buf + dev->buffer_size, dev->ts_buf, nextwrp); |
543 | dm1105dvb->ts_buf, nextwrp); | 562 | nbpackets = ((dev->buffer_size - oldwrp) + nextwrp) / 188; |
544 | nbpackets = ((dm1105dvb->buffer_size - oldwrp) + nextwrp) / 188; | ||
545 | } else | 563 | } else |
546 | nbpackets = (nextwrp - oldwrp) / 188; | 564 | nbpackets = (nextwrp - oldwrp) / 188; |
547 | 565 | ||
548 | dm1105dvb->wrp = nextwrp; | 566 | dev->wrp = nextwrp; |
549 | dvb_dmx_swfilter_packets(&dm1105dvb->demux, | 567 | dvb_dmx_swfilter_packets(&dev->demux, &dev->ts_buf[oldwrp], nbpackets); |
550 | &dm1105dvb->ts_buf[oldwrp], nbpackets); | ||
551 | } | 568 | } |
552 | 569 | ||
553 | static irqreturn_t dm1105dvb_irq(int irq, void *dev_id) | 570 | static irqreturn_t dm1105_irq(int irq, void *dev_id) |
554 | { | 571 | { |
555 | struct dm1105dvb *dm1105dvb = dev_id; | 572 | struct dm1105_dev *dev = dev_id; |
556 | 573 | ||
557 | /* Read-Write INSTS Ack's Interrupt for DM1105 chip 16.03.2008 */ | 574 | /* Read-Write INSTS Ack's Interrupt for DM1105 chip 16.03.2008 */ |
558 | unsigned int intsts = inb(dm_io_mem(DM1105_INTSTS)); | 575 | unsigned int intsts = dm_readb(DM1105_INTSTS); |
559 | outb(intsts, dm_io_mem(DM1105_INTSTS)); | 576 | dm_writeb(DM1105_INTSTS, intsts); |
560 | 577 | ||
561 | switch (intsts) { | 578 | switch (intsts) { |
562 | case INTSTS_TSIRQ: | 579 | case INTSTS_TSIRQ: |
563 | case (INTSTS_TSIRQ | INTSTS_IR): | 580 | case (INTSTS_TSIRQ | INTSTS_IR): |
564 | dm1105dvb->nextwrp = inl(dm_io_mem(DM1105_WRP)) - | 581 | dev->nextwrp = dm_readl(DM1105_WRP) - dm_readl(DM1105_STADR); |
565 | inl(dm_io_mem(DM1105_STADR)); | 582 | queue_work(dev->wq, &dev->work); |
566 | queue_work(dm1105dvb->wq, &dm1105dvb->work); | ||
567 | break; | 583 | break; |
568 | case INTSTS_IR: | 584 | case INTSTS_IR: |
569 | dm1105dvb->ir.ir_command = inl(dm_io_mem(DM1105_IRCODE)); | 585 | dev->ir.ir_command = dm_readl(DM1105_IRCODE); |
570 | schedule_work(&dm1105dvb->ir.work); | 586 | schedule_work(&dev->ir.work); |
571 | break; | 587 | break; |
572 | } | 588 | } |
573 | 589 | ||
574 | return IRQ_HANDLED; | 590 | return IRQ_HANDLED; |
575 | } | 591 | } |
576 | 592 | ||
577 | int __devinit dm1105_ir_init(struct dm1105dvb *dm1105) | 593 | int __devinit dm1105_ir_init(struct dm1105_dev *dm1105) |
578 | { | 594 | { |
579 | struct input_dev *input_dev; | 595 | struct input_dev *input_dev; |
580 | struct ir_scancode_table *ir_codes = &ir_codes_dm1105_nec_table; | 596 | struct ir_scancode_table *ir_codes = &ir_codes_dm1105_nec_table; |
581 | int ir_type = IR_TYPE_OTHER; | 597 | u64 ir_type = IR_TYPE_OTHER; |
582 | int err = -ENOMEM; | 598 | int err = -ENOMEM; |
583 | 599 | ||
584 | input_dev = input_allocate_device(); | 600 | input_dev = input_allocate_device(); |
@@ -611,51 +627,51 @@ int __devinit dm1105_ir_init(struct dm1105dvb *dm1105) | |||
611 | 627 | ||
612 | INIT_WORK(&dm1105->ir.work, dm1105_emit_key); | 628 | INIT_WORK(&dm1105->ir.work, dm1105_emit_key); |
613 | 629 | ||
614 | err = ir_input_register(input_dev, ir_codes); | 630 | err = ir_input_register(input_dev, ir_codes, NULL); |
615 | 631 | ||
616 | return err; | 632 | return err; |
617 | } | 633 | } |
618 | 634 | ||
619 | void __devexit dm1105_ir_exit(struct dm1105dvb *dm1105) | 635 | void __devexit dm1105_ir_exit(struct dm1105_dev *dm1105) |
620 | { | 636 | { |
621 | ir_input_unregister(dm1105->ir.input_dev); | 637 | ir_input_unregister(dm1105->ir.input_dev); |
622 | } | 638 | } |
623 | 639 | ||
624 | static int __devinit dm1105dvb_hw_init(struct dm1105dvb *dm1105dvb) | 640 | static int __devinit dm1105_hw_init(struct dm1105_dev *dev) |
625 | { | 641 | { |
626 | dm1105dvb_disable_irqs(dm1105dvb); | 642 | dm1105_disable_irqs(dev); |
627 | 643 | ||
628 | outb(0, dm_io_mem(DM1105_HOST_CTR)); | 644 | dm_writeb(DM1105_HOST_CTR, 0); |
629 | 645 | ||
630 | /*DATALEN 188,*/ | 646 | /*DATALEN 188,*/ |
631 | outb(188, dm_io_mem(DM1105_DTALENTH)); | 647 | dm_writeb(DM1105_DTALENTH, 188); |
632 | /*TS_STRT TS_VALP MSBFIRST TS_MODE ALPAS TSPES*/ | 648 | /*TS_STRT TS_VALP MSBFIRST TS_MODE ALPAS TSPES*/ |
633 | outw(0xc10a, dm_io_mem(DM1105_TSCTR)); | 649 | dm_writew(DM1105_TSCTR, 0xc10a); |
634 | 650 | ||
635 | /* map DMA and set address */ | 651 | /* map DMA and set address */ |
636 | dm1105dvb_dma_map(dm1105dvb); | 652 | dm1105_dma_map(dev); |
637 | dm1105dvb_set_dma_addr(dm1105dvb); | 653 | dm1105_set_dma_addr(dev); |
638 | /* big buffer */ | 654 | /* big buffer */ |
639 | outl(5*DM1105_DMA_BYTES, dm_io_mem(DM1105_RLEN)); | 655 | dm_writel(DM1105_RLEN, 5 * DM1105_DMA_BYTES); |
640 | outb(47, dm_io_mem(DM1105_INTCNT)); | 656 | dm_writeb(DM1105_INTCNT, 47); |
641 | 657 | ||
642 | /* IR NEC mode enable */ | 658 | /* IR NEC mode enable */ |
643 | outb((DM1105_IR_EN | DM1105_SYS_CHK), dm_io_mem(DM1105_IRCTR)); | 659 | dm_writeb(DM1105_IRCTR, (DM1105_IR_EN | DM1105_SYS_CHK)); |
644 | outb(0, dm_io_mem(DM1105_IRMODE)); | 660 | dm_writeb(DM1105_IRMODE, 0); |
645 | outw(0, dm_io_mem(DM1105_SYSTEMCODE)); | 661 | dm_writew(DM1105_SYSTEMCODE, 0); |
646 | 662 | ||
647 | return 0; | 663 | return 0; |
648 | } | 664 | } |
649 | 665 | ||
650 | static void dm1105dvb_hw_exit(struct dm1105dvb *dm1105dvb) | 666 | static void dm1105_hw_exit(struct dm1105_dev *dev) |
651 | { | 667 | { |
652 | dm1105dvb_disable_irqs(dm1105dvb); | 668 | dm1105_disable_irqs(dev); |
653 | 669 | ||
654 | /* IR disable */ | 670 | /* IR disable */ |
655 | outb(0, dm_io_mem(DM1105_IRCTR)); | 671 | dm_writeb(DM1105_IRCTR, 0); |
656 | outb(INTMAK_NONEMASK, dm_io_mem(DM1105_INTMAK)); | 672 | dm_writeb(DM1105_INTMAK, INTMAK_NONEMASK); |
657 | 673 | ||
658 | dm1105dvb_dma_unmap(dm1105dvb); | 674 | dm1105_dma_unmap(dev); |
659 | } | 675 | } |
660 | 676 | ||
661 | static struct stv0299_config sharp_z0194a_config = { | 677 | static struct stv0299_config sharp_z0194a_config = { |
@@ -685,70 +701,79 @@ static struct cx24116_config serit_sp2633_config = { | |||
685 | .demod_address = 0x55, | 701 | .demod_address = 0x55, |
686 | }; | 702 | }; |
687 | 703 | ||
688 | static int __devinit frontend_init(struct dm1105dvb *dm1105dvb) | 704 | static struct ds3000_config dvbworld_ds3000_config = { |
705 | .demod_address = 0x68, | ||
706 | }; | ||
707 | |||
708 | static int __devinit frontend_init(struct dm1105_dev *dev) | ||
689 | { | 709 | { |
690 | int ret; | 710 | int ret; |
691 | 711 | ||
692 | switch (dm1105dvb->boardnr) { | 712 | switch (dev->boardnr) { |
693 | case DM1105_BOARD_DVBWORLD_2004: | 713 | case DM1105_BOARD_DVBWORLD_2004: |
694 | dm1105dvb->fe = dvb_attach( | 714 | dev->fe = dvb_attach( |
695 | cx24116_attach, &serit_sp2633_config, | 715 | cx24116_attach, &serit_sp2633_config, |
696 | &dm1105dvb->i2c_adap); | 716 | &dev->i2c_adap); |
697 | if (dm1105dvb->fe) | 717 | if (dev->fe) { |
698 | dm1105dvb->fe->ops.set_voltage = dm1105dvb_set_voltage; | 718 | dev->fe->ops.set_voltage = dm1105_set_voltage; |
719 | break; | ||
720 | } | ||
721 | |||
722 | dev->fe = dvb_attach( | ||
723 | ds3000_attach, &dvbworld_ds3000_config, | ||
724 | &dev->i2c_adap); | ||
725 | if (dev->fe) | ||
726 | dev->fe->ops.set_voltage = dm1105_set_voltage; | ||
699 | 727 | ||
700 | break; | 728 | break; |
701 | case DM1105_BOARD_DVBWORLD_2002: | 729 | case DM1105_BOARD_DVBWORLD_2002: |
702 | case DM1105_BOARD_AXESS_DM05: | 730 | case DM1105_BOARD_AXESS_DM05: |
703 | default: | 731 | default: |
704 | dm1105dvb->fe = dvb_attach( | 732 | dev->fe = dvb_attach( |
705 | stv0299_attach, &sharp_z0194a_config, | 733 | stv0299_attach, &sharp_z0194a_config, |
706 | &dm1105dvb->i2c_adap); | 734 | &dev->i2c_adap); |
707 | if (dm1105dvb->fe) { | 735 | if (dev->fe) { |
708 | dm1105dvb->fe->ops.set_voltage = | 736 | dev->fe->ops.set_voltage = dm1105_set_voltage; |
709 | dm1105dvb_set_voltage; | 737 | dvb_attach(dvb_pll_attach, dev->fe, 0x60, |
710 | dvb_attach(dvb_pll_attach, dm1105dvb->fe, 0x60, | 738 | &dev->i2c_adap, DVB_PLL_OPERA1); |
711 | &dm1105dvb->i2c_adap, DVB_PLL_OPERA1); | ||
712 | break; | 739 | break; |
713 | } | 740 | } |
714 | 741 | ||
715 | dm1105dvb->fe = dvb_attach( | 742 | dev->fe = dvb_attach( |
716 | stv0288_attach, &earda_config, | 743 | stv0288_attach, &earda_config, |
717 | &dm1105dvb->i2c_adap); | 744 | &dev->i2c_adap); |
718 | if (dm1105dvb->fe) { | 745 | if (dev->fe) { |
719 | dm1105dvb->fe->ops.set_voltage = | 746 | dev->fe->ops.set_voltage = dm1105_set_voltage; |
720 | dm1105dvb_set_voltage; | 747 | dvb_attach(stb6000_attach, dev->fe, 0x61, |
721 | dvb_attach(stb6000_attach, dm1105dvb->fe, 0x61, | 748 | &dev->i2c_adap); |
722 | &dm1105dvb->i2c_adap); | ||
723 | break; | 749 | break; |
724 | } | 750 | } |
725 | 751 | ||
726 | dm1105dvb->fe = dvb_attach( | 752 | dev->fe = dvb_attach( |
727 | si21xx_attach, &serit_config, | 753 | si21xx_attach, &serit_config, |
728 | &dm1105dvb->i2c_adap); | 754 | &dev->i2c_adap); |
729 | if (dm1105dvb->fe) | 755 | if (dev->fe) |
730 | dm1105dvb->fe->ops.set_voltage = | 756 | dev->fe->ops.set_voltage = dm1105_set_voltage; |
731 | dm1105dvb_set_voltage; | ||
732 | 757 | ||
733 | } | 758 | } |
734 | 759 | ||
735 | if (!dm1105dvb->fe) { | 760 | if (!dev->fe) { |
736 | dev_err(&dm1105dvb->pdev->dev, "could not attach frontend\n"); | 761 | dev_err(&dev->pdev->dev, "could not attach frontend\n"); |
737 | return -ENODEV; | 762 | return -ENODEV; |
738 | } | 763 | } |
739 | 764 | ||
740 | ret = dvb_register_frontend(&dm1105dvb->dvb_adapter, dm1105dvb->fe); | 765 | ret = dvb_register_frontend(&dev->dvb_adapter, dev->fe); |
741 | if (ret < 0) { | 766 | if (ret < 0) { |
742 | if (dm1105dvb->fe->ops.release) | 767 | if (dev->fe->ops.release) |
743 | dm1105dvb->fe->ops.release(dm1105dvb->fe); | 768 | dev->fe->ops.release(dev->fe); |
744 | dm1105dvb->fe = NULL; | 769 | dev->fe = NULL; |
745 | return ret; | 770 | return ret; |
746 | } | 771 | } |
747 | 772 | ||
748 | return 0; | 773 | return 0; |
749 | } | 774 | } |
750 | 775 | ||
751 | static void __devinit dm1105dvb_read_mac(struct dm1105dvb *dm1105dvb, u8 *mac) | 776 | static void __devinit dm1105_read_mac(struct dm1105_dev *dev, u8 *mac) |
752 | { | 777 | { |
753 | static u8 command[1] = { 0x28 }; | 778 | static u8 command[1] = { 0x28 }; |
754 | 779 | ||
@@ -766,47 +791,47 @@ static void __devinit dm1105dvb_read_mac(struct dm1105dvb *dm1105dvb, u8 *mac) | |||
766 | }, | 791 | }, |
767 | }; | 792 | }; |
768 | 793 | ||
769 | dm1105_i2c_xfer(&dm1105dvb->i2c_adap, msg , 2); | 794 | dm1105_i2c_xfer(&dev->i2c_adap, msg , 2); |
770 | dev_info(&dm1105dvb->pdev->dev, "MAC %pM\n", mac); | 795 | dev_info(&dev->pdev->dev, "MAC %pM\n", mac); |
771 | } | 796 | } |
772 | 797 | ||
773 | static int __devinit dm1105_probe(struct pci_dev *pdev, | 798 | static int __devinit dm1105_probe(struct pci_dev *pdev, |
774 | const struct pci_device_id *ent) | 799 | const struct pci_device_id *ent) |
775 | { | 800 | { |
776 | struct dm1105dvb *dm1105dvb; | 801 | struct dm1105_dev *dev; |
777 | struct dvb_adapter *dvb_adapter; | 802 | struct dvb_adapter *dvb_adapter; |
778 | struct dvb_demux *dvbdemux; | 803 | struct dvb_demux *dvbdemux; |
779 | struct dmx_demux *dmx; | 804 | struct dmx_demux *dmx; |
780 | int ret = -ENOMEM; | 805 | int ret = -ENOMEM; |
781 | int i; | 806 | int i; |
782 | 807 | ||
783 | dm1105dvb = kzalloc(sizeof(struct dm1105dvb), GFP_KERNEL); | 808 | dev = kzalloc(sizeof(struct dm1105_dev), GFP_KERNEL); |
784 | if (!dm1105dvb) | 809 | if (!dev) |
785 | return -ENOMEM; | 810 | return -ENOMEM; |
786 | 811 | ||
787 | /* board config */ | 812 | /* board config */ |
788 | dm1105dvb->nr = dm1105_devcount; | 813 | dev->nr = dm1105_devcount; |
789 | dm1105dvb->boardnr = UNSET; | 814 | dev->boardnr = UNSET; |
790 | if (card[dm1105dvb->nr] < ARRAY_SIZE(dm1105_boards)) | 815 | if (card[dev->nr] < ARRAY_SIZE(dm1105_boards)) |
791 | dm1105dvb->boardnr = card[dm1105dvb->nr]; | 816 | dev->boardnr = card[dev->nr]; |
792 | for (i = 0; UNSET == dm1105dvb->boardnr && | 817 | for (i = 0; UNSET == dev->boardnr && |
793 | i < ARRAY_SIZE(dm1105_subids); i++) | 818 | i < ARRAY_SIZE(dm1105_subids); i++) |
794 | if (pdev->subsystem_vendor == | 819 | if (pdev->subsystem_vendor == |
795 | dm1105_subids[i].subvendor && | 820 | dm1105_subids[i].subvendor && |
796 | pdev->subsystem_device == | 821 | pdev->subsystem_device == |
797 | dm1105_subids[i].subdevice) | 822 | dm1105_subids[i].subdevice) |
798 | dm1105dvb->boardnr = dm1105_subids[i].card; | 823 | dev->boardnr = dm1105_subids[i].card; |
799 | 824 | ||
800 | if (UNSET == dm1105dvb->boardnr) { | 825 | if (UNSET == dev->boardnr) { |
801 | dm1105dvb->boardnr = DM1105_BOARD_UNKNOWN; | 826 | dev->boardnr = DM1105_BOARD_UNKNOWN; |
802 | dm1105_card_list(pdev); | 827 | dm1105_card_list(pdev); |
803 | } | 828 | } |
804 | 829 | ||
805 | dm1105_devcount++; | 830 | dm1105_devcount++; |
806 | dm1105dvb->pdev = pdev; | 831 | dev->pdev = pdev; |
807 | dm1105dvb->buffer_size = 5 * DM1105_DMA_BYTES; | 832 | dev->buffer_size = 5 * DM1105_DMA_BYTES; |
808 | dm1105dvb->PacketErrorCount = 0; | 833 | dev->PacketErrorCount = 0; |
809 | dm1105dvb->dmarst = 0; | 834 | dev->dmarst = 0; |
810 | 835 | ||
811 | ret = pci_enable_device(pdev); | 836 | ret = pci_enable_device(pdev); |
812 | if (ret < 0) | 837 | if (ret < 0) |
@@ -822,47 +847,47 @@ static int __devinit dm1105_probe(struct pci_dev *pdev, | |||
822 | if (ret < 0) | 847 | if (ret < 0) |
823 | goto err_pci_disable_device; | 848 | goto err_pci_disable_device; |
824 | 849 | ||
825 | dm1105dvb->io_mem = pci_iomap(pdev, 0, pci_resource_len(pdev, 0)); | 850 | dev->io_mem = pci_iomap(pdev, 0, pci_resource_len(pdev, 0)); |
826 | if (!dm1105dvb->io_mem) { | 851 | if (!dev->io_mem) { |
827 | ret = -EIO; | 852 | ret = -EIO; |
828 | goto err_pci_release_regions; | 853 | goto err_pci_release_regions; |
829 | } | 854 | } |
830 | 855 | ||
831 | spin_lock_init(&dm1105dvb->lock); | 856 | spin_lock_init(&dev->lock); |
832 | pci_set_drvdata(pdev, dm1105dvb); | 857 | pci_set_drvdata(pdev, dev); |
833 | 858 | ||
834 | ret = dm1105dvb_hw_init(dm1105dvb); | 859 | ret = dm1105_hw_init(dev); |
835 | if (ret < 0) | 860 | if (ret < 0) |
836 | goto err_pci_iounmap; | 861 | goto err_pci_iounmap; |
837 | 862 | ||
838 | /* i2c */ | 863 | /* i2c */ |
839 | i2c_set_adapdata(&dm1105dvb->i2c_adap, dm1105dvb); | 864 | i2c_set_adapdata(&dev->i2c_adap, dev); |
840 | strcpy(dm1105dvb->i2c_adap.name, DRIVER_NAME); | 865 | strcpy(dev->i2c_adap.name, DRIVER_NAME); |
841 | dm1105dvb->i2c_adap.owner = THIS_MODULE; | 866 | dev->i2c_adap.owner = THIS_MODULE; |
842 | dm1105dvb->i2c_adap.class = I2C_CLASS_TV_DIGITAL; | 867 | dev->i2c_adap.class = I2C_CLASS_TV_DIGITAL; |
843 | dm1105dvb->i2c_adap.dev.parent = &pdev->dev; | 868 | dev->i2c_adap.dev.parent = &pdev->dev; |
844 | dm1105dvb->i2c_adap.algo = &dm1105_algo; | 869 | dev->i2c_adap.algo = &dm1105_algo; |
845 | dm1105dvb->i2c_adap.algo_data = dm1105dvb; | 870 | dev->i2c_adap.algo_data = dev; |
846 | ret = i2c_add_adapter(&dm1105dvb->i2c_adap); | 871 | ret = i2c_add_adapter(&dev->i2c_adap); |
847 | 872 | ||
848 | if (ret < 0) | 873 | if (ret < 0) |
849 | goto err_dm1105dvb_hw_exit; | 874 | goto err_dm1105_hw_exit; |
850 | 875 | ||
851 | /* dvb */ | 876 | /* dvb */ |
852 | ret = dvb_register_adapter(&dm1105dvb->dvb_adapter, DRIVER_NAME, | 877 | ret = dvb_register_adapter(&dev->dvb_adapter, DRIVER_NAME, |
853 | THIS_MODULE, &pdev->dev, adapter_nr); | 878 | THIS_MODULE, &pdev->dev, adapter_nr); |
854 | if (ret < 0) | 879 | if (ret < 0) |
855 | goto err_i2c_del_adapter; | 880 | goto err_i2c_del_adapter; |
856 | 881 | ||
857 | dvb_adapter = &dm1105dvb->dvb_adapter; | 882 | dvb_adapter = &dev->dvb_adapter; |
858 | 883 | ||
859 | dm1105dvb_read_mac(dm1105dvb, dvb_adapter->proposed_mac); | 884 | dm1105_read_mac(dev, dvb_adapter->proposed_mac); |
860 | 885 | ||
861 | dvbdemux = &dm1105dvb->demux; | 886 | dvbdemux = &dev->demux; |
862 | dvbdemux->filternum = 256; | 887 | dvbdemux->filternum = 256; |
863 | dvbdemux->feednum = 256; | 888 | dvbdemux->feednum = 256; |
864 | dvbdemux->start_feed = dm1105dvb_start_feed; | 889 | dvbdemux->start_feed = dm1105_start_feed; |
865 | dvbdemux->stop_feed = dm1105dvb_stop_feed; | 890 | dvbdemux->stop_feed = dm1105_stop_feed; |
866 | dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | | 891 | dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | |
867 | DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING); | 892 | DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING); |
868 | ret = dvb_dmx_init(dvbdemux); | 893 | ret = dvb_dmx_init(dvbdemux); |
@@ -870,113 +895,113 @@ static int __devinit dm1105_probe(struct pci_dev *pdev, | |||
870 | goto err_dvb_unregister_adapter; | 895 | goto err_dvb_unregister_adapter; |
871 | 896 | ||
872 | dmx = &dvbdemux->dmx; | 897 | dmx = &dvbdemux->dmx; |
873 | dm1105dvb->dmxdev.filternum = 256; | 898 | dev->dmxdev.filternum = 256; |
874 | dm1105dvb->dmxdev.demux = dmx; | 899 | dev->dmxdev.demux = dmx; |
875 | dm1105dvb->dmxdev.capabilities = 0; | 900 | dev->dmxdev.capabilities = 0; |
876 | 901 | ||
877 | ret = dvb_dmxdev_init(&dm1105dvb->dmxdev, dvb_adapter); | 902 | ret = dvb_dmxdev_init(&dev->dmxdev, dvb_adapter); |
878 | if (ret < 0) | 903 | if (ret < 0) |
879 | goto err_dvb_dmx_release; | 904 | goto err_dvb_dmx_release; |
880 | 905 | ||
881 | dm1105dvb->hw_frontend.source = DMX_FRONTEND_0; | 906 | dev->hw_frontend.source = DMX_FRONTEND_0; |
882 | 907 | ||
883 | ret = dmx->add_frontend(dmx, &dm1105dvb->hw_frontend); | 908 | ret = dmx->add_frontend(dmx, &dev->hw_frontend); |
884 | if (ret < 0) | 909 | if (ret < 0) |
885 | goto err_dvb_dmxdev_release; | 910 | goto err_dvb_dmxdev_release; |
886 | 911 | ||
887 | dm1105dvb->mem_frontend.source = DMX_MEMORY_FE; | 912 | dev->mem_frontend.source = DMX_MEMORY_FE; |
888 | 913 | ||
889 | ret = dmx->add_frontend(dmx, &dm1105dvb->mem_frontend); | 914 | ret = dmx->add_frontend(dmx, &dev->mem_frontend); |
890 | if (ret < 0) | 915 | if (ret < 0) |
891 | goto err_remove_hw_frontend; | 916 | goto err_remove_hw_frontend; |
892 | 917 | ||
893 | ret = dmx->connect_frontend(dmx, &dm1105dvb->hw_frontend); | 918 | ret = dmx->connect_frontend(dmx, &dev->hw_frontend); |
894 | if (ret < 0) | 919 | if (ret < 0) |
895 | goto err_remove_mem_frontend; | 920 | goto err_remove_mem_frontend; |
896 | 921 | ||
897 | ret = frontend_init(dm1105dvb); | 922 | ret = frontend_init(dev); |
898 | if (ret < 0) | 923 | if (ret < 0) |
899 | goto err_disconnect_frontend; | 924 | goto err_disconnect_frontend; |
900 | 925 | ||
901 | dvb_net_init(dvb_adapter, &dm1105dvb->dvbnet, dmx); | 926 | dvb_net_init(dvb_adapter, &dev->dvbnet, dmx); |
902 | dm1105_ir_init(dm1105dvb); | 927 | dm1105_ir_init(dev); |
903 | 928 | ||
904 | INIT_WORK(&dm1105dvb->work, dm1105_dmx_buffer); | 929 | INIT_WORK(&dev->work, dm1105_dmx_buffer); |
905 | sprintf(dm1105dvb->wqn, "%s/%d", dvb_adapter->name, dvb_adapter->num); | 930 | sprintf(dev->wqn, "%s/%d", dvb_adapter->name, dvb_adapter->num); |
906 | dm1105dvb->wq = create_singlethread_workqueue(dm1105dvb->wqn); | 931 | dev->wq = create_singlethread_workqueue(dev->wqn); |
907 | if (!dm1105dvb->wq) | 932 | if (!dev->wq) |
908 | goto err_dvb_net; | 933 | goto err_dvb_net; |
909 | 934 | ||
910 | ret = request_irq(pdev->irq, dm1105dvb_irq, IRQF_SHARED, | 935 | ret = request_irq(pdev->irq, dm1105_irq, IRQF_SHARED, |
911 | DRIVER_NAME, dm1105dvb); | 936 | DRIVER_NAME, dev); |
912 | if (ret < 0) | 937 | if (ret < 0) |
913 | goto err_workqueue; | 938 | goto err_workqueue; |
914 | 939 | ||
915 | return 0; | 940 | return 0; |
916 | 941 | ||
917 | err_workqueue: | 942 | err_workqueue: |
918 | destroy_workqueue(dm1105dvb->wq); | 943 | destroy_workqueue(dev->wq); |
919 | err_dvb_net: | 944 | err_dvb_net: |
920 | dvb_net_release(&dm1105dvb->dvbnet); | 945 | dvb_net_release(&dev->dvbnet); |
921 | err_disconnect_frontend: | 946 | err_disconnect_frontend: |
922 | dmx->disconnect_frontend(dmx); | 947 | dmx->disconnect_frontend(dmx); |
923 | err_remove_mem_frontend: | 948 | err_remove_mem_frontend: |
924 | dmx->remove_frontend(dmx, &dm1105dvb->mem_frontend); | 949 | dmx->remove_frontend(dmx, &dev->mem_frontend); |
925 | err_remove_hw_frontend: | 950 | err_remove_hw_frontend: |
926 | dmx->remove_frontend(dmx, &dm1105dvb->hw_frontend); | 951 | dmx->remove_frontend(dmx, &dev->hw_frontend); |
927 | err_dvb_dmxdev_release: | 952 | err_dvb_dmxdev_release: |
928 | dvb_dmxdev_release(&dm1105dvb->dmxdev); | 953 | dvb_dmxdev_release(&dev->dmxdev); |
929 | err_dvb_dmx_release: | 954 | err_dvb_dmx_release: |
930 | dvb_dmx_release(dvbdemux); | 955 | dvb_dmx_release(dvbdemux); |
931 | err_dvb_unregister_adapter: | 956 | err_dvb_unregister_adapter: |
932 | dvb_unregister_adapter(dvb_adapter); | 957 | dvb_unregister_adapter(dvb_adapter); |
933 | err_i2c_del_adapter: | 958 | err_i2c_del_adapter: |
934 | i2c_del_adapter(&dm1105dvb->i2c_adap); | 959 | i2c_del_adapter(&dev->i2c_adap); |
935 | err_dm1105dvb_hw_exit: | 960 | err_dm1105_hw_exit: |
936 | dm1105dvb_hw_exit(dm1105dvb); | 961 | dm1105_hw_exit(dev); |
937 | err_pci_iounmap: | 962 | err_pci_iounmap: |
938 | pci_iounmap(pdev, dm1105dvb->io_mem); | 963 | pci_iounmap(pdev, dev->io_mem); |
939 | err_pci_release_regions: | 964 | err_pci_release_regions: |
940 | pci_release_regions(pdev); | 965 | pci_release_regions(pdev); |
941 | err_pci_disable_device: | 966 | err_pci_disable_device: |
942 | pci_disable_device(pdev); | 967 | pci_disable_device(pdev); |
943 | err_kfree: | 968 | err_kfree: |
944 | pci_set_drvdata(pdev, NULL); | 969 | pci_set_drvdata(pdev, NULL); |
945 | kfree(dm1105dvb); | 970 | kfree(dev); |
946 | return ret; | 971 | return ret; |
947 | } | 972 | } |
948 | 973 | ||
949 | static void __devexit dm1105_remove(struct pci_dev *pdev) | 974 | static void __devexit dm1105_remove(struct pci_dev *pdev) |
950 | { | 975 | { |
951 | struct dm1105dvb *dm1105dvb = pci_get_drvdata(pdev); | 976 | struct dm1105_dev *dev = pci_get_drvdata(pdev); |
952 | struct dvb_adapter *dvb_adapter = &dm1105dvb->dvb_adapter; | 977 | struct dvb_adapter *dvb_adapter = &dev->dvb_adapter; |
953 | struct dvb_demux *dvbdemux = &dm1105dvb->demux; | 978 | struct dvb_demux *dvbdemux = &dev->demux; |
954 | struct dmx_demux *dmx = &dvbdemux->dmx; | 979 | struct dmx_demux *dmx = &dvbdemux->dmx; |
955 | 980 | ||
956 | dm1105_ir_exit(dm1105dvb); | 981 | dm1105_ir_exit(dev); |
957 | dmx->close(dmx); | 982 | dmx->close(dmx); |
958 | dvb_net_release(&dm1105dvb->dvbnet); | 983 | dvb_net_release(&dev->dvbnet); |
959 | if (dm1105dvb->fe) | 984 | if (dev->fe) |
960 | dvb_unregister_frontend(dm1105dvb->fe); | 985 | dvb_unregister_frontend(dev->fe); |
961 | 986 | ||
962 | dmx->disconnect_frontend(dmx); | 987 | dmx->disconnect_frontend(dmx); |
963 | dmx->remove_frontend(dmx, &dm1105dvb->mem_frontend); | 988 | dmx->remove_frontend(dmx, &dev->mem_frontend); |
964 | dmx->remove_frontend(dmx, &dm1105dvb->hw_frontend); | 989 | dmx->remove_frontend(dmx, &dev->hw_frontend); |
965 | dvb_dmxdev_release(&dm1105dvb->dmxdev); | 990 | dvb_dmxdev_release(&dev->dmxdev); |
966 | dvb_dmx_release(dvbdemux); | 991 | dvb_dmx_release(dvbdemux); |
967 | dvb_unregister_adapter(dvb_adapter); | 992 | dvb_unregister_adapter(dvb_adapter); |
968 | if (&dm1105dvb->i2c_adap) | 993 | if (&dev->i2c_adap) |
969 | i2c_del_adapter(&dm1105dvb->i2c_adap); | 994 | i2c_del_adapter(&dev->i2c_adap); |
970 | 995 | ||
971 | dm1105dvb_hw_exit(dm1105dvb); | 996 | dm1105_hw_exit(dev); |
972 | synchronize_irq(pdev->irq); | 997 | synchronize_irq(pdev->irq); |
973 | free_irq(pdev->irq, dm1105dvb); | 998 | free_irq(pdev->irq, dev); |
974 | pci_iounmap(pdev, dm1105dvb->io_mem); | 999 | pci_iounmap(pdev, dev->io_mem); |
975 | pci_release_regions(pdev); | 1000 | pci_release_regions(pdev); |
976 | pci_disable_device(pdev); | 1001 | pci_disable_device(pdev); |
977 | pci_set_drvdata(pdev, NULL); | 1002 | pci_set_drvdata(pdev, NULL); |
978 | dm1105_devcount--; | 1003 | dm1105_devcount--; |
979 | kfree(dm1105dvb); | 1004 | kfree(dev); |
980 | } | 1005 | } |
981 | 1006 | ||
982 | static struct pci_device_id dm1105_id_table[] __devinitdata = { | 1007 | static struct pci_device_id dm1105_id_table[] __devinitdata = { |
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 07461222a7f5..55ea260572bf 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c | |||
@@ -1199,8 +1199,6 @@ static int dtv_property_process_get(struct dvb_frontend *fe, | |||
1199 | { | 1199 | { |
1200 | int r = 0; | 1200 | int r = 0; |
1201 | 1201 | ||
1202 | dtv_property_dump(tvp); | ||
1203 | |||
1204 | /* Allow the frontend to validate incoming properties */ | 1202 | /* Allow the frontend to validate incoming properties */ |
1205 | if (fe->ops.get_property) | 1203 | if (fe->ops.get_property) |
1206 | r = fe->ops.get_property(fe, tvp); | 1204 | r = fe->ops.get_property(fe, tvp); |
@@ -1323,6 +1321,8 @@ static int dtv_property_process_get(struct dvb_frontend *fe, | |||
1323 | r = -1; | 1321 | r = -1; |
1324 | } | 1322 | } |
1325 | 1323 | ||
1324 | dtv_property_dump(tvp); | ||
1325 | |||
1326 | return r; | 1326 | return r; |
1327 | } | 1327 | } |
1328 | 1328 | ||
@@ -1488,7 +1488,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, | |||
1488 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | 1488 | struct dvb_frontend_private *fepriv = fe->frontend_priv; |
1489 | int err = -EOPNOTSUPP; | 1489 | int err = -EOPNOTSUPP; |
1490 | 1490 | ||
1491 | dprintk ("%s\n", __func__); | 1491 | dprintk("%s (%d)\n", __func__, _IOC_NR(cmd)); |
1492 | 1492 | ||
1493 | if (fepriv->exit) | 1493 | if (fepriv->exit) |
1494 | return -ENODEV; | 1494 | return -ENODEV; |
@@ -1536,8 +1536,7 @@ static int dvb_frontend_ioctl_properties(struct inode *inode, struct file *file, | |||
1536 | if ((tvps->num == 0) || (tvps->num > DTV_IOCTL_MAX_MSGS)) | 1536 | if ((tvps->num == 0) || (tvps->num > DTV_IOCTL_MAX_MSGS)) |
1537 | return -EINVAL; | 1537 | return -EINVAL; |
1538 | 1538 | ||
1539 | tvp = (struct dtv_property *) kmalloc(tvps->num * | 1539 | tvp = kmalloc(tvps->num * sizeof(struct dtv_property), GFP_KERNEL); |
1540 | sizeof(struct dtv_property), GFP_KERNEL); | ||
1541 | if (!tvp) { | 1540 | if (!tvp) { |
1542 | err = -ENOMEM; | 1541 | err = -ENOMEM; |
1543 | goto out; | 1542 | goto out; |
@@ -1569,8 +1568,7 @@ static int dvb_frontend_ioctl_properties(struct inode *inode, struct file *file, | |||
1569 | if ((tvps->num == 0) || (tvps->num > DTV_IOCTL_MAX_MSGS)) | 1568 | if ((tvps->num == 0) || (tvps->num > DTV_IOCTL_MAX_MSGS)) |
1570 | return -EINVAL; | 1569 | return -EINVAL; |
1571 | 1570 | ||
1572 | tvp = (struct dtv_property *) kmalloc(tvps->num * | 1571 | tvp = kmalloc(tvps->num * sizeof(struct dtv_property), GFP_KERNEL); |
1573 | sizeof(struct dtv_property), GFP_KERNEL); | ||
1574 | if (!tvp) { | 1572 | if (!tvp) { |
1575 | err = -ENOMEM; | 1573 | err = -ENOMEM; |
1576 | goto out; | 1574 | goto out; |
diff --git a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c index 584bbd194dc8..a5712cd7c65f 100644 --- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c +++ b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c | |||
@@ -89,6 +89,7 @@ void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf) | |||
89 | rbuf->pread = rbuf->pwrite; | 89 | rbuf->pread = rbuf->pwrite; |
90 | rbuf->error = 0; | 90 | rbuf->error = 0; |
91 | } | 91 | } |
92 | EXPORT_SYMBOL(dvb_ringbuffer_flush); | ||
92 | 93 | ||
93 | void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf) | 94 | void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf) |
94 | { | 95 | { |
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index 465295b1d14b..e5f91f16ffa4 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig | |||
@@ -336,3 +336,11 @@ config DVB_USB_EC168 | |||
336 | select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE | 336 | select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE |
337 | help | 337 | help |
338 | Say Y here to support the E3C EC168 DVB-T USB2.0 receiver. | 338 | Say Y here to support the E3C EC168 DVB-T USB2.0 receiver. |
339 | |||
340 | config DVB_USB_AZ6027 | ||
341 | tristate "Azurewave DVB-S/S2 USB2.0 AZ6027 support" | ||
342 | depends on DVB_USB | ||
343 | select DVB_STB0899 if !DVB_FE_CUSTOMISE | ||
344 | select DVB_STB6100 if !DVB_FE_CUSTOMISE | ||
345 | help | ||
346 | Say Y here to support the AZ6027 device | ||
diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile index 72c92cb69a22..1a192453b0e7 100644 --- a/drivers/media/dvb/dvb-usb/Makefile +++ b/drivers/media/dvb/dvb-usb/Makefile | |||
@@ -85,6 +85,9 @@ obj-$(CONFIG_DVB_USB_FRIIO) += dvb-usb-friio.o | |||
85 | dvb-usb-ec168-objs = ec168.o | 85 | dvb-usb-ec168-objs = ec168.o |
86 | obj-$(CONFIG_DVB_USB_EC168) += dvb-usb-ec168.o | 86 | obj-$(CONFIG_DVB_USB_EC168) += dvb-usb-ec168.o |
87 | 87 | ||
88 | dvb-usb-az6027-objs = az6027.o | ||
89 | obj-$(CONFIG_DVB_USB_AZ6027) += dvb-usb-az6027.o | ||
90 | |||
88 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ | 91 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ |
89 | # due to tuner-xc3028 | 92 | # due to tuner-xc3028 |
90 | EXTRA_CFLAGS += -Idrivers/media/common/tuners | 93 | EXTRA_CFLAGS += -Idrivers/media/common/tuners |
diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c index 8b60a601fb82..d7975383d31b 100644 --- a/drivers/media/dvb/dvb-usb/af9015.c +++ b/drivers/media/dvb/dvb-usb/af9015.c | |||
@@ -21,6 +21,8 @@ | |||
21 | * | 21 | * |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <linux/hash.h> | ||
25 | |||
24 | #include "af9015.h" | 26 | #include "af9015.h" |
25 | #include "af9013.h" | 27 | #include "af9013.h" |
26 | #include "mt2060.h" | 28 | #include "mt2060.h" |
@@ -553,26 +555,45 @@ exit: | |||
553 | return ret; | 555 | return ret; |
554 | } | 556 | } |
555 | 557 | ||
556 | /* dump eeprom */ | 558 | /* hash (and dump) eeprom */ |
557 | static int af9015_eeprom_dump(struct dvb_usb_device *d) | 559 | static int af9015_eeprom_hash(struct usb_device *udev) |
558 | { | 560 | { |
559 | u8 reg, val; | 561 | static const unsigned int eeprom_size = 256; |
562 | unsigned int reg; | ||
563 | int ret; | ||
564 | u8 val, *eeprom; | ||
565 | struct req_t req = {READ_I2C, AF9015_I2C_EEPROM, 0, 0, 1, 1, &val}; | ||
560 | 566 | ||
561 | for (reg = 0; ; reg++) { | 567 | eeprom = kmalloc(eeprom_size, GFP_KERNEL); |
562 | if (reg % 16 == 0) { | 568 | if (eeprom == NULL) |
563 | if (reg) | 569 | return -ENOMEM; |
564 | deb_info(KERN_CONT "\n"); | 570 | |
565 | deb_info(KERN_DEBUG "%02x:", reg); | 571 | for (reg = 0; reg < eeprom_size; reg++) { |
566 | } | 572 | req.addr = reg; |
567 | if (af9015_read_reg_i2c(d, AF9015_I2C_EEPROM, reg, &val) == 0) | 573 | ret = af9015_rw_udev(udev, &req); |
568 | deb_info(KERN_CONT " %02x", val); | 574 | if (ret) |
569 | else | 575 | goto free; |
570 | deb_info(KERN_CONT " --"); | 576 | eeprom[reg] = val; |
571 | if (reg == 0xff) | ||
572 | break; | ||
573 | } | 577 | } |
574 | deb_info(KERN_CONT "\n"); | 578 | |
575 | return 0; | 579 | if (dvb_usb_af9015_debug & 0x01) |
580 | print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, eeprom, | ||
581 | eeprom_size); | ||
582 | |||
583 | BUG_ON(eeprom_size % 4); | ||
584 | |||
585 | af9015_config.eeprom_sum = 0; | ||
586 | for (reg = 0; reg < eeprom_size / sizeof(u32); reg++) { | ||
587 | af9015_config.eeprom_sum *= GOLDEN_RATIO_PRIME_32; | ||
588 | af9015_config.eeprom_sum += le32_to_cpu(((u32 *)eeprom)[reg]); | ||
589 | } | ||
590 | |||
591 | deb_info("%s: eeprom sum=%.8x\n", __func__, af9015_config.eeprom_sum); | ||
592 | |||
593 | ret = 0; | ||
594 | free: | ||
595 | kfree(eeprom); | ||
596 | return ret; | ||
576 | } | 597 | } |
577 | 598 | ||
578 | static int af9015_download_ir_table(struct dvb_usb_device *d) | 599 | static int af9015_download_ir_table(struct dvb_usb_device *d) |
@@ -711,12 +732,132 @@ error: | |||
711 | return ret; | 732 | return ret; |
712 | } | 733 | } |
713 | 734 | ||
735 | struct af9015_setup { | ||
736 | unsigned int id; | ||
737 | struct dvb_usb_rc_key *rc_key_map; | ||
738 | unsigned int rc_key_map_size; | ||
739 | u8 *ir_table; | ||
740 | unsigned int ir_table_size; | ||
741 | }; | ||
742 | |||
743 | static const struct af9015_setup *af9015_setup_match(unsigned int id, | ||
744 | const struct af9015_setup *table) | ||
745 | { | ||
746 | for (; table->rc_key_map; table++) | ||
747 | if (table->id == id) | ||
748 | return table; | ||
749 | return NULL; | ||
750 | } | ||
751 | |||
752 | static const struct af9015_setup af9015_setup_modparam[] = { | ||
753 | { AF9015_REMOTE_A_LINK_DTU_M, | ||
754 | af9015_rc_keys_a_link, ARRAY_SIZE(af9015_rc_keys_a_link), | ||
755 | af9015_ir_table_a_link, ARRAY_SIZE(af9015_ir_table_a_link) }, | ||
756 | { AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3, | ||
757 | af9015_rc_keys_msi, ARRAY_SIZE(af9015_rc_keys_msi), | ||
758 | af9015_ir_table_msi, ARRAY_SIZE(af9015_ir_table_msi) }, | ||
759 | { AF9015_REMOTE_MYGICTV_U718, | ||
760 | af9015_rc_keys_mygictv, ARRAY_SIZE(af9015_rc_keys_mygictv), | ||
761 | af9015_ir_table_mygictv, ARRAY_SIZE(af9015_ir_table_mygictv) }, | ||
762 | { AF9015_REMOTE_DIGITTRADE_DVB_T, | ||
763 | af9015_rc_keys_digittrade, ARRAY_SIZE(af9015_rc_keys_digittrade), | ||
764 | af9015_ir_table_digittrade, ARRAY_SIZE(af9015_ir_table_digittrade) }, | ||
765 | { AF9015_REMOTE_AVERMEDIA_KS, | ||
766 | af9015_rc_keys_avermedia, ARRAY_SIZE(af9015_rc_keys_avermedia), | ||
767 | af9015_ir_table_avermedia_ks, ARRAY_SIZE(af9015_ir_table_avermedia_ks) }, | ||
768 | { } | ||
769 | }; | ||
770 | |||
771 | /* don't add new entries here anymore, use hashes instead */ | ||
772 | static const struct af9015_setup af9015_setup_usbids[] = { | ||
773 | { USB_VID_LEADTEK, | ||
774 | af9015_rc_keys_leadtek, ARRAY_SIZE(af9015_rc_keys_leadtek), | ||
775 | af9015_ir_table_leadtek, ARRAY_SIZE(af9015_ir_table_leadtek) }, | ||
776 | { USB_VID_VISIONPLUS, | ||
777 | af9015_rc_keys_twinhan, ARRAY_SIZE(af9015_rc_keys_twinhan), | ||
778 | af9015_ir_table_twinhan, ARRAY_SIZE(af9015_ir_table_twinhan) }, | ||
779 | { USB_VID_KWORLD_2, /* TODO: use correct rc keys */ | ||
780 | af9015_rc_keys_twinhan, ARRAY_SIZE(af9015_rc_keys_twinhan), | ||
781 | af9015_ir_table_kworld, ARRAY_SIZE(af9015_ir_table_kworld) }, | ||
782 | { USB_VID_AVERMEDIA, | ||
783 | af9015_rc_keys_avermedia, ARRAY_SIZE(af9015_rc_keys_avermedia), | ||
784 | af9015_ir_table_avermedia, ARRAY_SIZE(af9015_ir_table_avermedia) }, | ||
785 | { USB_VID_MSI_2, | ||
786 | af9015_rc_keys_msi_digivox_iii, ARRAY_SIZE(af9015_rc_keys_msi_digivox_iii), | ||
787 | af9015_ir_table_msi_digivox_iii, ARRAY_SIZE(af9015_ir_table_msi_digivox_iii) }, | ||
788 | { } | ||
789 | }; | ||
790 | |||
791 | static const struct af9015_setup af9015_setup_hashes[] = { | ||
792 | { 0xb8feb708, | ||
793 | af9015_rc_keys_msi, ARRAY_SIZE(af9015_rc_keys_msi), | ||
794 | af9015_ir_table_msi, ARRAY_SIZE(af9015_ir_table_msi) }, | ||
795 | { 0xa3703d00, | ||
796 | af9015_rc_keys_a_link, ARRAY_SIZE(af9015_rc_keys_a_link), | ||
797 | af9015_ir_table_a_link, ARRAY_SIZE(af9015_ir_table_a_link) }, | ||
798 | { 0x9b7dc64e, | ||
799 | af9015_rc_keys_mygictv, ARRAY_SIZE(af9015_rc_keys_mygictv), | ||
800 | af9015_ir_table_mygictv, ARRAY_SIZE(af9015_ir_table_mygictv) }, | ||
801 | { } | ||
802 | }; | ||
803 | |||
804 | static void af9015_set_remote_config(struct usb_device *udev, | ||
805 | struct dvb_usb_device_properties *props) | ||
806 | { | ||
807 | const struct af9015_setup *table = NULL; | ||
808 | |||
809 | if (dvb_usb_af9015_remote) { | ||
810 | /* load remote defined as module param */ | ||
811 | table = af9015_setup_match(dvb_usb_af9015_remote, | ||
812 | af9015_setup_modparam); | ||
813 | } else { | ||
814 | u16 vendor = le16_to_cpu(udev->descriptor.idVendor); | ||
815 | |||
816 | table = af9015_setup_match(af9015_config.eeprom_sum, | ||
817 | af9015_setup_hashes); | ||
818 | |||
819 | if (!table && vendor == USB_VID_AFATECH) { | ||
820 | /* Check USB manufacturer and product strings and try | ||
821 | to determine correct remote in case of chip vendor | ||
822 | reference IDs are used. | ||
823 | DO NOT ADD ANYTHING NEW HERE. Use hashes instead. | ||
824 | */ | ||
825 | char manufacturer[10]; | ||
826 | memset(manufacturer, 0, sizeof(manufacturer)); | ||
827 | usb_string(udev, udev->descriptor.iManufacturer, | ||
828 | manufacturer, sizeof(manufacturer)); | ||
829 | if (!strcmp("MSI", manufacturer)) { | ||
830 | /* iManufacturer 1 MSI | ||
831 | iProduct 2 MSI K-VOX */ | ||
832 | table = af9015_setup_match( | ||
833 | AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3, | ||
834 | af9015_setup_modparam); | ||
835 | } else if (udev->descriptor.idProduct == | ||
836 | cpu_to_le16(USB_PID_TREKSTOR_DVBT)) { | ||
837 | table = &(const struct af9015_setup){ 0, | ||
838 | af9015_rc_keys_trekstor, | ||
839 | ARRAY_SIZE(af9015_rc_keys_trekstor), | ||
840 | af9015_ir_table_trekstor, | ||
841 | ARRAY_SIZE(af9015_ir_table_trekstor) | ||
842 | }; | ||
843 | } | ||
844 | } else if (!table) | ||
845 | table = af9015_setup_match(vendor, af9015_setup_usbids); | ||
846 | } | ||
847 | |||
848 | if (table) { | ||
849 | props->rc_key_map = table->rc_key_map; | ||
850 | props->rc_key_map_size = table->rc_key_map_size; | ||
851 | af9015_config.ir_table = table->ir_table; | ||
852 | af9015_config.ir_table_size = table->ir_table_size; | ||
853 | } | ||
854 | } | ||
855 | |||
714 | static int af9015_read_config(struct usb_device *udev) | 856 | static int af9015_read_config(struct usb_device *udev) |
715 | { | 857 | { |
716 | int ret; | 858 | int ret; |
717 | u8 val, i, offset = 0; | 859 | u8 val, i, offset = 0; |
718 | struct req_t req = {READ_I2C, AF9015_I2C_EEPROM, 0, 0, 1, 1, &val}; | 860 | struct req_t req = {READ_I2C, AF9015_I2C_EEPROM, 0, 0, 1, 1, &val}; |
719 | char manufacturer[10]; | ||
720 | 861 | ||
721 | /* IR remote controller */ | 862 | /* IR remote controller */ |
722 | req.addr = AF9015_EEPROM_IR_MODE; | 863 | req.addr = AF9015_EEPROM_IR_MODE; |
@@ -728,158 +869,18 @@ static int af9015_read_config(struct usb_device *udev) | |||
728 | } | 869 | } |
729 | if (ret) | 870 | if (ret) |
730 | goto error; | 871 | goto error; |
872 | |||
873 | ret = af9015_eeprom_hash(udev); | ||
874 | if (ret) | ||
875 | goto error; | ||
876 | |||
731 | deb_info("%s: IR mode:%d\n", __func__, val); | 877 | deb_info("%s: IR mode:%d\n", __func__, val); |
732 | for (i = 0; i < af9015_properties_count; i++) { | 878 | for (i = 0; i < af9015_properties_count; i++) { |
733 | if (val == AF9015_IR_MODE_DISABLED) { | 879 | if (val == AF9015_IR_MODE_DISABLED) { |
734 | af9015_properties[i].rc_key_map = NULL; | 880 | af9015_properties[i].rc_key_map = NULL; |
735 | af9015_properties[i].rc_key_map_size = 0; | 881 | af9015_properties[i].rc_key_map_size = 0; |
736 | } else if (dvb_usb_af9015_remote) { | 882 | } else |
737 | /* load remote defined as module param */ | 883 | af9015_set_remote_config(udev, &af9015_properties[i]); |
738 | switch (dvb_usb_af9015_remote) { | ||
739 | case AF9015_REMOTE_A_LINK_DTU_M: | ||
740 | af9015_properties[i].rc_key_map = | ||
741 | af9015_rc_keys_a_link; | ||
742 | af9015_properties[i].rc_key_map_size = | ||
743 | ARRAY_SIZE(af9015_rc_keys_a_link); | ||
744 | af9015_config.ir_table = af9015_ir_table_a_link; | ||
745 | af9015_config.ir_table_size = | ||
746 | ARRAY_SIZE(af9015_ir_table_a_link); | ||
747 | break; | ||
748 | case AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3: | ||
749 | af9015_properties[i].rc_key_map = | ||
750 | af9015_rc_keys_msi; | ||
751 | af9015_properties[i].rc_key_map_size = | ||
752 | ARRAY_SIZE(af9015_rc_keys_msi); | ||
753 | af9015_config.ir_table = af9015_ir_table_msi; | ||
754 | af9015_config.ir_table_size = | ||
755 | ARRAY_SIZE(af9015_ir_table_msi); | ||
756 | break; | ||
757 | case AF9015_REMOTE_MYGICTV_U718: | ||
758 | af9015_properties[i].rc_key_map = | ||
759 | af9015_rc_keys_mygictv; | ||
760 | af9015_properties[i].rc_key_map_size = | ||
761 | ARRAY_SIZE(af9015_rc_keys_mygictv); | ||
762 | af9015_config.ir_table = | ||
763 | af9015_ir_table_mygictv; | ||
764 | af9015_config.ir_table_size = | ||
765 | ARRAY_SIZE(af9015_ir_table_mygictv); | ||
766 | break; | ||
767 | case AF9015_REMOTE_DIGITTRADE_DVB_T: | ||
768 | af9015_properties[i].rc_key_map = | ||
769 | af9015_rc_keys_digittrade; | ||
770 | af9015_properties[i].rc_key_map_size = | ||
771 | ARRAY_SIZE(af9015_rc_keys_digittrade); | ||
772 | af9015_config.ir_table = | ||
773 | af9015_ir_table_digittrade; | ||
774 | af9015_config.ir_table_size = | ||
775 | ARRAY_SIZE(af9015_ir_table_digittrade); | ||
776 | break; | ||
777 | case AF9015_REMOTE_AVERMEDIA_KS: | ||
778 | af9015_properties[i].rc_key_map = | ||
779 | af9015_rc_keys_avermedia; | ||
780 | af9015_properties[i].rc_key_map_size = | ||
781 | ARRAY_SIZE(af9015_rc_keys_avermedia); | ||
782 | af9015_config.ir_table = | ||
783 | af9015_ir_table_avermedia_ks; | ||
784 | af9015_config.ir_table_size = | ||
785 | ARRAY_SIZE(af9015_ir_table_avermedia_ks); | ||
786 | break; | ||
787 | } | ||
788 | } else { | ||
789 | switch (le16_to_cpu(udev->descriptor.idVendor)) { | ||
790 | case USB_VID_LEADTEK: | ||
791 | af9015_properties[i].rc_key_map = | ||
792 | af9015_rc_keys_leadtek; | ||
793 | af9015_properties[i].rc_key_map_size = | ||
794 | ARRAY_SIZE(af9015_rc_keys_leadtek); | ||
795 | af9015_config.ir_table = | ||
796 | af9015_ir_table_leadtek; | ||
797 | af9015_config.ir_table_size = | ||
798 | ARRAY_SIZE(af9015_ir_table_leadtek); | ||
799 | break; | ||
800 | case USB_VID_VISIONPLUS: | ||
801 | af9015_properties[i].rc_key_map = | ||
802 | af9015_rc_keys_twinhan; | ||
803 | af9015_properties[i].rc_key_map_size = | ||
804 | ARRAY_SIZE(af9015_rc_keys_twinhan); | ||
805 | af9015_config.ir_table = | ||
806 | af9015_ir_table_twinhan; | ||
807 | af9015_config.ir_table_size = | ||
808 | ARRAY_SIZE(af9015_ir_table_twinhan); | ||
809 | break; | ||
810 | case USB_VID_KWORLD_2: | ||
811 | /* TODO: use correct rc keys */ | ||
812 | af9015_properties[i].rc_key_map = | ||
813 | af9015_rc_keys_twinhan; | ||
814 | af9015_properties[i].rc_key_map_size = | ||
815 | ARRAY_SIZE(af9015_rc_keys_twinhan); | ||
816 | af9015_config.ir_table = af9015_ir_table_kworld; | ||
817 | af9015_config.ir_table_size = | ||
818 | ARRAY_SIZE(af9015_ir_table_kworld); | ||
819 | break; | ||
820 | /* Check USB manufacturer and product strings and try | ||
821 | to determine correct remote in case of chip vendor | ||
822 | reference IDs are used. */ | ||
823 | case USB_VID_AFATECH: | ||
824 | memset(manufacturer, 0, sizeof(manufacturer)); | ||
825 | usb_string(udev, udev->descriptor.iManufacturer, | ||
826 | manufacturer, sizeof(manufacturer)); | ||
827 | if (!strcmp("Geniatech", manufacturer)) { | ||
828 | /* iManufacturer 1 Geniatech | ||
829 | iProduct 2 AF9015 */ | ||
830 | af9015_properties[i].rc_key_map = | ||
831 | af9015_rc_keys_mygictv; | ||
832 | af9015_properties[i].rc_key_map_size = | ||
833 | ARRAY_SIZE(af9015_rc_keys_mygictv); | ||
834 | af9015_config.ir_table = | ||
835 | af9015_ir_table_mygictv; | ||
836 | af9015_config.ir_table_size = | ||
837 | ARRAY_SIZE(af9015_ir_table_mygictv); | ||
838 | } else if (!strcmp("MSI", manufacturer)) { | ||
839 | /* iManufacturer 1 MSI | ||
840 | iProduct 2 MSI K-VOX */ | ||
841 | af9015_properties[i].rc_key_map = | ||
842 | af9015_rc_keys_msi; | ||
843 | af9015_properties[i].rc_key_map_size = | ||
844 | ARRAY_SIZE(af9015_rc_keys_msi); | ||
845 | af9015_config.ir_table = | ||
846 | af9015_ir_table_msi; | ||
847 | af9015_config.ir_table_size = | ||
848 | ARRAY_SIZE(af9015_ir_table_msi); | ||
849 | } else if (udev->descriptor.idProduct == | ||
850 | cpu_to_le16(USB_PID_TREKSTOR_DVBT)) { | ||
851 | af9015_properties[i].rc_key_map = | ||
852 | af9015_rc_keys_trekstor; | ||
853 | af9015_properties[i].rc_key_map_size = | ||
854 | ARRAY_SIZE(af9015_rc_keys_trekstor); | ||
855 | af9015_config.ir_table = | ||
856 | af9015_ir_table_trekstor; | ||
857 | af9015_config.ir_table_size = | ||
858 | ARRAY_SIZE(af9015_ir_table_trekstor); | ||
859 | } | ||
860 | break; | ||
861 | case USB_VID_AVERMEDIA: | ||
862 | af9015_properties[i].rc_key_map = | ||
863 | af9015_rc_keys_avermedia; | ||
864 | af9015_properties[i].rc_key_map_size = | ||
865 | ARRAY_SIZE(af9015_rc_keys_avermedia); | ||
866 | af9015_config.ir_table = | ||
867 | af9015_ir_table_avermedia; | ||
868 | af9015_config.ir_table_size = | ||
869 | ARRAY_SIZE(af9015_ir_table_avermedia); | ||
870 | break; | ||
871 | case USB_VID_MSI_2: | ||
872 | af9015_properties[i].rc_key_map = | ||
873 | af9015_rc_keys_msi_digivox_iii; | ||
874 | af9015_properties[i].rc_key_map_size = | ||
875 | ARRAY_SIZE(af9015_rc_keys_msi_digivox_iii); | ||
876 | af9015_config.ir_table = | ||
877 | af9015_ir_table_msi_digivox_iii; | ||
878 | af9015_config.ir_table_size = | ||
879 | ARRAY_SIZE(af9015_ir_table_msi_digivox_iii); | ||
880 | break; | ||
881 | } | ||
882 | } | ||
883 | } | 884 | } |
884 | 885 | ||
885 | /* TS mode - one or two receivers */ | 886 | /* TS mode - one or two receivers */ |
@@ -1001,6 +1002,9 @@ static int af9015_read_config(struct usb_device *udev) | |||
1001 | af9015_af9013_config[i].gpio[1] = AF9013_GPIO_LO; | 1002 | af9015_af9013_config[i].gpio[1] = AF9013_GPIO_LO; |
1002 | af9015_af9013_config[i].rf_spec_inv = 1; | 1003 | af9015_af9013_config[i].rf_spec_inv = 1; |
1003 | break; | 1004 | break; |
1005 | case AF9013_TUNER_TDA18218: | ||
1006 | warn("tuner NXP TDA18218 not supported yet"); | ||
1007 | return -ENODEV; | ||
1004 | default: | 1008 | default: |
1005 | warn("tuner id:%d not supported, please report!", val); | 1009 | warn("tuner id:%d not supported, please report!", val); |
1006 | return -ENODEV; | 1010 | return -ENODEV; |
@@ -1125,11 +1129,6 @@ static int af9015_af9013_frontend_attach(struct dvb_usb_adapter *adap) | |||
1125 | 1129 | ||
1126 | deb_info("%s: init I2C\n", __func__); | 1130 | deb_info("%s: init I2C\n", __func__); |
1127 | ret = af9015_i2c_init(adap->dev); | 1131 | ret = af9015_i2c_init(adap->dev); |
1128 | |||
1129 | /* dump eeprom (debug) */ | ||
1130 | ret = af9015_eeprom_dump(adap->dev); | ||
1131 | if (ret) | ||
1132 | return ret; | ||
1133 | } else { | 1132 | } else { |
1134 | /* select I2C adapter */ | 1133 | /* select I2C adapter */ |
1135 | i2c_adap = &state->i2c_adap; | 1134 | i2c_adap = &state->i2c_adap; |
@@ -1295,6 +1294,8 @@ static struct usb_device_id af9015_usb_table[] = { | |||
1295 | /* 25 */{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_399U_2)}, | 1294 | /* 25 */{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_399U_2)}, |
1296 | {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_PC160_T)}, | 1295 | {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_PC160_T)}, |
1297 | {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV20)}, | 1296 | {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV20)}, |
1297 | {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_TINYTWIN_2)}, | ||
1298 | {USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV2000DS)}, | ||
1298 | {0}, | 1299 | {0}, |
1299 | }; | 1300 | }; |
1300 | MODULE_DEVICE_TABLE(usb, af9015_usb_table); | 1301 | MODULE_DEVICE_TABLE(usb, af9015_usb_table); |
@@ -1381,7 +1382,8 @@ static struct dvb_usb_device_properties af9015_properties[] = { | |||
1381 | }, | 1382 | }, |
1382 | { | 1383 | { |
1383 | .name = "DigitalNow TinyTwin DVB-T Receiver", | 1384 | .name = "DigitalNow TinyTwin DVB-T Receiver", |
1384 | .cold_ids = {&af9015_usb_table[5], NULL}, | 1385 | .cold_ids = {&af9015_usb_table[5], |
1386 | &af9015_usb_table[28], NULL}, | ||
1385 | .warm_ids = {NULL}, | 1387 | .warm_ids = {NULL}, |
1386 | }, | 1388 | }, |
1387 | { | 1389 | { |
@@ -1566,7 +1568,7 @@ static struct dvb_usb_device_properties af9015_properties[] = { | |||
1566 | 1568 | ||
1567 | .i2c_algo = &af9015_i2c_algo, | 1569 | .i2c_algo = &af9015_i2c_algo, |
1568 | 1570 | ||
1569 | .num_device_descs = 6, /* max 9 */ | 1571 | .num_device_descs = 7, /* max 9 */ |
1570 | .devices = { | 1572 | .devices = { |
1571 | { | 1573 | { |
1572 | .name = "AverMedia AVerTV Volar GPS 805 (A805)", | 1574 | .name = "AverMedia AVerTV Volar GPS 805 (A805)", |
@@ -1600,6 +1602,11 @@ static struct dvb_usb_device_properties af9015_properties[] = { | |||
1600 | .cold_ids = {&af9015_usb_table[27], NULL}, | 1602 | .cold_ids = {&af9015_usb_table[27], NULL}, |
1601 | .warm_ids = {NULL}, | 1603 | .warm_ids = {NULL}, |
1602 | }, | 1604 | }, |
1605 | { | ||
1606 | .name = "Leadtek WinFast DTV2000DS", | ||
1607 | .cold_ids = {&af9015_usb_table[29], NULL}, | ||
1608 | .warm_ids = {NULL}, | ||
1609 | }, | ||
1603 | } | 1610 | } |
1604 | }, | 1611 | }, |
1605 | }; | 1612 | }; |
diff --git a/drivers/media/dvb/dvb-usb/af9015.h b/drivers/media/dvb/dvb-usb/af9015.h index 931c8515830d..ef36b1831490 100644 --- a/drivers/media/dvb/dvb-usb/af9015.h +++ b/drivers/media/dvb/dvb-usb/af9015.h | |||
@@ -107,6 +107,7 @@ struct af9015_config { | |||
107 | u16 mt2060_if1[2]; | 107 | u16 mt2060_if1[2]; |
108 | u16 firmware_size; | 108 | u16 firmware_size; |
109 | u16 firmware_checksum; | 109 | u16 firmware_checksum; |
110 | u32 eeprom_sum; | ||
110 | u8 *ir_table; | 111 | u8 *ir_table; |
111 | u16 ir_table_size; | 112 | u16 ir_table_size; |
112 | }; | 113 | }; |
diff --git a/drivers/media/dvb/dvb-usb/az6027.c b/drivers/media/dvb/dvb-usb/az6027.c new file mode 100644 index 000000000000..d7290b2c0913 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/az6027.c | |||
@@ -0,0 +1,1151 @@ | |||
1 | /* DVB USB compliant Linux driver for the AZUREWAVE DVB-S/S2 USB2.0 (AZ6027) | ||
2 | * receiver. | ||
3 | * | ||
4 | * Copyright (C) 2009 Adams.Xu <adams.xu@azwave.com.cn> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the Free | ||
8 | * Software Foundation, version 2. | ||
9 | * | ||
10 | * see Documentation/dvb/README.dvb-usb for more information | ||
11 | */ | ||
12 | #include "az6027.h" | ||
13 | |||
14 | #include "stb0899_drv.h" | ||
15 | #include "stb0899_reg.h" | ||
16 | #include "stb0899_cfg.h" | ||
17 | |||
18 | #include "stb6100.h" | ||
19 | #include "stb6100_cfg.h" | ||
20 | #include "dvb_ca_en50221.h" | ||
21 | |||
22 | int dvb_usb_az6027_debug; | ||
23 | module_param_named(debug, dvb_usb_az6027_debug, int, 0644); | ||
24 | MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS); | ||
25 | |||
26 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
27 | |||
28 | struct az6027_device_state { | ||
29 | struct dvb_ca_en50221 ca; | ||
30 | struct mutex ca_mutex; | ||
31 | u8 power_state; | ||
32 | }; | ||
33 | |||
34 | static const struct stb0899_s1_reg az6027_stb0899_s1_init_1[] = { | ||
35 | |||
36 | /* 0x0000000b, SYSREG */ | ||
37 | { STB0899_DEV_ID , 0x30 }, | ||
38 | { STB0899_DISCNTRL1 , 0x32 }, | ||
39 | { STB0899_DISCNTRL2 , 0x80 }, | ||
40 | { STB0899_DISRX_ST0 , 0x04 }, | ||
41 | { STB0899_DISRX_ST1 , 0x00 }, | ||
42 | { STB0899_DISPARITY , 0x00 }, | ||
43 | { STB0899_DISFIFO , 0x00 }, | ||
44 | { STB0899_DISSTATUS , 0x20 }, | ||
45 | { STB0899_DISF22 , 0x99 }, | ||
46 | { STB0899_DISF22RX , 0xa8 }, | ||
47 | /* SYSREG ? */ | ||
48 | { STB0899_ACRPRESC , 0x11 }, | ||
49 | { STB0899_ACRDIV1 , 0x0a }, | ||
50 | { STB0899_ACRDIV2 , 0x05 }, | ||
51 | { STB0899_DACR1 , 0x00 }, | ||
52 | { STB0899_DACR2 , 0x00 }, | ||
53 | { STB0899_OUTCFG , 0x00 }, | ||
54 | { STB0899_MODECFG , 0x00 }, | ||
55 | { STB0899_IRQSTATUS_3 , 0xfe }, | ||
56 | { STB0899_IRQSTATUS_2 , 0x03 }, | ||
57 | { STB0899_IRQSTATUS_1 , 0x7c }, | ||
58 | { STB0899_IRQSTATUS_0 , 0xf4 }, | ||
59 | { STB0899_IRQMSK_3 , 0xf3 }, | ||
60 | { STB0899_IRQMSK_2 , 0xfc }, | ||
61 | { STB0899_IRQMSK_1 , 0xff }, | ||
62 | { STB0899_IRQMSK_0 , 0xff }, | ||
63 | { STB0899_IRQCFG , 0x00 }, | ||
64 | { STB0899_I2CCFG , 0x88 }, | ||
65 | { STB0899_I2CRPT , 0x58 }, | ||
66 | { STB0899_IOPVALUE5 , 0x00 }, | ||
67 | { STB0899_IOPVALUE4 , 0x33 }, | ||
68 | { STB0899_IOPVALUE3 , 0x6d }, | ||
69 | { STB0899_IOPVALUE2 , 0x90 }, | ||
70 | { STB0899_IOPVALUE1 , 0x60 }, | ||
71 | { STB0899_IOPVALUE0 , 0x00 }, | ||
72 | { STB0899_GPIO00CFG , 0x82 }, | ||
73 | { STB0899_GPIO01CFG , 0x82 }, | ||
74 | { STB0899_GPIO02CFG , 0x82 }, | ||
75 | { STB0899_GPIO03CFG , 0x82 }, | ||
76 | { STB0899_GPIO04CFG , 0x82 }, | ||
77 | { STB0899_GPIO05CFG , 0x82 }, | ||
78 | { STB0899_GPIO06CFG , 0x82 }, | ||
79 | { STB0899_GPIO07CFG , 0x82 }, | ||
80 | { STB0899_GPIO08CFG , 0x82 }, | ||
81 | { STB0899_GPIO09CFG , 0x82 }, | ||
82 | { STB0899_GPIO10CFG , 0x82 }, | ||
83 | { STB0899_GPIO11CFG , 0x82 }, | ||
84 | { STB0899_GPIO12CFG , 0x82 }, | ||
85 | { STB0899_GPIO13CFG , 0x82 }, | ||
86 | { STB0899_GPIO14CFG , 0x82 }, | ||
87 | { STB0899_GPIO15CFG , 0x82 }, | ||
88 | { STB0899_GPIO16CFG , 0x82 }, | ||
89 | { STB0899_GPIO17CFG , 0x82 }, | ||
90 | { STB0899_GPIO18CFG , 0x82 }, | ||
91 | { STB0899_GPIO19CFG , 0x82 }, | ||
92 | { STB0899_GPIO20CFG , 0x82 }, | ||
93 | { STB0899_SDATCFG , 0xb8 }, | ||
94 | { STB0899_SCLTCFG , 0xba }, | ||
95 | { STB0899_AGCRFCFG , 0x1c }, /* 0x11 */ | ||
96 | { STB0899_GPIO22 , 0x82 }, /* AGCBB2CFG */ | ||
97 | { STB0899_GPIO21 , 0x91 }, /* AGCBB1CFG */ | ||
98 | { STB0899_DIRCLKCFG , 0x82 }, | ||
99 | { STB0899_CLKOUT27CFG , 0x7e }, | ||
100 | { STB0899_STDBYCFG , 0x82 }, | ||
101 | { STB0899_CS0CFG , 0x82 }, | ||
102 | { STB0899_CS1CFG , 0x82 }, | ||
103 | { STB0899_DISEQCOCFG , 0x20 }, | ||
104 | { STB0899_GPIO32CFG , 0x82 }, | ||
105 | { STB0899_GPIO33CFG , 0x82 }, | ||
106 | { STB0899_GPIO34CFG , 0x82 }, | ||
107 | { STB0899_GPIO35CFG , 0x82 }, | ||
108 | { STB0899_GPIO36CFG , 0x82 }, | ||
109 | { STB0899_GPIO37CFG , 0x82 }, | ||
110 | { STB0899_GPIO38CFG , 0x82 }, | ||
111 | { STB0899_GPIO39CFG , 0x82 }, | ||
112 | { STB0899_NCOARSE , 0x17 }, /* 0x15 = 27 Mhz Clock, F/3 = 198MHz, F/6 = 99MHz */ | ||
113 | { STB0899_SYNTCTRL , 0x02 }, /* 0x00 = CLK from CLKI, 0x02 = CLK from XTALI */ | ||
114 | { STB0899_FILTCTRL , 0x00 }, | ||
115 | { STB0899_SYSCTRL , 0x01 }, | ||
116 | { STB0899_STOPCLK1 , 0x20 }, | ||
117 | { STB0899_STOPCLK2 , 0x00 }, | ||
118 | { STB0899_INTBUFSTATUS , 0x00 }, | ||
119 | { STB0899_INTBUFCTRL , 0x0a }, | ||
120 | { 0xffff , 0xff }, | ||
121 | }; | ||
122 | |||
123 | static const struct stb0899_s1_reg az6027_stb0899_s1_init_3[] = { | ||
124 | { STB0899_DEMOD , 0x00 }, | ||
125 | { STB0899_RCOMPC , 0xc9 }, | ||
126 | { STB0899_AGC1CN , 0x01 }, | ||
127 | { STB0899_AGC1REF , 0x10 }, | ||
128 | { STB0899_RTC , 0x23 }, | ||
129 | { STB0899_TMGCFG , 0x4e }, | ||
130 | { STB0899_AGC2REF , 0x34 }, | ||
131 | { STB0899_TLSR , 0x84 }, | ||
132 | { STB0899_CFD , 0xf7 }, | ||
133 | { STB0899_ACLC , 0x87 }, | ||
134 | { STB0899_BCLC , 0x94 }, | ||
135 | { STB0899_EQON , 0x41 }, | ||
136 | { STB0899_LDT , 0xf1 }, | ||
137 | { STB0899_LDT2 , 0xe3 }, | ||
138 | { STB0899_EQUALREF , 0xb4 }, | ||
139 | { STB0899_TMGRAMP , 0x10 }, | ||
140 | { STB0899_TMGTHD , 0x30 }, | ||
141 | { STB0899_IDCCOMP , 0xfd }, | ||
142 | { STB0899_QDCCOMP , 0xff }, | ||
143 | { STB0899_POWERI , 0x0c }, | ||
144 | { STB0899_POWERQ , 0x0f }, | ||
145 | { STB0899_RCOMP , 0x6c }, | ||
146 | { STB0899_AGCIQIN , 0x80 }, | ||
147 | { STB0899_AGC2I1 , 0x06 }, | ||
148 | { STB0899_AGC2I2 , 0x00 }, | ||
149 | { STB0899_TLIR , 0x30 }, | ||
150 | { STB0899_RTF , 0x7f }, | ||
151 | { STB0899_DSTATUS , 0x00 }, | ||
152 | { STB0899_LDI , 0xbc }, | ||
153 | { STB0899_CFRM , 0xea }, | ||
154 | { STB0899_CFRL , 0x31 }, | ||
155 | { STB0899_NIRM , 0x2b }, | ||
156 | { STB0899_NIRL , 0x80 }, | ||
157 | { STB0899_ISYMB , 0x1d }, | ||
158 | { STB0899_QSYMB , 0xa6 }, | ||
159 | { STB0899_SFRH , 0x2f }, | ||
160 | { STB0899_SFRM , 0x68 }, | ||
161 | { STB0899_SFRL , 0x40 }, | ||
162 | { STB0899_SFRUPH , 0x2f }, | ||
163 | { STB0899_SFRUPM , 0x68 }, | ||
164 | { STB0899_SFRUPL , 0x40 }, | ||
165 | { STB0899_EQUAI1 , 0x02 }, | ||
166 | { STB0899_EQUAQ1 , 0xff }, | ||
167 | { STB0899_EQUAI2 , 0x04 }, | ||
168 | { STB0899_EQUAQ2 , 0x05 }, | ||
169 | { STB0899_EQUAI3 , 0x02 }, | ||
170 | { STB0899_EQUAQ3 , 0xfd }, | ||
171 | { STB0899_EQUAI4 , 0x03 }, | ||
172 | { STB0899_EQUAQ4 , 0x07 }, | ||
173 | { STB0899_EQUAI5 , 0x08 }, | ||
174 | { STB0899_EQUAQ5 , 0xf5 }, | ||
175 | { STB0899_DSTATUS2 , 0x00 }, | ||
176 | { STB0899_VSTATUS , 0x00 }, | ||
177 | { STB0899_VERROR , 0x86 }, | ||
178 | { STB0899_IQSWAP , 0x2a }, | ||
179 | { STB0899_ECNT1M , 0x00 }, | ||
180 | { STB0899_ECNT1L , 0x00 }, | ||
181 | { STB0899_ECNT2M , 0x00 }, | ||
182 | { STB0899_ECNT2L , 0x00 }, | ||
183 | { STB0899_ECNT3M , 0x0a }, | ||
184 | { STB0899_ECNT3L , 0xad }, | ||
185 | { STB0899_FECAUTO1 , 0x06 }, | ||
186 | { STB0899_FECM , 0x01 }, | ||
187 | { STB0899_VTH12 , 0xb0 }, | ||
188 | { STB0899_VTH23 , 0x7a }, | ||
189 | { STB0899_VTH34 , 0x58 }, | ||
190 | { STB0899_VTH56 , 0x38 }, | ||
191 | { STB0899_VTH67 , 0x34 }, | ||
192 | { STB0899_VTH78 , 0x24 }, | ||
193 | { STB0899_PRVIT , 0xff }, | ||
194 | { STB0899_VITSYNC , 0x19 }, | ||
195 | { STB0899_RSULC , 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */ | ||
196 | { STB0899_TSULC , 0x42 }, | ||
197 | { STB0899_RSLLC , 0x41 }, | ||
198 | { STB0899_TSLPL , 0x12 }, | ||
199 | { STB0899_TSCFGH , 0x0c }, | ||
200 | { STB0899_TSCFGM , 0x00 }, | ||
201 | { STB0899_TSCFGL , 0x00 }, | ||
202 | { STB0899_TSOUT , 0x69 }, /* 0x0d for CAM */ | ||
203 | { STB0899_RSSYNCDEL , 0x00 }, | ||
204 | { STB0899_TSINHDELH , 0x02 }, | ||
205 | { STB0899_TSINHDELM , 0x00 }, | ||
206 | { STB0899_TSINHDELL , 0x00 }, | ||
207 | { STB0899_TSLLSTKM , 0x1b }, | ||
208 | { STB0899_TSLLSTKL , 0xb3 }, | ||
209 | { STB0899_TSULSTKM , 0x00 }, | ||
210 | { STB0899_TSULSTKL , 0x00 }, | ||
211 | { STB0899_PCKLENUL , 0xbc }, | ||
212 | { STB0899_PCKLENLL , 0xcc }, | ||
213 | { STB0899_RSPCKLEN , 0xbd }, | ||
214 | { STB0899_TSSTATUS , 0x90 }, | ||
215 | { STB0899_ERRCTRL1 , 0xb6 }, | ||
216 | { STB0899_ERRCTRL2 , 0x95 }, | ||
217 | { STB0899_ERRCTRL3 , 0x8d }, | ||
218 | { STB0899_DMONMSK1 , 0x27 }, | ||
219 | { STB0899_DMONMSK0 , 0x03 }, | ||
220 | { STB0899_DEMAPVIT , 0x5c }, | ||
221 | { STB0899_PLPARM , 0x19 }, | ||
222 | { STB0899_PDELCTRL , 0x48 }, | ||
223 | { STB0899_PDELCTRL2 , 0x00 }, | ||
224 | { STB0899_BBHCTRL1 , 0x00 }, | ||
225 | { STB0899_BBHCTRL2 , 0x00 }, | ||
226 | { STB0899_HYSTTHRESH , 0x77 }, | ||
227 | { STB0899_MATCSTM , 0x00 }, | ||
228 | { STB0899_MATCSTL , 0x00 }, | ||
229 | { STB0899_UPLCSTM , 0x00 }, | ||
230 | { STB0899_UPLCSTL , 0x00 }, | ||
231 | { STB0899_DFLCSTM , 0x00 }, | ||
232 | { STB0899_DFLCSTL , 0x00 }, | ||
233 | { STB0899_SYNCCST , 0x00 }, | ||
234 | { STB0899_SYNCDCSTM , 0x00 }, | ||
235 | { STB0899_SYNCDCSTL , 0x00 }, | ||
236 | { STB0899_ISI_ENTRY , 0x00 }, | ||
237 | { STB0899_ISI_BIT_EN , 0x00 }, | ||
238 | { STB0899_MATSTRM , 0xf0 }, | ||
239 | { STB0899_MATSTRL , 0x02 }, | ||
240 | { STB0899_UPLSTRM , 0x45 }, | ||
241 | { STB0899_UPLSTRL , 0x60 }, | ||
242 | { STB0899_DFLSTRM , 0xe3 }, | ||
243 | { STB0899_DFLSTRL , 0x00 }, | ||
244 | { STB0899_SYNCSTR , 0x47 }, | ||
245 | { STB0899_SYNCDSTRM , 0x05 }, | ||
246 | { STB0899_SYNCDSTRL , 0x18 }, | ||
247 | { STB0899_CFGPDELSTATUS1 , 0x19 }, | ||
248 | { STB0899_CFGPDELSTATUS2 , 0x2b }, | ||
249 | { STB0899_BBFERRORM , 0x00 }, | ||
250 | { STB0899_BBFERRORL , 0x01 }, | ||
251 | { STB0899_UPKTERRORM , 0x00 }, | ||
252 | { STB0899_UPKTERRORL , 0x00 }, | ||
253 | { 0xffff , 0xff }, | ||
254 | }; | ||
255 | |||
256 | |||
257 | |||
258 | struct stb0899_config az6027_stb0899_config = { | ||
259 | .init_dev = az6027_stb0899_s1_init_1, | ||
260 | .init_s2_demod = stb0899_s2_init_2, | ||
261 | .init_s1_demod = az6027_stb0899_s1_init_3, | ||
262 | .init_s2_fec = stb0899_s2_init_4, | ||
263 | .init_tst = stb0899_s1_init_5, | ||
264 | |||
265 | .demod_address = 0xd0, /* 0x68, 0xd0 >> 1 */ | ||
266 | |||
267 | .xtal_freq = 27000000, | ||
268 | .inversion = IQ_SWAP_ON, /* 1 */ | ||
269 | |||
270 | .lo_clk = 76500000, | ||
271 | .hi_clk = 99000000, | ||
272 | |||
273 | .esno_ave = STB0899_DVBS2_ESNO_AVE, | ||
274 | .esno_quant = STB0899_DVBS2_ESNO_QUANT, | ||
275 | .avframes_coarse = STB0899_DVBS2_AVFRAMES_COARSE, | ||
276 | .avframes_fine = STB0899_DVBS2_AVFRAMES_FINE, | ||
277 | .miss_threshold = STB0899_DVBS2_MISS_THRESHOLD, | ||
278 | .uwp_threshold_acq = STB0899_DVBS2_UWP_THRESHOLD_ACQ, | ||
279 | .uwp_threshold_track = STB0899_DVBS2_UWP_THRESHOLD_TRACK, | ||
280 | .uwp_threshold_sof = STB0899_DVBS2_UWP_THRESHOLD_SOF, | ||
281 | .sof_search_timeout = STB0899_DVBS2_SOF_SEARCH_TIMEOUT, | ||
282 | |||
283 | .btr_nco_bits = STB0899_DVBS2_BTR_NCO_BITS, | ||
284 | .btr_gain_shift_offset = STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET, | ||
285 | .crl_nco_bits = STB0899_DVBS2_CRL_NCO_BITS, | ||
286 | .ldpc_max_iter = STB0899_DVBS2_LDPC_MAX_ITER, | ||
287 | |||
288 | .tuner_get_frequency = stb6100_get_frequency, | ||
289 | .tuner_set_frequency = stb6100_set_frequency, | ||
290 | .tuner_set_bandwidth = stb6100_set_bandwidth, | ||
291 | .tuner_get_bandwidth = stb6100_get_bandwidth, | ||
292 | .tuner_set_rfsiggain = NULL, | ||
293 | }; | ||
294 | |||
295 | struct stb6100_config az6027_stb6100_config = { | ||
296 | .tuner_address = 0xc0, | ||
297 | .refclock = 27000000, | ||
298 | }; | ||
299 | |||
300 | |||
301 | /* check for mutex FIXME */ | ||
302 | int az6027_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen) | ||
303 | { | ||
304 | int ret = -1; | ||
305 | if (mutex_lock_interruptible(&d->usb_mutex)) | ||
306 | return -EAGAIN; | ||
307 | |||
308 | ret = usb_control_msg(d->udev, | ||
309 | usb_rcvctrlpipe(d->udev, 0), | ||
310 | req, | ||
311 | USB_TYPE_VENDOR | USB_DIR_IN, | ||
312 | value, | ||
313 | index, | ||
314 | b, | ||
315 | blen, | ||
316 | 2000); | ||
317 | |||
318 | if (ret < 0) { | ||
319 | warn("usb in operation failed. (%d)", ret); | ||
320 | ret = -EIO; | ||
321 | } else | ||
322 | ret = 0; | ||
323 | |||
324 | deb_xfer("in: req. %02x, val: %04x, ind: %04x, buffer: ", req, value, index); | ||
325 | debug_dump(b, blen, deb_xfer); | ||
326 | |||
327 | mutex_unlock(&d->usb_mutex); | ||
328 | return ret; | ||
329 | } | ||
330 | |||
331 | static int az6027_usb_out_op(struct dvb_usb_device *d, | ||
332 | u8 req, | ||
333 | u16 value, | ||
334 | u16 index, | ||
335 | u8 *b, | ||
336 | int blen) | ||
337 | { | ||
338 | int ret; | ||
339 | |||
340 | deb_xfer("out: req. %02x, val: %04x, ind: %04x, buffer: ", req, value, index); | ||
341 | debug_dump(b, blen, deb_xfer); | ||
342 | |||
343 | if (mutex_lock_interruptible(&d->usb_mutex)) | ||
344 | return -EAGAIN; | ||
345 | |||
346 | ret = usb_control_msg(d->udev, | ||
347 | usb_sndctrlpipe(d->udev, 0), | ||
348 | req, | ||
349 | USB_TYPE_VENDOR | USB_DIR_OUT, | ||
350 | value, | ||
351 | index, | ||
352 | b, | ||
353 | blen, | ||
354 | 2000); | ||
355 | |||
356 | if (ret != blen) { | ||
357 | warn("usb out operation failed. (%d)", ret); | ||
358 | mutex_unlock(&d->usb_mutex); | ||
359 | return -EIO; | ||
360 | } else{ | ||
361 | mutex_unlock(&d->usb_mutex); | ||
362 | return 0; | ||
363 | } | ||
364 | } | ||
365 | |||
366 | static int az6027_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | ||
367 | { | ||
368 | int ret; | ||
369 | u8 req; | ||
370 | u16 value; | ||
371 | u16 index; | ||
372 | int blen; | ||
373 | |||
374 | deb_info("%s %d", __func__, onoff); | ||
375 | |||
376 | req = 0xBC; | ||
377 | value = onoff; | ||
378 | index = 0; | ||
379 | blen = 0; | ||
380 | |||
381 | ret = az6027_usb_out_op(adap->dev, req, value, index, NULL, blen); | ||
382 | if (ret != 0) | ||
383 | warn("usb out operation failed. (%d)", ret); | ||
384 | |||
385 | return ret; | ||
386 | } | ||
387 | |||
388 | /* keys for the enclosed remote control */ | ||
389 | static struct dvb_usb_rc_key az6027_rc_keys[] = { | ||
390 | { 0x01, KEY_1 }, | ||
391 | { 0x02, KEY_2 }, | ||
392 | }; | ||
393 | |||
394 | /* remote control stuff (does not work with my box) */ | ||
395 | static int az6027_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | ||
396 | { | ||
397 | return 0; | ||
398 | } | ||
399 | |||
400 | /* | ||
401 | int az6027_power_ctrl(struct dvb_usb_device *d, int onoff) | ||
402 | { | ||
403 | u8 v = onoff; | ||
404 | return az6027_usb_out_op(d,0xBC,v,3,NULL,1); | ||
405 | } | ||
406 | */ | ||
407 | |||
408 | static int az6027_ci_read_attribute_mem(struct dvb_ca_en50221 *ca, | ||
409 | int slot, | ||
410 | int address) | ||
411 | { | ||
412 | struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; | ||
413 | struct az6027_device_state *state = (struct az6027_device_state *)d->priv; | ||
414 | |||
415 | int ret; | ||
416 | u8 req; | ||
417 | u16 value; | ||
418 | u16 index; | ||
419 | int blen; | ||
420 | u8 b[12]; | ||
421 | |||
422 | if (slot != 0) | ||
423 | return -EINVAL; | ||
424 | |||
425 | mutex_lock(&state->ca_mutex); | ||
426 | |||
427 | req = 0xC1; | ||
428 | value = address; | ||
429 | index = 0; | ||
430 | blen = 1; | ||
431 | |||
432 | ret = az6027_usb_in_op(d, req, value, index, b, blen); | ||
433 | if (ret < 0) { | ||
434 | warn("usb in operation failed. (%d)", ret); | ||
435 | ret = -EINVAL; | ||
436 | } else { | ||
437 | ret = b[0]; | ||
438 | } | ||
439 | |||
440 | mutex_unlock(&state->ca_mutex); | ||
441 | return ret; | ||
442 | } | ||
443 | |||
444 | static int az6027_ci_write_attribute_mem(struct dvb_ca_en50221 *ca, | ||
445 | int slot, | ||
446 | int address, | ||
447 | u8 value) | ||
448 | { | ||
449 | struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; | ||
450 | struct az6027_device_state *state = (struct az6027_device_state *)d->priv; | ||
451 | |||
452 | int ret; | ||
453 | u8 req; | ||
454 | u16 value1; | ||
455 | u16 index; | ||
456 | int blen; | ||
457 | |||
458 | deb_info("%s %d", __func__, slot); | ||
459 | if (slot != 0) | ||
460 | return -EINVAL; | ||
461 | |||
462 | mutex_lock(&state->ca_mutex); | ||
463 | req = 0xC2; | ||
464 | value1 = address; | ||
465 | index = value; | ||
466 | blen = 0; | ||
467 | |||
468 | ret = az6027_usb_out_op(d, req, value1, index, NULL, blen); | ||
469 | if (ret != 0) | ||
470 | warn("usb out operation failed. (%d)", ret); | ||
471 | |||
472 | mutex_unlock(&state->ca_mutex); | ||
473 | return ret; | ||
474 | } | ||
475 | |||
476 | static int az6027_ci_read_cam_control(struct dvb_ca_en50221 *ca, | ||
477 | int slot, | ||
478 | u8 address) | ||
479 | { | ||
480 | struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; | ||
481 | struct az6027_device_state *state = (struct az6027_device_state *)d->priv; | ||
482 | |||
483 | int ret; | ||
484 | u8 req; | ||
485 | u16 value; | ||
486 | u16 index; | ||
487 | int blen; | ||
488 | u8 b[12]; | ||
489 | |||
490 | if (slot != 0) | ||
491 | return -EINVAL; | ||
492 | |||
493 | mutex_lock(&state->ca_mutex); | ||
494 | |||
495 | req = 0xC3; | ||
496 | value = address; | ||
497 | index = 0; | ||
498 | blen = 2; | ||
499 | |||
500 | ret = az6027_usb_in_op(d, req, value, index, b, blen); | ||
501 | if (ret < 0) { | ||
502 | warn("usb in operation failed. (%d)", ret); | ||
503 | ret = -EINVAL; | ||
504 | } else { | ||
505 | if (b[0] == 0) | ||
506 | warn("Read CI IO error"); | ||
507 | |||
508 | ret = b[1]; | ||
509 | deb_info("read cam data = %x from 0x%x", b[1], value); | ||
510 | } | ||
511 | |||
512 | mutex_unlock(&state->ca_mutex); | ||
513 | return ret; | ||
514 | } | ||
515 | |||
516 | static int az6027_ci_write_cam_control(struct dvb_ca_en50221 *ca, | ||
517 | int slot, | ||
518 | u8 address, | ||
519 | u8 value) | ||
520 | { | ||
521 | struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; | ||
522 | struct az6027_device_state *state = (struct az6027_device_state *)d->priv; | ||
523 | |||
524 | int ret; | ||
525 | u8 req; | ||
526 | u16 value1; | ||
527 | u16 index; | ||
528 | int blen; | ||
529 | |||
530 | if (slot != 0) | ||
531 | return -EINVAL; | ||
532 | |||
533 | mutex_lock(&state->ca_mutex); | ||
534 | req = 0xC4; | ||
535 | value1 = address; | ||
536 | index = value; | ||
537 | blen = 0; | ||
538 | |||
539 | ret = az6027_usb_out_op(d, req, value1, index, NULL, blen); | ||
540 | if (ret != 0) { | ||
541 | warn("usb out operation failed. (%d)", ret); | ||
542 | goto failed; | ||
543 | } | ||
544 | |||
545 | failed: | ||
546 | mutex_unlock(&state->ca_mutex); | ||
547 | return ret; | ||
548 | } | ||
549 | |||
550 | static int CI_CamReady(struct dvb_ca_en50221 *ca, int slot) | ||
551 | { | ||
552 | struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; | ||
553 | |||
554 | int ret; | ||
555 | u8 req; | ||
556 | u16 value; | ||
557 | u16 index; | ||
558 | int blen; | ||
559 | u8 b[12]; | ||
560 | |||
561 | req = 0xC8; | ||
562 | value = 0; | ||
563 | index = 0; | ||
564 | blen = 1; | ||
565 | |||
566 | ret = az6027_usb_in_op(d, req, value, index, b, blen); | ||
567 | if (ret < 0) { | ||
568 | warn("usb in operation failed. (%d)", ret); | ||
569 | ret = -EIO; | ||
570 | } else{ | ||
571 | ret = b[0]; | ||
572 | } | ||
573 | return ret; | ||
574 | } | ||
575 | |||
576 | static int az6027_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot) | ||
577 | { | ||
578 | struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; | ||
579 | struct az6027_device_state *state = (struct az6027_device_state *)d->priv; | ||
580 | |||
581 | int ret, i; | ||
582 | u8 req; | ||
583 | u16 value; | ||
584 | u16 index; | ||
585 | int blen; | ||
586 | |||
587 | mutex_lock(&state->ca_mutex); | ||
588 | |||
589 | req = 0xC6; | ||
590 | value = 1; | ||
591 | index = 0; | ||
592 | blen = 0; | ||
593 | |||
594 | ret = az6027_usb_out_op(d, req, value, index, NULL, blen); | ||
595 | if (ret != 0) { | ||
596 | warn("usb out operation failed. (%d)", ret); | ||
597 | goto failed; | ||
598 | } | ||
599 | |||
600 | msleep(500); | ||
601 | req = 0xC6; | ||
602 | value = 0; | ||
603 | index = 0; | ||
604 | blen = 0; | ||
605 | |||
606 | ret = az6027_usb_out_op(d, req, value, index, NULL, blen); | ||
607 | if (ret != 0) { | ||
608 | warn("usb out operation failed. (%d)", ret); | ||
609 | goto failed; | ||
610 | } | ||
611 | |||
612 | for (i = 0; i < 15; i++) { | ||
613 | msleep(100); | ||
614 | |||
615 | if (CI_CamReady(ca, slot)) { | ||
616 | deb_info("CAM Ready"); | ||
617 | break; | ||
618 | } | ||
619 | } | ||
620 | msleep(5000); | ||
621 | |||
622 | failed: | ||
623 | mutex_unlock(&state->ca_mutex); | ||
624 | return ret; | ||
625 | } | ||
626 | |||
627 | static int az6027_ci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot) | ||
628 | { | ||
629 | return 0; | ||
630 | } | ||
631 | |||
632 | static int az6027_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) | ||
633 | { | ||
634 | struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; | ||
635 | struct az6027_device_state *state = (struct az6027_device_state *)d->priv; | ||
636 | |||
637 | int ret; | ||
638 | u8 req; | ||
639 | u16 value; | ||
640 | u16 index; | ||
641 | int blen; | ||
642 | |||
643 | deb_info("%s", __func__); | ||
644 | mutex_lock(&state->ca_mutex); | ||
645 | req = 0xC7; | ||
646 | value = 1; | ||
647 | index = 0; | ||
648 | blen = 0; | ||
649 | |||
650 | ret = az6027_usb_out_op(d, req, value, index, NULL, blen); | ||
651 | if (ret != 0) { | ||
652 | warn("usb out operation failed. (%d)", ret); | ||
653 | goto failed; | ||
654 | } | ||
655 | |||
656 | failed: | ||
657 | mutex_unlock(&state->ca_mutex); | ||
658 | return ret; | ||
659 | } | ||
660 | |||
661 | static int az6027_ci_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open) | ||
662 | { | ||
663 | struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; | ||
664 | struct az6027_device_state *state = (struct az6027_device_state *)d->priv; | ||
665 | int ret; | ||
666 | u8 req; | ||
667 | u16 value; | ||
668 | u16 index; | ||
669 | int blen; | ||
670 | u8 b[12]; | ||
671 | |||
672 | mutex_lock(&state->ca_mutex); | ||
673 | |||
674 | req = 0xC5; | ||
675 | value = 0; | ||
676 | index = 0; | ||
677 | blen = 1; | ||
678 | |||
679 | ret = az6027_usb_in_op(d, req, value, index, b, blen); | ||
680 | if (ret < 0) { | ||
681 | warn("usb in operation failed. (%d)", ret); | ||
682 | ret = -EIO; | ||
683 | } else | ||
684 | ret = 0; | ||
685 | |||
686 | if (b[0] == 0) { | ||
687 | ret = 0; | ||
688 | |||
689 | } else if (b[0] == 1) { | ||
690 | ret = DVB_CA_EN50221_POLL_CAM_PRESENT | | ||
691 | DVB_CA_EN50221_POLL_CAM_READY; | ||
692 | } | ||
693 | |||
694 | mutex_unlock(&state->ca_mutex); | ||
695 | return ret; | ||
696 | } | ||
697 | |||
698 | |||
699 | static void az6027_ci_uninit(struct dvb_usb_device *d) | ||
700 | { | ||
701 | struct az6027_device_state *state; | ||
702 | |||
703 | deb_info("%s", __func__); | ||
704 | |||
705 | if (NULL == d) | ||
706 | return; | ||
707 | |||
708 | state = (struct az6027_device_state *)d->priv; | ||
709 | if (NULL == state) | ||
710 | return; | ||
711 | |||
712 | if (NULL == state->ca.data) | ||
713 | return; | ||
714 | |||
715 | dvb_ca_en50221_release(&state->ca); | ||
716 | |||
717 | memset(&state->ca, 0, sizeof(state->ca)); | ||
718 | } | ||
719 | |||
720 | |||
721 | static int az6027_ci_init(struct dvb_usb_adapter *a) | ||
722 | { | ||
723 | struct dvb_usb_device *d = a->dev; | ||
724 | struct az6027_device_state *state = (struct az6027_device_state *)d->priv; | ||
725 | int ret; | ||
726 | |||
727 | deb_info("%s", __func__); | ||
728 | |||
729 | mutex_init(&state->ca_mutex); | ||
730 | |||
731 | state->ca.owner = THIS_MODULE; | ||
732 | state->ca.read_attribute_mem = az6027_ci_read_attribute_mem; | ||
733 | state->ca.write_attribute_mem = az6027_ci_write_attribute_mem; | ||
734 | state->ca.read_cam_control = az6027_ci_read_cam_control; | ||
735 | state->ca.write_cam_control = az6027_ci_write_cam_control; | ||
736 | state->ca.slot_reset = az6027_ci_slot_reset; | ||
737 | state->ca.slot_shutdown = az6027_ci_slot_shutdown; | ||
738 | state->ca.slot_ts_enable = az6027_ci_slot_ts_enable; | ||
739 | state->ca.poll_slot_status = az6027_ci_poll_slot_status; | ||
740 | state->ca.data = d; | ||
741 | |||
742 | ret = dvb_ca_en50221_init(&a->dvb_adap, | ||
743 | &state->ca, | ||
744 | 0, /* flags */ | ||
745 | 1);/* n_slots */ | ||
746 | if (ret != 0) { | ||
747 | err("Cannot initialize CI: Error %d.", ret); | ||
748 | memset(&state->ca, 0, sizeof(state->ca)); | ||
749 | return ret; | ||
750 | } | ||
751 | |||
752 | deb_info("CI initialized."); | ||
753 | |||
754 | return 0; | ||
755 | } | ||
756 | |||
757 | /* | ||
758 | static int az6027_read_mac_addr(struct dvb_usb_device *d, u8 mac[6]) | ||
759 | { | ||
760 | az6027_usb_in_op(d, 0xb7, 6, 0, &mac[0], 6); | ||
761 | return 0; | ||
762 | } | ||
763 | */ | ||
764 | |||
765 | static int az6027_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) | ||
766 | { | ||
767 | |||
768 | u8 buf; | ||
769 | int ret; | ||
770 | struct dvb_usb_adapter *adap = fe->dvb->priv; | ||
771 | |||
772 | struct i2c_msg i2c_msg = { | ||
773 | .addr = 0x99, | ||
774 | .flags = 0, | ||
775 | .buf = &buf, | ||
776 | .len = 1 | ||
777 | }; | ||
778 | |||
779 | /* | ||
780 | * 2 --18v | ||
781 | * 1 --13v | ||
782 | * 0 --off | ||
783 | */ | ||
784 | switch (voltage) { | ||
785 | case SEC_VOLTAGE_13: | ||
786 | buf = 1; | ||
787 | ret = i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1); | ||
788 | break; | ||
789 | |||
790 | case SEC_VOLTAGE_18: | ||
791 | buf = 2; | ||
792 | ret = i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1); | ||
793 | break; | ||
794 | |||
795 | case SEC_VOLTAGE_OFF: | ||
796 | buf = 0; | ||
797 | ret = i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1); | ||
798 | break; | ||
799 | |||
800 | default: | ||
801 | return -EINVAL; | ||
802 | } | ||
803 | return 0; | ||
804 | } | ||
805 | |||
806 | |||
807 | static int az6027_frontend_poweron(struct dvb_usb_adapter *adap) | ||
808 | { | ||
809 | int ret; | ||
810 | u8 req; | ||
811 | u16 value; | ||
812 | u16 index; | ||
813 | int blen; | ||
814 | |||
815 | req = 0xBC; | ||
816 | value = 1; /* power on */ | ||
817 | index = 3; | ||
818 | blen = 0; | ||
819 | |||
820 | ret = az6027_usb_out_op(adap->dev, req, value, index, NULL, blen); | ||
821 | if (ret != 0) | ||
822 | return -EIO; | ||
823 | |||
824 | return 0; | ||
825 | } | ||
826 | static int az6027_frontend_reset(struct dvb_usb_adapter *adap) | ||
827 | { | ||
828 | int ret; | ||
829 | u8 req; | ||
830 | u16 value; | ||
831 | u16 index; | ||
832 | int blen; | ||
833 | |||
834 | /* reset demodulator */ | ||
835 | req = 0xC0; | ||
836 | value = 1; /* high */ | ||
837 | index = 3; | ||
838 | blen = 0; | ||
839 | |||
840 | ret = az6027_usb_out_op(adap->dev, req, value, index, NULL, blen); | ||
841 | if (ret != 0) | ||
842 | return -EIO; | ||
843 | |||
844 | req = 0xC0; | ||
845 | value = 0; /* low */ | ||
846 | index = 3; | ||
847 | blen = 0; | ||
848 | msleep_interruptible(200); | ||
849 | |||
850 | ret = az6027_usb_out_op(adap->dev, req, value, index, NULL, blen); | ||
851 | if (ret != 0) | ||
852 | return -EIO; | ||
853 | |||
854 | msleep_interruptible(200); | ||
855 | |||
856 | req = 0xC0; | ||
857 | value = 1; /*high */ | ||
858 | index = 3; | ||
859 | blen = 0; | ||
860 | |||
861 | ret = az6027_usb_out_op(adap->dev, req, value, index, NULL, blen); | ||
862 | if (ret != 0) | ||
863 | return -EIO; | ||
864 | |||
865 | msleep_interruptible(200); | ||
866 | return 0; | ||
867 | } | ||
868 | |||
869 | static int az6027_frontend_tsbypass(struct dvb_usb_adapter *adap, int onoff) | ||
870 | { | ||
871 | int ret; | ||
872 | u8 req; | ||
873 | u16 value; | ||
874 | u16 index; | ||
875 | int blen; | ||
876 | |||
877 | /* TS passthrough */ | ||
878 | req = 0xC7; | ||
879 | value = onoff; | ||
880 | index = 0; | ||
881 | blen = 0; | ||
882 | |||
883 | ret = az6027_usb_out_op(adap->dev, req, value, index, NULL, blen); | ||
884 | if (ret != 0) | ||
885 | return -EIO; | ||
886 | |||
887 | return 0; | ||
888 | } | ||
889 | |||
890 | static int az6027_frontend_attach(struct dvb_usb_adapter *adap) | ||
891 | { | ||
892 | |||
893 | az6027_frontend_poweron(adap); | ||
894 | az6027_frontend_reset(adap); | ||
895 | |||
896 | deb_info("adap = %p, dev = %p\n", adap, adap->dev); | ||
897 | adap->fe = stb0899_attach(&az6027_stb0899_config, &adap->dev->i2c_adap); | ||
898 | |||
899 | if (adap->fe) { | ||
900 | deb_info("found STB0899 DVB-S/DVB-S2 frontend @0x%02x", az6027_stb0899_config.demod_address); | ||
901 | if (stb6100_attach(adap->fe, &az6027_stb6100_config, &adap->dev->i2c_adap)) { | ||
902 | deb_info("found STB6100 DVB-S/DVB-S2 frontend @0x%02x", az6027_stb6100_config.tuner_address); | ||
903 | adap->fe->ops.set_voltage = az6027_set_voltage; | ||
904 | az6027_ci_init(adap); | ||
905 | } else { | ||
906 | adap->fe = NULL; | ||
907 | } | ||
908 | } else | ||
909 | warn("no front-end attached\n"); | ||
910 | |||
911 | az6027_frontend_tsbypass(adap, 0); | ||
912 | |||
913 | return 0; | ||
914 | } | ||
915 | |||
916 | static struct dvb_usb_device_properties az6027_properties; | ||
917 | |||
918 | static void az6027_usb_disconnect(struct usb_interface *intf) | ||
919 | { | ||
920 | struct dvb_usb_device *d = usb_get_intfdata(intf); | ||
921 | az6027_ci_uninit(d); | ||
922 | dvb_usb_device_exit(intf); | ||
923 | } | ||
924 | |||
925 | |||
926 | static int az6027_usb_probe(struct usb_interface *intf, | ||
927 | const struct usb_device_id *id) | ||
928 | { | ||
929 | return dvb_usb_device_init(intf, | ||
930 | &az6027_properties, | ||
931 | THIS_MODULE, | ||
932 | NULL, | ||
933 | adapter_nr); | ||
934 | } | ||
935 | |||
936 | /* I2C */ | ||
937 | static int az6027_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) | ||
938 | { | ||
939 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
940 | int i = 0, j = 0, len = 0; | ||
941 | int ret; | ||
942 | u16 index; | ||
943 | u16 value; | ||
944 | int length; | ||
945 | u8 req; | ||
946 | u8 data[256]; | ||
947 | |||
948 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
949 | return -EAGAIN; | ||
950 | |||
951 | if (num > 2) | ||
952 | warn("more than 2 i2c messages at a time is not handled yet. TODO."); | ||
953 | |||
954 | for (i = 0; i < num; i++) { | ||
955 | |||
956 | if (msg[i].addr == 0x99) { | ||
957 | req = 0xBE; | ||
958 | index = 0; | ||
959 | value = msg[i].buf[0] & 0x00ff; | ||
960 | length = 1; | ||
961 | az6027_usb_out_op(d, req, value, index, data, length); | ||
962 | } | ||
963 | |||
964 | if (msg[i].addr == 0xd0) { | ||
965 | /* write/read request */ | ||
966 | if (i + 1 < num && (msg[i + 1].flags & I2C_M_RD)) { | ||
967 | req = 0xB9; | ||
968 | index = (((msg[i].buf[0] << 8) & 0xff00) | (msg[i].buf[1] & 0x00ff)); | ||
969 | value = msg[i].addr + (msg[i].len << 8); | ||
970 | length = msg[i + 1].len + 6; | ||
971 | ret = az6027_usb_in_op(d, req, value, index, data, length); | ||
972 | len = msg[i + 1].len; | ||
973 | for (j = 0; j < len; j++) | ||
974 | msg[i + 1].buf[j] = data[j + 5]; | ||
975 | |||
976 | i++; | ||
977 | } else { | ||
978 | |||
979 | if (msg[i].addr == 0xd0) { | ||
980 | /* demod 16bit addr */ | ||
981 | req = 0xBD; | ||
982 | index = (((msg[i].buf[0] << 8) & 0xff00) | (msg[i].buf[1] & 0x00ff)); | ||
983 | value = msg[i].addr + (2 << 8); | ||
984 | length = msg[i].len - 2; | ||
985 | len = msg[i].len - 2; | ||
986 | for (j = 0; j < len; j++) | ||
987 | data[j] = msg[i].buf[j + 2]; | ||
988 | |||
989 | } | ||
990 | az6027_usb_out_op(d, req, value, index, data, length); | ||
991 | } | ||
992 | } | ||
993 | |||
994 | if (msg[i].addr == 0xc0) { | ||
995 | if (msg[i].flags & I2C_M_RD) { | ||
996 | |||
997 | req = 0xB9; | ||
998 | index = 0x0; | ||
999 | value = msg[i].addr; | ||
1000 | length = msg[i].len + 6; | ||
1001 | ret = az6027_usb_in_op(d, req, value, index, data, length); | ||
1002 | len = msg[i].len; | ||
1003 | for (j = 0; j < len; j++) | ||
1004 | msg[i].buf[j] = data[j + 5]; | ||
1005 | |||
1006 | } else { | ||
1007 | |||
1008 | req = 0xBD; | ||
1009 | index = msg[i].buf[0] & 0x00FF; | ||
1010 | value = msg[i].addr + (1 << 8); | ||
1011 | length = msg[i].len - 1; | ||
1012 | len = msg[i].len - 1; | ||
1013 | |||
1014 | for (j = 0; j < len; j++) | ||
1015 | data[j] = msg[i].buf[j + 1]; | ||
1016 | |||
1017 | az6027_usb_out_op(d, req, value, index, data, length); | ||
1018 | } | ||
1019 | } | ||
1020 | } | ||
1021 | mutex_unlock(&d->i2c_mutex); | ||
1022 | |||
1023 | return i; | ||
1024 | } | ||
1025 | |||
1026 | |||
1027 | static u32 az6027_i2c_func(struct i2c_adapter *adapter) | ||
1028 | { | ||
1029 | return I2C_FUNC_I2C; | ||
1030 | } | ||
1031 | |||
1032 | static struct i2c_algorithm az6027_i2c_algo = { | ||
1033 | .master_xfer = az6027_i2c_xfer, | ||
1034 | .functionality = az6027_i2c_func, | ||
1035 | }; | ||
1036 | |||
1037 | int az6027_identify_state(struct usb_device *udev, | ||
1038 | struct dvb_usb_device_properties *props, | ||
1039 | struct dvb_usb_device_description **desc, | ||
1040 | int *cold) | ||
1041 | { | ||
1042 | u8 b[16]; | ||
1043 | s16 ret = usb_control_msg(udev, | ||
1044 | usb_rcvctrlpipe(udev, 0), | ||
1045 | 0xb7, | ||
1046 | USB_TYPE_VENDOR | USB_DIR_IN, | ||
1047 | 6, | ||
1048 | 0, | ||
1049 | b, | ||
1050 | 6, | ||
1051 | USB_CTRL_GET_TIMEOUT); | ||
1052 | |||
1053 | *cold = ret <= 0; | ||
1054 | |||
1055 | deb_info("cold: %d\n", *cold); | ||
1056 | return 0; | ||
1057 | } | ||
1058 | |||
1059 | |||
1060 | static struct usb_device_id az6027_usb_table[] = { | ||
1061 | { USB_DEVICE(USB_VID_AZUREWAVE, USB_PID_AZUREWAVE_AZ6027) }, | ||
1062 | { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_DVBS2CI) }, | ||
1063 | { USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_HDCI) }, | ||
1064 | { }, | ||
1065 | }; | ||
1066 | |||
1067 | MODULE_DEVICE_TABLE(usb, az6027_usb_table); | ||
1068 | |||
1069 | static struct dvb_usb_device_properties az6027_properties = { | ||
1070 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
1071 | .usb_ctrl = CYPRESS_FX2, | ||
1072 | .firmware = "dvb-usb-az6027-03.fw", | ||
1073 | .no_reconnect = 1, | ||
1074 | |||
1075 | .size_of_priv = sizeof(struct az6027_device_state), | ||
1076 | .identify_state = az6027_identify_state, | ||
1077 | .num_adapters = 1, | ||
1078 | .adapter = { | ||
1079 | { | ||
1080 | .streaming_ctrl = az6027_streaming_ctrl, | ||
1081 | .frontend_attach = az6027_frontend_attach, | ||
1082 | |||
1083 | /* parameter for the MPEG2-data transfer */ | ||
1084 | .stream = { | ||
1085 | .type = USB_BULK, | ||
1086 | .count = 10, | ||
1087 | .endpoint = 0x02, | ||
1088 | .u = { | ||
1089 | .bulk = { | ||
1090 | .buffersize = 4096, | ||
1091 | } | ||
1092 | } | ||
1093 | }, | ||
1094 | } | ||
1095 | }, | ||
1096 | /* | ||
1097 | .power_ctrl = az6027_power_ctrl, | ||
1098 | .read_mac_address = az6027_read_mac_addr, | ||
1099 | */ | ||
1100 | .rc_key_map = az6027_rc_keys, | ||
1101 | .rc_key_map_size = ARRAY_SIZE(az6027_rc_keys), | ||
1102 | .rc_interval = 400, | ||
1103 | .rc_query = az6027_rc_query, | ||
1104 | .i2c_algo = &az6027_i2c_algo, | ||
1105 | |||
1106 | .num_device_descs = 1, | ||
1107 | .devices = { | ||
1108 | { | ||
1109 | .name = "AZUREWAVE DVB-S/S2 USB2.0 (AZ6027)", | ||
1110 | .cold_ids = { &az6027_usb_table[0], NULL }, | ||
1111 | .warm_ids = { NULL }, | ||
1112 | }, | ||
1113 | { NULL }, | ||
1114 | } | ||
1115 | }; | ||
1116 | |||
1117 | /* usb specific object needed to register this driver with the usb subsystem */ | ||
1118 | static struct usb_driver az6027_usb_driver = { | ||
1119 | .name = "dvb_usb_az6027", | ||
1120 | .probe = az6027_usb_probe, | ||
1121 | .disconnect = az6027_usb_disconnect, | ||
1122 | .id_table = az6027_usb_table, | ||
1123 | }; | ||
1124 | |||
1125 | /* module stuff */ | ||
1126 | static int __init az6027_usb_module_init(void) | ||
1127 | { | ||
1128 | int result; | ||
1129 | |||
1130 | result = usb_register(&az6027_usb_driver); | ||
1131 | if (result) { | ||
1132 | err("usb_register failed. (%d)", result); | ||
1133 | return result; | ||
1134 | } | ||
1135 | |||
1136 | return 0; | ||
1137 | } | ||
1138 | |||
1139 | static void __exit az6027_usb_module_exit(void) | ||
1140 | { | ||
1141 | /* deregister this driver from the USB subsystem */ | ||
1142 | usb_deregister(&az6027_usb_driver); | ||
1143 | } | ||
1144 | |||
1145 | module_init(az6027_usb_module_init); | ||
1146 | module_exit(az6027_usb_module_exit); | ||
1147 | |||
1148 | MODULE_AUTHOR("Adams Xu <Adams.xu@azwave.com.cn>"); | ||
1149 | MODULE_DESCRIPTION("Driver for AZUREWAVE DVB-S/S2 USB2.0 (AZ6027)"); | ||
1150 | MODULE_VERSION("1.0"); | ||
1151 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/az6027.h b/drivers/media/dvb/dvb-usb/az6027.h new file mode 100644 index 000000000000..f3afe17f3f3d --- /dev/null +++ b/drivers/media/dvb/dvb-usb/az6027.h | |||
@@ -0,0 +1,14 @@ | |||
1 | #ifndef _DVB_USB_VP6027_H_ | ||
2 | #define _DVB_USB_VP6027_H_ | ||
3 | |||
4 | #define DVB_USB_LOG_PREFIX "az6027" | ||
5 | #include "dvb-usb.h" | ||
6 | |||
7 | |||
8 | extern int dvb_usb_az6027_debug; | ||
9 | #define deb_info(args...) dprintk(dvb_usb_az6027_debug, 0x01, args) | ||
10 | #define deb_xfer(args...) dprintk(dvb_usb_az6027_debug, 0x02, args) | ||
11 | #define deb_rc(args...) dprintk(dvb_usb_az6027_debug, 0x04, args) | ||
12 | #define deb_fe(args...) dprintk(dvb_usb_az6027_debug, 0x08, args) | ||
13 | |||
14 | #endif | ||
diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index 05fb28e9c69e..a7b8405c291e 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c | |||
@@ -1184,6 +1184,9 @@ static struct atbm8830_config mygica_d689_atbm8830_cfg = { | |||
1184 | .osc_clk_freq = 30400, /* in kHz */ | 1184 | .osc_clk_freq = 30400, /* in kHz */ |
1185 | .if_freq = 0, /* zero IF */ | 1185 | .if_freq = 0, /* zero IF */ |
1186 | .zif_swap_iq = 1, | 1186 | .zif_swap_iq = 1, |
1187 | .agc_min = 0x2E, | ||
1188 | .agc_max = 0x90, | ||
1189 | .agc_hold_loop = 0, | ||
1187 | }; | 1190 | }; |
1188 | 1191 | ||
1189 | static int cxusb_mygica_d689_frontend_attach(struct dvb_usb_adapter *adap) | 1192 | static int cxusb_mygica_d689_frontend_attach(struct dvb_usb_adapter *adap) |
diff --git a/drivers/media/dvb/dvb-usb/dib0700.h b/drivers/media/dvb/dvb-usb/dib0700.h index 495a90577c5f..83fc24a6c31a 100644 --- a/drivers/media/dvb/dvb-usb/dib0700.h +++ b/drivers/media/dvb/dvb-usb/dib0700.h | |||
@@ -42,7 +42,6 @@ struct dib0700_state { | |||
42 | u16 mt2060_if1[2]; | 42 | u16 mt2060_if1[2]; |
43 | u8 rc_toggle; | 43 | u8 rc_toggle; |
44 | u8 rc_counter; | 44 | u8 rc_counter; |
45 | u8 rc_func_version; | ||
46 | u8 is_dib7000pc; | 45 | u8 is_dib7000pc; |
47 | u8 fw_use_new_i2c_api; | 46 | u8 fw_use_new_i2c_api; |
48 | u8 disable_streaming_master_mode; | 47 | u8 disable_streaming_master_mode; |
diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c index 0d3c9a9a33be..4f961d2d1817 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_core.c +++ b/drivers/media/dvb/dvb-usb/dib0700_core.c | |||
@@ -471,14 +471,209 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | |||
471 | return dib0700_ctrl_wr(adap->dev, b, 4); | 471 | return dib0700_ctrl_wr(adap->dev, b, 4); |
472 | } | 472 | } |
473 | 473 | ||
474 | /* Number of keypresses to ignore before start repeating */ | ||
475 | #define RC_REPEAT_DELAY_V1_20 10 | ||
476 | |||
477 | /* This is the structure of the RC response packet starting in firmware 1.20 */ | ||
478 | struct dib0700_rc_response { | ||
479 | u8 report_id; | ||
480 | u8 data_state; | ||
481 | u16 system; | ||
482 | u8 data; | ||
483 | u8 not_data; | ||
484 | }; | ||
485 | #define RC_MSG_SIZE_V1_20 6 | ||
486 | |||
487 | static void dib0700_rc_urb_completion(struct urb *purb) | ||
488 | { | ||
489 | struct dvb_usb_device *d = purb->context; | ||
490 | struct dvb_usb_rc_key *keymap; | ||
491 | struct dib0700_state *st; | ||
492 | struct dib0700_rc_response poll_reply; | ||
493 | u8 *buf; | ||
494 | int found = 0; | ||
495 | u32 event; | ||
496 | int state; | ||
497 | int i; | ||
498 | |||
499 | deb_info("%s()\n", __func__); | ||
500 | if (d == NULL) | ||
501 | return; | ||
502 | |||
503 | if (d->rc_input_dev == NULL) { | ||
504 | /* This will occur if disable_rc_polling=1 */ | ||
505 | usb_free_urb(purb); | ||
506 | return; | ||
507 | } | ||
508 | |||
509 | keymap = d->props.rc_key_map; | ||
510 | st = d->priv; | ||
511 | buf = (u8 *)purb->transfer_buffer; | ||
512 | |||
513 | if (purb->status < 0) { | ||
514 | deb_info("discontinuing polling\n"); | ||
515 | usb_free_urb(purb); | ||
516 | return; | ||
517 | } | ||
518 | |||
519 | if (purb->actual_length != RC_MSG_SIZE_V1_20) { | ||
520 | deb_info("malformed rc msg size=%d\n", purb->actual_length); | ||
521 | goto resubmit; | ||
522 | } | ||
523 | |||
524 | /* Set initial results in case we exit the function early */ | ||
525 | event = 0; | ||
526 | state = REMOTE_NO_KEY_PRESSED; | ||
527 | |||
528 | deb_data("IR raw %02X %02X %02X %02X %02X %02X (len %d)\n", buf[0], | ||
529 | buf[1], buf[2], buf[3], buf[4], buf[5], purb->actual_length); | ||
530 | |||
531 | switch (dvb_usb_dib0700_ir_proto) { | ||
532 | case 0: | ||
533 | /* NEC Protocol */ | ||
534 | poll_reply.report_id = 0; | ||
535 | poll_reply.data_state = 1; | ||
536 | poll_reply.system = buf[2]; | ||
537 | poll_reply.data = buf[4]; | ||
538 | poll_reply.not_data = buf[5]; | ||
539 | |||
540 | /* NEC protocol sends repeat code as 0 0 0 FF */ | ||
541 | if ((poll_reply.system == 0x00) && (poll_reply.data == 0x00) | ||
542 | && (poll_reply.not_data == 0xff)) { | ||
543 | poll_reply.data_state = 2; | ||
544 | break; | ||
545 | } | ||
546 | break; | ||
547 | default: | ||
548 | /* RC5 Protocol */ | ||
549 | poll_reply.report_id = buf[0]; | ||
550 | poll_reply.data_state = buf[1]; | ||
551 | poll_reply.system = (buf[2] << 8) | buf[3]; | ||
552 | poll_reply.data = buf[4]; | ||
553 | poll_reply.not_data = buf[5]; | ||
554 | break; | ||
555 | } | ||
556 | |||
557 | if ((poll_reply.data + poll_reply.not_data) != 0xff) { | ||
558 | /* Key failed integrity check */ | ||
559 | err("key failed integrity check: %04x %02x %02x", | ||
560 | poll_reply.system, | ||
561 | poll_reply.data, poll_reply.not_data); | ||
562 | goto resubmit; | ||
563 | } | ||
564 | |||
565 | deb_data("rid=%02x ds=%02x sm=%04x d=%02x nd=%02x\n", | ||
566 | poll_reply.report_id, poll_reply.data_state, | ||
567 | poll_reply.system, poll_reply.data, poll_reply.not_data); | ||
568 | |||
569 | /* Find the key in the map */ | ||
570 | for (i = 0; i < d->props.rc_key_map_size; i++) { | ||
571 | if (rc5_custom(&keymap[i]) == (poll_reply.system & 0xff) && | ||
572 | rc5_data(&keymap[i]) == poll_reply.data) { | ||
573 | event = keymap[i].event; | ||
574 | found = 1; | ||
575 | break; | ||
576 | } | ||
577 | } | ||
578 | |||
579 | if (found == 0) { | ||
580 | err("Unknown remote controller key: %04x %02x %02x", | ||
581 | poll_reply.system, poll_reply.data, poll_reply.not_data); | ||
582 | d->last_event = 0; | ||
583 | goto resubmit; | ||
584 | } | ||
585 | |||
586 | if (poll_reply.data_state == 1) { | ||
587 | /* New key hit */ | ||
588 | st->rc_counter = 0; | ||
589 | event = keymap[i].event; | ||
590 | state = REMOTE_KEY_PRESSED; | ||
591 | d->last_event = keymap[i].event; | ||
592 | } else if (poll_reply.data_state == 2) { | ||
593 | /* Key repeated */ | ||
594 | st->rc_counter++; | ||
595 | |||
596 | /* prevents unwanted double hits */ | ||
597 | if (st->rc_counter > RC_REPEAT_DELAY_V1_20) { | ||
598 | event = d->last_event; | ||
599 | state = REMOTE_KEY_PRESSED; | ||
600 | st->rc_counter = RC_REPEAT_DELAY_V1_20; | ||
601 | } | ||
602 | } else { | ||
603 | err("Unknown data state [%d]", poll_reply.data_state); | ||
604 | } | ||
605 | |||
606 | switch (state) { | ||
607 | case REMOTE_NO_KEY_PRESSED: | ||
608 | break; | ||
609 | case REMOTE_KEY_PRESSED: | ||
610 | deb_info("key pressed\n"); | ||
611 | d->last_event = event; | ||
612 | case REMOTE_KEY_REPEAT: | ||
613 | deb_info("key repeated\n"); | ||
614 | input_event(d->rc_input_dev, EV_KEY, event, 1); | ||
615 | input_sync(d->rc_input_dev); | ||
616 | input_event(d->rc_input_dev, EV_KEY, d->last_event, 0); | ||
617 | input_sync(d->rc_input_dev); | ||
618 | break; | ||
619 | default: | ||
620 | break; | ||
621 | } | ||
622 | |||
623 | resubmit: | ||
624 | /* Clean the buffer before we requeue */ | ||
625 | memset(purb->transfer_buffer, 0, RC_MSG_SIZE_V1_20); | ||
626 | |||
627 | /* Requeue URB */ | ||
628 | usb_submit_urb(purb, GFP_ATOMIC); | ||
629 | } | ||
630 | |||
474 | int dib0700_rc_setup(struct dvb_usb_device *d) | 631 | int dib0700_rc_setup(struct dvb_usb_device *d) |
475 | { | 632 | { |
633 | struct dib0700_state *st = d->priv; | ||
476 | u8 rc_setup[3] = {REQUEST_SET_RC, dvb_usb_dib0700_ir_proto, 0}; | 634 | u8 rc_setup[3] = {REQUEST_SET_RC, dvb_usb_dib0700_ir_proto, 0}; |
477 | int i = dib0700_ctrl_wr(d, rc_setup, 3); | 635 | struct urb *purb; |
636 | int ret; | ||
637 | int i; | ||
638 | |||
639 | if (d->props.rc_key_map == NULL) | ||
640 | return 0; | ||
641 | |||
642 | /* Set the IR mode */ | ||
643 | i = dib0700_ctrl_wr(d, rc_setup, 3); | ||
478 | if (i<0) { | 644 | if (i<0) { |
479 | err("ir protocol setup failed"); | 645 | err("ir protocol setup failed"); |
480 | return -1; | 646 | return -1; |
481 | } | 647 | } |
648 | |||
649 | if (st->fw_version < 0x10200) | ||
650 | return 0; | ||
651 | |||
652 | /* Starting in firmware 1.20, the RC info is provided on a bulk pipe */ | ||
653 | purb = usb_alloc_urb(0, GFP_KERNEL); | ||
654 | if (purb == NULL) { | ||
655 | err("rc usb alloc urb failed\n"); | ||
656 | return -1; | ||
657 | } | ||
658 | |||
659 | purb->transfer_buffer = kzalloc(RC_MSG_SIZE_V1_20, GFP_KERNEL); | ||
660 | if (purb->transfer_buffer == NULL) { | ||
661 | err("rc kzalloc failed\n"); | ||
662 | usb_free_urb(purb); | ||
663 | return -1; | ||
664 | } | ||
665 | |||
666 | purb->status = -EINPROGRESS; | ||
667 | usb_fill_bulk_urb(purb, d->udev, usb_rcvbulkpipe(d->udev, 1), | ||
668 | purb->transfer_buffer, RC_MSG_SIZE_V1_20, | ||
669 | dib0700_rc_urb_completion, d); | ||
670 | |||
671 | ret = usb_submit_urb(purb, GFP_ATOMIC); | ||
672 | if (ret != 0) { | ||
673 | err("rc submit urb failed\n"); | ||
674 | return -1; | ||
675 | } | ||
676 | |||
482 | return 0; | 677 | return 0; |
483 | } | 678 | } |
484 | 679 | ||
diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index 44972d01bbd0..34eab05afc6c 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c | |||
@@ -472,20 +472,25 @@ static u8 rc_request[] = { REQUEST_POLL_RC, 0 }; | |||
472 | 472 | ||
473 | /* Number of keypresses to ignore before start repeating */ | 473 | /* Number of keypresses to ignore before start repeating */ |
474 | #define RC_REPEAT_DELAY 6 | 474 | #define RC_REPEAT_DELAY 6 |
475 | #define RC_REPEAT_DELAY_V1_20 10 | ||
476 | 475 | ||
477 | 476 | static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | |
478 | |||
479 | /* Used by firmware versions < 1.20 (deprecated) */ | ||
480 | static int dib0700_rc_query_legacy(struct dvb_usb_device *d, u32 *event, | ||
481 | int *state) | ||
482 | { | 477 | { |
483 | u8 key[4]; | 478 | u8 key[4]; |
484 | int i; | 479 | int i; |
485 | struct dvb_usb_rc_key *keymap = d->props.rc_key_map; | 480 | struct dvb_usb_rc_key *keymap = d->props.rc_key_map; |
486 | struct dib0700_state *st = d->priv; | 481 | struct dib0700_state *st = d->priv; |
482 | |||
487 | *event = 0; | 483 | *event = 0; |
488 | *state = REMOTE_NO_KEY_PRESSED; | 484 | *state = REMOTE_NO_KEY_PRESSED; |
485 | |||
486 | if (st->fw_version >= 0x10200) { | ||
487 | /* For 1.20 firmware , We need to keep the RC polling | ||
488 | callback so we can reuse the input device setup in | ||
489 | dvb-usb-remote.c. However, the actual work is being done | ||
490 | in the bulk URB completion handler. */ | ||
491 | return 0; | ||
492 | } | ||
493 | |||
489 | i=dib0700_ctrl_rd(d,rc_request,2,key,4); | 494 | i=dib0700_ctrl_rd(d,rc_request,2,key,4); |
490 | if (i<=0) { | 495 | if (i<=0) { |
491 | err("RC Query Failed"); | 496 | err("RC Query Failed"); |
@@ -557,149 +562,6 @@ static int dib0700_rc_query_legacy(struct dvb_usb_device *d, u32 *event, | |||
557 | return 0; | 562 | return 0; |
558 | } | 563 | } |
559 | 564 | ||
560 | /* This is the structure of the RC response packet starting in firmware 1.20 */ | ||
561 | struct dib0700_rc_response { | ||
562 | u8 report_id; | ||
563 | u8 data_state; | ||
564 | u16 system; | ||
565 | u8 data; | ||
566 | u8 not_data; | ||
567 | }; | ||
568 | |||
569 | /* This supports the new IR response format for firmware v1.20 */ | ||
570 | static int dib0700_rc_query_v1_20(struct dvb_usb_device *d, u32 *event, | ||
571 | int *state) | ||
572 | { | ||
573 | struct dvb_usb_rc_key *keymap = d->props.rc_key_map; | ||
574 | struct dib0700_state *st = d->priv; | ||
575 | struct dib0700_rc_response poll_reply; | ||
576 | u8 buf[6]; | ||
577 | int i; | ||
578 | int status; | ||
579 | int actlen; | ||
580 | int found = 0; | ||
581 | |||
582 | /* Set initial results in case we exit the function early */ | ||
583 | *event = 0; | ||
584 | *state = REMOTE_NO_KEY_PRESSED; | ||
585 | |||
586 | /* Firmware v1.20 provides RC data via bulk endpoint 1 */ | ||
587 | status = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev, 1), buf, | ||
588 | sizeof(buf), &actlen, 50); | ||
589 | if (status < 0) { | ||
590 | /* No data available (meaning no key press) */ | ||
591 | return 0; | ||
592 | } | ||
593 | |||
594 | |||
595 | switch (dvb_usb_dib0700_ir_proto) { | ||
596 | case 0: | ||
597 | poll_reply.report_id = 0; | ||
598 | poll_reply.data_state = 1; | ||
599 | poll_reply.system = buf[2]; | ||
600 | poll_reply.data = buf[4]; | ||
601 | poll_reply.not_data = buf[5]; | ||
602 | |||
603 | /* NEC protocol sends repeat code as 0 0 0 FF */ | ||
604 | if ((poll_reply.system == 0x00) && (poll_reply.data == 0x00) | ||
605 | && (poll_reply.not_data == 0xff)) { | ||
606 | poll_reply.data_state = 2; | ||
607 | break; | ||
608 | } | ||
609 | break; | ||
610 | default: | ||
611 | if (actlen != sizeof(buf)) { | ||
612 | /* We didn't get back the 6 byte message we expected */ | ||
613 | err("Unexpected RC response size [%d]", actlen); | ||
614 | return -1; | ||
615 | } | ||
616 | |||
617 | poll_reply.report_id = buf[0]; | ||
618 | poll_reply.data_state = buf[1]; | ||
619 | poll_reply.system = (buf[2] << 8) | buf[3]; | ||
620 | poll_reply.data = buf[4]; | ||
621 | poll_reply.not_data = buf[5]; | ||
622 | |||
623 | break; | ||
624 | } | ||
625 | |||
626 | if ((poll_reply.data + poll_reply.not_data) != 0xff) { | ||
627 | /* Key failed integrity check */ | ||
628 | err("key failed integrity check: %04x %02x %02x", | ||
629 | poll_reply.system, | ||
630 | poll_reply.data, poll_reply.not_data); | ||
631 | return -1; | ||
632 | } | ||
633 | |||
634 | |||
635 | /* Find the key in the map */ | ||
636 | for (i = 0; i < d->props.rc_key_map_size; i++) { | ||
637 | if (rc5_custom(&keymap[i]) == (poll_reply.system & 0xff) && | ||
638 | rc5_data(&keymap[i]) == poll_reply.data) { | ||
639 | *event = keymap[i].event; | ||
640 | found = 1; | ||
641 | break; | ||
642 | } | ||
643 | } | ||
644 | |||
645 | if (found == 0) { | ||
646 | err("Unknown remote controller key: %04x %02x %02x", | ||
647 | poll_reply.system, | ||
648 | poll_reply.data, poll_reply.not_data); | ||
649 | d->last_event = 0; | ||
650 | return 0; | ||
651 | } | ||
652 | |||
653 | if (poll_reply.data_state == 1) { | ||
654 | /* New key hit */ | ||
655 | st->rc_counter = 0; | ||
656 | *event = keymap[i].event; | ||
657 | *state = REMOTE_KEY_PRESSED; | ||
658 | d->last_event = keymap[i].event; | ||
659 | } else if (poll_reply.data_state == 2) { | ||
660 | /* Key repeated */ | ||
661 | st->rc_counter++; | ||
662 | |||
663 | /* prevents unwanted double hits */ | ||
664 | if (st->rc_counter > RC_REPEAT_DELAY_V1_20) { | ||
665 | *event = d->last_event; | ||
666 | *state = REMOTE_KEY_PRESSED; | ||
667 | st->rc_counter = RC_REPEAT_DELAY_V1_20; | ||
668 | } | ||
669 | } else { | ||
670 | err("Unknown data state [%d]", poll_reply.data_state); | ||
671 | } | ||
672 | |||
673 | return 0; | ||
674 | } | ||
675 | |||
676 | static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | ||
677 | { | ||
678 | struct dib0700_state *st = d->priv; | ||
679 | |||
680 | /* Because some people may have improperly named firmware files, | ||
681 | let's figure out whether to use the new firmware call or the legacy | ||
682 | call based on the firmware version embedded in the file */ | ||
683 | if (st->rc_func_version == 0) { | ||
684 | u32 hwver, romver, ramver, fwtype; | ||
685 | int ret = dib0700_get_version(d, &hwver, &romver, &ramver, | ||
686 | &fwtype); | ||
687 | if (ret < 0) { | ||
688 | err("Could not determine version info"); | ||
689 | return -1; | ||
690 | } | ||
691 | if (ramver < 0x10200) | ||
692 | st->rc_func_version = 1; | ||
693 | else | ||
694 | st->rc_func_version = 2; | ||
695 | } | ||
696 | |||
697 | if (st->rc_func_version == 2) | ||
698 | return dib0700_rc_query_v1_20(d, event, state); | ||
699 | else | ||
700 | return dib0700_rc_query_legacy(d, event, state); | ||
701 | } | ||
702 | |||
703 | static struct dvb_usb_rc_key dib0700_rc_keys[] = { | 565 | static struct dvb_usb_rc_key dib0700_rc_keys[] = { |
704 | /* Key codes for the tiny Pinnacle remote*/ | 566 | /* Key codes for the tiny Pinnacle remote*/ |
705 | { 0x0700, KEY_MUTE }, | 567 | { 0x0700, KEY_MUTE }, |
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index bc3581d58ced..ae8b57acfe05 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h | |||
@@ -64,6 +64,8 @@ | |||
64 | #define USB_VID_HUMAX_COEX 0x10b9 | 64 | #define USB_VID_HUMAX_COEX 0x10b9 |
65 | #define USB_VID_774 0x7a69 | 65 | #define USB_VID_774 0x7a69 |
66 | #define USB_VID_EVOLUTEPC 0x1e59 | 66 | #define USB_VID_EVOLUTEPC 0x1e59 |
67 | #define USB_VID_AZUREWAVE 0x13d3 | ||
68 | #define USB_VID_TECHNISAT 0x14f7 | ||
67 | 69 | ||
68 | /* Product IDs */ | 70 | /* Product IDs */ |
69 | #define USB_PID_ADSTECH_USB2_COLD 0xa333 | 71 | #define USB_PID_ADSTECH_USB2_COLD 0xa333 |
@@ -138,6 +140,7 @@ | |||
138 | #define USB_PID_TWINHAN_VP7021_COLD 0x3207 | 140 | #define USB_PID_TWINHAN_VP7021_COLD 0x3207 |
139 | #define USB_PID_TWINHAN_VP7021_WARM 0x3208 | 141 | #define USB_PID_TWINHAN_VP7021_WARM 0x3208 |
140 | #define USB_PID_TINYTWIN 0x3226 | 142 | #define USB_PID_TINYTWIN 0x3226 |
143 | #define USB_PID_TINYTWIN_2 0xe402 | ||
141 | #define USB_PID_DNTV_TINYUSB2_COLD 0x3223 | 144 | #define USB_PID_DNTV_TINYUSB2_COLD 0x3223 |
142 | #define USB_PID_DNTV_TINYUSB2_WARM 0x3224 | 145 | #define USB_PID_DNTV_TINYUSB2_WARM 0x3224 |
143 | #define USB_PID_ULTIMA_TVBOX_COLD 0x8105 | 146 | #define USB_PID_ULTIMA_TVBOX_COLD 0x8105 |
@@ -209,6 +212,7 @@ | |||
209 | #define USB_PID_PINNACLE_PCTV71E 0x022b | 212 | #define USB_PID_PINNACLE_PCTV71E 0x022b |
210 | #define USB_PID_PINNACLE_PCTV72E 0x0236 | 213 | #define USB_PID_PINNACLE_PCTV72E 0x0236 |
211 | #define USB_PID_PINNACLE_PCTV73E 0x0237 | 214 | #define USB_PID_PINNACLE_PCTV73E 0x0237 |
215 | #define USB_PID_PINNACLE_PCTV310E 0x3211 | ||
212 | #define USB_PID_PINNACLE_PCTV801E 0x023a | 216 | #define USB_PID_PINNACLE_PCTV801E 0x023a |
213 | #define USB_PID_PINNACLE_PCTV801E_SE 0x023b | 217 | #define USB_PID_PINNACLE_PCTV801E_SE 0x023b |
214 | #define USB_PID_PINNACLE_PCTV73A 0x0243 | 218 | #define USB_PID_PINNACLE_PCTV73A 0x0243 |
@@ -248,6 +252,7 @@ | |||
248 | #define USB_PID_DIGIVOX_MINI_SL_WARM 0xe361 | 252 | #define USB_PID_DIGIVOX_MINI_SL_WARM 0xe361 |
249 | #define USB_PID_GRANDTEC_DVBT_USB2_COLD 0x0bc6 | 253 | #define USB_PID_GRANDTEC_DVBT_USB2_COLD 0x0bc6 |
250 | #define USB_PID_GRANDTEC_DVBT_USB2_WARM 0x0bc7 | 254 | #define USB_PID_GRANDTEC_DVBT_USB2_WARM 0x0bc7 |
255 | #define USB_PID_WINFAST_DTV2000DS 0x6a04 | ||
251 | #define USB_PID_WINFAST_DTV_DONGLE_COLD 0x6025 | 256 | #define USB_PID_WINFAST_DTV_DONGLE_COLD 0x6025 |
252 | #define USB_PID_WINFAST_DTV_DONGLE_WARM 0x6026 | 257 | #define USB_PID_WINFAST_DTV_DONGLE_WARM 0x6026 |
253 | #define USB_PID_WINFAST_DTV_DONGLE_STK7700P 0x6f00 | 258 | #define USB_PID_WINFAST_DTV_DONGLE_STK7700P 0x6f00 |
@@ -290,5 +295,7 @@ | |||
290 | #define USB_PID_FRIIO_WHITE 0x0001 | 295 | #define USB_PID_FRIIO_WHITE 0x0001 |
291 | #define USB_PID_TVWAY_PLUS 0x0002 | 296 | #define USB_PID_TVWAY_PLUS 0x0002 |
292 | #define USB_PID_SVEON_STV20 0xe39d | 297 | #define USB_PID_SVEON_STV20 0xe39d |
293 | 298 | #define USB_PID_AZUREWAVE_AZ6027 0x3275 | |
299 | #define USB_PID_TERRATEC_DVBS2CI 0x3275 | ||
300 | #define USB_PID_TECHNISAT_USB2_HDCI 0x0002 | ||
294 | #endif | 301 | #endif |
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-init.c b/drivers/media/dvb/dvb-usb/dvb-usb-init.c index e331db8c77b2..5d91f70d2d2d 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-init.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-init.c | |||
@@ -243,7 +243,7 @@ int dvb_usb_device_init(struct usb_interface *intf, | |||
243 | d = kzalloc(sizeof(struct dvb_usb_device),GFP_KERNEL); | 243 | d = kzalloc(sizeof(struct dvb_usb_device),GFP_KERNEL); |
244 | if (d == NULL) { | 244 | if (d == NULL) { |
245 | err("no memory for 'struct dvb_usb_device'"); | 245 | err("no memory for 'struct dvb_usb_device'"); |
246 | return ret; | 246 | return -ENOMEM; |
247 | } | 247 | } |
248 | 248 | ||
249 | d->udev = udev; | 249 | d->udev = udev; |
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c index 6b5ded9e7d5d..a03ef7efec9a 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c | |||
@@ -107,6 +107,7 @@ static void dvb_usb_read_remote_control(struct work_struct *work) | |||
107 | case REMOTE_KEY_REPEAT: | 107 | case REMOTE_KEY_REPEAT: |
108 | deb_rc("key repeated\n"); | 108 | deb_rc("key repeated\n"); |
109 | input_event(d->rc_input_dev, EV_KEY, event, 1); | 109 | input_event(d->rc_input_dev, EV_KEY, event, 1); |
110 | input_sync(d->rc_input_dev); | ||
110 | input_event(d->rc_input_dev, EV_KEY, d->last_event, 0); | 111 | input_event(d->rc_input_dev, EV_KEY, d->last_event, 0); |
111 | input_sync(d->rc_input_dev); | 112 | input_sync(d->rc_input_dev); |
112 | break; | 113 | break; |
diff --git a/drivers/media/dvb/dvb-usb/dw2102.c b/drivers/media/dvb/dvb-usb/dw2102.c index 64132c0cf80d..accc65509b07 100644 --- a/drivers/media/dvb/dvb-usb/dw2102.c +++ b/drivers/media/dvb/dvb-usb/dw2102.c | |||
@@ -1,6 +1,7 @@ | |||
1 | /* DVB USB framework compliant Linux driver for the | 1 | /* DVB USB framework compliant Linux driver for the |
2 | * DVBWorld DVB-S 2101, 2102, DVB-S2 2104, DVB-C 3101, | 2 | * DVBWorld DVB-S 2101, 2102, DVB-S2 2104, DVB-C 3101, |
3 | * TeVii S600, S630, S650 Cards | 3 | * TeVii S600, S630, S650, |
4 | * Prof 1100, 7500 Cards | ||
4 | * Copyright (C) 2008,2009 Igor M. Liplianin (liplianin@me.by) | 5 | * Copyright (C) 2008,2009 Igor M. Liplianin (liplianin@me.by) |
5 | * | 6 | * |
6 | * This program is free software; you can redistribute it and/or modify it | 7 | * This program is free software; you can redistribute it and/or modify it |
@@ -469,11 +470,13 @@ static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], | |||
469 | int num) | 470 | int num) |
470 | { | 471 | { |
471 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | 472 | struct dvb_usb_device *d = i2c_get_adapdata(adap); |
473 | struct usb_device *udev; | ||
472 | int ret = 0; | 474 | int ret = 0; |
473 | int len, i, j; | 475 | int len, i, j; |
474 | 476 | ||
475 | if (!d) | 477 | if (!d) |
476 | return -ENODEV; | 478 | return -ENODEV; |
479 | udev = d->udev; | ||
477 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | 480 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) |
478 | return -EAGAIN; | 481 | return -EAGAIN; |
479 | 482 | ||
@@ -488,8 +491,13 @@ static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], | |||
488 | } | 491 | } |
489 | case (DW2102_VOLTAGE_CTRL): { | 492 | case (DW2102_VOLTAGE_CTRL): { |
490 | u8 obuf[2]; | 493 | u8 obuf[2]; |
494 | |||
495 | obuf[0] = 1; | ||
496 | obuf[1] = msg[j].buf[1];/* off-on */ | ||
497 | ret = dw210x_op_rw(d->udev, 0x8a, 0, 0, | ||
498 | obuf, 2, DW210X_WRITE_MSG); | ||
491 | obuf[0] = 3; | 499 | obuf[0] = 3; |
492 | obuf[1] = msg[j].buf[0]; | 500 | obuf[1] = msg[j].buf[0];/* 13v-18v */ |
493 | ret = dw210x_op_rw(d->udev, 0x8a, 0, 0, | 501 | ret = dw210x_op_rw(d->udev, 0x8a, 0, 0, |
494 | obuf, 2, DW210X_WRITE_MSG); | 502 | obuf, 2, DW210X_WRITE_MSG); |
495 | break; | 503 | break; |
@@ -527,6 +535,17 @@ static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], | |||
527 | i += 16; | 535 | i += 16; |
528 | len -= 16; | 536 | len -= 16; |
529 | } while (len > 0); | 537 | } while (len > 0); |
538 | } else if ((udev->descriptor.idProduct == 0x7500) | ||
539 | && (j < (num - 1))) { | ||
540 | /* write register addr before read */ | ||
541 | u8 obuf[msg[j].len + 2]; | ||
542 | obuf[0] = msg[j + 1].len; | ||
543 | obuf[1] = (msg[j].addr << 1); | ||
544 | memcpy(obuf + 2, msg[j].buf, msg[j].len); | ||
545 | ret = dw210x_op_rw(d->udev, 0x92, 0, 0, | ||
546 | obuf, msg[j].len + 2, | ||
547 | DW210X_WRITE_MSG); | ||
548 | break; | ||
530 | } else { | 549 | } else { |
531 | /* write registers */ | 550 | /* write registers */ |
532 | u8 obuf[msg[j].len + 2]; | 551 | u8 obuf[msg[j].len + 2]; |
@@ -651,18 +670,25 @@ static int s6x0_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) | |||
651 | 670 | ||
652 | static int dw210x_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) | 671 | static int dw210x_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) |
653 | { | 672 | { |
654 | static u8 command_13v[1] = {0x00}; | 673 | static u8 command_13v[] = {0x00, 0x01}; |
655 | static u8 command_18v[1] = {0x01}; | 674 | static u8 command_18v[] = {0x01, 0x01}; |
656 | struct i2c_msg msg[] = { | 675 | static u8 command_off[] = {0x00, 0x00}; |
657 | {.addr = DW2102_VOLTAGE_CTRL, .flags = 0, | 676 | struct i2c_msg msg = { |
658 | .buf = command_13v, .len = 1}, | 677 | .addr = DW2102_VOLTAGE_CTRL, |
678 | .flags = 0, | ||
679 | .buf = command_off, | ||
680 | .len = 2, | ||
659 | }; | 681 | }; |
660 | 682 | ||
661 | struct dvb_usb_adapter *udev_adap = | 683 | struct dvb_usb_adapter *udev_adap = |
662 | (struct dvb_usb_adapter *)(fe->dvb->priv); | 684 | (struct dvb_usb_adapter *)(fe->dvb->priv); |
663 | if (voltage == SEC_VOLTAGE_18) | 685 | if (voltage == SEC_VOLTAGE_18) |
664 | msg[0].buf = command_18v; | 686 | msg.buf = command_18v; |
665 | i2c_transfer(&udev_adap->dev->i2c_adap, msg, 1); | 687 | else if (voltage == SEC_VOLTAGE_13) |
688 | msg.buf = command_13v; | ||
689 | |||
690 | i2c_transfer(&udev_adap->dev->i2c_adap, &msg, 1); | ||
691 | |||
666 | return 0; | 692 | return 0; |
667 | } | 693 | } |
668 | 694 | ||
@@ -735,6 +761,18 @@ static struct stv6110_config dw2104_stv6110_config = { | |||
735 | .clk_div = 1, | 761 | .clk_div = 1, |
736 | }; | 762 | }; |
737 | 763 | ||
764 | static struct stv0900_config prof_7500_stv0900_config = { | ||
765 | .demod_address = 0x6a, | ||
766 | .demod_mode = 0, | ||
767 | .xtal = 27000000, | ||
768 | .clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */ | ||
769 | .diseqc_mode = 2,/* 2/3 PWM */ | ||
770 | .tun1_maddress = 0,/* 0x60 */ | ||
771 | .tun1_adc = 0,/* 2 Vpp */ | ||
772 | .path1_mode = 3, | ||
773 | .tun1_type = 3, | ||
774 | }; | ||
775 | |||
738 | static int dw2104_frontend_attach(struct dvb_usb_adapter *d) | 776 | static int dw2104_frontend_attach(struct dvb_usb_adapter *d) |
739 | { | 777 | { |
740 | struct dvb_tuner_ops *tuner_ops = NULL; | 778 | struct dvb_tuner_ops *tuner_ops = NULL; |
@@ -882,6 +920,19 @@ static int s6x0_frontend_attach(struct dvb_usb_adapter *d) | |||
882 | return -EIO; | 920 | return -EIO; |
883 | } | 921 | } |
884 | 922 | ||
923 | static int prof_7500_frontend_attach(struct dvb_usb_adapter *d) | ||
924 | { | ||
925 | d->fe = dvb_attach(stv0900_attach, &prof_7500_stv0900_config, | ||
926 | &d->dev->i2c_adap, 0); | ||
927 | if (d->fe == NULL) | ||
928 | return -EIO; | ||
929 | d->fe->ops.set_voltage = dw210x_set_voltage; | ||
930 | |||
931 | info("Attached STV0900+STB6100A!\n"); | ||
932 | |||
933 | return 0; | ||
934 | } | ||
935 | |||
885 | static int dw2102_tuner_attach(struct dvb_usb_adapter *adap) | 936 | static int dw2102_tuner_attach(struct dvb_usb_adapter *adap) |
886 | { | 937 | { |
887 | dvb_attach(dvb_pll_attach, adap->fe, 0x60, | 938 | dvb_attach(dvb_pll_attach, adap->fe, 0x60, |
@@ -1073,6 +1124,7 @@ static struct usb_device_id dw2102_table[] = { | |||
1073 | {USB_DEVICE(0x9022, USB_PID_TEVII_S630)}, | 1124 | {USB_DEVICE(0x9022, USB_PID_TEVII_S630)}, |
1074 | {USB_DEVICE(0x3011, USB_PID_PROF_1100)}, | 1125 | {USB_DEVICE(0x3011, USB_PID_PROF_1100)}, |
1075 | {USB_DEVICE(0x9022, USB_PID_TEVII_S660)}, | 1126 | {USB_DEVICE(0x9022, USB_PID_TEVII_S660)}, |
1127 | {USB_DEVICE(0x3034, 0x7500)}, | ||
1076 | { } | 1128 | { } |
1077 | }; | 1129 | }; |
1078 | 1130 | ||
@@ -1387,9 +1439,30 @@ static struct dvb_usb_device_properties s6x0_properties = { | |||
1387 | } | 1439 | } |
1388 | }; | 1440 | }; |
1389 | 1441 | ||
1442 | struct dvb_usb_device_properties *p7500; | ||
1443 | static struct dvb_usb_device_description d7500 = { | ||
1444 | "Prof 7500 USB DVB-S2", | ||
1445 | {&dw2102_table[9], NULL}, | ||
1446 | {NULL}, | ||
1447 | }; | ||
1448 | |||
1390 | static int dw2102_probe(struct usb_interface *intf, | 1449 | static int dw2102_probe(struct usb_interface *intf, |
1391 | const struct usb_device_id *id) | 1450 | const struct usb_device_id *id) |
1392 | { | 1451 | { |
1452 | |||
1453 | p7500 = kzalloc(sizeof(struct dvb_usb_device_properties), GFP_KERNEL); | ||
1454 | if (!p7500) | ||
1455 | return -ENOMEM; | ||
1456 | /* copy default structure */ | ||
1457 | memcpy(p7500, &s6x0_properties, | ||
1458 | sizeof(struct dvb_usb_device_properties)); | ||
1459 | /* fill only different fields */ | ||
1460 | p7500->firmware = "dvb-usb-p7500.fw"; | ||
1461 | p7500->devices[0] = d7500; | ||
1462 | p7500->rc_key_map = tbs_rc_keys; | ||
1463 | p7500->rc_key_map_size = ARRAY_SIZE(tbs_rc_keys); | ||
1464 | p7500->adapter->frontend_attach = prof_7500_frontend_attach; | ||
1465 | |||
1393 | if (0 == dvb_usb_device_init(intf, &dw2102_properties, | 1466 | if (0 == dvb_usb_device_init(intf, &dw2102_properties, |
1394 | THIS_MODULE, NULL, adapter_nr) || | 1467 | THIS_MODULE, NULL, adapter_nr) || |
1395 | 0 == dvb_usb_device_init(intf, &dw2104_properties, | 1468 | 0 == dvb_usb_device_init(intf, &dw2104_properties, |
@@ -1397,6 +1470,8 @@ static int dw2102_probe(struct usb_interface *intf, | |||
1397 | 0 == dvb_usb_device_init(intf, &dw3101_properties, | 1470 | 0 == dvb_usb_device_init(intf, &dw3101_properties, |
1398 | THIS_MODULE, NULL, adapter_nr) || | 1471 | THIS_MODULE, NULL, adapter_nr) || |
1399 | 0 == dvb_usb_device_init(intf, &s6x0_properties, | 1472 | 0 == dvb_usb_device_init(intf, &s6x0_properties, |
1473 | THIS_MODULE, NULL, adapter_nr) || | ||
1474 | 0 == dvb_usb_device_init(intf, p7500, | ||
1400 | THIS_MODULE, NULL, adapter_nr)) | 1475 | THIS_MODULE, NULL, adapter_nr)) |
1401 | return 0; | 1476 | return 0; |
1402 | 1477 | ||
@@ -1431,6 +1506,6 @@ MODULE_AUTHOR("Igor M. Liplianin (c) liplianin@me.by"); | |||
1431 | MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104," | 1506 | MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104," |
1432 | " DVB-C 3101 USB2.0," | 1507 | " DVB-C 3101 USB2.0," |
1433 | " TeVii S600, S630, S650, S660 USB2.0," | 1508 | " TeVii S600, S630, S650, S660 USB2.0," |
1434 | " Prof 1100 USB2.0 devices"); | 1509 | " Prof 1100, 7500 USB2.0 devices"); |
1435 | MODULE_VERSION("0.1"); | 1510 | MODULE_VERSION("0.1"); |
1436 | MODULE_LICENSE("GPL"); | 1511 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/media/dvb/dvb-usb/friio-fe.c b/drivers/media/dvb/dvb-usb/friio-fe.c index ebb7b9fd115b..d14bd227b502 100644 --- a/drivers/media/dvb/dvb-usb/friio-fe.c +++ b/drivers/media/dvb/dvb-usb/friio-fe.c | |||
@@ -366,7 +366,7 @@ static u8 init_code[][2] = { | |||
366 | {0x76, 0x0C}, | 366 | {0x76, 0x0C}, |
367 | }; | 367 | }; |
368 | 368 | ||
369 | const static int init_code_len = sizeof(init_code) / sizeof(u8[2]); | 369 | static const int init_code_len = sizeof(init_code) / sizeof(u8[2]); |
370 | 370 | ||
371 | static int jdvbt90502_init(struct dvb_frontend *fe) | 371 | static int jdvbt90502_init(struct dvb_frontend *fe) |
372 | { | 372 | { |
diff --git a/drivers/media/dvb/dvb-usb/m920x.c b/drivers/media/dvb/dvb-usb/m920x.c index ef9b7bed13ff..737ffa36ac9c 100644 --- a/drivers/media/dvb/dvb-usb/m920x.c +++ b/drivers/media/dvb/dvb-usb/m920x.c | |||
@@ -16,6 +16,9 @@ | |||
16 | #include "qt1010.h" | 16 | #include "qt1010.h" |
17 | #include "tda1004x.h" | 17 | #include "tda1004x.h" |
18 | #include "tda827x.h" | 18 | #include "tda827x.h" |
19 | |||
20 | #include <media/tuner.h> | ||
21 | #include "tuner-simple.h" | ||
19 | #include <asm/unaligned.h> | 22 | #include <asm/unaligned.h> |
20 | 23 | ||
21 | /* debug */ | 24 | /* debug */ |
@@ -158,11 +161,14 @@ static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | |||
158 | 161 | ||
159 | case 0x93: | 162 | case 0x93: |
160 | case 0x92: | 163 | case 0x92: |
164 | case 0x83: /* pinnacle PCTV310e */ | ||
165 | case 0x82: | ||
161 | m->rep_count = 0; | 166 | m->rep_count = 0; |
162 | *state = REMOTE_KEY_PRESSED; | 167 | *state = REMOTE_KEY_PRESSED; |
163 | goto unlock; | 168 | goto unlock; |
164 | 169 | ||
165 | case 0x91: | 170 | case 0x91: |
171 | case 0x81: /* pinnacle PCTV310e */ | ||
166 | /* prevent immediate auto-repeat */ | 172 | /* prevent immediate auto-repeat */ |
167 | if (++m->rep_count > 2) | 173 | if (++m->rep_count > 2) |
168 | *state = REMOTE_KEY_REPEAT; | 174 | *state = REMOTE_KEY_REPEAT; |
@@ -546,6 +552,14 @@ static int m920x_tda8275_61_tuner_attach(struct dvb_usb_adapter *adap) | |||
546 | return 0; | 552 | return 0; |
547 | } | 553 | } |
548 | 554 | ||
555 | static int m920x_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap) | ||
556 | { | ||
557 | dvb_attach(simple_tuner_attach, adap->fe, | ||
558 | &adap->dev->i2c_adap, 0x61, | ||
559 | TUNER_PHILIPS_FMD1216ME_MK3); | ||
560 | return 0; | ||
561 | } | ||
562 | |||
549 | /* device-specific initialization */ | 563 | /* device-specific initialization */ |
550 | static struct m920x_inits megasky_rc_init [] = { | 564 | static struct m920x_inits megasky_rc_init [] = { |
551 | { M9206_RC_INIT2, 0xa8 }, | 565 | { M9206_RC_INIT2, 0xa8 }, |
@@ -562,6 +576,18 @@ static struct m920x_inits tvwalkertwin_rc_init [] = { | |||
562 | { } /* terminating entry */ | 576 | { } /* terminating entry */ |
563 | }; | 577 | }; |
564 | 578 | ||
579 | static struct m920x_inits pinnacle310e_init[] = { | ||
580 | /* without these the tuner don't work */ | ||
581 | { 0xff20, 0x9b }, | ||
582 | { 0xff22, 0x70 }, | ||
583 | |||
584 | /* rc settings */ | ||
585 | { 0xff50, 0x80 }, | ||
586 | { M9206_RC_INIT1, 0x00 }, | ||
587 | { M9206_RC_INIT2, 0xff }, | ||
588 | { } /* terminating entry */ | ||
589 | }; | ||
590 | |||
565 | /* ir keymaps */ | 591 | /* ir keymaps */ |
566 | static struct dvb_usb_rc_key megasky_rc_keys [] = { | 592 | static struct dvb_usb_rc_key megasky_rc_keys [] = { |
567 | { 0x0012, KEY_POWER }, | 593 | { 0x0012, KEY_POWER }, |
@@ -602,11 +628,68 @@ static struct dvb_usb_rc_key tvwalkertwin_rc_keys [] = { | |||
602 | { 0x001e, KEY_VOLUMEUP }, | 628 | { 0x001e, KEY_VOLUMEUP }, |
603 | }; | 629 | }; |
604 | 630 | ||
631 | static struct dvb_usb_rc_key pinnacle310e_rc_keys[] = { | ||
632 | { 0x16, KEY_POWER }, | ||
633 | { 0x17, KEY_FAVORITES }, | ||
634 | { 0x0f, KEY_TEXT }, | ||
635 | { 0x48, KEY_MEDIA }, /* preview */ | ||
636 | { 0x1c, KEY_EPG }, | ||
637 | { 0x04, KEY_LIST }, /* record list */ | ||
638 | { 0x03, KEY_1 }, | ||
639 | { 0x01, KEY_2 }, | ||
640 | { 0x06, KEY_3 }, | ||
641 | { 0x09, KEY_4 }, | ||
642 | { 0x1d, KEY_5 }, | ||
643 | { 0x1f, KEY_6 }, | ||
644 | { 0x0d, KEY_7 }, | ||
645 | { 0x19, KEY_8 }, | ||
646 | { 0x1b, KEY_9 }, | ||
647 | { 0x15, KEY_0 }, | ||
648 | { 0x0c, KEY_CANCEL }, | ||
649 | { 0x4a, KEY_CLEAR }, | ||
650 | { 0x13, KEY_BACK }, | ||
651 | { 0x00, KEY_TAB }, | ||
652 | { 0x4b, KEY_UP }, | ||
653 | { 0x4e, KEY_LEFT }, | ||
654 | { 0x52, KEY_RIGHT }, | ||
655 | { 0x51, KEY_DOWN }, | ||
656 | { 0x4f, KEY_ENTER }, /* could also be KEY_OK */ | ||
657 | { 0x1e, KEY_VOLUMEUP }, | ||
658 | { 0x0a, KEY_VOLUMEDOWN }, | ||
659 | { 0x05, KEY_CHANNELUP }, | ||
660 | { 0x02, KEY_CHANNELDOWN }, | ||
661 | { 0x11, KEY_RECORD }, | ||
662 | { 0x14, KEY_PLAY }, | ||
663 | { 0x4c, KEY_PAUSE }, | ||
664 | { 0x1a, KEY_STOP }, | ||
665 | { 0x40, KEY_REWIND }, | ||
666 | { 0x12, KEY_FASTFORWARD }, | ||
667 | { 0x41, KEY_PREVIOUSSONG }, /* Replay */ | ||
668 | { 0x42, KEY_NEXTSONG }, /* Skip */ | ||
669 | { 0x54, KEY_CAMERA }, /* Capture */ | ||
670 | /* { 0x50, KEY_SAP }, */ /* Sap */ | ||
671 | { 0x47, KEY_CYCLEWINDOWS }, /* Pip */ | ||
672 | { 0x4d, KEY_SCREEN }, /* FullScreen */ | ||
673 | { 0x08, KEY_SUBTITLE }, | ||
674 | { 0x0e, KEY_MUTE }, | ||
675 | /* { 0x49, KEY_LR }, */ /* L/R */ | ||
676 | { 0x07, KEY_SLEEP }, /* Hibernate */ | ||
677 | { 0x08, KEY_MEDIA }, /* A/V */ | ||
678 | { 0x0e, KEY_MENU }, /* Recall */ | ||
679 | { 0x45, KEY_ZOOMIN }, | ||
680 | { 0x46, KEY_ZOOMOUT }, | ||
681 | { 0x18, KEY_TV }, /* Red */ | ||
682 | { 0x53, KEY_VCR }, /* Green */ | ||
683 | { 0x5e, KEY_SAT }, /* Yellow */ | ||
684 | { 0x5f, KEY_PLAYER }, /* Blue */ | ||
685 | }; | ||
686 | |||
605 | /* DVB USB Driver stuff */ | 687 | /* DVB USB Driver stuff */ |
606 | static struct dvb_usb_device_properties megasky_properties; | 688 | static struct dvb_usb_device_properties megasky_properties; |
607 | static struct dvb_usb_device_properties digivox_mini_ii_properties; | 689 | static struct dvb_usb_device_properties digivox_mini_ii_properties; |
608 | static struct dvb_usb_device_properties tvwalkertwin_properties; | 690 | static struct dvb_usb_device_properties tvwalkertwin_properties; |
609 | static struct dvb_usb_device_properties dposh_properties; | 691 | static struct dvb_usb_device_properties dposh_properties; |
692 | static struct dvb_usb_device_properties pinnacle_pctv310e_properties; | ||
610 | 693 | ||
611 | static int m920x_probe(struct usb_interface *intf, | 694 | static int m920x_probe(struct usb_interface *intf, |
612 | const struct usb_device_id *id) | 695 | const struct usb_device_id *id) |
@@ -652,6 +735,13 @@ static int m920x_probe(struct usb_interface *intf, | |||
652 | goto found; | 735 | goto found; |
653 | } | 736 | } |
654 | 737 | ||
738 | ret = dvb_usb_device_init(intf, &pinnacle_pctv310e_properties, | ||
739 | THIS_MODULE, &d, adapter_nr); | ||
740 | if (ret == 0) { | ||
741 | rc_init_seq = pinnacle310e_init; | ||
742 | goto found; | ||
743 | } | ||
744 | |||
655 | return ret; | 745 | return ret; |
656 | } else { | 746 | } else { |
657 | /* Another interface on a multi-tuner device */ | 747 | /* Another interface on a multi-tuner device */ |
@@ -682,6 +772,7 @@ static struct usb_device_id m920x_table [] = { | |||
682 | USB_PID_LIFEVIEW_TV_WALKER_TWIN_WARM) }, | 772 | USB_PID_LIFEVIEW_TV_WALKER_TWIN_WARM) }, |
683 | { USB_DEVICE(USB_VID_DPOSH, USB_PID_DPOSH_M9206_COLD) }, | 773 | { USB_DEVICE(USB_VID_DPOSH, USB_PID_DPOSH_M9206_COLD) }, |
684 | { USB_DEVICE(USB_VID_DPOSH, USB_PID_DPOSH_M9206_WARM) }, | 774 | { USB_DEVICE(USB_VID_DPOSH, USB_PID_DPOSH_M9206_WARM) }, |
775 | { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_PINNACLE_PCTV310E) }, | ||
685 | { } /* Terminating entry */ | 776 | { } /* Terminating entry */ |
686 | }; | 777 | }; |
687 | MODULE_DEVICE_TABLE (usb, m920x_table); | 778 | MODULE_DEVICE_TABLE (usb, m920x_table); |
@@ -895,6 +986,56 @@ static struct dvb_usb_device_properties dposh_properties = { | |||
895 | } | 986 | } |
896 | }; | 987 | }; |
897 | 988 | ||
989 | static struct dvb_usb_device_properties pinnacle_pctv310e_properties = { | ||
990 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
991 | |||
992 | .usb_ctrl = DEVICE_SPECIFIC, | ||
993 | .download_firmware = NULL, | ||
994 | |||
995 | .rc_interval = 100, | ||
996 | .rc_key_map = pinnacle310e_rc_keys, | ||
997 | .rc_key_map_size = ARRAY_SIZE(pinnacle310e_rc_keys), | ||
998 | .rc_query = m920x_rc_query, | ||
999 | |||
1000 | .size_of_priv = sizeof(struct m920x_state), | ||
1001 | |||
1002 | .identify_state = m920x_identify_state, | ||
1003 | .num_adapters = 1, | ||
1004 | .adapter = {{ | ||
1005 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | | ||
1006 | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
1007 | |||
1008 | .pid_filter_count = 8, | ||
1009 | .pid_filter = m920x_pid_filter, | ||
1010 | .pid_filter_ctrl = m920x_pid_filter_ctrl, | ||
1011 | |||
1012 | .frontend_attach = m920x_mt352_frontend_attach, | ||
1013 | .tuner_attach = m920x_fmd1216me_tuner_attach, | ||
1014 | |||
1015 | .stream = { | ||
1016 | .type = USB_ISOC, | ||
1017 | .count = 5, | ||
1018 | .endpoint = 0x84, | ||
1019 | .u = { | ||
1020 | .isoc = { | ||
1021 | .framesperurb = 128, | ||
1022 | .framesize = 564, | ||
1023 | .interval = 1, | ||
1024 | } | ||
1025 | } | ||
1026 | }, | ||
1027 | } }, | ||
1028 | .i2c_algo = &m920x_i2c_algo, | ||
1029 | |||
1030 | .num_device_descs = 1, | ||
1031 | .devices = { | ||
1032 | { "Pinnacle PCTV 310e", | ||
1033 | { &m920x_table[6], NULL }, | ||
1034 | { NULL }, | ||
1035 | } | ||
1036 | } | ||
1037 | }; | ||
1038 | |||
898 | static struct usb_driver m920x_driver = { | 1039 | static struct usb_driver m920x_driver = { |
899 | .name = "dvb_usb_m920x", | 1040 | .name = "dvb_usb_m920x", |
900 | .probe = m920x_probe, | 1041 | .probe = m920x_probe, |
diff --git a/drivers/media/dvb/dvb-usb/m920x.h b/drivers/media/dvb/dvb-usb/m920x.h index 37532890accd..3c061518ffc1 100644 --- a/drivers/media/dvb/dvb-usb/m920x.h +++ b/drivers/media/dvb/dvb-usb/m920x.h | |||
@@ -18,7 +18,7 @@ | |||
18 | #define M9206_FW 0x30 | 18 | #define M9206_FW 0x30 |
19 | 19 | ||
20 | #define M9206_MAX_FILTERS 8 | 20 | #define M9206_MAX_FILTERS 8 |
21 | #define M9206_MAX_ADAPTERS 2 | 21 | #define M9206_MAX_ADAPTERS 4 |
22 | 22 | ||
23 | /* | 23 | /* |
24 | sequences found in logs: | 24 | sequences found in logs: |
diff --git a/drivers/media/dvb/dvb-usb/opera1.c b/drivers/media/dvb/dvb-usb/opera1.c index d4e230941679..830557696ae6 100644 --- a/drivers/media/dvb/dvb-usb/opera1.c +++ b/drivers/media/dvb/dvb-usb/opera1.c | |||
@@ -138,7 +138,7 @@ static int opera1_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], | |||
138 | (msg[i].addr<<1)|(msg[i].flags&I2C_M_RD?0x01:0), | 138 | (msg[i].addr<<1)|(msg[i].flags&I2C_M_RD?0x01:0), |
139 | msg[i].buf, | 139 | msg[i].buf, |
140 | msg[i].len | 140 | msg[i].len |
141 | )!= msg[i].len)) { | 141 | )) != msg[i].len) { |
142 | break; | 142 | break; |
143 | } | 143 | } |
144 | if (dvb_usb_opera1_debug & 0x10) | 144 | if (dvb_usb_opera1_debug & 0x10) |
diff --git a/drivers/media/dvb/firewire/firedtv-1394.c b/drivers/media/dvb/firewire/firedtv-1394.c index 7c5459c27b75..c3e0ec2dcfca 100644 --- a/drivers/media/dvb/firewire/firedtv-1394.c +++ b/drivers/media/dvb/firewire/firedtv-1394.c | |||
@@ -90,13 +90,14 @@ static inline struct node_entry *node_of(struct firedtv *fdtv) | |||
90 | return container_of(fdtv->device, struct unit_directory, device)->ne; | 90 | return container_of(fdtv->device, struct unit_directory, device)->ne; |
91 | } | 91 | } |
92 | 92 | ||
93 | static int node_lock(struct firedtv *fdtv, u64 addr, __be32 data[]) | 93 | static int node_lock(struct firedtv *fdtv, u64 addr, void *data) |
94 | { | 94 | { |
95 | quadlet_t *d = data; | ||
95 | int ret; | 96 | int ret; |
96 | 97 | ||
97 | ret = hpsb_node_lock(node_of(fdtv), addr, EXTCODE_COMPARE_SWAP, | 98 | ret = hpsb_node_lock(node_of(fdtv), addr, |
98 | (__force quadlet_t *)&data[1], (__force quadlet_t)data[0]); | 99 | EXTCODE_COMPARE_SWAP, &d[1], d[0]); |
99 | data[0] = data[1]; | 100 | d[0] = d[1]; |
100 | 101 | ||
101 | return ret; | 102 | return ret; |
102 | } | 103 | } |
@@ -192,9 +193,13 @@ static int node_probe(struct device *dev) | |||
192 | int kv_len, err; | 193 | int kv_len, err; |
193 | void *kv_str; | 194 | void *kv_str; |
194 | 195 | ||
195 | kv_len = (ud->model_name_kv->value.leaf.len - 2) * sizeof(quadlet_t); | 196 | if (ud->model_name_kv) { |
196 | kv_str = CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(ud->model_name_kv); | 197 | kv_len = (ud->model_name_kv->value.leaf.len - 2) * 4; |
197 | 198 | kv_str = CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(ud->model_name_kv); | |
199 | } else { | ||
200 | kv_len = 0; | ||
201 | kv_str = NULL; | ||
202 | } | ||
198 | fdtv = fdtv_alloc(dev, &fdtv_1394_backend, kv_str, kv_len); | 203 | fdtv = fdtv_alloc(dev, &fdtv_1394_backend, kv_str, kv_len); |
199 | if (!fdtv) | 204 | if (!fdtv) |
200 | return -ENOMEM; | 205 | return -ENOMEM; |
diff --git a/drivers/media/dvb/firewire/firedtv-avc.c b/drivers/media/dvb/firewire/firedtv-avc.c index 50c42a4b972b..1b31bebc27d6 100644 --- a/drivers/media/dvb/firewire/firedtv-avc.c +++ b/drivers/media/dvb/firewire/firedtv-avc.c | |||
@@ -74,7 +74,6 @@ | |||
74 | #define EN50221_TAG_CA_INFO 0x9f8031 | 74 | #define EN50221_TAG_CA_INFO 0x9f8031 |
75 | 75 | ||
76 | struct avc_command_frame { | 76 | struct avc_command_frame { |
77 | int length; | ||
78 | u8 ctype; | 77 | u8 ctype; |
79 | u8 subunit; | 78 | u8 subunit; |
80 | u8 opcode; | 79 | u8 opcode; |
@@ -82,13 +81,27 @@ struct avc_command_frame { | |||
82 | }; | 81 | }; |
83 | 82 | ||
84 | struct avc_response_frame { | 83 | struct avc_response_frame { |
85 | int length; | ||
86 | u8 response; | 84 | u8 response; |
87 | u8 subunit; | 85 | u8 subunit; |
88 | u8 opcode; | 86 | u8 opcode; |
89 | u8 operand[509]; | 87 | u8 operand[509]; |
90 | }; | 88 | }; |
91 | 89 | ||
90 | #define LAST_OPERAND (509 - 1) | ||
91 | |||
92 | static inline void clear_operands(struct avc_command_frame *c, int from, int to) | ||
93 | { | ||
94 | memset(&c->operand[from], 0, to - from + 1); | ||
95 | } | ||
96 | |||
97 | static void pad_operands(struct avc_command_frame *c, int from) | ||
98 | { | ||
99 | int to = ALIGN(from, 4); | ||
100 | |||
101 | if (from <= to && to <= LAST_OPERAND) | ||
102 | clear_operands(c, from, to); | ||
103 | } | ||
104 | |||
92 | #define AVC_DEBUG_READ_DESCRIPTOR 0x0001 | 105 | #define AVC_DEBUG_READ_DESCRIPTOR 0x0001 |
93 | #define AVC_DEBUG_DSIT 0x0002 | 106 | #define AVC_DEBUG_DSIT 0x0002 |
94 | #define AVC_DEBUG_DSD 0x0004 | 107 | #define AVC_DEBUG_DSD 0x0004 |
@@ -202,78 +215,65 @@ static void debug_pmt(char *msg, int length) | |||
202 | 16, 1, msg, length, false); | 215 | 16, 1, msg, length, false); |
203 | } | 216 | } |
204 | 217 | ||
205 | static int __avc_write(struct firedtv *fdtv, | 218 | static int avc_write(struct firedtv *fdtv) |
206 | const struct avc_command_frame *c, struct avc_response_frame *r) | ||
207 | { | 219 | { |
208 | int err, retry; | 220 | int err, retry; |
209 | 221 | ||
210 | if (r) | 222 | fdtv->avc_reply_received = false; |
211 | fdtv->avc_reply_received = false; | ||
212 | 223 | ||
213 | for (retry = 0; retry < 6; retry++) { | 224 | for (retry = 0; retry < 6; retry++) { |
214 | if (unlikely(avc_debug)) | 225 | if (unlikely(avc_debug)) |
215 | debug_fcp(&c->ctype, c->length); | 226 | debug_fcp(fdtv->avc_data, fdtv->avc_data_length); |
216 | 227 | ||
217 | err = fdtv->backend->write(fdtv, FCP_COMMAND_REGISTER, | 228 | err = fdtv->backend->write(fdtv, FCP_COMMAND_REGISTER, |
218 | (void *)&c->ctype, c->length); | 229 | fdtv->avc_data, fdtv->avc_data_length); |
219 | if (err) { | 230 | if (err) { |
220 | fdtv->avc_reply_received = true; | ||
221 | dev_err(fdtv->device, "FCP command write failed\n"); | 231 | dev_err(fdtv->device, "FCP command write failed\n"); |
232 | |||
222 | return err; | 233 | return err; |
223 | } | 234 | } |
224 | 235 | ||
225 | if (!r) | ||
226 | return 0; | ||
227 | |||
228 | /* | 236 | /* |
229 | * AV/C specs say that answers should be sent within 150 ms. | 237 | * AV/C specs say that answers should be sent within 150 ms. |
230 | * Time out after 200 ms. | 238 | * Time out after 200 ms. |
231 | */ | 239 | */ |
232 | if (wait_event_timeout(fdtv->avc_wait, | 240 | if (wait_event_timeout(fdtv->avc_wait, |
233 | fdtv->avc_reply_received, | 241 | fdtv->avc_reply_received, |
234 | msecs_to_jiffies(200)) != 0) { | 242 | msecs_to_jiffies(200)) != 0) |
235 | r->length = fdtv->response_length; | ||
236 | memcpy(&r->response, fdtv->response, r->length); | ||
237 | |||
238 | return 0; | 243 | return 0; |
239 | } | ||
240 | } | 244 | } |
241 | dev_err(fdtv->device, "FCP response timed out\n"); | 245 | dev_err(fdtv->device, "FCP response timed out\n"); |
246 | |||
242 | return -ETIMEDOUT; | 247 | return -ETIMEDOUT; |
243 | } | 248 | } |
244 | 249 | ||
245 | static int avc_write(struct firedtv *fdtv, | 250 | static bool is_register_rc(struct avc_response_frame *r) |
246 | const struct avc_command_frame *c, struct avc_response_frame *r) | ||
247 | { | 251 | { |
248 | int ret; | 252 | return r->opcode == AVC_OPCODE_VENDOR && |
249 | 253 | r->operand[0] == SFE_VENDOR_DE_COMPANYID_0 && | |
250 | if (mutex_lock_interruptible(&fdtv->avc_mutex)) | 254 | r->operand[1] == SFE_VENDOR_DE_COMPANYID_1 && |
251 | return -EINTR; | 255 | r->operand[2] == SFE_VENDOR_DE_COMPANYID_2 && |
252 | 256 | r->operand[3] == SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL; | |
253 | ret = __avc_write(fdtv, c, r); | ||
254 | |||
255 | mutex_unlock(&fdtv->avc_mutex); | ||
256 | return ret; | ||
257 | } | 257 | } |
258 | 258 | ||
259 | int avc_recv(struct firedtv *fdtv, void *data, size_t length) | 259 | int avc_recv(struct firedtv *fdtv, void *data, size_t length) |
260 | { | 260 | { |
261 | struct avc_response_frame *r = | 261 | struct avc_response_frame *r = data; |
262 | data - offsetof(struct avc_response_frame, response); | ||
263 | 262 | ||
264 | if (unlikely(avc_debug)) | 263 | if (unlikely(avc_debug)) |
265 | debug_fcp(data, length); | 264 | debug_fcp(data, length); |
266 | 265 | ||
267 | if (length >= 8 && | 266 | if (length >= 8 && is_register_rc(r)) { |
268 | r->operand[0] == SFE_VENDOR_DE_COMPANYID_0 && | 267 | switch (r->response) { |
269 | r->operand[1] == SFE_VENDOR_DE_COMPANYID_1 && | 268 | case AVC_RESPONSE_CHANGED: |
270 | r->operand[2] == SFE_VENDOR_DE_COMPANYID_2 && | 269 | fdtv_handle_rc(fdtv, r->operand[4] << 8 | r->operand[5]); |
271 | r->operand[3] == SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL) { | ||
272 | if (r->response == AVC_RESPONSE_CHANGED) { | ||
273 | fdtv_handle_rc(fdtv, | ||
274 | r->operand[4] << 8 | r->operand[5]); | ||
275 | schedule_work(&fdtv->remote_ctrl_work); | 270 | schedule_work(&fdtv->remote_ctrl_work); |
276 | } else if (r->response != AVC_RESPONSE_INTERIM) { | 271 | break; |
272 | case AVC_RESPONSE_INTERIM: | ||
273 | if (is_register_rc((void *)fdtv->avc_data)) | ||
274 | goto wake; | ||
275 | break; | ||
276 | default: | ||
277 | dev_info(fdtv->device, | 277 | dev_info(fdtv->device, |
278 | "remote control result = %d\n", r->response); | 278 | "remote control result = %d\n", r->response); |
279 | } | 279 | } |
@@ -285,9 +285,9 @@ int avc_recv(struct firedtv *fdtv, void *data, size_t length) | |||
285 | return -EIO; | 285 | return -EIO; |
286 | } | 286 | } |
287 | 287 | ||
288 | memcpy(fdtv->response, data, length); | 288 | memcpy(fdtv->avc_data, data, length); |
289 | fdtv->response_length = length; | 289 | fdtv->avc_data_length = length; |
290 | 290 | wake: | |
291 | fdtv->avc_reply_received = true; | 291 | fdtv->avc_reply_received = true; |
292 | wake_up(&fdtv->avc_wait); | 292 | wake_up(&fdtv->avc_wait); |
293 | 293 | ||
@@ -318,10 +318,11 @@ static int add_pid_filter(struct firedtv *fdtv, u8 *operand) | |||
318 | * tuning command for setting the relative LNB frequency | 318 | * tuning command for setting the relative LNB frequency |
319 | * (not supported by the AVC standard) | 319 | * (not supported by the AVC standard) |
320 | */ | 320 | */ |
321 | static void avc_tuner_tuneqpsk(struct firedtv *fdtv, | 321 | static int avc_tuner_tuneqpsk(struct firedtv *fdtv, |
322 | struct dvb_frontend_parameters *params, | 322 | struct dvb_frontend_parameters *params) |
323 | struct avc_command_frame *c) | ||
324 | { | 323 | { |
324 | struct avc_command_frame *c = (void *)fdtv->avc_data; | ||
325 | |||
325 | c->opcode = AVC_OPCODE_VENDOR; | 326 | c->opcode = AVC_OPCODE_VENDOR; |
326 | 327 | ||
327 | c->operand[0] = SFE_VENDOR_DE_COMPANYID_0; | 328 | c->operand[0] = SFE_VENDOR_DE_COMPANYID_0; |
@@ -370,16 +371,18 @@ static void avc_tuner_tuneqpsk(struct firedtv *fdtv, | |||
370 | c->operand[13] = 0x1; | 371 | c->operand[13] = 0x1; |
371 | c->operand[14] = 0xff; | 372 | c->operand[14] = 0xff; |
372 | c->operand[15] = 0xff; | 373 | c->operand[15] = 0xff; |
373 | c->length = 20; | 374 | |
375 | return 16; | ||
374 | } else { | 376 | } else { |
375 | c->length = 16; | 377 | return 13; |
376 | } | 378 | } |
377 | } | 379 | } |
378 | 380 | ||
379 | static void avc_tuner_dsd_dvb_c(struct firedtv *fdtv, | 381 | static int avc_tuner_dsd_dvb_c(struct firedtv *fdtv, |
380 | struct dvb_frontend_parameters *params, | 382 | struct dvb_frontend_parameters *params) |
381 | struct avc_command_frame *c) | ||
382 | { | 383 | { |
384 | struct avc_command_frame *c = (void *)fdtv->avc_data; | ||
385 | |||
383 | c->opcode = AVC_OPCODE_DSD; | 386 | c->opcode = AVC_OPCODE_DSD; |
384 | 387 | ||
385 | c->operand[0] = 0; /* source plug */ | 388 | c->operand[0] = 0; /* source plug */ |
@@ -440,15 +443,14 @@ static void avc_tuner_dsd_dvb_c(struct firedtv *fdtv, | |||
440 | c->operand[20] = 0x00; | 443 | c->operand[20] = 0x00; |
441 | c->operand[21] = 0x00; | 444 | c->operand[21] = 0x00; |
442 | 445 | ||
443 | /* Add PIDs to filter */ | 446 | return 22 + add_pid_filter(fdtv, &c->operand[22]); |
444 | c->length = ALIGN(22 + add_pid_filter(fdtv, &c->operand[22]) + 3, 4); | ||
445 | } | 447 | } |
446 | 448 | ||
447 | static void avc_tuner_dsd_dvb_t(struct firedtv *fdtv, | 449 | static int avc_tuner_dsd_dvb_t(struct firedtv *fdtv, |
448 | struct dvb_frontend_parameters *params, | 450 | struct dvb_frontend_parameters *params) |
449 | struct avc_command_frame *c) | ||
450 | { | 451 | { |
451 | struct dvb_ofdm_parameters *ofdm = ¶ms->u.ofdm; | 452 | struct dvb_ofdm_parameters *ofdm = ¶ms->u.ofdm; |
453 | struct avc_command_frame *c = (void *)fdtv->avc_data; | ||
452 | 454 | ||
453 | c->opcode = AVC_OPCODE_DSD; | 455 | c->opcode = AVC_OPCODE_DSD; |
454 | 456 | ||
@@ -543,55 +545,58 @@ static void avc_tuner_dsd_dvb_t(struct firedtv *fdtv, | |||
543 | c->operand[15] = 0x00; /* network_ID[0] */ | 545 | c->operand[15] = 0x00; /* network_ID[0] */ |
544 | c->operand[16] = 0x00; /* network_ID[1] */ | 546 | c->operand[16] = 0x00; /* network_ID[1] */ |
545 | 547 | ||
546 | /* Add PIDs to filter */ | 548 | return 17 + add_pid_filter(fdtv, &c->operand[17]); |
547 | c->length = ALIGN(17 + add_pid_filter(fdtv, &c->operand[17]) + 3, 4); | ||
548 | } | 549 | } |
549 | 550 | ||
550 | int avc_tuner_dsd(struct firedtv *fdtv, | 551 | int avc_tuner_dsd(struct firedtv *fdtv, |
551 | struct dvb_frontend_parameters *params) | 552 | struct dvb_frontend_parameters *params) |
552 | { | 553 | { |
553 | char buffer[sizeof(struct avc_command_frame)]; | 554 | struct avc_command_frame *c = (void *)fdtv->avc_data; |
554 | struct avc_command_frame *c = (void *)buffer; | 555 | int pos, ret; |
555 | struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */ | ||
556 | 556 | ||
557 | memset(c, 0, sizeof(*c)); | 557 | mutex_lock(&fdtv->avc_mutex); |
558 | 558 | ||
559 | c->ctype = AVC_CTYPE_CONTROL; | 559 | c->ctype = AVC_CTYPE_CONTROL; |
560 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; | 560 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; |
561 | 561 | ||
562 | switch (fdtv->type) { | 562 | switch (fdtv->type) { |
563 | case FIREDTV_DVB_S: | 563 | case FIREDTV_DVB_S: |
564 | case FIREDTV_DVB_S2: avc_tuner_tuneqpsk(fdtv, params, c); break; | 564 | case FIREDTV_DVB_S2: pos = avc_tuner_tuneqpsk(fdtv, params); break; |
565 | case FIREDTV_DVB_C: avc_tuner_dsd_dvb_c(fdtv, params, c); break; | 565 | case FIREDTV_DVB_C: pos = avc_tuner_dsd_dvb_c(fdtv, params); break; |
566 | case FIREDTV_DVB_T: avc_tuner_dsd_dvb_t(fdtv, params, c); break; | 566 | case FIREDTV_DVB_T: pos = avc_tuner_dsd_dvb_t(fdtv, params); break; |
567 | default: | 567 | default: |
568 | BUG(); | 568 | BUG(); |
569 | } | 569 | } |
570 | pad_operands(c, pos); | ||
570 | 571 | ||
571 | if (avc_write(fdtv, c, r) < 0) | 572 | fdtv->avc_data_length = ALIGN(3 + pos, 4); |
572 | return -EIO; | 573 | ret = avc_write(fdtv); |
573 | |||
574 | msleep(500); | ||
575 | #if 0 | 574 | #if 0 |
576 | /* FIXME: */ | 575 | /* |
577 | /* u8 *status was an out-parameter of avc_tuner_dsd, unused by caller */ | 576 | * FIXME: |
577 | * u8 *status was an out-parameter of avc_tuner_dsd, unused by caller. | ||
578 | * Check for AVC_RESPONSE_ACCEPTED here instead? | ||
579 | */ | ||
578 | if (status) | 580 | if (status) |
579 | *status = r->operand[2]; | 581 | *status = r->operand[2]; |
580 | #endif | 582 | #endif |
581 | return 0; | 583 | mutex_unlock(&fdtv->avc_mutex); |
584 | |||
585 | if (ret == 0) | ||
586 | msleep(500); | ||
587 | |||
588 | return ret; | ||
582 | } | 589 | } |
583 | 590 | ||
584 | int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[]) | 591 | int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[]) |
585 | { | 592 | { |
586 | char buffer[sizeof(struct avc_command_frame)]; | 593 | struct avc_command_frame *c = (void *)fdtv->avc_data; |
587 | struct avc_command_frame *c = (void *)buffer; | 594 | int ret, pos, k; |
588 | struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */ | ||
589 | int pos, k; | ||
590 | 595 | ||
591 | if (pidc > 16 && pidc != 0xff) | 596 | if (pidc > 16 && pidc != 0xff) |
592 | return -EINVAL; | 597 | return -EINVAL; |
593 | 598 | ||
594 | memset(c, 0, sizeof(*c)); | 599 | mutex_lock(&fdtv->avc_mutex); |
595 | 600 | ||
596 | c->ctype = AVC_CTYPE_CONTROL; | 601 | c->ctype = AVC_CTYPE_CONTROL; |
597 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; | 602 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; |
@@ -614,24 +619,27 @@ int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[]) | |||
614 | c->operand[pos++] = 0x00; /* tableID */ | 619 | c->operand[pos++] = 0x00; /* tableID */ |
615 | c->operand[pos++] = 0x00; /* filter_length */ | 620 | c->operand[pos++] = 0x00; /* filter_length */ |
616 | } | 621 | } |
622 | pad_operands(c, pos); | ||
617 | 623 | ||
618 | c->length = ALIGN(3 + pos, 4); | 624 | fdtv->avc_data_length = ALIGN(3 + pos, 4); |
625 | ret = avc_write(fdtv); | ||
619 | 626 | ||
620 | if (avc_write(fdtv, c, r) < 0) | 627 | /* FIXME: check response code? */ |
621 | return -EIO; | ||
622 | 628 | ||
623 | msleep(50); | 629 | mutex_unlock(&fdtv->avc_mutex); |
624 | return 0; | 630 | |
631 | if (ret == 0) | ||
632 | msleep(50); | ||
633 | |||
634 | return ret; | ||
625 | } | 635 | } |
626 | 636 | ||
627 | int avc_tuner_get_ts(struct firedtv *fdtv) | 637 | int avc_tuner_get_ts(struct firedtv *fdtv) |
628 | { | 638 | { |
629 | char buffer[sizeof(struct avc_command_frame)]; | 639 | struct avc_command_frame *c = (void *)fdtv->avc_data; |
630 | struct avc_command_frame *c = (void *)buffer; | 640 | int ret, sl; |
631 | struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */ | ||
632 | int sl; | ||
633 | 641 | ||
634 | memset(c, 0, sizeof(*c)); | 642 | mutex_lock(&fdtv->avc_mutex); |
635 | 643 | ||
636 | c->ctype = AVC_CTYPE_CONTROL; | 644 | c->ctype = AVC_CTYPE_CONTROL; |
637 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; | 645 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; |
@@ -646,26 +654,33 @@ int avc_tuner_get_ts(struct firedtv *fdtv) | |||
646 | c->operand[4] = 0x00; /* antenna number */ | 654 | c->operand[4] = 0x00; /* antenna number */ |
647 | c->operand[5] = 0x0; /* system_specific_search_flags */ | 655 | c->operand[5] = 0x0; /* system_specific_search_flags */ |
648 | c->operand[6] = sl; /* system_specific_multiplex selection_length */ | 656 | c->operand[6] = sl; /* system_specific_multiplex selection_length */ |
649 | c->operand[7] = 0x00; /* valid_flags [0] */ | 657 | /* |
650 | c->operand[8] = 0x00; /* valid_flags [1] */ | 658 | * operand[7]: valid_flags[0] |
651 | c->operand[7 + sl] = 0x00; /* nr_of_dsit_sel_specs (always 0) */ | 659 | * operand[8]: valid_flags[1] |
660 | * operand[7 + sl]: nr_of_dsit_sel_specs (always 0) | ||
661 | */ | ||
662 | clear_operands(c, 7, 24); | ||
652 | 663 | ||
653 | c->length = fdtv->type == FIREDTV_DVB_T ? 24 : 28; | 664 | fdtv->avc_data_length = fdtv->type == FIREDTV_DVB_T ? 24 : 28; |
665 | ret = avc_write(fdtv); | ||
654 | 666 | ||
655 | if (avc_write(fdtv, c, r) < 0) | 667 | /* FIXME: check response code? */ |
656 | return -EIO; | ||
657 | 668 | ||
658 | msleep(250); | 669 | mutex_unlock(&fdtv->avc_mutex); |
659 | return 0; | 670 | |
671 | if (ret == 0) | ||
672 | msleep(250); | ||
673 | |||
674 | return ret; | ||
660 | } | 675 | } |
661 | 676 | ||
662 | int avc_identify_subunit(struct firedtv *fdtv) | 677 | int avc_identify_subunit(struct firedtv *fdtv) |
663 | { | 678 | { |
664 | char buffer[sizeof(struct avc_command_frame)]; | 679 | struct avc_command_frame *c = (void *)fdtv->avc_data; |
665 | struct avc_command_frame *c = (void *)buffer; | 680 | struct avc_response_frame *r = (void *)fdtv->avc_data; |
666 | struct avc_response_frame *r = (void *)buffer; | 681 | int ret; |
667 | 682 | ||
668 | memset(c, 0, sizeof(*c)); | 683 | mutex_lock(&fdtv->avc_mutex); |
669 | 684 | ||
670 | c->ctype = AVC_CTYPE_CONTROL; | 685 | c->ctype = AVC_CTYPE_CONTROL; |
671 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; | 686 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; |
@@ -678,31 +693,34 @@ int avc_identify_subunit(struct firedtv *fdtv) | |||
678 | c->operand[4] = 0x08; /* length lowbyte */ | 693 | c->operand[4] = 0x08; /* length lowbyte */ |
679 | c->operand[5] = 0x00; /* offset highbyte */ | 694 | c->operand[5] = 0x00; /* offset highbyte */ |
680 | c->operand[6] = 0x0d; /* offset lowbyte */ | 695 | c->operand[6] = 0x0d; /* offset lowbyte */ |
696 | clear_operands(c, 7, 8); /* padding */ | ||
681 | 697 | ||
682 | c->length = 12; | 698 | fdtv->avc_data_length = 12; |
683 | 699 | ret = avc_write(fdtv); | |
684 | if (avc_write(fdtv, c, r) < 0) | 700 | if (ret < 0) |
685 | return -EIO; | 701 | goto out; |
686 | 702 | ||
687 | if ((r->response != AVC_RESPONSE_STABLE && | 703 | if ((r->response != AVC_RESPONSE_STABLE && |
688 | r->response != AVC_RESPONSE_ACCEPTED) || | 704 | r->response != AVC_RESPONSE_ACCEPTED) || |
689 | (r->operand[3] << 8) + r->operand[4] != 8) { | 705 | (r->operand[3] << 8) + r->operand[4] != 8) { |
690 | dev_err(fdtv->device, "cannot read subunit identifier\n"); | 706 | dev_err(fdtv->device, "cannot read subunit identifier\n"); |
691 | return -EINVAL; | 707 | ret = -EINVAL; |
692 | } | 708 | } |
693 | return 0; | 709 | out: |
710 | mutex_unlock(&fdtv->avc_mutex); | ||
711 | |||
712 | return ret; | ||
694 | } | 713 | } |
695 | 714 | ||
696 | #define SIZEOF_ANTENNA_INPUT_INFO 22 | 715 | #define SIZEOF_ANTENNA_INPUT_INFO 22 |
697 | 716 | ||
698 | int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat) | 717 | int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat) |
699 | { | 718 | { |
700 | char buffer[sizeof(struct avc_command_frame)]; | 719 | struct avc_command_frame *c = (void *)fdtv->avc_data; |
701 | struct avc_command_frame *c = (void *)buffer; | 720 | struct avc_response_frame *r = (void *)fdtv->avc_data; |
702 | struct avc_response_frame *r = (void *)buffer; | 721 | int length, ret; |
703 | int length; | ||
704 | 722 | ||
705 | memset(c, 0, sizeof(*c)); | 723 | mutex_lock(&fdtv->avc_mutex); |
706 | 724 | ||
707 | c->ctype = AVC_CTYPE_CONTROL; | 725 | c->ctype = AVC_CTYPE_CONTROL; |
708 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; | 726 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; |
@@ -710,27 +728,30 @@ int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat) | |||
710 | 728 | ||
711 | c->operand[0] = DESCRIPTOR_TUNER_STATUS; | 729 | c->operand[0] = DESCRIPTOR_TUNER_STATUS; |
712 | c->operand[1] = 0xff; /* read_result_status */ | 730 | c->operand[1] = 0xff; /* read_result_status */ |
713 | c->operand[2] = 0x00; /* reserved */ | 731 | /* |
714 | c->operand[3] = 0; /* SIZEOF_ANTENNA_INPUT_INFO >> 8; */ | 732 | * operand[2]: reserved |
715 | c->operand[4] = 0; /* SIZEOF_ANTENNA_INPUT_INFO & 0xff; */ | 733 | * operand[3]: SIZEOF_ANTENNA_INPUT_INFO >> 8 |
716 | c->operand[5] = 0x00; | 734 | * operand[4]: SIZEOF_ANTENNA_INPUT_INFO & 0xff |
717 | c->operand[6] = 0x00; | 735 | */ |
718 | 736 | clear_operands(c, 2, 31); | |
719 | c->length = 12; | 737 | |
720 | 738 | fdtv->avc_data_length = 12; | |
721 | if (avc_write(fdtv, c, r) < 0) | 739 | ret = avc_write(fdtv); |
722 | return -EIO; | 740 | if (ret < 0) |
741 | goto out; | ||
723 | 742 | ||
724 | if (r->response != AVC_RESPONSE_STABLE && | 743 | if (r->response != AVC_RESPONSE_STABLE && |
725 | r->response != AVC_RESPONSE_ACCEPTED) { | 744 | r->response != AVC_RESPONSE_ACCEPTED) { |
726 | dev_err(fdtv->device, "cannot read tuner status\n"); | 745 | dev_err(fdtv->device, "cannot read tuner status\n"); |
727 | return -EINVAL; | 746 | ret = -EINVAL; |
747 | goto out; | ||
728 | } | 748 | } |
729 | 749 | ||
730 | length = r->operand[9]; | 750 | length = r->operand[9]; |
731 | if (r->operand[1] != 0x10 || length != SIZEOF_ANTENNA_INPUT_INFO) { | 751 | if (r->operand[1] != 0x10 || length != SIZEOF_ANTENNA_INPUT_INFO) { |
732 | dev_err(fdtv->device, "got invalid tuner status\n"); | 752 | dev_err(fdtv->device, "got invalid tuner status\n"); |
733 | return -EINVAL; | 753 | ret = -EINVAL; |
754 | goto out; | ||
734 | } | 755 | } |
735 | 756 | ||
736 | stat->active_system = r->operand[10]; | 757 | stat->active_system = r->operand[10]; |
@@ -766,20 +787,21 @@ int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat) | |||
766 | stat->ca_dvb_flag = r->operand[31] >> 3 & 1; | 787 | stat->ca_dvb_flag = r->operand[31] >> 3 & 1; |
767 | stat->ca_error_flag = r->operand[31] >> 2 & 1; | 788 | stat->ca_error_flag = r->operand[31] >> 2 & 1; |
768 | stat->ca_initialization_status = r->operand[31] >> 1 & 1; | 789 | stat->ca_initialization_status = r->operand[31] >> 1 & 1; |
790 | out: | ||
791 | mutex_unlock(&fdtv->avc_mutex); | ||
769 | 792 | ||
770 | return 0; | 793 | return ret; |
771 | } | 794 | } |
772 | 795 | ||
773 | int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst, | 796 | int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst, |
774 | char conttone, char nrdiseq, | 797 | char conttone, char nrdiseq, |
775 | struct dvb_diseqc_master_cmd *diseqcmd) | 798 | struct dvb_diseqc_master_cmd *diseqcmd) |
776 | { | 799 | { |
777 | char buffer[sizeof(struct avc_command_frame)]; | 800 | struct avc_command_frame *c = (void *)fdtv->avc_data; |
778 | struct avc_command_frame *c = (void *)buffer; | 801 | struct avc_response_frame *r = (void *)fdtv->avc_data; |
779 | struct avc_response_frame *r = (void *)buffer; | 802 | int pos, j, k, ret; |
780 | int i, j, k; | ||
781 | 803 | ||
782 | memset(c, 0, sizeof(*c)); | 804 | mutex_lock(&fdtv->avc_mutex); |
783 | 805 | ||
784 | c->ctype = AVC_CTYPE_CONTROL; | 806 | c->ctype = AVC_CTYPE_CONTROL; |
785 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; | 807 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; |
@@ -789,41 +811,41 @@ int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst, | |||
789 | c->operand[1] = SFE_VENDOR_DE_COMPANYID_1; | 811 | c->operand[1] = SFE_VENDOR_DE_COMPANYID_1; |
790 | c->operand[2] = SFE_VENDOR_DE_COMPANYID_2; | 812 | c->operand[2] = SFE_VENDOR_DE_COMPANYID_2; |
791 | c->operand[3] = SFE_VENDOR_OPCODE_LNB_CONTROL; | 813 | c->operand[3] = SFE_VENDOR_OPCODE_LNB_CONTROL; |
792 | |||
793 | c->operand[4] = voltage; | 814 | c->operand[4] = voltage; |
794 | c->operand[5] = nrdiseq; | 815 | c->operand[5] = nrdiseq; |
795 | 816 | ||
796 | i = 6; | 817 | pos = 6; |
797 | |||
798 | for (j = 0; j < nrdiseq; j++) { | 818 | for (j = 0; j < nrdiseq; j++) { |
799 | c->operand[i++] = diseqcmd[j].msg_len; | 819 | c->operand[pos++] = diseqcmd[j].msg_len; |
800 | 820 | ||
801 | for (k = 0; k < diseqcmd[j].msg_len; k++) | 821 | for (k = 0; k < diseqcmd[j].msg_len; k++) |
802 | c->operand[i++] = diseqcmd[j].msg[k]; | 822 | c->operand[pos++] = diseqcmd[j].msg[k]; |
803 | } | 823 | } |
824 | c->operand[pos++] = burst; | ||
825 | c->operand[pos++] = conttone; | ||
826 | pad_operands(c, pos); | ||
804 | 827 | ||
805 | c->operand[i++] = burst; | 828 | fdtv->avc_data_length = ALIGN(3 + pos, 4); |
806 | c->operand[i++] = conttone; | 829 | ret = avc_write(fdtv); |
807 | 830 | if (ret < 0) | |
808 | c->length = ALIGN(3 + i, 4); | 831 | goto out; |
809 | |||
810 | if (avc_write(fdtv, c, r) < 0) | ||
811 | return -EIO; | ||
812 | 832 | ||
813 | if (r->response != AVC_RESPONSE_ACCEPTED) { | 833 | if (r->response != AVC_RESPONSE_ACCEPTED) { |
814 | dev_err(fdtv->device, "LNB control failed\n"); | 834 | dev_err(fdtv->device, "LNB control failed\n"); |
815 | return -EINVAL; | 835 | ret = -EINVAL; |
816 | } | 836 | } |
837 | out: | ||
838 | mutex_unlock(&fdtv->avc_mutex); | ||
817 | 839 | ||
818 | return 0; | 840 | return ret; |
819 | } | 841 | } |
820 | 842 | ||
821 | int avc_register_remote_control(struct firedtv *fdtv) | 843 | int avc_register_remote_control(struct firedtv *fdtv) |
822 | { | 844 | { |
823 | char buffer[sizeof(struct avc_command_frame)]; | 845 | struct avc_command_frame *c = (void *)fdtv->avc_data; |
824 | struct avc_command_frame *c = (void *)buffer; | 846 | int ret; |
825 | 847 | ||
826 | memset(c, 0, sizeof(*c)); | 848 | mutex_lock(&fdtv->avc_mutex); |
827 | 849 | ||
828 | c->ctype = AVC_CTYPE_NOTIFY; | 850 | c->ctype = AVC_CTYPE_NOTIFY; |
829 | c->subunit = AVC_SUBUNIT_TYPE_UNIT | 7; | 851 | c->subunit = AVC_SUBUNIT_TYPE_UNIT | 7; |
@@ -833,10 +855,16 @@ int avc_register_remote_control(struct firedtv *fdtv) | |||
833 | c->operand[1] = SFE_VENDOR_DE_COMPANYID_1; | 855 | c->operand[1] = SFE_VENDOR_DE_COMPANYID_1; |
834 | c->operand[2] = SFE_VENDOR_DE_COMPANYID_2; | 856 | c->operand[2] = SFE_VENDOR_DE_COMPANYID_2; |
835 | c->operand[3] = SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL; | 857 | c->operand[3] = SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL; |
858 | c->operand[4] = 0; /* padding */ | ||
859 | |||
860 | fdtv->avc_data_length = 8; | ||
861 | ret = avc_write(fdtv); | ||
836 | 862 | ||
837 | c->length = 8; | 863 | /* FIXME: check response code? */ |
838 | 864 | ||
839 | return avc_write(fdtv, c, NULL); | 865 | mutex_unlock(&fdtv->avc_mutex); |
866 | |||
867 | return ret; | ||
840 | } | 868 | } |
841 | 869 | ||
842 | void avc_remote_ctrl_work(struct work_struct *work) | 870 | void avc_remote_ctrl_work(struct work_struct *work) |
@@ -851,11 +879,10 @@ void avc_remote_ctrl_work(struct work_struct *work) | |||
851 | #if 0 /* FIXME: unused */ | 879 | #if 0 /* FIXME: unused */ |
852 | int avc_tuner_host2ca(struct firedtv *fdtv) | 880 | int avc_tuner_host2ca(struct firedtv *fdtv) |
853 | { | 881 | { |
854 | char buffer[sizeof(struct avc_command_frame)]; | 882 | struct avc_command_frame *c = (void *)fdtv->avc_data; |
855 | struct avc_command_frame *c = (void *)buffer; | 883 | int ret; |
856 | struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */ | ||
857 | 884 | ||
858 | memset(c, 0, sizeof(*c)); | 885 | mutex_lock(&fdtv->avc_mutex); |
859 | 886 | ||
860 | c->ctype = AVC_CTYPE_CONTROL; | 887 | c->ctype = AVC_CTYPE_CONTROL; |
861 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; | 888 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; |
@@ -867,15 +894,16 @@ int avc_tuner_host2ca(struct firedtv *fdtv) | |||
867 | c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA; | 894 | c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA; |
868 | c->operand[4] = 0; /* slot */ | 895 | c->operand[4] = 0; /* slot */ |
869 | c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */ | 896 | c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */ |
870 | c->operand[6] = 0; /* more/last */ | 897 | clear_operands(c, 6, 8); |
871 | c->operand[7] = 0; /* length */ | ||
872 | 898 | ||
873 | c->length = 12; | 899 | fdtv->avc_data_length = 12; |
900 | ret = avc_write(fdtv); | ||
874 | 901 | ||
875 | if (avc_write(fdtv, c, r) < 0) | 902 | /* FIXME: check response code? */ |
876 | return -EIO; | ||
877 | 903 | ||
878 | return 0; | 904 | mutex_unlock(&fdtv->avc_mutex); |
905 | |||
906 | return ret; | ||
879 | } | 907 | } |
880 | #endif | 908 | #endif |
881 | 909 | ||
@@ -906,12 +934,11 @@ static int get_ca_object_length(struct avc_response_frame *r) | |||
906 | 934 | ||
907 | int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len) | 935 | int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len) |
908 | { | 936 | { |
909 | char buffer[sizeof(struct avc_command_frame)]; | 937 | struct avc_command_frame *c = (void *)fdtv->avc_data; |
910 | struct avc_command_frame *c = (void *)buffer; | 938 | struct avc_response_frame *r = (void *)fdtv->avc_data; |
911 | struct avc_response_frame *r = (void *)buffer; | 939 | int pos, ret; |
912 | int pos; | ||
913 | 940 | ||
914 | memset(c, 0, sizeof(*c)); | 941 | mutex_lock(&fdtv->avc_mutex); |
915 | 942 | ||
916 | c->ctype = AVC_CTYPE_STATUS; | 943 | c->ctype = AVC_CTYPE_STATUS; |
917 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; | 944 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; |
@@ -923,11 +950,12 @@ int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len) | |||
923 | c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST; | 950 | c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST; |
924 | c->operand[4] = 0; /* slot */ | 951 | c->operand[4] = 0; /* slot */ |
925 | c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */ | 952 | c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */ |
953 | clear_operands(c, 6, LAST_OPERAND); | ||
926 | 954 | ||
927 | c->length = 12; | 955 | fdtv->avc_data_length = 12; |
928 | 956 | ret = avc_write(fdtv); | |
929 | if (avc_write(fdtv, c, r) < 0) | 957 | if (ret < 0) |
930 | return -EIO; | 958 | goto out; |
931 | 959 | ||
932 | /* FIXME: check response code and validate response data */ | 960 | /* FIXME: check response code and validate response data */ |
933 | 961 | ||
@@ -939,18 +967,19 @@ int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len) | |||
939 | app_info[4] = 0x01; | 967 | app_info[4] = 0x01; |
940 | memcpy(&app_info[5], &r->operand[pos], 5 + r->operand[pos + 4]); | 968 | memcpy(&app_info[5], &r->operand[pos], 5 + r->operand[pos + 4]); |
941 | *len = app_info[3] + 4; | 969 | *len = app_info[3] + 4; |
970 | out: | ||
971 | mutex_unlock(&fdtv->avc_mutex); | ||
942 | 972 | ||
943 | return 0; | 973 | return ret; |
944 | } | 974 | } |
945 | 975 | ||
946 | int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len) | 976 | int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len) |
947 | { | 977 | { |
948 | char buffer[sizeof(struct avc_command_frame)]; | 978 | struct avc_command_frame *c = (void *)fdtv->avc_data; |
949 | struct avc_command_frame *c = (void *)buffer; | 979 | struct avc_response_frame *r = (void *)fdtv->avc_data; |
950 | struct avc_response_frame *r = (void *)buffer; | 980 | int pos, ret; |
951 | int pos; | ||
952 | 981 | ||
953 | memset(c, 0, sizeof(*c)); | 982 | mutex_lock(&fdtv->avc_mutex); |
954 | 983 | ||
955 | c->ctype = AVC_CTYPE_STATUS; | 984 | c->ctype = AVC_CTYPE_STATUS; |
956 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; | 985 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; |
@@ -962,11 +991,14 @@ int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len) | |||
962 | c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST; | 991 | c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST; |
963 | c->operand[4] = 0; /* slot */ | 992 | c->operand[4] = 0; /* slot */ |
964 | c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */ | 993 | c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */ |
994 | clear_operands(c, 6, LAST_OPERAND); | ||
965 | 995 | ||
966 | c->length = 12; | 996 | fdtv->avc_data_length = 12; |
997 | ret = avc_write(fdtv); | ||
998 | if (ret < 0) | ||
999 | goto out; | ||
967 | 1000 | ||
968 | if (avc_write(fdtv, c, r) < 0) | 1001 | /* FIXME: check response code and validate response data */ |
969 | return -EIO; | ||
970 | 1002 | ||
971 | pos = get_ca_object_pos(r); | 1003 | pos = get_ca_object_pos(r); |
972 | app_info[0] = (EN50221_TAG_CA_INFO >> 16) & 0xff; | 1004 | app_info[0] = (EN50221_TAG_CA_INFO >> 16) & 0xff; |
@@ -976,17 +1008,18 @@ int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len) | |||
976 | app_info[4] = r->operand[pos + 0]; | 1008 | app_info[4] = r->operand[pos + 0]; |
977 | app_info[5] = r->operand[pos + 1]; | 1009 | app_info[5] = r->operand[pos + 1]; |
978 | *len = app_info[3] + 4; | 1010 | *len = app_info[3] + 4; |
1011 | out: | ||
1012 | mutex_unlock(&fdtv->avc_mutex); | ||
979 | 1013 | ||
980 | return 0; | 1014 | return ret; |
981 | } | 1015 | } |
982 | 1016 | ||
983 | int avc_ca_reset(struct firedtv *fdtv) | 1017 | int avc_ca_reset(struct firedtv *fdtv) |
984 | { | 1018 | { |
985 | char buffer[sizeof(struct avc_command_frame)]; | 1019 | struct avc_command_frame *c = (void *)fdtv->avc_data; |
986 | struct avc_command_frame *c = (void *)buffer; | 1020 | int ret; |
987 | struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */ | ||
988 | 1021 | ||
989 | memset(c, 0, sizeof(*c)); | 1022 | mutex_lock(&fdtv->avc_mutex); |
990 | 1023 | ||
991 | c->ctype = AVC_CTYPE_CONTROL; | 1024 | c->ctype = AVC_CTYPE_CONTROL; |
992 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; | 1025 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; |
@@ -1002,19 +1035,20 @@ int avc_ca_reset(struct firedtv *fdtv) | |||
1002 | c->operand[7] = 1; /* length */ | 1035 | c->operand[7] = 1; /* length */ |
1003 | c->operand[8] = 0; /* force hardware reset */ | 1036 | c->operand[8] = 0; /* force hardware reset */ |
1004 | 1037 | ||
1005 | c->length = 12; | 1038 | fdtv->avc_data_length = 12; |
1039 | ret = avc_write(fdtv); | ||
1006 | 1040 | ||
1007 | if (avc_write(fdtv, c, r) < 0) | 1041 | /* FIXME: check response code? */ |
1008 | return -EIO; | ||
1009 | 1042 | ||
1010 | return 0; | 1043 | mutex_unlock(&fdtv->avc_mutex); |
1044 | |||
1045 | return ret; | ||
1011 | } | 1046 | } |
1012 | 1047 | ||
1013 | int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length) | 1048 | int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length) |
1014 | { | 1049 | { |
1015 | char buffer[sizeof(struct avc_command_frame)]; | 1050 | struct avc_command_frame *c = (void *)fdtv->avc_data; |
1016 | struct avc_command_frame *c = (void *)buffer; | 1051 | struct avc_response_frame *r = (void *)fdtv->avc_data; |
1017 | struct avc_response_frame *r = (void *)buffer; | ||
1018 | int list_management; | 1052 | int list_management; |
1019 | int program_info_length; | 1053 | int program_info_length; |
1020 | int pmt_cmd_id; | 1054 | int pmt_cmd_id; |
@@ -1022,11 +1056,12 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length) | |||
1022 | int write_pos; | 1056 | int write_pos; |
1023 | int es_info_length; | 1057 | int es_info_length; |
1024 | int crc32_csum; | 1058 | int crc32_csum; |
1059 | int ret; | ||
1025 | 1060 | ||
1026 | if (unlikely(avc_debug & AVC_DEBUG_APPLICATION_PMT)) | 1061 | if (unlikely(avc_debug & AVC_DEBUG_APPLICATION_PMT)) |
1027 | debug_pmt(msg, length); | 1062 | debug_pmt(msg, length); |
1028 | 1063 | ||
1029 | memset(c, 0, sizeof(*c)); | 1064 | mutex_lock(&fdtv->avc_mutex); |
1030 | 1065 | ||
1031 | c->ctype = AVC_CTYPE_CONTROL; | 1066 | c->ctype = AVC_CTYPE_CONTROL; |
1032 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; | 1067 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; |
@@ -1058,7 +1093,7 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length) | |||
1058 | 1093 | ||
1059 | c->operand[12] = 0x02; /* Table id=2 */ | 1094 | c->operand[12] = 0x02; /* Table id=2 */ |
1060 | c->operand[13] = 0x80; /* Section syntax + length */ | 1095 | c->operand[13] = 0x80; /* Section syntax + length */ |
1061 | /* c->operand[14] = XXXprogram_info_length + 12; */ | 1096 | |
1062 | c->operand[15] = msg[1]; /* Program number */ | 1097 | c->operand[15] = msg[1]; /* Program number */ |
1063 | c->operand[16] = msg[2]; | 1098 | c->operand[16] = msg[2]; |
1064 | c->operand[17] = 0x01; /* Version number=0 + current/next=1 */ | 1099 | c->operand[17] = 0x01; /* Version number=0 + current/next=1 */ |
@@ -1106,12 +1141,7 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length) | |||
1106 | write_pos += es_info_length; | 1141 | write_pos += es_info_length; |
1107 | } | 1142 | } |
1108 | } | 1143 | } |
1109 | 1144 | write_pos += 4; /* CRC */ | |
1110 | /* CRC */ | ||
1111 | c->operand[write_pos++] = 0x00; | ||
1112 | c->operand[write_pos++] = 0x00; | ||
1113 | c->operand[write_pos++] = 0x00; | ||
1114 | c->operand[write_pos++] = 0x00; | ||
1115 | 1145 | ||
1116 | c->operand[7] = 0x82; | 1146 | c->operand[7] = 0x82; |
1117 | c->operand[8] = (write_pos - 10) >> 8; | 1147 | c->operand[8] = (write_pos - 10) >> 8; |
@@ -1123,28 +1153,31 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length) | |||
1123 | c->operand[write_pos - 3] = (crc32_csum >> 16) & 0xff; | 1153 | c->operand[write_pos - 3] = (crc32_csum >> 16) & 0xff; |
1124 | c->operand[write_pos - 2] = (crc32_csum >> 8) & 0xff; | 1154 | c->operand[write_pos - 2] = (crc32_csum >> 8) & 0xff; |
1125 | c->operand[write_pos - 1] = (crc32_csum >> 0) & 0xff; | 1155 | c->operand[write_pos - 1] = (crc32_csum >> 0) & 0xff; |
1156 | pad_operands(c, write_pos); | ||
1126 | 1157 | ||
1127 | c->length = ALIGN(3 + write_pos, 4); | 1158 | fdtv->avc_data_length = ALIGN(3 + write_pos, 4); |
1128 | 1159 | ret = avc_write(fdtv); | |
1129 | if (avc_write(fdtv, c, r) < 0) | 1160 | if (ret < 0) |
1130 | return -EIO; | 1161 | goto out; |
1131 | 1162 | ||
1132 | if (r->response != AVC_RESPONSE_ACCEPTED) { | 1163 | if (r->response != AVC_RESPONSE_ACCEPTED) { |
1133 | dev_err(fdtv->device, | 1164 | dev_err(fdtv->device, |
1134 | "CA PMT failed with response 0x%x\n", r->response); | 1165 | "CA PMT failed with response 0x%x\n", r->response); |
1135 | return -EFAULT; | 1166 | ret = -EFAULT; |
1136 | } | 1167 | } |
1168 | out: | ||
1169 | mutex_unlock(&fdtv->avc_mutex); | ||
1137 | 1170 | ||
1138 | return 0; | 1171 | return ret; |
1139 | } | 1172 | } |
1140 | 1173 | ||
1141 | int avc_ca_get_time_date(struct firedtv *fdtv, int *interval) | 1174 | int avc_ca_get_time_date(struct firedtv *fdtv, int *interval) |
1142 | { | 1175 | { |
1143 | char buffer[sizeof(struct avc_command_frame)]; | 1176 | struct avc_command_frame *c = (void *)fdtv->avc_data; |
1144 | struct avc_command_frame *c = (void *)buffer; | 1177 | struct avc_response_frame *r = (void *)fdtv->avc_data; |
1145 | struct avc_response_frame *r = (void *)buffer; | 1178 | int ret; |
1146 | 1179 | ||
1147 | memset(c, 0, sizeof(*c)); | 1180 | mutex_lock(&fdtv->avc_mutex); |
1148 | 1181 | ||
1149 | c->ctype = AVC_CTYPE_STATUS; | 1182 | c->ctype = AVC_CTYPE_STATUS; |
1150 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; | 1183 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; |
@@ -1156,28 +1189,28 @@ int avc_ca_get_time_date(struct firedtv *fdtv, int *interval) | |||
1156 | c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST; | 1189 | c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST; |
1157 | c->operand[4] = 0; /* slot */ | 1190 | c->operand[4] = 0; /* slot */ |
1158 | c->operand[5] = SFE_VENDOR_TAG_CA_DATE_TIME; /* ca tag */ | 1191 | c->operand[5] = SFE_VENDOR_TAG_CA_DATE_TIME; /* ca tag */ |
1159 | c->operand[6] = 0; /* more/last */ | 1192 | clear_operands(c, 6, LAST_OPERAND); |
1160 | c->operand[7] = 0; /* length */ | ||
1161 | 1193 | ||
1162 | c->length = 12; | 1194 | fdtv->avc_data_length = 12; |
1163 | 1195 | ret = avc_write(fdtv); | |
1164 | if (avc_write(fdtv, c, r) < 0) | 1196 | if (ret < 0) |
1165 | return -EIO; | 1197 | goto out; |
1166 | 1198 | ||
1167 | /* FIXME: check response code and validate response data */ | 1199 | /* FIXME: check response code and validate response data */ |
1168 | 1200 | ||
1169 | *interval = r->operand[get_ca_object_pos(r)]; | 1201 | *interval = r->operand[get_ca_object_pos(r)]; |
1202 | out: | ||
1203 | mutex_unlock(&fdtv->avc_mutex); | ||
1170 | 1204 | ||
1171 | return 0; | 1205 | return ret; |
1172 | } | 1206 | } |
1173 | 1207 | ||
1174 | int avc_ca_enter_menu(struct firedtv *fdtv) | 1208 | int avc_ca_enter_menu(struct firedtv *fdtv) |
1175 | { | 1209 | { |
1176 | char buffer[sizeof(struct avc_command_frame)]; | 1210 | struct avc_command_frame *c = (void *)fdtv->avc_data; |
1177 | struct avc_command_frame *c = (void *)buffer; | 1211 | int ret; |
1178 | struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */ | ||
1179 | 1212 | ||
1180 | memset(c, 0, sizeof(*c)); | 1213 | mutex_lock(&fdtv->avc_mutex); |
1181 | 1214 | ||
1182 | c->ctype = AVC_CTYPE_STATUS; | 1215 | c->ctype = AVC_CTYPE_STATUS; |
1183 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; | 1216 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; |
@@ -1189,24 +1222,25 @@ int avc_ca_enter_menu(struct firedtv *fdtv) | |||
1189 | c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA; | 1222 | c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA; |
1190 | c->operand[4] = 0; /* slot */ | 1223 | c->operand[4] = 0; /* slot */ |
1191 | c->operand[5] = SFE_VENDOR_TAG_CA_ENTER_MENU; | 1224 | c->operand[5] = SFE_VENDOR_TAG_CA_ENTER_MENU; |
1192 | c->operand[6] = 0; /* more/last */ | 1225 | clear_operands(c, 6, 8); |
1193 | c->operand[7] = 0; /* length */ | ||
1194 | 1226 | ||
1195 | c->length = 12; | 1227 | fdtv->avc_data_length = 12; |
1228 | ret = avc_write(fdtv); | ||
1196 | 1229 | ||
1197 | if (avc_write(fdtv, c, r) < 0) | 1230 | /* FIXME: check response code? */ |
1198 | return -EIO; | ||
1199 | 1231 | ||
1200 | return 0; | 1232 | mutex_unlock(&fdtv->avc_mutex); |
1233 | |||
1234 | return ret; | ||
1201 | } | 1235 | } |
1202 | 1236 | ||
1203 | int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len) | 1237 | int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len) |
1204 | { | 1238 | { |
1205 | char buffer[sizeof(struct avc_command_frame)]; | 1239 | struct avc_command_frame *c = (void *)fdtv->avc_data; |
1206 | struct avc_command_frame *c = (void *)buffer; | 1240 | struct avc_response_frame *r = (void *)fdtv->avc_data; |
1207 | struct avc_response_frame *r = (void *)buffer; | 1241 | int ret; |
1208 | 1242 | ||
1209 | memset(c, 0, sizeof(*c)); | 1243 | mutex_lock(&fdtv->avc_mutex); |
1210 | 1244 | ||
1211 | c->ctype = AVC_CTYPE_STATUS; | 1245 | c->ctype = AVC_CTYPE_STATUS; |
1212 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; | 1246 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; |
@@ -1218,20 +1252,21 @@ int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len) | |||
1218 | c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST; | 1252 | c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST; |
1219 | c->operand[4] = 0; /* slot */ | 1253 | c->operand[4] = 0; /* slot */ |
1220 | c->operand[5] = SFE_VENDOR_TAG_CA_MMI; | 1254 | c->operand[5] = SFE_VENDOR_TAG_CA_MMI; |
1221 | c->operand[6] = 0; /* more/last */ | 1255 | clear_operands(c, 6, LAST_OPERAND); |
1222 | c->operand[7] = 0; /* length */ | ||
1223 | 1256 | ||
1224 | c->length = 12; | 1257 | fdtv->avc_data_length = 12; |
1225 | 1258 | ret = avc_write(fdtv); | |
1226 | if (avc_write(fdtv, c, r) < 0) | 1259 | if (ret < 0) |
1227 | return -EIO; | 1260 | goto out; |
1228 | 1261 | ||
1229 | /* FIXME: check response code and validate response data */ | 1262 | /* FIXME: check response code and validate response data */ |
1230 | 1263 | ||
1231 | *len = get_ca_object_length(r); | 1264 | *len = get_ca_object_length(r); |
1232 | memcpy(mmi_object, &r->operand[get_ca_object_pos(r)], *len); | 1265 | memcpy(mmi_object, &r->operand[get_ca_object_pos(r)], *len); |
1266 | out: | ||
1267 | mutex_unlock(&fdtv->avc_mutex); | ||
1233 | 1268 | ||
1234 | return 0; | 1269 | return ret; |
1235 | } | 1270 | } |
1236 | 1271 | ||
1237 | #define CMP_OUTPUT_PLUG_CONTROL_REG_0 0xfffff0000904ULL | 1272 | #define CMP_OUTPUT_PLUG_CONTROL_REG_0 0xfffff0000904ULL |
@@ -1240,14 +1275,14 @@ static int cmp_read(struct firedtv *fdtv, u64 addr, __be32 *data) | |||
1240 | { | 1275 | { |
1241 | int ret; | 1276 | int ret; |
1242 | 1277 | ||
1243 | if (mutex_lock_interruptible(&fdtv->avc_mutex)) | 1278 | mutex_lock(&fdtv->avc_mutex); |
1244 | return -EINTR; | ||
1245 | 1279 | ||
1246 | ret = fdtv->backend->read(fdtv, addr, data); | 1280 | ret = fdtv->backend->read(fdtv, addr, data); |
1247 | if (ret < 0) | 1281 | if (ret < 0) |
1248 | dev_err(fdtv->device, "CMP: read I/O error\n"); | 1282 | dev_err(fdtv->device, "CMP: read I/O error\n"); |
1249 | 1283 | ||
1250 | mutex_unlock(&fdtv->avc_mutex); | 1284 | mutex_unlock(&fdtv->avc_mutex); |
1285 | |||
1251 | return ret; | 1286 | return ret; |
1252 | } | 1287 | } |
1253 | 1288 | ||
@@ -1255,14 +1290,19 @@ static int cmp_lock(struct firedtv *fdtv, u64 addr, __be32 data[]) | |||
1255 | { | 1290 | { |
1256 | int ret; | 1291 | int ret; |
1257 | 1292 | ||
1258 | if (mutex_lock_interruptible(&fdtv->avc_mutex)) | 1293 | mutex_lock(&fdtv->avc_mutex); |
1259 | return -EINTR; | 1294 | |
1295 | /* data[] is stack-allocated and should not be DMA-mapped. */ | ||
1296 | memcpy(fdtv->avc_data, data, 8); | ||
1260 | 1297 | ||
1261 | ret = fdtv->backend->lock(fdtv, addr, data); | 1298 | ret = fdtv->backend->lock(fdtv, addr, fdtv->avc_data); |
1262 | if (ret < 0) | 1299 | if (ret < 0) |
1263 | dev_err(fdtv->device, "CMP: lock I/O error\n"); | 1300 | dev_err(fdtv->device, "CMP: lock I/O error\n"); |
1301 | else | ||
1302 | memcpy(data, fdtv->avc_data, 8); | ||
1264 | 1303 | ||
1265 | mutex_unlock(&fdtv->avc_mutex); | 1304 | mutex_unlock(&fdtv->avc_mutex); |
1305 | |||
1266 | return ret; | 1306 | return ret; |
1267 | } | 1307 | } |
1268 | 1308 | ||
diff --git a/drivers/media/dvb/firewire/firedtv-dvb.c b/drivers/media/dvb/firewire/firedtv-dvb.c index fc9996c13e13..079e8c5b0475 100644 --- a/drivers/media/dvb/firewire/firedtv-dvb.c +++ b/drivers/media/dvb/firewire/firedtv-dvb.c | |||
@@ -277,7 +277,6 @@ struct firedtv *fdtv_alloc(struct device *dev, | |||
277 | 277 | ||
278 | mutex_init(&fdtv->avc_mutex); | 278 | mutex_init(&fdtv->avc_mutex); |
279 | init_waitqueue_head(&fdtv->avc_wait); | 279 | init_waitqueue_head(&fdtv->avc_wait); |
280 | fdtv->avc_reply_received = true; | ||
281 | mutex_init(&fdtv->demux_mutex); | 280 | mutex_init(&fdtv->demux_mutex); |
282 | INIT_WORK(&fdtv->remote_ctrl_work, avc_remote_ctrl_work); | 281 | INIT_WORK(&fdtv->remote_ctrl_work, avc_remote_ctrl_work); |
283 | 282 | ||
diff --git a/drivers/media/dvb/firewire/firedtv-fw.c b/drivers/media/dvb/firewire/firedtv-fw.c index 6223bf01efe9..7a3de16fba06 100644 --- a/drivers/media/dvb/firewire/firedtv-fw.c +++ b/drivers/media/dvb/firewire/firedtv-fw.c | |||
@@ -41,7 +41,7 @@ static int node_req(struct firedtv *fdtv, u64 addr, void *data, size_t len, | |||
41 | return rcode != RCODE_COMPLETE ? -EIO : 0; | 41 | return rcode != RCODE_COMPLETE ? -EIO : 0; |
42 | } | 42 | } |
43 | 43 | ||
44 | static int node_lock(struct firedtv *fdtv, u64 addr, __be32 data[]) | 44 | static int node_lock(struct firedtv *fdtv, u64 addr, void *data) |
45 | { | 45 | { |
46 | return node_req(fdtv, addr, data, 8, TCODE_LOCK_COMPARE_SWAP); | 46 | return node_req(fdtv, addr, data, 8, TCODE_LOCK_COMPARE_SWAP); |
47 | } | 47 | } |
diff --git a/drivers/media/dvb/firewire/firedtv.h b/drivers/media/dvb/firewire/firedtv.h index 35080dbb3c66..78cc28f36914 100644 --- a/drivers/media/dvb/firewire/firedtv.h +++ b/drivers/media/dvb/firewire/firedtv.h | |||
@@ -73,7 +73,7 @@ struct input_dev; | |||
73 | struct firedtv; | 73 | struct firedtv; |
74 | 74 | ||
75 | struct firedtv_backend { | 75 | struct firedtv_backend { |
76 | int (*lock)(struct firedtv *fdtv, u64 addr, __be32 data[]); | 76 | int (*lock)(struct firedtv *fdtv, u64 addr, void *data); |
77 | int (*read)(struct firedtv *fdtv, u64 addr, void *data); | 77 | int (*read)(struct firedtv *fdtv, u64 addr, void *data); |
78 | int (*write)(struct firedtv *fdtv, u64 addr, void *data, size_t len); | 78 | int (*write)(struct firedtv *fdtv, u64 addr, void *data, size_t len); |
79 | int (*start_iso)(struct firedtv *fdtv); | 79 | int (*start_iso)(struct firedtv *fdtv); |
@@ -114,8 +114,8 @@ struct firedtv { | |||
114 | unsigned long channel_active; | 114 | unsigned long channel_active; |
115 | u16 channel_pid[16]; | 115 | u16 channel_pid[16]; |
116 | 116 | ||
117 | size_t response_length; | 117 | int avc_data_length; |
118 | u8 response[512]; | 118 | u8 avc_data[512]; |
119 | }; | 119 | }; |
120 | 120 | ||
121 | /* firedtv-1394.c */ | 121 | /* firedtv-1394.c */ |
diff --git a/drivers/media/dvb/frontends/af9013.h b/drivers/media/dvb/frontends/af9013.h index 28b90c91c766..e90fa92b1c1d 100644 --- a/drivers/media/dvb/frontends/af9013.h +++ b/drivers/media/dvb/frontends/af9013.h | |||
@@ -44,6 +44,7 @@ enum af9013_tuner { | |||
44 | AF9013_TUNER_MT2060_2 = 147, /* Microtune */ | 44 | AF9013_TUNER_MT2060_2 = 147, /* Microtune */ |
45 | AF9013_TUNER_TDA18271 = 156, /* NXP */ | 45 | AF9013_TUNER_TDA18271 = 156, /* NXP */ |
46 | AF9013_TUNER_QT1010A = 162, /* Quantek */ | 46 | AF9013_TUNER_QT1010A = 162, /* Quantek */ |
47 | AF9013_TUNER_TDA18218 = 179, /* NXP */ | ||
47 | }; | 48 | }; |
48 | 49 | ||
49 | /* AF9013/5 GPIOs (mostly guessed) | 50 | /* AF9013/5 GPIOs (mostly guessed) |
diff --git a/drivers/media/dvb/frontends/atbm8830.c b/drivers/media/dvb/frontends/atbm8830.c index 59881a5944eb..43aac2f85c2e 100644 --- a/drivers/media/dvb/frontends/atbm8830.c +++ b/drivers/media/dvb/frontends/atbm8830.c | |||
@@ -170,6 +170,19 @@ static int is_locked(struct atbm_state *priv, u8 *locked) | |||
170 | return 0; | 170 | return 0; |
171 | } | 171 | } |
172 | 172 | ||
173 | static int set_agc_config(struct atbm_state *priv, | ||
174 | u8 min, u8 max, u8 hold_loop) | ||
175 | { | ||
176 | /* no effect if both min and max are zero */ | ||
177 | if (!min && !max) | ||
178 | return 0; | ||
179 | |||
180 | atbm8830_write_reg(priv, REG_AGC_MIN, min); | ||
181 | atbm8830_write_reg(priv, REG_AGC_MAX, max); | ||
182 | atbm8830_write_reg(priv, REG_AGC_HOLD_LOOP, hold_loop); | ||
183 | |||
184 | return 0; | ||
185 | } | ||
173 | 186 | ||
174 | static int set_static_channel_mode(struct atbm_state *priv) | 187 | static int set_static_channel_mode(struct atbm_state *priv) |
175 | { | 188 | { |
@@ -227,6 +240,9 @@ static int atbm8830_init(struct dvb_frontend *fe) | |||
227 | /*Set IF frequency*/ | 240 | /*Set IF frequency*/ |
228 | set_if_freq(priv, cfg->if_freq); | 241 | set_if_freq(priv, cfg->if_freq); |
229 | 242 | ||
243 | /*Set AGC Config*/ | ||
244 | set_agc_config(priv, cfg->agc_min, cfg->agc_max, | ||
245 | cfg->agc_hold_loop); | ||
230 | 246 | ||
231 | /*Set static channel mode*/ | 247 | /*Set static channel mode*/ |
232 | set_static_channel_mode(priv); | 248 | set_static_channel_mode(priv); |
diff --git a/drivers/media/dvb/frontends/dib0090.c b/drivers/media/dvb/frontends/dib0090.c index 614552709a6f..7eac178f57b2 100644 --- a/drivers/media/dvb/frontends/dib0090.c +++ b/drivers/media/dvb/frontends/dib0090.c | |||
@@ -283,7 +283,7 @@ static int dib0090_sleep(struct dvb_frontend *fe) | |||
283 | return 0; | 283 | return 0; |
284 | } | 284 | } |
285 | 285 | ||
286 | extern void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast) | 286 | void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast) |
287 | { | 287 | { |
288 | struct dib0090_state *state = fe->tuner_priv; | 288 | struct dib0090_state *state = fe->tuner_priv; |
289 | if (fast) | 289 | if (fast) |
diff --git a/drivers/media/dvb/frontends/dib8000.c b/drivers/media/dvb/frontends/dib8000.c index 6f6fa29d9ea4..2aa97dd6a8af 100644 --- a/drivers/media/dvb/frontends/dib8000.c +++ b/drivers/media/dvb/frontends/dib8000.c | |||
@@ -1999,6 +1999,8 @@ static int dib8000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par | |||
1999 | struct dib8000_state *state = fe->demodulator_priv; | 1999 | struct dib8000_state *state = fe->demodulator_priv; |
2000 | int time, ret; | 2000 | int time, ret; |
2001 | 2001 | ||
2002 | fe->dtv_property_cache.delivery_system = SYS_ISDBT; | ||
2003 | |||
2002 | dib8000_set_output_mode(state, OUTMODE_HIGH_Z); | 2004 | dib8000_set_output_mode(state, OUTMODE_HIGH_Z); |
2003 | 2005 | ||
2004 | if (fe->ops.tuner_ops.set_params) | 2006 | if (fe->ops.tuner_ops.set_params) |
diff --git a/drivers/media/dvb/frontends/dibx000_common.c b/drivers/media/dvb/frontends/dibx000_common.c index e6f3d73db9d3..980e02f1575e 100644 --- a/drivers/media/dvb/frontends/dibx000_common.c +++ b/drivers/media/dvb/frontends/dibx000_common.c | |||
@@ -174,7 +174,7 @@ void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst) | |||
174 | EXPORT_SYMBOL(dibx000_exit_i2c_master); | 174 | EXPORT_SYMBOL(dibx000_exit_i2c_master); |
175 | 175 | ||
176 | 176 | ||
177 | u32 systime() | 177 | u32 systime(void) |
178 | { | 178 | { |
179 | struct timespec t; | 179 | struct timespec t; |
180 | 180 | ||
diff --git a/drivers/media/dvb/frontends/lnbp21.c b/drivers/media/dvb/frontends/lnbp21.c index b181bf023ada..13437259eeac 100644 --- a/drivers/media/dvb/frontends/lnbp21.c +++ b/drivers/media/dvb/frontends/lnbp21.c | |||
@@ -158,7 +158,8 @@ static struct dvb_frontend *lnbx2x_attach(struct dvb_frontend *fe, | |||
158 | /* override frontend ops */ | 158 | /* override frontend ops */ |
159 | fe->ops.set_voltage = lnbp21_set_voltage; | 159 | fe->ops.set_voltage = lnbp21_set_voltage; |
160 | fe->ops.enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage; | 160 | fe->ops.enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage; |
161 | fe->ops.set_tone = lnbp21_set_tone; | 161 | if (!(override_clear & LNBH24_TEN)) /*22kHz logic controlled by demod*/ |
162 | fe->ops.set_tone = lnbp21_set_tone; | ||
162 | printk(KERN_INFO "LNBx2x attached on addr=%x\n", lnbp21->i2c_addr); | 163 | printk(KERN_INFO "LNBx2x attached on addr=%x\n", lnbp21->i2c_addr); |
163 | 164 | ||
164 | return fe; | 165 | return fe; |
diff --git a/drivers/media/dvb/frontends/si21xx.c b/drivers/media/dvb/frontends/si21xx.c index 9552a22ccffb..d21a327db629 100644 --- a/drivers/media/dvb/frontends/si21xx.c +++ b/drivers/media/dvb/frontends/si21xx.c | |||
@@ -97,8 +97,6 @@ | |||
97 | #define LNB_SUPPLY_CTRL_REG_4 0xce | 97 | #define LNB_SUPPLY_CTRL_REG_4 0xce |
98 | #define LNB_SUPPLY_STATUS_REG 0xcf | 98 | #define LNB_SUPPLY_STATUS_REG 0xcf |
99 | 99 | ||
100 | #define FALSE 0 | ||
101 | #define TRUE 1 | ||
102 | #define FAIL -1 | 100 | #define FAIL -1 |
103 | #define PASS 0 | 101 | #define PASS 0 |
104 | 102 | ||
@@ -718,7 +716,7 @@ static int si21xx_set_frontend(struct dvb_frontend *fe, | |||
718 | int fine_tune_freq; | 716 | int fine_tune_freq; |
719 | unsigned char sample_rate = 0; | 717 | unsigned char sample_rate = 0; |
720 | /* boolean */ | 718 | /* boolean */ |
721 | unsigned int inband_interferer_ind; | 719 | bool inband_interferer_ind; |
722 | 720 | ||
723 | /* INTERMEDIATE VALUES */ | 721 | /* INTERMEDIATE VALUES */ |
724 | int icoarse_tune_freq; /* MHz */ | 722 | int icoarse_tune_freq; /* MHz */ |
@@ -728,15 +726,8 @@ static int si21xx_set_frontend(struct dvb_frontend *fe, | |||
728 | unsigned int x1; | 726 | unsigned int x1; |
729 | unsigned int x2; | 727 | unsigned int x2; |
730 | int i; | 728 | int i; |
731 | unsigned int inband_interferer_div2[ALLOWABLE_FS_COUNT] = { | 729 | bool inband_interferer_div2[ALLOWABLE_FS_COUNT]; |
732 | FALSE, FALSE, FALSE, FALSE, FALSE, | 730 | bool inband_interferer_div4[ALLOWABLE_FS_COUNT]; |
733 | FALSE, FALSE, FALSE, FALSE, FALSE | ||
734 | }; | ||
735 | unsigned int inband_interferer_div4[ALLOWABLE_FS_COUNT] = { | ||
736 | FALSE, FALSE, FALSE, FALSE, FALSE, | ||
737 | FALSE, FALSE, FALSE, FALSE, FALSE | ||
738 | }; | ||
739 | |||
740 | int status; | 731 | int status; |
741 | 732 | ||
742 | /* allowable sample rates for ADC in MHz */ | 733 | /* allowable sample rates for ADC in MHz */ |
@@ -762,7 +753,7 @@ static int si21xx_set_frontend(struct dvb_frontend *fe, | |||
762 | } | 753 | } |
763 | 754 | ||
764 | for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) | 755 | for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) |
765 | inband_interferer_div2[i] = inband_interferer_div4[i] = FALSE; | 756 | inband_interferer_div2[i] = inband_interferer_div4[i] = false; |
766 | 757 | ||
767 | if_limit_high = -700000; | 758 | if_limit_high = -700000; |
768 | if_limit_low = -100000; | 759 | if_limit_low = -100000; |
@@ -798,7 +789,7 @@ static int si21xx_set_frontend(struct dvb_frontend *fe, | |||
798 | 789 | ||
799 | if (((band_low < x1) && (x1 < band_high)) || | 790 | if (((band_low < x1) && (x1 < band_high)) || |
800 | ((band_low < x2) && (x2 < band_high))) | 791 | ((band_low < x2) && (x2 < band_high))) |
801 | inband_interferer_div4[i] = TRUE; | 792 | inband_interferer_div4[i] = true; |
802 | 793 | ||
803 | } | 794 | } |
804 | 795 | ||
@@ -811,25 +802,28 @@ static int si21xx_set_frontend(struct dvb_frontend *fe, | |||
811 | 802 | ||
812 | if (((band_low < x1) && (x1 < band_high)) || | 803 | if (((band_low < x1) && (x1 < band_high)) || |
813 | ((band_low < x2) && (x2 < band_high))) | 804 | ((band_low < x2) && (x2 < band_high))) |
814 | inband_interferer_div2[i] = TRUE; | 805 | inband_interferer_div2[i] = true; |
815 | } | 806 | } |
816 | 807 | ||
817 | inband_interferer_ind = TRUE; | 808 | inband_interferer_ind = true; |
818 | for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) | 809 | for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) { |
819 | inband_interferer_ind &= inband_interferer_div2[i] | | 810 | if (inband_interferer_div2[i] || inband_interferer_div4[i]) { |
820 | inband_interferer_div4[i]; | 811 | inband_interferer_ind = false; |
812 | break; | ||
813 | } | ||
814 | } | ||
821 | 815 | ||
822 | if (inband_interferer_ind) { | 816 | if (inband_interferer_ind) { |
823 | for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) { | 817 | for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) { |
824 | if (inband_interferer_div2[i] == FALSE) { | 818 | if (!inband_interferer_div2[i]) { |
825 | sample_rate = (u8) afs[i]; | 819 | sample_rate = (u8) afs[i]; |
826 | break; | 820 | break; |
827 | } | 821 | } |
828 | } | 822 | } |
829 | } else { | 823 | } else { |
830 | for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) { | 824 | for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) { |
831 | if ((inband_interferer_div2[i] | | 825 | if ((inband_interferer_div2[i] || |
832 | inband_interferer_div4[i]) == FALSE) { | 826 | !inband_interferer_div4[i])) { |
833 | sample_rate = (u8) afs[i]; | 827 | sample_rate = (u8) afs[i]; |
834 | break; | 828 | break; |
835 | } | 829 | } |
diff --git a/drivers/media/dvb/frontends/stv0900.h b/drivers/media/dvb/frontends/stv0900.h index 29c3fa85c227..e3e35d1ce838 100644 --- a/drivers/media/dvb/frontends/stv0900.h +++ b/drivers/media/dvb/frontends/stv0900.h | |||
@@ -49,6 +49,8 @@ struct stv0900_config { | |||
49 | u8 tun2_maddress; | 49 | u8 tun2_maddress; |
50 | u8 tun1_adc;/* 1 for stv6110, 2 for stb6100 */ | 50 | u8 tun1_adc;/* 1 for stv6110, 2 for stb6100 */ |
51 | u8 tun2_adc; | 51 | u8 tun2_adc; |
52 | u8 tun1_type;/* for now 3 for stb6100 auto, else - software */ | ||
53 | u8 tun2_type; | ||
52 | /* Set device param to start dma */ | 54 | /* Set device param to start dma */ |
53 | int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured); | 55 | int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured); |
54 | }; | 56 | }; |
diff --git a/drivers/media/dvb/frontends/stv0900_core.c b/drivers/media/dvb/frontends/stv0900_core.c index 8762c86044a5..01f8f1f802fd 100644 --- a/drivers/media/dvb/frontends/stv0900_core.c +++ b/drivers/media/dvb/frontends/stv0900_core.c | |||
@@ -177,7 +177,7 @@ u8 stv0900_read_reg(struct stv0900_internal *intp, u16 reg) | |||
177 | return buf; | 177 | return buf; |
178 | } | 178 | } |
179 | 179 | ||
180 | void extract_mask_pos(u32 label, u8 *mask, u8 *pos) | 180 | static void extract_mask_pos(u32 label, u8 *mask, u8 *pos) |
181 | { | 181 | { |
182 | u8 position = 0, i = 0; | 182 | u8 position = 0, i = 0; |
183 | 183 | ||
@@ -218,7 +218,7 @@ u8 stv0900_get_bits(struct stv0900_internal *intp, u32 label) | |||
218 | return val; | 218 | return val; |
219 | } | 219 | } |
220 | 220 | ||
221 | enum fe_stv0900_error stv0900_initialize(struct stv0900_internal *intp) | 221 | static enum fe_stv0900_error stv0900_initialize(struct stv0900_internal *intp) |
222 | { | 222 | { |
223 | s32 i; | 223 | s32 i; |
224 | 224 | ||
@@ -282,7 +282,7 @@ enum fe_stv0900_error stv0900_initialize(struct stv0900_internal *intp) | |||
282 | return STV0900_NO_ERROR; | 282 | return STV0900_NO_ERROR; |
283 | } | 283 | } |
284 | 284 | ||
285 | u32 stv0900_get_mclk_freq(struct stv0900_internal *intp, u32 ext_clk) | 285 | static u32 stv0900_get_mclk_freq(struct stv0900_internal *intp, u32 ext_clk) |
286 | { | 286 | { |
287 | u32 mclk = 90000000, div = 0, ad_div = 0; | 287 | u32 mclk = 90000000, div = 0, ad_div = 0; |
288 | 288 | ||
@@ -296,7 +296,7 @@ u32 stv0900_get_mclk_freq(struct stv0900_internal *intp, u32 ext_clk) | |||
296 | return mclk; | 296 | return mclk; |
297 | } | 297 | } |
298 | 298 | ||
299 | enum fe_stv0900_error stv0900_set_mclk(struct stv0900_internal *intp, u32 mclk) | 299 | static enum fe_stv0900_error stv0900_set_mclk(struct stv0900_internal *intp, u32 mclk) |
300 | { | 300 | { |
301 | u32 m_div, clk_sel; | 301 | u32 m_div, clk_sel; |
302 | 302 | ||
@@ -334,7 +334,7 @@ enum fe_stv0900_error stv0900_set_mclk(struct stv0900_internal *intp, u32 mclk) | |||
334 | return STV0900_NO_ERROR; | 334 | return STV0900_NO_ERROR; |
335 | } | 335 | } |
336 | 336 | ||
337 | u32 stv0900_get_err_count(struct stv0900_internal *intp, int cntr, | 337 | static u32 stv0900_get_err_count(struct stv0900_internal *intp, int cntr, |
338 | enum fe_stv0900_demod_num demod) | 338 | enum fe_stv0900_demod_num demod) |
339 | { | 339 | { |
340 | u32 lsb, msb, hsb, err_val; | 340 | u32 lsb, msb, hsb, err_val; |
@@ -567,6 +567,46 @@ void stv0900_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth) | |||
567 | } | 567 | } |
568 | } | 568 | } |
569 | 569 | ||
570 | u32 stv0900_get_freq_auto(struct stv0900_internal *intp, int demod) | ||
571 | { | ||
572 | u32 freq, round; | ||
573 | /* Formulat : | ||
574 | Tuner_Frequency(MHz) = Regs / 64 | ||
575 | Tuner_granularity(MHz) = Regs / 2048 | ||
576 | real_Tuner_Frequency = Tuner_Frequency(MHz) - Tuner_granularity(MHz) | ||
577 | */ | ||
578 | freq = (stv0900_get_bits(intp, TUN_RFFREQ2) << 10) + | ||
579 | (stv0900_get_bits(intp, TUN_RFFREQ1) << 2) + | ||
580 | stv0900_get_bits(intp, TUN_RFFREQ0); | ||
581 | |||
582 | freq = (freq * 1000) / 64; | ||
583 | |||
584 | round = (stv0900_get_bits(intp, TUN_RFRESTE1) >> 2) + | ||
585 | stv0900_get_bits(intp, TUN_RFRESTE0); | ||
586 | |||
587 | round = (round * 1000) / 2048; | ||
588 | |||
589 | return freq + round; | ||
590 | } | ||
591 | |||
592 | void stv0900_set_tuner_auto(struct stv0900_internal *intp, u32 Frequency, | ||
593 | u32 Bandwidth, int demod) | ||
594 | { | ||
595 | u32 tunerFrequency; | ||
596 | /* Formulat: | ||
597 | Tuner_frequency_reg= Frequency(MHz)*64 | ||
598 | */ | ||
599 | tunerFrequency = (Frequency * 64) / 1000; | ||
600 | |||
601 | stv0900_write_bits(intp, TUN_RFFREQ2, (tunerFrequency >> 10)); | ||
602 | stv0900_write_bits(intp, TUN_RFFREQ1, (tunerFrequency >> 2) & 0xff); | ||
603 | stv0900_write_bits(intp, TUN_RFFREQ0, (tunerFrequency & 0x03)); | ||
604 | /* Low Pass Filter = BW /2 (MHz)*/ | ||
605 | stv0900_write_bits(intp, TUN_BW, Bandwidth / 2000000); | ||
606 | /* Tuner Write trig */ | ||
607 | stv0900_write_reg(intp, TNRLD, 1); | ||
608 | } | ||
609 | |||
570 | static s32 stv0900_get_rf_level(struct stv0900_internal *intp, | 610 | static s32 stv0900_get_rf_level(struct stv0900_internal *intp, |
571 | const struct stv0900_table *lookup, | 611 | const struct stv0900_table *lookup, |
572 | enum fe_stv0900_demod_num demod) | 612 | enum fe_stv0900_demod_num demod) |
@@ -1329,7 +1369,6 @@ static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe, | |||
1329 | enum fe_stv0900_error error = STV0900_NO_ERROR; | 1369 | enum fe_stv0900_error error = STV0900_NO_ERROR; |
1330 | enum fe_stv0900_error demodError = STV0900_NO_ERROR; | 1370 | enum fe_stv0900_error demodError = STV0900_NO_ERROR; |
1331 | struct stv0900_internal *intp = NULL; | 1371 | struct stv0900_internal *intp = NULL; |
1332 | |||
1333 | int selosci, i; | 1372 | int selosci, i; |
1334 | 1373 | ||
1335 | struct stv0900_inode *temp_int = find_inode(state->i2c_adap, | 1374 | struct stv0900_inode *temp_int = find_inode(state->i2c_adap, |
@@ -1345,7 +1384,14 @@ static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe, | |||
1345 | } else { | 1384 | } else { |
1346 | state->internal = kmalloc(sizeof(struct stv0900_internal), | 1385 | state->internal = kmalloc(sizeof(struct stv0900_internal), |
1347 | GFP_KERNEL); | 1386 | GFP_KERNEL); |
1387 | if (state->internal == NULL) | ||
1388 | return STV0900_INVALID_HANDLE; | ||
1348 | temp_int = append_internal(state->internal); | 1389 | temp_int = append_internal(state->internal); |
1390 | if (temp_int == NULL) { | ||
1391 | kfree(state->internal); | ||
1392 | state->internal = NULL; | ||
1393 | return STV0900_INVALID_HANDLE; | ||
1394 | } | ||
1349 | state->internal->dmds_used = 1; | 1395 | state->internal->dmds_used = 1; |
1350 | state->internal->i2c_adap = state->i2c_adap; | 1396 | state->internal->i2c_adap = state->i2c_adap; |
1351 | state->internal->i2c_addr = state->config->demod_address; | 1397 | state->internal->i2c_addr = state->config->demod_address; |
@@ -1371,11 +1417,6 @@ static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe, | |||
1371 | return error; | 1417 | return error; |
1372 | } | 1418 | } |
1373 | 1419 | ||
1374 | if (state->internal == NULL) { | ||
1375 | error = STV0900_INVALID_HANDLE; | ||
1376 | return error; | ||
1377 | } | ||
1378 | |||
1379 | intp = state->internal; | 1420 | intp = state->internal; |
1380 | 1421 | ||
1381 | intp->demod_mode = p_init->demod_mode; | 1422 | intp->demod_mode = p_init->demod_mode; |
@@ -1404,6 +1445,27 @@ static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe, | |||
1404 | stv0900_write_bits(intp, F0900_P1_RST_HWARE, 0); | 1445 | stv0900_write_bits(intp, F0900_P1_RST_HWARE, 0); |
1405 | } | 1446 | } |
1406 | 1447 | ||
1448 | intp->tuner_type[0] = p_init->tuner1_type; | ||
1449 | intp->tuner_type[1] = p_init->tuner2_type; | ||
1450 | /* tuner init */ | ||
1451 | switch (p_init->tuner1_type) { | ||
1452 | case 3: /*FE_AUTO_STB6100:*/ | ||
1453 | stv0900_write_reg(intp, R0900_P1_TNRCFG, 0x3c); | ||
1454 | stv0900_write_reg(intp, R0900_P1_TNRCFG2, 0x86); | ||
1455 | stv0900_write_reg(intp, R0900_P1_TNRCFG3, 0x18); | ||
1456 | stv0900_write_reg(intp, R0900_P1_TNRXTAL, 27); /* 27MHz */ | ||
1457 | stv0900_write_reg(intp, R0900_P1_TNRSTEPS, 0x05); | ||
1458 | stv0900_write_reg(intp, R0900_P1_TNRGAIN, 0x17); | ||
1459 | stv0900_write_reg(intp, R0900_P1_TNRADJ, 0x1f); | ||
1460 | stv0900_write_reg(intp, R0900_P1_TNRCTL2, 0x0); | ||
1461 | stv0900_write_bits(intp, F0900_P1_TUN_TYPE, 3); | ||
1462 | break; | ||
1463 | /* case FE_SW_TUNER: */ | ||
1464 | default: | ||
1465 | stv0900_write_bits(intp, F0900_P1_TUN_TYPE, 6); | ||
1466 | break; | ||
1467 | } | ||
1468 | |||
1407 | stv0900_write_bits(intp, F0900_P1_TUN_MADDRESS, p_init->tun1_maddress); | 1469 | stv0900_write_bits(intp, F0900_P1_TUN_MADDRESS, p_init->tun1_maddress); |
1408 | switch (p_init->tuner1_adc) { | 1470 | switch (p_init->tuner1_adc) { |
1409 | case 1: | 1471 | case 1: |
@@ -1413,6 +1475,27 @@ static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe, | |||
1413 | break; | 1475 | break; |
1414 | } | 1476 | } |
1415 | 1477 | ||
1478 | stv0900_write_reg(intp, R0900_P1_TNRLD, 1); /* hw tuner */ | ||
1479 | |||
1480 | /* tuner init */ | ||
1481 | switch (p_init->tuner2_type) { | ||
1482 | case 3: /*FE_AUTO_STB6100:*/ | ||
1483 | stv0900_write_reg(intp, R0900_P2_TNRCFG, 0x3c); | ||
1484 | stv0900_write_reg(intp, R0900_P2_TNRCFG2, 0x86); | ||
1485 | stv0900_write_reg(intp, R0900_P2_TNRCFG3, 0x18); | ||
1486 | stv0900_write_reg(intp, R0900_P2_TNRXTAL, 27); /* 27MHz */ | ||
1487 | stv0900_write_reg(intp, R0900_P2_TNRSTEPS, 0x05); | ||
1488 | stv0900_write_reg(intp, R0900_P2_TNRGAIN, 0x17); | ||
1489 | stv0900_write_reg(intp, R0900_P2_TNRADJ, 0x1f); | ||
1490 | stv0900_write_reg(intp, R0900_P2_TNRCTL2, 0x0); | ||
1491 | stv0900_write_bits(intp, F0900_P2_TUN_TYPE, 3); | ||
1492 | break; | ||
1493 | /* case FE_SW_TUNER: */ | ||
1494 | default: | ||
1495 | stv0900_write_bits(intp, F0900_P2_TUN_TYPE, 6); | ||
1496 | break; | ||
1497 | } | ||
1498 | |||
1416 | stv0900_write_bits(intp, F0900_P2_TUN_MADDRESS, p_init->tun2_maddress); | 1499 | stv0900_write_bits(intp, F0900_P2_TUN_MADDRESS, p_init->tun2_maddress); |
1417 | switch (p_init->tuner2_adc) { | 1500 | switch (p_init->tuner2_adc) { |
1418 | case 1: | 1501 | case 1: |
@@ -1422,6 +1505,8 @@ static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe, | |||
1422 | break; | 1505 | break; |
1423 | } | 1506 | } |
1424 | 1507 | ||
1508 | stv0900_write_reg(intp, R0900_P2_TNRLD, 1); /* hw tuner */ | ||
1509 | |||
1425 | stv0900_write_bits(intp, F0900_P1_TUN_IQSWAP, p_init->tun1_iq_inv); | 1510 | stv0900_write_bits(intp, F0900_P1_TUN_IQSWAP, p_init->tun1_iq_inv); |
1426 | stv0900_write_bits(intp, F0900_P2_TUN_IQSWAP, p_init->tun2_iq_inv); | 1511 | stv0900_write_bits(intp, F0900_P2_TUN_IQSWAP, p_init->tun2_iq_inv); |
1427 | stv0900_set_mclk(intp, 135000000); | 1512 | stv0900_set_mclk(intp, 135000000); |
@@ -1824,10 +1909,12 @@ struct dvb_frontend *stv0900_attach(const struct stv0900_config *config, | |||
1824 | init_params.tun1_maddress = config->tun1_maddress; | 1909 | init_params.tun1_maddress = config->tun1_maddress; |
1825 | init_params.tun1_iq_inv = STV0900_IQ_NORMAL; | 1910 | init_params.tun1_iq_inv = STV0900_IQ_NORMAL; |
1826 | init_params.tuner1_adc = config->tun1_adc; | 1911 | init_params.tuner1_adc = config->tun1_adc; |
1912 | init_params.tuner1_type = config->tun1_type; | ||
1827 | init_params.path2_ts_clock = config->path2_mode; | 1913 | init_params.path2_ts_clock = config->path2_mode; |
1828 | init_params.ts_config = config->ts_config_regs; | 1914 | init_params.ts_config = config->ts_config_regs; |
1829 | init_params.tun2_maddress = config->tun2_maddress; | 1915 | init_params.tun2_maddress = config->tun2_maddress; |
1830 | init_params.tuner2_adc = config->tun2_adc; | 1916 | init_params.tuner2_adc = config->tun2_adc; |
1917 | init_params.tuner2_type = config->tun2_type; | ||
1831 | init_params.tun2_iq_inv = STV0900_IQ_SWAPPED; | 1918 | init_params.tun2_iq_inv = STV0900_IQ_SWAPPED; |
1832 | 1919 | ||
1833 | err_stv0900 = stv0900_init_internal(&state->frontend, | 1920 | err_stv0900 = stv0900_init_internal(&state->frontend, |
diff --git a/drivers/media/dvb/frontends/stv0900_priv.h b/drivers/media/dvb/frontends/stv0900_priv.h index d8ba8a984abe..b62b0f0a4fef 100644 --- a/drivers/media/dvb/frontends/stv0900_priv.h +++ b/drivers/media/dvb/frontends/stv0900_priv.h | |||
@@ -247,6 +247,7 @@ struct stv0900_init_params{ | |||
247 | 247 | ||
248 | u8 tun1_maddress; | 248 | u8 tun1_maddress; |
249 | int tuner1_adc; | 249 | int tuner1_adc; |
250 | int tuner1_type; | ||
250 | 251 | ||
251 | /* IQ from the tuner1 to the demod */ | 252 | /* IQ from the tuner1 to the demod */ |
252 | enum stv0900_iq_inversion tun1_iq_inv; | 253 | enum stv0900_iq_inversion tun1_iq_inv; |
@@ -254,6 +255,7 @@ struct stv0900_init_params{ | |||
254 | 255 | ||
255 | u8 tun2_maddress; | 256 | u8 tun2_maddress; |
256 | int tuner2_adc; | 257 | int tuner2_adc; |
258 | int tuner2_type; | ||
257 | 259 | ||
258 | /* IQ from the tuner2 to the demod */ | 260 | /* IQ from the tuner2 to the demod */ |
259 | enum stv0900_iq_inversion tun2_iq_inv; | 261 | enum stv0900_iq_inversion tun2_iq_inv; |
@@ -309,6 +311,8 @@ struct stv0900_internal{ | |||
309 | s32 bw[2]; | 311 | s32 bw[2]; |
310 | s32 symbol_rate[2]; | 312 | s32 symbol_rate[2]; |
311 | s32 srch_range[2]; | 313 | s32 srch_range[2]; |
314 | /* for software/auto tuner */ | ||
315 | int tuner_type[2]; | ||
312 | 316 | ||
313 | /* algorithm for search Blind, Cold or Warm*/ | 317 | /* algorithm for search Blind, Cold or Warm*/ |
314 | enum fe_stv0900_search_algo srch_algo[2]; | 318 | enum fe_stv0900_search_algo srch_algo[2]; |
@@ -394,4 +398,11 @@ extern enum | |||
394 | fe_stv0900_tracking_standard stv0900_get_standard(struct dvb_frontend *fe, | 398 | fe_stv0900_tracking_standard stv0900_get_standard(struct dvb_frontend *fe, |
395 | enum fe_stv0900_demod_num demod); | 399 | enum fe_stv0900_demod_num demod); |
396 | 400 | ||
401 | extern u32 | ||
402 | stv0900_get_freq_auto(struct stv0900_internal *intp, int demod); | ||
403 | |||
404 | extern void | ||
405 | stv0900_set_tuner_auto(struct stv0900_internal *intp, u32 Frequency, | ||
406 | u32 Bandwidth, int demod); | ||
407 | |||
397 | #endif | 408 | #endif |
diff --git a/drivers/media/dvb/frontends/stv0900_reg.h b/drivers/media/dvb/frontends/stv0900_reg.h index 7b8edf192e97..731afe93a823 100644 --- a/drivers/media/dvb/frontends/stv0900_reg.h +++ b/drivers/media/dvb/frontends/stv0900_reg.h | |||
@@ -3174,17 +3174,21 @@ extern s32 shiftx(s32 x, int demod, s32 shift); | |||
3174 | #define R0900_P1_TNRRF1 0xf4e9 | 3174 | #define R0900_P1_TNRRF1 0xf4e9 |
3175 | #define TNRRF1 REGx(R0900_P1_TNRRF1) | 3175 | #define TNRRF1 REGx(R0900_P1_TNRRF1) |
3176 | #define F0900_P1_TUN_RFFREQ2 0xf4e900ff | 3176 | #define F0900_P1_TUN_RFFREQ2 0xf4e900ff |
3177 | #define TUN_RFFREQ2 FLDx(F0900_P1_TUN_RFFREQ2) | ||
3177 | 3178 | ||
3178 | /*P1_TNRRF0*/ | 3179 | /*P1_TNRRF0*/ |
3179 | #define R0900_P1_TNRRF0 0xf4ea | 3180 | #define R0900_P1_TNRRF0 0xf4ea |
3180 | #define TNRRF0 REGx(R0900_P1_TNRRF0) | 3181 | #define TNRRF0 REGx(R0900_P1_TNRRF0) |
3181 | #define F0900_P1_TUN_RFFREQ1 0xf4ea00ff | 3182 | #define F0900_P1_TUN_RFFREQ1 0xf4ea00ff |
3183 | #define TUN_RFFREQ1 FLDx(F0900_P1_TUN_RFFREQ1) | ||
3182 | 3184 | ||
3183 | /*P1_TNRBW*/ | 3185 | /*P1_TNRBW*/ |
3184 | #define R0900_P1_TNRBW 0xf4eb | 3186 | #define R0900_P1_TNRBW 0xf4eb |
3185 | #define TNRBW REGx(R0900_P1_TNRBW) | 3187 | #define TNRBW REGx(R0900_P1_TNRBW) |
3186 | #define F0900_P1_TUN_RFFREQ0 0xf4eb00c0 | 3188 | #define F0900_P1_TUN_RFFREQ0 0xf4eb00c0 |
3189 | #define TUN_RFFREQ0 FLDx(F0900_P1_TUN_RFFREQ0) | ||
3187 | #define F0900_P1_TUN_BW 0xf4eb003f | 3190 | #define F0900_P1_TUN_BW 0xf4eb003f |
3191 | #define TUN_BW FLDx(F0900_P1_TUN_BW) | ||
3188 | 3192 | ||
3189 | /*P1_TNRADJ*/ | 3193 | /*P1_TNRADJ*/ |
3190 | #define R0900_P1_TNRADJ 0xf4ec | 3194 | #define R0900_P1_TNRADJ 0xf4ec |
@@ -3234,11 +3238,13 @@ extern s32 shiftx(s32 x, int demod, s32 shift); | |||
3234 | #define F0900_P1_TUN_I2CLOCKED 0xf4f60010 | 3238 | #define F0900_P1_TUN_I2CLOCKED 0xf4f60010 |
3235 | #define F0900_P1_TUN_PROGDONE 0xf4f6000c | 3239 | #define F0900_P1_TUN_PROGDONE 0xf4f6000c |
3236 | #define F0900_P1_TUN_RFRESTE1 0xf4f60003 | 3240 | #define F0900_P1_TUN_RFRESTE1 0xf4f60003 |
3241 | #define TUN_RFRESTE1 FLDx(F0900_P1_TUN_RFRESTE1) | ||
3237 | 3242 | ||
3238 | /*P1_TNRRESTE*/ | 3243 | /*P1_TNRRESTE*/ |
3239 | #define R0900_P1_TNRRESTE 0xf4f7 | 3244 | #define R0900_P1_TNRRESTE 0xf4f7 |
3240 | #define TNRRESTE REGx(R0900_P1_TNRRESTE) | 3245 | #define TNRRESTE REGx(R0900_P1_TNRRESTE) |
3241 | #define F0900_P1_TUN_RFRESTE0 0xf4f700ff | 3246 | #define F0900_P1_TUN_RFRESTE0 0xf4f700ff |
3247 | #define TUN_RFRESTE0 FLDx(F0900_P1_TUN_RFRESTE0) | ||
3242 | 3248 | ||
3243 | /*P1_SMAPCOEF7*/ | 3249 | /*P1_SMAPCOEF7*/ |
3244 | #define R0900_P1_SMAPCOEF7 0xf500 | 3250 | #define R0900_P1_SMAPCOEF7 0xf500 |
diff --git a/drivers/media/dvb/frontends/stv0900_sw.c b/drivers/media/dvb/frontends/stv0900_sw.c index b8da87fa637f..ba0709b2d433 100644 --- a/drivers/media/dvb/frontends/stv0900_sw.c +++ b/drivers/media/dvb/frontends/stv0900_sw.c | |||
@@ -193,7 +193,7 @@ static int stv0900_search_carr_sw_loop(struct stv0900_internal *intp, | |||
193 | return lock; | 193 | return lock; |
194 | } | 194 | } |
195 | 195 | ||
196 | int stv0900_sw_algo(struct stv0900_internal *intp, | 196 | static int stv0900_sw_algo(struct stv0900_internal *intp, |
197 | enum fe_stv0900_demod_num demod) | 197 | enum fe_stv0900_demod_num demod) |
198 | { | 198 | { |
199 | int lock = FALSE, | 199 | int lock = FALSE, |
@@ -606,7 +606,12 @@ static int stv0900_get_demod_cold_lock(struct dvb_frontend *fe, | |||
606 | tuner_freq -= (current_step * currier_step); | 606 | tuner_freq -= (current_step * currier_step); |
607 | 607 | ||
608 | if (intp->chip_id <= 0x20) { | 608 | if (intp->chip_id <= 0x20) { |
609 | stv0900_set_tuner(fe, tuner_freq, intp->bw[d]); | 609 | if (intp->tuner_type[d] == 3) |
610 | stv0900_set_tuner_auto(intp, tuner_freq, | ||
611 | intp->bw[d], demod); | ||
612 | else | ||
613 | stv0900_set_tuner(fe, tuner_freq, intp->bw[d]); | ||
614 | |||
610 | stv0900_write_reg(intp, DMDISTATE, 0x1c); | 615 | stv0900_write_reg(intp, DMDISTATE, 0x1c); |
611 | stv0900_write_reg(intp, CFRINIT1, 0); | 616 | stv0900_write_reg(intp, CFRINIT1, 0); |
612 | stv0900_write_reg(intp, CFRINIT0, 0); | 617 | stv0900_write_reg(intp, CFRINIT0, 0); |
@@ -790,7 +795,7 @@ static enum fe_stv0900_fec stv0900_get_vit_fec(struct stv0900_internal *intp, | |||
790 | return prate; | 795 | return prate; |
791 | } | 796 | } |
792 | 797 | ||
793 | void stv0900_set_dvbs1_track_car_loop(struct stv0900_internal *intp, | 798 | static void stv0900_set_dvbs1_track_car_loop(struct stv0900_internal *intp, |
794 | enum fe_stv0900_demod_num demod, | 799 | enum fe_stv0900_demod_num demod, |
795 | u32 srate) | 800 | u32 srate) |
796 | { | 801 | { |
@@ -976,8 +981,16 @@ static void stv0900_track_optimization(struct dvb_frontend *fe) | |||
976 | intp->rolloff) + 10000000; | 981 | intp->rolloff) + 10000000; |
977 | 982 | ||
978 | if ((intp->chip_id >= 0x20) || (blind_tun_sw == 1)) { | 983 | if ((intp->chip_id >= 0x20) || (blind_tun_sw == 1)) { |
979 | if (intp->srch_algo[demod] != STV0900_WARM_START) | 984 | if (intp->srch_algo[demod] != STV0900_WARM_START) { |
980 | stv0900_set_bandwidth(fe, intp->bw[demod]); | 985 | if (intp->tuner_type[demod] == 3) |
986 | stv0900_set_tuner_auto(intp, | ||
987 | intp->freq[demod], | ||
988 | intp->bw[demod], | ||
989 | demod); | ||
990 | else | ||
991 | stv0900_set_bandwidth(fe, | ||
992 | intp->bw[demod]); | ||
993 | } | ||
981 | } | 994 | } |
982 | 995 | ||
983 | if ((intp->srch_algo[demod] == STV0900_BLIND_SEARCH) || | 996 | if ((intp->srch_algo[demod] == STV0900_BLIND_SEARCH) || |
@@ -1202,7 +1215,11 @@ fe_stv0900_signal_type stv0900_get_signal_params(struct dvb_frontend *fe) | |||
1202 | } | 1215 | } |
1203 | 1216 | ||
1204 | result->standard = stv0900_get_standard(fe, d); | 1217 | result->standard = stv0900_get_standard(fe, d); |
1205 | result->frequency = stv0900_get_tuner_freq(fe); | 1218 | if (intp->tuner_type[demod] == 3) |
1219 | result->frequency = stv0900_get_freq_auto(intp, d); | ||
1220 | else | ||
1221 | result->frequency = stv0900_get_tuner_freq(fe); | ||
1222 | |||
1206 | offsetFreq = stv0900_get_carr_freq(intp, intp->mclk, d) / 1000; | 1223 | offsetFreq = stv0900_get_carr_freq(intp, intp->mclk, d) / 1000; |
1207 | result->frequency += offsetFreq; | 1224 | result->frequency += offsetFreq; |
1208 | result->symbol_rate = stv0900_get_symbol_rate(intp, intp->mclk, d); | 1225 | result->symbol_rate = stv0900_get_symbol_rate(intp, intp->mclk, d); |
@@ -1213,6 +1230,9 @@ fe_stv0900_signal_type stv0900_get_signal_params(struct dvb_frontend *fe) | |||
1213 | result->pilot = stv0900_get_bits(intp, DEMOD_TYPE) & 0x01; | 1230 | result->pilot = stv0900_get_bits(intp, DEMOD_TYPE) & 0x01; |
1214 | result->frame_len = ((u32)stv0900_get_bits(intp, DEMOD_TYPE)) >> 1; | 1231 | result->frame_len = ((u32)stv0900_get_bits(intp, DEMOD_TYPE)) >> 1; |
1215 | result->rolloff = stv0900_get_bits(intp, ROLLOFF_STATUS); | 1232 | result->rolloff = stv0900_get_bits(intp, ROLLOFF_STATUS); |
1233 | |||
1234 | dprintk("%s: modcode=0x%x \n", __func__, result->modcode); | ||
1235 | |||
1216 | switch (result->standard) { | 1236 | switch (result->standard) { |
1217 | case STV0900_DVBS2_STANDARD: | 1237 | case STV0900_DVBS2_STANDARD: |
1218 | result->spectrum = stv0900_get_bits(intp, SPECINV_DEMOD); | 1238 | result->spectrum = stv0900_get_bits(intp, SPECINV_DEMOD); |
@@ -1239,7 +1259,11 @@ fe_stv0900_signal_type stv0900_get_signal_params(struct dvb_frontend *fe) | |||
1239 | if ((intp->srch_algo[d] == STV0900_BLIND_SEARCH) || | 1259 | if ((intp->srch_algo[d] == STV0900_BLIND_SEARCH) || |
1240 | (intp->symbol_rate[d] < 10000000)) { | 1260 | (intp->symbol_rate[d] < 10000000)) { |
1241 | offsetFreq = result->frequency - intp->freq[d]; | 1261 | offsetFreq = result->frequency - intp->freq[d]; |
1242 | intp->freq[d] = stv0900_get_tuner_freq(fe); | 1262 | if (intp->tuner_type[demod] == 3) |
1263 | intp->freq[d] = stv0900_get_freq_auto(intp, d); | ||
1264 | else | ||
1265 | intp->freq[d] = stv0900_get_tuner_freq(fe); | ||
1266 | |||
1243 | if (ABS(offsetFreq) <= ((intp->srch_range[d] / 2000) + 500)) | 1267 | if (ABS(offsetFreq) <= ((intp->srch_range[d] / 2000) + 500)) |
1244 | range = STV0900_RANGEOK; | 1268 | range = STV0900_RANGEOK; |
1245 | else if (ABS(offsetFreq) <= | 1269 | else if (ABS(offsetFreq) <= |
@@ -1481,7 +1505,12 @@ static u32 stv0900_search_srate_coarse(struct dvb_frontend *fe) | |||
1481 | else | 1505 | else |
1482 | tuner_freq -= (current_step * currier_step); | 1506 | tuner_freq -= (current_step * currier_step); |
1483 | 1507 | ||
1484 | stv0900_set_tuner(fe, tuner_freq, intp->bw[demod]); | 1508 | if (intp->tuner_type[demod] == 3) |
1509 | stv0900_set_tuner_auto(intp, tuner_freq, | ||
1510 | intp->bw[demod], demod); | ||
1511 | else | ||
1512 | stv0900_set_tuner(fe, tuner_freq, | ||
1513 | intp->bw[demod]); | ||
1485 | } | 1514 | } |
1486 | } | 1515 | } |
1487 | 1516 | ||
@@ -1608,7 +1637,8 @@ static int stv0900_blind_search_algo(struct dvb_frontend *fe) | |||
1608 | 1637 | ||
1609 | agc2_int = stv0900_blind_check_agc2_min_level(intp, demod); | 1638 | agc2_int = stv0900_blind_check_agc2_min_level(intp, demod); |
1610 | 1639 | ||
1611 | if (agc2_int > STV0900_BLIND_SEARCH_AGC2_TH) | 1640 | dprintk("%s agc2_int=%d agc2_th=%d \n", __func__, agc2_int, agc2_th); |
1641 | if (agc2_int > agc2_th) | ||
1612 | return FALSE; | 1642 | return FALSE; |
1613 | 1643 | ||
1614 | if (intp->chip_id == 0x10) | 1644 | if (intp->chip_id == 0x10) |
@@ -1875,7 +1905,11 @@ enum fe_stv0900_signal_type stv0900_algo(struct dvb_frontend *fe) | |||
1875 | 1905 | ||
1876 | } | 1906 | } |
1877 | 1907 | ||
1878 | stv0900_set_tuner(fe, intp->freq[demod], intp->bw[demod]); | 1908 | if (intp->tuner_type[demod] == 3) |
1909 | stv0900_set_tuner_auto(intp, intp->freq[demod], | ||
1910 | intp->bw[demod], demod); | ||
1911 | else | ||
1912 | stv0900_set_tuner(fe, intp->freq[demod], intp->bw[demod]); | ||
1879 | 1913 | ||
1880 | agc1_power = MAKEWORD(stv0900_get_bits(intp, AGCIQ_VALUE1), | 1914 | agc1_power = MAKEWORD(stv0900_get_bits(intp, AGCIQ_VALUE1), |
1881 | stv0900_get_bits(intp, AGCIQ_VALUE0)); | 1915 | stv0900_get_bits(intp, AGCIQ_VALUE0)); |
diff --git a/drivers/media/dvb/frontends/stv090x.c b/drivers/media/dvb/frontends/stv090x.c index 1573466a5c74..c52c3357dc54 100644 --- a/drivers/media/dvb/frontends/stv090x.c +++ b/drivers/media/dvb/frontends/stv090x.c | |||
@@ -37,7 +37,82 @@ | |||
37 | static unsigned int verbose; | 37 | static unsigned int verbose; |
38 | module_param(verbose, int, 0644); | 38 | module_param(verbose, int, 0644); |
39 | 39 | ||
40 | struct mutex demod_lock; | 40 | /* internal params node */ |
41 | struct stv090x_dev { | ||
42 | /* pointer for internal params, one for each pair of demods */ | ||
43 | struct stv090x_internal *internal; | ||
44 | struct stv090x_dev *next_dev; | ||
45 | }; | ||
46 | |||
47 | /* first internal params */ | ||
48 | static struct stv090x_dev *stv090x_first_dev; | ||
49 | |||
50 | /* find chip by i2c adapter and i2c address */ | ||
51 | static struct stv090x_dev *find_dev(struct i2c_adapter *i2c_adap, | ||
52 | u8 i2c_addr) | ||
53 | { | ||
54 | struct stv090x_dev *temp_dev = stv090x_first_dev; | ||
55 | |||
56 | /* | ||
57 | Search of the last stv0900 chip or | ||
58 | find it by i2c adapter and i2c address */ | ||
59 | while ((temp_dev != NULL) && | ||
60 | ((temp_dev->internal->i2c_adap != i2c_adap) || | ||
61 | (temp_dev->internal->i2c_addr != i2c_addr))) { | ||
62 | |||
63 | temp_dev = temp_dev->next_dev; | ||
64 | } | ||
65 | |||
66 | return temp_dev; | ||
67 | } | ||
68 | |||
69 | /* deallocating chip */ | ||
70 | static void remove_dev(struct stv090x_internal *internal) | ||
71 | { | ||
72 | struct stv090x_dev *prev_dev = stv090x_first_dev; | ||
73 | struct stv090x_dev *del_dev = find_dev(internal->i2c_adap, | ||
74 | internal->i2c_addr); | ||
75 | |||
76 | if (del_dev != NULL) { | ||
77 | if (del_dev == stv090x_first_dev) { | ||
78 | stv090x_first_dev = del_dev->next_dev; | ||
79 | } else { | ||
80 | while (prev_dev->next_dev != del_dev) | ||
81 | prev_dev = prev_dev->next_dev; | ||
82 | |||
83 | prev_dev->next_dev = del_dev->next_dev; | ||
84 | } | ||
85 | |||
86 | kfree(del_dev); | ||
87 | } | ||
88 | } | ||
89 | |||
90 | /* allocating new chip */ | ||
91 | static struct stv090x_dev *append_internal(struct stv090x_internal *internal) | ||
92 | { | ||
93 | struct stv090x_dev *new_dev; | ||
94 | struct stv090x_dev *temp_dev; | ||
95 | |||
96 | new_dev = kmalloc(sizeof(struct stv090x_dev), GFP_KERNEL); | ||
97 | if (new_dev != NULL) { | ||
98 | new_dev->internal = internal; | ||
99 | new_dev->next_dev = NULL; | ||
100 | |||
101 | /* append to list */ | ||
102 | if (stv090x_first_dev == NULL) { | ||
103 | stv090x_first_dev = new_dev; | ||
104 | } else { | ||
105 | temp_dev = stv090x_first_dev; | ||
106 | while (temp_dev->next_dev != NULL) | ||
107 | temp_dev = temp_dev->next_dev; | ||
108 | |||
109 | temp_dev->next_dev = new_dev; | ||
110 | } | ||
111 | } | ||
112 | |||
113 | return new_dev; | ||
114 | } | ||
115 | |||
41 | 116 | ||
42 | /* DVBS1 and DSS C/N Lookup table */ | 117 | /* DVBS1 and DSS C/N Lookup table */ |
43 | static const struct stv090x_tab stv090x_s1cn_tab[] = { | 118 | static const struct stv090x_tab stv090x_s1cn_tab[] = { |
@@ -683,6 +758,9 @@ static int stv090x_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) | |||
683 | struct stv090x_state *state = fe->demodulator_priv; | 758 | struct stv090x_state *state = fe->demodulator_priv; |
684 | u32 reg; | 759 | u32 reg; |
685 | 760 | ||
761 | if (enable) | ||
762 | mutex_lock(&state->internal->tuner_lock); | ||
763 | |||
686 | reg = STV090x_READ_DEMOD(state, I2CRPT); | 764 | reg = STV090x_READ_DEMOD(state, I2CRPT); |
687 | if (enable) { | 765 | if (enable) { |
688 | dprintk(FE_DEBUG, 1, "Enable Gate"); | 766 | dprintk(FE_DEBUG, 1, "Enable Gate"); |
@@ -696,9 +774,14 @@ static int stv090x_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) | |||
696 | if ((STV090x_WRITE_DEMOD(state, I2CRPT, reg)) < 0) | 774 | if ((STV090x_WRITE_DEMOD(state, I2CRPT, reg)) < 0) |
697 | goto err; | 775 | goto err; |
698 | } | 776 | } |
777 | |||
778 | if (!enable) | ||
779 | mutex_unlock(&state->internal->tuner_lock); | ||
780 | |||
699 | return 0; | 781 | return 0; |
700 | err: | 782 | err: |
701 | dprintk(FE_ERROR, 1, "I/O error"); | 783 | dprintk(FE_ERROR, 1, "I/O error"); |
784 | mutex_unlock(&state->internal->tuner_lock); | ||
702 | return -1; | 785 | return -1; |
703 | } | 786 | } |
704 | 787 | ||
@@ -755,13 +838,13 @@ static int stv090x_set_srate(struct stv090x_state *state, u32 srate) | |||
755 | 838 | ||
756 | if (srate > 60000000) { | 839 | if (srate > 60000000) { |
757 | sym = (srate << 4); /* SR * 2^16 / master_clk */ | 840 | sym = (srate << 4); /* SR * 2^16 / master_clk */ |
758 | sym /= (state->mclk >> 12); | 841 | sym /= (state->internal->mclk >> 12); |
759 | } else if (srate > 6000000) { | 842 | } else if (srate > 6000000) { |
760 | sym = (srate << 6); | 843 | sym = (srate << 6); |
761 | sym /= (state->mclk >> 10); | 844 | sym /= (state->internal->mclk >> 10); |
762 | } else { | 845 | } else { |
763 | sym = (srate << 9); | 846 | sym = (srate << 9); |
764 | sym /= (state->mclk >> 7); | 847 | sym /= (state->internal->mclk >> 7); |
765 | } | 848 | } |
766 | 849 | ||
767 | if (STV090x_WRITE_DEMOD(state, SFRINIT1, (sym >> 8) & 0x7f) < 0) /* MSB */ | 850 | if (STV090x_WRITE_DEMOD(state, SFRINIT1, (sym >> 8) & 0x7f) < 0) /* MSB */ |
@@ -782,13 +865,13 @@ static int stv090x_set_max_srate(struct stv090x_state *state, u32 clk, u32 srate | |||
782 | srate = 105 * (srate / 100); | 865 | srate = 105 * (srate / 100); |
783 | if (srate > 60000000) { | 866 | if (srate > 60000000) { |
784 | sym = (srate << 4); /* SR * 2^16 / master_clk */ | 867 | sym = (srate << 4); /* SR * 2^16 / master_clk */ |
785 | sym /= (state->mclk >> 12); | 868 | sym /= (state->internal->mclk >> 12); |
786 | } else if (srate > 6000000) { | 869 | } else if (srate > 6000000) { |
787 | sym = (srate << 6); | 870 | sym = (srate << 6); |
788 | sym /= (state->mclk >> 10); | 871 | sym /= (state->internal->mclk >> 10); |
789 | } else { | 872 | } else { |
790 | sym = (srate << 9); | 873 | sym = (srate << 9); |
791 | sym /= (state->mclk >> 7); | 874 | sym /= (state->internal->mclk >> 7); |
792 | } | 875 | } |
793 | 876 | ||
794 | if (sym < 0x7fff) { | 877 | if (sym < 0x7fff) { |
@@ -816,13 +899,13 @@ static int stv090x_set_min_srate(struct stv090x_state *state, u32 clk, u32 srate | |||
816 | srate = 95 * (srate / 100); | 899 | srate = 95 * (srate / 100); |
817 | if (srate > 60000000) { | 900 | if (srate > 60000000) { |
818 | sym = (srate << 4); /* SR * 2^16 / master_clk */ | 901 | sym = (srate << 4); /* SR * 2^16 / master_clk */ |
819 | sym /= (state->mclk >> 12); | 902 | sym /= (state->internal->mclk >> 12); |
820 | } else if (srate > 6000000) { | 903 | } else if (srate > 6000000) { |
821 | sym = (srate << 6); | 904 | sym = (srate << 6); |
822 | sym /= (state->mclk >> 10); | 905 | sym /= (state->internal->mclk >> 10); |
823 | } else { | 906 | } else { |
824 | sym = (srate << 9); | 907 | sym = (srate << 9); |
825 | sym /= (state->mclk >> 7); | 908 | sym /= (state->internal->mclk >> 7); |
826 | } | 909 | } |
827 | 910 | ||
828 | if (STV090x_WRITE_DEMOD(state, SFRLOW1, ((sym >> 8) & 0x7f)) < 0) /* MSB */ | 911 | if (STV090x_WRITE_DEMOD(state, SFRLOW1, ((sym >> 8) & 0x7f)) < 0) /* MSB */ |
@@ -1103,21 +1186,21 @@ static int stv090x_vitclk_ctl(struct stv090x_state *state, int enable) | |||
1103 | 1186 | ||
1104 | switch (state->demod) { | 1187 | switch (state->demod) { |
1105 | case STV090x_DEMODULATOR_0: | 1188 | case STV090x_DEMODULATOR_0: |
1106 | mutex_lock(&demod_lock); | 1189 | mutex_lock(&state->internal->demod_lock); |
1107 | reg = stv090x_read_reg(state, STV090x_STOPCLK2); | 1190 | reg = stv090x_read_reg(state, STV090x_STOPCLK2); |
1108 | STV090x_SETFIELD(reg, STOP_CLKVIT1_FIELD, enable); | 1191 | STV090x_SETFIELD(reg, STOP_CLKVIT1_FIELD, enable); |
1109 | if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0) | 1192 | if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0) |
1110 | goto err; | 1193 | goto err; |
1111 | mutex_unlock(&demod_lock); | 1194 | mutex_unlock(&state->internal->demod_lock); |
1112 | break; | 1195 | break; |
1113 | 1196 | ||
1114 | case STV090x_DEMODULATOR_1: | 1197 | case STV090x_DEMODULATOR_1: |
1115 | mutex_lock(&demod_lock); | 1198 | mutex_lock(&state->internal->demod_lock); |
1116 | reg = stv090x_read_reg(state, STV090x_STOPCLK2); | 1199 | reg = stv090x_read_reg(state, STV090x_STOPCLK2); |
1117 | STV090x_SETFIELD(reg, STOP_CLKVIT2_FIELD, enable); | 1200 | STV090x_SETFIELD(reg, STOP_CLKVIT2_FIELD, enable); |
1118 | if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0) | 1201 | if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0) |
1119 | goto err; | 1202 | goto err; |
1120 | mutex_unlock(&demod_lock); | 1203 | mutex_unlock(&state->internal->demod_lock); |
1121 | break; | 1204 | break; |
1122 | 1205 | ||
1123 | default: | 1206 | default: |
@@ -1126,14 +1209,14 @@ static int stv090x_vitclk_ctl(struct stv090x_state *state, int enable) | |||
1126 | } | 1209 | } |
1127 | return 0; | 1210 | return 0; |
1128 | err: | 1211 | err: |
1129 | mutex_unlock(&demod_lock); | 1212 | mutex_unlock(&state->internal->demod_lock); |
1130 | dprintk(FE_ERROR, 1, "I/O error"); | 1213 | dprintk(FE_ERROR, 1, "I/O error"); |
1131 | return -1; | 1214 | return -1; |
1132 | } | 1215 | } |
1133 | 1216 | ||
1134 | static int stv090x_dvbs_track_crl(struct stv090x_state *state) | 1217 | static int stv090x_dvbs_track_crl(struct stv090x_state *state) |
1135 | { | 1218 | { |
1136 | if (state->dev_ver >= 0x30) { | 1219 | if (state->internal->dev_ver >= 0x30) { |
1137 | /* Set ACLC BCLC optimised value vs SR */ | 1220 | /* Set ACLC BCLC optimised value vs SR */ |
1138 | if (state->srate >= 15000000) { | 1221 | if (state->srate >= 15000000) { |
1139 | if (STV090x_WRITE_DEMOD(state, ACLC, 0x2b) < 0) | 1222 | if (STV090x_WRITE_DEMOD(state, ACLC, 0x2b) < 0) |
@@ -1215,7 +1298,7 @@ static int stv090x_delivery_search(struct stv090x_state *state) | |||
1215 | if (STV090x_WRITE_DEMOD(state, BCLC, 0x09) < 0) | 1298 | if (STV090x_WRITE_DEMOD(state, BCLC, 0x09) < 0) |
1216 | goto err; | 1299 | goto err; |
1217 | 1300 | ||
1218 | if (state->dev_ver <= 0x20) { | 1301 | if (state->internal->dev_ver <= 0x20) { |
1219 | /* enable S2 carrier loop */ | 1302 | /* enable S2 carrier loop */ |
1220 | if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x26) < 0) | 1303 | if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x26) < 0) |
1221 | goto err; | 1304 | goto err; |
@@ -1246,6 +1329,10 @@ static int stv090x_delivery_search(struct stv090x_state *state) | |||
1246 | default: | 1329 | default: |
1247 | /* enable DVB-S2 and DVB-S2 in Auto MODE */ | 1330 | /* enable DVB-S2 and DVB-S2 in Auto MODE */ |
1248 | reg = STV090x_READ_DEMOD(state, DMDCFGMD); | 1331 | reg = STV090x_READ_DEMOD(state, DMDCFGMD); |
1332 | STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 0); | ||
1333 | STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 0); | ||
1334 | if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) | ||
1335 | goto err; | ||
1249 | STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1); | 1336 | STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1); |
1250 | STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 1); | 1337 | STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 1); |
1251 | if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) | 1338 | if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0) |
@@ -1257,7 +1344,7 @@ static int stv090x_delivery_search(struct stv090x_state *state) | |||
1257 | if (stv090x_dvbs_track_crl(state) < 0) | 1344 | if (stv090x_dvbs_track_crl(state) < 0) |
1258 | goto err; | 1345 | goto err; |
1259 | 1346 | ||
1260 | if (state->dev_ver <= 0x20) { | 1347 | if (state->internal->dev_ver <= 0x20) { |
1261 | /* enable S2 carrier loop */ | 1348 | /* enable S2 carrier loop */ |
1262 | if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x26) < 0) | 1349 | if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x26) < 0) |
1263 | goto err; | 1350 | goto err; |
@@ -1304,7 +1391,7 @@ static int stv090x_start_search(struct stv090x_state *state) | |||
1304 | if (STV090x_WRITE_DEMOD(state, DMDISTATE, reg) < 0) | 1391 | if (STV090x_WRITE_DEMOD(state, DMDISTATE, reg) < 0) |
1305 | goto err; | 1392 | goto err; |
1306 | 1393 | ||
1307 | if (state->dev_ver <= 0x20) { | 1394 | if (state->internal->dev_ver <= 0x20) { |
1308 | if (state->srate <= 5000000) { | 1395 | if (state->srate <= 5000000) { |
1309 | if (STV090x_WRITE_DEMOD(state, CARCFG, 0x44) < 0) | 1396 | if (STV090x_WRITE_DEMOD(state, CARCFG, 0x44) < 0) |
1310 | goto err; | 1397 | goto err; |
@@ -1348,7 +1435,7 @@ static int stv090x_start_search(struct stv090x_state *state) | |||
1348 | * CFR max = +1MHz | 1435 | * CFR max = +1MHz |
1349 | */ | 1436 | */ |
1350 | freq_abs = 1000 << 16; | 1437 | freq_abs = 1000 << 16; |
1351 | freq_abs /= (state->mclk / 1000); | 1438 | freq_abs /= (state->internal->mclk / 1000); |
1352 | freq = (s16) freq_abs; | 1439 | freq = (s16) freq_abs; |
1353 | } else { | 1440 | } else { |
1354 | /* COLD Start | 1441 | /* COLD Start |
@@ -1358,7 +1445,7 @@ static int stv090x_start_search(struct stv090x_state *state) | |||
1358 | */ | 1445 | */ |
1359 | freq_abs = (state->search_range / 2000) + 600; | 1446 | freq_abs = (state->search_range / 2000) + 600; |
1360 | freq_abs = freq_abs << 16; | 1447 | freq_abs = freq_abs << 16; |
1361 | freq_abs /= (state->mclk / 1000); | 1448 | freq_abs /= (state->internal->mclk / 1000); |
1362 | freq = (s16) freq_abs; | 1449 | freq = (s16) freq_abs; |
1363 | } | 1450 | } |
1364 | 1451 | ||
@@ -1381,7 +1468,7 @@ static int stv090x_start_search(struct stv090x_state *state) | |||
1381 | if (STV090x_WRITE_DEMOD(state, CFRINIT0, 0) < 0) | 1468 | if (STV090x_WRITE_DEMOD(state, CFRINIT0, 0) < 0) |
1382 | goto err; | 1469 | goto err; |
1383 | 1470 | ||
1384 | if (state->dev_ver >= 0x20) { | 1471 | if (state->internal->dev_ver >= 0x20) { |
1385 | if (STV090x_WRITE_DEMOD(state, EQUALCFG, 0x41) < 0) | 1472 | if (STV090x_WRITE_DEMOD(state, EQUALCFG, 0x41) < 0) |
1386 | goto err; | 1473 | goto err; |
1387 | if (STV090x_WRITE_DEMOD(state, FFECFG, 0x41) < 0) | 1474 | if (STV090x_WRITE_DEMOD(state, FFECFG, 0x41) < 0) |
@@ -1418,10 +1505,10 @@ static int stv090x_start_search(struct stv090x_state *state) | |||
1418 | if (STV090x_WRITE_DEMOD(state, RTC, 0x88) < 0) | 1505 | if (STV090x_WRITE_DEMOD(state, RTC, 0x88) < 0) |
1419 | goto err; | 1506 | goto err; |
1420 | 1507 | ||
1421 | if (state->dev_ver >= 0x20) { | 1508 | if (state->internal->dev_ver >= 0x20) { |
1422 | /*Frequency offset detector setting*/ | 1509 | /*Frequency offset detector setting*/ |
1423 | if (state->srate < 2000000) { | 1510 | if (state->srate < 2000000) { |
1424 | if (state->dev_ver <= 0x20) { | 1511 | if (state->internal->dev_ver <= 0x20) { |
1425 | /* Cut 2 */ | 1512 | /* Cut 2 */ |
1426 | if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x39) < 0) | 1513 | if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x39) < 0) |
1427 | goto err; | 1514 | goto err; |
@@ -1512,7 +1599,7 @@ static int stv090x_get_agc2_min_level(struct stv090x_state *state) | |||
1512 | steps = 1; | 1599 | steps = 1; |
1513 | 1600 | ||
1514 | dir = 1; | 1601 | dir = 1; |
1515 | freq_step = (1000000 * 256) / (state->mclk / 256); | 1602 | freq_step = (1000000 * 256) / (state->internal->mclk / 256); |
1516 | freq_init = 0; | 1603 | freq_init = 0; |
1517 | 1604 | ||
1518 | for (i = 0; i < steps; i++) { | 1605 | for (i = 0; i < steps; i++) { |
@@ -1583,7 +1670,7 @@ static u32 stv090x_srate_srch_coarse(struct stv090x_state *state) | |||
1583 | u32 srate_coarse = 0, agc2 = 0, car_step = 1200, reg; | 1670 | u32 srate_coarse = 0, agc2 = 0, car_step = 1200, reg; |
1584 | u32 agc2th; | 1671 | u32 agc2th; |
1585 | 1672 | ||
1586 | if (state->dev_ver >= 0x30) | 1673 | if (state->internal->dev_ver >= 0x30) |
1587 | agc2th = 0x2e00; | 1674 | agc2th = 0x2e00; |
1588 | else | 1675 | else |
1589 | agc2th = 0x1f00; | 1676 | agc2th = 0x1f00; |
@@ -1619,13 +1706,13 @@ static u32 stv090x_srate_srch_coarse(struct stv090x_state *state) | |||
1619 | if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x50) < 0) | 1706 | if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x50) < 0) |
1620 | goto err; | 1707 | goto err; |
1621 | 1708 | ||
1622 | if (state->dev_ver >= 0x30) { | 1709 | if (state->internal->dev_ver >= 0x30) { |
1623 | if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x99) < 0) | 1710 | if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x99) < 0) |
1624 | goto err; | 1711 | goto err; |
1625 | if (STV090x_WRITE_DEMOD(state, SFRSTEP, 0x98) < 0) | 1712 | if (STV090x_WRITE_DEMOD(state, SFRSTEP, 0x98) < 0) |
1626 | goto err; | 1713 | goto err; |
1627 | 1714 | ||
1628 | } else if (state->dev_ver >= 0x20) { | 1715 | } else if (state->internal->dev_ver >= 0x20) { |
1629 | if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x6a) < 0) | 1716 | if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x6a) < 0) |
1630 | goto err; | 1717 | goto err; |
1631 | if (STV090x_WRITE_DEMOD(state, SFRSTEP, 0x95) < 0) | 1718 | if (STV090x_WRITE_DEMOD(state, SFRSTEP, 0x95) < 0) |
@@ -1677,7 +1764,7 @@ static u32 stv090x_srate_srch_coarse(struct stv090x_state *state) | |||
1677 | STV090x_READ_DEMOD(state, AGC2I0); | 1764 | STV090x_READ_DEMOD(state, AGC2I0); |
1678 | } | 1765 | } |
1679 | agc2 /= 10; | 1766 | agc2 /= 10; |
1680 | srate_coarse = stv090x_get_srate(state, state->mclk); | 1767 | srate_coarse = stv090x_get_srate(state, state->internal->mclk); |
1681 | cur_step++; | 1768 | cur_step++; |
1682 | dir *= -1; | 1769 | dir *= -1; |
1683 | if ((tmg_cpt >= 5) && (agc2 < agc2th) && | 1770 | if ((tmg_cpt >= 5) && (agc2 < agc2th) && |
@@ -1695,12 +1782,12 @@ static u32 stv090x_srate_srch_coarse(struct stv090x_state *state) | |||
1695 | 1782 | ||
1696 | if (state->config->tuner_set_frequency) { | 1783 | if (state->config->tuner_set_frequency) { |
1697 | if (state->config->tuner_set_frequency(fe, freq) < 0) | 1784 | if (state->config->tuner_set_frequency(fe, freq) < 0) |
1698 | goto err; | 1785 | goto err_gateoff; |
1699 | } | 1786 | } |
1700 | 1787 | ||
1701 | if (state->config->tuner_set_bandwidth) { | 1788 | if (state->config->tuner_set_bandwidth) { |
1702 | if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0) | 1789 | if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0) |
1703 | goto err; | 1790 | goto err_gateoff; |
1704 | } | 1791 | } |
1705 | 1792 | ||
1706 | if (stv090x_i2c_gate_ctrl(fe, 0) < 0) | 1793 | if (stv090x_i2c_gate_ctrl(fe, 0) < 0) |
@@ -1713,7 +1800,7 @@ static u32 stv090x_srate_srch_coarse(struct stv090x_state *state) | |||
1713 | 1800 | ||
1714 | if (state->config->tuner_get_status) { | 1801 | if (state->config->tuner_get_status) { |
1715 | if (state->config->tuner_get_status(fe, ®) < 0) | 1802 | if (state->config->tuner_get_status(fe, ®) < 0) |
1716 | goto err; | 1803 | goto err_gateoff; |
1717 | } | 1804 | } |
1718 | 1805 | ||
1719 | if (reg) | 1806 | if (reg) |
@@ -1729,9 +1816,12 @@ static u32 stv090x_srate_srch_coarse(struct stv090x_state *state) | |||
1729 | if (!tmg_lock) | 1816 | if (!tmg_lock) |
1730 | srate_coarse = 0; | 1817 | srate_coarse = 0; |
1731 | else | 1818 | else |
1732 | srate_coarse = stv090x_get_srate(state, state->mclk); | 1819 | srate_coarse = stv090x_get_srate(state, state->internal->mclk); |
1733 | 1820 | ||
1734 | return srate_coarse; | 1821 | return srate_coarse; |
1822 | |||
1823 | err_gateoff: | ||
1824 | stv090x_i2c_gate_ctrl(fe, 0); | ||
1735 | err: | 1825 | err: |
1736 | dprintk(FE_ERROR, 1, "I/O error"); | 1826 | dprintk(FE_ERROR, 1, "I/O error"); |
1737 | return -1; | 1827 | return -1; |
@@ -1741,7 +1831,7 @@ static u32 stv090x_srate_srch_fine(struct stv090x_state *state) | |||
1741 | { | 1831 | { |
1742 | u32 srate_coarse, freq_coarse, sym, reg; | 1832 | u32 srate_coarse, freq_coarse, sym, reg; |
1743 | 1833 | ||
1744 | srate_coarse = stv090x_get_srate(state, state->mclk); | 1834 | srate_coarse = stv090x_get_srate(state, state->internal->mclk); |
1745 | freq_coarse = STV090x_READ_DEMOD(state, CFR2) << 8; | 1835 | freq_coarse = STV090x_READ_DEMOD(state, CFR2) << 8; |
1746 | freq_coarse |= STV090x_READ_DEMOD(state, CFR1); | 1836 | freq_coarse |= STV090x_READ_DEMOD(state, CFR1); |
1747 | sym = 13 * (srate_coarse / 10); /* SFRUP = SFR + 30% */ | 1837 | sym = 13 * (srate_coarse / 10); /* SFRUP = SFR + 30% */ |
@@ -1767,10 +1857,10 @@ static u32 stv090x_srate_srch_fine(struct stv090x_state *state) | |||
1767 | if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0) | 1857 | if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0) |
1768 | goto err; | 1858 | goto err; |
1769 | 1859 | ||
1770 | if (state->dev_ver >= 0x30) { | 1860 | if (state->internal->dev_ver >= 0x30) { |
1771 | if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x79) < 0) | 1861 | if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x79) < 0) |
1772 | goto err; | 1862 | goto err; |
1773 | } else if (state->dev_ver >= 0x20) { | 1863 | } else if (state->internal->dev_ver >= 0x20) { |
1774 | if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x49) < 0) | 1864 | if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x49) < 0) |
1775 | goto err; | 1865 | goto err; |
1776 | } | 1866 | } |
@@ -1778,20 +1868,20 @@ static u32 stv090x_srate_srch_fine(struct stv090x_state *state) | |||
1778 | if (srate_coarse > 3000000) { | 1868 | if (srate_coarse > 3000000) { |
1779 | sym = 13 * (srate_coarse / 10); /* SFRUP = SFR + 30% */ | 1869 | sym = 13 * (srate_coarse / 10); /* SFRUP = SFR + 30% */ |
1780 | sym = (sym / 1000) * 65536; | 1870 | sym = (sym / 1000) * 65536; |
1781 | sym /= (state->mclk / 1000); | 1871 | sym /= (state->internal->mclk / 1000); |
1782 | if (STV090x_WRITE_DEMOD(state, SFRUP1, (sym >> 8) & 0x7f) < 0) | 1872 | if (STV090x_WRITE_DEMOD(state, SFRUP1, (sym >> 8) & 0x7f) < 0) |
1783 | goto err; | 1873 | goto err; |
1784 | if (STV090x_WRITE_DEMOD(state, SFRUP0, sym & 0xff) < 0) | 1874 | if (STV090x_WRITE_DEMOD(state, SFRUP0, sym & 0xff) < 0) |
1785 | goto err; | 1875 | goto err; |
1786 | sym = 10 * (srate_coarse / 13); /* SFRLOW = SFR - 30% */ | 1876 | sym = 10 * (srate_coarse / 13); /* SFRLOW = SFR - 30% */ |
1787 | sym = (sym / 1000) * 65536; | 1877 | sym = (sym / 1000) * 65536; |
1788 | sym /= (state->mclk / 1000); | 1878 | sym /= (state->internal->mclk / 1000); |
1789 | if (STV090x_WRITE_DEMOD(state, SFRLOW1, (sym >> 8) & 0x7f) < 0) | 1879 | if (STV090x_WRITE_DEMOD(state, SFRLOW1, (sym >> 8) & 0x7f) < 0) |
1790 | goto err; | 1880 | goto err; |
1791 | if (STV090x_WRITE_DEMOD(state, SFRLOW0, sym & 0xff) < 0) | 1881 | if (STV090x_WRITE_DEMOD(state, SFRLOW0, sym & 0xff) < 0) |
1792 | goto err; | 1882 | goto err; |
1793 | sym = (srate_coarse / 1000) * 65536; | 1883 | sym = (srate_coarse / 1000) * 65536; |
1794 | sym /= (state->mclk / 1000); | 1884 | sym /= (state->internal->mclk / 1000); |
1795 | if (STV090x_WRITE_DEMOD(state, SFRINIT1, (sym >> 8) & 0xff) < 0) | 1885 | if (STV090x_WRITE_DEMOD(state, SFRINIT1, (sym >> 8) & 0xff) < 0) |
1796 | goto err; | 1886 | goto err; |
1797 | if (STV090x_WRITE_DEMOD(state, SFRINIT0, sym & 0xff) < 0) | 1887 | if (STV090x_WRITE_DEMOD(state, SFRINIT0, sym & 0xff) < 0) |
@@ -1799,20 +1889,20 @@ static u32 stv090x_srate_srch_fine(struct stv090x_state *state) | |||
1799 | } else { | 1889 | } else { |
1800 | sym = 13 * (srate_coarse / 10); /* SFRUP = SFR + 30% */ | 1890 | sym = 13 * (srate_coarse / 10); /* SFRUP = SFR + 30% */ |
1801 | sym = (sym / 100) * 65536; | 1891 | sym = (sym / 100) * 65536; |
1802 | sym /= (state->mclk / 100); | 1892 | sym /= (state->internal->mclk / 100); |
1803 | if (STV090x_WRITE_DEMOD(state, SFRUP1, (sym >> 8) & 0x7f) < 0) | 1893 | if (STV090x_WRITE_DEMOD(state, SFRUP1, (sym >> 8) & 0x7f) < 0) |
1804 | goto err; | 1894 | goto err; |
1805 | if (STV090x_WRITE_DEMOD(state, SFRUP0, sym & 0xff) < 0) | 1895 | if (STV090x_WRITE_DEMOD(state, SFRUP0, sym & 0xff) < 0) |
1806 | goto err; | 1896 | goto err; |
1807 | sym = 10 * (srate_coarse / 14); /* SFRLOW = SFR - 30% */ | 1897 | sym = 10 * (srate_coarse / 14); /* SFRLOW = SFR - 30% */ |
1808 | sym = (sym / 100) * 65536; | 1898 | sym = (sym / 100) * 65536; |
1809 | sym /= (state->mclk / 100); | 1899 | sym /= (state->internal->mclk / 100); |
1810 | if (STV090x_WRITE_DEMOD(state, SFRLOW1, (sym >> 8) & 0x7f) < 0) | 1900 | if (STV090x_WRITE_DEMOD(state, SFRLOW1, (sym >> 8) & 0x7f) < 0) |
1811 | goto err; | 1901 | goto err; |
1812 | if (STV090x_WRITE_DEMOD(state, SFRLOW0, sym & 0xff) < 0) | 1902 | if (STV090x_WRITE_DEMOD(state, SFRLOW0, sym & 0xff) < 0) |
1813 | goto err; | 1903 | goto err; |
1814 | sym = (srate_coarse / 100) * 65536; | 1904 | sym = (srate_coarse / 100) * 65536; |
1815 | sym /= (state->mclk / 100); | 1905 | sym /= (state->internal->mclk / 100); |
1816 | if (STV090x_WRITE_DEMOD(state, SFRINIT1, (sym >> 8) & 0xff) < 0) | 1906 | if (STV090x_WRITE_DEMOD(state, SFRINIT1, (sym >> 8) & 0xff) < 0) |
1817 | goto err; | 1907 | goto err; |
1818 | if (STV090x_WRITE_DEMOD(state, SFRINIT0, sym & 0xff) < 0) | 1908 | if (STV090x_WRITE_DEMOD(state, SFRINIT0, sym & 0xff) < 0) |
@@ -1874,18 +1964,19 @@ static int stv090x_blind_search(struct stv090x_state *state) | |||
1874 | u32 agc2, reg, srate_coarse; | 1964 | u32 agc2, reg, srate_coarse; |
1875 | s32 cpt_fail, agc2_ovflw, i; | 1965 | s32 cpt_fail, agc2_ovflw, i; |
1876 | u8 k_ref, k_max, k_min; | 1966 | u8 k_ref, k_max, k_min; |
1877 | int coarse_fail, lock; | 1967 | int coarse_fail = 0; |
1968 | int lock; | ||
1878 | 1969 | ||
1879 | k_max = 110; | 1970 | k_max = 110; |
1880 | k_min = 10; | 1971 | k_min = 10; |
1881 | 1972 | ||
1882 | agc2 = stv090x_get_agc2_min_level(state); | 1973 | agc2 = stv090x_get_agc2_min_level(state); |
1883 | 1974 | ||
1884 | if (agc2 > STV090x_SEARCH_AGC2_TH(state->dev_ver)) { | 1975 | if (agc2 > STV090x_SEARCH_AGC2_TH(state->internal->dev_ver)) { |
1885 | lock = 0; | 1976 | lock = 0; |
1886 | } else { | 1977 | } else { |
1887 | 1978 | ||
1888 | if (state->dev_ver <= 0x20) { | 1979 | if (state->internal->dev_ver <= 0x20) { |
1889 | if (STV090x_WRITE_DEMOD(state, CARCFG, 0xc4) < 0) | 1980 | if (STV090x_WRITE_DEMOD(state, CARCFG, 0xc4) < 0) |
1890 | goto err; | 1981 | goto err; |
1891 | } else { | 1982 | } else { |
@@ -1897,7 +1988,7 @@ static int stv090x_blind_search(struct stv090x_state *state) | |||
1897 | if (STV090x_WRITE_DEMOD(state, RTCS2, 0x44) < 0) | 1988 | if (STV090x_WRITE_DEMOD(state, RTCS2, 0x44) < 0) |
1898 | goto err; | 1989 | goto err; |
1899 | 1990 | ||
1900 | if (state->dev_ver >= 0x20) { | 1991 | if (state->internal->dev_ver >= 0x20) { |
1901 | if (STV090x_WRITE_DEMOD(state, EQUALCFG, 0x41) < 0) | 1992 | if (STV090x_WRITE_DEMOD(state, EQUALCFG, 0x41) < 0) |
1902 | goto err; | 1993 | goto err; |
1903 | if (STV090x_WRITE_DEMOD(state, FFECFG, 0x41) < 0) | 1994 | if (STV090x_WRITE_DEMOD(state, FFECFG, 0x41) < 0) |
@@ -1956,7 +2047,7 @@ static int stv090x_chk_tmg(struct stv090x_state *state) | |||
1956 | u32 reg; | 2047 | u32 reg; |
1957 | s32 tmg_cpt = 0, i; | 2048 | s32 tmg_cpt = 0, i; |
1958 | u8 freq, tmg_thh, tmg_thl; | 2049 | u8 freq, tmg_thh, tmg_thl; |
1959 | int tmg_lock; | 2050 | int tmg_lock = 0; |
1960 | 2051 | ||
1961 | freq = STV090x_READ_DEMOD(state, CARFREQ); | 2052 | freq = STV090x_READ_DEMOD(state, CARFREQ); |
1962 | tmg_thh = STV090x_READ_DEMOD(state, TMGTHRISE); | 2053 | tmg_thh = STV090x_READ_DEMOD(state, TMGTHRISE); |
@@ -2080,12 +2171,12 @@ static int stv090x_get_coldlock(struct stv090x_state *state, s32 timeout_dmd) | |||
2080 | 2171 | ||
2081 | if (state->config->tuner_set_frequency) { | 2172 | if (state->config->tuner_set_frequency) { |
2082 | if (state->config->tuner_set_frequency(fe, freq) < 0) | 2173 | if (state->config->tuner_set_frequency(fe, freq) < 0) |
2083 | goto err; | 2174 | goto err_gateoff; |
2084 | } | 2175 | } |
2085 | 2176 | ||
2086 | if (state->config->tuner_set_bandwidth) { | 2177 | if (state->config->tuner_set_bandwidth) { |
2087 | if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0) | 2178 | if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0) |
2088 | goto err; | 2179 | goto err_gateoff; |
2089 | } | 2180 | } |
2090 | 2181 | ||
2091 | if (stv090x_i2c_gate_ctrl(fe, 0) < 0) | 2182 | if (stv090x_i2c_gate_ctrl(fe, 0) < 0) |
@@ -2098,7 +2189,7 @@ static int stv090x_get_coldlock(struct stv090x_state *state, s32 timeout_dmd) | |||
2098 | 2189 | ||
2099 | if (state->config->tuner_get_status) { | 2190 | if (state->config->tuner_get_status) { |
2100 | if (state->config->tuner_get_status(fe, ®) < 0) | 2191 | if (state->config->tuner_get_status(fe, ®) < 0) |
2101 | goto err; | 2192 | goto err_gateoff; |
2102 | } | 2193 | } |
2103 | 2194 | ||
2104 | if (reg) | 2195 | if (reg) |
@@ -2129,6 +2220,8 @@ static int stv090x_get_coldlock(struct stv090x_state *state, s32 timeout_dmd) | |||
2129 | 2220 | ||
2130 | return lock; | 2221 | return lock; |
2131 | 2222 | ||
2223 | err_gateoff: | ||
2224 | stv090x_i2c_gate_ctrl(fe, 0); | ||
2132 | err: | 2225 | err: |
2133 | dprintk(FE_ERROR, 1, "I/O error"); | 2226 | dprintk(FE_ERROR, 1, "I/O error"); |
2134 | return -1; | 2227 | return -1; |
@@ -2142,13 +2235,13 @@ static int stv090x_get_loop_params(struct stv090x_state *state, s32 *freq_inc, s | |||
2142 | car_max = state->search_range / 1000; | 2235 | car_max = state->search_range / 1000; |
2143 | car_max += car_max / 10; | 2236 | car_max += car_max / 10; |
2144 | car_max = 65536 * (car_max / 2); | 2237 | car_max = 65536 * (car_max / 2); |
2145 | car_max /= (state->mclk / 1000); | 2238 | car_max /= (state->internal->mclk / 1000); |
2146 | 2239 | ||
2147 | if (car_max > 0x4000) | 2240 | if (car_max > 0x4000) |
2148 | car_max = 0x4000 ; /* maxcarrier should be<= +-1/4 Mclk */ | 2241 | car_max = 0x4000 ; /* maxcarrier should be<= +-1/4 Mclk */ |
2149 | 2242 | ||
2150 | inc = srate; | 2243 | inc = srate; |
2151 | inc /= state->mclk / 1000; | 2244 | inc /= state->internal->mclk / 1000; |
2152 | inc *= 256; | 2245 | inc *= 256; |
2153 | inc *= 256; | 2246 | inc *= 256; |
2154 | inc /= 1000; | 2247 | inc /= 1000; |
@@ -2209,7 +2302,7 @@ static int stv090x_chk_signal(struct stv090x_state *state) | |||
2209 | 2302 | ||
2210 | car_max += (car_max / 10); /* 10% margin */ | 2303 | car_max += (car_max / 10); /* 10% margin */ |
2211 | car_max = (65536 * car_max / 2); | 2304 | car_max = (65536 * car_max / 2); |
2212 | car_max /= state->mclk / 1000; | 2305 | car_max /= state->internal->mclk / 1000; |
2213 | 2306 | ||
2214 | if (car_max > 0x4000) | 2307 | if (car_max > 0x4000) |
2215 | car_max = 0x4000; | 2308 | car_max = 0x4000; |
@@ -2234,7 +2327,7 @@ static int stv090x_search_car_loop(struct stv090x_state *state, s32 inc, s32 tim | |||
2234 | car_max = state->search_range / 1000; | 2327 | car_max = state->search_range / 1000; |
2235 | car_max += (car_max / 10); | 2328 | car_max += (car_max / 10); |
2236 | car_max = (65536 * car_max / 2); | 2329 | car_max = (65536 * car_max / 2); |
2237 | car_max /= (state->mclk / 1000); | 2330 | car_max /= (state->internal->mclk / 1000); |
2238 | if (car_max > 0x4000) | 2331 | if (car_max > 0x4000) |
2239 | car_max = 0x4000; | 2332 | car_max = 0x4000; |
2240 | 2333 | ||
@@ -2304,7 +2397,7 @@ static int stv090x_sw_algo(struct stv090x_state *state) | |||
2304 | case STV090x_SEARCH_DVBS1: | 2397 | case STV090x_SEARCH_DVBS1: |
2305 | case STV090x_SEARCH_DSS: | 2398 | case STV090x_SEARCH_DSS: |
2306 | /* accelerate the frequency detector */ | 2399 | /* accelerate the frequency detector */ |
2307 | if (state->dev_ver >= 0x20) { | 2400 | if (state->internal->dev_ver >= 0x20) { |
2308 | if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x3B) < 0) | 2401 | if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x3B) < 0) |
2309 | goto err; | 2402 | goto err; |
2310 | } | 2403 | } |
@@ -2315,7 +2408,7 @@ static int stv090x_sw_algo(struct stv090x_state *state) | |||
2315 | break; | 2408 | break; |
2316 | 2409 | ||
2317 | case STV090x_SEARCH_DVBS2: | 2410 | case STV090x_SEARCH_DVBS2: |
2318 | if (state->dev_ver >= 0x20) { | 2411 | if (state->internal->dev_ver >= 0x20) { |
2319 | if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x79) < 0) | 2412 | if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x79) < 0) |
2320 | goto err; | 2413 | goto err; |
2321 | } | 2414 | } |
@@ -2328,7 +2421,7 @@ static int stv090x_sw_algo(struct stv090x_state *state) | |||
2328 | case STV090x_SEARCH_AUTO: | 2421 | case STV090x_SEARCH_AUTO: |
2329 | default: | 2422 | default: |
2330 | /* accelerate the frequency detector */ | 2423 | /* accelerate the frequency detector */ |
2331 | if (state->dev_ver >= 0x20) { | 2424 | if (state->internal->dev_ver >= 0x20) { |
2332 | if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x3b) < 0) | 2425 | if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x3b) < 0) |
2333 | goto err; | 2426 | goto err; |
2334 | if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x79) < 0) | 2427 | if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x79) < 0) |
@@ -2350,7 +2443,7 @@ static int stv090x_sw_algo(struct stv090x_state *state) | |||
2350 | /*run the SW search 2 times maximum*/ | 2443 | /*run the SW search 2 times maximum*/ |
2351 | if (lock || no_signal || (trials == 2)) { | 2444 | if (lock || no_signal || (trials == 2)) { |
2352 | /*Check if the demod is not losing lock in DVBS2*/ | 2445 | /*Check if the demod is not losing lock in DVBS2*/ |
2353 | if (state->dev_ver >= 0x20) { | 2446 | if (state->internal->dev_ver >= 0x20) { |
2354 | if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x49) < 0) | 2447 | if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x49) < 0) |
2355 | goto err; | 2448 | goto err; |
2356 | if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x9e) < 0) | 2449 | if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x9e) < 0) |
@@ -2372,7 +2465,7 @@ static int stv090x_sw_algo(struct stv090x_state *state) | |||
2372 | /*FALSE lock, The demod is loosing lock */ | 2465 | /*FALSE lock, The demod is loosing lock */ |
2373 | lock = 0; | 2466 | lock = 0; |
2374 | if (trials < 2) { | 2467 | if (trials < 2) { |
2375 | if (state->dev_ver >= 0x20) { | 2468 | if (state->internal->dev_ver >= 0x20) { |
2376 | if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x79) < 0) | 2469 | if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x79) < 0) |
2377 | goto err; | 2470 | goto err; |
2378 | } | 2471 | } |
@@ -2422,11 +2515,11 @@ static s32 stv090x_get_car_freq(struct stv090x_state *state, u32 mclk) | |||
2422 | derot |= STV090x_READ_DEMOD(state, CFR0); | 2515 | derot |= STV090x_READ_DEMOD(state, CFR0); |
2423 | 2516 | ||
2424 | derot = comp2(derot, 24); | 2517 | derot = comp2(derot, 24); |
2425 | int_1 = state->mclk >> 12; | 2518 | int_1 = mclk >> 12; |
2426 | int_2 = derot >> 12; | 2519 | int_2 = derot >> 12; |
2427 | 2520 | ||
2428 | /* carrier_frequency = MasterClock * Reg / 2^24 */ | 2521 | /* carrier_frequency = MasterClock * Reg / 2^24 */ |
2429 | tmp_1 = state->mclk % 0x1000; | 2522 | tmp_1 = mclk % 0x1000; |
2430 | tmp_2 = derot % 0x1000; | 2523 | tmp_2 = derot % 0x1000; |
2431 | 2524 | ||
2432 | derot = (int_1 * int_2) + | 2525 | derot = (int_1 * int_2) + |
@@ -2502,13 +2595,13 @@ static enum stv090x_signal_state stv090x_get_sig_params(struct stv090x_state *st | |||
2502 | 2595 | ||
2503 | if (state->config->tuner_get_frequency) { | 2596 | if (state->config->tuner_get_frequency) { |
2504 | if (state->config->tuner_get_frequency(fe, &state->frequency) < 0) | 2597 | if (state->config->tuner_get_frequency(fe, &state->frequency) < 0) |
2505 | goto err; | 2598 | goto err_gateoff; |
2506 | } | 2599 | } |
2507 | 2600 | ||
2508 | if (stv090x_i2c_gate_ctrl(fe, 0) < 0) | 2601 | if (stv090x_i2c_gate_ctrl(fe, 0) < 0) |
2509 | goto err; | 2602 | goto err; |
2510 | 2603 | ||
2511 | offst_freq = stv090x_get_car_freq(state, state->mclk) / 1000; | 2604 | offst_freq = stv090x_get_car_freq(state, state->internal->mclk) / 1000; |
2512 | state->frequency += offst_freq; | 2605 | state->frequency += offst_freq; |
2513 | 2606 | ||
2514 | if (stv090x_get_viterbi(state) < 0) | 2607 | if (stv090x_get_viterbi(state) < 0) |
@@ -2530,7 +2623,7 @@ static enum stv090x_signal_state stv090x_get_sig_params(struct stv090x_state *st | |||
2530 | 2623 | ||
2531 | if (state->config->tuner_get_frequency) { | 2624 | if (state->config->tuner_get_frequency) { |
2532 | if (state->config->tuner_get_frequency(fe, &state->frequency) < 0) | 2625 | if (state->config->tuner_get_frequency(fe, &state->frequency) < 0) |
2533 | goto err; | 2626 | goto err_gateoff; |
2534 | } | 2627 | } |
2535 | 2628 | ||
2536 | if (stv090x_i2c_gate_ctrl(fe, 0) < 0) | 2629 | if (stv090x_i2c_gate_ctrl(fe, 0) < 0) |
@@ -2550,6 +2643,9 @@ static enum stv090x_signal_state stv090x_get_sig_params(struct stv090x_state *st | |||
2550 | } | 2643 | } |
2551 | 2644 | ||
2552 | return STV090x_OUTOFRANGE; | 2645 | return STV090x_OUTOFRANGE; |
2646 | |||
2647 | err_gateoff: | ||
2648 | stv090x_i2c_gate_ctrl(fe, 0); | ||
2553 | err: | 2649 | err: |
2554 | dprintk(FE_ERROR, 1, "I/O error"); | 2650 | dprintk(FE_ERROR, 1, "I/O error"); |
2555 | return -1; | 2651 | return -1; |
@@ -2579,7 +2675,7 @@ static u8 stv090x_optimize_carloop(struct stv090x_state *state, enum stv090x_mod | |||
2579 | s32 i; | 2675 | s32 i; |
2580 | struct stv090x_long_frame_crloop *car_loop, *car_loop_qpsk_low, *car_loop_apsk_low; | 2676 | struct stv090x_long_frame_crloop *car_loop, *car_loop_qpsk_low, *car_loop_apsk_low; |
2581 | 2677 | ||
2582 | if (state->dev_ver == 0x20) { | 2678 | if (state->internal->dev_ver == 0x20) { |
2583 | car_loop = stv090x_s2_crl_cut20; | 2679 | car_loop = stv090x_s2_crl_cut20; |
2584 | car_loop_qpsk_low = stv090x_s2_lowqpsk_crl_cut20; | 2680 | car_loop_qpsk_low = stv090x_s2_lowqpsk_crl_cut20; |
2585 | car_loop_apsk_low = stv090x_s2_apsk_crl_cut20; | 2681 | car_loop_apsk_low = stv090x_s2_apsk_crl_cut20; |
@@ -2700,7 +2796,7 @@ static u8 stv090x_optimize_carloop_short(struct stv090x_state *state) | |||
2700 | break; | 2796 | break; |
2701 | } | 2797 | } |
2702 | 2798 | ||
2703 | if (state->dev_ver >= 0x30) { | 2799 | if (state->internal->dev_ver >= 0x30) { |
2704 | /* Cut 3.0 and up */ | 2800 | /* Cut 3.0 and up */ |
2705 | short_crl = stv090x_s2_short_crl_cut30; | 2801 | short_crl = stv090x_s2_short_crl_cut30; |
2706 | } else { | 2802 | } else { |
@@ -2732,7 +2828,7 @@ static int stv090x_optimize_track(struct stv090x_state *state) | |||
2732 | s32 srate, pilots, aclc, f_1, f_0, i = 0, blind_tune = 0; | 2828 | s32 srate, pilots, aclc, f_1, f_0, i = 0, blind_tune = 0; |
2733 | u32 reg; | 2829 | u32 reg; |
2734 | 2830 | ||
2735 | srate = stv090x_get_srate(state, state->mclk); | 2831 | srate = stv090x_get_srate(state, state->internal->mclk); |
2736 | srate += stv090x_get_tmgoffst(state, srate); | 2832 | srate += stv090x_get_tmgoffst(state, srate); |
2737 | 2833 | ||
2738 | switch (state->delsys) { | 2834 | switch (state->delsys) { |
@@ -2751,7 +2847,7 @@ static int stv090x_optimize_track(struct stv090x_state *state) | |||
2751 | if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0) | 2847 | if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0) |
2752 | goto err; | 2848 | goto err; |
2753 | 2849 | ||
2754 | if (state->dev_ver >= 0x30) { | 2850 | if (state->internal->dev_ver >= 0x30) { |
2755 | if (stv090x_get_viterbi(state) < 0) | 2851 | if (stv090x_get_viterbi(state) < 0) |
2756 | goto err; | 2852 | goto err; |
2757 | 2853 | ||
@@ -2868,7 +2964,7 @@ static int stv090x_optimize_track(struct stv090x_state *state) | |||
2868 | goto err; | 2964 | goto err; |
2869 | } | 2965 | } |
2870 | 2966 | ||
2871 | if (state->dev_ver >= 0x20) { | 2967 | if (state->internal->dev_ver >= 0x20) { |
2872 | if ((state->search_mode == STV090x_SEARCH_DVBS1) || | 2968 | if ((state->search_mode == STV090x_SEARCH_DVBS1) || |
2873 | (state->search_mode == STV090x_SEARCH_DSS) || | 2969 | (state->search_mode == STV090x_SEARCH_DSS) || |
2874 | (state->search_mode == STV090x_SEARCH_AUTO)) { | 2970 | (state->search_mode == STV090x_SEARCH_AUTO)) { |
@@ -2890,7 +2986,8 @@ static int stv090x_optimize_track(struct stv090x_state *state) | |||
2890 | if (STV090x_WRITE_DEMOD(state, SFRLOW1, 0x80) < 0) | 2986 | if (STV090x_WRITE_DEMOD(state, SFRLOW1, 0x80) < 0) |
2891 | goto err; | 2987 | goto err; |
2892 | 2988 | ||
2893 | if ((state->dev_ver >= 0x20) || (blind_tune == 1) || (state->srate < 10000000)) { | 2989 | if ((state->internal->dev_ver >= 0x20) || (blind_tune == 1) || |
2990 | (state->srate < 10000000)) { | ||
2894 | /* update initial carrier freq with the found freq offset */ | 2991 | /* update initial carrier freq with the found freq offset */ |
2895 | if (STV090x_WRITE_DEMOD(state, CFRINIT1, f_1) < 0) | 2992 | if (STV090x_WRITE_DEMOD(state, CFRINIT1, f_1) < 0) |
2896 | goto err; | 2993 | goto err; |
@@ -2898,7 +2995,7 @@ static int stv090x_optimize_track(struct stv090x_state *state) | |||
2898 | goto err; | 2995 | goto err; |
2899 | state->tuner_bw = stv090x_car_width(srate, state->rolloff) + 10000000; | 2996 | state->tuner_bw = stv090x_car_width(srate, state->rolloff) + 10000000; |
2900 | 2997 | ||
2901 | if ((state->dev_ver >= 0x20) || (blind_tune == 1)) { | 2998 | if ((state->internal->dev_ver >= 0x20) || (blind_tune == 1)) { |
2902 | 2999 | ||
2903 | if (state->algo != STV090x_WARM_SEARCH) { | 3000 | if (state->algo != STV090x_WARM_SEARCH) { |
2904 | 3001 | ||
@@ -2907,7 +3004,7 @@ static int stv090x_optimize_track(struct stv090x_state *state) | |||
2907 | 3004 | ||
2908 | if (state->config->tuner_set_bandwidth) { | 3005 | if (state->config->tuner_set_bandwidth) { |
2909 | if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0) | 3006 | if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0) |
2910 | goto err; | 3007 | goto err_gateoff; |
2911 | } | 3008 | } |
2912 | 3009 | ||
2913 | if (stv090x_i2c_gate_ctrl(fe, 0) < 0) | 3010 | if (stv090x_i2c_gate_ctrl(fe, 0) < 0) |
@@ -2950,7 +3047,7 @@ static int stv090x_optimize_track(struct stv090x_state *state) | |||
2950 | 3047 | ||
2951 | } | 3048 | } |
2952 | 3049 | ||
2953 | if (state->dev_ver >= 0x20) { | 3050 | if (state->internal->dev_ver >= 0x20) { |
2954 | if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x49) < 0) | 3051 | if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x49) < 0) |
2955 | goto err; | 3052 | goto err; |
2956 | } | 3053 | } |
@@ -2959,6 +3056,9 @@ static int stv090x_optimize_track(struct stv090x_state *state) | |||
2959 | stv090x_set_vit_thtracq(state); | 3056 | stv090x_set_vit_thtracq(state); |
2960 | 3057 | ||
2961 | return 0; | 3058 | return 0; |
3059 | |||
3060 | err_gateoff: | ||
3061 | stv090x_i2c_gate_ctrl(fe, 0); | ||
2962 | err: | 3062 | err: |
2963 | dprintk(FE_ERROR, 1, "I/O error"); | 3063 | dprintk(FE_ERROR, 1, "I/O error"); |
2964 | return -1; | 3064 | return -1; |
@@ -3026,7 +3126,7 @@ static int stv090x_set_s2rolloff(struct stv090x_state *state) | |||
3026 | { | 3126 | { |
3027 | u32 reg; | 3127 | u32 reg; |
3028 | 3128 | ||
3029 | if (state->dev_ver <= 0x20) { | 3129 | if (state->internal->dev_ver <= 0x20) { |
3030 | /* rolloff to auto mode if DVBS2 */ | 3130 | /* rolloff to auto mode if DVBS2 */ |
3031 | reg = STV090x_READ_DEMOD(state, DEMOD); | 3131 | reg = STV090x_READ_DEMOD(state, DEMOD); |
3032 | STV090x_SETFIELD_Px(reg, MANUAL_SXROLLOFF_FIELD, 0x00); | 3132 | STV090x_SETFIELD_Px(reg, MANUAL_SXROLLOFF_FIELD, 0x00); |
@@ -3062,7 +3162,7 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) | |||
3062 | if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x5c) < 0) /* Demod stop */ | 3162 | if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x5c) < 0) /* Demod stop */ |
3063 | goto err; | 3163 | goto err; |
3064 | 3164 | ||
3065 | if (state->dev_ver >= 0x20) { | 3165 | if (state->internal->dev_ver >= 0x20) { |
3066 | if (state->srate > 5000000) { | 3166 | if (state->srate > 5000000) { |
3067 | if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x9e) < 0) | 3167 | if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x9e) < 0) |
3068 | goto err; | 3168 | goto err; |
@@ -3102,7 +3202,7 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) | |||
3102 | if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0) | 3202 | if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0) |
3103 | goto err; | 3203 | goto err; |
3104 | 3204 | ||
3105 | if (state->dev_ver >= 0x20) { | 3205 | if (state->internal->dev_ver >= 0x20) { |
3106 | if (STV090x_WRITE_DEMOD(state, KREFTMG, 0x5a) < 0) | 3206 | if (STV090x_WRITE_DEMOD(state, KREFTMG, 0x5a) < 0) |
3107 | goto err; | 3207 | goto err; |
3108 | if (state->algo == STV090x_COLD_SEARCH) | 3208 | if (state->algo == STV090x_COLD_SEARCH) |
@@ -3120,9 +3220,11 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) | |||
3120 | if (stv090x_set_srate(state, state->srate) < 0) | 3220 | if (stv090x_set_srate(state, state->srate) < 0) |
3121 | goto err; | 3221 | goto err; |
3122 | 3222 | ||
3123 | if (stv090x_set_max_srate(state, state->mclk, state->srate) < 0) | 3223 | if (stv090x_set_max_srate(state, state->internal->mclk, |
3224 | state->srate) < 0) | ||
3124 | goto err; | 3225 | goto err; |
3125 | if (stv090x_set_min_srate(state, state->mclk, state->srate) < 0) | 3226 | if (stv090x_set_min_srate(state, state->internal->mclk, |
3227 | state->srate) < 0) | ||
3126 | goto err; | 3228 | goto err; |
3127 | 3229 | ||
3128 | if (state->srate >= 10000000) | 3230 | if (state->srate >= 10000000) |
@@ -3136,18 +3238,21 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) | |||
3136 | goto err; | 3238 | goto err; |
3137 | 3239 | ||
3138 | if (state->config->tuner_set_bbgain) { | 3240 | if (state->config->tuner_set_bbgain) { |
3139 | if (state->config->tuner_set_bbgain(fe, 10) < 0) /* 10dB */ | 3241 | reg = state->config->tuner_bbgain; |
3140 | goto err; | 3242 | if (reg == 0) |
3243 | reg = 10; /* default: 10dB */ | ||
3244 | if (state->config->tuner_set_bbgain(fe, reg) < 0) | ||
3245 | goto err_gateoff; | ||
3141 | } | 3246 | } |
3142 | 3247 | ||
3143 | if (state->config->tuner_set_frequency) { | 3248 | if (state->config->tuner_set_frequency) { |
3144 | if (state->config->tuner_set_frequency(fe, state->frequency) < 0) | 3249 | if (state->config->tuner_set_frequency(fe, state->frequency) < 0) |
3145 | goto err; | 3250 | goto err_gateoff; |
3146 | } | 3251 | } |
3147 | 3252 | ||
3148 | if (state->config->tuner_set_bandwidth) { | 3253 | if (state->config->tuner_set_bandwidth) { |
3149 | if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0) | 3254 | if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0) |
3150 | goto err; | 3255 | goto err_gateoff; |
3151 | } | 3256 | } |
3152 | 3257 | ||
3153 | if (stv090x_i2c_gate_ctrl(fe, 0) < 0) | 3258 | if (stv090x_i2c_gate_ctrl(fe, 0) < 0) |
@@ -3155,21 +3260,21 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) | |||
3155 | 3260 | ||
3156 | msleep(50); | 3261 | msleep(50); |
3157 | 3262 | ||
3158 | if (stv090x_i2c_gate_ctrl(fe, 1) < 0) | ||
3159 | goto err; | ||
3160 | |||
3161 | if (state->config->tuner_get_status) { | 3263 | if (state->config->tuner_get_status) { |
3264 | if (stv090x_i2c_gate_ctrl(fe, 1) < 0) | ||
3265 | goto err; | ||
3162 | if (state->config->tuner_get_status(fe, ®) < 0) | 3266 | if (state->config->tuner_get_status(fe, ®) < 0) |
3267 | goto err_gateoff; | ||
3268 | if (stv090x_i2c_gate_ctrl(fe, 0) < 0) | ||
3163 | goto err; | 3269 | goto err; |
3164 | } | ||
3165 | 3270 | ||
3166 | if (reg) | 3271 | if (reg) |
3167 | dprintk(FE_DEBUG, 1, "Tuner phase locked"); | 3272 | dprintk(FE_DEBUG, 1, "Tuner phase locked"); |
3168 | else | 3273 | else { |
3169 | dprintk(FE_DEBUG, 1, "Tuner unlocked"); | 3274 | dprintk(FE_DEBUG, 1, "Tuner unlocked"); |
3170 | 3275 | return STV090x_NOCARRIER; | |
3171 | if (stv090x_i2c_gate_ctrl(fe, 0) < 0) | 3276 | } |
3172 | goto err; | 3277 | } |
3173 | 3278 | ||
3174 | msleep(10); | 3279 | msleep(10); |
3175 | agc1_power = MAKEWORD16(STV090x_READ_DEMOD(state, AGCIQIN1), | 3280 | agc1_power = MAKEWORD16(STV090x_READ_DEMOD(state, AGCIQIN1), |
@@ -3194,7 +3299,7 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) | |||
3194 | reg = STV090x_READ_DEMOD(state, DEMOD); | 3299 | reg = STV090x_READ_DEMOD(state, DEMOD); |
3195 | STV090x_SETFIELD_Px(reg, SPECINV_CONTROL_FIELD, state->inversion); | 3300 | STV090x_SETFIELD_Px(reg, SPECINV_CONTROL_FIELD, state->inversion); |
3196 | 3301 | ||
3197 | if (state->dev_ver <= 0x20) { | 3302 | if (state->internal->dev_ver <= 0x20) { |
3198 | /* rolloff to auto mode if DVBS2 */ | 3303 | /* rolloff to auto mode if DVBS2 */ |
3199 | STV090x_SETFIELD_Px(reg, MANUAL_SXROLLOFF_FIELD, 1); | 3304 | STV090x_SETFIELD_Px(reg, MANUAL_SXROLLOFF_FIELD, 1); |
3200 | } else { | 3305 | } else { |
@@ -3238,7 +3343,7 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) | |||
3238 | if ((lock) && (signal_state == STV090x_RANGEOK)) { /* signal within Range */ | 3343 | if ((lock) && (signal_state == STV090x_RANGEOK)) { /* signal within Range */ |
3239 | stv090x_optimize_track(state); | 3344 | stv090x_optimize_track(state); |
3240 | 3345 | ||
3241 | if (state->dev_ver >= 0x20) { | 3346 | if (state->internal->dev_ver >= 0x20) { |
3242 | /* >= Cut 2.0 :release TS reset after | 3347 | /* >= Cut 2.0 :release TS reset after |
3243 | * demod lock and optimized Tracking | 3348 | * demod lock and optimized Tracking |
3244 | */ | 3349 | */ |
@@ -3293,6 +3398,8 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state) | |||
3293 | } | 3398 | } |
3294 | return signal_state; | 3399 | return signal_state; |
3295 | 3400 | ||
3401 | err_gateoff: | ||
3402 | stv090x_i2c_gate_ctrl(fe, 0); | ||
3296 | err: | 3403 | err: |
3297 | dprintk(FE_ERROR, 1, "I/O error"); | 3404 | dprintk(FE_ERROR, 1, "I/O error"); |
3298 | return -1; | 3405 | return -1; |
@@ -3303,6 +3410,9 @@ static enum dvbfe_search stv090x_search(struct dvb_frontend *fe, struct dvb_fron | |||
3303 | struct stv090x_state *state = fe->demodulator_priv; | 3410 | struct stv090x_state *state = fe->demodulator_priv; |
3304 | struct dtv_frontend_properties *props = &fe->dtv_property_cache; | 3411 | struct dtv_frontend_properties *props = &fe->dtv_property_cache; |
3305 | 3412 | ||
3413 | if (p->frequency == 0) | ||
3414 | return DVBFE_ALGO_SEARCH_INVALID; | ||
3415 | |||
3306 | state->delsys = props->delivery_system; | 3416 | state->delsys = props->delivery_system; |
3307 | state->frequency = p->frequency; | 3417 | state->frequency = p->frequency; |
3308 | state->srate = p->u.qpsk.symbol_rate; | 3418 | state->srate = p->u.qpsk.symbol_rate; |
@@ -3353,7 +3463,8 @@ static int stv090x_read_status(struct dvb_frontend *fe, enum fe_status *status) | |||
3353 | if (STV090x_GETFIELD_Px(reg, PKTDELIN_LOCK_FIELD)) { | 3463 | if (STV090x_GETFIELD_Px(reg, PKTDELIN_LOCK_FIELD)) { |
3354 | reg = STV090x_READ_DEMOD(state, TSSTATUS); | 3464 | reg = STV090x_READ_DEMOD(state, TSSTATUS); |
3355 | if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD)) { | 3465 | if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD)) { |
3356 | *status = FE_HAS_CARRIER | | 3466 | *status = FE_HAS_SIGNAL | |
3467 | FE_HAS_CARRIER | | ||
3357 | FE_HAS_VITERBI | | 3468 | FE_HAS_VITERBI | |
3358 | FE_HAS_SYNC | | 3469 | FE_HAS_SYNC | |
3359 | FE_HAS_LOCK; | 3470 | FE_HAS_LOCK; |
@@ -3370,7 +3481,11 @@ static int stv090x_read_status(struct dvb_frontend *fe, enum fe_status *status) | |||
3370 | if (STV090x_GETFIELD_Px(reg, LOCKEDVIT_FIELD)) { | 3481 | if (STV090x_GETFIELD_Px(reg, LOCKEDVIT_FIELD)) { |
3371 | reg = STV090x_READ_DEMOD(state, TSSTATUS); | 3482 | reg = STV090x_READ_DEMOD(state, TSSTATUS); |
3372 | if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD)) { | 3483 | if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD)) { |
3373 | *status = FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; | 3484 | *status = FE_HAS_SIGNAL | |
3485 | FE_HAS_CARRIER | | ||
3486 | FE_HAS_VITERBI | | ||
3487 | FE_HAS_SYNC | | ||
3488 | FE_HAS_LOCK; | ||
3374 | } | 3489 | } |
3375 | } | 3490 | } |
3376 | } | 3491 | } |
@@ -3770,6 +3885,15 @@ static void stv090x_release(struct dvb_frontend *fe) | |||
3770 | { | 3885 | { |
3771 | struct stv090x_state *state = fe->demodulator_priv; | 3886 | struct stv090x_state *state = fe->demodulator_priv; |
3772 | 3887 | ||
3888 | state->internal->num_used--; | ||
3889 | if (state->internal->num_used <= 0) { | ||
3890 | |||
3891 | dprintk(FE_ERROR, 1, "Actually removing"); | ||
3892 | |||
3893 | remove_dev(state->internal); | ||
3894 | kfree(state->internal); | ||
3895 | } | ||
3896 | |||
3773 | kfree(state); | 3897 | kfree(state); |
3774 | } | 3898 | } |
3775 | 3899 | ||
@@ -3901,10 +4025,10 @@ static int stv090x_set_mclk(struct stv090x_state *state, u32 mclk, u32 clk) | |||
3901 | if (stv090x_write_reg(state, STV090x_NCOARSE, reg) < 0) | 4025 | if (stv090x_write_reg(state, STV090x_NCOARSE, reg) < 0) |
3902 | goto err; | 4026 | goto err; |
3903 | 4027 | ||
3904 | state->mclk = stv090x_get_mclk(state); | 4028 | state->internal->mclk = stv090x_get_mclk(state); |
3905 | 4029 | ||
3906 | /*Set the DiseqC frequency to 22KHz */ | 4030 | /*Set the DiseqC frequency to 22KHz */ |
3907 | div = state->mclk / 704000; | 4031 | div = state->internal->mclk / 704000; |
3908 | if (STV090x_WRITE_DEMOD(state, F22TX, div) < 0) | 4032 | if (STV090x_WRITE_DEMOD(state, F22TX, div) < 0) |
3909 | goto err; | 4033 | goto err; |
3910 | if (STV090x_WRITE_DEMOD(state, F22RX, div) < 0) | 4034 | if (STV090x_WRITE_DEMOD(state, F22RX, div) < 0) |
@@ -3920,7 +4044,7 @@ static int stv090x_set_tspath(struct stv090x_state *state) | |||
3920 | { | 4044 | { |
3921 | u32 reg; | 4045 | u32 reg; |
3922 | 4046 | ||
3923 | if (state->dev_ver >= 0x20) { | 4047 | if (state->internal->dev_ver >= 0x20) { |
3924 | switch (state->config->ts1_mode) { | 4048 | switch (state->config->ts1_mode) { |
3925 | case STV090x_TSMODE_PARALLEL_PUNCTURED: | 4049 | case STV090x_TSMODE_PARALLEL_PUNCTURED: |
3926 | case STV090x_TSMODE_DVBCI: | 4050 | case STV090x_TSMODE_DVBCI: |
@@ -4092,6 +4216,71 @@ static int stv090x_set_tspath(struct stv090x_state *state) | |||
4092 | default: | 4216 | default: |
4093 | break; | 4217 | break; |
4094 | } | 4218 | } |
4219 | |||
4220 | if (state->config->ts1_clk > 0) { | ||
4221 | u32 speed; | ||
4222 | |||
4223 | switch (state->config->ts1_mode) { | ||
4224 | case STV090x_TSMODE_PARALLEL_PUNCTURED: | ||
4225 | case STV090x_TSMODE_DVBCI: | ||
4226 | default: | ||
4227 | speed = state->internal->mclk / | ||
4228 | (state->config->ts1_clk / 4); | ||
4229 | if (speed < 0x08) | ||
4230 | speed = 0x08; | ||
4231 | if (speed > 0xFF) | ||
4232 | speed = 0xFF; | ||
4233 | break; | ||
4234 | case STV090x_TSMODE_SERIAL_PUNCTURED: | ||
4235 | case STV090x_TSMODE_SERIAL_CONTINUOUS: | ||
4236 | speed = state->internal->mclk / | ||
4237 | (state->config->ts1_clk / 32); | ||
4238 | if (speed < 0x20) | ||
4239 | speed = 0x20; | ||
4240 | if (speed > 0xFF) | ||
4241 | speed = 0xFF; | ||
4242 | break; | ||
4243 | } | ||
4244 | reg = stv090x_read_reg(state, STV090x_P1_TSCFGM); | ||
4245 | STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 3); | ||
4246 | if (stv090x_write_reg(state, STV090x_P1_TSCFGM, reg) < 0) | ||
4247 | goto err; | ||
4248 | if (stv090x_write_reg(state, STV090x_P1_TSSPEED, speed) < 0) | ||
4249 | goto err; | ||
4250 | } | ||
4251 | |||
4252 | if (state->config->ts2_clk > 0) { | ||
4253 | u32 speed; | ||
4254 | |||
4255 | switch (state->config->ts2_mode) { | ||
4256 | case STV090x_TSMODE_PARALLEL_PUNCTURED: | ||
4257 | case STV090x_TSMODE_DVBCI: | ||
4258 | default: | ||
4259 | speed = state->internal->mclk / | ||
4260 | (state->config->ts2_clk / 4); | ||
4261 | if (speed < 0x08) | ||
4262 | speed = 0x08; | ||
4263 | if (speed > 0xFF) | ||
4264 | speed = 0xFF; | ||
4265 | break; | ||
4266 | case STV090x_TSMODE_SERIAL_PUNCTURED: | ||
4267 | case STV090x_TSMODE_SERIAL_CONTINUOUS: | ||
4268 | speed = state->internal->mclk / | ||
4269 | (state->config->ts2_clk / 32); | ||
4270 | if (speed < 0x20) | ||
4271 | speed = 0x20; | ||
4272 | if (speed > 0xFF) | ||
4273 | speed = 0xFF; | ||
4274 | break; | ||
4275 | } | ||
4276 | reg = stv090x_read_reg(state, STV090x_P2_TSCFGM); | ||
4277 | STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 3); | ||
4278 | if (stv090x_write_reg(state, STV090x_P2_TSCFGM, reg) < 0) | ||
4279 | goto err; | ||
4280 | if (stv090x_write_reg(state, STV090x_P2_TSSPEED, speed) < 0) | ||
4281 | goto err; | ||
4282 | } | ||
4283 | |||
4095 | reg = stv090x_read_reg(state, STV090x_P2_TSCFGH); | 4284 | reg = stv090x_read_reg(state, STV090x_P2_TSCFGH); |
4096 | STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x01); | 4285 | STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x01); |
4097 | if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0) | 4286 | if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0) |
@@ -4120,6 +4309,15 @@ static int stv090x_init(struct dvb_frontend *fe) | |||
4120 | const struct stv090x_config *config = state->config; | 4309 | const struct stv090x_config *config = state->config; |
4121 | u32 reg; | 4310 | u32 reg; |
4122 | 4311 | ||
4312 | if (state->internal->mclk == 0) { | ||
4313 | stv090x_set_mclk(state, 135000000, config->xtal); /* 135 Mhz */ | ||
4314 | msleep(5); | ||
4315 | if (stv090x_write_reg(state, STV090x_SYNTCTRL, | ||
4316 | 0x20 | config->clk_mode) < 0) | ||
4317 | goto err; | ||
4318 | stv090x_get_mclk(state); | ||
4319 | } | ||
4320 | |||
4123 | if (stv090x_wakeup(fe) < 0) { | 4321 | if (stv090x_wakeup(fe) < 0) { |
4124 | dprintk(FE_ERROR, 1, "Error waking device"); | 4322 | dprintk(FE_ERROR, 1, "Error waking device"); |
4125 | goto err; | 4323 | goto err; |
@@ -4142,12 +4340,12 @@ static int stv090x_init(struct dvb_frontend *fe) | |||
4142 | 4340 | ||
4143 | if (config->tuner_set_mode) { | 4341 | if (config->tuner_set_mode) { |
4144 | if (config->tuner_set_mode(fe, TUNER_WAKE) < 0) | 4342 | if (config->tuner_set_mode(fe, TUNER_WAKE) < 0) |
4145 | goto err; | 4343 | goto err_gateoff; |
4146 | } | 4344 | } |
4147 | 4345 | ||
4148 | if (config->tuner_init) { | 4346 | if (config->tuner_init) { |
4149 | if (config->tuner_init(fe) < 0) | 4347 | if (config->tuner_init(fe) < 0) |
4150 | goto err; | 4348 | goto err_gateoff; |
4151 | } | 4349 | } |
4152 | 4350 | ||
4153 | if (stv090x_i2c_gate_ctrl(fe, 0) < 0) | 4351 | if (stv090x_i2c_gate_ctrl(fe, 0) < 0) |
@@ -4157,6 +4355,9 @@ static int stv090x_init(struct dvb_frontend *fe) | |||
4157 | goto err; | 4355 | goto err; |
4158 | 4356 | ||
4159 | return 0; | 4357 | return 0; |
4358 | |||
4359 | err_gateoff: | ||
4360 | stv090x_i2c_gate_ctrl(fe, 0); | ||
4160 | err: | 4361 | err: |
4161 | dprintk(FE_ERROR, 1, "I/O error"); | 4362 | dprintk(FE_ERROR, 1, "I/O error"); |
4162 | return -1; | 4363 | return -1; |
@@ -4188,16 +4389,26 @@ static int stv090x_setup(struct dvb_frontend *fe) | |||
4188 | } | 4389 | } |
4189 | 4390 | ||
4190 | /* STV090x init */ | 4391 | /* STV090x init */ |
4191 | if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x5c) < 0) /* Stop Demod */ | 4392 | |
4393 | /* Stop Demod */ | ||
4394 | if (stv090x_write_reg(state, STV090x_P1_DMDISTATE, 0x5c) < 0) | ||
4395 | goto err; | ||
4396 | if (stv090x_write_reg(state, STV090x_P2_DMDISTATE, 0x5c) < 0) | ||
4192 | goto err; | 4397 | goto err; |
4193 | 4398 | ||
4194 | msleep(5); | 4399 | msleep(5); |
4195 | 4400 | ||
4196 | if (STV090x_WRITE_DEMOD(state, TNRCFG, 0x6c) < 0) /* check register ! (No Tuner Mode) */ | 4401 | /* Set No Tuner Mode */ |
4402 | if (stv090x_write_reg(state, STV090x_P1_TNRCFG, 0x6c) < 0) | ||
4403 | goto err; | ||
4404 | if (stv090x_write_reg(state, STV090x_P2_TNRCFG, 0x6c) < 0) | ||
4197 | goto err; | 4405 | goto err; |
4198 | 4406 | ||
4407 | /* I2C repeater OFF */ | ||
4199 | STV090x_SETFIELD_Px(reg, ENARPT_LEVEL_FIELD, config->repeater_level); | 4408 | STV090x_SETFIELD_Px(reg, ENARPT_LEVEL_FIELD, config->repeater_level); |
4200 | if (STV090x_WRITE_DEMOD(state, I2CRPT, reg) < 0) /* repeater OFF */ | 4409 | if (stv090x_write_reg(state, STV090x_P1_I2CRPT, reg) < 0) |
4410 | goto err; | ||
4411 | if (stv090x_write_reg(state, STV090x_P2_I2CRPT, reg) < 0) | ||
4201 | goto err; | 4412 | goto err; |
4202 | 4413 | ||
4203 | if (stv090x_write_reg(state, STV090x_NCOARSE, 0x13) < 0) /* set PLL divider */ | 4414 | if (stv090x_write_reg(state, STV090x_NCOARSE, 0x13) < 0) /* set PLL divider */ |
@@ -4216,8 +4427,8 @@ static int stv090x_setup(struct dvb_frontend *fe) | |||
4216 | goto err; | 4427 | goto err; |
4217 | } | 4428 | } |
4218 | 4429 | ||
4219 | state->dev_ver = stv090x_read_reg(state, STV090x_MID); | 4430 | state->internal->dev_ver = stv090x_read_reg(state, STV090x_MID); |
4220 | if (state->dev_ver >= 0x20) { | 4431 | if (state->internal->dev_ver >= 0x20) { |
4221 | if (stv090x_write_reg(state, STV090x_TSGENERAL, 0x0c) < 0) | 4432 | if (stv090x_write_reg(state, STV090x_TSGENERAL, 0x0c) < 0) |
4222 | goto err; | 4433 | goto err; |
4223 | 4434 | ||
@@ -4228,27 +4439,35 @@ static int stv090x_setup(struct dvb_frontend *fe) | |||
4228 | goto err; | 4439 | goto err; |
4229 | } | 4440 | } |
4230 | 4441 | ||
4231 | } else if (state->dev_ver < 0x20) { | 4442 | } else if (state->internal->dev_ver < 0x20) { |
4232 | dprintk(FE_ERROR, 1, "ERROR: Unsupported Cut: 0x%02x!", | 4443 | dprintk(FE_ERROR, 1, "ERROR: Unsupported Cut: 0x%02x!", |
4233 | state->dev_ver); | 4444 | state->internal->dev_ver); |
4234 | 4445 | ||
4235 | goto err; | 4446 | goto err; |
4236 | } else if (state->dev_ver > 0x30) { | 4447 | } else if (state->internal->dev_ver > 0x30) { |
4237 | /* we shouldn't bail out from here */ | 4448 | /* we shouldn't bail out from here */ |
4238 | dprintk(FE_ERROR, 1, "INFO: Cut: 0x%02x probably incomplete support!", | 4449 | dprintk(FE_ERROR, 1, "INFO: Cut: 0x%02x probably incomplete support!", |
4239 | state->dev_ver); | 4450 | state->internal->dev_ver); |
4240 | } | 4451 | } |
4241 | 4452 | ||
4242 | if (stv090x_write_reg(state, STV090x_TSTRES0, 0x80) < 0) | 4453 | /* ADC1 range */ |
4454 | reg = stv090x_read_reg(state, STV090x_TSTTNR1); | ||
4455 | STV090x_SETFIELD(reg, ADC1_INMODE_FIELD, | ||
4456 | (config->adc1_range == STV090x_ADC_1Vpp) ? 0 : 1); | ||
4457 | if (stv090x_write_reg(state, STV090x_TSTTNR1, reg) < 0) | ||
4243 | goto err; | 4458 | goto err; |
4244 | if (stv090x_write_reg(state, STV090x_TSTRES0, 0x00) < 0) | 4459 | |
4460 | /* ADC2 range */ | ||
4461 | reg = stv090x_read_reg(state, STV090x_TSTTNR3); | ||
4462 | STV090x_SETFIELD(reg, ADC2_INMODE_FIELD, | ||
4463 | (config->adc2_range == STV090x_ADC_1Vpp) ? 0 : 1); | ||
4464 | if (stv090x_write_reg(state, STV090x_TSTTNR3, reg) < 0) | ||
4245 | goto err; | 4465 | goto err; |
4246 | 4466 | ||
4247 | stv090x_set_mclk(state, 135000000, config->xtal); /* 135 Mhz */ | 4467 | if (stv090x_write_reg(state, STV090x_TSTRES0, 0x80) < 0) |
4248 | msleep(5); | 4468 | goto err; |
4249 | if (stv090x_write_reg(state, STV090x_SYNTCTRL, 0x20 | config->clk_mode) < 0) | 4469 | if (stv090x_write_reg(state, STV090x_TSTRES0, 0x00) < 0) |
4250 | goto err; | 4470 | goto err; |
4251 | stv090x_get_mclk(state); | ||
4252 | 4471 | ||
4253 | return 0; | 4472 | return 0; |
4254 | err: | 4473 | err: |
@@ -4299,6 +4518,7 @@ struct dvb_frontend *stv090x_attach(const struct stv090x_config *config, | |||
4299 | enum stv090x_demodulator demod) | 4518 | enum stv090x_demodulator demod) |
4300 | { | 4519 | { |
4301 | struct stv090x_state *state = NULL; | 4520 | struct stv090x_state *state = NULL; |
4521 | struct stv090x_dev *temp_int; | ||
4302 | 4522 | ||
4303 | state = kzalloc(sizeof (struct stv090x_state), GFP_KERNEL); | 4523 | state = kzalloc(sizeof (struct stv090x_state), GFP_KERNEL); |
4304 | if (state == NULL) | 4524 | if (state == NULL) |
@@ -4314,8 +4534,32 @@ struct dvb_frontend *stv090x_attach(const struct stv090x_config *config, | |||
4314 | state->device = config->device; | 4534 | state->device = config->device; |
4315 | state->rolloff = STV090x_RO_35; /* default */ | 4535 | state->rolloff = STV090x_RO_35; /* default */ |
4316 | 4536 | ||
4317 | if (state->demod == STV090x_DEMODULATOR_0) | 4537 | temp_int = find_dev(state->i2c, |
4318 | mutex_init(&demod_lock); | 4538 | state->config->address); |
4539 | |||
4540 | if ((temp_int != NULL) && (state->demod_mode == STV090x_DUAL)) { | ||
4541 | state->internal = temp_int->internal; | ||
4542 | state->internal->num_used++; | ||
4543 | dprintk(FE_INFO, 1, "Found Internal Structure!"); | ||
4544 | dprintk(FE_ERROR, 1, "Attaching %s demodulator(%d) Cut=0x%02x", | ||
4545 | state->device == STV0900 ? "STV0900" : "STV0903", | ||
4546 | demod, | ||
4547 | state->internal->dev_ver); | ||
4548 | return &state->frontend; | ||
4549 | } else { | ||
4550 | state->internal = kmalloc(sizeof(struct stv090x_internal), | ||
4551 | GFP_KERNEL); | ||
4552 | temp_int = append_internal(state->internal); | ||
4553 | state->internal->num_used = 1; | ||
4554 | state->internal->mclk = 0; | ||
4555 | state->internal->dev_ver = 0; | ||
4556 | state->internal->i2c_adap = state->i2c; | ||
4557 | state->internal->i2c_addr = state->config->address; | ||
4558 | dprintk(FE_INFO, 1, "Create New Internal Structure!"); | ||
4559 | } | ||
4560 | |||
4561 | mutex_init(&state->internal->demod_lock); | ||
4562 | mutex_init(&state->internal->tuner_lock); | ||
4319 | 4563 | ||
4320 | if (stv090x_sleep(&state->frontend) < 0) { | 4564 | if (stv090x_sleep(&state->frontend) < 0) { |
4321 | dprintk(FE_ERROR, 1, "Error putting device to sleep"); | 4565 | dprintk(FE_ERROR, 1, "Error putting device to sleep"); |
@@ -4331,10 +4575,10 @@ struct dvb_frontend *stv090x_attach(const struct stv090x_config *config, | |||
4331 | goto error; | 4575 | goto error; |
4332 | } | 4576 | } |
4333 | 4577 | ||
4334 | dprintk(FE_ERROR, 1, "Attaching %s demodulator(%d) Cut=0x%02x\n", | 4578 | dprintk(FE_ERROR, 1, "Attaching %s demodulator(%d) Cut=0x%02x", |
4335 | state->device == STV0900 ? "STV0900" : "STV0903", | 4579 | state->device == STV0900 ? "STV0900" : "STV0903", |
4336 | demod, | 4580 | demod, |
4337 | state->dev_ver); | 4581 | state->internal->dev_ver); |
4338 | 4582 | ||
4339 | return &state->frontend; | 4583 | return &state->frontend; |
4340 | 4584 | ||
diff --git a/drivers/media/dvb/frontends/stv090x.h b/drivers/media/dvb/frontends/stv090x.h index b133807663ea..30f01a6902ac 100644 --- a/drivers/media/dvb/frontends/stv090x.h +++ b/drivers/media/dvb/frontends/stv090x.h | |||
@@ -60,6 +60,11 @@ enum stv090x_i2crpt { | |||
60 | STV090x_RPTLEVEL_2 = 7, | 60 | STV090x_RPTLEVEL_2 = 7, |
61 | }; | 61 | }; |
62 | 62 | ||
63 | enum stv090x_adc_range { | ||
64 | STV090x_ADC_2Vpp = 0, | ||
65 | STV090x_ADC_1Vpp = 1 | ||
66 | }; | ||
67 | |||
63 | struct stv090x_config { | 68 | struct stv090x_config { |
64 | enum stv090x_device device; | 69 | enum stv090x_device device; |
65 | enum stv090x_mode demod_mode; | 70 | enum stv090x_mode demod_mode; |
@@ -68,13 +73,17 @@ struct stv090x_config { | |||
68 | u32 xtal; /* default: 8000000 */ | 73 | u32 xtal; /* default: 8000000 */ |
69 | u8 address; /* default: 0x68 */ | 74 | u8 address; /* default: 0x68 */ |
70 | 75 | ||
71 | u32 ref_clk; /* default: 16000000 FIXME to tuner config */ | ||
72 | |||
73 | u8 ts1_mode; | 76 | u8 ts1_mode; |
74 | u8 ts2_mode; | 77 | u8 ts2_mode; |
78 | u32 ts1_clk; | ||
79 | u32 ts2_clk; | ||
75 | 80 | ||
76 | enum stv090x_i2crpt repeater_level; | 81 | enum stv090x_i2crpt repeater_level; |
77 | 82 | ||
83 | u8 tuner_bbgain; /* default: 10db */ | ||
84 | enum stv090x_adc_range adc1_range; /* default: 2Vpp */ | ||
85 | enum stv090x_adc_range adc2_range; /* default: 2Vpp */ | ||
86 | |||
78 | bool diseqc_envelope_mode; | 87 | bool diseqc_envelope_mode; |
79 | 88 | ||
80 | int (*tuner_init) (struct dvb_frontend *fe); | 89 | int (*tuner_init) (struct dvb_frontend *fe); |
diff --git a/drivers/media/dvb/frontends/stv090x_priv.h b/drivers/media/dvb/frontends/stv090x_priv.h index 5921a8d6c89f..5b780c80d496 100644 --- a/drivers/media/dvb/frontends/stv090x_priv.h +++ b/drivers/media/dvb/frontends/stv090x_priv.h | |||
@@ -230,11 +230,23 @@ struct stv090x_tab { | |||
230 | s32 read; | 230 | s32 read; |
231 | }; | 231 | }; |
232 | 232 | ||
233 | struct stv090x_internal { | ||
234 | struct i2c_adapter *i2c_adap; | ||
235 | u8 i2c_addr; | ||
236 | |||
237 | struct mutex demod_lock; /* Lock access to shared register */ | ||
238 | struct mutex tuner_lock; /* Lock access to tuners */ | ||
239 | s32 mclk; /* Masterclock Divider factor */ | ||
240 | u32 dev_ver; | ||
241 | |||
242 | int num_used; | ||
243 | }; | ||
244 | |||
233 | struct stv090x_state { | 245 | struct stv090x_state { |
234 | enum stv090x_device device; | 246 | enum stv090x_device device; |
235 | enum stv090x_demodulator demod; | 247 | enum stv090x_demodulator demod; |
236 | enum stv090x_mode demod_mode; | 248 | enum stv090x_mode demod_mode; |
237 | u32 dev_ver; | 249 | struct stv090x_internal *internal; |
238 | 250 | ||
239 | struct i2c_adapter *i2c; | 251 | struct i2c_adapter *i2c; |
240 | const struct stv090x_config *config; | 252 | const struct stv090x_config *config; |
@@ -256,11 +268,8 @@ struct stv090x_state { | |||
256 | u32 frequency; | 268 | u32 frequency; |
257 | u32 srate; | 269 | u32 srate; |
258 | 270 | ||
259 | s32 mclk; /* Masterclock Divider factor */ | ||
260 | s32 tuner_bw; | 271 | s32 tuner_bw; |
261 | 272 | ||
262 | u32 tuner_refclk; | ||
263 | |||
264 | s32 search_range; | 273 | s32 search_range; |
265 | 274 | ||
266 | s32 DemodTimeout; | 275 | s32 DemodTimeout; |
diff --git a/drivers/media/dvb/frontends/stv6110x.c b/drivers/media/dvb/frontends/stv6110x.c index bcfcb652464c..f931ed07e92d 100644 --- a/drivers/media/dvb/frontends/stv6110x.c +++ b/drivers/media/dvb/frontends/stv6110x.c | |||
@@ -35,8 +35,6 @@ static unsigned int verbose; | |||
35 | module_param(verbose, int, 0644); | 35 | module_param(verbose, int, 0644); |
36 | MODULE_PARM_DESC(verbose, "Set Verbosity level"); | 36 | MODULE_PARM_DESC(verbose, "Set Verbosity level"); |
37 | 37 | ||
38 | static u8 stv6110x_regs[] = {0x07, 0x11, 0xdc, 0x85, 0x17, 0x01, 0xe6, 0x1e}; | ||
39 | |||
40 | static int stv6110x_read_reg(struct stv6110x_state *stv6110x, u8 reg, u8 *data) | 38 | static int stv6110x_read_reg(struct stv6110x_state *stv6110x, u8 reg, u8 *data) |
41 | { | 39 | { |
42 | int ret; | 40 | int ret; |
@@ -58,12 +56,23 @@ static int stv6110x_read_reg(struct stv6110x_state *stv6110x, u8 reg, u8 *data) | |||
58 | return 0; | 56 | return 0; |
59 | } | 57 | } |
60 | 58 | ||
61 | static int stv6110x_write_reg(struct stv6110x_state *stv6110x, u8 reg, u8 data) | 59 | static int stv6110x_write_regs(struct stv6110x_state *stv6110x, int start, u8 data[], int len) |
62 | { | 60 | { |
63 | int ret; | 61 | int ret; |
64 | const struct stv6110x_config *config = stv6110x->config; | 62 | const struct stv6110x_config *config = stv6110x->config; |
65 | u8 buf[] = { reg, data }; | 63 | u8 buf[len + 1]; |
66 | struct i2c_msg msg = { .addr = config->addr, .flags = 0, . buf = buf, .len = 2 }; | 64 | struct i2c_msg msg = { |
65 | .addr = config->addr, | ||
66 | .flags = 0, | ||
67 | .buf = buf, | ||
68 | .len = len + 1 | ||
69 | }; | ||
70 | |||
71 | if (start + len > 8) | ||
72 | return -EINVAL; | ||
73 | |||
74 | buf[0] = start; | ||
75 | memcpy(&buf[1], data, len); | ||
67 | 76 | ||
68 | ret = i2c_transfer(stv6110x->i2c, &msg, 1); | 77 | ret = i2c_transfer(stv6110x->i2c, &msg, 1); |
69 | if (ret != 1) { | 78 | if (ret != 1) { |
@@ -74,18 +83,21 @@ static int stv6110x_write_reg(struct stv6110x_state *stv6110x, u8 reg, u8 data) | |||
74 | return 0; | 83 | return 0; |
75 | } | 84 | } |
76 | 85 | ||
86 | static int stv6110x_write_reg(struct stv6110x_state *stv6110x, u8 reg, u8 data) | ||
87 | { | ||
88 | return stv6110x_write_regs(stv6110x, reg, &data, 1); | ||
89 | } | ||
90 | |||
77 | static int stv6110x_init(struct dvb_frontend *fe) | 91 | static int stv6110x_init(struct dvb_frontend *fe) |
78 | { | 92 | { |
79 | struct stv6110x_state *stv6110x = fe->tuner_priv; | 93 | struct stv6110x_state *stv6110x = fe->tuner_priv; |
80 | int ret; | 94 | int ret; |
81 | u8 i; | ||
82 | 95 | ||
83 | for (i = 0; i < ARRAY_SIZE(stv6110x_regs); i++) { | 96 | ret = stv6110x_write_regs(stv6110x, 0, stv6110x->regs, |
84 | ret = stv6110x_write_reg(stv6110x, i, stv6110x_regs[i]); | 97 | ARRAY_SIZE(stv6110x->regs)); |
85 | if (ret < 0) { | 98 | if (ret < 0) { |
86 | dprintk(FE_ERROR, 1, "Initialization failed"); | 99 | dprintk(FE_ERROR, 1, "Initialization failed"); |
87 | return -1; | 100 | return -1; |
88 | } | ||
89 | } | 101 | } |
90 | 102 | ||
91 | return 0; | 103 | return 0; |
@@ -98,23 +110,23 @@ static int stv6110x_set_frequency(struct dvb_frontend *fe, u32 frequency) | |||
98 | s32 pVal, pCalc, rDivOpt = 0, pCalcOpt = 1000; | 110 | s32 pVal, pCalc, rDivOpt = 0, pCalcOpt = 1000; |
99 | u8 i; | 111 | u8 i; |
100 | 112 | ||
101 | STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_K, (REFCLOCK_MHz - 16)); | 113 | STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_K, (REFCLOCK_MHz - 16)); |
102 | 114 | ||
103 | if (frequency <= 1023000) { | 115 | if (frequency <= 1023000) { |
104 | STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_DIV4SEL, 1); | 116 | STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_DIV4SEL, 1); |
105 | STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_PRESC32_ON, 0); | 117 | STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_PRESC32_ON, 0); |
106 | pVal = 40; | 118 | pVal = 40; |
107 | } else if (frequency <= 1300000) { | 119 | } else if (frequency <= 1300000) { |
108 | STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_DIV4SEL, 1); | 120 | STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_DIV4SEL, 1); |
109 | STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_PRESC32_ON, 1); | 121 | STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_PRESC32_ON, 1); |
110 | pVal = 40; | 122 | pVal = 40; |
111 | } else if (frequency <= 2046000) { | 123 | } else if (frequency <= 2046000) { |
112 | STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_DIV4SEL, 0); | 124 | STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_DIV4SEL, 0); |
113 | STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_PRESC32_ON, 0); | 125 | STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_PRESC32_ON, 0); |
114 | pVal = 20; | 126 | pVal = 20; |
115 | } else { | 127 | } else { |
116 | STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_DIV4SEL, 0); | 128 | STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_DIV4SEL, 0); |
117 | STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_PRESC32_ON, 1); | 129 | STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_PRESC32_ON, 1); |
118 | pVal = 20; | 130 | pVal = 20; |
119 | } | 131 | } |
120 | 132 | ||
@@ -130,21 +142,21 @@ static int stv6110x_set_frequency(struct dvb_frontend *fe, u32 frequency) | |||
130 | divider = (frequency * R_DIV(rDivOpt) * pVal) / REFCLOCK_kHz; | 142 | divider = (frequency * R_DIV(rDivOpt) * pVal) / REFCLOCK_kHz; |
131 | divider = (divider + 5) / 10; | 143 | divider = (divider + 5) / 10; |
132 | 144 | ||
133 | STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_R_DIV, rDivOpt); | 145 | STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_R_DIV, rDivOpt); |
134 | STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_N_DIV_11_8, MSB(divider)); | 146 | STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_N_DIV_11_8, MSB(divider)); |
135 | STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG0], TNG0_N_DIV_7_0, LSB(divider)); | 147 | STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG0], TNG0_N_DIV_7_0, LSB(divider)); |
136 | 148 | ||
137 | /* VCO Auto calibration */ | 149 | /* VCO Auto calibration */ |
138 | STV6110x_SETFIELD(stv6110x_regs[STV6110x_STAT1], STAT1_CALVCO_STRT, 1); | 150 | STV6110x_SETFIELD(stv6110x->regs[STV6110x_STAT1], STAT1_CALVCO_STRT, 1); |
139 | 151 | ||
140 | stv6110x_write_reg(stv6110x, STV6110x_CTRL1, stv6110x_regs[STV6110x_CTRL1]); | 152 | stv6110x_write_reg(stv6110x, STV6110x_CTRL1, stv6110x->regs[STV6110x_CTRL1]); |
141 | stv6110x_write_reg(stv6110x, STV6110x_TNG1, stv6110x_regs[STV6110x_TNG1]); | 153 | stv6110x_write_reg(stv6110x, STV6110x_TNG1, stv6110x->regs[STV6110x_TNG1]); |
142 | stv6110x_write_reg(stv6110x, STV6110x_TNG0, stv6110x_regs[STV6110x_TNG0]); | 154 | stv6110x_write_reg(stv6110x, STV6110x_TNG0, stv6110x->regs[STV6110x_TNG0]); |
143 | stv6110x_write_reg(stv6110x, STV6110x_STAT1, stv6110x_regs[STV6110x_STAT1]); | 155 | stv6110x_write_reg(stv6110x, STV6110x_STAT1, stv6110x->regs[STV6110x_STAT1]); |
144 | 156 | ||
145 | for (i = 0; i < TRIALS; i++) { | 157 | for (i = 0; i < TRIALS; i++) { |
146 | stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x_regs[STV6110x_STAT1]); | 158 | stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x->regs[STV6110x_STAT1]); |
147 | if (!STV6110x_GETFIELD(STAT1_CALVCO_STRT, stv6110x_regs[STV6110x_STAT1])) | 159 | if (!STV6110x_GETFIELD(STAT1_CALVCO_STRT, stv6110x->regs[STV6110x_STAT1])) |
148 | break; | 160 | break; |
149 | msleep(1); | 161 | msleep(1); |
150 | } | 162 | } |
@@ -156,14 +168,14 @@ static int stv6110x_get_frequency(struct dvb_frontend *fe, u32 *frequency) | |||
156 | { | 168 | { |
157 | struct stv6110x_state *stv6110x = fe->tuner_priv; | 169 | struct stv6110x_state *stv6110x = fe->tuner_priv; |
158 | 170 | ||
159 | stv6110x_read_reg(stv6110x, STV6110x_TNG1, &stv6110x_regs[STV6110x_TNG1]); | 171 | stv6110x_read_reg(stv6110x, STV6110x_TNG1, &stv6110x->regs[STV6110x_TNG1]); |
160 | stv6110x_read_reg(stv6110x, STV6110x_TNG0, &stv6110x_regs[STV6110x_TNG0]); | 172 | stv6110x_read_reg(stv6110x, STV6110x_TNG0, &stv6110x->regs[STV6110x_TNG0]); |
161 | 173 | ||
162 | *frequency = (MAKEWORD16(STV6110x_GETFIELD(TNG1_N_DIV_11_8, stv6110x_regs[STV6110x_TNG1]), | 174 | *frequency = (MAKEWORD16(STV6110x_GETFIELD(TNG1_N_DIV_11_8, stv6110x->regs[STV6110x_TNG1]), |
163 | STV6110x_GETFIELD(TNG0_N_DIV_7_0, stv6110x_regs[STV6110x_TNG0]))) * REFCLOCK_kHz; | 175 | STV6110x_GETFIELD(TNG0_N_DIV_7_0, stv6110x->regs[STV6110x_TNG0]))) * REFCLOCK_kHz; |
164 | 176 | ||
165 | *frequency /= (1 << (STV6110x_GETFIELD(TNG1_R_DIV, stv6110x_regs[STV6110x_TNG1]) + | 177 | *frequency /= (1 << (STV6110x_GETFIELD(TNG1_R_DIV, stv6110x->regs[STV6110x_TNG1]) + |
166 | STV6110x_GETFIELD(TNG1_DIV4SEL, stv6110x_regs[STV6110x_TNG1]))); | 178 | STV6110x_GETFIELD(TNG1_DIV4SEL, stv6110x->regs[STV6110x_TNG1]))); |
167 | 179 | ||
168 | *frequency >>= 2; | 180 | *frequency >>= 2; |
169 | 181 | ||
@@ -179,27 +191,27 @@ static int stv6110x_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth) | |||
179 | halfbw = bandwidth >> 1; | 191 | halfbw = bandwidth >> 1; |
180 | 192 | ||
181 | if (halfbw > 36000000) | 193 | if (halfbw > 36000000) |
182 | STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_CF, 31); /* LPF */ | 194 | STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_CF, 31); /* LPF */ |
183 | else if (halfbw < 5000000) | 195 | else if (halfbw < 5000000) |
184 | STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_CF, 0); /* LPF */ | 196 | STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_CF, 0); /* LPF */ |
185 | else | 197 | else |
186 | STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_CF, ((halfbw / 1000000) - 5)); /* LPF */ | 198 | STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_CF, ((halfbw / 1000000) - 5)); /* LPF */ |
187 | 199 | ||
188 | 200 | ||
189 | STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_RCCLK_OFF, 0x0); /* cal. clk activated */ | 201 | STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_RCCLK_OFF, 0x0); /* cal. clk activated */ |
190 | STV6110x_SETFIELD(stv6110x_regs[STV6110x_STAT1], STAT1_CALRC_STRT, 0x1); /* LPF auto cal */ | 202 | STV6110x_SETFIELD(stv6110x->regs[STV6110x_STAT1], STAT1_CALRC_STRT, 0x1); /* LPF auto cal */ |
191 | 203 | ||
192 | stv6110x_write_reg(stv6110x, STV6110x_CTRL3, stv6110x_regs[STV6110x_CTRL3]); | 204 | stv6110x_write_reg(stv6110x, STV6110x_CTRL3, stv6110x->regs[STV6110x_CTRL3]); |
193 | stv6110x_write_reg(stv6110x, STV6110x_STAT1, stv6110x_regs[STV6110x_STAT1]); | 205 | stv6110x_write_reg(stv6110x, STV6110x_STAT1, stv6110x->regs[STV6110x_STAT1]); |
194 | 206 | ||
195 | for (i = 0; i < TRIALS; i++) { | 207 | for (i = 0; i < TRIALS; i++) { |
196 | stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x_regs[STV6110x_STAT1]); | 208 | stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x->regs[STV6110x_STAT1]); |
197 | if (!STV6110x_GETFIELD(STAT1_CALRC_STRT, stv6110x_regs[STV6110x_STAT1])) | 209 | if (!STV6110x_GETFIELD(STAT1_CALRC_STRT, stv6110x->regs[STV6110x_STAT1])) |
198 | break; | 210 | break; |
199 | msleep(1); | 211 | msleep(1); |
200 | } | 212 | } |
201 | STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_RCCLK_OFF, 0x1); /* cal. done */ | 213 | STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_RCCLK_OFF, 0x1); /* cal. done */ |
202 | stv6110x_write_reg(stv6110x, STV6110x_CTRL3, stv6110x_regs[STV6110x_CTRL3]); | 214 | stv6110x_write_reg(stv6110x, STV6110x_CTRL3, stv6110x->regs[STV6110x_CTRL3]); |
203 | 215 | ||
204 | return 0; | 216 | return 0; |
205 | } | 217 | } |
@@ -208,8 +220,8 @@ static int stv6110x_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) | |||
208 | { | 220 | { |
209 | struct stv6110x_state *stv6110x = fe->tuner_priv; | 221 | struct stv6110x_state *stv6110x = fe->tuner_priv; |
210 | 222 | ||
211 | stv6110x_read_reg(stv6110x, STV6110x_CTRL3, &stv6110x_regs[STV6110x_CTRL3]); | 223 | stv6110x_read_reg(stv6110x, STV6110x_CTRL3, &stv6110x->regs[STV6110x_CTRL3]); |
212 | *bandwidth = (STV6110x_GETFIELD(CTRL3_CF, stv6110x_regs[STV6110x_CTRL3]) + 5) * 2000000; | 224 | *bandwidth = (STV6110x_GETFIELD(CTRL3_CF, stv6110x->regs[STV6110x_CTRL3]) + 5) * 2000000; |
213 | 225 | ||
214 | return 0; | 226 | return 0; |
215 | } | 227 | } |
@@ -222,20 +234,20 @@ static int stv6110x_set_refclock(struct dvb_frontend *fe, u32 refclock) | |||
222 | switch (refclock) { | 234 | switch (refclock) { |
223 | default: | 235 | default: |
224 | case 1: | 236 | case 1: |
225 | STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_CO_DIV, 0); | 237 | STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 0); |
226 | break; | 238 | break; |
227 | case 2: | 239 | case 2: |
228 | STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_CO_DIV, 1); | 240 | STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 1); |
229 | break; | 241 | break; |
230 | case 4: | 242 | case 4: |
231 | STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_CO_DIV, 2); | 243 | STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 2); |
232 | break; | 244 | break; |
233 | case 8: | 245 | case 8: |
234 | case 0: | 246 | case 0: |
235 | STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_CO_DIV, 3); | 247 | STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 3); |
236 | break; | 248 | break; |
237 | } | 249 | } |
238 | stv6110x_write_reg(stv6110x, STV6110x_CTRL2, stv6110x_regs[STV6110x_CTRL2]); | 250 | stv6110x_write_reg(stv6110x, STV6110x_CTRL2, stv6110x->regs[STV6110x_CTRL2]); |
239 | 251 | ||
240 | return 0; | 252 | return 0; |
241 | } | 253 | } |
@@ -244,8 +256,8 @@ static int stv6110x_get_bbgain(struct dvb_frontend *fe, u32 *gain) | |||
244 | { | 256 | { |
245 | struct stv6110x_state *stv6110x = fe->tuner_priv; | 257 | struct stv6110x_state *stv6110x = fe->tuner_priv; |
246 | 258 | ||
247 | stv6110x_read_reg(stv6110x, STV6110x_CTRL2, &stv6110x_regs[STV6110x_CTRL2]); | 259 | stv6110x_read_reg(stv6110x, STV6110x_CTRL2, &stv6110x->regs[STV6110x_CTRL2]); |
248 | *gain = 2 * STV6110x_GETFIELD(CTRL2_BBGAIN, stv6110x_regs[STV6110x_CTRL2]); | 260 | *gain = 2 * STV6110x_GETFIELD(CTRL2_BBGAIN, stv6110x->regs[STV6110x_CTRL2]); |
249 | 261 | ||
250 | return 0; | 262 | return 0; |
251 | } | 263 | } |
@@ -254,8 +266,8 @@ static int stv6110x_set_bbgain(struct dvb_frontend *fe, u32 gain) | |||
254 | { | 266 | { |
255 | struct stv6110x_state *stv6110x = fe->tuner_priv; | 267 | struct stv6110x_state *stv6110x = fe->tuner_priv; |
256 | 268 | ||
257 | STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_BBGAIN, gain / 2); | 269 | STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_BBGAIN, gain / 2); |
258 | stv6110x_write_reg(stv6110x, STV6110x_CTRL2, stv6110x_regs[STV6110x_CTRL2]); | 270 | stv6110x_write_reg(stv6110x, STV6110x_CTRL2, stv6110x->regs[STV6110x_CTRL2]); |
259 | 271 | ||
260 | return 0; | 272 | return 0; |
261 | } | 273 | } |
@@ -267,19 +279,19 @@ static int stv6110x_set_mode(struct dvb_frontend *fe, enum tuner_mode mode) | |||
267 | 279 | ||
268 | switch (mode) { | 280 | switch (mode) { |
269 | case TUNER_SLEEP: | 281 | case TUNER_SLEEP: |
270 | STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_SYN, 0); | 282 | STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_SYN, 0); |
271 | STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_RX, 0); | 283 | STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_RX, 0); |
272 | STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_LPT, 0); | 284 | STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_LPT, 0); |
273 | break; | 285 | break; |
274 | 286 | ||
275 | case TUNER_WAKE: | 287 | case TUNER_WAKE: |
276 | STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_SYN, 1); | 288 | STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_SYN, 1); |
277 | STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_RX, 1); | 289 | STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_RX, 1); |
278 | STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_LPT, 1); | 290 | STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_LPT, 1); |
279 | break; | 291 | break; |
280 | } | 292 | } |
281 | 293 | ||
282 | ret = stv6110x_write_reg(stv6110x, STV6110x_CTRL1, stv6110x_regs[STV6110x_CTRL1]); | 294 | ret = stv6110x_write_reg(stv6110x, STV6110x_CTRL1, stv6110x->regs[STV6110x_CTRL1]); |
283 | if (ret < 0) { | 295 | if (ret < 0) { |
284 | dprintk(FE_ERROR, 1, "I/O Error"); | 296 | dprintk(FE_ERROR, 1, "I/O Error"); |
285 | return -EIO; | 297 | return -EIO; |
@@ -297,9 +309,9 @@ static int stv6110x_get_status(struct dvb_frontend *fe, u32 *status) | |||
297 | { | 309 | { |
298 | struct stv6110x_state *stv6110x = fe->tuner_priv; | 310 | struct stv6110x_state *stv6110x = fe->tuner_priv; |
299 | 311 | ||
300 | stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x_regs[STV6110x_STAT1]); | 312 | stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x->regs[STV6110x_STAT1]); |
301 | 313 | ||
302 | if (STV6110x_GETFIELD(STAT1_LOCK, stv6110x_regs[STV6110x_STAT1])) | 314 | if (STV6110x_GETFIELD(STAT1_LOCK, stv6110x->regs[STV6110x_STAT1])) |
303 | *status = TUNER_PHASELOCKED; | 315 | *status = TUNER_PHASELOCKED; |
304 | else | 316 | else |
305 | *status = 0; | 317 | *status = 0; |
@@ -349,6 +361,8 @@ struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe, | |||
349 | struct i2c_adapter *i2c) | 361 | struct i2c_adapter *i2c) |
350 | { | 362 | { |
351 | struct stv6110x_state *stv6110x; | 363 | struct stv6110x_state *stv6110x; |
364 | u8 default_regs[] = {0x07, 0x11, 0xdc, 0x85, 0x17, 0x01, 0xe6, 0x1e}; | ||
365 | int ret; | ||
352 | 366 | ||
353 | stv6110x = kzalloc(sizeof (struct stv6110x_state), GFP_KERNEL); | 367 | stv6110x = kzalloc(sizeof (struct stv6110x_state), GFP_KERNEL); |
354 | if (stv6110x == NULL) | 368 | if (stv6110x == NULL) |
@@ -357,6 +371,44 @@ struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe, | |||
357 | stv6110x->i2c = i2c; | 371 | stv6110x->i2c = i2c; |
358 | stv6110x->config = config; | 372 | stv6110x->config = config; |
359 | stv6110x->devctl = &stv6110x_ctl; | 373 | stv6110x->devctl = &stv6110x_ctl; |
374 | memcpy(stv6110x->regs, default_regs, 8); | ||
375 | |||
376 | /* setup divider */ | ||
377 | switch (stv6110x->config->clk_div) { | ||
378 | default: | ||
379 | case 1: | ||
380 | STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 0); | ||
381 | break; | ||
382 | case 2: | ||
383 | STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 1); | ||
384 | break; | ||
385 | case 4: | ||
386 | STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 2); | ||
387 | break; | ||
388 | case 8: | ||
389 | case 0: | ||
390 | STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 3); | ||
391 | break; | ||
392 | } | ||
393 | |||
394 | if (fe->ops.i2c_gate_ctrl) { | ||
395 | ret = fe->ops.i2c_gate_ctrl(fe, 1); | ||
396 | if (ret < 0) | ||
397 | goto error; | ||
398 | } | ||
399 | |||
400 | ret = stv6110x_write_regs(stv6110x, 0, stv6110x->regs, | ||
401 | ARRAY_SIZE(stv6110x->regs)); | ||
402 | if (ret < 0) { | ||
403 | dprintk(FE_ERROR, 1, "Initialization failed"); | ||
404 | goto error; | ||
405 | } | ||
406 | |||
407 | if (fe->ops.i2c_gate_ctrl) { | ||
408 | ret = fe->ops.i2c_gate_ctrl(fe, 0); | ||
409 | if (ret < 0) | ||
410 | goto error; | ||
411 | } | ||
360 | 412 | ||
361 | fe->tuner_priv = stv6110x; | 413 | fe->tuner_priv = stv6110x; |
362 | fe->ops.tuner_ops = stv6110x_ops; | 414 | fe->ops.tuner_ops = stv6110x_ops; |
diff --git a/drivers/media/dvb/frontends/stv6110x.h b/drivers/media/dvb/frontends/stv6110x.h index a38257080e01..2429ae6d7847 100644 --- a/drivers/media/dvb/frontends/stv6110x.h +++ b/drivers/media/dvb/frontends/stv6110x.h | |||
@@ -26,6 +26,7 @@ | |||
26 | struct stv6110x_config { | 26 | struct stv6110x_config { |
27 | u8 addr; | 27 | u8 addr; |
28 | u32 refclk; | 28 | u32 refclk; |
29 | u8 clk_div; /* divisor value for the output clock */ | ||
29 | }; | 30 | }; |
30 | 31 | ||
31 | enum tuner_mode { | 32 | enum tuner_mode { |
diff --git a/drivers/media/dvb/frontends/stv6110x_priv.h b/drivers/media/dvb/frontends/stv6110x_priv.h index 7260da633d49..0ec936a660a7 100644 --- a/drivers/media/dvb/frontends/stv6110x_priv.h +++ b/drivers/media/dvb/frontends/stv6110x_priv.h | |||
@@ -68,6 +68,7 @@ | |||
68 | struct stv6110x_state { | 68 | struct stv6110x_state { |
69 | struct i2c_adapter *i2c; | 69 | struct i2c_adapter *i2c; |
70 | const struct stv6110x_config *config; | 70 | const struct stv6110x_config *config; |
71 | u8 regs[8]; | ||
71 | 72 | ||
72 | struct stv6110x_devctl *devctl; | 73 | struct stv6110x_devctl *devctl; |
73 | }; | 74 | }; |
diff --git a/drivers/media/dvb/frontends/tda665x.c b/drivers/media/dvb/frontends/tda665x.c index 87d52739c828..c44fefe92d97 100644 --- a/drivers/media/dvb/frontends/tda665x.c +++ b/drivers/media/dvb/frontends/tda665x.c | |||
@@ -133,7 +133,7 @@ static int tda665x_set_state(struct dvb_frontend *fe, | |||
133 | frequency += config->ref_divider >> 1; | 133 | frequency += config->ref_divider >> 1; |
134 | frequency /= config->ref_divider; | 134 | frequency /= config->ref_divider; |
135 | 135 | ||
136 | buf[0] = (u8) (frequency & 0x7f00) >> 8; | 136 | buf[0] = (u8) ((frequency & 0x7f00) >> 8); |
137 | buf[1] = (u8) (frequency & 0x00ff) >> 0; | 137 | buf[1] = (u8) (frequency & 0x00ff) >> 0; |
138 | buf[2] = 0x80 | 0x40 | 0x02; | 138 | buf[2] = 0x80 | 0x40 | 0x02; |
139 | buf[3] = 0x00; | 139 | buf[3] = 0x00; |
diff --git a/drivers/media/dvb/frontends/tda8261.c b/drivers/media/dvb/frontends/tda8261.c index 320c3c36d8b2..614afcec05f1 100644 --- a/drivers/media/dvb/frontends/tda8261.c +++ b/drivers/media/dvb/frontends/tda8261.c | |||
@@ -39,7 +39,7 @@ static int tda8261_read(struct tda8261_state *state, u8 *buf) | |||
39 | { | 39 | { |
40 | const struct tda8261_config *config = state->config; | 40 | const struct tda8261_config *config = state->config; |
41 | int err = 0; | 41 | int err = 0; |
42 | struct i2c_msg msg = { .addr = config->addr, .flags = I2C_M_RD,.buf = buf, .len = 2 }; | 42 | struct i2c_msg msg = { .addr = config->addr, .flags = I2C_M_RD,.buf = buf, .len = 1 }; |
43 | 43 | ||
44 | if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) | 44 | if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) |
45 | printk("%s: read error, err=%d\n", __func__, err); | 45 | printk("%s: read error, err=%d\n", __func__, err); |
diff --git a/drivers/media/dvb/frontends/zl10036.c b/drivers/media/dvb/frontends/zl10036.c index 4e814ff22b23..34c5de491d2b 100644 --- a/drivers/media/dvb/frontends/zl10036.c +++ b/drivers/media/dvb/frontends/zl10036.c | |||
@@ -411,7 +411,7 @@ static int zl10036_init_regs(struct zl10036_state *state) | |||
411 | state->bf = 0xff; | 411 | state->bf = 0xff; |
412 | 412 | ||
413 | if (!state->config->rf_loop_enable) | 413 | if (!state->config->rf_loop_enable) |
414 | zl10036_init_tab[1][2] |= 0x01; | 414 | zl10036_init_tab[1][0] |= 0x01; |
415 | 415 | ||
416 | deb_info("%s\n", __func__); | 416 | deb_info("%s\n", __func__); |
417 | 417 | ||
diff --git a/drivers/media/dvb/frontends/zl10039.c b/drivers/media/dvb/frontends/zl10039.c index 11b29cb883e6..c085e58a94bf 100644 --- a/drivers/media/dvb/frontends/zl10039.c +++ b/drivers/media/dvb/frontends/zl10039.c | |||
@@ -287,7 +287,6 @@ struct dvb_frontend *zl10039_attach(struct dvb_frontend *fe, | |||
287 | break; | 287 | break; |
288 | default: | 288 | default: |
289 | dprintk("Chip ID=%x does not match a known type\n", state->id); | 289 | dprintk("Chip ID=%x does not match a known type\n", state->id); |
290 | break; | ||
291 | goto error; | 290 | goto error; |
292 | } | 291 | } |
293 | 292 | ||
diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index 7477dac628b4..5772ebb3a69e 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c | |||
@@ -22,8 +22,6 @@ | |||
22 | #include <linux/signal.h> | 22 | #include <linux/signal.h> |
23 | #include <linux/sched.h> | 23 | #include <linux/sched.h> |
24 | 24 | ||
25 | #include <linux/signal.h> | ||
26 | #include <linux/sched.h> | ||
27 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
28 | 26 | ||
29 | #include "dmxdev.h" | 27 | #include "dmxdev.h" |
diff --git a/drivers/media/dvb/mantis/mantis_input.c b/drivers/media/dvb/mantis/mantis_input.c index 6a9df779441f..4675a3b53c7d 100644 --- a/drivers/media/dvb/mantis/mantis_input.c +++ b/drivers/media/dvb/mantis/mantis_input.c | |||
@@ -126,7 +126,7 @@ int mantis_input_init(struct mantis_pci *mantis) | |||
126 | rc->id.version = 1; | 126 | rc->id.version = 1; |
127 | rc->dev = mantis->pdev->dev; | 127 | rc->dev = mantis->pdev->dev; |
128 | 128 | ||
129 | err = ir_input_register(rc, &ir_mantis); | 129 | err = ir_input_register(rc, &ir_mantis, NULL); |
130 | if (err) { | 130 | if (err) { |
131 | dprintk(MANTIS_ERROR, 1, "IR device registration failed, ret = %d", err); | 131 | dprintk(MANTIS_ERROR, 1, "IR device registration failed, ret = %d", err); |
132 | input_free_device(rc); | 132 | input_free_device(rc); |
diff --git a/drivers/media/dvb/mantis/mantis_pci.c b/drivers/media/dvb/mantis/mantis_pci.c index 6c7534af6b44..59feeb84aec7 100644 --- a/drivers/media/dvb/mantis/mantis_pci.c +++ b/drivers/media/dvb/mantis/mantis_pci.c | |||
@@ -41,11 +41,6 @@ | |||
41 | #include "dvb_frontend.h" | 41 | #include "dvb_frontend.h" |
42 | #include "dvb_net.h" | 42 | #include "dvb_net.h" |
43 | 43 | ||
44 | #include <asm/irq.h> | ||
45 | #include <linux/signal.h> | ||
46 | #include <linux/sched.h> | ||
47 | #include <linux/interrupt.h> | ||
48 | |||
49 | #include "mantis_common.h" | 44 | #include "mantis_common.h" |
50 | #include "mantis_reg.h" | 45 | #include "mantis_reg.h" |
51 | #include "mantis_pci.h" | 46 | #include "mantis_pci.h" |
diff --git a/drivers/media/dvb/ngene/Kconfig b/drivers/media/dvb/ngene/Kconfig new file mode 100644 index 000000000000..3ec8e6fcbb1d --- /dev/null +++ b/drivers/media/dvb/ngene/Kconfig | |||
@@ -0,0 +1,9 @@ | |||
1 | config DVB_NGENE | ||
2 | tristate "Micronas nGene support" | ||
3 | depends on DVB_CORE && PCI && I2C | ||
4 | select DVB_LNBP21 if !DVB_FE_CUSTOMISE | ||
5 | select DVB_STV6110x if !DVB_FE_CUSTOMISE | ||
6 | select DVB_STV090x if !DVB_FE_CUSTOMISE | ||
7 | ---help--- | ||
8 | Support for Micronas PCI express cards with nGene bridge. | ||
9 | |||
diff --git a/drivers/media/dvb/ngene/Makefile b/drivers/media/dvb/ngene/Makefile new file mode 100644 index 000000000000..40435cad4819 --- /dev/null +++ b/drivers/media/dvb/ngene/Makefile | |||
@@ -0,0 +1,11 @@ | |||
1 | # | ||
2 | # Makefile for the nGene device driver | ||
3 | # | ||
4 | |||
5 | ngene-objs := ngene-core.o | ||
6 | |||
7 | obj-$(CONFIG_DVB_NGENE) += ngene.o | ||
8 | |||
9 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ | ||
10 | EXTRA_CFLAGS += -Idrivers/media/dvb/frontends/ | ||
11 | |||
diff --git a/drivers/media/dvb/ngene/ngene-core.c b/drivers/media/dvb/ngene/ngene-core.c new file mode 100644 index 000000000000..0150dfe7cfbb --- /dev/null +++ b/drivers/media/dvb/ngene/ngene-core.c | |||
@@ -0,0 +1,2024 @@ | |||
1 | /* | ||
2 | * ngene.c: nGene PCIe bridge driver | ||
3 | * | ||
4 | * Copyright (C) 2005-2007 Micronas | ||
5 | * | ||
6 | * Copyright (C) 2008-2009 Ralph Metzler <rjkm@metzlerbros.de> | ||
7 | * Modifications for new nGene firmware, | ||
8 | * support for EEPROM-copying, | ||
9 | * support for new dual DVB-S2 card prototype | ||
10 | * | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * version 2 only, as published by the Free Software Foundation. | ||
15 | * | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
26 | * 02110-1301, USA | ||
27 | * Or, point your browser to http://www.gnu.org/copyleft/gpl.html | ||
28 | */ | ||
29 | |||
30 | #include <linux/module.h> | ||
31 | #include <linux/init.h> | ||
32 | #include <linux/delay.h> | ||
33 | #include <linux/slab.h> | ||
34 | #include <linux/poll.h> | ||
35 | #include <linux/io.h> | ||
36 | #include <asm/div64.h> | ||
37 | #include <linux/pci.h> | ||
38 | #include <linux/pci_ids.h> | ||
39 | #include <linux/smp_lock.h> | ||
40 | #include <linux/timer.h> | ||
41 | #include <linux/version.h> | ||
42 | #include <linux/byteorder/generic.h> | ||
43 | #include <linux/firmware.h> | ||
44 | #include <linux/vmalloc.h> | ||
45 | |||
46 | #include "ngene.h" | ||
47 | |||
48 | #include "stv6110x.h" | ||
49 | #include "stv090x.h" | ||
50 | #include "lnbh24.h" | ||
51 | |||
52 | static int one_adapter = 1; | ||
53 | module_param(one_adapter, int, 0444); | ||
54 | MODULE_PARM_DESC(one_adapter, "Use only one adapter."); | ||
55 | |||
56 | |||
57 | static int debug; | ||
58 | module_param(debug, int, 0444); | ||
59 | MODULE_PARM_DESC(debug, "Print debugging information."); | ||
60 | |||
61 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
62 | |||
63 | #define COMMAND_TIMEOUT_WORKAROUND | ||
64 | |||
65 | #define dprintk if (debug) printk | ||
66 | |||
67 | #define DEVICE_NAME "ngene" | ||
68 | |||
69 | #define ngwriteb(dat, adr) writeb((dat), (char *)(dev->iomem + (adr))) | ||
70 | #define ngwritel(dat, adr) writel((dat), (char *)(dev->iomem + (adr))) | ||
71 | #define ngwriteb(dat, adr) writeb((dat), (char *)(dev->iomem + (adr))) | ||
72 | #define ngreadl(adr) readl(dev->iomem + (adr)) | ||
73 | #define ngreadb(adr) readb(dev->iomem + (adr)) | ||
74 | #define ngcpyto(adr, src, count) memcpy_toio((char *) \ | ||
75 | (dev->iomem + (adr)), (src), (count)) | ||
76 | #define ngcpyfrom(dst, adr, count) memcpy_fromio((dst), (char *) \ | ||
77 | (dev->iomem + (adr)), (count)) | ||
78 | |||
79 | /****************************************************************************/ | ||
80 | /* nGene interrupt handler **************************************************/ | ||
81 | /****************************************************************************/ | ||
82 | |||
83 | static void event_tasklet(unsigned long data) | ||
84 | { | ||
85 | struct ngene *dev = (struct ngene *)data; | ||
86 | |||
87 | while (dev->EventQueueReadIndex != dev->EventQueueWriteIndex) { | ||
88 | struct EVENT_BUFFER Event = | ||
89 | dev->EventQueue[dev->EventQueueReadIndex]; | ||
90 | dev->EventQueueReadIndex = | ||
91 | (dev->EventQueueReadIndex + 1) & (EVENT_QUEUE_SIZE - 1); | ||
92 | |||
93 | if ((Event.UARTStatus & 0x01) && (dev->TxEventNotify)) | ||
94 | dev->TxEventNotify(dev, Event.TimeStamp); | ||
95 | if ((Event.UARTStatus & 0x02) && (dev->RxEventNotify)) | ||
96 | dev->RxEventNotify(dev, Event.TimeStamp, | ||
97 | Event.RXCharacter); | ||
98 | } | ||
99 | } | ||
100 | |||
101 | static void demux_tasklet(unsigned long data) | ||
102 | { | ||
103 | struct ngene_channel *chan = (struct ngene_channel *)data; | ||
104 | struct SBufferHeader *Cur = chan->nextBuffer; | ||
105 | |||
106 | spin_lock_irq(&chan->state_lock); | ||
107 | |||
108 | while (Cur->ngeneBuffer.SR.Flags & 0x80) { | ||
109 | if (chan->mode & NGENE_IO_TSOUT) { | ||
110 | u32 Flags = chan->DataFormatFlags; | ||
111 | if (Cur->ngeneBuffer.SR.Flags & 0x20) | ||
112 | Flags |= BEF_OVERFLOW; | ||
113 | if (chan->pBufferExchange) { | ||
114 | if (!chan->pBufferExchange(chan, | ||
115 | Cur->Buffer1, | ||
116 | chan->Capture1Length, | ||
117 | Cur->ngeneBuffer.SR. | ||
118 | Clock, Flags)) { | ||
119 | /* | ||
120 | We didn't get data | ||
121 | Clear in service flag to make sure we | ||
122 | get called on next interrupt again. | ||
123 | leave fill/empty (0x80) flag alone | ||
124 | to avoid hardware running out of | ||
125 | buffers during startup, we hold only | ||
126 | in run state ( the source may be late | ||
127 | delivering data ) | ||
128 | */ | ||
129 | |||
130 | if (chan->HWState == HWSTATE_RUN) { | ||
131 | Cur->ngeneBuffer.SR.Flags &= | ||
132 | ~0x40; | ||
133 | break; | ||
134 | /* Stop proccessing stream */ | ||
135 | } | ||
136 | } else { | ||
137 | /* We got a valid buffer, | ||
138 | so switch to run state */ | ||
139 | chan->HWState = HWSTATE_RUN; | ||
140 | } | ||
141 | } else { | ||
142 | printk(KERN_ERR DEVICE_NAME ": OOPS\n"); | ||
143 | if (chan->HWState == HWSTATE_RUN) { | ||
144 | Cur->ngeneBuffer.SR.Flags &= ~0x40; | ||
145 | break; /* Stop proccessing stream */ | ||
146 | } | ||
147 | } | ||
148 | if (chan->AudioDTOUpdated) { | ||
149 | printk(KERN_INFO DEVICE_NAME | ||
150 | ": Update AudioDTO = %d\n", | ||
151 | chan->AudioDTOValue); | ||
152 | Cur->ngeneBuffer.SR.DTOUpdate = | ||
153 | chan->AudioDTOValue; | ||
154 | chan->AudioDTOUpdated = 0; | ||
155 | } | ||
156 | } else { | ||
157 | if (chan->HWState == HWSTATE_RUN) { | ||
158 | u32 Flags = 0; | ||
159 | if (Cur->ngeneBuffer.SR.Flags & 0x01) | ||
160 | Flags |= BEF_EVEN_FIELD; | ||
161 | if (Cur->ngeneBuffer.SR.Flags & 0x20) | ||
162 | Flags |= BEF_OVERFLOW; | ||
163 | if (chan->pBufferExchange) | ||
164 | chan->pBufferExchange(chan, | ||
165 | Cur->Buffer1, | ||
166 | chan-> | ||
167 | Capture1Length, | ||
168 | Cur->ngeneBuffer. | ||
169 | SR.Clock, Flags); | ||
170 | if (chan->pBufferExchange2) | ||
171 | chan->pBufferExchange2(chan, | ||
172 | Cur->Buffer2, | ||
173 | chan-> | ||
174 | Capture2Length, | ||
175 | Cur->ngeneBuffer. | ||
176 | SR.Clock, Flags); | ||
177 | } else if (chan->HWState != HWSTATE_STOP) | ||
178 | chan->HWState = HWSTATE_RUN; | ||
179 | } | ||
180 | Cur->ngeneBuffer.SR.Flags = 0x00; | ||
181 | Cur = Cur->Next; | ||
182 | } | ||
183 | chan->nextBuffer = Cur; | ||
184 | |||
185 | spin_unlock_irq(&chan->state_lock); | ||
186 | } | ||
187 | |||
188 | static irqreturn_t irq_handler(int irq, void *dev_id) | ||
189 | { | ||
190 | struct ngene *dev = (struct ngene *)dev_id; | ||
191 | u32 icounts = 0; | ||
192 | irqreturn_t rc = IRQ_NONE; | ||
193 | u32 i = MAX_STREAM; | ||
194 | u8 *tmpCmdDoneByte; | ||
195 | |||
196 | if (dev->BootFirmware) { | ||
197 | icounts = ngreadl(NGENE_INT_COUNTS); | ||
198 | if (icounts != dev->icounts) { | ||
199 | ngwritel(0, FORCE_NMI); | ||
200 | dev->cmd_done = 1; | ||
201 | wake_up(&dev->cmd_wq); | ||
202 | dev->icounts = icounts; | ||
203 | rc = IRQ_HANDLED; | ||
204 | } | ||
205 | return rc; | ||
206 | } | ||
207 | |||
208 | ngwritel(0, FORCE_NMI); | ||
209 | |||
210 | spin_lock(&dev->cmd_lock); | ||
211 | tmpCmdDoneByte = dev->CmdDoneByte; | ||
212 | if (tmpCmdDoneByte && | ||
213 | (*tmpCmdDoneByte || | ||
214 | (dev->ngenetohost[0] == 1 && dev->ngenetohost[1] != 0))) { | ||
215 | dev->CmdDoneByte = NULL; | ||
216 | dev->cmd_done = 1; | ||
217 | wake_up(&dev->cmd_wq); | ||
218 | rc = IRQ_HANDLED; | ||
219 | } | ||
220 | spin_unlock(&dev->cmd_lock); | ||
221 | |||
222 | if (dev->EventBuffer->EventStatus & 0x80) { | ||
223 | u8 nextWriteIndex = | ||
224 | (dev->EventQueueWriteIndex + 1) & | ||
225 | (EVENT_QUEUE_SIZE - 1); | ||
226 | if (nextWriteIndex != dev->EventQueueReadIndex) { | ||
227 | dev->EventQueue[dev->EventQueueWriteIndex] = | ||
228 | *(dev->EventBuffer); | ||
229 | dev->EventQueueWriteIndex = nextWriteIndex; | ||
230 | } else { | ||
231 | printk(KERN_ERR DEVICE_NAME ": event overflow\n"); | ||
232 | dev->EventQueueOverflowCount += 1; | ||
233 | dev->EventQueueOverflowFlag = 1; | ||
234 | } | ||
235 | dev->EventBuffer->EventStatus &= ~0x80; | ||
236 | tasklet_schedule(&dev->event_tasklet); | ||
237 | rc = IRQ_HANDLED; | ||
238 | } | ||
239 | |||
240 | while (i > 0) { | ||
241 | i--; | ||
242 | spin_lock(&dev->channel[i].state_lock); | ||
243 | /* if (dev->channel[i].State>=KSSTATE_RUN) { */ | ||
244 | if (dev->channel[i].nextBuffer) { | ||
245 | if ((dev->channel[i].nextBuffer-> | ||
246 | ngeneBuffer.SR.Flags & 0xC0) == 0x80) { | ||
247 | dev->channel[i].nextBuffer-> | ||
248 | ngeneBuffer.SR.Flags |= 0x40; | ||
249 | tasklet_schedule( | ||
250 | &dev->channel[i].demux_tasklet); | ||
251 | rc = IRQ_HANDLED; | ||
252 | } | ||
253 | } | ||
254 | spin_unlock(&dev->channel[i].state_lock); | ||
255 | } | ||
256 | |||
257 | /* Request might have been processed by a previous call. */ | ||
258 | return IRQ_HANDLED; | ||
259 | } | ||
260 | |||
261 | /****************************************************************************/ | ||
262 | /* nGene command interface **************************************************/ | ||
263 | /****************************************************************************/ | ||
264 | |||
265 | static void dump_command_io(struct ngene *dev) | ||
266 | { | ||
267 | u8 buf[8], *b; | ||
268 | |||
269 | ngcpyfrom(buf, HOST_TO_NGENE, 8); | ||
270 | printk(KERN_ERR "host_to_ngene (%04x): %02x %02x %02x %02x %02x %02x %02x %02x\n", | ||
271 | HOST_TO_NGENE, buf[0], buf[1], buf[2], buf[3], | ||
272 | buf[4], buf[5], buf[6], buf[7]); | ||
273 | |||
274 | ngcpyfrom(buf, NGENE_TO_HOST, 8); | ||
275 | printk(KERN_ERR "ngene_to_host (%04x): %02x %02x %02x %02x %02x %02x %02x %02x\n", | ||
276 | NGENE_TO_HOST, buf[0], buf[1], buf[2], buf[3], | ||
277 | buf[4], buf[5], buf[6], buf[7]); | ||
278 | |||
279 | b = dev->hosttongene; | ||
280 | printk(KERN_ERR "dev->hosttongene (%p): %02x %02x %02x %02x %02x %02x %02x %02x\n", | ||
281 | b, b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]); | ||
282 | |||
283 | b = dev->ngenetohost; | ||
284 | printk(KERN_ERR "dev->ngenetohost (%p): %02x %02x %02x %02x %02x %02x %02x %02x\n", | ||
285 | b, b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]); | ||
286 | } | ||
287 | |||
288 | static int ngene_command_mutex(struct ngene *dev, struct ngene_command *com) | ||
289 | { | ||
290 | int ret; | ||
291 | u8 *tmpCmdDoneByte; | ||
292 | |||
293 | dev->cmd_done = 0; | ||
294 | |||
295 | if (com->cmd.hdr.Opcode == CMD_FWLOAD_PREPARE) { | ||
296 | dev->BootFirmware = 1; | ||
297 | dev->icounts = ngreadl(NGENE_INT_COUNTS); | ||
298 | ngwritel(0, NGENE_COMMAND); | ||
299 | ngwritel(0, NGENE_COMMAND_HI); | ||
300 | ngwritel(0, NGENE_STATUS); | ||
301 | ngwritel(0, NGENE_STATUS_HI); | ||
302 | ngwritel(0, NGENE_EVENT); | ||
303 | ngwritel(0, NGENE_EVENT_HI); | ||
304 | } else if (com->cmd.hdr.Opcode == CMD_FWLOAD_FINISH) { | ||
305 | u64 fwio = dev->PAFWInterfaceBuffer; | ||
306 | |||
307 | ngwritel(fwio & 0xffffffff, NGENE_COMMAND); | ||
308 | ngwritel(fwio >> 32, NGENE_COMMAND_HI); | ||
309 | ngwritel((fwio + 256) & 0xffffffff, NGENE_STATUS); | ||
310 | ngwritel((fwio + 256) >> 32, NGENE_STATUS_HI); | ||
311 | ngwritel((fwio + 512) & 0xffffffff, NGENE_EVENT); | ||
312 | ngwritel((fwio + 512) >> 32, NGENE_EVENT_HI); | ||
313 | } | ||
314 | |||
315 | memcpy(dev->FWInterfaceBuffer, com->cmd.raw8, com->in_len + 2); | ||
316 | |||
317 | if (dev->BootFirmware) | ||
318 | ngcpyto(HOST_TO_NGENE, com->cmd.raw8, com->in_len + 2); | ||
319 | |||
320 | spin_lock_irq(&dev->cmd_lock); | ||
321 | tmpCmdDoneByte = dev->ngenetohost + com->out_len; | ||
322 | if (!com->out_len) | ||
323 | tmpCmdDoneByte++; | ||
324 | *tmpCmdDoneByte = 0; | ||
325 | dev->ngenetohost[0] = 0; | ||
326 | dev->ngenetohost[1] = 0; | ||
327 | dev->CmdDoneByte = tmpCmdDoneByte; | ||
328 | spin_unlock_irq(&dev->cmd_lock); | ||
329 | |||
330 | /* Notify 8051. */ | ||
331 | ngwritel(1, FORCE_INT); | ||
332 | |||
333 | ret = wait_event_timeout(dev->cmd_wq, dev->cmd_done == 1, 2 * HZ); | ||
334 | if (!ret) { | ||
335 | /*ngwritel(0, FORCE_NMI);*/ | ||
336 | |||
337 | printk(KERN_ERR DEVICE_NAME | ||
338 | ": Command timeout cmd=%02x prev=%02x\n", | ||
339 | com->cmd.hdr.Opcode, dev->prev_cmd); | ||
340 | dump_command_io(dev); | ||
341 | return -1; | ||
342 | } | ||
343 | if (com->cmd.hdr.Opcode == CMD_FWLOAD_FINISH) | ||
344 | dev->BootFirmware = 0; | ||
345 | |||
346 | dev->prev_cmd = com->cmd.hdr.Opcode; | ||
347 | |||
348 | if (!com->out_len) | ||
349 | return 0; | ||
350 | |||
351 | memcpy(com->cmd.raw8, dev->ngenetohost, com->out_len); | ||
352 | |||
353 | return 0; | ||
354 | } | ||
355 | |||
356 | static int ngene_command(struct ngene *dev, struct ngene_command *com) | ||
357 | { | ||
358 | int result; | ||
359 | |||
360 | down(&dev->cmd_mutex); | ||
361 | result = ngene_command_mutex(dev, com); | ||
362 | up(&dev->cmd_mutex); | ||
363 | return result; | ||
364 | } | ||
365 | |||
366 | |||
367 | static int ngene_command_i2c_read(struct ngene *dev, u8 adr, | ||
368 | u8 *out, u8 outlen, u8 *in, u8 inlen, int flag) | ||
369 | { | ||
370 | struct ngene_command com; | ||
371 | |||
372 | com.cmd.hdr.Opcode = CMD_I2C_READ; | ||
373 | com.cmd.hdr.Length = outlen + 3; | ||
374 | com.cmd.I2CRead.Device = adr << 1; | ||
375 | memcpy(com.cmd.I2CRead.Data, out, outlen); | ||
376 | com.cmd.I2CRead.Data[outlen] = inlen; | ||
377 | com.cmd.I2CRead.Data[outlen + 1] = 0; | ||
378 | com.in_len = outlen + 3; | ||
379 | com.out_len = inlen + 1; | ||
380 | |||
381 | if (ngene_command(dev, &com) < 0) | ||
382 | return -EIO; | ||
383 | |||
384 | if ((com.cmd.raw8[0] >> 1) != adr) | ||
385 | return -EIO; | ||
386 | |||
387 | if (flag) | ||
388 | memcpy(in, com.cmd.raw8, inlen + 1); | ||
389 | else | ||
390 | memcpy(in, com.cmd.raw8 + 1, inlen); | ||
391 | return 0; | ||
392 | } | ||
393 | |||
394 | static int ngene_command_i2c_write(struct ngene *dev, u8 adr, | ||
395 | u8 *out, u8 outlen) | ||
396 | { | ||
397 | struct ngene_command com; | ||
398 | |||
399 | |||
400 | com.cmd.hdr.Opcode = CMD_I2C_WRITE; | ||
401 | com.cmd.hdr.Length = outlen + 1; | ||
402 | com.cmd.I2CRead.Device = adr << 1; | ||
403 | memcpy(com.cmd.I2CRead.Data, out, outlen); | ||
404 | com.in_len = outlen + 1; | ||
405 | com.out_len = 1; | ||
406 | |||
407 | if (ngene_command(dev, &com) < 0) | ||
408 | return -EIO; | ||
409 | |||
410 | if (com.cmd.raw8[0] == 1) | ||
411 | return -EIO; | ||
412 | |||
413 | return 0; | ||
414 | } | ||
415 | |||
416 | static int ngene_command_load_firmware(struct ngene *dev, | ||
417 | u8 *ngene_fw, u32 size) | ||
418 | { | ||
419 | #define FIRSTCHUNK (1024) | ||
420 | u32 cleft; | ||
421 | struct ngene_command com; | ||
422 | |||
423 | com.cmd.hdr.Opcode = CMD_FWLOAD_PREPARE; | ||
424 | com.cmd.hdr.Length = 0; | ||
425 | com.in_len = 0; | ||
426 | com.out_len = 0; | ||
427 | |||
428 | ngene_command(dev, &com); | ||
429 | |||
430 | cleft = (size + 3) & ~3; | ||
431 | if (cleft > FIRSTCHUNK) { | ||
432 | ngcpyto(PROGRAM_SRAM + FIRSTCHUNK, ngene_fw + FIRSTCHUNK, | ||
433 | cleft - FIRSTCHUNK); | ||
434 | cleft = FIRSTCHUNK; | ||
435 | } | ||
436 | ngcpyto(DATA_FIFO_AREA, ngene_fw, cleft); | ||
437 | |||
438 | memset(&com, 0, sizeof(struct ngene_command)); | ||
439 | com.cmd.hdr.Opcode = CMD_FWLOAD_FINISH; | ||
440 | com.cmd.hdr.Length = 4; | ||
441 | com.cmd.FWLoadFinish.Address = DATA_FIFO_AREA; | ||
442 | com.cmd.FWLoadFinish.Length = (unsigned short)cleft; | ||
443 | com.in_len = 4; | ||
444 | com.out_len = 0; | ||
445 | |||
446 | return ngene_command(dev, &com); | ||
447 | } | ||
448 | |||
449 | |||
450 | static int ngene_command_config_buf(struct ngene *dev, u8 config) | ||
451 | { | ||
452 | struct ngene_command com; | ||
453 | |||
454 | com.cmd.hdr.Opcode = CMD_CONFIGURE_BUFFER; | ||
455 | com.cmd.hdr.Length = 1; | ||
456 | com.cmd.ConfigureBuffers.config = config; | ||
457 | com.in_len = 1; | ||
458 | com.out_len = 0; | ||
459 | |||
460 | if (ngene_command(dev, &com) < 0) | ||
461 | return -EIO; | ||
462 | return 0; | ||
463 | } | ||
464 | |||
465 | static int ngene_command_config_free_buf(struct ngene *dev, u8 *config) | ||
466 | { | ||
467 | struct ngene_command com; | ||
468 | |||
469 | com.cmd.hdr.Opcode = CMD_CONFIGURE_FREE_BUFFER; | ||
470 | com.cmd.hdr.Length = 6; | ||
471 | memcpy(&com.cmd.ConfigureBuffers.config, config, 6); | ||
472 | com.in_len = 6; | ||
473 | com.out_len = 0; | ||
474 | |||
475 | if (ngene_command(dev, &com) < 0) | ||
476 | return -EIO; | ||
477 | |||
478 | return 0; | ||
479 | } | ||
480 | |||
481 | static int ngene_command_gpio_set(struct ngene *dev, u8 select, u8 level) | ||
482 | { | ||
483 | struct ngene_command com; | ||
484 | |||
485 | com.cmd.hdr.Opcode = CMD_SET_GPIO_PIN; | ||
486 | com.cmd.hdr.Length = 1; | ||
487 | com.cmd.SetGpioPin.select = select | (level << 7); | ||
488 | com.in_len = 1; | ||
489 | com.out_len = 0; | ||
490 | |||
491 | return ngene_command(dev, &com); | ||
492 | } | ||
493 | |||
494 | |||
495 | /* | ||
496 | 02000640 is sample on rising edge. | ||
497 | 02000740 is sample on falling edge. | ||
498 | 02000040 is ignore "valid" signal | ||
499 | |||
500 | 0: FD_CTL1 Bit 7,6 must be 0,1 | ||
501 | 7 disable(fw controlled) | ||
502 | 6 0-AUX,1-TS | ||
503 | 5 0-par,1-ser | ||
504 | 4 0-lsb/1-msb | ||
505 | 3,2 reserved | ||
506 | 1,0 0-no sync, 1-use ext. start, 2-use 0x47, 3-both | ||
507 | 1: FD_CTL2 has 3-valid must be hi, 2-use valid, 1-edge | ||
508 | 2: FD_STA is read-only. 0-sync | ||
509 | 3: FD_INSYNC is number of 47s to trigger "in sync". | ||
510 | 4: FD_OUTSYNC is number of 47s to trigger "out of sync". | ||
511 | 5: FD_MAXBYTE1 is low-order of bytes per packet. | ||
512 | 6: FD_MAXBYTE2 is high-order of bytes per packet. | ||
513 | 7: Top byte is unused. | ||
514 | */ | ||
515 | |||
516 | /****************************************************************************/ | ||
517 | |||
518 | static u8 TSFeatureDecoderSetup[8 * 4] = { | ||
519 | 0x42, 0x00, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, | ||
520 | 0x40, 0x06, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* DRXH */ | ||
521 | 0x71, 0x07, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* DRXHser */ | ||
522 | 0x72, 0x06, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* S2ser */ | ||
523 | }; | ||
524 | |||
525 | /* Set NGENE I2S Config to 16 bit packed */ | ||
526 | static u8 I2SConfiguration[] = { | ||
527 | 0x00, 0x10, 0x00, 0x00, | ||
528 | 0x80, 0x10, 0x00, 0x00, | ||
529 | }; | ||
530 | |||
531 | static u8 SPDIFConfiguration[10] = { | ||
532 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | ||
533 | }; | ||
534 | |||
535 | /* Set NGENE I2S Config to transport stream compatible mode */ | ||
536 | |||
537 | static u8 TS_I2SConfiguration[4] = { 0x3E, 0x1A, 0x00, 0x00 }; /*3e 18 00 00 ?*/ | ||
538 | |||
539 | static u8 TS_I2SOutConfiguration[4] = { 0x80, 0x20, 0x00, 0x00 }; | ||
540 | |||
541 | static u8 ITUDecoderSetup[4][16] = { | ||
542 | {0x1c, 0x13, 0x01, 0x68, 0x3d, 0x90, 0x14, 0x20, /* SDTV */ | ||
543 | 0x00, 0x00, 0x01, 0xb0, 0x9c, 0x00, 0x00, 0x00}, | ||
544 | {0x9c, 0x03, 0x23, 0xC0, 0x60, 0x0E, 0x13, 0x00, | ||
545 | 0x00, 0x00, 0x00, 0x01, 0xB0, 0x00, 0x00, 0x00}, | ||
546 | {0x9f, 0x00, 0x23, 0xC0, 0x60, 0x0F, 0x13, 0x00, /* HDTV 1080i50 */ | ||
547 | 0x00, 0x00, 0x00, 0x01, 0xB0, 0x00, 0x00, 0x00}, | ||
548 | {0x9c, 0x01, 0x23, 0xC0, 0x60, 0x0E, 0x13, 0x00, /* HDTV 1080i60 */ | ||
549 | 0x00, 0x00, 0x00, 0x01, 0xB0, 0x00, 0x00, 0x00}, | ||
550 | }; | ||
551 | |||
552 | /* | ||
553 | * 50 48 60 gleich | ||
554 | * 27p50 9f 00 22 80 42 69 18 ... | ||
555 | * 27p60 93 00 22 80 82 69 1c ... | ||
556 | */ | ||
557 | |||
558 | /* Maxbyte to 1144 (for raw data) */ | ||
559 | static u8 ITUFeatureDecoderSetup[8] = { | ||
560 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x04, 0x00 | ||
561 | }; | ||
562 | |||
563 | static void FillTSBuffer(void *Buffer, int Length, u32 Flags) | ||
564 | { | ||
565 | u32 *ptr = Buffer; | ||
566 | |||
567 | memset(Buffer, 0xff, Length); | ||
568 | while (Length > 0) { | ||
569 | if (Flags & DF_SWAP32) | ||
570 | *ptr = 0x471FFF10; | ||
571 | else | ||
572 | *ptr = 0x10FF1F47; | ||
573 | ptr += (188 / 4); | ||
574 | Length -= 188; | ||
575 | } | ||
576 | } | ||
577 | |||
578 | |||
579 | static void flush_buffers(struct ngene_channel *chan) | ||
580 | { | ||
581 | u8 val; | ||
582 | |||
583 | do { | ||
584 | msleep(1); | ||
585 | spin_lock_irq(&chan->state_lock); | ||
586 | val = chan->nextBuffer->ngeneBuffer.SR.Flags & 0x80; | ||
587 | spin_unlock_irq(&chan->state_lock); | ||
588 | } while (val); | ||
589 | } | ||
590 | |||
591 | static void clear_buffers(struct ngene_channel *chan) | ||
592 | { | ||
593 | struct SBufferHeader *Cur = chan->nextBuffer; | ||
594 | |||
595 | do { | ||
596 | memset(&Cur->ngeneBuffer.SR, 0, sizeof(Cur->ngeneBuffer.SR)); | ||
597 | if (chan->mode & NGENE_IO_TSOUT) | ||
598 | FillTSBuffer(Cur->Buffer1, | ||
599 | chan->Capture1Length, | ||
600 | chan->DataFormatFlags); | ||
601 | Cur = Cur->Next; | ||
602 | } while (Cur != chan->nextBuffer); | ||
603 | |||
604 | if (chan->mode & NGENE_IO_TSOUT) { | ||
605 | chan->nextBuffer->ngeneBuffer.SR.DTOUpdate = | ||
606 | chan->AudioDTOValue; | ||
607 | chan->AudioDTOUpdated = 0; | ||
608 | |||
609 | Cur = chan->TSIdleBuffer.Head; | ||
610 | |||
611 | do { | ||
612 | memset(&Cur->ngeneBuffer.SR, 0, | ||
613 | sizeof(Cur->ngeneBuffer.SR)); | ||
614 | FillTSBuffer(Cur->Buffer1, | ||
615 | chan->Capture1Length, | ||
616 | chan->DataFormatFlags); | ||
617 | Cur = Cur->Next; | ||
618 | } while (Cur != chan->TSIdleBuffer.Head); | ||
619 | } | ||
620 | } | ||
621 | |||
622 | static int ngene_command_stream_control(struct ngene *dev, u8 stream, | ||
623 | u8 control, u8 mode, u8 flags) | ||
624 | { | ||
625 | struct ngene_channel *chan = &dev->channel[stream]; | ||
626 | struct ngene_command com; | ||
627 | u16 BsUVI = ((stream & 1) ? 0x9400 : 0x9300); | ||
628 | u16 BsSDI = ((stream & 1) ? 0x9600 : 0x9500); | ||
629 | u16 BsSPI = ((stream & 1) ? 0x9800 : 0x9700); | ||
630 | u16 BsSDO = 0x9B00; | ||
631 | |||
632 | /* down(&dev->stream_mutex); */ | ||
633 | while (down_trylock(&dev->stream_mutex)) { | ||
634 | printk(KERN_INFO DEVICE_NAME ": SC locked\n"); | ||
635 | msleep(1); | ||
636 | } | ||
637 | memset(&com, 0, sizeof(com)); | ||
638 | com.cmd.hdr.Opcode = CMD_CONTROL; | ||
639 | com.cmd.hdr.Length = sizeof(struct FW_STREAM_CONTROL) - 2; | ||
640 | com.cmd.StreamControl.Stream = stream | (control ? 8 : 0); | ||
641 | if (chan->mode & NGENE_IO_TSOUT) | ||
642 | com.cmd.StreamControl.Stream |= 0x07; | ||
643 | com.cmd.StreamControl.Control = control | | ||
644 | (flags & SFLAG_ORDER_LUMA_CHROMA); | ||
645 | com.cmd.StreamControl.Mode = mode; | ||
646 | com.in_len = sizeof(struct FW_STREAM_CONTROL); | ||
647 | com.out_len = 0; | ||
648 | |||
649 | dprintk(KERN_INFO DEVICE_NAME | ||
650 | ": Stream=%02x, Control=%02x, Mode=%02x\n", | ||
651 | com.cmd.StreamControl.Stream, com.cmd.StreamControl.Control, | ||
652 | com.cmd.StreamControl.Mode); | ||
653 | |||
654 | chan->Mode = mode; | ||
655 | |||
656 | if (!(control & 0x80)) { | ||
657 | spin_lock_irq(&chan->state_lock); | ||
658 | if (chan->State == KSSTATE_RUN) { | ||
659 | chan->State = KSSTATE_ACQUIRE; | ||
660 | chan->HWState = HWSTATE_STOP; | ||
661 | spin_unlock_irq(&chan->state_lock); | ||
662 | if (ngene_command(dev, &com) < 0) { | ||
663 | up(&dev->stream_mutex); | ||
664 | return -1; | ||
665 | } | ||
666 | /* clear_buffers(chan); */ | ||
667 | flush_buffers(chan); | ||
668 | up(&dev->stream_mutex); | ||
669 | return 0; | ||
670 | } | ||
671 | spin_unlock_irq(&chan->state_lock); | ||
672 | up(&dev->stream_mutex); | ||
673 | return 0; | ||
674 | } | ||
675 | |||
676 | if (mode & SMODE_AUDIO_CAPTURE) { | ||
677 | com.cmd.StreamControl.CaptureBlockCount = | ||
678 | chan->Capture1Length / AUDIO_BLOCK_SIZE; | ||
679 | com.cmd.StreamControl.Buffer_Address = chan->RingBuffer.PAHead; | ||
680 | } else if (mode & SMODE_TRANSPORT_STREAM) { | ||
681 | com.cmd.StreamControl.CaptureBlockCount = | ||
682 | chan->Capture1Length / TS_BLOCK_SIZE; | ||
683 | com.cmd.StreamControl.MaxLinesPerField = | ||
684 | chan->Capture1Length / TS_BLOCK_SIZE; | ||
685 | com.cmd.StreamControl.Buffer_Address = | ||
686 | chan->TSRingBuffer.PAHead; | ||
687 | if (chan->mode & NGENE_IO_TSOUT) { | ||
688 | com.cmd.StreamControl.BytesPerVBILine = | ||
689 | chan->Capture1Length / TS_BLOCK_SIZE; | ||
690 | com.cmd.StreamControl.Stream |= 0x07; | ||
691 | } | ||
692 | } else { | ||
693 | com.cmd.StreamControl.BytesPerVideoLine = chan->nBytesPerLine; | ||
694 | com.cmd.StreamControl.MaxLinesPerField = chan->nLines; | ||
695 | com.cmd.StreamControl.MinLinesPerField = 100; | ||
696 | com.cmd.StreamControl.Buffer_Address = chan->RingBuffer.PAHead; | ||
697 | |||
698 | if (mode & SMODE_VBI_CAPTURE) { | ||
699 | com.cmd.StreamControl.MaxVBILinesPerField = | ||
700 | chan->nVBILines; | ||
701 | com.cmd.StreamControl.MinVBILinesPerField = 0; | ||
702 | com.cmd.StreamControl.BytesPerVBILine = | ||
703 | chan->nBytesPerVBILine; | ||
704 | } | ||
705 | if (flags & SFLAG_COLORBAR) | ||
706 | com.cmd.StreamControl.Stream |= 0x04; | ||
707 | } | ||
708 | |||
709 | spin_lock_irq(&chan->state_lock); | ||
710 | if (mode & SMODE_AUDIO_CAPTURE) { | ||
711 | chan->nextBuffer = chan->RingBuffer.Head; | ||
712 | if (mode & SMODE_AUDIO_SPDIF) { | ||
713 | com.cmd.StreamControl.SetupDataLen = | ||
714 | sizeof(SPDIFConfiguration); | ||
715 | com.cmd.StreamControl.SetupDataAddr = BsSPI; | ||
716 | memcpy(com.cmd.StreamControl.SetupData, | ||
717 | SPDIFConfiguration, sizeof(SPDIFConfiguration)); | ||
718 | } else { | ||
719 | com.cmd.StreamControl.SetupDataLen = 4; | ||
720 | com.cmd.StreamControl.SetupDataAddr = BsSDI; | ||
721 | memcpy(com.cmd.StreamControl.SetupData, | ||
722 | I2SConfiguration + | ||
723 | 4 * dev->card_info->i2s[stream], 4); | ||
724 | } | ||
725 | } else if (mode & SMODE_TRANSPORT_STREAM) { | ||
726 | chan->nextBuffer = chan->TSRingBuffer.Head; | ||
727 | if (stream >= STREAM_AUDIOIN1) { | ||
728 | if (chan->mode & NGENE_IO_TSOUT) { | ||
729 | com.cmd.StreamControl.SetupDataLen = | ||
730 | sizeof(TS_I2SOutConfiguration); | ||
731 | com.cmd.StreamControl.SetupDataAddr = BsSDO; | ||
732 | memcpy(com.cmd.StreamControl.SetupData, | ||
733 | TS_I2SOutConfiguration, | ||
734 | sizeof(TS_I2SOutConfiguration)); | ||
735 | } else { | ||
736 | com.cmd.StreamControl.SetupDataLen = | ||
737 | sizeof(TS_I2SConfiguration); | ||
738 | com.cmd.StreamControl.SetupDataAddr = BsSDI; | ||
739 | memcpy(com.cmd.StreamControl.SetupData, | ||
740 | TS_I2SConfiguration, | ||
741 | sizeof(TS_I2SConfiguration)); | ||
742 | } | ||
743 | } else { | ||
744 | com.cmd.StreamControl.SetupDataLen = 8; | ||
745 | com.cmd.StreamControl.SetupDataAddr = BsUVI + 0x10; | ||
746 | memcpy(com.cmd.StreamControl.SetupData, | ||
747 | TSFeatureDecoderSetup + | ||
748 | 8 * dev->card_info->tsf[stream], 8); | ||
749 | } | ||
750 | } else { | ||
751 | chan->nextBuffer = chan->RingBuffer.Head; | ||
752 | com.cmd.StreamControl.SetupDataLen = | ||
753 | 16 + sizeof(ITUFeatureDecoderSetup); | ||
754 | com.cmd.StreamControl.SetupDataAddr = BsUVI; | ||
755 | memcpy(com.cmd.StreamControl.SetupData, | ||
756 | ITUDecoderSetup[chan->itumode], 16); | ||
757 | memcpy(com.cmd.StreamControl.SetupData + 16, | ||
758 | ITUFeatureDecoderSetup, sizeof(ITUFeatureDecoderSetup)); | ||
759 | } | ||
760 | clear_buffers(chan); | ||
761 | chan->State = KSSTATE_RUN; | ||
762 | if (mode & SMODE_TRANSPORT_STREAM) | ||
763 | chan->HWState = HWSTATE_RUN; | ||
764 | else | ||
765 | chan->HWState = HWSTATE_STARTUP; | ||
766 | spin_unlock_irq(&chan->state_lock); | ||
767 | |||
768 | if (ngene_command(dev, &com) < 0) { | ||
769 | up(&dev->stream_mutex); | ||
770 | return -1; | ||
771 | } | ||
772 | up(&dev->stream_mutex); | ||
773 | return 0; | ||
774 | } | ||
775 | |||
776 | |||
777 | /****************************************************************************/ | ||
778 | /* I2C **********************************************************************/ | ||
779 | /****************************************************************************/ | ||
780 | |||
781 | static void ngene_i2c_set_bus(struct ngene *dev, int bus) | ||
782 | { | ||
783 | if (!(dev->card_info->i2c_access & 2)) | ||
784 | return; | ||
785 | if (dev->i2c_current_bus == bus) | ||
786 | return; | ||
787 | |||
788 | switch (bus) { | ||
789 | case 0: | ||
790 | ngene_command_gpio_set(dev, 3, 0); | ||
791 | ngene_command_gpio_set(dev, 2, 1); | ||
792 | break; | ||
793 | |||
794 | case 1: | ||
795 | ngene_command_gpio_set(dev, 2, 0); | ||
796 | ngene_command_gpio_set(dev, 3, 1); | ||
797 | break; | ||
798 | } | ||
799 | dev->i2c_current_bus = bus; | ||
800 | } | ||
801 | |||
802 | static int ngene_i2c_master_xfer(struct i2c_adapter *adapter, | ||
803 | struct i2c_msg msg[], int num) | ||
804 | { | ||
805 | struct ngene_channel *chan = | ||
806 | (struct ngene_channel *)i2c_get_adapdata(adapter); | ||
807 | struct ngene *dev = chan->dev; | ||
808 | |||
809 | down(&dev->i2c_switch_mutex); | ||
810 | ngene_i2c_set_bus(dev, chan->number); | ||
811 | |||
812 | if (num == 2 && msg[1].flags & I2C_M_RD && !(msg[0].flags & I2C_M_RD)) | ||
813 | if (!ngene_command_i2c_read(dev, msg[0].addr, | ||
814 | msg[0].buf, msg[0].len, | ||
815 | msg[1].buf, msg[1].len, 0)) | ||
816 | goto done; | ||
817 | |||
818 | if (num == 1 && !(msg[0].flags & I2C_M_RD)) | ||
819 | if (!ngene_command_i2c_write(dev, msg[0].addr, | ||
820 | msg[0].buf, msg[0].len)) | ||
821 | goto done; | ||
822 | if (num == 1 && (msg[0].flags & I2C_M_RD)) | ||
823 | if (!ngene_command_i2c_read(dev, msg[0].addr, 0, 0, | ||
824 | msg[0].buf, msg[0].len, 0)) | ||
825 | goto done; | ||
826 | |||
827 | up(&dev->i2c_switch_mutex); | ||
828 | return -EIO; | ||
829 | |||
830 | done: | ||
831 | up(&dev->i2c_switch_mutex); | ||
832 | return num; | ||
833 | } | ||
834 | |||
835 | |||
836 | static u32 ngene_i2c_functionality(struct i2c_adapter *adap) | ||
837 | { | ||
838 | return I2C_FUNC_SMBUS_EMUL; | ||
839 | } | ||
840 | |||
841 | static struct i2c_algorithm ngene_i2c_algo = { | ||
842 | .master_xfer = ngene_i2c_master_xfer, | ||
843 | .functionality = ngene_i2c_functionality, | ||
844 | }; | ||
845 | |||
846 | static int ngene_i2c_init(struct ngene *dev, int dev_nr) | ||
847 | { | ||
848 | struct i2c_adapter *adap = &(dev->channel[dev_nr].i2c_adapter); | ||
849 | |||
850 | i2c_set_adapdata(adap, &(dev->channel[dev_nr])); | ||
851 | adap->class = I2C_CLASS_TV_DIGITAL | I2C_CLASS_TV_ANALOG; | ||
852 | |||
853 | strcpy(adap->name, "nGene"); | ||
854 | |||
855 | adap->algo = &ngene_i2c_algo; | ||
856 | adap->algo_data = (void *)&(dev->channel[dev_nr]); | ||
857 | adap->dev.parent = &dev->pci_dev->dev; | ||
858 | |||
859 | return i2c_add_adapter(adap); | ||
860 | } | ||
861 | |||
862 | |||
863 | /****************************************************************************/ | ||
864 | /* DVB functions and API interface ******************************************/ | ||
865 | /****************************************************************************/ | ||
866 | |||
867 | static void swap_buffer(u32 *p, u32 len) | ||
868 | { | ||
869 | while (len) { | ||
870 | *p = swab32(*p); | ||
871 | p++; | ||
872 | len -= 4; | ||
873 | } | ||
874 | } | ||
875 | |||
876 | |||
877 | static void *tsin_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) | ||
878 | { | ||
879 | struct ngene_channel *chan = priv; | ||
880 | |||
881 | |||
882 | #ifdef COMMAND_TIMEOUT_WORKAROUND | ||
883 | if (chan->users > 0) | ||
884 | #endif | ||
885 | dvb_dmx_swfilter(&chan->demux, buf, len); | ||
886 | return 0; | ||
887 | } | ||
888 | |||
889 | u8 fill_ts[188] = { 0x47, 0x1f, 0xff, 0x10 }; | ||
890 | |||
891 | static void *tsout_exchange(void *priv, void *buf, u32 len, | ||
892 | u32 clock, u32 flags) | ||
893 | { | ||
894 | struct ngene_channel *chan = priv; | ||
895 | struct ngene *dev = chan->dev; | ||
896 | u32 alen; | ||
897 | |||
898 | alen = dvb_ringbuffer_avail(&dev->tsout_rbuf); | ||
899 | alen -= alen % 188; | ||
900 | |||
901 | if (alen < len) | ||
902 | FillTSBuffer(buf + alen, len - alen, flags); | ||
903 | else | ||
904 | alen = len; | ||
905 | dvb_ringbuffer_read(&dev->tsout_rbuf, buf, alen); | ||
906 | if (flags & DF_SWAP32) | ||
907 | swap_buffer((u32 *)buf, alen); | ||
908 | wake_up_interruptible(&dev->tsout_rbuf.queue); | ||
909 | return buf; | ||
910 | } | ||
911 | |||
912 | |||
913 | static void set_transfer(struct ngene_channel *chan, int state) | ||
914 | { | ||
915 | u8 control = 0, mode = 0, flags = 0; | ||
916 | struct ngene *dev = chan->dev; | ||
917 | int ret; | ||
918 | |||
919 | /* | ||
920 | printk(KERN_INFO DEVICE_NAME ": st %d\n", state); | ||
921 | msleep(100); | ||
922 | */ | ||
923 | |||
924 | if (state) { | ||
925 | if (chan->running) { | ||
926 | printk(KERN_INFO DEVICE_NAME ": already running\n"); | ||
927 | return; | ||
928 | } | ||
929 | } else { | ||
930 | if (!chan->running) { | ||
931 | printk(KERN_INFO DEVICE_NAME ": already stopped\n"); | ||
932 | return; | ||
933 | } | ||
934 | } | ||
935 | |||
936 | if (dev->card_info->switch_ctrl) | ||
937 | dev->card_info->switch_ctrl(chan, 1, state ^ 1); | ||
938 | |||
939 | if (state) { | ||
940 | spin_lock_irq(&chan->state_lock); | ||
941 | |||
942 | /* printk(KERN_INFO DEVICE_NAME ": lock=%08x\n", | ||
943 | ngreadl(0x9310)); */ | ||
944 | dvb_ringbuffer_flush(&dev->tsout_rbuf); | ||
945 | control = 0x80; | ||
946 | if (chan->mode & (NGENE_IO_TSIN | NGENE_IO_TSOUT)) { | ||
947 | chan->Capture1Length = 512 * 188; | ||
948 | mode = SMODE_TRANSPORT_STREAM; | ||
949 | } | ||
950 | if (chan->mode & NGENE_IO_TSOUT) { | ||
951 | chan->pBufferExchange = tsout_exchange; | ||
952 | /* 0x66666666 = 50MHz *2^33 /250MHz */ | ||
953 | chan->AudioDTOValue = 0x66666666; | ||
954 | /* set_dto(chan, 38810700+1000); */ | ||
955 | /* set_dto(chan, 19392658); */ | ||
956 | } | ||
957 | if (chan->mode & NGENE_IO_TSIN) | ||
958 | chan->pBufferExchange = tsin_exchange; | ||
959 | /* ngwritel(0, 0x9310); */ | ||
960 | spin_unlock_irq(&chan->state_lock); | ||
961 | } else | ||
962 | ;/* printk(KERN_INFO DEVICE_NAME ": lock=%08x\n", | ||
963 | ngreadl(0x9310)); */ | ||
964 | |||
965 | ret = ngene_command_stream_control(dev, chan->number, | ||
966 | control, mode, flags); | ||
967 | if (!ret) | ||
968 | chan->running = state; | ||
969 | else | ||
970 | printk(KERN_ERR DEVICE_NAME ": set_transfer %d failed\n", | ||
971 | state); | ||
972 | if (!state) { | ||
973 | spin_lock_irq(&chan->state_lock); | ||
974 | chan->pBufferExchange = 0; | ||
975 | dvb_ringbuffer_flush(&dev->tsout_rbuf); | ||
976 | spin_unlock_irq(&chan->state_lock); | ||
977 | } | ||
978 | } | ||
979 | |||
980 | static int ngene_start_feed(struct dvb_demux_feed *dvbdmxfeed) | ||
981 | { | ||
982 | struct dvb_demux *dvbdmx = dvbdmxfeed->demux; | ||
983 | struct ngene_channel *chan = dvbdmx->priv; | ||
984 | |||
985 | if (chan->users == 0) { | ||
986 | #ifdef COMMAND_TIMEOUT_WORKAROUND | ||
987 | if (!chan->running) | ||
988 | #endif | ||
989 | set_transfer(chan, 1); | ||
990 | /* msleep(10); */ | ||
991 | } | ||
992 | |||
993 | return ++chan->users; | ||
994 | } | ||
995 | |||
996 | static int ngene_stop_feed(struct dvb_demux_feed *dvbdmxfeed) | ||
997 | { | ||
998 | struct dvb_demux *dvbdmx = dvbdmxfeed->demux; | ||
999 | struct ngene_channel *chan = dvbdmx->priv; | ||
1000 | |||
1001 | if (--chan->users) | ||
1002 | return chan->users; | ||
1003 | |||
1004 | #ifndef COMMAND_TIMEOUT_WORKAROUND | ||
1005 | set_transfer(chan, 0); | ||
1006 | #endif | ||
1007 | |||
1008 | return 0; | ||
1009 | } | ||
1010 | |||
1011 | |||
1012 | |||
1013 | static int my_dvb_dmx_ts_card_init(struct dvb_demux *dvbdemux, char *id, | ||
1014 | int (*start_feed)(struct dvb_demux_feed *), | ||
1015 | int (*stop_feed)(struct dvb_demux_feed *), | ||
1016 | void *priv) | ||
1017 | { | ||
1018 | dvbdemux->priv = priv; | ||
1019 | |||
1020 | dvbdemux->filternum = 256; | ||
1021 | dvbdemux->feednum = 256; | ||
1022 | dvbdemux->start_feed = start_feed; | ||
1023 | dvbdemux->stop_feed = stop_feed; | ||
1024 | dvbdemux->write_to_decoder = 0; | ||
1025 | dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | | ||
1026 | DMX_SECTION_FILTERING | | ||
1027 | DMX_MEMORY_BASED_FILTERING); | ||
1028 | return dvb_dmx_init(dvbdemux); | ||
1029 | } | ||
1030 | |||
1031 | static int my_dvb_dmxdev_ts_card_init(struct dmxdev *dmxdev, | ||
1032 | struct dvb_demux *dvbdemux, | ||
1033 | struct dmx_frontend *hw_frontend, | ||
1034 | struct dmx_frontend *mem_frontend, | ||
1035 | struct dvb_adapter *dvb_adapter) | ||
1036 | { | ||
1037 | int ret; | ||
1038 | |||
1039 | dmxdev->filternum = 256; | ||
1040 | dmxdev->demux = &dvbdemux->dmx; | ||
1041 | dmxdev->capabilities = 0; | ||
1042 | ret = dvb_dmxdev_init(dmxdev, dvb_adapter); | ||
1043 | if (ret < 0) | ||
1044 | return ret; | ||
1045 | |||
1046 | hw_frontend->source = DMX_FRONTEND_0; | ||
1047 | dvbdemux->dmx.add_frontend(&dvbdemux->dmx, hw_frontend); | ||
1048 | mem_frontend->source = DMX_MEMORY_FE; | ||
1049 | dvbdemux->dmx.add_frontend(&dvbdemux->dmx, mem_frontend); | ||
1050 | return dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, hw_frontend); | ||
1051 | } | ||
1052 | |||
1053 | |||
1054 | /****************************************************************************/ | ||
1055 | /* nGene hardware init and release functions ********************************/ | ||
1056 | /****************************************************************************/ | ||
1057 | |||
1058 | static void free_ringbuffer(struct ngene *dev, struct SRingBufferDescriptor *rb) | ||
1059 | { | ||
1060 | struct SBufferHeader *Cur = rb->Head; | ||
1061 | u32 j; | ||
1062 | |||
1063 | if (!Cur) | ||
1064 | return; | ||
1065 | |||
1066 | for (j = 0; j < rb->NumBuffers; j++, Cur = Cur->Next) { | ||
1067 | if (Cur->Buffer1) | ||
1068 | pci_free_consistent(dev->pci_dev, | ||
1069 | rb->Buffer1Length, | ||
1070 | Cur->Buffer1, | ||
1071 | Cur->scList1->Address); | ||
1072 | |||
1073 | if (Cur->Buffer2) | ||
1074 | pci_free_consistent(dev->pci_dev, | ||
1075 | rb->Buffer2Length, | ||
1076 | Cur->Buffer2, | ||
1077 | Cur->scList2->Address); | ||
1078 | } | ||
1079 | |||
1080 | if (rb->SCListMem) | ||
1081 | pci_free_consistent(dev->pci_dev, rb->SCListMemSize, | ||
1082 | rb->SCListMem, rb->PASCListMem); | ||
1083 | |||
1084 | pci_free_consistent(dev->pci_dev, rb->MemSize, rb->Head, rb->PAHead); | ||
1085 | } | ||
1086 | |||
1087 | static void free_idlebuffer(struct ngene *dev, | ||
1088 | struct SRingBufferDescriptor *rb, | ||
1089 | struct SRingBufferDescriptor *tb) | ||
1090 | { | ||
1091 | int j; | ||
1092 | struct SBufferHeader *Cur = tb->Head; | ||
1093 | |||
1094 | if (!rb->Head) | ||
1095 | return; | ||
1096 | free_ringbuffer(dev, rb); | ||
1097 | for (j = 0; j < tb->NumBuffers; j++, Cur = Cur->Next) { | ||
1098 | Cur->Buffer2 = 0; | ||
1099 | Cur->scList2 = 0; | ||
1100 | Cur->ngeneBuffer.Address_of_first_entry_2 = 0; | ||
1101 | Cur->ngeneBuffer.Number_of_entries_2 = 0; | ||
1102 | } | ||
1103 | } | ||
1104 | |||
1105 | static void free_common_buffers(struct ngene *dev) | ||
1106 | { | ||
1107 | u32 i; | ||
1108 | struct ngene_channel *chan; | ||
1109 | |||
1110 | for (i = STREAM_VIDEOIN1; i < MAX_STREAM; i++) { | ||
1111 | chan = &dev->channel[i]; | ||
1112 | free_idlebuffer(dev, &chan->TSIdleBuffer, &chan->TSRingBuffer); | ||
1113 | free_ringbuffer(dev, &chan->RingBuffer); | ||
1114 | free_ringbuffer(dev, &chan->TSRingBuffer); | ||
1115 | } | ||
1116 | |||
1117 | if (dev->OverflowBuffer) | ||
1118 | pci_free_consistent(dev->pci_dev, | ||
1119 | OVERFLOW_BUFFER_SIZE, | ||
1120 | dev->OverflowBuffer, dev->PAOverflowBuffer); | ||
1121 | |||
1122 | if (dev->FWInterfaceBuffer) | ||
1123 | pci_free_consistent(dev->pci_dev, | ||
1124 | 4096, | ||
1125 | dev->FWInterfaceBuffer, | ||
1126 | dev->PAFWInterfaceBuffer); | ||
1127 | } | ||
1128 | |||
1129 | /****************************************************************************/ | ||
1130 | /* Ring buffer handling *****************************************************/ | ||
1131 | /****************************************************************************/ | ||
1132 | |||
1133 | static int create_ring_buffer(struct pci_dev *pci_dev, | ||
1134 | struct SRingBufferDescriptor *descr, u32 NumBuffers) | ||
1135 | { | ||
1136 | dma_addr_t tmp; | ||
1137 | struct SBufferHeader *Head; | ||
1138 | u32 i; | ||
1139 | u32 MemSize = SIZEOF_SBufferHeader * NumBuffers; | ||
1140 | u64 PARingBufferHead; | ||
1141 | u64 PARingBufferCur; | ||
1142 | u64 PARingBufferNext; | ||
1143 | struct SBufferHeader *Cur, *Next; | ||
1144 | |||
1145 | descr->Head = 0; | ||
1146 | descr->MemSize = 0; | ||
1147 | descr->PAHead = 0; | ||
1148 | descr->NumBuffers = 0; | ||
1149 | |||
1150 | if (MemSize < 4096) | ||
1151 | MemSize = 4096; | ||
1152 | |||
1153 | Head = pci_alloc_consistent(pci_dev, MemSize, &tmp); | ||
1154 | PARingBufferHead = tmp; | ||
1155 | |||
1156 | if (!Head) | ||
1157 | return -ENOMEM; | ||
1158 | |||
1159 | memset(Head, 0, MemSize); | ||
1160 | |||
1161 | PARingBufferCur = PARingBufferHead; | ||
1162 | Cur = Head; | ||
1163 | |||
1164 | for (i = 0; i < NumBuffers - 1; i++) { | ||
1165 | Next = (struct SBufferHeader *) | ||
1166 | (((u8 *) Cur) + SIZEOF_SBufferHeader); | ||
1167 | PARingBufferNext = PARingBufferCur + SIZEOF_SBufferHeader; | ||
1168 | Cur->Next = Next; | ||
1169 | Cur->ngeneBuffer.Next = PARingBufferNext; | ||
1170 | Cur = Next; | ||
1171 | PARingBufferCur = PARingBufferNext; | ||
1172 | } | ||
1173 | /* Last Buffer points back to first one */ | ||
1174 | Cur->Next = Head; | ||
1175 | Cur->ngeneBuffer.Next = PARingBufferHead; | ||
1176 | |||
1177 | descr->Head = Head; | ||
1178 | descr->MemSize = MemSize; | ||
1179 | descr->PAHead = PARingBufferHead; | ||
1180 | descr->NumBuffers = NumBuffers; | ||
1181 | |||
1182 | return 0; | ||
1183 | } | ||
1184 | |||
1185 | static int AllocateRingBuffers(struct pci_dev *pci_dev, | ||
1186 | dma_addr_t of, | ||
1187 | struct SRingBufferDescriptor *pRingBuffer, | ||
1188 | u32 Buffer1Length, u32 Buffer2Length) | ||
1189 | { | ||
1190 | dma_addr_t tmp; | ||
1191 | u32 i, j; | ||
1192 | int status = 0; | ||
1193 | u32 SCListMemSize = pRingBuffer->NumBuffers | ||
1194 | * ((Buffer2Length != 0) ? (NUM_SCATTER_GATHER_ENTRIES * 2) : | ||
1195 | NUM_SCATTER_GATHER_ENTRIES) | ||
1196 | * sizeof(struct HW_SCATTER_GATHER_ELEMENT); | ||
1197 | |||
1198 | u64 PASCListMem; | ||
1199 | struct HW_SCATTER_GATHER_ELEMENT *SCListEntry; | ||
1200 | u64 PASCListEntry; | ||
1201 | struct SBufferHeader *Cur; | ||
1202 | void *SCListMem; | ||
1203 | |||
1204 | if (SCListMemSize < 4096) | ||
1205 | SCListMemSize = 4096; | ||
1206 | |||
1207 | SCListMem = pci_alloc_consistent(pci_dev, SCListMemSize, &tmp); | ||
1208 | |||
1209 | PASCListMem = tmp; | ||
1210 | if (SCListMem == NULL) | ||
1211 | return -ENOMEM; | ||
1212 | |||
1213 | memset(SCListMem, 0, SCListMemSize); | ||
1214 | |||
1215 | pRingBuffer->SCListMem = SCListMem; | ||
1216 | pRingBuffer->PASCListMem = PASCListMem; | ||
1217 | pRingBuffer->SCListMemSize = SCListMemSize; | ||
1218 | pRingBuffer->Buffer1Length = Buffer1Length; | ||
1219 | pRingBuffer->Buffer2Length = Buffer2Length; | ||
1220 | |||
1221 | SCListEntry = SCListMem; | ||
1222 | PASCListEntry = PASCListMem; | ||
1223 | Cur = pRingBuffer->Head; | ||
1224 | |||
1225 | for (i = 0; i < pRingBuffer->NumBuffers; i += 1, Cur = Cur->Next) { | ||
1226 | u64 PABuffer; | ||
1227 | |||
1228 | void *Buffer = pci_alloc_consistent(pci_dev, Buffer1Length, | ||
1229 | &tmp); | ||
1230 | PABuffer = tmp; | ||
1231 | |||
1232 | if (Buffer == NULL) | ||
1233 | return -ENOMEM; | ||
1234 | |||
1235 | Cur->Buffer1 = Buffer; | ||
1236 | |||
1237 | SCListEntry->Address = PABuffer; | ||
1238 | SCListEntry->Length = Buffer1Length; | ||
1239 | |||
1240 | Cur->scList1 = SCListEntry; | ||
1241 | Cur->ngeneBuffer.Address_of_first_entry_1 = PASCListEntry; | ||
1242 | Cur->ngeneBuffer.Number_of_entries_1 = | ||
1243 | NUM_SCATTER_GATHER_ENTRIES; | ||
1244 | |||
1245 | SCListEntry += 1; | ||
1246 | PASCListEntry += sizeof(struct HW_SCATTER_GATHER_ELEMENT); | ||
1247 | |||
1248 | #if NUM_SCATTER_GATHER_ENTRIES > 1 | ||
1249 | for (j = 0; j < NUM_SCATTER_GATHER_ENTRIES - 1; j += 1) { | ||
1250 | SCListEntry->Address = of; | ||
1251 | SCListEntry->Length = OVERFLOW_BUFFER_SIZE; | ||
1252 | SCListEntry += 1; | ||
1253 | PASCListEntry += | ||
1254 | sizeof(struct HW_SCATTER_GATHER_ELEMENT); | ||
1255 | } | ||
1256 | #endif | ||
1257 | |||
1258 | if (!Buffer2Length) | ||
1259 | continue; | ||
1260 | |||
1261 | Buffer = pci_alloc_consistent(pci_dev, Buffer2Length, &tmp); | ||
1262 | PABuffer = tmp; | ||
1263 | |||
1264 | if (Buffer == NULL) | ||
1265 | return -ENOMEM; | ||
1266 | |||
1267 | Cur->Buffer2 = Buffer; | ||
1268 | |||
1269 | SCListEntry->Address = PABuffer; | ||
1270 | SCListEntry->Length = Buffer2Length; | ||
1271 | |||
1272 | Cur->scList2 = SCListEntry; | ||
1273 | Cur->ngeneBuffer.Address_of_first_entry_2 = PASCListEntry; | ||
1274 | Cur->ngeneBuffer.Number_of_entries_2 = | ||
1275 | NUM_SCATTER_GATHER_ENTRIES; | ||
1276 | |||
1277 | SCListEntry += 1; | ||
1278 | PASCListEntry += sizeof(struct HW_SCATTER_GATHER_ELEMENT); | ||
1279 | |||
1280 | #if NUM_SCATTER_GATHER_ENTRIES > 1 | ||
1281 | for (j = 0; j < NUM_SCATTER_GATHER_ENTRIES - 1; j++) { | ||
1282 | SCListEntry->Address = of; | ||
1283 | SCListEntry->Length = OVERFLOW_BUFFER_SIZE; | ||
1284 | SCListEntry += 1; | ||
1285 | PASCListEntry += | ||
1286 | sizeof(struct HW_SCATTER_GATHER_ELEMENT); | ||
1287 | } | ||
1288 | #endif | ||
1289 | |||
1290 | } | ||
1291 | |||
1292 | return status; | ||
1293 | } | ||
1294 | |||
1295 | static int FillTSIdleBuffer(struct SRingBufferDescriptor *pIdleBuffer, | ||
1296 | struct SRingBufferDescriptor *pRingBuffer) | ||
1297 | { | ||
1298 | int status = 0; | ||
1299 | |||
1300 | /* Copy pointer to scatter gather list in TSRingbuffer | ||
1301 | structure for buffer 2 | ||
1302 | Load number of buffer | ||
1303 | */ | ||
1304 | u32 n = pRingBuffer->NumBuffers; | ||
1305 | |||
1306 | /* Point to first buffer entry */ | ||
1307 | struct SBufferHeader *Cur = pRingBuffer->Head; | ||
1308 | int i; | ||
1309 | /* Loop thru all buffer and set Buffer 2 pointers to TSIdlebuffer */ | ||
1310 | for (i = 0; i < n; i++) { | ||
1311 | Cur->Buffer2 = pIdleBuffer->Head->Buffer1; | ||
1312 | Cur->scList2 = pIdleBuffer->Head->scList1; | ||
1313 | Cur->ngeneBuffer.Address_of_first_entry_2 = | ||
1314 | pIdleBuffer->Head->ngeneBuffer. | ||
1315 | Address_of_first_entry_1; | ||
1316 | Cur->ngeneBuffer.Number_of_entries_2 = | ||
1317 | pIdleBuffer->Head->ngeneBuffer.Number_of_entries_1; | ||
1318 | Cur = Cur->Next; | ||
1319 | } | ||
1320 | return status; | ||
1321 | } | ||
1322 | |||
1323 | static u32 RingBufferSizes[MAX_STREAM] = { | ||
1324 | RING_SIZE_VIDEO, | ||
1325 | RING_SIZE_VIDEO, | ||
1326 | RING_SIZE_AUDIO, | ||
1327 | RING_SIZE_AUDIO, | ||
1328 | RING_SIZE_AUDIO, | ||
1329 | }; | ||
1330 | |||
1331 | static u32 Buffer1Sizes[MAX_STREAM] = { | ||
1332 | MAX_VIDEO_BUFFER_SIZE, | ||
1333 | MAX_VIDEO_BUFFER_SIZE, | ||
1334 | MAX_AUDIO_BUFFER_SIZE, | ||
1335 | MAX_AUDIO_BUFFER_SIZE, | ||
1336 | MAX_AUDIO_BUFFER_SIZE | ||
1337 | }; | ||
1338 | |||
1339 | static u32 Buffer2Sizes[MAX_STREAM] = { | ||
1340 | MAX_VBI_BUFFER_SIZE, | ||
1341 | MAX_VBI_BUFFER_SIZE, | ||
1342 | 0, | ||
1343 | 0, | ||
1344 | 0 | ||
1345 | }; | ||
1346 | |||
1347 | |||
1348 | static int AllocCommonBuffers(struct ngene *dev) | ||
1349 | { | ||
1350 | int status = 0, i; | ||
1351 | |||
1352 | dev->FWInterfaceBuffer = pci_alloc_consistent(dev->pci_dev, 4096, | ||
1353 | &dev->PAFWInterfaceBuffer); | ||
1354 | if (!dev->FWInterfaceBuffer) | ||
1355 | return -ENOMEM; | ||
1356 | dev->hosttongene = dev->FWInterfaceBuffer; | ||
1357 | dev->ngenetohost = dev->FWInterfaceBuffer + 256; | ||
1358 | dev->EventBuffer = dev->FWInterfaceBuffer + 512; | ||
1359 | |||
1360 | dev->OverflowBuffer = pci_alloc_consistent(dev->pci_dev, | ||
1361 | OVERFLOW_BUFFER_SIZE, | ||
1362 | &dev->PAOverflowBuffer); | ||
1363 | if (!dev->OverflowBuffer) | ||
1364 | return -ENOMEM; | ||
1365 | memset(dev->OverflowBuffer, 0, OVERFLOW_BUFFER_SIZE); | ||
1366 | |||
1367 | for (i = STREAM_VIDEOIN1; i < MAX_STREAM; i++) { | ||
1368 | int type = dev->card_info->io_type[i]; | ||
1369 | |||
1370 | dev->channel[i].State = KSSTATE_STOP; | ||
1371 | |||
1372 | if (type & (NGENE_IO_TV | NGENE_IO_HDTV | NGENE_IO_AIN)) { | ||
1373 | status = create_ring_buffer(dev->pci_dev, | ||
1374 | &dev->channel[i].RingBuffer, | ||
1375 | RingBufferSizes[i]); | ||
1376 | if (status < 0) | ||
1377 | break; | ||
1378 | |||
1379 | if (type & (NGENE_IO_TV | NGENE_IO_AIN)) { | ||
1380 | status = AllocateRingBuffers(dev->pci_dev, | ||
1381 | dev-> | ||
1382 | PAOverflowBuffer, | ||
1383 | &dev->channel[i]. | ||
1384 | RingBuffer, | ||
1385 | Buffer1Sizes[i], | ||
1386 | Buffer2Sizes[i]); | ||
1387 | if (status < 0) | ||
1388 | break; | ||
1389 | } else if (type & NGENE_IO_HDTV) { | ||
1390 | status = AllocateRingBuffers(dev->pci_dev, | ||
1391 | dev-> | ||
1392 | PAOverflowBuffer, | ||
1393 | &dev->channel[i]. | ||
1394 | RingBuffer, | ||
1395 | MAX_HDTV_BUFFER_SIZE, | ||
1396 | 0); | ||
1397 | if (status < 0) | ||
1398 | break; | ||
1399 | } | ||
1400 | } | ||
1401 | |||
1402 | if (type & (NGENE_IO_TSIN | NGENE_IO_TSOUT)) { | ||
1403 | |||
1404 | status = create_ring_buffer(dev->pci_dev, | ||
1405 | &dev->channel[i]. | ||
1406 | TSRingBuffer, RING_SIZE_TS); | ||
1407 | if (status < 0) | ||
1408 | break; | ||
1409 | |||
1410 | status = AllocateRingBuffers(dev->pci_dev, | ||
1411 | dev->PAOverflowBuffer, | ||
1412 | &dev->channel[i]. | ||
1413 | TSRingBuffer, | ||
1414 | MAX_TS_BUFFER_SIZE, 0); | ||
1415 | if (status) | ||
1416 | break; | ||
1417 | } | ||
1418 | |||
1419 | if (type & NGENE_IO_TSOUT) { | ||
1420 | status = create_ring_buffer(dev->pci_dev, | ||
1421 | &dev->channel[i]. | ||
1422 | TSIdleBuffer, 1); | ||
1423 | if (status < 0) | ||
1424 | break; | ||
1425 | status = AllocateRingBuffers(dev->pci_dev, | ||
1426 | dev->PAOverflowBuffer, | ||
1427 | &dev->channel[i]. | ||
1428 | TSIdleBuffer, | ||
1429 | MAX_TS_BUFFER_SIZE, 0); | ||
1430 | if (status) | ||
1431 | break; | ||
1432 | FillTSIdleBuffer(&dev->channel[i].TSIdleBuffer, | ||
1433 | &dev->channel[i].TSRingBuffer); | ||
1434 | } | ||
1435 | } | ||
1436 | return status; | ||
1437 | } | ||
1438 | |||
1439 | static void ngene_release_buffers(struct ngene *dev) | ||
1440 | { | ||
1441 | if (dev->iomem) | ||
1442 | iounmap(dev->iomem); | ||
1443 | free_common_buffers(dev); | ||
1444 | vfree(dev->tsout_buf); | ||
1445 | vfree(dev->ain_buf); | ||
1446 | vfree(dev->vin_buf); | ||
1447 | vfree(dev); | ||
1448 | } | ||
1449 | |||
1450 | static int ngene_get_buffers(struct ngene *dev) | ||
1451 | { | ||
1452 | if (AllocCommonBuffers(dev)) | ||
1453 | return -ENOMEM; | ||
1454 | if (dev->card_info->io_type[4] & NGENE_IO_TSOUT) { | ||
1455 | dev->tsout_buf = vmalloc(TSOUT_BUF_SIZE); | ||
1456 | if (!dev->tsout_buf) | ||
1457 | return -ENOMEM; | ||
1458 | dvb_ringbuffer_init(&dev->tsout_rbuf, | ||
1459 | dev->tsout_buf, TSOUT_BUF_SIZE); | ||
1460 | } | ||
1461 | if (dev->card_info->io_type[2] & NGENE_IO_AIN) { | ||
1462 | dev->ain_buf = vmalloc(AIN_BUF_SIZE); | ||
1463 | if (!dev->ain_buf) | ||
1464 | return -ENOMEM; | ||
1465 | dvb_ringbuffer_init(&dev->ain_rbuf, dev->ain_buf, AIN_BUF_SIZE); | ||
1466 | } | ||
1467 | if (dev->card_info->io_type[0] & NGENE_IO_HDTV) { | ||
1468 | dev->vin_buf = vmalloc(VIN_BUF_SIZE); | ||
1469 | if (!dev->vin_buf) | ||
1470 | return -ENOMEM; | ||
1471 | dvb_ringbuffer_init(&dev->vin_rbuf, dev->vin_buf, VIN_BUF_SIZE); | ||
1472 | } | ||
1473 | dev->iomem = ioremap(pci_resource_start(dev->pci_dev, 0), | ||
1474 | pci_resource_len(dev->pci_dev, 0)); | ||
1475 | if (!dev->iomem) | ||
1476 | return -ENOMEM; | ||
1477 | |||
1478 | return 0; | ||
1479 | } | ||
1480 | |||
1481 | static void ngene_init(struct ngene *dev) | ||
1482 | { | ||
1483 | int i; | ||
1484 | |||
1485 | tasklet_init(&dev->event_tasklet, event_tasklet, (unsigned long)dev); | ||
1486 | |||
1487 | memset_io(dev->iomem + 0xc000, 0x00, 0x220); | ||
1488 | memset_io(dev->iomem + 0xc400, 0x00, 0x100); | ||
1489 | |||
1490 | for (i = 0; i < MAX_STREAM; i++) { | ||
1491 | dev->channel[i].dev = dev; | ||
1492 | dev->channel[i].number = i; | ||
1493 | } | ||
1494 | |||
1495 | dev->fw_interface_version = 0; | ||
1496 | |||
1497 | ngwritel(0, NGENE_INT_ENABLE); | ||
1498 | |||
1499 | dev->icounts = ngreadl(NGENE_INT_COUNTS); | ||
1500 | |||
1501 | dev->device_version = ngreadl(DEV_VER) & 0x0f; | ||
1502 | printk(KERN_INFO DEVICE_NAME ": Device version %d\n", | ||
1503 | dev->device_version); | ||
1504 | } | ||
1505 | |||
1506 | static int ngene_load_firm(struct ngene *dev) | ||
1507 | { | ||
1508 | u32 size; | ||
1509 | const struct firmware *fw = NULL; | ||
1510 | u8 *ngene_fw; | ||
1511 | char *fw_name; | ||
1512 | int err, version; | ||
1513 | |||
1514 | version = dev->card_info->fw_version; | ||
1515 | |||
1516 | switch (version) { | ||
1517 | default: | ||
1518 | case 15: | ||
1519 | version = 15; | ||
1520 | size = 23466; | ||
1521 | fw_name = "ngene_15.fw"; | ||
1522 | break; | ||
1523 | case 16: | ||
1524 | size = 23498; | ||
1525 | fw_name = "ngene_16.fw"; | ||
1526 | break; | ||
1527 | case 17: | ||
1528 | size = 24446; | ||
1529 | fw_name = "ngene_17.fw"; | ||
1530 | break; | ||
1531 | } | ||
1532 | |||
1533 | if (request_firmware(&fw, fw_name, &dev->pci_dev->dev) < 0) { | ||
1534 | printk(KERN_ERR DEVICE_NAME | ||
1535 | ": Could not load firmware file %s.\n", fw_name); | ||
1536 | printk(KERN_INFO DEVICE_NAME | ||
1537 | ": Copy %s to your hotplug directory!\n", fw_name); | ||
1538 | return -1; | ||
1539 | } | ||
1540 | if (size != fw->size) { | ||
1541 | printk(KERN_ERR DEVICE_NAME | ||
1542 | ": Firmware %s has invalid size!", fw_name); | ||
1543 | err = -1; | ||
1544 | } else { | ||
1545 | printk(KERN_INFO DEVICE_NAME | ||
1546 | ": Loading firmware file %s.\n", fw_name); | ||
1547 | ngene_fw = (u8 *) fw->data; | ||
1548 | err = ngene_command_load_firmware(dev, ngene_fw, size); | ||
1549 | } | ||
1550 | |||
1551 | release_firmware(fw); | ||
1552 | |||
1553 | return err; | ||
1554 | } | ||
1555 | |||
1556 | static void ngene_stop(struct ngene *dev) | ||
1557 | { | ||
1558 | down(&dev->cmd_mutex); | ||
1559 | i2c_del_adapter(&(dev->channel[0].i2c_adapter)); | ||
1560 | i2c_del_adapter(&(dev->channel[1].i2c_adapter)); | ||
1561 | ngwritel(0, NGENE_INT_ENABLE); | ||
1562 | ngwritel(0, NGENE_COMMAND); | ||
1563 | ngwritel(0, NGENE_COMMAND_HI); | ||
1564 | ngwritel(0, NGENE_STATUS); | ||
1565 | ngwritel(0, NGENE_STATUS_HI); | ||
1566 | ngwritel(0, NGENE_EVENT); | ||
1567 | ngwritel(0, NGENE_EVENT_HI); | ||
1568 | free_irq(dev->pci_dev->irq, dev); | ||
1569 | } | ||
1570 | |||
1571 | static int ngene_start(struct ngene *dev) | ||
1572 | { | ||
1573 | int stat; | ||
1574 | int i; | ||
1575 | |||
1576 | pci_set_master(dev->pci_dev); | ||
1577 | ngene_init(dev); | ||
1578 | |||
1579 | stat = request_irq(dev->pci_dev->irq, irq_handler, | ||
1580 | IRQF_SHARED, "nGene", | ||
1581 | (void *)dev); | ||
1582 | if (stat < 0) | ||
1583 | return stat; | ||
1584 | |||
1585 | init_waitqueue_head(&dev->cmd_wq); | ||
1586 | init_waitqueue_head(&dev->tx_wq); | ||
1587 | init_waitqueue_head(&dev->rx_wq); | ||
1588 | sema_init(&dev->cmd_mutex, 1); | ||
1589 | sema_init(&dev->stream_mutex, 1); | ||
1590 | sema_init(&dev->pll_mutex, 1); | ||
1591 | sema_init(&dev->i2c_switch_mutex, 1); | ||
1592 | spin_lock_init(&dev->cmd_lock); | ||
1593 | for (i = 0; i < MAX_STREAM; i++) | ||
1594 | spin_lock_init(&dev->channel[i].state_lock); | ||
1595 | ngwritel(1, TIMESTAMPS); | ||
1596 | |||
1597 | ngwritel(1, NGENE_INT_ENABLE); | ||
1598 | |||
1599 | stat = ngene_load_firm(dev); | ||
1600 | if (stat < 0) | ||
1601 | goto fail; | ||
1602 | |||
1603 | stat = ngene_i2c_init(dev, 0); | ||
1604 | if (stat < 0) | ||
1605 | goto fail; | ||
1606 | |||
1607 | stat = ngene_i2c_init(dev, 1); | ||
1608 | if (stat < 0) | ||
1609 | goto fail; | ||
1610 | |||
1611 | if (dev->card_info->fw_version == 17) { | ||
1612 | u8 tsin4_config[6] = { | ||
1613 | 3072 / 64, 3072 / 64, 0, 3072 / 64, 3072 / 64, 0}; | ||
1614 | u8 default_config[6] = { | ||
1615 | 4096 / 64, 4096 / 64, 0, 2048 / 64, 2048 / 64, 0}; | ||
1616 | u8 *bconf = default_config; | ||
1617 | |||
1618 | if (dev->card_info->io_type[3] == NGENE_IO_TSIN) | ||
1619 | bconf = tsin4_config; | ||
1620 | dprintk(KERN_DEBUG DEVICE_NAME ": FW 17 buffer config\n"); | ||
1621 | stat = ngene_command_config_free_buf(dev, bconf); | ||
1622 | } else { | ||
1623 | int bconf = BUFFER_CONFIG_4422; | ||
1624 | if (dev->card_info->io_type[3] == NGENE_IO_TSIN) | ||
1625 | bconf = BUFFER_CONFIG_3333; | ||
1626 | stat = ngene_command_config_buf(dev, bconf); | ||
1627 | } | ||
1628 | return stat; | ||
1629 | fail: | ||
1630 | ngwritel(0, NGENE_INT_ENABLE); | ||
1631 | free_irq(dev->pci_dev->irq, dev); | ||
1632 | return stat; | ||
1633 | } | ||
1634 | |||
1635 | |||
1636 | |||
1637 | /****************************************************************************/ | ||
1638 | /* Switch control (I2C gates, etc.) *****************************************/ | ||
1639 | /****************************************************************************/ | ||
1640 | |||
1641 | |||
1642 | /****************************************************************************/ | ||
1643 | /* Demod/tuner attachment ***************************************************/ | ||
1644 | /****************************************************************************/ | ||
1645 | |||
1646 | static int tuner_attach_stv6110(struct ngene_channel *chan) | ||
1647 | { | ||
1648 | struct stv090x_config *feconf = (struct stv090x_config *) | ||
1649 | chan->dev->card_info->fe_config[chan->number]; | ||
1650 | struct stv6110x_config *tunerconf = (struct stv6110x_config *) | ||
1651 | chan->dev->card_info->tuner_config[chan->number]; | ||
1652 | struct stv6110x_devctl *ctl; | ||
1653 | |||
1654 | ctl = dvb_attach(stv6110x_attach, chan->fe, tunerconf, | ||
1655 | &chan->i2c_adapter); | ||
1656 | if (ctl == NULL) { | ||
1657 | printk(KERN_ERR DEVICE_NAME ": No STV6110X found!\n"); | ||
1658 | return -ENODEV; | ||
1659 | } | ||
1660 | |||
1661 | feconf->tuner_init = ctl->tuner_init; | ||
1662 | feconf->tuner_set_mode = ctl->tuner_set_mode; | ||
1663 | feconf->tuner_set_frequency = ctl->tuner_set_frequency; | ||
1664 | feconf->tuner_get_frequency = ctl->tuner_get_frequency; | ||
1665 | feconf->tuner_set_bandwidth = ctl->tuner_set_bandwidth; | ||
1666 | feconf->tuner_get_bandwidth = ctl->tuner_get_bandwidth; | ||
1667 | feconf->tuner_set_bbgain = ctl->tuner_set_bbgain; | ||
1668 | feconf->tuner_get_bbgain = ctl->tuner_get_bbgain; | ||
1669 | feconf->tuner_set_refclk = ctl->tuner_set_refclk; | ||
1670 | feconf->tuner_get_status = ctl->tuner_get_status; | ||
1671 | |||
1672 | return 0; | ||
1673 | } | ||
1674 | |||
1675 | |||
1676 | static int demod_attach_stv0900(struct ngene_channel *chan) | ||
1677 | { | ||
1678 | struct stv090x_config *feconf = (struct stv090x_config *) | ||
1679 | chan->dev->card_info->fe_config[chan->number]; | ||
1680 | |||
1681 | chan->fe = dvb_attach(stv090x_attach, | ||
1682 | feconf, | ||
1683 | &chan->i2c_adapter, | ||
1684 | chan->number == 0 ? STV090x_DEMODULATOR_0 : | ||
1685 | STV090x_DEMODULATOR_1); | ||
1686 | if (chan->fe == NULL) { | ||
1687 | printk(KERN_ERR DEVICE_NAME ": No STV0900 found!\n"); | ||
1688 | return -ENODEV; | ||
1689 | } | ||
1690 | |||
1691 | if (!dvb_attach(lnbh24_attach, chan->fe, &chan->i2c_adapter, 0, | ||
1692 | 0, chan->dev->card_info->lnb[chan->number])) { | ||
1693 | printk(KERN_ERR DEVICE_NAME ": No LNBH24 found!\n"); | ||
1694 | dvb_frontend_detach(chan->fe); | ||
1695 | return -ENODEV; | ||
1696 | } | ||
1697 | |||
1698 | return 0; | ||
1699 | } | ||
1700 | |||
1701 | /****************************************************************************/ | ||
1702 | /****************************************************************************/ | ||
1703 | /****************************************************************************/ | ||
1704 | |||
1705 | static void release_channel(struct ngene_channel *chan) | ||
1706 | { | ||
1707 | struct dvb_demux *dvbdemux = &chan->demux; | ||
1708 | struct ngene *dev = chan->dev; | ||
1709 | struct ngene_info *ni = dev->card_info; | ||
1710 | int io = ni->io_type[chan->number]; | ||
1711 | |||
1712 | #ifdef COMMAND_TIMEOUT_WORKAROUND | ||
1713 | if (chan->running) | ||
1714 | set_transfer(chan, 0); | ||
1715 | #endif | ||
1716 | |||
1717 | tasklet_kill(&chan->demux_tasklet); | ||
1718 | |||
1719 | if (io & (NGENE_IO_TSIN | NGENE_IO_TSOUT)) { | ||
1720 | if (chan->fe) { | ||
1721 | dvb_unregister_frontend(chan->fe); | ||
1722 | dvb_frontend_detach(chan->fe); | ||
1723 | chan->fe = 0; | ||
1724 | } | ||
1725 | dvbdemux->dmx.close(&dvbdemux->dmx); | ||
1726 | dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, | ||
1727 | &chan->hw_frontend); | ||
1728 | dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, | ||
1729 | &chan->mem_frontend); | ||
1730 | dvb_dmxdev_release(&chan->dmxdev); | ||
1731 | dvb_dmx_release(&chan->demux); | ||
1732 | |||
1733 | if (chan->number == 0 || !one_adapter) | ||
1734 | dvb_unregister_adapter(&dev->adapter[chan->number]); | ||
1735 | } | ||
1736 | } | ||
1737 | |||
1738 | static int init_channel(struct ngene_channel *chan) | ||
1739 | { | ||
1740 | int ret = 0, nr = chan->number; | ||
1741 | struct dvb_adapter *adapter = NULL; | ||
1742 | struct dvb_demux *dvbdemux = &chan->demux; | ||
1743 | struct ngene *dev = chan->dev; | ||
1744 | struct ngene_info *ni = dev->card_info; | ||
1745 | int io = ni->io_type[nr]; | ||
1746 | |||
1747 | tasklet_init(&chan->demux_tasklet, demux_tasklet, (unsigned long)chan); | ||
1748 | chan->users = 0; | ||
1749 | chan->type = io; | ||
1750 | chan->mode = chan->type; /* for now only one mode */ | ||
1751 | |||
1752 | if (io & (NGENE_IO_TSIN | NGENE_IO_TSOUT)) { | ||
1753 | if (nr >= STREAM_AUDIOIN1) | ||
1754 | chan->DataFormatFlags = DF_SWAP32; | ||
1755 | if (nr == 0 || !one_adapter) { | ||
1756 | adapter = &dev->adapter[nr]; | ||
1757 | ret = dvb_register_adapter(adapter, "nGene", | ||
1758 | THIS_MODULE, | ||
1759 | &chan->dev->pci_dev->dev, | ||
1760 | adapter_nr); | ||
1761 | if (ret < 0) | ||
1762 | return ret; | ||
1763 | } else { | ||
1764 | adapter = &dev->adapter[0]; | ||
1765 | } | ||
1766 | |||
1767 | ret = my_dvb_dmx_ts_card_init(dvbdemux, "SW demux", | ||
1768 | ngene_start_feed, | ||
1769 | ngene_stop_feed, chan); | ||
1770 | ret = my_dvb_dmxdev_ts_card_init(&chan->dmxdev, &chan->demux, | ||
1771 | &chan->hw_frontend, | ||
1772 | &chan->mem_frontend, adapter); | ||
1773 | } | ||
1774 | |||
1775 | if (io & NGENE_IO_TSIN) { | ||
1776 | chan->fe = NULL; | ||
1777 | if (ni->demod_attach[nr]) | ||
1778 | ni->demod_attach[nr](chan); | ||
1779 | if (chan->fe) { | ||
1780 | if (dvb_register_frontend(adapter, chan->fe) < 0) { | ||
1781 | if (chan->fe->ops.release) | ||
1782 | chan->fe->ops.release(chan->fe); | ||
1783 | chan->fe = NULL; | ||
1784 | } | ||
1785 | } | ||
1786 | if (chan->fe && ni->tuner_attach[nr]) | ||
1787 | if (ni->tuner_attach[nr] (chan) < 0) { | ||
1788 | printk(KERN_ERR DEVICE_NAME | ||
1789 | ": Tuner attach failed on channel %d!\n", | ||
1790 | nr); | ||
1791 | } | ||
1792 | } | ||
1793 | return ret; | ||
1794 | } | ||
1795 | |||
1796 | static int init_channels(struct ngene *dev) | ||
1797 | { | ||
1798 | int i, j; | ||
1799 | |||
1800 | for (i = 0; i < MAX_STREAM; i++) { | ||
1801 | if (init_channel(&dev->channel[i]) < 0) { | ||
1802 | for (j = i - 1; j >= 0; j--) | ||
1803 | release_channel(&dev->channel[j]); | ||
1804 | return -1; | ||
1805 | } | ||
1806 | } | ||
1807 | return 0; | ||
1808 | } | ||
1809 | |||
1810 | /****************************************************************************/ | ||
1811 | /* device probe/remove calls ************************************************/ | ||
1812 | /****************************************************************************/ | ||
1813 | |||
1814 | static void __devexit ngene_remove(struct pci_dev *pdev) | ||
1815 | { | ||
1816 | struct ngene *dev = (struct ngene *)pci_get_drvdata(pdev); | ||
1817 | int i; | ||
1818 | |||
1819 | tasklet_kill(&dev->event_tasklet); | ||
1820 | for (i = MAX_STREAM - 1; i >= 0; i--) | ||
1821 | release_channel(&dev->channel[i]); | ||
1822 | ngene_stop(dev); | ||
1823 | ngene_release_buffers(dev); | ||
1824 | pci_set_drvdata(pdev, 0); | ||
1825 | pci_disable_device(pdev); | ||
1826 | } | ||
1827 | |||
1828 | static int __devinit ngene_probe(struct pci_dev *pci_dev, | ||
1829 | const struct pci_device_id *id) | ||
1830 | { | ||
1831 | struct ngene *dev; | ||
1832 | int stat = 0; | ||
1833 | |||
1834 | if (pci_enable_device(pci_dev) < 0) | ||
1835 | return -ENODEV; | ||
1836 | |||
1837 | dev = vmalloc(sizeof(struct ngene)); | ||
1838 | if (dev == NULL) { | ||
1839 | stat = -ENOMEM; | ||
1840 | goto fail0; | ||
1841 | } | ||
1842 | memset(dev, 0, sizeof(struct ngene)); | ||
1843 | |||
1844 | dev->pci_dev = pci_dev; | ||
1845 | dev->card_info = (struct ngene_info *)id->driver_data; | ||
1846 | printk(KERN_INFO DEVICE_NAME ": Found %s\n", dev->card_info->name); | ||
1847 | |||
1848 | pci_set_drvdata(pci_dev, dev); | ||
1849 | |||
1850 | /* Alloc buffers and start nGene */ | ||
1851 | stat = ngene_get_buffers(dev); | ||
1852 | if (stat < 0) | ||
1853 | goto fail1; | ||
1854 | stat = ngene_start(dev); | ||
1855 | if (stat < 0) | ||
1856 | goto fail1; | ||
1857 | |||
1858 | dev->i2c_current_bus = -1; | ||
1859 | |||
1860 | /* Register DVB adapters and devices for both channels */ | ||
1861 | if (init_channels(dev) < 0) | ||
1862 | goto fail2; | ||
1863 | |||
1864 | return 0; | ||
1865 | |||
1866 | fail2: | ||
1867 | ngene_stop(dev); | ||
1868 | fail1: | ||
1869 | ngene_release_buffers(dev); | ||
1870 | fail0: | ||
1871 | pci_disable_device(pci_dev); | ||
1872 | pci_set_drvdata(pci_dev, 0); | ||
1873 | return stat; | ||
1874 | } | ||
1875 | |||
1876 | /****************************************************************************/ | ||
1877 | /* Card configs *************************************************************/ | ||
1878 | /****************************************************************************/ | ||
1879 | |||
1880 | static struct stv090x_config fe_cineS2 = { | ||
1881 | .device = STV0900, | ||
1882 | .demod_mode = STV090x_DUAL, | ||
1883 | .clk_mode = STV090x_CLK_EXT, | ||
1884 | |||
1885 | .xtal = 27000000, | ||
1886 | .address = 0x68, | ||
1887 | |||
1888 | .ts1_mode = STV090x_TSMODE_SERIAL_PUNCTURED, | ||
1889 | .ts2_mode = STV090x_TSMODE_SERIAL_PUNCTURED, | ||
1890 | |||
1891 | .repeater_level = STV090x_RPTLEVEL_16, | ||
1892 | |||
1893 | .adc1_range = STV090x_ADC_1Vpp, | ||
1894 | .adc2_range = STV090x_ADC_1Vpp, | ||
1895 | |||
1896 | .diseqc_envelope_mode = true, | ||
1897 | }; | ||
1898 | |||
1899 | static struct stv6110x_config tuner_cineS2_0 = { | ||
1900 | .addr = 0x60, | ||
1901 | .refclk = 27000000, | ||
1902 | .clk_div = 1, | ||
1903 | }; | ||
1904 | |||
1905 | static struct stv6110x_config tuner_cineS2_1 = { | ||
1906 | .addr = 0x63, | ||
1907 | .refclk = 27000000, | ||
1908 | .clk_div = 1, | ||
1909 | }; | ||
1910 | |||
1911 | static struct ngene_info ngene_info_cineS2 = { | ||
1912 | .type = NGENE_SIDEWINDER, | ||
1913 | .name = "Linux4Media cineS2 DVB-S2 Twin Tuner", | ||
1914 | .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, | ||
1915 | .demod_attach = {demod_attach_stv0900, demod_attach_stv0900}, | ||
1916 | .tuner_attach = {tuner_attach_stv6110, tuner_attach_stv6110}, | ||
1917 | .fe_config = {&fe_cineS2, &fe_cineS2}, | ||
1918 | .tuner_config = {&tuner_cineS2_0, &tuner_cineS2_1}, | ||
1919 | .lnb = {0x0b, 0x08}, | ||
1920 | .tsf = {3, 3}, | ||
1921 | .fw_version = 15, | ||
1922 | }; | ||
1923 | |||
1924 | static struct ngene_info ngene_info_satixs2 = { | ||
1925 | .type = NGENE_SIDEWINDER, | ||
1926 | .name = "Mystique SaTiX-S2 Dual", | ||
1927 | .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, | ||
1928 | .demod_attach = {demod_attach_stv0900, demod_attach_stv0900}, | ||
1929 | .tuner_attach = {tuner_attach_stv6110, tuner_attach_stv6110}, | ||
1930 | .fe_config = {&fe_cineS2, &fe_cineS2}, | ||
1931 | .tuner_config = {&tuner_cineS2_0, &tuner_cineS2_1}, | ||
1932 | .lnb = {0x0b, 0x08}, | ||
1933 | .tsf = {3, 3}, | ||
1934 | .fw_version = 15, | ||
1935 | }; | ||
1936 | |||
1937 | /****************************************************************************/ | ||
1938 | |||
1939 | |||
1940 | |||
1941 | /****************************************************************************/ | ||
1942 | /* PCI Subsystem ID *********************************************************/ | ||
1943 | /****************************************************************************/ | ||
1944 | |||
1945 | #define NGENE_ID(_subvend, _subdev, _driverdata) { \ | ||
1946 | .vendor = NGENE_VID, .device = NGENE_PID, \ | ||
1947 | .subvendor = _subvend, .subdevice = _subdev, \ | ||
1948 | .driver_data = (unsigned long) &_driverdata } | ||
1949 | |||
1950 | /****************************************************************************/ | ||
1951 | |||
1952 | static const struct pci_device_id ngene_id_tbl[] __devinitdata = { | ||
1953 | NGENE_ID(0x18c3, 0xabc3, ngene_info_cineS2), | ||
1954 | NGENE_ID(0x18c3, 0xabc4, ngene_info_cineS2), | ||
1955 | NGENE_ID(0x18c3, 0xdb01, ngene_info_satixs2), | ||
1956 | {0} | ||
1957 | }; | ||
1958 | MODULE_DEVICE_TABLE(pci, ngene_id_tbl); | ||
1959 | |||
1960 | /****************************************************************************/ | ||
1961 | /* Init/Exit ****************************************************************/ | ||
1962 | /****************************************************************************/ | ||
1963 | |||
1964 | static pci_ers_result_t ngene_error_detected(struct pci_dev *dev, | ||
1965 | enum pci_channel_state state) | ||
1966 | { | ||
1967 | printk(KERN_ERR DEVICE_NAME ": PCI error\n"); | ||
1968 | if (state == pci_channel_io_perm_failure) | ||
1969 | return PCI_ERS_RESULT_DISCONNECT; | ||
1970 | if (state == pci_channel_io_frozen) | ||
1971 | return PCI_ERS_RESULT_NEED_RESET; | ||
1972 | return PCI_ERS_RESULT_CAN_RECOVER; | ||
1973 | } | ||
1974 | |||
1975 | static pci_ers_result_t ngene_link_reset(struct pci_dev *dev) | ||
1976 | { | ||
1977 | printk(KERN_INFO DEVICE_NAME ": link reset\n"); | ||
1978 | return 0; | ||
1979 | } | ||
1980 | |||
1981 | static pci_ers_result_t ngene_slot_reset(struct pci_dev *dev) | ||
1982 | { | ||
1983 | printk(KERN_INFO DEVICE_NAME ": slot reset\n"); | ||
1984 | return 0; | ||
1985 | } | ||
1986 | |||
1987 | static void ngene_resume(struct pci_dev *dev) | ||
1988 | { | ||
1989 | printk(KERN_INFO DEVICE_NAME ": resume\n"); | ||
1990 | } | ||
1991 | |||
1992 | static struct pci_error_handlers ngene_errors = { | ||
1993 | .error_detected = ngene_error_detected, | ||
1994 | .link_reset = ngene_link_reset, | ||
1995 | .slot_reset = ngene_slot_reset, | ||
1996 | .resume = ngene_resume, | ||
1997 | }; | ||
1998 | |||
1999 | static struct pci_driver ngene_pci_driver = { | ||
2000 | .name = "ngene", | ||
2001 | .id_table = ngene_id_tbl, | ||
2002 | .probe = ngene_probe, | ||
2003 | .remove = __devexit_p(ngene_remove), | ||
2004 | .err_handler = &ngene_errors, | ||
2005 | }; | ||
2006 | |||
2007 | static __init int module_init_ngene(void) | ||
2008 | { | ||
2009 | printk(KERN_INFO | ||
2010 | "nGene PCIE bridge driver, Copyright (C) 2005-2007 Micronas\n"); | ||
2011 | return pci_register_driver(&ngene_pci_driver); | ||
2012 | } | ||
2013 | |||
2014 | static __exit void module_exit_ngene(void) | ||
2015 | { | ||
2016 | pci_unregister_driver(&ngene_pci_driver); | ||
2017 | } | ||
2018 | |||
2019 | module_init(module_init_ngene); | ||
2020 | module_exit(module_exit_ngene); | ||
2021 | |||
2022 | MODULE_DESCRIPTION("nGene"); | ||
2023 | MODULE_AUTHOR("Micronas, Ralph Metzler, Manfred Voelkel"); | ||
2024 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/ngene/ngene.h b/drivers/media/dvb/ngene/ngene.h new file mode 100644 index 000000000000..a7eb29846310 --- /dev/null +++ b/drivers/media/dvb/ngene/ngene.h | |||
@@ -0,0 +1,859 @@ | |||
1 | /* | ||
2 | * ngene.h: nGene PCIe bridge driver | ||
3 | * | ||
4 | * Copyright (C) 2005-2007 Micronas | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 only, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
20 | * 02110-1301, USA | ||
21 | * Or, point your browser to http://www.gnu.org/copyleft/gpl.html | ||
22 | */ | ||
23 | |||
24 | #ifndef _NGENE_H_ | ||
25 | #define _NGENE_H_ | ||
26 | |||
27 | #include <linux/types.h> | ||
28 | #include <linux/sched.h> | ||
29 | #include <linux/interrupt.h> | ||
30 | #include <linux/i2c.h> | ||
31 | #include <asm/dma.h> | ||
32 | #include <linux/scatterlist.h> | ||
33 | |||
34 | #include <linux/dvb/frontend.h> | ||
35 | |||
36 | #include "dmxdev.h" | ||
37 | #include "dvbdev.h" | ||
38 | #include "dvb_demux.h" | ||
39 | #include "dvb_frontend.h" | ||
40 | #include "dvb_ringbuffer.h" | ||
41 | |||
42 | #define NGENE_VID 0x18c3 | ||
43 | #define NGENE_PID 0x0720 | ||
44 | |||
45 | #ifndef VIDEO_CAP_VC1 | ||
46 | #define VIDEO_CAP_AVC 128 | ||
47 | #define VIDEO_CAP_H264 128 | ||
48 | #define VIDEO_CAP_VC1 256 | ||
49 | #define VIDEO_CAP_WMV9 256 | ||
50 | #define VIDEO_CAP_MPEG4 512 | ||
51 | #endif | ||
52 | |||
53 | enum STREAM { | ||
54 | STREAM_VIDEOIN1 = 0, /* ITU656 or TS Input */ | ||
55 | STREAM_VIDEOIN2, | ||
56 | STREAM_AUDIOIN1, /* I2S or SPI Input */ | ||
57 | STREAM_AUDIOIN2, | ||
58 | STREAM_AUDIOOUT, | ||
59 | MAX_STREAM | ||
60 | }; | ||
61 | |||
62 | enum SMODE_BITS { | ||
63 | SMODE_AUDIO_SPDIF = 0x20, | ||
64 | SMODE_AVSYNC = 0x10, | ||
65 | SMODE_TRANSPORT_STREAM = 0x08, | ||
66 | SMODE_AUDIO_CAPTURE = 0x04, | ||
67 | SMODE_VBI_CAPTURE = 0x02, | ||
68 | SMODE_VIDEO_CAPTURE = 0x01 | ||
69 | }; | ||
70 | |||
71 | enum STREAM_FLAG_BITS { | ||
72 | SFLAG_CHROMA_FORMAT_2COMP = 0x01, /* Chroma Format : 2's complement */ | ||
73 | SFLAG_CHROMA_FORMAT_OFFSET = 0x00, /* Chroma Format : Binary offset */ | ||
74 | SFLAG_ORDER_LUMA_CHROMA = 0x02, /* Byte order: Y,Cb,Y,Cr */ | ||
75 | SFLAG_ORDER_CHROMA_LUMA = 0x00, /* Byte order: Cb,Y,Cr,Y */ | ||
76 | SFLAG_COLORBAR = 0x04, /* Select colorbar */ | ||
77 | }; | ||
78 | |||
79 | #define PROGRAM_ROM 0x0000 | ||
80 | #define PROGRAM_SRAM 0x1000 | ||
81 | #define PERIPHERALS0 0x8000 | ||
82 | #define PERIPHERALS1 0x9000 | ||
83 | #define SHARED_BUFFER 0xC000 | ||
84 | |||
85 | #define HOST_TO_NGENE (SHARED_BUFFER+0x0000) | ||
86 | #define NGENE_TO_HOST (SHARED_BUFFER+0x0100) | ||
87 | #define NGENE_COMMAND (SHARED_BUFFER+0x0200) | ||
88 | #define NGENE_COMMAND_HI (SHARED_BUFFER+0x0204) | ||
89 | #define NGENE_STATUS (SHARED_BUFFER+0x0208) | ||
90 | #define NGENE_STATUS_HI (SHARED_BUFFER+0x020C) | ||
91 | #define NGENE_EVENT (SHARED_BUFFER+0x0210) | ||
92 | #define NGENE_EVENT_HI (SHARED_BUFFER+0x0214) | ||
93 | #define VARIABLES (SHARED_BUFFER+0x0210) | ||
94 | |||
95 | #define NGENE_INT_COUNTS (SHARED_BUFFER+0x0260) | ||
96 | #define NGENE_INT_ENABLE (SHARED_BUFFER+0x0264) | ||
97 | #define NGENE_VBI_LINE_COUNT (SHARED_BUFFER+0x0268) | ||
98 | |||
99 | #define BUFFER_GP_XMIT (SHARED_BUFFER+0x0800) | ||
100 | #define BUFFER_GP_RECV (SHARED_BUFFER+0x0900) | ||
101 | #define EEPROM_AREA (SHARED_BUFFER+0x0A00) | ||
102 | |||
103 | #define SG_V_IN_1 (SHARED_BUFFER+0x0A80) | ||
104 | #define SG_VBI_1 (SHARED_BUFFER+0x0B00) | ||
105 | #define SG_A_IN_1 (SHARED_BUFFER+0x0B80) | ||
106 | #define SG_V_IN_2 (SHARED_BUFFER+0x0C00) | ||
107 | #define SG_VBI_2 (SHARED_BUFFER+0x0C80) | ||
108 | #define SG_A_IN_2 (SHARED_BUFFER+0x0D00) | ||
109 | #define SG_V_OUT (SHARED_BUFFER+0x0D80) | ||
110 | #define SG_A_OUT2 (SHARED_BUFFER+0x0E00) | ||
111 | |||
112 | #define DATA_A_IN_1 (SHARED_BUFFER+0x0E80) | ||
113 | #define DATA_A_IN_2 (SHARED_BUFFER+0x0F00) | ||
114 | #define DATA_A_OUT (SHARED_BUFFER+0x0F80) | ||
115 | #define DATA_V_IN_1 (SHARED_BUFFER+0x1000) | ||
116 | #define DATA_V_IN_2 (SHARED_BUFFER+0x2000) | ||
117 | #define DATA_V_OUT (SHARED_BUFFER+0x3000) | ||
118 | |||
119 | #define DATA_FIFO_AREA (SHARED_BUFFER+0x1000) | ||
120 | |||
121 | #define TIMESTAMPS 0xA000 | ||
122 | #define SCRATCHPAD 0xA080 | ||
123 | #define FORCE_INT 0xA088 | ||
124 | #define FORCE_NMI 0xA090 | ||
125 | #define INT_STATUS 0xA0A0 | ||
126 | |||
127 | #define DEV_VER 0x9004 | ||
128 | |||
129 | #define FW_DEBUG_DEFAULT (PROGRAM_SRAM+0x00FF) | ||
130 | |||
131 | struct SG_ADDR { | ||
132 | u64 start; | ||
133 | u64 curr; | ||
134 | u16 curr_ptr; | ||
135 | u16 elements; | ||
136 | u32 pad[3]; | ||
137 | } __attribute__ ((__packed__)); | ||
138 | |||
139 | struct SHARED_MEMORY { | ||
140 | /* C000 */ | ||
141 | u32 HostToNgene[64]; | ||
142 | |||
143 | /* C100 */ | ||
144 | u32 NgeneToHost[64]; | ||
145 | |||
146 | /* C200 */ | ||
147 | u64 NgeneCommand; | ||
148 | u64 NgeneStatus; | ||
149 | u64 NgeneEvent; | ||
150 | |||
151 | /* C210 */ | ||
152 | u8 pad1[0xc260 - 0xc218]; | ||
153 | |||
154 | /* C260 */ | ||
155 | u32 IntCounts; | ||
156 | u32 IntEnable; | ||
157 | |||
158 | /* C268 */ | ||
159 | u8 pad2[0xd000 - 0xc268]; | ||
160 | |||
161 | } __attribute__ ((__packed__)); | ||
162 | |||
163 | struct BUFFER_STREAM_RESULTS { | ||
164 | u32 Clock; /* Stream time in 100ns units */ | ||
165 | u16 RemainingLines; /* Remaining lines in this field. | ||
166 | 0 for complete field */ | ||
167 | u8 FieldCount; /* Video field number */ | ||
168 | u8 Flags; /* Bit 7 = Done, Bit 6 = seen, Bit 5 = overflow, | ||
169 | Bit 0 = FieldID */ | ||
170 | u16 BlockCount; /* Audio block count (unused) */ | ||
171 | u8 Reserved[2]; | ||
172 | u32 DTOUpdate; | ||
173 | } __attribute__ ((__packed__)); | ||
174 | |||
175 | struct HW_SCATTER_GATHER_ELEMENT { | ||
176 | u64 Address; | ||
177 | u32 Length; | ||
178 | u32 Reserved; | ||
179 | } __attribute__ ((__packed__)); | ||
180 | |||
181 | struct BUFFER_HEADER { | ||
182 | u64 Next; | ||
183 | struct BUFFER_STREAM_RESULTS SR; | ||
184 | |||
185 | u32 Number_of_entries_1; | ||
186 | u32 Reserved5; | ||
187 | u64 Address_of_first_entry_1; | ||
188 | |||
189 | u32 Number_of_entries_2; | ||
190 | u32 Reserved7; | ||
191 | u64 Address_of_first_entry_2; | ||
192 | } __attribute__ ((__packed__)); | ||
193 | |||
194 | struct EVENT_BUFFER { | ||
195 | u32 TimeStamp; | ||
196 | u8 GPIOStatus; | ||
197 | u8 UARTStatus; | ||
198 | u8 RXCharacter; | ||
199 | u8 EventStatus; | ||
200 | u32 Reserved[2]; | ||
201 | } __attribute__ ((__packed__)); | ||
202 | |||
203 | /* Firmware commands. */ | ||
204 | |||
205 | enum OPCODES { | ||
206 | CMD_NOP = 0, | ||
207 | CMD_FWLOAD_PREPARE = 0x01, | ||
208 | CMD_FWLOAD_FINISH = 0x02, | ||
209 | CMD_I2C_READ = 0x03, | ||
210 | CMD_I2C_WRITE = 0x04, | ||
211 | |||
212 | CMD_I2C_WRITE_NOSTOP = 0x05, | ||
213 | CMD_I2C_CONTINUE_WRITE = 0x06, | ||
214 | CMD_I2C_CONTINUE_WRITE_NOSTOP = 0x07, | ||
215 | |||
216 | CMD_DEBUG_OUTPUT = 0x09, | ||
217 | |||
218 | CMD_CONTROL = 0x10, | ||
219 | CMD_CONFIGURE_BUFFER = 0x11, | ||
220 | CMD_CONFIGURE_FREE_BUFFER = 0x12, | ||
221 | |||
222 | CMD_SPI_READ = 0x13, | ||
223 | CMD_SPI_WRITE = 0x14, | ||
224 | |||
225 | CMD_MEM_READ = 0x20, | ||
226 | CMD_MEM_WRITE = 0x21, | ||
227 | CMD_SFR_READ = 0x22, | ||
228 | CMD_SFR_WRITE = 0x23, | ||
229 | CMD_IRAM_READ = 0x24, | ||
230 | CMD_IRAM_WRITE = 0x25, | ||
231 | CMD_SET_GPIO_PIN = 0x26, | ||
232 | CMD_SET_GPIO_INT = 0x27, | ||
233 | CMD_CONFIGURE_UART = 0x28, | ||
234 | CMD_WRITE_UART = 0x29, | ||
235 | MAX_CMD | ||
236 | }; | ||
237 | |||
238 | enum RESPONSES { | ||
239 | OK = 0, | ||
240 | ERROR = 1 | ||
241 | }; | ||
242 | |||
243 | struct FW_HEADER { | ||
244 | u8 Opcode; | ||
245 | u8 Length; | ||
246 | } __attribute__ ((__packed__)); | ||
247 | |||
248 | struct FW_I2C_WRITE { | ||
249 | struct FW_HEADER hdr; | ||
250 | u8 Device; | ||
251 | u8 Data[250]; | ||
252 | } __attribute__ ((__packed__)); | ||
253 | |||
254 | struct FW_I2C_CONTINUE_WRITE { | ||
255 | struct FW_HEADER hdr; | ||
256 | u8 Data[250]; | ||
257 | } __attribute__ ((__packed__)); | ||
258 | |||
259 | struct FW_I2C_READ { | ||
260 | struct FW_HEADER hdr; | ||
261 | u8 Device; | ||
262 | u8 Data[252]; /* followed by two bytes of read data count */ | ||
263 | } __attribute__ ((__packed__)); | ||
264 | |||
265 | struct FW_SPI_WRITE { | ||
266 | struct FW_HEADER hdr; | ||
267 | u8 ModeSelect; | ||
268 | u8 Data[250]; | ||
269 | } __attribute__ ((__packed__)); | ||
270 | |||
271 | struct FW_SPI_READ { | ||
272 | struct FW_HEADER hdr; | ||
273 | u8 ModeSelect; | ||
274 | u8 Data[252]; /* followed by two bytes of read data count */ | ||
275 | } __attribute__ ((__packed__)); | ||
276 | |||
277 | struct FW_FWLOAD_PREPARE { | ||
278 | struct FW_HEADER hdr; | ||
279 | } __attribute__ ((__packed__)); | ||
280 | |||
281 | struct FW_FWLOAD_FINISH { | ||
282 | struct FW_HEADER hdr; | ||
283 | u16 Address; /* address of final block */ | ||
284 | u16 Length; | ||
285 | } __attribute__ ((__packed__)); | ||
286 | |||
287 | /* | ||
288 | * Meaning of FW_STREAM_CONTROL::Mode bits: | ||
289 | * Bit 7: Loopback PEXin to PEXout using TVOut channel | ||
290 | * Bit 6: AVLOOP | ||
291 | * Bit 5: Audio select; 0=I2S, 1=SPDIF | ||
292 | * Bit 4: AVSYNC | ||
293 | * Bit 3: Enable transport stream | ||
294 | * Bit 2: Enable audio capture | ||
295 | * Bit 1: Enable ITU-Video VBI capture | ||
296 | * Bit 0: Enable ITU-Video capture | ||
297 | * | ||
298 | * Meaning of FW_STREAM_CONTROL::Control bits (see UVI1_CTL) | ||
299 | * Bit 7: continuous capture | ||
300 | * Bit 6: capture one field | ||
301 | * Bit 5: capture one frame | ||
302 | * Bit 4: unused | ||
303 | * Bit 3: starting field; 0=odd, 1=even | ||
304 | * Bit 2: sample size; 0=8-bit, 1=10-bit | ||
305 | * Bit 1: data format; 0=UYVY, 1=YUY2 | ||
306 | * Bit 0: resets buffer pointers | ||
307 | */ | ||
308 | |||
309 | enum FSC_MODE_BITS { | ||
310 | SMODE_LOOPBACK = 0x80, | ||
311 | SMODE_AVLOOP = 0x40, | ||
312 | _SMODE_AUDIO_SPDIF = 0x20, | ||
313 | _SMODE_AVSYNC = 0x10, | ||
314 | _SMODE_TRANSPORT_STREAM = 0x08, | ||
315 | _SMODE_AUDIO_CAPTURE = 0x04, | ||
316 | _SMODE_VBI_CAPTURE = 0x02, | ||
317 | _SMODE_VIDEO_CAPTURE = 0x01 | ||
318 | }; | ||
319 | |||
320 | |||
321 | /* Meaning of FW_STREAM_CONTROL::Stream bits: | ||
322 | * Bit 3: Audio sample count: 0 = relative, 1 = absolute | ||
323 | * Bit 2: color bar select; 1=color bars, 0=CV3 decoder | ||
324 | * Bits 1-0: stream select, UVI1, UVI2, TVOUT | ||
325 | */ | ||
326 | |||
327 | struct FW_STREAM_CONTROL { | ||
328 | struct FW_HEADER hdr; | ||
329 | u8 Stream; /* Stream number (UVI1, UVI2, TVOUT) */ | ||
330 | u8 Control; /* Value written to UVI1_CTL */ | ||
331 | u8 Mode; /* Controls clock source */ | ||
332 | u8 SetupDataLen; /* Length of setup data, MSB=1 write | ||
333 | backwards */ | ||
334 | u16 CaptureBlockCount; /* Blocks (a 256 Bytes) to capture per buffer | ||
335 | for TS and Audio */ | ||
336 | u64 Buffer_Address; /* Address of first buffer header */ | ||
337 | u16 BytesPerVideoLine; | ||
338 | u16 MaxLinesPerField; | ||
339 | u16 MinLinesPerField; | ||
340 | u16 Reserved_1; | ||
341 | u16 BytesPerVBILine; | ||
342 | u16 MaxVBILinesPerField; | ||
343 | u16 MinVBILinesPerField; | ||
344 | u16 SetupDataAddr; /* ngene relative address of setup data */ | ||
345 | u8 SetupData[32]; /* setup data */ | ||
346 | } __attribute__((__packed__)); | ||
347 | |||
348 | #define AUDIO_BLOCK_SIZE 256 | ||
349 | #define TS_BLOCK_SIZE 256 | ||
350 | |||
351 | struct FW_MEM_READ { | ||
352 | struct FW_HEADER hdr; | ||
353 | u16 address; | ||
354 | } __attribute__ ((__packed__)); | ||
355 | |||
356 | struct FW_MEM_WRITE { | ||
357 | struct FW_HEADER hdr; | ||
358 | u16 address; | ||
359 | u8 data; | ||
360 | } __attribute__ ((__packed__)); | ||
361 | |||
362 | struct FW_SFR_IRAM_READ { | ||
363 | struct FW_HEADER hdr; | ||
364 | u8 address; | ||
365 | } __attribute__ ((__packed__)); | ||
366 | |||
367 | struct FW_SFR_IRAM_WRITE { | ||
368 | struct FW_HEADER hdr; | ||
369 | u8 address; | ||
370 | u8 data; | ||
371 | } __attribute__ ((__packed__)); | ||
372 | |||
373 | struct FW_SET_GPIO_PIN { | ||
374 | struct FW_HEADER hdr; | ||
375 | u8 select; | ||
376 | } __attribute__ ((__packed__)); | ||
377 | |||
378 | struct FW_SET_GPIO_INT { | ||
379 | struct FW_HEADER hdr; | ||
380 | u8 select; | ||
381 | } __attribute__ ((__packed__)); | ||
382 | |||
383 | struct FW_SET_DEBUGMODE { | ||
384 | struct FW_HEADER hdr; | ||
385 | u8 debug_flags; | ||
386 | } __attribute__ ((__packed__)); | ||
387 | |||
388 | struct FW_CONFIGURE_BUFFERS { | ||
389 | struct FW_HEADER hdr; | ||
390 | u8 config; | ||
391 | } __attribute__ ((__packed__)); | ||
392 | |||
393 | enum _BUFFER_CONFIGS { | ||
394 | /* 4k UVI1, 4k UVI2, 2k AUD1, 2k AUD2 (standard usage) */ | ||
395 | BUFFER_CONFIG_4422 = 0, | ||
396 | /* 3k UVI1, 3k UVI2, 3k AUD1, 3k AUD2 (4x TS input usage) */ | ||
397 | BUFFER_CONFIG_3333 = 1, | ||
398 | /* 8k UVI1, 0k UVI2, 2k AUD1, 2k I2SOut (HDTV decoder usage) */ | ||
399 | BUFFER_CONFIG_8022 = 2, | ||
400 | BUFFER_CONFIG_FW17 = 255, /* Use new FW 17 command */ | ||
401 | }; | ||
402 | |||
403 | struct FW_CONFIGURE_FREE_BUFFERS { | ||
404 | struct FW_HEADER hdr; | ||
405 | u8 UVI1_BufferLength; | ||
406 | u8 UVI2_BufferLength; | ||
407 | u8 TVO_BufferLength; | ||
408 | u8 AUD1_BufferLength; | ||
409 | u8 AUD2_BufferLength; | ||
410 | u8 TVA_BufferLength; | ||
411 | } __attribute__ ((__packed__)); | ||
412 | |||
413 | struct FW_CONFIGURE_UART { | ||
414 | struct FW_HEADER hdr; | ||
415 | u8 UartControl; | ||
416 | } __attribute__ ((__packed__)); | ||
417 | |||
418 | enum _UART_CONFIG { | ||
419 | _UART_BAUDRATE_19200 = 0, | ||
420 | _UART_BAUDRATE_9600 = 1, | ||
421 | _UART_BAUDRATE_4800 = 2, | ||
422 | _UART_BAUDRATE_2400 = 3, | ||
423 | _UART_RX_ENABLE = 0x40, | ||
424 | _UART_TX_ENABLE = 0x80, | ||
425 | }; | ||
426 | |||
427 | struct FW_WRITE_UART { | ||
428 | struct FW_HEADER hdr; | ||
429 | u8 Data[252]; | ||
430 | } __attribute__ ((__packed__)); | ||
431 | |||
432 | |||
433 | struct ngene_command { | ||
434 | u32 in_len; | ||
435 | u32 out_len; | ||
436 | union { | ||
437 | u32 raw[64]; | ||
438 | u8 raw8[256]; | ||
439 | struct FW_HEADER hdr; | ||
440 | struct FW_I2C_WRITE I2CWrite; | ||
441 | struct FW_I2C_CONTINUE_WRITE I2CContinueWrite; | ||
442 | struct FW_I2C_READ I2CRead; | ||
443 | struct FW_STREAM_CONTROL StreamControl; | ||
444 | struct FW_FWLOAD_PREPARE FWLoadPrepare; | ||
445 | struct FW_FWLOAD_FINISH FWLoadFinish; | ||
446 | struct FW_MEM_READ MemoryRead; | ||
447 | struct FW_MEM_WRITE MemoryWrite; | ||
448 | struct FW_SFR_IRAM_READ SfrIramRead; | ||
449 | struct FW_SFR_IRAM_WRITE SfrIramWrite; | ||
450 | struct FW_SPI_WRITE SPIWrite; | ||
451 | struct FW_SPI_READ SPIRead; | ||
452 | struct FW_SET_GPIO_PIN SetGpioPin; | ||
453 | struct FW_SET_GPIO_INT SetGpioInt; | ||
454 | struct FW_SET_DEBUGMODE SetDebugMode; | ||
455 | struct FW_CONFIGURE_BUFFERS ConfigureBuffers; | ||
456 | struct FW_CONFIGURE_FREE_BUFFERS ConfigureFreeBuffers; | ||
457 | struct FW_CONFIGURE_UART ConfigureUart; | ||
458 | struct FW_WRITE_UART WriteUart; | ||
459 | } cmd; | ||
460 | } __attribute__ ((__packed__)); | ||
461 | |||
462 | #define NGENE_INTERFACE_VERSION 0x103 | ||
463 | #define MAX_VIDEO_BUFFER_SIZE (417792) /* 288*1440 rounded up to next page */ | ||
464 | #define MAX_AUDIO_BUFFER_SIZE (8192) /* Gives room for about 23msec@48KHz */ | ||
465 | #define MAX_VBI_BUFFER_SIZE (28672) /* 1144*18 rounded up to next page */ | ||
466 | #define MAX_TS_BUFFER_SIZE (98304) /* 512*188 rounded up to next page */ | ||
467 | #define MAX_HDTV_BUFFER_SIZE (2080768) /* 541*1920*2 rounded up to next page | ||
468 | Max: (1920x1080i60) */ | ||
469 | |||
470 | #define OVERFLOW_BUFFER_SIZE (8192) | ||
471 | |||
472 | #define RING_SIZE_VIDEO 4 | ||
473 | #define RING_SIZE_AUDIO 8 | ||
474 | #define RING_SIZE_TS 8 | ||
475 | |||
476 | #define NUM_SCATTER_GATHER_ENTRIES 8 | ||
477 | |||
478 | #define MAX_DMA_LENGTH (((MAX_VIDEO_BUFFER_SIZE + MAX_VBI_BUFFER_SIZE) * \ | ||
479 | RING_SIZE_VIDEO * 2) + \ | ||
480 | (MAX_AUDIO_BUFFER_SIZE * RING_SIZE_AUDIO * 2) + \ | ||
481 | (MAX_TS_BUFFER_SIZE * RING_SIZE_TS * 4) + \ | ||
482 | (RING_SIZE_VIDEO * PAGE_SIZE * 2) + \ | ||
483 | (RING_SIZE_AUDIO * PAGE_SIZE * 2) + \ | ||
484 | (RING_SIZE_TS * PAGE_SIZE * 4) + \ | ||
485 | 8 * PAGE_SIZE + OVERFLOW_BUFFER_SIZE + PAGE_SIZE) | ||
486 | |||
487 | #define EVENT_QUEUE_SIZE 16 | ||
488 | |||
489 | /* Gathers the current state of a single channel. */ | ||
490 | |||
491 | struct SBufferHeader { | ||
492 | struct BUFFER_HEADER ngeneBuffer; /* Physical descriptor */ | ||
493 | struct SBufferHeader *Next; | ||
494 | void *Buffer1; | ||
495 | struct HW_SCATTER_GATHER_ELEMENT *scList1; | ||
496 | void *Buffer2; | ||
497 | struct HW_SCATTER_GATHER_ELEMENT *scList2; | ||
498 | }; | ||
499 | |||
500 | /* Sizeof SBufferHeader aligned to next 64 Bit boundary (hw restriction) */ | ||
501 | #define SIZEOF_SBufferHeader ((sizeof(struct SBufferHeader) + 63) & ~63) | ||
502 | |||
503 | enum HWSTATE { | ||
504 | HWSTATE_STOP, | ||
505 | HWSTATE_STARTUP, | ||
506 | HWSTATE_RUN, | ||
507 | HWSTATE_PAUSE, | ||
508 | }; | ||
509 | |||
510 | enum KSSTATE { | ||
511 | KSSTATE_STOP, | ||
512 | KSSTATE_ACQUIRE, | ||
513 | KSSTATE_PAUSE, | ||
514 | KSSTATE_RUN, | ||
515 | }; | ||
516 | |||
517 | struct SRingBufferDescriptor { | ||
518 | struct SBufferHeader *Head; /* Points to first buffer in ring buffer | ||
519 | structure*/ | ||
520 | u64 PAHead; /* Physical address of first buffer */ | ||
521 | u32 MemSize; /* Memory size of allocated ring buffers | ||
522 | (needed for freeing) */ | ||
523 | u32 NumBuffers; /* Number of buffers in the ring */ | ||
524 | u32 Buffer1Length; /* Allocated length of Buffer 1 */ | ||
525 | u32 Buffer2Length; /* Allocated length of Buffer 2 */ | ||
526 | void *SCListMem; /* Memory to hold scatter gather lists for this | ||
527 | ring */ | ||
528 | u64 PASCListMem; /* Physical address .. */ | ||
529 | u32 SCListMemSize; /* Size of this memory */ | ||
530 | }; | ||
531 | |||
532 | enum STREAMMODEFLAGS { | ||
533 | StreamMode_NONE = 0, /* Stream not used */ | ||
534 | StreamMode_ANALOG = 1, /* Analog: Stream 0,1 = Video, 2,3 = Audio */ | ||
535 | StreamMode_TSIN = 2, /* Transport stream input (all) */ | ||
536 | StreamMode_HDTV = 4, /* HDTV: Maximum 1920x1080p30,1920x1080i60 | ||
537 | (only stream 0) */ | ||
538 | StreamMode_TSOUT = 8, /* Transport stream output (only stream 3) */ | ||
539 | }; | ||
540 | |||
541 | |||
542 | enum BufferExchangeFlags { | ||
543 | BEF_EVEN_FIELD = 0x00000001, | ||
544 | BEF_CONTINUATION = 0x00000002, | ||
545 | BEF_MORE_DATA = 0x00000004, | ||
546 | BEF_OVERFLOW = 0x00000008, | ||
547 | DF_SWAP32 = 0x00010000, | ||
548 | }; | ||
549 | |||
550 | typedef void *(IBufferExchange)(void *, void *, u32, u32, u32); | ||
551 | |||
552 | struct MICI_STREAMINFO { | ||
553 | IBufferExchange *pExchange; | ||
554 | IBufferExchange *pExchangeVBI; /* Secondary (VBI, ancillary) */ | ||
555 | u8 Stream; | ||
556 | u8 Flags; | ||
557 | u8 Mode; | ||
558 | u8 Reserved; | ||
559 | u16 nLinesVideo; | ||
560 | u16 nBytesPerLineVideo; | ||
561 | u16 nLinesVBI; | ||
562 | u16 nBytesPerLineVBI; | ||
563 | u32 CaptureLength; /* Used for audio and transport stream */ | ||
564 | }; | ||
565 | |||
566 | /****************************************************************************/ | ||
567 | /* STRUCTS ******************************************************************/ | ||
568 | /****************************************************************************/ | ||
569 | |||
570 | /* sound hardware definition */ | ||
571 | #define MIXER_ADDR_TVTUNER 0 | ||
572 | #define MIXER_ADDR_LAST 0 | ||
573 | |||
574 | struct ngene_channel; | ||
575 | |||
576 | /*struct sound chip*/ | ||
577 | |||
578 | struct mychip { | ||
579 | struct ngene_channel *chan; | ||
580 | struct snd_card *card; | ||
581 | struct pci_dev *pci; | ||
582 | struct snd_pcm_substream *substream; | ||
583 | struct snd_pcm *pcm; | ||
584 | unsigned long port; | ||
585 | int irq; | ||
586 | spinlock_t mixer_lock; | ||
587 | spinlock_t lock; | ||
588 | int mixer_volume[MIXER_ADDR_LAST + 1][2]; | ||
589 | int capture_source[MIXER_ADDR_LAST + 1][2]; | ||
590 | }; | ||
591 | |||
592 | #ifdef NGENE_V4L | ||
593 | struct ngene_overlay { | ||
594 | int tvnorm; | ||
595 | struct v4l2_rect w; | ||
596 | enum v4l2_field field; | ||
597 | struct v4l2_clip *clips; | ||
598 | int nclips; | ||
599 | int setup_ok; | ||
600 | }; | ||
601 | |||
602 | struct ngene_tvnorm { | ||
603 | int v4l2_id; | ||
604 | char *name; | ||
605 | u16 swidth, sheight; /* scaled standard width, height */ | ||
606 | int tuner_norm; | ||
607 | int soundstd; | ||
608 | }; | ||
609 | |||
610 | struct ngene_vopen { | ||
611 | struct ngene_channel *ch; | ||
612 | enum v4l2_priority prio; | ||
613 | int width; | ||
614 | int height; | ||
615 | int depth; | ||
616 | struct videobuf_queue vbuf_q; | ||
617 | struct videobuf_queue vbi; | ||
618 | int fourcc; | ||
619 | int picxcount; | ||
620 | int resources; | ||
621 | enum v4l2_buf_type type; | ||
622 | const struct ngene_format *fmt; | ||
623 | |||
624 | const struct ngene_format *ovfmt; | ||
625 | struct ngene_overlay ov; | ||
626 | }; | ||
627 | #endif | ||
628 | |||
629 | struct ngene_channel { | ||
630 | struct device device; | ||
631 | struct i2c_adapter i2c_adapter; | ||
632 | |||
633 | struct ngene *dev; | ||
634 | int number; | ||
635 | int type; | ||
636 | int mode; | ||
637 | |||
638 | struct dvb_frontend *fe; | ||
639 | struct dmxdev dmxdev; | ||
640 | struct dvb_demux demux; | ||
641 | struct dmx_frontend hw_frontend; | ||
642 | struct dmx_frontend mem_frontend; | ||
643 | int users; | ||
644 | struct video_device *v4l_dev; | ||
645 | struct tasklet_struct demux_tasklet; | ||
646 | |||
647 | struct SBufferHeader *nextBuffer; | ||
648 | enum KSSTATE State; | ||
649 | enum HWSTATE HWState; | ||
650 | u8 Stream; | ||
651 | u8 Flags; | ||
652 | u8 Mode; | ||
653 | IBufferExchange *pBufferExchange; | ||
654 | IBufferExchange *pBufferExchange2; | ||
655 | |||
656 | spinlock_t state_lock; | ||
657 | u16 nLines; | ||
658 | u16 nBytesPerLine; | ||
659 | u16 nVBILines; | ||
660 | u16 nBytesPerVBILine; | ||
661 | u16 itumode; | ||
662 | u32 Capture1Length; | ||
663 | u32 Capture2Length; | ||
664 | struct SRingBufferDescriptor RingBuffer; | ||
665 | struct SRingBufferDescriptor TSRingBuffer; | ||
666 | struct SRingBufferDescriptor TSIdleBuffer; | ||
667 | |||
668 | u32 DataFormatFlags; | ||
669 | |||
670 | int AudioDTOUpdated; | ||
671 | u32 AudioDTOValue; | ||
672 | |||
673 | int (*set_tone)(struct dvb_frontend *, fe_sec_tone_mode_t); | ||
674 | u8 lnbh; | ||
675 | |||
676 | /* stuff from analog driver */ | ||
677 | |||
678 | int minor; | ||
679 | struct mychip *mychip; | ||
680 | struct snd_card *soundcard; | ||
681 | u8 *evenbuffer; | ||
682 | u8 dma_on; | ||
683 | int soundstreamon; | ||
684 | int audiomute; | ||
685 | int soundbuffisallocated; | ||
686 | int sndbuffflag; | ||
687 | int tun_rdy; | ||
688 | int dec_rdy; | ||
689 | int tun_dec_rdy; | ||
690 | int lastbufferflag; | ||
691 | |||
692 | struct ngene_tvnorm *tvnorms; | ||
693 | int tvnorm_num; | ||
694 | int tvnorm; | ||
695 | |||
696 | #ifdef NGENE_V4L | ||
697 | int videousers; | ||
698 | struct v4l2_prio_state prio; | ||
699 | struct ngene_vopen init; | ||
700 | int resources; | ||
701 | struct v4l2_framebuffer fbuf; | ||
702 | struct ngene_buffer *screen; /* overlay */ | ||
703 | struct list_head capture; /* video capture queue */ | ||
704 | spinlock_t s_lock; | ||
705 | struct semaphore reslock; | ||
706 | #endif | ||
707 | |||
708 | int running; | ||
709 | }; | ||
710 | |||
711 | struct ngene; | ||
712 | |||
713 | typedef void (rx_cb_t)(struct ngene *, u32, u8); | ||
714 | typedef void (tx_cb_t)(struct ngene *, u32); | ||
715 | |||
716 | struct ngene { | ||
717 | int nr; | ||
718 | struct pci_dev *pci_dev; | ||
719 | unsigned char *iomem; | ||
720 | |||
721 | /*struct i2c_adapter i2c_adapter;*/ | ||
722 | |||
723 | u32 device_version; | ||
724 | u32 fw_interface_version; | ||
725 | u32 icounts; | ||
726 | |||
727 | u8 *CmdDoneByte; | ||
728 | int BootFirmware; | ||
729 | void *OverflowBuffer; | ||
730 | dma_addr_t PAOverflowBuffer; | ||
731 | void *FWInterfaceBuffer; | ||
732 | dma_addr_t PAFWInterfaceBuffer; | ||
733 | u8 *ngenetohost; | ||
734 | u8 *hosttongene; | ||
735 | |||
736 | struct EVENT_BUFFER EventQueue[EVENT_QUEUE_SIZE]; | ||
737 | int EventQueueOverflowCount; | ||
738 | int EventQueueOverflowFlag; | ||
739 | struct tasklet_struct event_tasklet; | ||
740 | struct EVENT_BUFFER *EventBuffer; | ||
741 | int EventQueueWriteIndex; | ||
742 | int EventQueueReadIndex; | ||
743 | |||
744 | wait_queue_head_t cmd_wq; | ||
745 | int cmd_done; | ||
746 | struct semaphore cmd_mutex; | ||
747 | struct semaphore stream_mutex; | ||
748 | struct semaphore pll_mutex; | ||
749 | struct semaphore i2c_switch_mutex; | ||
750 | int i2c_current_channel; | ||
751 | int i2c_current_bus; | ||
752 | spinlock_t cmd_lock; | ||
753 | |||
754 | struct dvb_adapter adapter[MAX_STREAM]; | ||
755 | struct ngene_channel channel[MAX_STREAM]; | ||
756 | |||
757 | struct ngene_info *card_info; | ||
758 | |||
759 | tx_cb_t *TxEventNotify; | ||
760 | rx_cb_t *RxEventNotify; | ||
761 | int tx_busy; | ||
762 | wait_queue_head_t tx_wq; | ||
763 | wait_queue_head_t rx_wq; | ||
764 | #define UART_RBUF_LEN 4096 | ||
765 | u8 uart_rbuf[UART_RBUF_LEN]; | ||
766 | int uart_rp, uart_wp; | ||
767 | |||
768 | u8 *tsout_buf; | ||
769 | #define TSOUT_BUF_SIZE (512*188*8) | ||
770 | struct dvb_ringbuffer tsout_rbuf; | ||
771 | |||
772 | u8 *ain_buf; | ||
773 | #define AIN_BUF_SIZE (128*1024) | ||
774 | struct dvb_ringbuffer ain_rbuf; | ||
775 | |||
776 | |||
777 | u8 *vin_buf; | ||
778 | #define VIN_BUF_SIZE (4*1920*1080) | ||
779 | struct dvb_ringbuffer vin_rbuf; | ||
780 | |||
781 | unsigned long exp_val; | ||
782 | int prev_cmd; | ||
783 | }; | ||
784 | |||
785 | struct ngene_info { | ||
786 | int type; | ||
787 | #define NGENE_APP 0 | ||
788 | #define NGENE_TERRATEC 1 | ||
789 | #define NGENE_SIDEWINDER 2 | ||
790 | #define NGENE_RACER 3 | ||
791 | #define NGENE_VIPER 4 | ||
792 | #define NGENE_PYTHON 5 | ||
793 | #define NGENE_VBOX_V1 6 | ||
794 | #define NGENE_VBOX_V2 7 | ||
795 | |||
796 | int fw_version; | ||
797 | char *name; | ||
798 | |||
799 | int io_type[MAX_STREAM]; | ||
800 | #define NGENE_IO_NONE 0 | ||
801 | #define NGENE_IO_TV 1 | ||
802 | #define NGENE_IO_HDTV 2 | ||
803 | #define NGENE_IO_TSIN 4 | ||
804 | #define NGENE_IO_TSOUT 8 | ||
805 | #define NGENE_IO_AIN 16 | ||
806 | |||
807 | void *fe_config[4]; | ||
808 | void *tuner_config[4]; | ||
809 | |||
810 | int (*demod_attach[4])(struct ngene_channel *); | ||
811 | int (*tuner_attach[4])(struct ngene_channel *); | ||
812 | |||
813 | u8 avf[4]; | ||
814 | u8 msp[4]; | ||
815 | u8 demoda[4]; | ||
816 | u8 lnb[4]; | ||
817 | int i2c_access; | ||
818 | u8 ntsc; | ||
819 | u8 tsf[4]; | ||
820 | u8 i2s[4]; | ||
821 | |||
822 | int (*gate_ctrl)(struct dvb_frontend *, int); | ||
823 | int (*switch_ctrl)(struct ngene_channel *, int, int); | ||
824 | }; | ||
825 | |||
826 | #ifdef NGENE_V4L | ||
827 | struct ngene_format{ | ||
828 | char *name; | ||
829 | int fourcc; /* video4linux 2 */ | ||
830 | int btformat; /* BT848_COLOR_FMT_* */ | ||
831 | int format; | ||
832 | int btswap; /* BT848_COLOR_CTL_* */ | ||
833 | int depth; /* bit/pixel */ | ||
834 | int flags; | ||
835 | int hshift, vshift; /* for planar modes */ | ||
836 | int palette; | ||
837 | }; | ||
838 | |||
839 | #define RESOURCE_OVERLAY 1 | ||
840 | #define RESOURCE_VIDEO 2 | ||
841 | #define RESOURCE_VBI 4 | ||
842 | |||
843 | struct ngene_buffer { | ||
844 | /* common v4l buffer stuff -- must be first */ | ||
845 | struct videobuf_buffer vb; | ||
846 | |||
847 | /* ngene specific */ | ||
848 | const struct ngene_format *fmt; | ||
849 | int tvnorm; | ||
850 | int btformat; | ||
851 | int btswap; | ||
852 | }; | ||
853 | #endif | ||
854 | |||
855 | |||
856 | #endif | ||
857 | |||
858 | /* LocalWords: Endif | ||
859 | */ | ||
diff --git a/drivers/media/dvb/siano/sms-cards.c b/drivers/media/dvb/siano/sms-cards.c index 1067b22eb0c6..cff77e2eb557 100644 --- a/drivers/media/dvb/siano/sms-cards.c +++ b/drivers/media/dvb/siano/sms-cards.c | |||
@@ -62,6 +62,7 @@ static struct sms_board sms_boards[] = { | |||
62 | [SMS1XXX_BOARD_HAUPPAUGE_WINDHAM] = { | 62 | [SMS1XXX_BOARD_HAUPPAUGE_WINDHAM] = { |
63 | .name = "Hauppauge WinTV MiniStick", | 63 | .name = "Hauppauge WinTV MiniStick", |
64 | .type = SMS_NOVA_B0, | 64 | .type = SMS_NOVA_B0, |
65 | .fw[DEVICE_MODE_ISDBT_BDA] = "sms1xxx-hcw-55xxx-isdbt-02.fw", | ||
65 | .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw", | 66 | .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw", |
66 | .board_cfg.leds_power = 26, | 67 | .board_cfg.leds_power = 26, |
67 | .board_cfg.led0 = 27, | 68 | .board_cfg.led0 = 27, |
diff --git a/drivers/media/dvb/siano/smscoreapi.c b/drivers/media/dvb/siano/smscoreapi.c index ca758bcb48c9..4bfd3451b568 100644 --- a/drivers/media/dvb/siano/smscoreapi.c +++ b/drivers/media/dvb/siano/smscoreapi.c | |||
@@ -1459,8 +1459,10 @@ int smscore_gpio_configure(struct smscore_device_t *coredev, u8 PinNum, | |||
1459 | if (!(coredev->device_flags & SMS_DEVICE_FAMILY2)) { | 1459 | if (!(coredev->device_flags & SMS_DEVICE_FAMILY2)) { |
1460 | pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_CONFIG_REQ; | 1460 | pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_CONFIG_REQ; |
1461 | if (GetGpioPinParams(PinNum, &TranslatedPinNum, &GroupNum, | 1461 | if (GetGpioPinParams(PinNum, &TranslatedPinNum, &GroupNum, |
1462 | &groupCfg) != 0) | 1462 | &groupCfg) != 0) { |
1463 | return -EINVAL; | 1463 | rc = -EINVAL; |
1464 | goto free; | ||
1465 | } | ||
1464 | 1466 | ||
1465 | pMsg->msgData[1] = TranslatedPinNum; | 1467 | pMsg->msgData[1] = TranslatedPinNum; |
1466 | pMsg->msgData[2] = GroupNum; | 1468 | pMsg->msgData[2] = GroupNum; |
@@ -1490,6 +1492,7 @@ int smscore_gpio_configure(struct smscore_device_t *coredev, u8 PinNum, | |||
1490 | else | 1492 | else |
1491 | sms_err("smscore_gpio_configure error"); | 1493 | sms_err("smscore_gpio_configure error"); |
1492 | } | 1494 | } |
1495 | free: | ||
1493 | kfree(buffer); | 1496 | kfree(buffer); |
1494 | 1497 | ||
1495 | return rc; | 1498 | return rc; |
diff --git a/drivers/media/dvb/siano/smscoreapi.h b/drivers/media/dvb/siano/smscoreapi.h index eec18aaf5512..8ecadecaa9d0 100644 --- a/drivers/media/dvb/siano/smscoreapi.h +++ b/drivers/media/dvb/siano/smscoreapi.h | |||
@@ -212,6 +212,8 @@ struct smscore_device_t { | |||
212 | #define MSG_SMS_DAB_CHANNEL 607 | 212 | #define MSG_SMS_DAB_CHANNEL 607 |
213 | #define MSG_SMS_GET_PID_FILTER_LIST_REQ 608 | 213 | #define MSG_SMS_GET_PID_FILTER_LIST_REQ 608 |
214 | #define MSG_SMS_GET_PID_FILTER_LIST_RES 609 | 214 | #define MSG_SMS_GET_PID_FILTER_LIST_RES 609 |
215 | #define MSG_SMS_GET_STATISTICS_RES 616 | ||
216 | #define MSG_SMS_GET_STATISTICS_REQ 615 | ||
215 | #define MSG_SMS_HO_PER_SLICES_IND 630 | 217 | #define MSG_SMS_HO_PER_SLICES_IND 630 |
216 | #define MSG_SMS_SET_ANTENNA_CONFIG_REQ 651 | 218 | #define MSG_SMS_SET_ANTENNA_CONFIG_REQ 651 |
217 | #define MSG_SMS_SET_ANTENNA_CONFIG_RES 652 | 219 | #define MSG_SMS_SET_ANTENNA_CONFIG_RES 652 |
@@ -339,7 +341,7 @@ struct SmsFirmware_ST { | |||
339 | 341 | ||
340 | /* Statistics information returned as response for | 342 | /* Statistics information returned as response for |
341 | * SmsHostApiGetStatistics_Req */ | 343 | * SmsHostApiGetStatistics_Req */ |
342 | struct SMSHOSTLIB_STATISTICS_S { | 344 | struct SMSHOSTLIB_STATISTICS_ST { |
343 | u32 Reserved; /* Reserved */ | 345 | u32 Reserved; /* Reserved */ |
344 | 346 | ||
345 | /* Common parameters */ | 347 | /* Common parameters */ |
@@ -424,6 +426,79 @@ struct SMSHOSTLIB_STATISTICS_S { | |||
424 | u32 ReservedFields[10]; /* Reserved */ | 426 | u32 ReservedFields[10]; /* Reserved */ |
425 | }; | 427 | }; |
426 | 428 | ||
429 | struct SmsMsgStatisticsInfo_ST { | ||
430 | u32 RequestResult; | ||
431 | |||
432 | struct SMSHOSTLIB_STATISTICS_ST Stat; | ||
433 | |||
434 | /* Split the calc of the SNR in DAB */ | ||
435 | u32 Signal; /* dB */ | ||
436 | u32 Noise; /* dB */ | ||
437 | |||
438 | }; | ||
439 | |||
440 | struct SMSHOSTLIB_ISDBT_LAYER_STAT_ST { | ||
441 | /* Per-layer information */ | ||
442 | u32 CodeRate; /* Code Rate from SMSHOSTLIB_CODE_RATE_ET, | ||
443 | * 255 means layer does not exist */ | ||
444 | u32 Constellation; /* Constellation from SMSHOSTLIB_CONSTELLATION_ET, | ||
445 | * 255 means layer does not exist */ | ||
446 | u32 BER; /* Post Viterbi BER [1E-5], 0xFFFFFFFF indicate N/A */ | ||
447 | u32 BERErrorCount; /* Post Viterbi Error Bits Count */ | ||
448 | u32 BERBitCount; /* Post Viterbi Total Bits Count */ | ||
449 | u32 PreBER; /* Pre Viterbi BER [1E-5], 0xFFFFFFFF indicate N/A */ | ||
450 | u32 TS_PER; /* Transport stream PER [%], 0xFFFFFFFF indicate N/A */ | ||
451 | u32 ErrorTSPackets; /* Number of erroneous transport-stream packets */ | ||
452 | u32 TotalTSPackets; /* Total number of transport-stream packets */ | ||
453 | u32 TILdepthI; /* Time interleaver depth I parameter, | ||
454 | * 255 means layer does not exist */ | ||
455 | u32 NumberOfSegments; /* Number of segments in layer A, | ||
456 | * 255 means layer does not exist */ | ||
457 | u32 TMCCErrors; /* TMCC errors */ | ||
458 | }; | ||
459 | |||
460 | struct SMSHOSTLIB_STATISTICS_ISDBT_ST { | ||
461 | u32 StatisticsType; /* Enumerator identifying the type of the | ||
462 | * structure. Values are the same as | ||
463 | * SMSHOSTLIB_DEVICE_MODES_E | ||
464 | * | ||
465 | * This field MUST always be first in any | ||
466 | * statistics structure */ | ||
467 | |||
468 | u32 FullSize; /* Total size of the structure returned by the modem. | ||
469 | * If the size requested by the host is smaller than | ||
470 | * FullSize, the struct will be truncated */ | ||
471 | |||
472 | /* Common parameters */ | ||
473 | u32 IsRfLocked; /* 0 - not locked, 1 - locked */ | ||
474 | u32 IsDemodLocked; /* 0 - not locked, 1 - locked */ | ||
475 | u32 IsExternalLNAOn; /* 0 - external LNA off, 1 - external LNA on */ | ||
476 | |||
477 | /* Reception quality */ | ||
478 | s32 SNR; /* dB */ | ||
479 | s32 RSSI; /* dBm */ | ||
480 | s32 InBandPwr; /* In band power in dBM */ | ||
481 | s32 CarrierOffset; /* Carrier Offset in Hz */ | ||
482 | |||
483 | /* Transmission parameters */ | ||
484 | u32 Frequency; /* Frequency in Hz */ | ||
485 | u32 Bandwidth; /* Bandwidth in MHz */ | ||
486 | u32 TransmissionMode; /* ISDB-T transmission mode */ | ||
487 | u32 ModemState; /* 0 - Acquisition, 1 - Locked */ | ||
488 | u32 GuardInterval; /* Guard Interval, 1 divided by value */ | ||
489 | u32 SystemType; /* ISDB-T system type (ISDB-T / ISDB-Tsb) */ | ||
490 | u32 PartialReception; /* TRUE - partial reception, FALSE otherwise */ | ||
491 | u32 NumOfLayers; /* Number of ISDB-T layers in the network */ | ||
492 | |||
493 | /* Per-layer information */ | ||
494 | /* Layers A, B and C */ | ||
495 | struct SMSHOSTLIB_ISDBT_LAYER_STAT_ST LayerInfo[3]; | ||
496 | /* Per-layer statistics, see SMSHOSTLIB_ISDBT_LAYER_STAT_ST */ | ||
497 | |||
498 | /* Interface information */ | ||
499 | u32 SmsToHostTxErrors; /* Total number of transmission errors. */ | ||
500 | }; | ||
501 | |||
427 | struct PID_STATISTICS_DATA_S { | 502 | struct PID_STATISTICS_DATA_S { |
428 | struct PID_BURST_S { | 503 | struct PID_BURST_S { |
429 | u32 size; | 504 | u32 size; |
diff --git a/drivers/media/dvb/siano/smsdvb.c b/drivers/media/dvb/siano/smsdvb.c index 68bf9fbd8fed..5f3939821ca3 100644 --- a/drivers/media/dvb/siano/smsdvb.c +++ b/drivers/media/dvb/siano/smsdvb.c | |||
@@ -116,6 +116,118 @@ static void sms_board_dvb3_event(struct smsdvb_client_t *client, | |||
116 | } | 116 | } |
117 | } | 117 | } |
118 | 118 | ||
119 | |||
120 | static void smsdvb_update_dvb_stats(struct RECEPTION_STATISTICS_S *pReceptionData, | ||
121 | struct SMSHOSTLIB_STATISTICS_ST *p) | ||
122 | { | ||
123 | if (sms_dbg & 2) { | ||
124 | printk(KERN_DEBUG "Reserved = %d", p->Reserved); | ||
125 | printk(KERN_DEBUG "IsRfLocked = %d", p->IsRfLocked); | ||
126 | printk(KERN_DEBUG "IsDemodLocked = %d", p->IsDemodLocked); | ||
127 | printk(KERN_DEBUG "IsExternalLNAOn = %d", p->IsExternalLNAOn); | ||
128 | printk(KERN_DEBUG "SNR = %d", p->SNR); | ||
129 | printk(KERN_DEBUG "BER = %d", p->BER); | ||
130 | printk(KERN_DEBUG "FIB_CRC = %d", p->FIB_CRC); | ||
131 | printk(KERN_DEBUG "TS_PER = %d", p->TS_PER); | ||
132 | printk(KERN_DEBUG "MFER = %d", p->MFER); | ||
133 | printk(KERN_DEBUG "RSSI = %d", p->RSSI); | ||
134 | printk(KERN_DEBUG "InBandPwr = %d", p->InBandPwr); | ||
135 | printk(KERN_DEBUG "CarrierOffset = %d", p->CarrierOffset); | ||
136 | printk(KERN_DEBUG "Frequency = %d", p->Frequency); | ||
137 | printk(KERN_DEBUG "Bandwidth = %d", p->Bandwidth); | ||
138 | printk(KERN_DEBUG "TransmissionMode = %d", p->TransmissionMode); | ||
139 | printk(KERN_DEBUG "ModemState = %d", p->ModemState); | ||
140 | printk(KERN_DEBUG "GuardInterval = %d", p->GuardInterval); | ||
141 | printk(KERN_DEBUG "CodeRate = %d", p->CodeRate); | ||
142 | printk(KERN_DEBUG "LPCodeRate = %d", p->LPCodeRate); | ||
143 | printk(KERN_DEBUG "Hierarchy = %d", p->Hierarchy); | ||
144 | printk(KERN_DEBUG "Constellation = %d", p->Constellation); | ||
145 | printk(KERN_DEBUG "BurstSize = %d", p->BurstSize); | ||
146 | printk(KERN_DEBUG "BurstDuration = %d", p->BurstDuration); | ||
147 | printk(KERN_DEBUG "BurstCycleTime = %d", p->BurstCycleTime); | ||
148 | printk(KERN_DEBUG "CalculatedBurstCycleTime = %d", p->CalculatedBurstCycleTime); | ||
149 | printk(KERN_DEBUG "NumOfRows = %d", p->NumOfRows); | ||
150 | printk(KERN_DEBUG "NumOfPaddCols = %d", p->NumOfPaddCols); | ||
151 | printk(KERN_DEBUG "NumOfPunctCols = %d", p->NumOfPunctCols); | ||
152 | printk(KERN_DEBUG "ErrorTSPackets = %d", p->ErrorTSPackets); | ||
153 | printk(KERN_DEBUG "TotalTSPackets = %d", p->TotalTSPackets); | ||
154 | printk(KERN_DEBUG "NumOfValidMpeTlbs = %d", p->NumOfValidMpeTlbs); | ||
155 | printk(KERN_DEBUG "NumOfInvalidMpeTlbs = %d", p->NumOfInvalidMpeTlbs); | ||
156 | printk(KERN_DEBUG "NumOfCorrectedMpeTlbs = %d", p->NumOfCorrectedMpeTlbs); | ||
157 | printk(KERN_DEBUG "BERErrorCount = %d", p->BERErrorCount); | ||
158 | printk(KERN_DEBUG "BERBitCount = %d", p->BERBitCount); | ||
159 | printk(KERN_DEBUG "SmsToHostTxErrors = %d", p->SmsToHostTxErrors); | ||
160 | printk(KERN_DEBUG "PreBER = %d", p->PreBER); | ||
161 | printk(KERN_DEBUG "CellId = %d", p->CellId); | ||
162 | printk(KERN_DEBUG "DvbhSrvIndHP = %d", p->DvbhSrvIndHP); | ||
163 | printk(KERN_DEBUG "DvbhSrvIndLP = %d", p->DvbhSrvIndLP); | ||
164 | printk(KERN_DEBUG "NumMPEReceived = %d", p->NumMPEReceived); | ||
165 | } | ||
166 | |||
167 | pReceptionData->IsDemodLocked = p->IsDemodLocked; | ||
168 | |||
169 | pReceptionData->SNR = p->SNR; | ||
170 | pReceptionData->BER = p->BER; | ||
171 | pReceptionData->BERErrorCount = p->BERErrorCount; | ||
172 | pReceptionData->InBandPwr = p->InBandPwr; | ||
173 | pReceptionData->ErrorTSPackets = p->ErrorTSPackets; | ||
174 | }; | ||
175 | |||
176 | |||
177 | static void smsdvb_update_isdbt_stats(struct RECEPTION_STATISTICS_S *pReceptionData, | ||
178 | struct SMSHOSTLIB_STATISTICS_ISDBT_ST *p) | ||
179 | { | ||
180 | int i; | ||
181 | |||
182 | if (sms_dbg & 2) { | ||
183 | printk(KERN_DEBUG "IsRfLocked = %d", p->IsRfLocked); | ||
184 | printk(KERN_DEBUG "IsDemodLocked = %d", p->IsDemodLocked); | ||
185 | printk(KERN_DEBUG "IsExternalLNAOn = %d", p->IsExternalLNAOn); | ||
186 | printk(KERN_DEBUG "SNR = %d", p->SNR); | ||
187 | printk(KERN_DEBUG "RSSI = %d", p->RSSI); | ||
188 | printk(KERN_DEBUG "InBandPwr = %d", p->InBandPwr); | ||
189 | printk(KERN_DEBUG "CarrierOffset = %d", p->CarrierOffset); | ||
190 | printk(KERN_DEBUG "Frequency = %d", p->Frequency); | ||
191 | printk(KERN_DEBUG "Bandwidth = %d", p->Bandwidth); | ||
192 | printk(KERN_DEBUG "TransmissionMode = %d", p->TransmissionMode); | ||
193 | printk(KERN_DEBUG "ModemState = %d", p->ModemState); | ||
194 | printk(KERN_DEBUG "GuardInterval = %d", p->GuardInterval); | ||
195 | printk(KERN_DEBUG "SystemType = %d", p->SystemType); | ||
196 | printk(KERN_DEBUG "PartialReception = %d", p->PartialReception); | ||
197 | printk(KERN_DEBUG "NumOfLayers = %d", p->NumOfLayers); | ||
198 | printk(KERN_DEBUG "SmsToHostTxErrors = %d", p->SmsToHostTxErrors); | ||
199 | |||
200 | for (i = 0; i < 3; i++) { | ||
201 | printk(KERN_DEBUG "%d: CodeRate = %d", i, p->LayerInfo[i].CodeRate); | ||
202 | printk(KERN_DEBUG "%d: Constellation = %d", i, p->LayerInfo[i].Constellation); | ||
203 | printk(KERN_DEBUG "%d: BER = %d", i, p->LayerInfo[i].BER); | ||
204 | printk(KERN_DEBUG "%d: BERErrorCount = %d", i, p->LayerInfo[i].BERErrorCount); | ||
205 | printk(KERN_DEBUG "%d: BERBitCount = %d", i, p->LayerInfo[i].BERBitCount); | ||
206 | printk(KERN_DEBUG "%d: PreBER = %d", i, p->LayerInfo[i].PreBER); | ||
207 | printk(KERN_DEBUG "%d: TS_PER = %d", i, p->LayerInfo[i].TS_PER); | ||
208 | printk(KERN_DEBUG "%d: ErrorTSPackets = %d", i, p->LayerInfo[i].ErrorTSPackets); | ||
209 | printk(KERN_DEBUG "%d: TotalTSPackets = %d", i, p->LayerInfo[i].TotalTSPackets); | ||
210 | printk(KERN_DEBUG "%d: TILdepthI = %d", i, p->LayerInfo[i].TILdepthI); | ||
211 | printk(KERN_DEBUG "%d: NumberOfSegments = %d", i, p->LayerInfo[i].NumberOfSegments); | ||
212 | printk(KERN_DEBUG "%d: TMCCErrors = %d", i, p->LayerInfo[i].TMCCErrors); | ||
213 | } | ||
214 | } | ||
215 | |||
216 | pReceptionData->IsDemodLocked = p->IsDemodLocked; | ||
217 | |||
218 | pReceptionData->SNR = p->SNR; | ||
219 | pReceptionData->InBandPwr = p->InBandPwr; | ||
220 | |||
221 | pReceptionData->ErrorTSPackets = 0; | ||
222 | pReceptionData->BER = 0; | ||
223 | pReceptionData->BERErrorCount = 0; | ||
224 | for (i = 0; i < 3; i++) { | ||
225 | pReceptionData->BER += p->LayerInfo[i].BER; | ||
226 | pReceptionData->BERErrorCount += p->LayerInfo[i].BERErrorCount; | ||
227 | pReceptionData->ErrorTSPackets += p->LayerInfo[i].ErrorTSPackets; | ||
228 | } | ||
229 | } | ||
230 | |||
119 | static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb) | 231 | static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb) |
120 | { | 232 | { |
121 | struct smsdvb_client_t *client = (struct smsdvb_client_t *) context; | 233 | struct smsdvb_client_t *client = (struct smsdvb_client_t *) context; |
@@ -134,6 +246,7 @@ static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb) | |||
134 | break; | 246 | break; |
135 | 247 | ||
136 | case MSG_SMS_RF_TUNE_RES: | 248 | case MSG_SMS_RF_TUNE_RES: |
249 | case MSG_SMS_ISDBT_TUNE_RES: | ||
137 | complete(&client->tune_done); | 250 | complete(&client->tune_done); |
138 | break; | 251 | break; |
139 | 252 | ||
@@ -217,6 +330,40 @@ static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb) | |||
217 | is_status_update = true; | 330 | is_status_update = true; |
218 | break; | 331 | break; |
219 | } | 332 | } |
333 | case MSG_SMS_GET_STATISTICS_RES: { | ||
334 | union { | ||
335 | struct SMSHOSTLIB_STATISTICS_ISDBT_ST isdbt; | ||
336 | struct SmsMsgStatisticsInfo_ST dvb; | ||
337 | } *p = (void *) (phdr + 1); | ||
338 | struct RECEPTION_STATISTICS_S *pReceptionData = | ||
339 | &client->sms_stat_dvb.ReceptionData; | ||
340 | |||
341 | sms_info("MSG_SMS_GET_STATISTICS_RES"); | ||
342 | |||
343 | is_status_update = true; | ||
344 | |||
345 | switch (smscore_get_device_mode(client->coredev)) { | ||
346 | case DEVICE_MODE_ISDBT: | ||
347 | case DEVICE_MODE_ISDBT_BDA: | ||
348 | smsdvb_update_isdbt_stats(pReceptionData, &p->isdbt); | ||
349 | break; | ||
350 | default: | ||
351 | smsdvb_update_dvb_stats(pReceptionData, &p->dvb.Stat); | ||
352 | } | ||
353 | if (!pReceptionData->IsDemodLocked) { | ||
354 | pReceptionData->SNR = 0; | ||
355 | pReceptionData->BER = 0; | ||
356 | pReceptionData->BERErrorCount = 0; | ||
357 | pReceptionData->InBandPwr = 0; | ||
358 | pReceptionData->ErrorTSPackets = 0; | ||
359 | } | ||
360 | |||
361 | complete(&client->tune_done); | ||
362 | break; | ||
363 | } | ||
364 | default: | ||
365 | sms_info("Unhandled message %d", phdr->msgType); | ||
366 | |||
220 | } | 367 | } |
221 | smscore_putbuffer(client->coredev, cb); | 368 | smscore_putbuffer(client->coredev, cb); |
222 | 369 | ||
@@ -233,10 +380,10 @@ static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb) | |||
233 | DVB3_EVENT_UNC_ERR); | 380 | DVB3_EVENT_UNC_ERR); |
234 | 381 | ||
235 | } else { | 382 | } else { |
236 | /*client->fe_status = | 383 | if (client->sms_stat_dvb.ReceptionData.IsRfLocked) |
237 | (phdr->msgType == MSG_SMS_NO_SIGNAL_IND) ? | 384 | client->fe_status = FE_HAS_SIGNAL | FE_HAS_CARRIER; |
238 | 0 : FE_HAS_SIGNAL;*/ | 385 | else |
239 | client->fe_status = 0; | 386 | client->fe_status = 0; |
240 | sms_board_dvb3_event(client, DVB3_EVENT_FE_UNLOCK); | 387 | sms_board_dvb3_event(client, DVB3_EVENT_FE_UNLOCK); |
241 | } | 388 | } |
242 | } | 389 | } |
@@ -325,6 +472,20 @@ static int smsdvb_sendrequest_and_wait(struct smsdvb_client_t *client, | |||
325 | 0 : -ETIME; | 472 | 0 : -ETIME; |
326 | } | 473 | } |
327 | 474 | ||
475 | static int smsdvb_send_statistics_request(struct smsdvb_client_t *client) | ||
476 | { | ||
477 | int rc; | ||
478 | struct SmsMsgHdr_ST Msg = { MSG_SMS_GET_STATISTICS_REQ, | ||
479 | DVBT_BDA_CONTROL_MSG_ID, | ||
480 | HIF_TASK, | ||
481 | sizeof(struct SmsMsgHdr_ST), 0 }; | ||
482 | |||
483 | rc = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg), | ||
484 | &client->tune_done); | ||
485 | |||
486 | return rc; | ||
487 | } | ||
488 | |||
328 | static inline int led_feedback(struct smsdvb_client_t *client) | 489 | static inline int led_feedback(struct smsdvb_client_t *client) |
329 | { | 490 | { |
330 | if (client->fe_status & FE_HAS_LOCK) | 491 | if (client->fe_status & FE_HAS_LOCK) |
@@ -337,33 +498,43 @@ static inline int led_feedback(struct smsdvb_client_t *client) | |||
337 | 498 | ||
338 | static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat) | 499 | static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat) |
339 | { | 500 | { |
501 | int rc; | ||
340 | struct smsdvb_client_t *client; | 502 | struct smsdvb_client_t *client; |
341 | client = container_of(fe, struct smsdvb_client_t, frontend); | 503 | client = container_of(fe, struct smsdvb_client_t, frontend); |
342 | 504 | ||
505 | rc = smsdvb_send_statistics_request(client); | ||
506 | |||
343 | *stat = client->fe_status; | 507 | *stat = client->fe_status; |
344 | 508 | ||
345 | led_feedback(client); | 509 | led_feedback(client); |
346 | 510 | ||
347 | return 0; | 511 | return rc; |
348 | } | 512 | } |
349 | 513 | ||
350 | static int smsdvb_read_ber(struct dvb_frontend *fe, u32 *ber) | 514 | static int smsdvb_read_ber(struct dvb_frontend *fe, u32 *ber) |
351 | { | 515 | { |
516 | int rc; | ||
352 | struct smsdvb_client_t *client; | 517 | struct smsdvb_client_t *client; |
353 | client = container_of(fe, struct smsdvb_client_t, frontend); | 518 | client = container_of(fe, struct smsdvb_client_t, frontend); |
354 | 519 | ||
520 | rc = smsdvb_send_statistics_request(client); | ||
521 | |||
355 | *ber = client->sms_stat_dvb.ReceptionData.BER; | 522 | *ber = client->sms_stat_dvb.ReceptionData.BER; |
356 | 523 | ||
357 | led_feedback(client); | 524 | led_feedback(client); |
358 | 525 | ||
359 | return 0; | 526 | return rc; |
360 | } | 527 | } |
361 | 528 | ||
362 | static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength) | 529 | static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength) |
363 | { | 530 | { |
531 | int rc; | ||
532 | |||
364 | struct smsdvb_client_t *client; | 533 | struct smsdvb_client_t *client; |
365 | client = container_of(fe, struct smsdvb_client_t, frontend); | 534 | client = container_of(fe, struct smsdvb_client_t, frontend); |
366 | 535 | ||
536 | rc = smsdvb_send_statistics_request(client); | ||
537 | |||
367 | if (client->sms_stat_dvb.ReceptionData.InBandPwr < -95) | 538 | if (client->sms_stat_dvb.ReceptionData.InBandPwr < -95) |
368 | *strength = 0; | 539 | *strength = 0; |
369 | else if (client->sms_stat_dvb.ReceptionData.InBandPwr > -29) | 540 | else if (client->sms_stat_dvb.ReceptionData.InBandPwr > -29) |
@@ -375,31 +546,37 @@ static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength) | |||
375 | 546 | ||
376 | led_feedback(client); | 547 | led_feedback(client); |
377 | 548 | ||
378 | return 0; | 549 | return rc; |
379 | } | 550 | } |
380 | 551 | ||
381 | static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr) | 552 | static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr) |
382 | { | 553 | { |
554 | int rc; | ||
383 | struct smsdvb_client_t *client; | 555 | struct smsdvb_client_t *client; |
384 | client = container_of(fe, struct smsdvb_client_t, frontend); | 556 | client = container_of(fe, struct smsdvb_client_t, frontend); |
385 | 557 | ||
558 | rc = smsdvb_send_statistics_request(client); | ||
559 | |||
386 | *snr = client->sms_stat_dvb.ReceptionData.SNR; | 560 | *snr = client->sms_stat_dvb.ReceptionData.SNR; |
387 | 561 | ||
388 | led_feedback(client); | 562 | led_feedback(client); |
389 | 563 | ||
390 | return 0; | 564 | return rc; |
391 | } | 565 | } |
392 | 566 | ||
393 | static int smsdvb_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) | 567 | static int smsdvb_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) |
394 | { | 568 | { |
569 | int rc; | ||
395 | struct smsdvb_client_t *client; | 570 | struct smsdvb_client_t *client; |
396 | client = container_of(fe, struct smsdvb_client_t, frontend); | 571 | client = container_of(fe, struct smsdvb_client_t, frontend); |
397 | 572 | ||
573 | rc = smsdvb_send_statistics_request(client); | ||
574 | |||
398 | *ucblocks = client->sms_stat_dvb.ReceptionData.ErrorTSPackets; | 575 | *ucblocks = client->sms_stat_dvb.ReceptionData.ErrorTSPackets; |
399 | 576 | ||
400 | led_feedback(client); | 577 | led_feedback(client); |
401 | 578 | ||
402 | return 0; | 579 | return rc; |
403 | } | 580 | } |
404 | 581 | ||
405 | static int smsdvb_get_tune_settings(struct dvb_frontend *fe, | 582 | static int smsdvb_get_tune_settings(struct dvb_frontend *fe, |
@@ -413,9 +590,10 @@ static int smsdvb_get_tune_settings(struct dvb_frontend *fe, | |||
413 | return 0; | 590 | return 0; |
414 | } | 591 | } |
415 | 592 | ||
416 | static int smsdvb_set_frontend(struct dvb_frontend *fe, | 593 | static int smsdvb_dvbt_set_frontend(struct dvb_frontend *fe, |
417 | struct dvb_frontend_parameters *fep) | 594 | struct dvb_frontend_parameters *p) |
418 | { | 595 | { |
596 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
419 | struct smsdvb_client_t *client = | 597 | struct smsdvb_client_t *client = |
420 | container_of(fe, struct smsdvb_client_t, frontend); | 598 | container_of(fe, struct smsdvb_client_t, frontend); |
421 | 599 | ||
@@ -429,24 +607,33 @@ static int smsdvb_set_frontend(struct dvb_frontend *fe, | |||
429 | client->fe_status = FE_HAS_SIGNAL; | 607 | client->fe_status = FE_HAS_SIGNAL; |
430 | client->event_fe_state = -1; | 608 | client->event_fe_state = -1; |
431 | client->event_unc_state = -1; | 609 | client->event_unc_state = -1; |
610 | fe->dtv_property_cache.delivery_system = SYS_DVBT; | ||
432 | 611 | ||
433 | Msg.Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID; | 612 | Msg.Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID; |
434 | Msg.Msg.msgDstId = HIF_TASK; | 613 | Msg.Msg.msgDstId = HIF_TASK; |
435 | Msg.Msg.msgFlags = 0; | 614 | Msg.Msg.msgFlags = 0; |
436 | Msg.Msg.msgType = MSG_SMS_RF_TUNE_REQ; | 615 | Msg.Msg.msgType = MSG_SMS_RF_TUNE_REQ; |
437 | Msg.Msg.msgLength = sizeof(Msg); | 616 | Msg.Msg.msgLength = sizeof(Msg); |
438 | Msg.Data[0] = fep->frequency; | 617 | Msg.Data[0] = c->frequency; |
439 | Msg.Data[2] = 12000000; | 618 | Msg.Data[2] = 12000000; |
440 | 619 | ||
441 | sms_debug("freq %d band %d", | 620 | sms_info("%s: freq %d band %d", __func__, c->frequency, |
442 | fep->frequency, fep->u.ofdm.bandwidth); | 621 | c->bandwidth_hz); |
443 | 622 | ||
444 | switch (fep->u.ofdm.bandwidth) { | 623 | switch (c->bandwidth_hz / 1000000) { |
445 | case BANDWIDTH_8_MHZ: Msg.Data[1] = BW_8_MHZ; break; | 624 | case 8: |
446 | case BANDWIDTH_7_MHZ: Msg.Data[1] = BW_7_MHZ; break; | 625 | Msg.Data[1] = BW_8_MHZ; |
447 | case BANDWIDTH_6_MHZ: Msg.Data[1] = BW_6_MHZ; break; | 626 | break; |
448 | case BANDWIDTH_AUTO: return -EOPNOTSUPP; | 627 | case 7: |
449 | default: return -EINVAL; | 628 | Msg.Data[1] = BW_7_MHZ; |
629 | break; | ||
630 | case 6: | ||
631 | Msg.Data[1] = BW_6_MHZ; | ||
632 | break; | ||
633 | case 0: | ||
634 | return -EOPNOTSUPP; | ||
635 | default: | ||
636 | return -EINVAL; | ||
450 | } | 637 | } |
451 | /* Disable LNA, if any. An error is returned if no LNA is present */ | 638 | /* Disable LNA, if any. An error is returned if no LNA is present */ |
452 | ret = sms_board_lna_control(client->coredev, 0); | 639 | ret = sms_board_lna_control(client->coredev, 0); |
@@ -470,6 +657,90 @@ static int smsdvb_set_frontend(struct dvb_frontend *fe, | |||
470 | &client->tune_done); | 657 | &client->tune_done); |
471 | } | 658 | } |
472 | 659 | ||
660 | static int smsdvb_isdbt_set_frontend(struct dvb_frontend *fe, | ||
661 | struct dvb_frontend_parameters *p) | ||
662 | { | ||
663 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
664 | struct smsdvb_client_t *client = | ||
665 | container_of(fe, struct smsdvb_client_t, frontend); | ||
666 | |||
667 | struct { | ||
668 | struct SmsMsgHdr_ST Msg; | ||
669 | u32 Data[4]; | ||
670 | } Msg; | ||
671 | |||
672 | fe->dtv_property_cache.delivery_system = SYS_ISDBT; | ||
673 | |||
674 | Msg.Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID; | ||
675 | Msg.Msg.msgDstId = HIF_TASK; | ||
676 | Msg.Msg.msgFlags = 0; | ||
677 | Msg.Msg.msgType = MSG_SMS_ISDBT_TUNE_REQ; | ||
678 | Msg.Msg.msgLength = sizeof(Msg); | ||
679 | |||
680 | if (c->isdbt_sb_segment_idx == -1) | ||
681 | c->isdbt_sb_segment_idx = 0; | ||
682 | |||
683 | switch (c->isdbt_sb_segment_count) { | ||
684 | case 3: | ||
685 | Msg.Data[1] = BW_ISDBT_3SEG; | ||
686 | break; | ||
687 | case 1: | ||
688 | Msg.Data[1] = BW_ISDBT_1SEG; | ||
689 | break; | ||
690 | case 0: /* AUTO */ | ||
691 | switch (c->bandwidth_hz / 1000000) { | ||
692 | case 8: | ||
693 | case 7: | ||
694 | c->isdbt_sb_segment_count = 3; | ||
695 | Msg.Data[1] = BW_ISDBT_3SEG; | ||
696 | break; | ||
697 | case 6: | ||
698 | c->isdbt_sb_segment_count = 1; | ||
699 | Msg.Data[1] = BW_ISDBT_1SEG; | ||
700 | break; | ||
701 | default: /* Assumes 6 MHZ bw */ | ||
702 | c->isdbt_sb_segment_count = 1; | ||
703 | c->bandwidth_hz = 6000; | ||
704 | Msg.Data[1] = BW_ISDBT_1SEG; | ||
705 | break; | ||
706 | } | ||
707 | break; | ||
708 | default: | ||
709 | sms_info("Segment count %d not supported", c->isdbt_sb_segment_count); | ||
710 | return -EINVAL; | ||
711 | } | ||
712 | |||
713 | Msg.Data[0] = c->frequency; | ||
714 | Msg.Data[2] = 12000000; | ||
715 | Msg.Data[3] = c->isdbt_sb_segment_idx; | ||
716 | |||
717 | sms_info("%s: freq %d segwidth %d segindex %d\n", __func__, | ||
718 | c->frequency, c->isdbt_sb_segment_count, | ||
719 | c->isdbt_sb_segment_idx); | ||
720 | |||
721 | return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg), | ||
722 | &client->tune_done); | ||
723 | } | ||
724 | |||
725 | static int smsdvb_set_frontend(struct dvb_frontend *fe, | ||
726 | struct dvb_frontend_parameters *fep) | ||
727 | { | ||
728 | struct smsdvb_client_t *client = | ||
729 | container_of(fe, struct smsdvb_client_t, frontend); | ||
730 | struct smscore_device_t *coredev = client->coredev; | ||
731 | |||
732 | switch (smscore_get_device_mode(coredev)) { | ||
733 | case DEVICE_MODE_DVBT: | ||
734 | case DEVICE_MODE_DVBT_BDA: | ||
735 | return smsdvb_dvbt_set_frontend(fe, fep); | ||
736 | case DEVICE_MODE_ISDBT: | ||
737 | case DEVICE_MODE_ISDBT_BDA: | ||
738 | return smsdvb_isdbt_set_frontend(fe, fep); | ||
739 | default: | ||
740 | return -EINVAL; | ||
741 | } | ||
742 | } | ||
743 | |||
473 | static int smsdvb_get_frontend(struct dvb_frontend *fe, | 744 | static int smsdvb_get_frontend(struct dvb_frontend *fe, |
474 | struct dvb_frontend_parameters *fep) | 745 | struct dvb_frontend_parameters *fep) |
475 | { | 746 | { |
@@ -557,13 +828,6 @@ static int smsdvb_hotplug(struct smscore_device_t *coredev, | |||
557 | /* device removal handled by onremove callback */ | 828 | /* device removal handled by onremove callback */ |
558 | if (!arrival) | 829 | if (!arrival) |
559 | return 0; | 830 | return 0; |
560 | |||
561 | if (smscore_get_device_mode(coredev) != DEVICE_MODE_DVBT_BDA) { | ||
562 | sms_err("SMS Device mode is not set for " | ||
563 | "DVB operation."); | ||
564 | return 0; | ||
565 | } | ||
566 | |||
567 | client = kzalloc(sizeof(struct smsdvb_client_t), GFP_KERNEL); | 831 | client = kzalloc(sizeof(struct smsdvb_client_t), GFP_KERNEL); |
568 | if (!client) { | 832 | if (!client) { |
569 | sms_err("kmalloc() failed"); | 833 | sms_err("kmalloc() failed"); |
diff --git a/drivers/media/dvb/siano/smsir.c b/drivers/media/dvb/siano/smsir.c index e3d776feeaca..a56eac76e0f0 100644 --- a/drivers/media/dvb/siano/smsir.c +++ b/drivers/media/dvb/siano/smsir.c | |||
@@ -85,9 +85,9 @@ static struct keyboard_layout_map_t keyboard_layout_maps[] = { | |||
85 | { } /* Terminating entry */ | 85 | { } /* Terminating entry */ |
86 | }; | 86 | }; |
87 | 87 | ||
88 | u32 ir_pos; | 88 | static u32 ir_pos; |
89 | u32 ir_word; | 89 | static u32 ir_word; |
90 | u32 ir_toggle; | 90 | static u32 ir_toggle; |
91 | 91 | ||
92 | #define RC5_PUSH_BIT(dst, bit, pos) \ | 92 | #define RC5_PUSH_BIT(dst, bit, pos) \ |
93 | { dst <<= 1; dst |= bit; pos++; } | 93 | { dst <<= 1; dst |= bit; pos++; } |
diff --git a/drivers/media/dvb/ttpci/av7110_ir.c b/drivers/media/dvb/ttpci/av7110_ir.c index 23a1c6380d3f..b070e88d8c6b 100644 --- a/drivers/media/dvb/ttpci/av7110_ir.c +++ b/drivers/media/dvb/ttpci/av7110_ir.c | |||
@@ -268,8 +268,8 @@ int av7110_check_ir_config(struct av7110 *av7110, int force) | |||
268 | 268 | ||
269 | 269 | ||
270 | /* /proc/av7110_ir interface */ | 270 | /* /proc/av7110_ir interface */ |
271 | static int av7110_ir_write_proc(struct file *file, const char __user *buffer, | 271 | static ssize_t av7110_ir_proc_write(struct file *file, const char __user *buffer, |
272 | unsigned long count, void *data) | 272 | size_t count, loff_t *pos) |
273 | { | 273 | { |
274 | char *page; | 274 | char *page; |
275 | u32 ir_config; | 275 | u32 ir_config; |
@@ -309,6 +309,10 @@ static int av7110_ir_write_proc(struct file *file, const char __user *buffer, | |||
309 | return count; | 309 | return count; |
310 | } | 310 | } |
311 | 311 | ||
312 | static const struct file_operations av7110_ir_proc_fops = { | ||
313 | .owner = THIS_MODULE, | ||
314 | .write = av7110_ir_proc_write, | ||
315 | }; | ||
312 | 316 | ||
313 | /* interrupt handler */ | 317 | /* interrupt handler */ |
314 | static void ir_handler(struct av7110 *av7110, u32 ircom) | 318 | static void ir_handler(struct av7110 *av7110, u32 ircom) |
@@ -368,11 +372,9 @@ int __devinit av7110_ir_init(struct av7110 *av7110) | |||
368 | input_dev->timer.data = (unsigned long) &av7110->ir; | 372 | input_dev->timer.data = (unsigned long) &av7110->ir; |
369 | 373 | ||
370 | if (av_cnt == 1) { | 374 | if (av_cnt == 1) { |
371 | e = create_proc_entry("av7110_ir", S_IFREG | S_IRUGO | S_IWUSR, NULL); | 375 | e = proc_create("av7110_ir", S_IWUSR, NULL, &av7110_ir_proc_fops); |
372 | if (e) { | 376 | if (e) |
373 | e->write_proc = av7110_ir_write_proc; | ||
374 | e->size = 4 + 256 * sizeof(u16); | 377 | e->size = 4 + 256 * sizeof(u16); |
375 | } | ||
376 | } | 378 | } |
377 | 379 | ||
378 | tasklet_init(&av7110->ir.ir_tasklet, av7110_emit_key, (unsigned long) &av7110->ir); | 380 | tasklet_init(&av7110->ir.ir_tasklet, av7110_emit_key, (unsigned long) &av7110->ir); |
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index 9782e0593733..49c2a817a06f 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c | |||
@@ -254,7 +254,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci) | |||
254 | budget_ci->ir.timer_keyup.function = msp430_ir_keyup; | 254 | budget_ci->ir.timer_keyup.function = msp430_ir_keyup; |
255 | budget_ci->ir.timer_keyup.data = (unsigned long) &budget_ci->ir; | 255 | budget_ci->ir.timer_keyup.data = (unsigned long) &budget_ci->ir; |
256 | budget_ci->ir.last_raw = 0xffff; /* An impossible value */ | 256 | budget_ci->ir.last_raw = 0xffff; /* An impossible value */ |
257 | error = ir_input_register(input_dev, ir_codes); | 257 | error = ir_input_register(input_dev, ir_codes, NULL); |
258 | if (error) { | 258 | if (error) { |
259 | printk(KERN_ERR "budget_ci: could not init driver for IR device (code %d)\n", error); | 259 | printk(KERN_ERR "budget_ci: could not init driver for IR device (code %d)\n", error); |
260 | return error; | 260 | return error; |
diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c index e48380c48990..9fdf26cc6998 100644 --- a/drivers/media/dvb/ttpci/budget.c +++ b/drivers/media/dvb/ttpci/budget.c | |||
@@ -433,9 +433,8 @@ static struct stv090x_config tt1600_stv090x_config = { | |||
433 | .demod_mode = STV090x_SINGLE, | 433 | .demod_mode = STV090x_SINGLE, |
434 | .clk_mode = STV090x_CLK_EXT, | 434 | .clk_mode = STV090x_CLK_EXT, |
435 | 435 | ||
436 | .xtal = 27000000, | 436 | .xtal = 13500000, |
437 | .address = 0x68, | 437 | .address = 0x68, |
438 | .ref_clk = 27000000, | ||
439 | 438 | ||
440 | .ts1_mode = STV090x_TSMODE_DVBCI, | 439 | .ts1_mode = STV090x_TSMODE_DVBCI, |
441 | .ts2_mode = STV090x_TSMODE_SERIAL_CONTINUOUS, | 440 | .ts2_mode = STV090x_TSMODE_SERIAL_CONTINUOUS, |
@@ -457,6 +456,7 @@ static struct stv090x_config tt1600_stv090x_config = { | |||
457 | static struct stv6110x_config tt1600_stv6110x_config = { | 456 | static struct stv6110x_config tt1600_stv6110x_config = { |
458 | .addr = 0x60, | 457 | .addr = 0x60, |
459 | .refclk = 27000000, | 458 | .refclk = 27000000, |
459 | .clk_div = 2, | ||
460 | }; | 460 | }; |
461 | 461 | ||
462 | static struct isl6423_config tt1600_isl6423_config = { | 462 | static struct isl6423_config tt1600_isl6423_config = { |
diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig index 3f40f375981b..83567b898d09 100644 --- a/drivers/media/radio/Kconfig +++ b/drivers/media/radio/Kconfig | |||
@@ -417,6 +417,18 @@ config RADIO_TEA5764_XTAL | |||
417 | Say Y here if TEA5764 have a 32768 Hz crystal in circuit, say N | 417 | Say Y here if TEA5764 have a 32768 Hz crystal in circuit, say N |
418 | here if TEA5764 reference frequency is connected in FREQIN. | 418 | here if TEA5764 reference frequency is connected in FREQIN. |
419 | 419 | ||
420 | config RADIO_SAA7706H | ||
421 | tristate "SAA7706H Car Radio DSP" | ||
422 | depends on I2C && VIDEO_V4L2 | ||
423 | ---help--- | ||
424 | Say Y here if you want to use the SAA7706H Car radio Digital | ||
425 | Signal Processor, found for instance on the Russellville development | ||
426 | board. On the russellville the device is connected to internal | ||
427 | timberdale I2C bus. | ||
428 | |||
429 | To compile this driver as a module, choose M here: the | ||
430 | module will be called SAA7706H. | ||
431 | |||
420 | config RADIO_TEF6862 | 432 | config RADIO_TEF6862 |
421 | tristate "TEF6862 Car Radio Enhanced Selectivity Tuner" | 433 | tristate "TEF6862 Car Radio Enhanced Selectivity Tuner" |
422 | depends on I2C && VIDEO_V4L2 | 434 | depends on I2C && VIDEO_V4L2 |
@@ -429,4 +441,15 @@ config RADIO_TEF6862 | |||
429 | To compile this driver as a module, choose M here: the | 441 | To compile this driver as a module, choose M here: the |
430 | module will be called TEF6862. | 442 | module will be called TEF6862. |
431 | 443 | ||
444 | config RADIO_TIMBERDALE | ||
445 | tristate "Enable the Timberdale radio driver" | ||
446 | depends on MFD_TIMBERDALE && VIDEO_V4L2 | ||
447 | depends on I2C # for RADIO_SAA7706H | ||
448 | select RADIO_TEF6862 | ||
449 | select RADIO_SAA7706H | ||
450 | ---help--- | ||
451 | This is a kind of umbrella driver for the Radio Tuner and DSP | ||
452 | found behind the Timberdale FPGA on the Russellville board. | ||
453 | Enabling this driver will automatically select the DSP and tuner. | ||
454 | |||
432 | endif # RADIO_ADAPTERS | 455 | endif # RADIO_ADAPTERS |
diff --git a/drivers/media/radio/Makefile b/drivers/media/radio/Makefile index 01922ada6914..f615583b4837 100644 --- a/drivers/media/radio/Makefile +++ b/drivers/media/radio/Makefile | |||
@@ -23,6 +23,8 @@ obj-$(CONFIG_USB_DSBR) += dsbr100.o | |||
23 | obj-$(CONFIG_RADIO_SI470X) += si470x/ | 23 | obj-$(CONFIG_RADIO_SI470X) += si470x/ |
24 | obj-$(CONFIG_USB_MR800) += radio-mr800.o | 24 | obj-$(CONFIG_USB_MR800) += radio-mr800.o |
25 | obj-$(CONFIG_RADIO_TEA5764) += radio-tea5764.o | 25 | obj-$(CONFIG_RADIO_TEA5764) += radio-tea5764.o |
26 | obj-$(CONFIG_RADIO_SAA7706H) += saa7706h.o | ||
26 | obj-$(CONFIG_RADIO_TEF6862) += tef6862.o | 27 | obj-$(CONFIG_RADIO_TEF6862) += tef6862.o |
28 | obj-$(CONFIG_RADIO_TIMBERDALE) += radio-timb.o | ||
27 | 29 | ||
28 | EXTRA_CFLAGS += -Isound | 30 | EXTRA_CFLAGS += -Isound |
diff --git a/drivers/media/radio/radio-timb.c b/drivers/media/radio/radio-timb.c new file mode 100644 index 000000000000..0de457f6e6eb --- /dev/null +++ b/drivers/media/radio/radio-timb.c | |||
@@ -0,0 +1,244 @@ | |||
1 | /* | ||
2 | * radio-timb.c Timberdale FPGA Radio driver | ||
3 | * Copyright (c) 2009 Intel Corporation | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | */ | ||
18 | |||
19 | #include <linux/version.h> | ||
20 | #include <linux/io.h> | ||
21 | #include <media/v4l2-ioctl.h> | ||
22 | #include <media/v4l2-device.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/interrupt.h> | ||
25 | #include <linux/i2c.h> | ||
26 | #include <media/timb_radio.h> | ||
27 | |||
28 | #define DRIVER_NAME "timb-radio" | ||
29 | |||
30 | struct timbradio { | ||
31 | struct timb_radio_platform_data pdata; | ||
32 | struct v4l2_subdev *sd_tuner; | ||
33 | struct v4l2_subdev *sd_dsp; | ||
34 | struct video_device video_dev; | ||
35 | struct v4l2_device v4l2_dev; | ||
36 | }; | ||
37 | |||
38 | |||
39 | static int timbradio_vidioc_querycap(struct file *file, void *priv, | ||
40 | struct v4l2_capability *v) | ||
41 | { | ||
42 | strlcpy(v->driver, DRIVER_NAME, sizeof(v->driver)); | ||
43 | strlcpy(v->card, "Timberdale Radio", sizeof(v->card)); | ||
44 | snprintf(v->bus_info, sizeof(v->bus_info), "platform:"DRIVER_NAME); | ||
45 | v->version = KERNEL_VERSION(0, 0, 1); | ||
46 | v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; | ||
47 | return 0; | ||
48 | } | ||
49 | |||
50 | static int timbradio_vidioc_g_tuner(struct file *file, void *priv, | ||
51 | struct v4l2_tuner *v) | ||
52 | { | ||
53 | struct timbradio *tr = video_drvdata(file); | ||
54 | return v4l2_subdev_call(tr->sd_tuner, tuner, g_tuner, v); | ||
55 | } | ||
56 | |||
57 | static int timbradio_vidioc_s_tuner(struct file *file, void *priv, | ||
58 | struct v4l2_tuner *v) | ||
59 | { | ||
60 | struct timbradio *tr = video_drvdata(file); | ||
61 | return v4l2_subdev_call(tr->sd_tuner, tuner, s_tuner, v); | ||
62 | } | ||
63 | |||
64 | static int timbradio_vidioc_g_input(struct file *filp, void *priv, | ||
65 | unsigned int *i) | ||
66 | { | ||
67 | *i = 0; | ||
68 | return 0; | ||
69 | } | ||
70 | |||
71 | static int timbradio_vidioc_s_input(struct file *filp, void *priv, | ||
72 | unsigned int i) | ||
73 | { | ||
74 | return i ? -EINVAL : 0; | ||
75 | } | ||
76 | |||
77 | static int timbradio_vidioc_g_audio(struct file *file, void *priv, | ||
78 | struct v4l2_audio *a) | ||
79 | { | ||
80 | a->index = 0; | ||
81 | strlcpy(a->name, "Radio", sizeof(a->name)); | ||
82 | a->capability = V4L2_AUDCAP_STEREO; | ||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | static int timbradio_vidioc_s_audio(struct file *file, void *priv, | ||
87 | struct v4l2_audio *a) | ||
88 | { | ||
89 | return a->index ? -EINVAL : 0; | ||
90 | } | ||
91 | |||
92 | static int timbradio_vidioc_s_frequency(struct file *file, void *priv, | ||
93 | struct v4l2_frequency *f) | ||
94 | { | ||
95 | struct timbradio *tr = video_drvdata(file); | ||
96 | return v4l2_subdev_call(tr->sd_tuner, tuner, s_frequency, f); | ||
97 | } | ||
98 | |||
99 | static int timbradio_vidioc_g_frequency(struct file *file, void *priv, | ||
100 | struct v4l2_frequency *f) | ||
101 | { | ||
102 | struct timbradio *tr = video_drvdata(file); | ||
103 | return v4l2_subdev_call(tr->sd_tuner, tuner, g_frequency, f); | ||
104 | } | ||
105 | |||
106 | static int timbradio_vidioc_queryctrl(struct file *file, void *priv, | ||
107 | struct v4l2_queryctrl *qc) | ||
108 | { | ||
109 | struct timbradio *tr = video_drvdata(file); | ||
110 | return v4l2_subdev_call(tr->sd_dsp, core, queryctrl, qc); | ||
111 | } | ||
112 | |||
113 | static int timbradio_vidioc_g_ctrl(struct file *file, void *priv, | ||
114 | struct v4l2_control *ctrl) | ||
115 | { | ||
116 | struct timbradio *tr = video_drvdata(file); | ||
117 | return v4l2_subdev_call(tr->sd_dsp, core, g_ctrl, ctrl); | ||
118 | } | ||
119 | |||
120 | static int timbradio_vidioc_s_ctrl(struct file *file, void *priv, | ||
121 | struct v4l2_control *ctrl) | ||
122 | { | ||
123 | struct timbradio *tr = video_drvdata(file); | ||
124 | return v4l2_subdev_call(tr->sd_dsp, core, s_ctrl, ctrl); | ||
125 | } | ||
126 | |||
127 | static const struct v4l2_ioctl_ops timbradio_ioctl_ops = { | ||
128 | .vidioc_querycap = timbradio_vidioc_querycap, | ||
129 | .vidioc_g_tuner = timbradio_vidioc_g_tuner, | ||
130 | .vidioc_s_tuner = timbradio_vidioc_s_tuner, | ||
131 | .vidioc_g_frequency = timbradio_vidioc_g_frequency, | ||
132 | .vidioc_s_frequency = timbradio_vidioc_s_frequency, | ||
133 | .vidioc_g_input = timbradio_vidioc_g_input, | ||
134 | .vidioc_s_input = timbradio_vidioc_s_input, | ||
135 | .vidioc_g_audio = timbradio_vidioc_g_audio, | ||
136 | .vidioc_s_audio = timbradio_vidioc_s_audio, | ||
137 | .vidioc_queryctrl = timbradio_vidioc_queryctrl, | ||
138 | .vidioc_g_ctrl = timbradio_vidioc_g_ctrl, | ||
139 | .vidioc_s_ctrl = timbradio_vidioc_s_ctrl | ||
140 | }; | ||
141 | |||
142 | static const struct v4l2_file_operations timbradio_fops = { | ||
143 | .owner = THIS_MODULE, | ||
144 | .ioctl = video_ioctl2, | ||
145 | }; | ||
146 | |||
147 | static int __devinit timbradio_probe(struct platform_device *pdev) | ||
148 | { | ||
149 | struct timb_radio_platform_data *pdata = pdev->dev.platform_data; | ||
150 | struct timbradio *tr; | ||
151 | int err; | ||
152 | |||
153 | if (!pdata) { | ||
154 | dev_err(&pdev->dev, "Platform data missing\n"); | ||
155 | err = -EINVAL; | ||
156 | goto err; | ||
157 | } | ||
158 | |||
159 | tr = kzalloc(sizeof(*tr), GFP_KERNEL); | ||
160 | if (!tr) { | ||
161 | err = -ENOMEM; | ||
162 | goto err; | ||
163 | } | ||
164 | |||
165 | tr->pdata = *pdata; | ||
166 | |||
167 | strlcpy(tr->video_dev.name, "Timberdale Radio", | ||
168 | sizeof(tr->video_dev.name)); | ||
169 | tr->video_dev.fops = &timbradio_fops; | ||
170 | tr->video_dev.ioctl_ops = &timbradio_ioctl_ops; | ||
171 | tr->video_dev.release = video_device_release_empty; | ||
172 | tr->video_dev.minor = -1; | ||
173 | |||
174 | strlcpy(tr->v4l2_dev.name, DRIVER_NAME, sizeof(tr->v4l2_dev.name)); | ||
175 | err = v4l2_device_register(NULL, &tr->v4l2_dev); | ||
176 | if (err) | ||
177 | goto err_v4l2_dev; | ||
178 | |||
179 | tr->video_dev.v4l2_dev = &tr->v4l2_dev; | ||
180 | |||
181 | err = video_register_device(&tr->video_dev, VFL_TYPE_RADIO, -1); | ||
182 | if (err) { | ||
183 | dev_err(&pdev->dev, "Error reg video\n"); | ||
184 | goto err_video_req; | ||
185 | } | ||
186 | |||
187 | video_set_drvdata(&tr->video_dev, tr); | ||
188 | |||
189 | platform_set_drvdata(pdev, tr); | ||
190 | return 0; | ||
191 | |||
192 | err_video_req: | ||
193 | video_device_release_empty(&tr->video_dev); | ||
194 | v4l2_device_unregister(&tr->v4l2_dev); | ||
195 | err_v4l2_dev: | ||
196 | kfree(tr); | ||
197 | err: | ||
198 | dev_err(&pdev->dev, "Failed to register: %d\n", err); | ||
199 | |||
200 | return err; | ||
201 | } | ||
202 | |||
203 | static int __devexit timbradio_remove(struct platform_device *pdev) | ||
204 | { | ||
205 | struct timbradio *tr = platform_get_drvdata(pdev); | ||
206 | |||
207 | video_unregister_device(&tr->video_dev); | ||
208 | video_device_release_empty(&tr->video_dev); | ||
209 | |||
210 | v4l2_device_unregister(&tr->v4l2_dev); | ||
211 | |||
212 | kfree(tr); | ||
213 | |||
214 | return 0; | ||
215 | } | ||
216 | |||
217 | static struct platform_driver timbradio_platform_driver = { | ||
218 | .driver = { | ||
219 | .name = DRIVER_NAME, | ||
220 | .owner = THIS_MODULE, | ||
221 | }, | ||
222 | .probe = timbradio_probe, | ||
223 | .remove = timbradio_remove, | ||
224 | }; | ||
225 | |||
226 | /*--------------------------------------------------------------------------*/ | ||
227 | |||
228 | static int __init timbradio_init(void) | ||
229 | { | ||
230 | return platform_driver_register(&timbradio_platform_driver); | ||
231 | } | ||
232 | |||
233 | static void __exit timbradio_exit(void) | ||
234 | { | ||
235 | platform_driver_unregister(&timbradio_platform_driver); | ||
236 | } | ||
237 | |||
238 | module_init(timbradio_init); | ||
239 | module_exit(timbradio_exit); | ||
240 | |||
241 | MODULE_DESCRIPTION("Timberdale Radio driver"); | ||
242 | MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>"); | ||
243 | MODULE_LICENSE("GPL v2"); | ||
244 | MODULE_ALIAS("platform:"DRIVER_NAME); | ||
diff --git a/drivers/media/radio/saa7706h.c b/drivers/media/radio/saa7706h.c new file mode 100644 index 000000000000..5db5528a8b25 --- /dev/null +++ b/drivers/media/radio/saa7706h.c | |||
@@ -0,0 +1,451 @@ | |||
1 | /* | ||
2 | * saa7706.c Philips SAA7706H Car Radio DSP driver | ||
3 | * Copyright (c) 2009 Intel Corporation | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | */ | ||
18 | |||
19 | #include <linux/module.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/delay.h> | ||
22 | #include <linux/errno.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/interrupt.h> | ||
25 | #include <linux/i2c.h> | ||
26 | #include <media/v4l2-device.h> | ||
27 | #include <media/v4l2-chip-ident.h> | ||
28 | |||
29 | #define DRIVER_NAME "saa7706h" | ||
30 | |||
31 | /* the I2C memory map looks like this | ||
32 | |||
33 | $1C00 - $FFFF Not Used | ||
34 | $2200 - $3FFF Reserved YRAM (DSP2) space | ||
35 | $2000 - $21FF YRAM (DSP2) | ||
36 | $1FF0 - $1FFF Hardware Registers | ||
37 | $1280 - $1FEF Reserved XRAM (DSP2) space | ||
38 | $1000 - $127F XRAM (DSP2) | ||
39 | $0FFF DSP CONTROL | ||
40 | $0A00 - $0FFE Reserved | ||
41 | $0980 - $09FF Reserved YRAM (DSP1) space | ||
42 | $0800 - $097F YRAM (DSP1) | ||
43 | $0200 - $07FF Not Used | ||
44 | $0180 - $01FF Reserved XRAM (DSP1) space | ||
45 | $0000 - $017F XRAM (DSP1) | ||
46 | */ | ||
47 | |||
48 | #define SAA7706H_REG_CTRL 0x0fff | ||
49 | #define SAA7706H_CTRL_BYP_PLL 0x0001 | ||
50 | #define SAA7706H_CTRL_PLL_DIV_MASK 0x003e | ||
51 | #define SAA7706H_CTRL_PLL3_62975MHZ 0x003e | ||
52 | #define SAA7706H_CTRL_DSP_TURBO 0x0040 | ||
53 | #define SAA7706H_CTRL_PC_RESET_DSP1 0x0080 | ||
54 | #define SAA7706H_CTRL_PC_RESET_DSP2 0x0100 | ||
55 | #define SAA7706H_CTRL_DSP1_ROM_EN_MASK 0x0600 | ||
56 | #define SAA7706H_CTRL_DSP1_FUNC_PROM 0x0000 | ||
57 | #define SAA7706H_CTRL_DSP2_ROM_EN_MASK 0x1800 | ||
58 | #define SAA7706H_CTRL_DSP2_FUNC_PROM 0x0000 | ||
59 | #define SAA7706H_CTRL_DIG_SIL_INTERPOL 0x8000 | ||
60 | |||
61 | #define SAA7706H_REG_EVALUATION 0x1ff0 | ||
62 | #define SAA7706H_EVAL_DISABLE_CHARGE_PUMP 0x000001 | ||
63 | #define SAA7706H_EVAL_DCS_CLOCK 0x000002 | ||
64 | #define SAA7706H_EVAL_GNDRC1_ENABLE 0x000004 | ||
65 | #define SAA7706H_EVAL_GNDRC2_ENABLE 0x000008 | ||
66 | |||
67 | #define SAA7706H_REG_CL_GEN1 0x1ff3 | ||
68 | #define SAA7706H_CL_GEN1_MIN_LOOPGAIN_MASK 0x00000f | ||
69 | #define SAA7706H_CL_GEN1_LOOPGAIN_MASK 0x0000f0 | ||
70 | #define SAA7706H_CL_GEN1_COARSE_RATION 0xffff00 | ||
71 | |||
72 | #define SAA7706H_REG_CL_GEN2 0x1ff4 | ||
73 | #define SAA7706H_CL_GEN2_WSEDGE_FALLING 0x000001 | ||
74 | #define SAA7706H_CL_GEN2_STOP_VCO 0x000002 | ||
75 | #define SAA7706H_CL_GEN2_FRERUN 0x000004 | ||
76 | #define SAA7706H_CL_GEN2_ADAPTIVE 0x000008 | ||
77 | #define SAA7706H_CL_GEN2_FINE_RATIO_MASK 0x0ffff0 | ||
78 | |||
79 | #define SAA7706H_REG_CL_GEN4 0x1ff6 | ||
80 | #define SAA7706H_CL_GEN4_BYPASS_PLL1 0x001000 | ||
81 | #define SAA7706H_CL_GEN4_PLL1_DIV_MASK 0x03e000 | ||
82 | #define SAA7706H_CL_GEN4_DSP1_TURBO 0x040000 | ||
83 | |||
84 | #define SAA7706H_REG_SEL 0x1ff7 | ||
85 | #define SAA7706H_SEL_DSP2_SRCA_MASK 0x000007 | ||
86 | #define SAA7706H_SEL_DSP2_FMTA_MASK 0x000031 | ||
87 | #define SAA7706H_SEL_DSP2_SRCB_MASK 0x0001c0 | ||
88 | #define SAA7706H_SEL_DSP2_FMTB_MASK 0x000e00 | ||
89 | #define SAA7706H_SEL_DSP1_SRC_MASK 0x003000 | ||
90 | #define SAA7706H_SEL_DSP1_FMT_MASK 0x01c003 | ||
91 | #define SAA7706H_SEL_SPDIF2 0x020000 | ||
92 | #define SAA7706H_SEL_HOST_IO_FMT_MASK 0x1c0000 | ||
93 | #define SAA7706H_SEL_EN_HOST_IO 0x200000 | ||
94 | |||
95 | #define SAA7706H_REG_IAC 0x1ff8 | ||
96 | #define SAA7706H_REG_CLK_SET 0x1ff9 | ||
97 | #define SAA7706H_REG_CLK_COEFF 0x1ffa | ||
98 | #define SAA7706H_REG_INPUT_SENS 0x1ffb | ||
99 | #define SAA7706H_INPUT_SENS_RDS_VOL_MASK 0x0003f | ||
100 | #define SAA7706H_INPUT_SENS_FM_VOL_MASK 0x00fc0 | ||
101 | #define SAA7706H_INPUT_SENS_FM_MPX 0x01000 | ||
102 | #define SAA7706H_INPUT_SENS_OFF_FILTER_A_EN 0x02000 | ||
103 | #define SAA7706H_INPUT_SENS_OFF_FILTER_B_EN 0x04000 | ||
104 | #define SAA7706H_REG_PHONE_NAV_AUDIO 0x1ffc | ||
105 | #define SAA7706H_REG_IO_CONF_DSP2 0x1ffd | ||
106 | #define SAA7706H_REG_STATUS_DSP2 0x1ffe | ||
107 | #define SAA7706H_REG_PC_DSP2 0x1fff | ||
108 | |||
109 | #define SAA7706H_DSP1_MOD0 0x0800 | ||
110 | #define SAA7706H_DSP1_ROM_VER 0x097f | ||
111 | #define SAA7706H_DSP2_MPTR0 0x1000 | ||
112 | |||
113 | #define SAA7706H_DSP1_MODPNTR 0x0000 | ||
114 | |||
115 | #define SAA7706H_DSP2_XMEM_CONTLLCW 0x113e | ||
116 | #define SAA7706H_DSP2_XMEM_BUSAMP 0x114a | ||
117 | #define SAA7706H_DSP2_XMEM_FDACPNTR 0x11f9 | ||
118 | #define SAA7706H_DSP2_XMEM_IIS1PNTR 0x11fb | ||
119 | |||
120 | #define SAA7706H_DSP2_YMEM_PVGA 0x212a | ||
121 | #define SAA7706H_DSP2_YMEM_PVAT1 0x212b | ||
122 | #define SAA7706H_DSP2_YMEM_PVAT 0x212c | ||
123 | #define SAA7706H_DSP2_YMEM_ROM_VER 0x21ff | ||
124 | |||
125 | #define SUPPORTED_DSP1_ROM_VER 0x667 | ||
126 | |||
127 | struct saa7706h_state { | ||
128 | struct v4l2_subdev sd; | ||
129 | unsigned muted; | ||
130 | }; | ||
131 | |||
132 | static inline struct saa7706h_state *to_state(struct v4l2_subdev *sd) | ||
133 | { | ||
134 | return container_of(sd, struct saa7706h_state, sd); | ||
135 | } | ||
136 | |||
137 | static int saa7706h_i2c_send(struct i2c_client *client, const u8 *data, int len) | ||
138 | { | ||
139 | int err = i2c_master_send(client, data, len); | ||
140 | if (err == len) | ||
141 | return 0; | ||
142 | return err > 0 ? -EIO : err; | ||
143 | } | ||
144 | |||
145 | static int saa7706h_i2c_transfer(struct i2c_client *client, | ||
146 | struct i2c_msg *msgs, int num) | ||
147 | { | ||
148 | int err = i2c_transfer(client->adapter, msgs, num); | ||
149 | if (err == num) | ||
150 | return 0; | ||
151 | return err > 0 ? -EIO : err; | ||
152 | } | ||
153 | |||
154 | static int saa7706h_set_reg24(struct v4l2_subdev *sd, u16 reg, u32 val) | ||
155 | { | ||
156 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
157 | u8 buf[5]; | ||
158 | int pos = 0; | ||
159 | |||
160 | buf[pos++] = reg >> 8; | ||
161 | buf[pos++] = reg; | ||
162 | buf[pos++] = val >> 16; | ||
163 | buf[pos++] = val >> 8; | ||
164 | buf[pos++] = val; | ||
165 | |||
166 | return saa7706h_i2c_send(client, buf, pos); | ||
167 | } | ||
168 | |||
169 | static int saa7706h_set_reg24_err(struct v4l2_subdev *sd, u16 reg, u32 val, | ||
170 | int *err) | ||
171 | { | ||
172 | return *err ? *err : saa7706h_set_reg24(sd, reg, val); | ||
173 | } | ||
174 | |||
175 | static int saa7706h_set_reg16(struct v4l2_subdev *sd, u16 reg, u16 val) | ||
176 | { | ||
177 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
178 | u8 buf[4]; | ||
179 | int pos = 0; | ||
180 | |||
181 | buf[pos++] = reg >> 8; | ||
182 | buf[pos++] = reg; | ||
183 | buf[pos++] = val >> 8; | ||
184 | buf[pos++] = val; | ||
185 | |||
186 | return saa7706h_i2c_send(client, buf, pos); | ||
187 | } | ||
188 | |||
189 | static int saa7706h_set_reg16_err(struct v4l2_subdev *sd, u16 reg, u16 val, | ||
190 | int *err) | ||
191 | { | ||
192 | return *err ? *err : saa7706h_set_reg16(sd, reg, val); | ||
193 | } | ||
194 | |||
195 | static int saa7706h_get_reg16(struct v4l2_subdev *sd, u16 reg) | ||
196 | { | ||
197 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
198 | u8 buf[2]; | ||
199 | int err; | ||
200 | u8 regaddr[] = {reg >> 8, reg}; | ||
201 | struct i2c_msg msg[] = { {client->addr, 0, sizeof(regaddr), regaddr}, | ||
202 | {client->addr, I2C_M_RD, sizeof(buf), buf} }; | ||
203 | |||
204 | err = saa7706h_i2c_transfer(client, msg, ARRAY_SIZE(msg)); | ||
205 | if (err) | ||
206 | return err; | ||
207 | |||
208 | return buf[0] << 8 | buf[1]; | ||
209 | } | ||
210 | |||
211 | static int saa7706h_unmute(struct v4l2_subdev *sd) | ||
212 | { | ||
213 | struct saa7706h_state *state = to_state(sd); | ||
214 | int err = 0; | ||
215 | |||
216 | err = saa7706h_set_reg16_err(sd, SAA7706H_REG_CTRL, | ||
217 | SAA7706H_CTRL_PLL3_62975MHZ | SAA7706H_CTRL_PC_RESET_DSP1 | | ||
218 | SAA7706H_CTRL_PC_RESET_DSP2, &err); | ||
219 | |||
220 | /* newer versions of the chip requires a small sleep after reset */ | ||
221 | msleep(1); | ||
222 | |||
223 | err = saa7706h_set_reg16_err(sd, SAA7706H_REG_CTRL, | ||
224 | SAA7706H_CTRL_PLL3_62975MHZ, &err); | ||
225 | |||
226 | err = saa7706h_set_reg24_err(sd, SAA7706H_REG_EVALUATION, 0, &err); | ||
227 | |||
228 | err = saa7706h_set_reg24_err(sd, SAA7706H_REG_CL_GEN1, 0x040022, &err); | ||
229 | |||
230 | err = saa7706h_set_reg24_err(sd, SAA7706H_REG_CL_GEN2, | ||
231 | SAA7706H_CL_GEN2_WSEDGE_FALLING, &err); | ||
232 | |||
233 | err = saa7706h_set_reg24_err(sd, SAA7706H_REG_CL_GEN4, 0x024080, &err); | ||
234 | |||
235 | err = saa7706h_set_reg24_err(sd, SAA7706H_REG_SEL, 0x200080, &err); | ||
236 | |||
237 | err = saa7706h_set_reg24_err(sd, SAA7706H_REG_IAC, 0xf4caed, &err); | ||
238 | |||
239 | err = saa7706h_set_reg24_err(sd, SAA7706H_REG_CLK_SET, 0x124334, &err); | ||
240 | |||
241 | err = saa7706h_set_reg24_err(sd, SAA7706H_REG_CLK_COEFF, 0x004a1a, | ||
242 | &err); | ||
243 | |||
244 | err = saa7706h_set_reg24_err(sd, SAA7706H_REG_INPUT_SENS, 0x0071c7, | ||
245 | &err); | ||
246 | |||
247 | err = saa7706h_set_reg24_err(sd, SAA7706H_REG_PHONE_NAV_AUDIO, | ||
248 | 0x0e22ff, &err); | ||
249 | |||
250 | err = saa7706h_set_reg24_err(sd, SAA7706H_REG_IO_CONF_DSP2, 0x001ff8, | ||
251 | &err); | ||
252 | |||
253 | err = saa7706h_set_reg24_err(sd, SAA7706H_REG_STATUS_DSP2, 0x080003, | ||
254 | &err); | ||
255 | |||
256 | err = saa7706h_set_reg24_err(sd, SAA7706H_REG_PC_DSP2, 0x000004, &err); | ||
257 | |||
258 | err = saa7706h_set_reg16_err(sd, SAA7706H_DSP1_MOD0, 0x0c6c, &err); | ||
259 | |||
260 | err = saa7706h_set_reg24_err(sd, SAA7706H_DSP2_MPTR0, 0x000b4b, &err); | ||
261 | |||
262 | err = saa7706h_set_reg24_err(sd, SAA7706H_DSP1_MODPNTR, 0x000600, &err); | ||
263 | |||
264 | err = saa7706h_set_reg24_err(sd, SAA7706H_DSP1_MODPNTR, 0x0000c0, &err); | ||
265 | |||
266 | err = saa7706h_set_reg24_err(sd, SAA7706H_DSP2_XMEM_CONTLLCW, 0x000819, | ||
267 | &err); | ||
268 | |||
269 | err = saa7706h_set_reg24_err(sd, SAA7706H_DSP2_XMEM_CONTLLCW, 0x00085a, | ||
270 | &err); | ||
271 | |||
272 | err = saa7706h_set_reg24_err(sd, SAA7706H_DSP2_XMEM_BUSAMP, 0x7fffff, | ||
273 | &err); | ||
274 | |||
275 | err = saa7706h_set_reg24_err(sd, SAA7706H_DSP2_XMEM_FDACPNTR, 0x2000cb, | ||
276 | &err); | ||
277 | |||
278 | err = saa7706h_set_reg24_err(sd, SAA7706H_DSP2_XMEM_IIS1PNTR, 0x2000cb, | ||
279 | &err); | ||
280 | |||
281 | err = saa7706h_set_reg16_err(sd, SAA7706H_DSP2_YMEM_PVGA, 0x0f80, &err); | ||
282 | |||
283 | err = saa7706h_set_reg16_err(sd, SAA7706H_DSP2_YMEM_PVAT1, 0x0800, | ||
284 | &err); | ||
285 | |||
286 | err = saa7706h_set_reg16_err(sd, SAA7706H_DSP2_YMEM_PVAT, 0x0800, &err); | ||
287 | |||
288 | err = saa7706h_set_reg24_err(sd, SAA7706H_DSP2_XMEM_CONTLLCW, 0x000905, | ||
289 | &err); | ||
290 | if (!err) | ||
291 | state->muted = 0; | ||
292 | return err; | ||
293 | } | ||
294 | |||
295 | static int saa7706h_mute(struct v4l2_subdev *sd) | ||
296 | { | ||
297 | struct saa7706h_state *state = to_state(sd); | ||
298 | int err; | ||
299 | |||
300 | err = saa7706h_set_reg16(sd, SAA7706H_REG_CTRL, | ||
301 | SAA7706H_CTRL_PLL3_62975MHZ | SAA7706H_CTRL_PC_RESET_DSP1 | | ||
302 | SAA7706H_CTRL_PC_RESET_DSP2); | ||
303 | if (!err) | ||
304 | state->muted = 1; | ||
305 | return err; | ||
306 | } | ||
307 | |||
308 | static int saa7706h_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) | ||
309 | { | ||
310 | switch (qc->id) { | ||
311 | case V4L2_CID_AUDIO_MUTE: | ||
312 | return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); | ||
313 | } | ||
314 | return -EINVAL; | ||
315 | } | ||
316 | |||
317 | static int saa7706h_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | ||
318 | { | ||
319 | struct saa7706h_state *state = to_state(sd); | ||
320 | |||
321 | switch (ctrl->id) { | ||
322 | case V4L2_CID_AUDIO_MUTE: | ||
323 | ctrl->value = state->muted; | ||
324 | return 0; | ||
325 | } | ||
326 | return -EINVAL; | ||
327 | } | ||
328 | |||
329 | static int saa7706h_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | ||
330 | { | ||
331 | switch (ctrl->id) { | ||
332 | case V4L2_CID_AUDIO_MUTE: | ||
333 | if (ctrl->value) | ||
334 | return saa7706h_mute(sd); | ||
335 | return saa7706h_unmute(sd); | ||
336 | } | ||
337 | return -EINVAL; | ||
338 | } | ||
339 | |||
340 | static int saa7706h_g_chip_ident(struct v4l2_subdev *sd, | ||
341 | struct v4l2_dbg_chip_ident *chip) | ||
342 | { | ||
343 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
344 | |||
345 | return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA7706H, 0); | ||
346 | } | ||
347 | |||
348 | static const struct v4l2_subdev_core_ops saa7706h_core_ops = { | ||
349 | .g_chip_ident = saa7706h_g_chip_ident, | ||
350 | .queryctrl = saa7706h_queryctrl, | ||
351 | .g_ctrl = saa7706h_g_ctrl, | ||
352 | .s_ctrl = saa7706h_s_ctrl, | ||
353 | }; | ||
354 | |||
355 | static const struct v4l2_subdev_ops saa7706h_ops = { | ||
356 | .core = &saa7706h_core_ops, | ||
357 | }; | ||
358 | |||
359 | /* | ||
360 | * Generic i2c probe | ||
361 | * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' | ||
362 | */ | ||
363 | |||
364 | static int __devinit saa7706h_probe(struct i2c_client *client, | ||
365 | const struct i2c_device_id *id) | ||
366 | { | ||
367 | struct saa7706h_state *state; | ||
368 | struct v4l2_subdev *sd; | ||
369 | int err; | ||
370 | |||
371 | /* Check if the adapter supports the needed features */ | ||
372 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
373 | return -EIO; | ||
374 | |||
375 | v4l_info(client, "chip found @ 0x%02x (%s)\n", | ||
376 | client->addr << 1, client->adapter->name); | ||
377 | |||
378 | state = kmalloc(sizeof(struct saa7706h_state), GFP_KERNEL); | ||
379 | if (state == NULL) | ||
380 | return -ENOMEM; | ||
381 | sd = &state->sd; | ||
382 | v4l2_i2c_subdev_init(sd, client, &saa7706h_ops); | ||
383 | |||
384 | /* check the rom versions */ | ||
385 | err = saa7706h_get_reg16(sd, SAA7706H_DSP1_ROM_VER); | ||
386 | if (err < 0) | ||
387 | goto err; | ||
388 | if (err != SUPPORTED_DSP1_ROM_VER) | ||
389 | v4l2_warn(sd, "Unknown DSP1 ROM code version: 0x%x\n", err); | ||
390 | |||
391 | state->muted = 1; | ||
392 | |||
393 | /* startup in a muted state */ | ||
394 | err = saa7706h_mute(sd); | ||
395 | if (err) | ||
396 | goto err; | ||
397 | |||
398 | return 0; | ||
399 | |||
400 | err: | ||
401 | v4l2_device_unregister_subdev(sd); | ||
402 | kfree(to_state(sd)); | ||
403 | |||
404 | printk(KERN_ERR DRIVER_NAME ": Failed to probe: %d\n", err); | ||
405 | |||
406 | return err; | ||
407 | } | ||
408 | |||
409 | static int __devexit saa7706h_remove(struct i2c_client *client) | ||
410 | { | ||
411 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | ||
412 | |||
413 | saa7706h_mute(sd); | ||
414 | v4l2_device_unregister_subdev(sd); | ||
415 | kfree(to_state(sd)); | ||
416 | return 0; | ||
417 | } | ||
418 | |||
419 | static const struct i2c_device_id saa7706h_id[] = { | ||
420 | {DRIVER_NAME, 0}, | ||
421 | {}, | ||
422 | }; | ||
423 | |||
424 | MODULE_DEVICE_TABLE(i2c, saa7706h_id); | ||
425 | |||
426 | static struct i2c_driver saa7706h_driver = { | ||
427 | .driver = { | ||
428 | .owner = THIS_MODULE, | ||
429 | .name = DRIVER_NAME, | ||
430 | }, | ||
431 | .probe = saa7706h_probe, | ||
432 | .remove = saa7706h_remove, | ||
433 | .id_table = saa7706h_id, | ||
434 | }; | ||
435 | |||
436 | static __init int saa7706h_init(void) | ||
437 | { | ||
438 | return i2c_add_driver(&saa7706h_driver); | ||
439 | } | ||
440 | |||
441 | static __exit void saa7706h_exit(void) | ||
442 | { | ||
443 | i2c_del_driver(&saa7706h_driver); | ||
444 | } | ||
445 | |||
446 | module_init(saa7706h_init); | ||
447 | module_exit(saa7706h_exit); | ||
448 | |||
449 | MODULE_DESCRIPTION("SAA7706H Car Radio DSP driver"); | ||
450 | MODULE_AUTHOR("Mocean Laboratories"); | ||
451 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/media/radio/si470x/radio-si470x-common.c b/drivers/media/radio/si470x/radio-si470x-common.c index 4da0f150c6e2..47075fc71f11 100644 --- a/drivers/media/radio/si470x/radio-si470x-common.c +++ b/drivers/media/radio/si470x/radio-si470x-common.c | |||
@@ -724,7 +724,7 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv, | |||
724 | tuner->audmode = V4L2_TUNER_MODE_MONO; | 724 | tuner->audmode = V4L2_TUNER_MODE_MONO; |
725 | 725 | ||
726 | /* min is worst, max is best; signal:0..0xffff; rssi: 0..0xff */ | 726 | /* min is worst, max is best; signal:0..0xffff; rssi: 0..0xff */ |
727 | /* measured in units of db쨉V in 1 db increments (max at ~75 db쨉V) */ | 727 | /* measured in units of dbµV in 1 db increments (max at ~75 dbµV) */ |
728 | tuner->signal = (radio->registers[STATUSRSSI] & STATUSRSSI_RSSI); | 728 | tuner->signal = (radio->registers[STATUSRSSI] & STATUSRSSI_RSSI); |
729 | /* the ideal factor is 0xffff/75 = 873,8 */ | 729 | /* the ideal factor is 0xffff/75 = 873,8 */ |
730 | tuner->signal = (tuner->signal * 873) + (8 * tuner->signal / 10); | 730 | tuner->signal = (tuner->signal * 873) + (8 * tuner->signal / 10); |
diff --git a/drivers/media/radio/si470x/radio-si470x-usb.c b/drivers/media/radio/si470x/radio-si470x-usb.c index a96e1b9dd646..6f60841828da 100644 --- a/drivers/media/radio/si470x/radio-si470x-usb.c +++ b/drivers/media/radio/si470x/radio-si470x-usb.c | |||
@@ -590,8 +590,9 @@ int si470x_fops_release(struct file *file) | |||
590 | video_unregister_device(radio->videodev); | 590 | video_unregister_device(radio->videodev); |
591 | kfree(radio->int_in_buffer); | 591 | kfree(radio->int_in_buffer); |
592 | kfree(radio->buffer); | 592 | kfree(radio->buffer); |
593 | mutex_unlock(&radio->disconnect_lock); | ||
593 | kfree(radio); | 594 | kfree(radio); |
594 | goto unlock; | 595 | goto done; |
595 | } | 596 | } |
596 | 597 | ||
597 | /* cancel read processes */ | 598 | /* cancel read processes */ |
@@ -601,7 +602,6 @@ int si470x_fops_release(struct file *file) | |||
601 | retval = si470x_stop(radio); | 602 | retval = si470x_stop(radio); |
602 | usb_autopm_put_interface(radio->intf); | 603 | usb_autopm_put_interface(radio->intf); |
603 | } | 604 | } |
604 | unlock: | ||
605 | mutex_unlock(&radio->disconnect_lock); | 605 | mutex_unlock(&radio->disconnect_lock); |
606 | done: | 606 | done: |
607 | return retval; | 607 | return retval; |
@@ -842,9 +842,11 @@ static void si470x_usb_driver_disconnect(struct usb_interface *intf) | |||
842 | kfree(radio->int_in_buffer); | 842 | kfree(radio->int_in_buffer); |
843 | video_unregister_device(radio->videodev); | 843 | video_unregister_device(radio->videodev); |
844 | kfree(radio->buffer); | 844 | kfree(radio->buffer); |
845 | mutex_unlock(&radio->disconnect_lock); | ||
845 | kfree(radio); | 846 | kfree(radio); |
847 | } else { | ||
848 | mutex_unlock(&radio->disconnect_lock); | ||
846 | } | 849 | } |
847 | mutex_unlock(&radio->disconnect_lock); | ||
848 | } | 850 | } |
849 | 851 | ||
850 | 852 | ||
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 2f83be766d9f..f8fc8654693d 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig | |||
@@ -388,6 +388,15 @@ config VIDEO_TVP5150 | |||
388 | To compile this driver as a module, choose M here: the | 388 | To compile this driver as a module, choose M here: the |
389 | module will be called tvp5150. | 389 | module will be called tvp5150. |
390 | 390 | ||
391 | config VIDEO_TVP7002 | ||
392 | tristate "Texas Instruments TVP7002 video decoder" | ||
393 | depends on VIDEO_V4L2 && I2C | ||
394 | ---help--- | ||
395 | Support for the Texas Instruments TVP7002 video decoder. | ||
396 | |||
397 | To compile this driver as a module, choose M here: the | ||
398 | module will be called tvp7002. | ||
399 | |||
391 | config VIDEO_VPX3220 | 400 | config VIDEO_VPX3220 |
392 | tristate "vpx3220a, vpx3216b & vpx3214c video decoders" | 401 | tristate "vpx3220a, vpx3216b & vpx3214c video decoders" |
393 | depends on VIDEO_V4L2 && I2C | 402 | depends on VIDEO_V4L2 && I2C |
@@ -548,7 +557,6 @@ config VIDEO_VPSS_SYSTEM | |||
548 | depends on ARCH_DAVINCI | 557 | depends on ARCH_DAVINCI |
549 | help | 558 | help |
550 | Support for vpss system module for video driver | 559 | Support for vpss system module for video driver |
551 | default y | ||
552 | 560 | ||
553 | config VIDEO_VPFE_CAPTURE | 561 | config VIDEO_VPFE_CAPTURE |
554 | tristate "VPFE Video Capture Driver" | 562 | tristate "VPFE Video Capture Driver" |
@@ -592,6 +600,19 @@ config VIDEO_DM355_CCDC | |||
592 | To compile this driver as a module, choose M here: the | 600 | To compile this driver as a module, choose M here: the |
593 | module will be called vpfe. | 601 | module will be called vpfe. |
594 | 602 | ||
603 | config VIDEO_ISIF | ||
604 | tristate "ISIF HW module" | ||
605 | depends on ARCH_DAVINCI_DM365 && VIDEO_VPFE_CAPTURE | ||
606 | select VIDEO_VPSS_SYSTEM | ||
607 | default y | ||
608 | help | ||
609 | Enables ISIF hw module. This is the hardware module for | ||
610 | configuring ISIF in VPFE to capture Raw Bayer RGB data from | ||
611 | a image sensor or YUV data from a YUV source. | ||
612 | |||
613 | To compile this driver as a module, choose M here: the | ||
614 | module will be called vpfe. | ||
615 | |||
595 | source "drivers/media/video/bt8xx/Kconfig" | 616 | source "drivers/media/video/bt8xx/Kconfig" |
596 | 617 | ||
597 | config VIDEO_PMS | 618 | config VIDEO_PMS |
@@ -638,9 +659,14 @@ config VIDEO_W9966 | |||
638 | information. | 659 | information. |
639 | 660 | ||
640 | config VIDEO_CPIA | 661 | config VIDEO_CPIA |
641 | tristate "CPiA Video For Linux" | 662 | tristate "CPiA Video For Linux (DEPRECATED)" |
642 | depends on VIDEO_V4L1 | 663 | depends on VIDEO_V4L1 |
664 | default n | ||
643 | ---help--- | 665 | ---help--- |
666 | This driver is DEPRECATED please use the gspca cpia1 module | ||
667 | instead. Note that you need atleast version 0.6.4 of libv4l for | ||
668 | the cpia1 gspca module. | ||
669 | |||
644 | This is the video4linux driver for cameras based on Vision's CPiA | 670 | This is the video4linux driver for cameras based on Vision's CPiA |
645 | (Colour Processor Interface ASIC), such as the Creative Labs Video | 671 | (Colour Processor Interface ASIC), such as the Creative Labs Video |
646 | Blaster Webcam II. If you have one of these cameras, say Y here | 672 | Blaster Webcam II. If you have one of these cameras, say Y here |
@@ -944,6 +970,8 @@ source "drivers/media/video/hdpvr/Kconfig" | |||
944 | 970 | ||
945 | source "drivers/media/video/em28xx/Kconfig" | 971 | source "drivers/media/video/em28xx/Kconfig" |
946 | 972 | ||
973 | source "drivers/media/video/tlg2300/Kconfig" | ||
974 | |||
947 | source "drivers/media/video/cx231xx/Kconfig" | 975 | source "drivers/media/video/cx231xx/Kconfig" |
948 | 976 | ||
949 | source "drivers/media/video/usbvision/Kconfig" | 977 | source "drivers/media/video/usbvision/Kconfig" |
@@ -955,6 +983,7 @@ source "drivers/media/video/et61x251/Kconfig" | |||
955 | config VIDEO_OVCAMCHIP | 983 | config VIDEO_OVCAMCHIP |
956 | tristate "OmniVision Camera Chip support (DEPRECATED)" | 984 | tristate "OmniVision Camera Chip support (DEPRECATED)" |
957 | depends on I2C && VIDEO_V4L1 | 985 | depends on I2C && VIDEO_V4L1 |
986 | default n | ||
958 | ---help--- | 987 | ---help--- |
959 | This driver is DEPRECATED please use the gspca ov519 module | 988 | This driver is DEPRECATED please use the gspca ov519 module |
960 | instead. Note that for the ov511 / ov518 support of the gspca module | 989 | instead. Note that for the ov511 / ov518 support of the gspca module |
@@ -971,6 +1000,7 @@ config VIDEO_OVCAMCHIP | |||
971 | config USB_W9968CF | 1000 | config USB_W9968CF |
972 | tristate "USB W996[87]CF JPEG Dual Mode Camera support (DEPRECATED)" | 1001 | tristate "USB W996[87]CF JPEG Dual Mode Camera support (DEPRECATED)" |
973 | depends on VIDEO_V4L1 && I2C && VIDEO_OVCAMCHIP | 1002 | depends on VIDEO_V4L1 && I2C && VIDEO_OVCAMCHIP |
1003 | default n | ||
974 | ---help--- | 1004 | ---help--- |
975 | This driver is DEPRECATED please use the gspca ov519 module | 1005 | This driver is DEPRECATED please use the gspca ov519 module |
976 | instead. Note that for the w9968cf support of the gspca module | 1006 | instead. Note that for the w9968cf support of the gspca module |
@@ -992,6 +1022,7 @@ config USB_W9968CF | |||
992 | config USB_OV511 | 1022 | config USB_OV511 |
993 | tristate "USB OV511 Camera support (DEPRECATED)" | 1023 | tristate "USB OV511 Camera support (DEPRECATED)" |
994 | depends on VIDEO_V4L1 | 1024 | depends on VIDEO_V4L1 |
1025 | default n | ||
995 | ---help--- | 1026 | ---help--- |
996 | This driver is DEPRECATED please use the gspca ov519 module | 1027 | This driver is DEPRECATED please use the gspca ov519 module |
997 | instead. Note that for the ov511 / ov518 support of the gspca module | 1028 | instead. Note that for the ov511 / ov518 support of the gspca module |
@@ -1020,6 +1051,7 @@ source "drivers/media/video/sn9c102/Kconfig" | |||
1020 | config USB_STV680 | 1051 | config USB_STV680 |
1021 | tristate "USB STV680 (Pencam) Camera support (DEPRECATED)" | 1052 | tristate "USB STV680 (Pencam) Camera support (DEPRECATED)" |
1022 | depends on VIDEO_V4L1 | 1053 | depends on VIDEO_V4L1 |
1054 | default n | ||
1023 | ---help--- | 1055 | ---help--- |
1024 | This driver is DEPRECATED please use the gspca stv0680 module | 1056 | This driver is DEPRECATED please use the gspca stv0680 module |
1025 | instead. Note that for the gspca stv0680 module you need | 1057 | instead. Note that for the gspca stv0680 module you need |
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 2af68ee84122..b88b6174a331 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile | |||
@@ -56,6 +56,7 @@ obj-$(CONFIG_VIDEO_THS7303) += ths7303.o | |||
56 | obj-$(CONFIG_VIDEO_VINO) += indycam.o | 56 | obj-$(CONFIG_VIDEO_VINO) += indycam.o |
57 | obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o | 57 | obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o |
58 | obj-$(CONFIG_VIDEO_TVP514X) += tvp514x.o | 58 | obj-$(CONFIG_VIDEO_TVP514X) += tvp514x.o |
59 | obj-$(CONFIG_VIDEO_TVP7002) += tvp7002.o | ||
59 | obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o | 60 | obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o |
60 | obj-$(CONFIG_VIDEO_CS5345) += cs5345.o | 61 | obj-$(CONFIG_VIDEO_CS5345) += cs5345.o |
61 | obj-$(CONFIG_VIDEO_CS53L32A) += cs53l32a.o | 62 | obj-$(CONFIG_VIDEO_CS53L32A) += cs53l32a.o |
@@ -99,6 +100,7 @@ obj-$(CONFIG_VIDEO_MEYE) += meye.o | |||
99 | obj-$(CONFIG_VIDEO_SAA7134) += saa7134/ | 100 | obj-$(CONFIG_VIDEO_SAA7134) += saa7134/ |
100 | obj-$(CONFIG_VIDEO_CX88) += cx88/ | 101 | obj-$(CONFIG_VIDEO_CX88) += cx88/ |
101 | obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ | 102 | obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ |
103 | obj-$(CONFIG_VIDEO_TLG2300) += tlg2300/ | ||
102 | obj-$(CONFIG_VIDEO_CX231XX) += cx231xx/ | 104 | obj-$(CONFIG_VIDEO_CX231XX) += cx231xx/ |
103 | obj-$(CONFIG_VIDEO_USBVISION) += usbvision/ | 105 | obj-$(CONFIG_VIDEO_USBVISION) += usbvision/ |
104 | obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/ | 106 | obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/ |
diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c index 5bb0f9e71583..547e1a93c421 100644 --- a/drivers/media/video/bt819.c +++ b/drivers/media/video/bt819.c | |||
@@ -254,7 +254,7 @@ static int bt819_s_std(struct v4l2_subdev *sd, v4l2_std_id std) | |||
254 | v4l2_err(sd, "no notify found!\n"); | 254 | v4l2_err(sd, "no notify found!\n"); |
255 | 255 | ||
256 | if (std & V4L2_STD_NTSC) { | 256 | if (std & V4L2_STD_NTSC) { |
257 | v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, 0); | 257 | v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, NULL); |
258 | bt819_setbit(decoder, 0x01, 0, 1); | 258 | bt819_setbit(decoder, 0x01, 0, 1); |
259 | bt819_setbit(decoder, 0x01, 1, 0); | 259 | bt819_setbit(decoder, 0x01, 1, 0); |
260 | bt819_setbit(decoder, 0x01, 5, 0); | 260 | bt819_setbit(decoder, 0x01, 5, 0); |
@@ -263,7 +263,7 @@ static int bt819_s_std(struct v4l2_subdev *sd, v4l2_std_id std) | |||
263 | /* bt819_setbit(decoder, 0x1a, 5, 1); */ | 263 | /* bt819_setbit(decoder, 0x1a, 5, 1); */ |
264 | timing = &timing_data[1]; | 264 | timing = &timing_data[1]; |
265 | } else if (std & V4L2_STD_PAL) { | 265 | } else if (std & V4L2_STD_PAL) { |
266 | v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, 0); | 266 | v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, NULL); |
267 | bt819_setbit(decoder, 0x01, 0, 1); | 267 | bt819_setbit(decoder, 0x01, 0, 1); |
268 | bt819_setbit(decoder, 0x01, 1, 1); | 268 | bt819_setbit(decoder, 0x01, 1, 1); |
269 | bt819_setbit(decoder, 0x01, 5, 1); | 269 | bt819_setbit(decoder, 0x01, 5, 1); |
@@ -288,7 +288,7 @@ static int bt819_s_std(struct v4l2_subdev *sd, v4l2_std_id std) | |||
288 | bt819_write(decoder, 0x08, (timing->hscale >> 8) & 0xff); | 288 | bt819_write(decoder, 0x08, (timing->hscale >> 8) & 0xff); |
289 | bt819_write(decoder, 0x09, timing->hscale & 0xff); | 289 | bt819_write(decoder, 0x09, timing->hscale & 0xff); |
290 | decoder->norm = std; | 290 | decoder->norm = std; |
291 | v4l2_subdev_notify(sd, BT819_FIFO_RESET_HIGH, 0); | 291 | v4l2_subdev_notify(sd, BT819_FIFO_RESET_HIGH, NULL); |
292 | return 0; | 292 | return 0; |
293 | } | 293 | } |
294 | 294 | ||
@@ -306,7 +306,7 @@ static int bt819_s_routing(struct v4l2_subdev *sd, | |||
306 | v4l2_err(sd, "no notify found!\n"); | 306 | v4l2_err(sd, "no notify found!\n"); |
307 | 307 | ||
308 | if (decoder->input != input) { | 308 | if (decoder->input != input) { |
309 | v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, 0); | 309 | v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, NULL); |
310 | decoder->input = input; | 310 | decoder->input = input; |
311 | /* select mode */ | 311 | /* select mode */ |
312 | if (decoder->input == 0) { | 312 | if (decoder->input == 0) { |
@@ -316,7 +316,7 @@ static int bt819_s_routing(struct v4l2_subdev *sd, | |||
316 | bt819_setbit(decoder, 0x0b, 6, 1); | 316 | bt819_setbit(decoder, 0x0b, 6, 1); |
317 | bt819_setbit(decoder, 0x1a, 1, 0); | 317 | bt819_setbit(decoder, 0x1a, 1, 0); |
318 | } | 318 | } |
319 | v4l2_subdev_notify(sd, BT819_FIFO_RESET_HIGH, 0); | 319 | v4l2_subdev_notify(sd, BT819_FIFO_RESET_HIGH, NULL); |
320 | } | 320 | } |
321 | return 0; | 321 | return 0; |
322 | } | 322 | } |
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index ae08b077fd04..cb46e8fa8aaa 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c | |||
@@ -81,6 +81,7 @@ static int video_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 }; | |||
81 | static int radio_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 }; | 81 | static int radio_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 }; |
82 | static int vbi_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 }; | 82 | static int vbi_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 }; |
83 | static int debug_latency; | 83 | static int debug_latency; |
84 | static int disable_ir; | ||
84 | 85 | ||
85 | static unsigned int fdsr; | 86 | static unsigned int fdsr; |
86 | 87 | ||
@@ -107,6 +108,7 @@ module_param(bttv_gpio, int, 0644); | |||
107 | module_param(bttv_debug, int, 0644); | 108 | module_param(bttv_debug, int, 0644); |
108 | module_param(irq_debug, int, 0644); | 109 | module_param(irq_debug, int, 0644); |
109 | module_param(debug_latency, int, 0644); | 110 | module_param(debug_latency, int, 0644); |
111 | module_param(disable_ir, int, 0444); | ||
110 | 112 | ||
111 | module_param(fdsr, int, 0444); | 113 | module_param(fdsr, int, 0444); |
112 | module_param(gbuffers, int, 0444); | 114 | module_param(gbuffers, int, 0444); |
@@ -139,6 +141,7 @@ MODULE_PARM_DESC(bttv_verbose,"verbose startup messages, default is 1 (yes)"); | |||
139 | MODULE_PARM_DESC(bttv_gpio,"log gpio changes, default is 0 (no)"); | 141 | MODULE_PARM_DESC(bttv_gpio,"log gpio changes, default is 0 (no)"); |
140 | MODULE_PARM_DESC(bttv_debug,"debug messages, default is 0 (no)"); | 142 | MODULE_PARM_DESC(bttv_debug,"debug messages, default is 0 (no)"); |
141 | MODULE_PARM_DESC(irq_debug,"irq handler debug messages, default is 0 (no)"); | 143 | MODULE_PARM_DESC(irq_debug,"irq handler debug messages, default is 0 (no)"); |
144 | MODULE_PARM_DESC(disable_ir, "disable infrared remote support"); | ||
142 | MODULE_PARM_DESC(gbuffers,"number of capture buffers. range 2-32, default 8"); | 145 | MODULE_PARM_DESC(gbuffers,"number of capture buffers. range 2-32, default 8"); |
143 | MODULE_PARM_DESC(gbufsize,"size of the capture buffers, default is 0x208000"); | 146 | MODULE_PARM_DESC(gbufsize,"size of the capture buffers, default is 0x208000"); |
144 | MODULE_PARM_DESC(reset_crop,"reset cropping parameters at open(), default " | 147 | MODULE_PARM_DESC(reset_crop,"reset cropping parameters at open(), default " |
@@ -4461,8 +4464,10 @@ static int __devinit bttv_probe(struct pci_dev *dev, | |||
4461 | request_modules(btv); | 4464 | request_modules(btv); |
4462 | } | 4465 | } |
4463 | 4466 | ||
4464 | init_bttv_i2c_ir(btv); | 4467 | if (!disable_ir) { |
4465 | bttv_input_init(btv); | 4468 | init_bttv_i2c_ir(btv); |
4469 | bttv_input_init(btv); | ||
4470 | } | ||
4466 | 4471 | ||
4467 | /* everything is fine */ | 4472 | /* everything is fine */ |
4468 | bttv_num++; | 4473 | bttv_num++; |
diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c index 277a092e1214..b320dbd635aa 100644 --- a/drivers/media/video/bt8xx/bttv-input.c +++ b/drivers/media/video/bt8xx/bttv-input.c | |||
@@ -247,7 +247,7 @@ int bttv_input_init(struct bttv *btv) | |||
247 | struct card_ir *ir; | 247 | struct card_ir *ir; |
248 | struct ir_scancode_table *ir_codes = NULL; | 248 | struct ir_scancode_table *ir_codes = NULL; |
249 | struct input_dev *input_dev; | 249 | struct input_dev *input_dev; |
250 | int ir_type = IR_TYPE_OTHER; | 250 | u64 ir_type = IR_TYPE_OTHER; |
251 | int err = -ENOMEM; | 251 | int err = -ENOMEM; |
252 | 252 | ||
253 | if (!btv->has_remote) | 253 | if (!btv->has_remote) |
@@ -389,7 +389,7 @@ int bttv_input_init(struct bttv *btv) | |||
389 | bttv_ir_start(btv, ir); | 389 | bttv_ir_start(btv, ir); |
390 | 390 | ||
391 | /* all done */ | 391 | /* all done */ |
392 | err = ir_input_register(btv->remote->dev, ir_codes); | 392 | err = ir_input_register(btv->remote->dev, ir_codes, NULL); |
393 | if (err) | 393 | if (err) |
394 | goto err_out_stop; | 394 | goto err_out_stop; |
395 | 395 | ||
diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c index 7bb9c1ec7819..cbbf7e80d2cf 100644 --- a/drivers/media/video/cafe_ccic.c +++ b/drivers/media/video/cafe_ccic.c | |||
@@ -1907,7 +1907,6 @@ static int cafe_pci_probe(struct pci_dev *pdev, | |||
1907 | goto out_free; | 1907 | goto out_free; |
1908 | 1908 | ||
1909 | mutex_init(&cam->s_mutex); | 1909 | mutex_init(&cam->s_mutex); |
1910 | mutex_lock(&cam->s_mutex); | ||
1911 | spin_lock_init(&cam->dev_lock); | 1910 | spin_lock_init(&cam->dev_lock); |
1912 | cam->state = S_NOTREADY; | 1911 | cam->state = S_NOTREADY; |
1913 | cafe_set_config_needed(cam, 1); | 1912 | cafe_set_config_needed(cam, 1); |
@@ -1947,7 +1946,6 @@ static int cafe_pci_probe(struct pci_dev *pdev, | |||
1947 | * because the sensor could attach in this call chain, leading to | 1946 | * because the sensor could attach in this call chain, leading to |
1948 | * unsightly deadlocks. | 1947 | * unsightly deadlocks. |
1949 | */ | 1948 | */ |
1950 | mutex_unlock(&cam->s_mutex); /* attach can deadlock */ | ||
1951 | ret = cafe_smbus_setup(cam); | 1949 | ret = cafe_smbus_setup(cam); |
1952 | if (ret) | 1950 | if (ret) |
1953 | goto out_freeirq; | 1951 | goto out_freeirq; |
@@ -1973,7 +1971,7 @@ static int cafe_pci_probe(struct pci_dev *pdev, | |||
1973 | cam->vdev.v4l2_dev = &cam->v4l2_dev; | 1971 | cam->vdev.v4l2_dev = &cam->v4l2_dev; |
1974 | ret = video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1); | 1972 | ret = video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1); |
1975 | if (ret) | 1973 | if (ret) |
1976 | goto out_smbus; | 1974 | goto out_unlock; |
1977 | video_set_drvdata(&cam->vdev, cam); | 1975 | video_set_drvdata(&cam->vdev, cam); |
1978 | 1976 | ||
1979 | /* | 1977 | /* |
@@ -1988,6 +1986,8 @@ static int cafe_pci_probe(struct pci_dev *pdev, | |||
1988 | mutex_unlock(&cam->s_mutex); | 1986 | mutex_unlock(&cam->s_mutex); |
1989 | return 0; | 1987 | return 0; |
1990 | 1988 | ||
1989 | out_unlock: | ||
1990 | mutex_unlock(&cam->s_mutex); | ||
1991 | out_smbus: | 1991 | out_smbus: |
1992 | cafe_smbus_shutdown(cam); | 1992 | cafe_smbus_shutdown(cam); |
1993 | out_freeirq: | 1993 | out_freeirq: |
diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c index 551ddf216a4b..933ae4c8cb9a 100644 --- a/drivers/media/video/cpia.c +++ b/drivers/media/video/cpia.c | |||
@@ -3737,9 +3737,6 @@ static int cpia_mmap(struct file *file, struct vm_area_struct *vma) | |||
3737 | if (size > FRAME_NUM*CPIA_MAX_FRAME_SIZE) | 3737 | if (size > FRAME_NUM*CPIA_MAX_FRAME_SIZE) |
3738 | return -EINVAL; | 3738 | return -EINVAL; |
3739 | 3739 | ||
3740 | if (!cam || !cam->ops) | ||
3741 | return -ENODEV; | ||
3742 | |||
3743 | /* make this _really_ smp-safe */ | 3740 | /* make this _really_ smp-safe */ |
3744 | if (mutex_lock_interruptible(&cam->busy_lock)) | 3741 | if (mutex_lock_interruptible(&cam->busy_lock)) |
3745 | return -EINTR; | 3742 | return -EINTR; |
diff --git a/drivers/media/video/cx18/Kconfig b/drivers/media/video/cx18/Kconfig index e8a50a611ebc..baf7e91ee0f5 100644 --- a/drivers/media/video/cx18/Kconfig +++ b/drivers/media/video/cx18/Kconfig | |||
@@ -19,3 +19,14 @@ config VIDEO_CX18 | |||
19 | 19 | ||
20 | To compile this driver as a module, choose M here: the | 20 | To compile this driver as a module, choose M here: the |
21 | module will be called cx18. | 21 | module will be called cx18. |
22 | |||
23 | config VIDEO_CX18_ALSA | ||
24 | tristate "Conexant 23418 DMA audio support" | ||
25 | depends on VIDEO_CX18 && SND && EXPERIMENTAL | ||
26 | select SND_PCM | ||
27 | ---help--- | ||
28 | This is a video4linux driver for direct (DMA) audio on | ||
29 | Conexant 23418 based TV cards using ALSA. | ||
30 | |||
31 | To compile this driver as a module, choose M here: the | ||
32 | module will be called cx18-alsa. | ||
diff --git a/drivers/media/video/cx18/Makefile b/drivers/media/video/cx18/Makefile index f7bf0edf93f9..2fadd9ded340 100644 --- a/drivers/media/video/cx18/Makefile +++ b/drivers/media/video/cx18/Makefile | |||
@@ -3,8 +3,10 @@ cx18-objs := cx18-driver.o cx18-cards.o cx18-i2c.o cx18-firmware.o cx18-gpio. | |||
3 | cx18-mailbox.o cx18-vbi.o cx18-audio.o cx18-video.o cx18-irq.o \ | 3 | cx18-mailbox.o cx18-vbi.o cx18-audio.o cx18-video.o cx18-irq.o \ |
4 | cx18-av-core.o cx18-av-audio.o cx18-av-firmware.o cx18-av-vbi.o cx18-scb.o \ | 4 | cx18-av-core.o cx18-av-audio.o cx18-av-firmware.o cx18-av-vbi.o cx18-scb.o \ |
5 | cx18-dvb.o cx18-io.o | 5 | cx18-dvb.o cx18-io.o |
6 | cx18-alsa-objs := cx18-alsa-main.o cx18-alsa-pcm.o | ||
6 | 7 | ||
7 | obj-$(CONFIG_VIDEO_CX18) += cx18.o | 8 | obj-$(CONFIG_VIDEO_CX18) += cx18.o |
9 | obj-$(CONFIG_VIDEO_CX18_ALSA) += cx18-alsa.o | ||
8 | 10 | ||
9 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core | 11 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core |
10 | EXTRA_CFLAGS += -Idrivers/media/dvb/frontends | 12 | EXTRA_CFLAGS += -Idrivers/media/dvb/frontends |
diff --git a/drivers/media/video/cx18/cx18-alsa-main.c b/drivers/media/video/cx18/cx18-alsa-main.c new file mode 100644 index 000000000000..eb41d7ec65b9 --- /dev/null +++ b/drivers/media/video/cx18/cx18-alsa-main.c | |||
@@ -0,0 +1,293 @@ | |||
1 | /* | ||
2 | * ALSA interface to cx18 PCM capture streams | ||
3 | * | ||
4 | * Copyright (C) 2009 Andy Walls <awalls@radix.net> | ||
5 | * Copyright (C) 2009 Devin Heitmueller <dheitmueller@kernellabs.com> | ||
6 | * | ||
7 | * Portions of this work were sponsored by ONELAN Limited. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | ||
22 | * 02111-1307 USA | ||
23 | */ | ||
24 | |||
25 | #include <linux/init.h> | ||
26 | #include <linux/module.h> | ||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/device.h> | ||
29 | #include <linux/spinlock.h> | ||
30 | |||
31 | #include <media/v4l2-device.h> | ||
32 | |||
33 | #include <sound/core.h> | ||
34 | #include <sound/initval.h> | ||
35 | |||
36 | #include "cx18-driver.h" | ||
37 | #include "cx18-version.h" | ||
38 | #include "cx18-alsa.h" | ||
39 | #include "cx18-alsa-mixer.h" | ||
40 | #include "cx18-alsa-pcm.h" | ||
41 | |||
42 | int cx18_alsa_debug; | ||
43 | |||
44 | #define CX18_DEBUG_ALSA_INFO(fmt, arg...) \ | ||
45 | do { \ | ||
46 | if (cx18_alsa_debug & 2) \ | ||
47 | printk(KERN_INFO "%s: " fmt, "cx18-alsa", ## arg); \ | ||
48 | } while (0); | ||
49 | |||
50 | module_param_named(debug, cx18_alsa_debug, int, 0644); | ||
51 | MODULE_PARM_DESC(debug, | ||
52 | "Debug level (bitmask). Default: 0\n" | ||
53 | "\t\t\t 1/0x0001: warning\n" | ||
54 | "\t\t\t 2/0x0002: info\n"); | ||
55 | |||
56 | MODULE_AUTHOR("Andy Walls"); | ||
57 | MODULE_DESCRIPTION("CX23418 ALSA Interface"); | ||
58 | MODULE_SUPPORTED_DEVICE("CX23418 MPEG2 encoder"); | ||
59 | MODULE_LICENSE("GPL"); | ||
60 | |||
61 | MODULE_VERSION(CX18_VERSION); | ||
62 | |||
63 | static inline | ||
64 | struct snd_cx18_card *to_snd_cx18_card(struct v4l2_device *v4l2_dev) | ||
65 | { | ||
66 | return to_cx18(v4l2_dev)->alsa; | ||
67 | } | ||
68 | |||
69 | static inline | ||
70 | struct snd_cx18_card *p_to_snd_cx18_card(struct v4l2_device **v4l2_dev) | ||
71 | { | ||
72 | return container_of(v4l2_dev, struct snd_cx18_card, v4l2_dev); | ||
73 | } | ||
74 | |||
75 | static void snd_cx18_card_free(struct snd_cx18_card *cxsc) | ||
76 | { | ||
77 | if (cxsc == NULL) | ||
78 | return; | ||
79 | |||
80 | if (cxsc->v4l2_dev != NULL) | ||
81 | to_cx18(cxsc->v4l2_dev)->alsa = NULL; | ||
82 | |||
83 | /* FIXME - take any other stopping actions needed */ | ||
84 | |||
85 | kfree(cxsc); | ||
86 | } | ||
87 | |||
88 | static void snd_cx18_card_private_free(struct snd_card *sc) | ||
89 | { | ||
90 | if (sc == NULL) | ||
91 | return; | ||
92 | snd_cx18_card_free(sc->private_data); | ||
93 | sc->private_data = NULL; | ||
94 | sc->private_free = NULL; | ||
95 | } | ||
96 | |||
97 | static int snd_cx18_card_create(struct v4l2_device *v4l2_dev, | ||
98 | struct snd_card *sc, | ||
99 | struct snd_cx18_card **cxsc) | ||
100 | { | ||
101 | *cxsc = kzalloc(sizeof(struct snd_cx18_card), GFP_KERNEL); | ||
102 | if (*cxsc == NULL) | ||
103 | return -ENOMEM; | ||
104 | |||
105 | (*cxsc)->v4l2_dev = v4l2_dev; | ||
106 | (*cxsc)->sc = sc; | ||
107 | |||
108 | sc->private_data = *cxsc; | ||
109 | sc->private_free = snd_cx18_card_private_free; | ||
110 | |||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | static int snd_cx18_card_set_names(struct snd_cx18_card *cxsc) | ||
115 | { | ||
116 | struct cx18 *cx = to_cx18(cxsc->v4l2_dev); | ||
117 | struct snd_card *sc = cxsc->sc; | ||
118 | |||
119 | /* sc->driver is used by alsa-lib's configurator: simple, unique */ | ||
120 | strlcpy(sc->driver, "CX23418", sizeof(sc->driver)); | ||
121 | |||
122 | /* sc->shortname is a symlink in /proc/asound: CX18-M -> cardN */ | ||
123 | snprintf(sc->shortname, sizeof(sc->shortname), "CX18-%d", | ||
124 | cx->instance); | ||
125 | |||
126 | /* sc->longname is read from /proc/asound/cards */ | ||
127 | snprintf(sc->longname, sizeof(sc->longname), | ||
128 | "CX23418 #%d %s TV/FM Radio/Line-In Capture", | ||
129 | cx->instance, cx->card_name); | ||
130 | |||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | static int snd_cx18_init(struct v4l2_device *v4l2_dev) | ||
135 | { | ||
136 | struct cx18 *cx = to_cx18(v4l2_dev); | ||
137 | struct snd_card *sc = NULL; | ||
138 | struct snd_cx18_card *cxsc; | ||
139 | int ret; | ||
140 | |||
141 | /* Numbrs steps from "Writing an ALSA Driver" by Takashi Iwai */ | ||
142 | |||
143 | /* (1) Check and increment the device index */ | ||
144 | /* This is a no-op for us. We'll use the cx->instance */ | ||
145 | |||
146 | /* (2) Create a card instance */ | ||
147 | ret = snd_card_create(SNDRV_DEFAULT_IDX1, /* use first available id */ | ||
148 | SNDRV_DEFAULT_STR1, /* xid from end of shortname*/ | ||
149 | THIS_MODULE, 0, &sc); | ||
150 | if (ret) { | ||
151 | CX18_ALSA_ERR("%s: snd_card_create() failed with err %d\n", | ||
152 | __func__, ret); | ||
153 | goto err_exit; | ||
154 | } | ||
155 | |||
156 | /* (3) Create a main component */ | ||
157 | ret = snd_cx18_card_create(v4l2_dev, sc, &cxsc); | ||
158 | if (ret) { | ||
159 | CX18_ALSA_ERR("%s: snd_cx18_card_create() failed with err %d\n", | ||
160 | __func__, ret); | ||
161 | goto err_exit_free; | ||
162 | } | ||
163 | |||
164 | /* (4) Set the driver ID and name strings */ | ||
165 | snd_cx18_card_set_names(cxsc); | ||
166 | |||
167 | |||
168 | ret = snd_cx18_pcm_create(cxsc); | ||
169 | if (ret) { | ||
170 | CX18_ALSA_ERR("%s: snd_cx18_pcm_create() failed with err %d\n", | ||
171 | __func__, ret); | ||
172 | goto err_exit_free; | ||
173 | } | ||
174 | /* FIXME - proc files */ | ||
175 | |||
176 | /* (7) Set the driver data and return 0 */ | ||
177 | /* We do this out of normal order for PCI drivers to avoid races */ | ||
178 | cx->alsa = cxsc; | ||
179 | |||
180 | /* (6) Register the card instance */ | ||
181 | ret = snd_card_register(sc); | ||
182 | if (ret) { | ||
183 | cx->alsa = NULL; | ||
184 | CX18_ALSA_ERR("%s: snd_card_register() failed with err %d\n", | ||
185 | __func__, ret); | ||
186 | goto err_exit_free; | ||
187 | } | ||
188 | |||
189 | return 0; | ||
190 | |||
191 | err_exit_free: | ||
192 | if (sc != NULL) | ||
193 | snd_card_free(sc); | ||
194 | err_exit: | ||
195 | return ret; | ||
196 | } | ||
197 | |||
198 | int cx18_alsa_load(struct cx18 *cx) | ||
199 | { | ||
200 | struct v4l2_device *v4l2_dev = &cx->v4l2_dev; | ||
201 | struct cx18_stream *s; | ||
202 | |||
203 | if (v4l2_dev == NULL) { | ||
204 | printk(KERN_ERR "cx18-alsa: %s: struct v4l2_device * is NULL\n", | ||
205 | __func__); | ||
206 | return 0; | ||
207 | } | ||
208 | |||
209 | cx = to_cx18(v4l2_dev); | ||
210 | if (cx == NULL) { | ||
211 | printk(KERN_ERR "cx18-alsa cx is NULL\n"); | ||
212 | return 0; | ||
213 | } | ||
214 | |||
215 | s = &cx->streams[CX18_ENC_STREAM_TYPE_PCM]; | ||
216 | if (s->video_dev == NULL) { | ||
217 | CX18_DEBUG_ALSA_INFO("%s: PCM stream for card is disabled - " | ||
218 | "skipping\n", __func__); | ||
219 | return 0; | ||
220 | } | ||
221 | |||
222 | if (cx->alsa != NULL) { | ||
223 | CX18_ALSA_ERR("%s: struct snd_cx18_card * already exists\n", | ||
224 | __func__); | ||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | if (snd_cx18_init(v4l2_dev)) { | ||
229 | CX18_ALSA_ERR("%s: failed to create struct snd_cx18_card\n", | ||
230 | __func__); | ||
231 | } else { | ||
232 | CX18_DEBUG_ALSA_INFO("%s: created cx18 ALSA interface instance " | ||
233 | "\n", __func__); | ||
234 | } | ||
235 | return 0; | ||
236 | } | ||
237 | |||
238 | static int __init cx18_alsa_init(void) | ||
239 | { | ||
240 | printk(KERN_INFO "cx18-alsa: module loading...\n"); | ||
241 | cx18_ext_init = &cx18_alsa_load; | ||
242 | return 0; | ||
243 | } | ||
244 | |||
245 | static void __exit snd_cx18_exit(struct snd_cx18_card *cxsc) | ||
246 | { | ||
247 | struct cx18 *cx = to_cx18(cxsc->v4l2_dev); | ||
248 | |||
249 | /* FIXME - pointer checks & shutdown cxsc */ | ||
250 | |||
251 | snd_card_free(cxsc->sc); | ||
252 | cx->alsa = NULL; | ||
253 | } | ||
254 | |||
255 | static int __exit cx18_alsa_exit_callback(struct device *dev, void *data) | ||
256 | { | ||
257 | struct v4l2_device *v4l2_dev = dev_get_drvdata(dev); | ||
258 | struct snd_cx18_card *cxsc; | ||
259 | |||
260 | if (v4l2_dev == NULL) { | ||
261 | printk(KERN_ERR "cx18-alsa: %s: struct v4l2_device * is NULL\n", | ||
262 | __func__); | ||
263 | return 0; | ||
264 | } | ||
265 | |||
266 | cxsc = to_snd_cx18_card(v4l2_dev); | ||
267 | if (cxsc == NULL) { | ||
268 | CX18_ALSA_WARN("%s: struct snd_cx18_card * is NULL\n", | ||
269 | __func__); | ||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | snd_cx18_exit(cxsc); | ||
274 | return 0; | ||
275 | } | ||
276 | |||
277 | static void __exit cx18_alsa_exit(void) | ||
278 | { | ||
279 | struct device_driver *drv; | ||
280 | int ret; | ||
281 | |||
282 | printk(KERN_INFO "cx18-alsa: module unloading...\n"); | ||
283 | |||
284 | drv = driver_find("cx18", &pci_bus_type); | ||
285 | ret = driver_for_each_device(drv, NULL, NULL, cx18_alsa_exit_callback); | ||
286 | put_driver(drv); | ||
287 | |||
288 | cx18_ext_init = NULL; | ||
289 | printk(KERN_INFO "cx18-alsa: module unload complete\n"); | ||
290 | } | ||
291 | |||
292 | module_init(cx18_alsa_init); | ||
293 | module_exit(cx18_alsa_exit); | ||
diff --git a/drivers/media/video/cx18/cx18-alsa-mixer.c b/drivers/media/video/cx18/cx18-alsa-mixer.c new file mode 100644 index 000000000000..ef21114309fe --- /dev/null +++ b/drivers/media/video/cx18/cx18-alsa-mixer.c | |||
@@ -0,0 +1,175 @@ | |||
1 | /* | ||
2 | * ALSA mixer controls for the | ||
3 | * ALSA interface to cx18 PCM capture streams | ||
4 | * | ||
5 | * Copyright (C) 2009 Andy Walls <awalls@radix.net> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | ||
20 | * 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | #include <linux/init.h> | ||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/device.h> | ||
26 | #include <linux/spinlock.h> | ||
27 | #include <linux/videodev2.h> | ||
28 | |||
29 | #include <media/v4l2-device.h> | ||
30 | |||
31 | #include <sound/core.h> | ||
32 | #include <sound/control.h> | ||
33 | #include <sound/tlv.h> | ||
34 | |||
35 | #include "cx18-alsa.h" | ||
36 | #include "cx18-driver.h" | ||
37 | |||
38 | /* | ||
39 | * Note the cx18-av-core volume scale is funny, due to the alignment of the | ||
40 | * scale with another chip's range: | ||
41 | * | ||
42 | * v4l2_control value /512 indicated dB actual dB reg 0x8d4 | ||
43 | * 0x0000 - 0x01ff 0 -119 -96 228 | ||
44 | * 0x0200 - 0x02ff 1 -118 -96 228 | ||
45 | * ... | ||
46 | * 0x2c00 - 0x2dff 22 -97 -96 228 | ||
47 | * 0x2e00 - 0x2fff 23 -96 -96 228 | ||
48 | * 0x3000 - 0x31ff 24 -95 -95 226 | ||
49 | * ... | ||
50 | * 0xee00 - 0xefff 119 0 0 36 | ||
51 | * ... | ||
52 | * 0xfe00 - 0xffff 127 +8 +8 20 | ||
53 | */ | ||
54 | static inline int dB_to_cx18_av_vol(int dB) | ||
55 | { | ||
56 | if (dB < -96) | ||
57 | dB = -96; | ||
58 | else if (dB > 8) | ||
59 | dB = 8; | ||
60 | return (dB + 119) << 9; | ||
61 | } | ||
62 | |||
63 | static inline int cx18_av_vol_to_dB(int v) | ||
64 | { | ||
65 | if (v < (23 << 9)) | ||
66 | v = (23 << 9); | ||
67 | else if (v > (127 << 9)) | ||
68 | v = (127 << 9); | ||
69 | return (v >> 9) - 119; | ||
70 | } | ||
71 | |||
72 | static int snd_cx18_mixer_tv_vol_info(struct snd_kcontrol *kcontrol, | ||
73 | struct snd_ctl_elem_info *uinfo) | ||
74 | { | ||
75 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
76 | uinfo->count = 1; | ||
77 | /* We're already translating values, just keep this control in dB */ | ||
78 | uinfo->value.integer.min = -96; | ||
79 | uinfo->value.integer.max = 8; | ||
80 | uinfo->value.integer.step = 1; | ||
81 | return 0; | ||
82 | } | ||
83 | |||
84 | static int snd_cx18_mixer_tv_vol_get(struct snd_kcontrol *kctl, | ||
85 | struct snd_ctl_elem_value *uctl) | ||
86 | { | ||
87 | struct snd_cx18_card *cxsc = snd_kcontrol_chip(kctl); | ||
88 | struct cx18 *cx = to_cx18(cxsc->v4l2_dev); | ||
89 | struct v4l2_control vctrl; | ||
90 | int ret; | ||
91 | |||
92 | vctrl.id = V4L2_CID_AUDIO_VOLUME; | ||
93 | vctrl.value = dB_to_cx18_av_vol(uctl->value.integer.value[0]); | ||
94 | |||
95 | snd_cx18_lock(cxsc); | ||
96 | ret = v4l2_subdev_call(cx->sd_av, core, g_ctrl, &vctrl); | ||
97 | snd_cx18_unlock(cxsc); | ||
98 | |||
99 | if (!ret) | ||
100 | uctl->value.integer.value[0] = cx18_av_vol_to_dB(vctrl.value); | ||
101 | return ret; | ||
102 | } | ||
103 | |||
104 | static int snd_cx18_mixer_tv_vol_put(struct snd_kcontrol *kctl, | ||
105 | struct snd_ctl_elem_value *uctl) | ||
106 | { | ||
107 | struct snd_cx18_card *cxsc = snd_kcontrol_chip(kctl); | ||
108 | struct cx18 *cx = to_cx18(cxsc->v4l2_dev); | ||
109 | struct v4l2_control vctrl; | ||
110 | int ret; | ||
111 | |||
112 | vctrl.id = V4L2_CID_AUDIO_VOLUME; | ||
113 | vctrl.value = dB_to_cx18_av_vol(uctl->value.integer.value[0]); | ||
114 | |||
115 | snd_cx18_lock(cxsc); | ||
116 | |||
117 | /* Fetch current state */ | ||
118 | ret = v4l2_subdev_call(cx->sd_av, core, g_ctrl, &vctrl); | ||
119 | |||
120 | if (ret || | ||
121 | (cx18_av_vol_to_dB(vctrl.value) != uctl->value.integer.value[0])) { | ||
122 | |||
123 | /* Set, if needed */ | ||
124 | vctrl.value = dB_to_cx18_av_vol(uctl->value.integer.value[0]); | ||
125 | ret = v4l2_subdev_call(cx->sd_av, core, s_ctrl, &vctrl); | ||
126 | if (!ret) | ||
127 | ret = 1; /* Indicate control was changed w/o error */ | ||
128 | } | ||
129 | snd_cx18_unlock(cxsc); | ||
130 | |||
131 | return ret; | ||
132 | } | ||
133 | |||
134 | |||
135 | /* This is a bit of overkill, the slider is already in dB internally */ | ||
136 | static DECLARE_TLV_DB_SCALE(snd_cx18_mixer_tv_vol_db_scale, -9600, 100, 0); | ||
137 | |||
138 | static struct snd_kcontrol_new snd_cx18_mixer_tv_vol __initdata = { | ||
139 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
140 | .name = "Analog TV Capture Volume", | ||
141 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
142 | SNDRV_CTL_ELEM_ACCESS_TLV_READ, | ||
143 | .info = snd_cx18_mixer_tv_volume_info, | ||
144 | .get = snd_cx18_mixer_tv_volume_get, | ||
145 | .put = snd_cx18_mixer_tv_volume_put, | ||
146 | .tlv.p = snd_cx18_mixer_tv_vol_db_scale | ||
147 | }; | ||
148 | |||
149 | /* FIXME - add mute switch and balance, bass, treble sliders: | ||
150 | V4L2_CID_AUDIO_MUTE | ||
151 | |||
152 | V4L2_CID_AUDIO_BALANCE | ||
153 | |||
154 | V4L2_CID_AUDIO_BASS | ||
155 | V4L2_CID_AUDIO_TREBLE | ||
156 | */ | ||
157 | |||
158 | /* FIXME - add stereo, lang1, lang2, mono menu */ | ||
159 | /* FIXME - add CS5345 I2S volume for HVR-1600 */ | ||
160 | |||
161 | int __init snd_cx18_mixer_create(struct snd_cx18_card *cxsc) | ||
162 | { | ||
163 | struct v4l2_device *v4l2_dev = cxsc->v4l2_dev; | ||
164 | struct snd_card *sc = cxsc->sc; | ||
165 | int ret; | ||
166 | |||
167 | strlcpy(sc->mixername, "CX23418 Mixer", sizeof(sc->mixername)); | ||
168 | |||
169 | ret = snd_ctl_add(sc, snd_ctl_new1(snd_cx18_mixer_tv_vol, cxsc)); | ||
170 | if (ret) { | ||
171 | CX18_ALSA_WARN("%s: failed to add %s control, err %d\n", | ||
172 | __func__, snd_cx18_mixer_tv_vol.name, ret); | ||
173 | } | ||
174 | return ret; | ||
175 | } | ||
diff --git a/drivers/media/video/cx18/cx18-alsa-mixer.h b/drivers/media/video/cx18/cx18-alsa-mixer.h new file mode 100644 index 000000000000..2d418db000fe --- /dev/null +++ b/drivers/media/video/cx18/cx18-alsa-mixer.h | |||
@@ -0,0 +1,23 @@ | |||
1 | /* | ||
2 | * ALSA mixer controls for the | ||
3 | * ALSA interface to cx18 PCM capture streams | ||
4 | * | ||
5 | * Copyright (C) 2009 Andy Walls <awalls@radix.net> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | ||
20 | * 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | int __init snd_cx18_mixer_create(struct snd_cx18_card *cxsc); | ||
diff --git a/drivers/media/video/cx18/cx18-alsa-pcm.c b/drivers/media/video/cx18/cx18-alsa-pcm.c new file mode 100644 index 000000000000..2bd312daeb1e --- /dev/null +++ b/drivers/media/video/cx18/cx18-alsa-pcm.c | |||
@@ -0,0 +1,354 @@ | |||
1 | /* | ||
2 | * ALSA PCM device for the | ||
3 | * ALSA interface to cx18 PCM capture streams | ||
4 | * | ||
5 | * Copyright (C) 2009 Andy Walls <awalls@radix.net> | ||
6 | * Copyright (C) 2009 Devin Heitmueller <dheitmueller@kernellabs.com> | ||
7 | * | ||
8 | * Portions of this work were sponsored by ONELAN Limited. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | ||
23 | * 02111-1307 USA | ||
24 | */ | ||
25 | |||
26 | #include <linux/init.h> | ||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/vmalloc.h> | ||
29 | |||
30 | #include <media/v4l2-device.h> | ||
31 | |||
32 | #include <sound/core.h> | ||
33 | #include <sound/pcm.h> | ||
34 | |||
35 | #include "cx18-driver.h" | ||
36 | #include "cx18-queue.h" | ||
37 | #include "cx18-streams.h" | ||
38 | #include "cx18-fileops.h" | ||
39 | #include "cx18-alsa.h" | ||
40 | |||
41 | static unsigned int pcm_debug; | ||
42 | module_param(pcm_debug, int, 0644); | ||
43 | MODULE_PARM_DESC(pcm_debug, "enable debug messages for pcm"); | ||
44 | |||
45 | #define dprintk(fmt, arg...) do { \ | ||
46 | if (pcm_debug) \ | ||
47 | printk(KERN_INFO "cx18-alsa-pcm %s: " fmt, \ | ||
48 | __func__, ##arg); \ | ||
49 | } while (0) | ||
50 | |||
51 | static struct snd_pcm_hardware snd_cx18_hw_capture = { | ||
52 | .info = SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
53 | SNDRV_PCM_INFO_MMAP | | ||
54 | SNDRV_PCM_INFO_INTERLEAVED | | ||
55 | SNDRV_PCM_INFO_MMAP_VALID, | ||
56 | |||
57 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
58 | |||
59 | .rates = SNDRV_PCM_RATE_48000, | ||
60 | |||
61 | .rate_min = 48000, | ||
62 | .rate_max = 48000, | ||
63 | .channels_min = 2, | ||
64 | .channels_max = 2, | ||
65 | .buffer_bytes_max = 62720 * 8, /* just about the value in usbaudio.c */ | ||
66 | .period_bytes_min = 64, /* 12544/2, */ | ||
67 | .period_bytes_max = 12544, | ||
68 | .periods_min = 2, | ||
69 | .periods_max = 98, /* 12544, */ | ||
70 | }; | ||
71 | |||
72 | void cx18_alsa_announce_pcm_data(struct snd_cx18_card *cxsc, u8 *pcm_data, | ||
73 | size_t num_bytes) | ||
74 | { | ||
75 | struct snd_pcm_substream *substream; | ||
76 | struct snd_pcm_runtime *runtime; | ||
77 | unsigned int oldptr; | ||
78 | unsigned int stride; | ||
79 | int period_elapsed = 0; | ||
80 | int length; | ||
81 | |||
82 | dprintk("cx18 alsa announce ptr=%p data=%p num_bytes=%zd\n", cxsc, | ||
83 | pcm_data, num_bytes); | ||
84 | |||
85 | substream = cxsc->capture_pcm_substream; | ||
86 | if (substream == NULL) { | ||
87 | dprintk("substream was NULL\n"); | ||
88 | return; | ||
89 | } | ||
90 | |||
91 | runtime = substream->runtime; | ||
92 | if (runtime == NULL) { | ||
93 | dprintk("runtime was NULL\n"); | ||
94 | return; | ||
95 | } | ||
96 | |||
97 | stride = runtime->frame_bits >> 3; | ||
98 | if (stride == 0) { | ||
99 | dprintk("stride is zero\n"); | ||
100 | return; | ||
101 | } | ||
102 | |||
103 | length = num_bytes / stride; | ||
104 | if (length == 0) { | ||
105 | dprintk("%s: length was zero\n", __func__); | ||
106 | return; | ||
107 | } | ||
108 | |||
109 | if (runtime->dma_area == NULL) { | ||
110 | dprintk("dma area was NULL - ignoring\n"); | ||
111 | return; | ||
112 | } | ||
113 | |||
114 | oldptr = cxsc->hwptr_done_capture; | ||
115 | if (oldptr + length >= runtime->buffer_size) { | ||
116 | unsigned int cnt = | ||
117 | runtime->buffer_size - oldptr; | ||
118 | memcpy(runtime->dma_area + oldptr * stride, pcm_data, | ||
119 | cnt * stride); | ||
120 | memcpy(runtime->dma_area, pcm_data + cnt * stride, | ||
121 | length * stride - cnt * stride); | ||
122 | } else { | ||
123 | memcpy(runtime->dma_area + oldptr * stride, pcm_data, | ||
124 | length * stride); | ||
125 | } | ||
126 | snd_pcm_stream_lock(substream); | ||
127 | |||
128 | cxsc->hwptr_done_capture += length; | ||
129 | if (cxsc->hwptr_done_capture >= | ||
130 | runtime->buffer_size) | ||
131 | cxsc->hwptr_done_capture -= | ||
132 | runtime->buffer_size; | ||
133 | |||
134 | cxsc->capture_transfer_done += length; | ||
135 | if (cxsc->capture_transfer_done >= | ||
136 | runtime->period_size) { | ||
137 | cxsc->capture_transfer_done -= | ||
138 | runtime->period_size; | ||
139 | period_elapsed = 1; | ||
140 | } | ||
141 | |||
142 | snd_pcm_stream_unlock(substream); | ||
143 | |||
144 | if (period_elapsed) | ||
145 | snd_pcm_period_elapsed(substream); | ||
146 | } | ||
147 | |||
148 | static int snd_cx18_pcm_capture_open(struct snd_pcm_substream *substream) | ||
149 | { | ||
150 | struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream); | ||
151 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
152 | struct v4l2_device *v4l2_dev = cxsc->v4l2_dev; | ||
153 | struct cx18 *cx = to_cx18(v4l2_dev); | ||
154 | struct cx18_stream *s; | ||
155 | struct cx18_open_id item; | ||
156 | int ret; | ||
157 | |||
158 | /* Instruct the cx18 to start sending packets */ | ||
159 | snd_cx18_lock(cxsc); | ||
160 | s = &cx->streams[CX18_ENC_STREAM_TYPE_PCM]; | ||
161 | |||
162 | item.cx = cx; | ||
163 | item.type = s->type; | ||
164 | item.open_id = cx->open_id++; | ||
165 | |||
166 | /* See if the stream is available */ | ||
167 | if (cx18_claim_stream(&item, item.type)) { | ||
168 | /* No, it's already in use */ | ||
169 | snd_cx18_unlock(cxsc); | ||
170 | return -EBUSY; | ||
171 | } | ||
172 | |||
173 | if (test_bit(CX18_F_S_STREAMOFF, &s->s_flags) || | ||
174 | test_and_set_bit(CX18_F_S_STREAMING, &s->s_flags)) { | ||
175 | /* We're already streaming. No additional action required */ | ||
176 | snd_cx18_unlock(cxsc); | ||
177 | return 0; | ||
178 | } | ||
179 | |||
180 | |||
181 | runtime->hw = snd_cx18_hw_capture; | ||
182 | snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); | ||
183 | cxsc->capture_pcm_substream = substream; | ||
184 | runtime->private_data = cx; | ||
185 | |||
186 | cx->pcm_announce_callback = cx18_alsa_announce_pcm_data; | ||
187 | |||
188 | /* Not currently streaming, so start it up */ | ||
189 | set_bit(CX18_F_S_STREAMING, &s->s_flags); | ||
190 | ret = cx18_start_v4l2_encode_stream(s); | ||
191 | snd_cx18_unlock(cxsc); | ||
192 | |||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | static int snd_cx18_pcm_capture_close(struct snd_pcm_substream *substream) | ||
197 | { | ||
198 | struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream); | ||
199 | struct v4l2_device *v4l2_dev = cxsc->v4l2_dev; | ||
200 | struct cx18 *cx = to_cx18(v4l2_dev); | ||
201 | struct cx18_stream *s; | ||
202 | int ret; | ||
203 | |||
204 | /* Instruct the cx18 to stop sending packets */ | ||
205 | snd_cx18_lock(cxsc); | ||
206 | s = &cx->streams[CX18_ENC_STREAM_TYPE_PCM]; | ||
207 | ret = cx18_stop_v4l2_encode_stream(s, 0); | ||
208 | clear_bit(CX18_F_S_STREAMING, &s->s_flags); | ||
209 | |||
210 | cx18_release_stream(s); | ||
211 | |||
212 | cx->pcm_announce_callback = NULL; | ||
213 | snd_cx18_unlock(cxsc); | ||
214 | |||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | static int snd_cx18_pcm_ioctl(struct snd_pcm_substream *substream, | ||
219 | unsigned int cmd, void *arg) | ||
220 | { | ||
221 | return snd_pcm_lib_ioctl(substream, cmd, arg); | ||
222 | } | ||
223 | |||
224 | |||
225 | static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs, | ||
226 | size_t size) | ||
227 | { | ||
228 | struct snd_pcm_runtime *runtime = subs->runtime; | ||
229 | |||
230 | dprintk("Allocating vbuffer\n"); | ||
231 | if (runtime->dma_area) { | ||
232 | if (runtime->dma_bytes > size) | ||
233 | return 0; | ||
234 | |||
235 | vfree(runtime->dma_area); | ||
236 | } | ||
237 | runtime->dma_area = vmalloc(size); | ||
238 | if (!runtime->dma_area) | ||
239 | return -ENOMEM; | ||
240 | |||
241 | runtime->dma_bytes = size; | ||
242 | |||
243 | return 0; | ||
244 | } | ||
245 | |||
246 | static int snd_cx18_pcm_hw_params(struct snd_pcm_substream *substream, | ||
247 | struct snd_pcm_hw_params *params) | ||
248 | { | ||
249 | int ret; | ||
250 | |||
251 | dprintk("%s called\n", __func__); | ||
252 | |||
253 | ret = snd_pcm_alloc_vmalloc_buffer(substream, | ||
254 | params_buffer_bytes(params)); | ||
255 | return 0; | ||
256 | } | ||
257 | |||
258 | static int snd_cx18_pcm_hw_free(struct snd_pcm_substream *substream) | ||
259 | { | ||
260 | struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream); | ||
261 | unsigned long flags; | ||
262 | |||
263 | spin_lock_irqsave(&cxsc->slock, flags); | ||
264 | if (substream->runtime->dma_area) { | ||
265 | dprintk("freeing pcm capture region\n"); | ||
266 | vfree(substream->runtime->dma_area); | ||
267 | substream->runtime->dma_area = NULL; | ||
268 | } | ||
269 | spin_unlock_irqrestore(&cxsc->slock, flags); | ||
270 | |||
271 | return 0; | ||
272 | } | ||
273 | |||
274 | static int snd_cx18_pcm_prepare(struct snd_pcm_substream *substream) | ||
275 | { | ||
276 | struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream); | ||
277 | |||
278 | cxsc->hwptr_done_capture = 0; | ||
279 | cxsc->capture_transfer_done = 0; | ||
280 | |||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | static int snd_cx18_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | ||
285 | { | ||
286 | return 0; | ||
287 | } | ||
288 | |||
289 | static | ||
290 | snd_pcm_uframes_t snd_cx18_pcm_pointer(struct snd_pcm_substream *substream) | ||
291 | { | ||
292 | unsigned long flags; | ||
293 | snd_pcm_uframes_t hwptr_done; | ||
294 | struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream); | ||
295 | |||
296 | spin_lock_irqsave(&cxsc->slock, flags); | ||
297 | hwptr_done = cxsc->hwptr_done_capture; | ||
298 | spin_unlock_irqrestore(&cxsc->slock, flags); | ||
299 | |||
300 | return hwptr_done; | ||
301 | } | ||
302 | |||
303 | static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs, | ||
304 | unsigned long offset) | ||
305 | { | ||
306 | void *pageptr = subs->runtime->dma_area + offset; | ||
307 | |||
308 | return vmalloc_to_page(pageptr); | ||
309 | } | ||
310 | |||
311 | static struct snd_pcm_ops snd_cx18_pcm_capture_ops = { | ||
312 | .open = snd_cx18_pcm_capture_open, | ||
313 | .close = snd_cx18_pcm_capture_close, | ||
314 | .ioctl = snd_cx18_pcm_ioctl, | ||
315 | .hw_params = snd_cx18_pcm_hw_params, | ||
316 | .hw_free = snd_cx18_pcm_hw_free, | ||
317 | .prepare = snd_cx18_pcm_prepare, | ||
318 | .trigger = snd_cx18_pcm_trigger, | ||
319 | .pointer = snd_cx18_pcm_pointer, | ||
320 | .page = snd_pcm_get_vmalloc_page, | ||
321 | }; | ||
322 | |||
323 | int snd_cx18_pcm_create(struct snd_cx18_card *cxsc) | ||
324 | { | ||
325 | struct snd_pcm *sp; | ||
326 | struct snd_card *sc = cxsc->sc; | ||
327 | struct v4l2_device *v4l2_dev = cxsc->v4l2_dev; | ||
328 | struct cx18 *cx = to_cx18(v4l2_dev); | ||
329 | int ret; | ||
330 | |||
331 | ret = snd_pcm_new(sc, "CX23418 PCM", | ||
332 | 0, /* PCM device 0, the only one for this card */ | ||
333 | 0, /* 0 playback substreams */ | ||
334 | 1, /* 1 capture substream */ | ||
335 | &sp); | ||
336 | if (ret) { | ||
337 | CX18_ALSA_ERR("%s: snd_cx18_pcm_create() failed with err %d\n", | ||
338 | __func__, ret); | ||
339 | goto err_exit; | ||
340 | } | ||
341 | |||
342 | spin_lock_init(&cxsc->slock); | ||
343 | |||
344 | snd_pcm_set_ops(sp, SNDRV_PCM_STREAM_CAPTURE, | ||
345 | &snd_cx18_pcm_capture_ops); | ||
346 | sp->info_flags = 0; | ||
347 | sp->private_data = cxsc; | ||
348 | strlcpy(sp->name, cx->card_name, sizeof(sp->name)); | ||
349 | |||
350 | return 0; | ||
351 | |||
352 | err_exit: | ||
353 | return ret; | ||
354 | } | ||
diff --git a/drivers/media/video/cx18/cx18-alsa-pcm.h b/drivers/media/video/cx18/cx18-alsa-pcm.h new file mode 100644 index 000000000000..325662c647a0 --- /dev/null +++ b/drivers/media/video/cx18/cx18-alsa-pcm.h | |||
@@ -0,0 +1,27 @@ | |||
1 | /* | ||
2 | * ALSA PCM device for the | ||
3 | * ALSA interface to cx18 PCM capture streams | ||
4 | * | ||
5 | * Copyright (C) 2009 Andy Walls <awalls@radix.net> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | ||
20 | * 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | int __init snd_cx18_pcm_create(struct snd_cx18_card *cxsc); | ||
24 | |||
25 | /* Used by cx18-mailbox to announce the PCM data to the module */ | ||
26 | void cx18_alsa_announce_pcm_data(struct snd_cx18_card *card, u8 *pcm_data, | ||
27 | size_t num_bytes); | ||
diff --git a/drivers/media/video/cx18/cx18-alsa.h b/drivers/media/video/cx18/cx18-alsa.h new file mode 100644 index 000000000000..88a1cde7540b --- /dev/null +++ b/drivers/media/video/cx18/cx18-alsa.h | |||
@@ -0,0 +1,75 @@ | |||
1 | /* | ||
2 | * ALSA interface to cx18 PCM capture streams | ||
3 | * | ||
4 | * Copyright (C) 2009 Andy Walls <awalls@radix.net> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | ||
19 | * 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | struct snd_card; | ||
23 | |||
24 | struct snd_cx18_card { | ||
25 | struct v4l2_device *v4l2_dev; | ||
26 | struct snd_card *sc; | ||
27 | unsigned int capture_transfer_done; | ||
28 | unsigned int hwptr_done_capture; | ||
29 | struct snd_pcm_substream *capture_pcm_substream; | ||
30 | spinlock_t slock; | ||
31 | }; | ||
32 | |||
33 | extern int cx18_alsa_debug; | ||
34 | |||
35 | /* | ||
36 | * File operations that manipulate the encoder or video or audio subdevices | ||
37 | * need to be serialized. Use the same lock we use for v4l2 file ops. | ||
38 | */ | ||
39 | static inline void snd_cx18_lock(struct snd_cx18_card *cxsc) | ||
40 | { | ||
41 | struct cx18 *cx = to_cx18(cxsc->v4l2_dev); | ||
42 | mutex_lock(&cx->serialize_lock); | ||
43 | } | ||
44 | |||
45 | static inline void snd_cx18_unlock(struct snd_cx18_card *cxsc) | ||
46 | { | ||
47 | struct cx18 *cx = to_cx18(cxsc->v4l2_dev); | ||
48 | mutex_unlock(&cx->serialize_lock); | ||
49 | } | ||
50 | |||
51 | #define CX18_ALSA_DBGFLG_WARN (1 << 0) | ||
52 | #define CX18_ALSA_DBGFLG_WARN (1 << 0) | ||
53 | #define CX18_ALSA_DBGFLG_INFO (1 << 1) | ||
54 | |||
55 | #define CX18_ALSA_DEBUG(x, type, fmt, args...) \ | ||
56 | do { \ | ||
57 | if ((x) & cx18_alsa_debug) \ | ||
58 | printk(KERN_INFO "%s-alsa: " type ": " fmt, \ | ||
59 | v4l2_dev->name , ## args); \ | ||
60 | } while (0) | ||
61 | |||
62 | #define CX18_ALSA_DEBUG_WARN(fmt, args...) \ | ||
63 | CX18_ALSA_DEBUG(CX18_ALSA_DBGFLG_WARN, "warning", fmt , ## args) | ||
64 | |||
65 | #define CX18_ALSA_DEBUG_INFO(fmt, args...) \ | ||
66 | CX18_ALSA_DEBUG(CX18_ALSA_DBGFLG_INFO, "info", fmt , ## args) | ||
67 | |||
68 | #define CX18_ALSA_ERR(fmt, args...) \ | ||
69 | printk(KERN_ERR "%s-alsa: " fmt, v4l2_dev->name , ## args) | ||
70 | |||
71 | #define CX18_ALSA_WARN(fmt, args...) \ | ||
72 | printk(KERN_WARNING "%s-alsa: " fmt, v4l2_dev->name , ## args) | ||
73 | |||
74 | #define CX18_ALSA_INFO(fmt, args...) \ | ||
75 | printk(KERN_INFO "%s-alsa: " fmt, v4l2_dev->name , ## args) | ||
diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c index f11e47a58286..f808fb6fc1c1 100644 --- a/drivers/media/video/cx18/cx18-cards.c +++ b/drivers/media/video/cx18/cx18-cards.c | |||
@@ -393,7 +393,7 @@ static const struct cx18_card cx18_card_leadtek_pvr2100 = { | |||
393 | .gpio_init.direction = 0x7, | 393 | .gpio_init.direction = 0x7, |
394 | .gpio_audio_input = { .mask = 0x7, | 394 | .gpio_audio_input = { .mask = 0x7, |
395 | .tuner = 0x6, .linein = 0x2, .radio = 0x2 }, | 395 | .tuner = 0x6, .linein = 0x2, .radio = 0x2 }, |
396 | .xceive_pin = 15, | 396 | .xceive_pin = 1, |
397 | .pci_list = cx18_pci_leadtek_pvr2100, | 397 | .pci_list = cx18_pci_leadtek_pvr2100, |
398 | .i2c = &cx18_i2c_std, | 398 | .i2c = &cx18_i2c_std, |
399 | }; | 399 | }; |
diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 7f65a47f12e1..c95a86ba33b0 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c | |||
@@ -47,6 +47,10 @@ | |||
47 | setting this to 1 you ensure that radio0 is now also radio1. */ | 47 | setting this to 1 you ensure that radio0 is now also radio1. */ |
48 | int cx18_first_minor; | 48 | int cx18_first_minor; |
49 | 49 | ||
50 | /* Callback for registering extensions */ | ||
51 | int (*cx18_ext_init)(struct cx18 *); | ||
52 | EXPORT_SYMBOL(cx18_ext_init); | ||
53 | |||
50 | /* add your revision and whatnot here */ | 54 | /* add your revision and whatnot here */ |
51 | static struct pci_device_id cx18_pci_tbl[] __devinitdata = { | 55 | static struct pci_device_id cx18_pci_tbl[] __devinitdata = { |
52 | {PCI_VENDOR_ID_CX, PCI_DEVICE_ID_CX23418, | 56 | {PCI_VENDOR_ID_CX, PCI_DEVICE_ID_CX23418, |
@@ -91,7 +95,7 @@ static int enc_pcm_bufsize = CX18_DEFAULT_ENC_PCM_BUFSIZE; | |||
91 | 95 | ||
92 | static int enc_ts_bufs = -1; | 96 | static int enc_ts_bufs = -1; |
93 | static int enc_mpg_bufs = -1; | 97 | static int enc_mpg_bufs = -1; |
94 | static int enc_idx_bufs = -1; | 98 | static int enc_idx_bufs = CX18_MAX_FW_MDLS_PER_STREAM; |
95 | static int enc_yuv_bufs = -1; | 99 | static int enc_yuv_bufs = -1; |
96 | static int enc_vbi_bufs = -1; | 100 | static int enc_vbi_bufs = -1; |
97 | static int enc_pcm_bufs = -1; | 101 | static int enc_pcm_bufs = -1; |
@@ -196,14 +200,17 @@ MODULE_PARM_DESC(enc_mpg_bufs, | |||
196 | "Number of encoder MPG buffers\n" | 200 | "Number of encoder MPG buffers\n" |
197 | "\t\t\tDefault is computed from other enc_mpg_* parameters"); | 201 | "\t\t\tDefault is computed from other enc_mpg_* parameters"); |
198 | MODULE_PARM_DESC(enc_idx_buffers, | 202 | MODULE_PARM_DESC(enc_idx_buffers, |
199 | "Encoder IDX buffer memory (MB). (enc_idx_bufs can override)\n" | 203 | "(Deprecated) Encoder IDX buffer memory (MB)\n" |
200 | "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_IDX_BUFFERS)); | 204 | "\t\t\tIgnored, except 0 disables IDX buffer allocations\n" |
205 | "\t\t\tDefault: 1 [Enabled]"); | ||
201 | MODULE_PARM_DESC(enc_idx_bufsize, | 206 | MODULE_PARM_DESC(enc_idx_bufsize, |
202 | "Size of an encoder IDX buffer (kB)\n" | 207 | "Size of an encoder IDX buffer (kB)\n" |
203 | "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_IDX_BUFSIZE)); | 208 | "\t\t\tAllowed values are multiples of 1.5 kB rounded up\n" |
209 | "\t\t\t(multiples of size required for 64 index entries)\n" | ||
210 | "\t\t\tDefault: 2"); | ||
204 | MODULE_PARM_DESC(enc_idx_bufs, | 211 | MODULE_PARM_DESC(enc_idx_bufs, |
205 | "Number of encoder IDX buffers\n" | 212 | "Number of encoder IDX buffers\n" |
206 | "\t\t\tDefault is computed from other enc_idx_* parameters"); | 213 | "\t\t\tDefault: " __stringify(CX18_MAX_FW_MDLS_PER_STREAM)); |
207 | MODULE_PARM_DESC(enc_yuv_buffers, | 214 | MODULE_PARM_DESC(enc_yuv_buffers, |
208 | "Encoder YUV buffer memory (MB). (enc_yuv_bufs can override)\n" | 215 | "Encoder YUV buffer memory (MB). (enc_yuv_bufs can override)\n" |
209 | "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_YUV_BUFFERS)); | 216 | "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_YUV_BUFFERS)); |
@@ -231,7 +238,8 @@ MODULE_PARM_DESC(enc_pcm_bufs, | |||
231 | "Number of encoder PCM buffers\n" | 238 | "Number of encoder PCM buffers\n" |
232 | "\t\t\tDefault is computed from other enc_pcm_* parameters"); | 239 | "\t\t\tDefault is computed from other enc_pcm_* parameters"); |
233 | 240 | ||
234 | MODULE_PARM_DESC(cx18_first_minor, "Set device node number assigned to first card"); | 241 | MODULE_PARM_DESC(cx18_first_minor, |
242 | "Set device node number assigned to first card"); | ||
235 | 243 | ||
236 | MODULE_AUTHOR("Hans Verkuil"); | 244 | MODULE_AUTHOR("Hans Verkuil"); |
237 | MODULE_DESCRIPTION("CX23418 driver"); | 245 | MODULE_DESCRIPTION("CX23418 driver"); |
@@ -240,6 +248,28 @@ MODULE_LICENSE("GPL"); | |||
240 | 248 | ||
241 | MODULE_VERSION(CX18_VERSION); | 249 | MODULE_VERSION(CX18_VERSION); |
242 | 250 | ||
251 | #if defined(CONFIG_MODULES) && defined(MODULE) | ||
252 | static void request_module_async(struct work_struct *work) | ||
253 | { | ||
254 | struct cx18 *dev = container_of(work, struct cx18, request_module_wk); | ||
255 | |||
256 | /* Make sure cx18-alsa module is loaded */ | ||
257 | request_module("cx18-alsa"); | ||
258 | |||
259 | /* Initialize cx18-alsa for this instance of the cx18 device */ | ||
260 | if (cx18_ext_init != NULL) | ||
261 | cx18_ext_init(dev); | ||
262 | } | ||
263 | |||
264 | static void request_modules(struct cx18 *dev) | ||
265 | { | ||
266 | INIT_WORK(&dev->request_module_wk, request_module_async); | ||
267 | schedule_work(&dev->request_module_wk); | ||
268 | } | ||
269 | #else | ||
270 | #define request_modules(dev) | ||
271 | #endif /* CONFIG_MODULES */ | ||
272 | |||
243 | /* Generic utility functions */ | 273 | /* Generic utility functions */ |
244 | int cx18_msleep_timeout(unsigned int msecs, int intr) | 274 | int cx18_msleep_timeout(unsigned int msecs, int intr) |
245 | { | 275 | { |
@@ -501,7 +531,12 @@ static void cx18_process_options(struct cx18 *cx) | |||
501 | /* | 531 | /* |
502 | * YUV is a special case where the stream_buf_size needs to be | 532 | * YUV is a special case where the stream_buf_size needs to be |
503 | * an integral multiple of 33.75 kB (storage for 32 screens | 533 | * an integral multiple of 33.75 kB (storage for 32 screens |
504 | * lines to maintain alignment in case of lost buffers | 534 | * lines to maintain alignment in case of lost buffers). |
535 | * | ||
536 | * IDX is a special case where the stream_buf_size should be | ||
537 | * an integral multiple of 1.5 kB (storage for 64 index entries | ||
538 | * to maintain alignment in case of lost buffers). | ||
539 | * | ||
505 | */ | 540 | */ |
506 | if (i == CX18_ENC_STREAM_TYPE_YUV) { | 541 | if (i == CX18_ENC_STREAM_TYPE_YUV) { |
507 | cx->stream_buf_size[i] *= 1024; | 542 | cx->stream_buf_size[i] *= 1024; |
@@ -511,15 +546,24 @@ static void cx18_process_options(struct cx18 *cx) | |||
511 | if (cx->stream_buf_size[i] < CX18_UNIT_ENC_YUV_BUFSIZE) | 546 | if (cx->stream_buf_size[i] < CX18_UNIT_ENC_YUV_BUFSIZE) |
512 | cx->stream_buf_size[i] = | 547 | cx->stream_buf_size[i] = |
513 | CX18_UNIT_ENC_YUV_BUFSIZE; | 548 | CX18_UNIT_ENC_YUV_BUFSIZE; |
549 | } else if (i == CX18_ENC_STREAM_TYPE_IDX) { | ||
550 | cx->stream_buf_size[i] *= 1024; | ||
551 | cx->stream_buf_size[i] -= | ||
552 | (cx->stream_buf_size[i] % CX18_UNIT_ENC_IDX_BUFSIZE); | ||
553 | |||
554 | if (cx->stream_buf_size[i] < CX18_UNIT_ENC_IDX_BUFSIZE) | ||
555 | cx->stream_buf_size[i] = | ||
556 | CX18_UNIT_ENC_IDX_BUFSIZE; | ||
514 | } | 557 | } |
515 | /* | 558 | /* |
516 | * YUV is a special case where the stream_buf_size is | 559 | * YUV and IDX are special cases where the stream_buf_size is |
517 | * now in bytes. | 560 | * now in bytes. |
518 | * VBI is a special case where the stream_buf_size is fixed | 561 | * VBI is a special case where the stream_buf_size is fixed |
519 | * and already in bytes | 562 | * and already in bytes |
520 | */ | 563 | */ |
521 | if (i == CX18_ENC_STREAM_TYPE_VBI || | 564 | if (i == CX18_ENC_STREAM_TYPE_VBI || |
522 | i == CX18_ENC_STREAM_TYPE_YUV) { | 565 | i == CX18_ENC_STREAM_TYPE_YUV || |
566 | i == CX18_ENC_STREAM_TYPE_IDX) { | ||
523 | if (cx->stream_buffers[i] < 0) { | 567 | if (cx->stream_buffers[i] < 0) { |
524 | cx->stream_buffers[i] = | 568 | cx->stream_buffers[i] = |
525 | cx->options.megabytes[i] * 1024 * 1024 | 569 | cx->options.megabytes[i] * 1024 * 1024 |
@@ -1032,6 +1076,10 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev, | |||
1032 | } | 1076 | } |
1033 | 1077 | ||
1034 | CX18_INFO("Initialized card: %s\n", cx->card_name); | 1078 | CX18_INFO("Initialized card: %s\n", cx->card_name); |
1079 | |||
1080 | /* Load cx18 submodules (cx18-alsa) */ | ||
1081 | request_modules(cx); | ||
1082 | |||
1035 | return 0; | 1083 | return 0; |
1036 | 1084 | ||
1037 | free_streams: | 1085 | free_streams: |
@@ -1220,6 +1268,7 @@ static void cx18_remove(struct pci_dev *pci_dev) | |||
1220 | kfree(cx); | 1268 | kfree(cx); |
1221 | } | 1269 | } |
1222 | 1270 | ||
1271 | |||
1223 | /* define a pci_driver for card detection */ | 1272 | /* define a pci_driver for card detection */ |
1224 | static struct pci_driver cx18_pci_driver = { | 1273 | static struct pci_driver cx18_pci_driver = { |
1225 | .name = "cx18", | 1274 | .name = "cx18", |
@@ -1230,7 +1279,8 @@ static struct pci_driver cx18_pci_driver = { | |||
1230 | 1279 | ||
1231 | static int __init module_start(void) | 1280 | static int __init module_start(void) |
1232 | { | 1281 | { |
1233 | printk(KERN_INFO "cx18: Start initialization, version %s\n", CX18_VERSION); | 1282 | printk(KERN_INFO "cx18: Start initialization, version %s\n", |
1283 | CX18_VERSION); | ||
1234 | 1284 | ||
1235 | /* Validate parameters */ | 1285 | /* Validate parameters */ |
1236 | if (cx18_first_minor < 0 || cx18_first_minor >= CX18_MAX_CARDS) { | 1286 | if (cx18_first_minor < 0 || cx18_first_minor >= CX18_MAX_CARDS) { |
diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index e3f7911a7385..23ad6d548dc5 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h | |||
@@ -126,10 +126,22 @@ | |||
126 | #define CX18_625_LINE_ENC_YUV_BUFSIZE (CX18_UNIT_ENC_YUV_BUFSIZE * 576/32) | 126 | #define CX18_625_LINE_ENC_YUV_BUFSIZE (CX18_UNIT_ENC_YUV_BUFSIZE * 576/32) |
127 | #define CX18_525_LINE_ENC_YUV_BUFSIZE (CX18_UNIT_ENC_YUV_BUFSIZE * 480/32) | 127 | #define CX18_525_LINE_ENC_YUV_BUFSIZE (CX18_UNIT_ENC_YUV_BUFSIZE * 480/32) |
128 | 128 | ||
129 | /* IDX buffer size should be a multiple of the index entry size from the chip */ | ||
130 | struct cx18_enc_idx_entry { | ||
131 | __le32 length; | ||
132 | __le32 offset_low; | ||
133 | __le32 offset_high; | ||
134 | __le32 flags; | ||
135 | __le32 pts_low; | ||
136 | __le32 pts_high; | ||
137 | } __attribute__ ((packed)); | ||
138 | #define CX18_UNIT_ENC_IDX_BUFSIZE \ | ||
139 | (sizeof(struct cx18_enc_idx_entry) * V4L2_ENC_IDX_ENTRIES) | ||
140 | |||
129 | /* DMA buffer, default size in kB allocated */ | 141 | /* DMA buffer, default size in kB allocated */ |
130 | #define CX18_DEFAULT_ENC_TS_BUFSIZE 32 | 142 | #define CX18_DEFAULT_ENC_TS_BUFSIZE 32 |
131 | #define CX18_DEFAULT_ENC_MPG_BUFSIZE 32 | 143 | #define CX18_DEFAULT_ENC_MPG_BUFSIZE 32 |
132 | #define CX18_DEFAULT_ENC_IDX_BUFSIZE 32 | 144 | #define CX18_DEFAULT_ENC_IDX_BUFSIZE (CX18_UNIT_ENC_IDX_BUFSIZE * 1 / 1024 + 1) |
133 | #define CX18_DEFAULT_ENC_YUV_BUFSIZE (CX18_UNIT_ENC_YUV_BUFSIZE * 3 / 1024 + 1) | 145 | #define CX18_DEFAULT_ENC_YUV_BUFSIZE (CX18_UNIT_ENC_YUV_BUFSIZE * 3 / 1024 + 1) |
134 | #define CX18_DEFAULT_ENC_PCM_BUFSIZE 4 | 146 | #define CX18_DEFAULT_ENC_PCM_BUFSIZE 4 |
135 | 147 | ||
@@ -234,16 +246,8 @@ | |||
234 | #define CX18_WARN_DEV(dev, fmt, args...) v4l2_warn(dev, fmt , ## args) | 246 | #define CX18_WARN_DEV(dev, fmt, args...) v4l2_warn(dev, fmt , ## args) |
235 | #define CX18_INFO_DEV(dev, fmt, args...) v4l2_info(dev, fmt , ## args) | 247 | #define CX18_INFO_DEV(dev, fmt, args...) v4l2_info(dev, fmt , ## args) |
236 | 248 | ||
237 | /* Values for CX18_API_DEC_PLAYBACK_SPEED mpeg_frame_type_mask parameter: */ | ||
238 | #define MPEG_FRAME_TYPE_IFRAME 1 | ||
239 | #define MPEG_FRAME_TYPE_IFRAME_PFRAME 3 | ||
240 | #define MPEG_FRAME_TYPE_ALL 7 | ||
241 | |||
242 | #define CX18_MAX_PGM_INDEX (400) | ||
243 | |||
244 | extern int cx18_debug; | 249 | extern int cx18_debug; |
245 | 250 | ||
246 | |||
247 | struct cx18_options { | 251 | struct cx18_options { |
248 | int megabytes[CX18_MAX_STREAMS]; /* Size in megabytes of each stream */ | 252 | int megabytes[CX18_MAX_STREAMS]; /* Size in megabytes of each stream */ |
249 | int cardtype; /* force card type on load */ | 253 | int cardtype; /* force card type on load */ |
@@ -276,6 +280,18 @@ struct cx18_options { | |||
276 | #define CX18_SLICED_TYPE_WSS_625 (5) | 280 | #define CX18_SLICED_TYPE_WSS_625 (5) |
277 | #define CX18_SLICED_TYPE_VPS (7) | 281 | #define CX18_SLICED_TYPE_VPS (7) |
278 | 282 | ||
283 | /** | ||
284 | * list_entry_is_past_end - check if a previous loop cursor is off list end | ||
285 | * @pos: the type * previously used as a loop cursor. | ||
286 | * @head: the head for your list. | ||
287 | * @member: the name of the list_struct within the struct. | ||
288 | * | ||
289 | * Check if the entry's list_head is the head of the list, thus it's not a | ||
290 | * real entry but was the loop cursor that walked past the end | ||
291 | */ | ||
292 | #define list_entry_is_past_end(pos, head, member) \ | ||
293 | (&pos->member == (head)) | ||
294 | |||
279 | struct cx18_buffer { | 295 | struct cx18_buffer { |
280 | struct list_head list; | 296 | struct list_head list; |
281 | dma_addr_t dma_handle; | 297 | dma_addr_t dma_handle; |
@@ -558,6 +574,10 @@ struct cx18 { | |||
558 | int stream_buffers[CX18_MAX_STREAMS]; /* # of buffers for each stream */ | 574 | int stream_buffers[CX18_MAX_STREAMS]; /* # of buffers for each stream */ |
559 | int stream_buf_size[CX18_MAX_STREAMS]; /* Stream buffer size */ | 575 | int stream_buf_size[CX18_MAX_STREAMS]; /* Stream buffer size */ |
560 | struct cx18_stream streams[CX18_MAX_STREAMS]; /* Stream data */ | 576 | struct cx18_stream streams[CX18_MAX_STREAMS]; /* Stream data */ |
577 | struct snd_cx18_card *alsa; /* ALSA interface for PCM capture stream */ | ||
578 | void (*pcm_announce_callback)(struct snd_cx18_card *card, u8 *pcm_data, | ||
579 | size_t num_bytes); | ||
580 | |||
561 | unsigned long i_flags; /* global cx18 flags */ | 581 | unsigned long i_flags; /* global cx18 flags */ |
562 | atomic_t ana_capturing; /* count number of active analog capture streams */ | 582 | atomic_t ana_capturing; /* count number of active analog capture streams */ |
563 | atomic_t tot_capturing; /* total count number of active capture streams */ | 583 | atomic_t tot_capturing; /* total count number of active capture streams */ |
@@ -575,12 +595,6 @@ struct cx18 { | |||
575 | 595 | ||
576 | struct vbi_info vbi; | 596 | struct vbi_info vbi; |
577 | 597 | ||
578 | u32 pgm_info_offset; | ||
579 | u32 pgm_info_num; | ||
580 | u32 pgm_info_write_idx; | ||
581 | u32 pgm_info_read_idx; | ||
582 | struct v4l2_enc_idx_entry pgm_info[CX18_MAX_PGM_INDEX]; | ||
583 | |||
584 | u64 mpg_data_received; | 598 | u64 mpg_data_received; |
585 | u64 vbi_data_inserted; | 599 | u64 vbi_data_inserted; |
586 | 600 | ||
@@ -623,6 +637,9 @@ struct cx18 { | |||
623 | u32 active_input; | 637 | u32 active_input; |
624 | v4l2_std_id std; | 638 | v4l2_std_id std; |
625 | v4l2_std_id tuner_std; /* The norm of the tuner (fixed) */ | 639 | v4l2_std_id tuner_std; /* The norm of the tuner (fixed) */ |
640 | |||
641 | /* Used for cx18-alsa module loading */ | ||
642 | struct work_struct request_module_wk; | ||
626 | }; | 643 | }; |
627 | 644 | ||
628 | static inline struct cx18 *to_cx18(struct v4l2_device *v4l2_dev) | 645 | static inline struct cx18 *to_cx18(struct v4l2_device *v4l2_dev) |
@@ -630,6 +647,9 @@ static inline struct cx18 *to_cx18(struct v4l2_device *v4l2_dev) | |||
630 | return container_of(v4l2_dev, struct cx18, v4l2_dev); | 647 | return container_of(v4l2_dev, struct cx18, v4l2_dev); |
631 | } | 648 | } |
632 | 649 | ||
650 | /* cx18 extensions to be loaded */ | ||
651 | extern int (*cx18_ext_init)(struct cx18 *); | ||
652 | |||
633 | /* Globals */ | 653 | /* Globals */ |
634 | extern int cx18_first_minor; | 654 | extern int cx18_first_minor; |
635 | 655 | ||
diff --git a/drivers/media/video/cx18/cx18-dvb.c b/drivers/media/video/cx18/cx18-dvb.c index 71ad2d1b4c2c..0ae2c2e1eab5 100644 --- a/drivers/media/video/cx18/cx18-dvb.c +++ b/drivers/media/video/cx18/cx18-dvb.c | |||
@@ -213,10 +213,14 @@ static int cx18_dvb_start_feed(struct dvb_demux_feed *feed) | |||
213 | { | 213 | { |
214 | struct dvb_demux *demux = feed->demux; | 214 | struct dvb_demux *demux = feed->demux; |
215 | struct cx18_stream *stream = (struct cx18_stream *) demux->priv; | 215 | struct cx18_stream *stream = (struct cx18_stream *) demux->priv; |
216 | struct cx18 *cx = stream->cx; | 216 | struct cx18 *cx; |
217 | int ret; | 217 | int ret; |
218 | u32 v; | 218 | u32 v; |
219 | 219 | ||
220 | if (!stream) | ||
221 | return -EINVAL; | ||
222 | |||
223 | cx = stream->cx; | ||
220 | CX18_DEBUG_INFO("Start feed: pid = 0x%x index = %d\n", | 224 | CX18_DEBUG_INFO("Start feed: pid = 0x%x index = %d\n", |
221 | feed->pid, feed->index); | 225 | feed->pid, feed->index); |
222 | 226 | ||
@@ -253,12 +257,10 @@ static int cx18_dvb_start_feed(struct dvb_demux_feed *feed) | |||
253 | if (!demux->dmx.frontend) | 257 | if (!demux->dmx.frontend) |
254 | return -EINVAL; | 258 | return -EINVAL; |
255 | 259 | ||
256 | if (!stream) | ||
257 | return -EINVAL; | ||
258 | |||
259 | mutex_lock(&stream->dvb.feedlock); | 260 | mutex_lock(&stream->dvb.feedlock); |
260 | if (stream->dvb.feeding++ == 0) { | 261 | if (stream->dvb.feeding++ == 0) { |
261 | CX18_DEBUG_INFO("Starting Transport DMA\n"); | 262 | CX18_DEBUG_INFO("Starting Transport DMA\n"); |
263 | mutex_lock(&cx->serialize_lock); | ||
262 | set_bit(CX18_F_S_STREAMING, &stream->s_flags); | 264 | set_bit(CX18_F_S_STREAMING, &stream->s_flags); |
263 | ret = cx18_start_v4l2_encode_stream(stream); | 265 | ret = cx18_start_v4l2_encode_stream(stream); |
264 | if (ret < 0) { | 266 | if (ret < 0) { |
@@ -267,6 +269,7 @@ static int cx18_dvb_start_feed(struct dvb_demux_feed *feed) | |||
267 | if (stream->dvb.feeding == 0) | 269 | if (stream->dvb.feeding == 0) |
268 | clear_bit(CX18_F_S_STREAMING, &stream->s_flags); | 270 | clear_bit(CX18_F_S_STREAMING, &stream->s_flags); |
269 | } | 271 | } |
272 | mutex_unlock(&cx->serialize_lock); | ||
270 | } else | 273 | } else |
271 | ret = 0; | 274 | ret = 0; |
272 | mutex_unlock(&stream->dvb.feedlock); | 275 | mutex_unlock(&stream->dvb.feedlock); |
@@ -279,17 +282,20 @@ static int cx18_dvb_stop_feed(struct dvb_demux_feed *feed) | |||
279 | { | 282 | { |
280 | struct dvb_demux *demux = feed->demux; | 283 | struct dvb_demux *demux = feed->demux; |
281 | struct cx18_stream *stream = (struct cx18_stream *)demux->priv; | 284 | struct cx18_stream *stream = (struct cx18_stream *)demux->priv; |
282 | struct cx18 *cx = stream->cx; | 285 | struct cx18 *cx; |
283 | int ret = -EINVAL; | 286 | int ret = -EINVAL; |
284 | 287 | ||
285 | CX18_DEBUG_INFO("Stop feed: pid = 0x%x index = %d\n", | ||
286 | feed->pid, feed->index); | ||
287 | |||
288 | if (stream) { | 288 | if (stream) { |
289 | cx = stream->cx; | ||
290 | CX18_DEBUG_INFO("Stop feed: pid = 0x%x index = %d\n", | ||
291 | feed->pid, feed->index); | ||
292 | |||
289 | mutex_lock(&stream->dvb.feedlock); | 293 | mutex_lock(&stream->dvb.feedlock); |
290 | if (--stream->dvb.feeding == 0) { | 294 | if (--stream->dvb.feeding == 0) { |
291 | CX18_DEBUG_INFO("Stopping Transport DMA\n"); | 295 | CX18_DEBUG_INFO("Stopping Transport DMA\n"); |
296 | mutex_lock(&cx->serialize_lock); | ||
292 | ret = cx18_stop_v4l2_encode_stream(stream, 0); | 297 | ret = cx18_stop_v4l2_encode_stream(stream, 0); |
298 | mutex_unlock(&cx->serialize_lock); | ||
293 | } else | 299 | } else |
294 | ret = 0; | 300 | ret = 0; |
295 | mutex_unlock(&stream->dvb.feedlock); | 301 | mutex_unlock(&stream->dvb.feedlock); |
diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c index c0885c69fd89..863ce7758239 100644 --- a/drivers/media/video/cx18/cx18-fileops.c +++ b/drivers/media/video/cx18/cx18-fileops.c | |||
@@ -37,15 +37,21 @@ | |||
37 | 37 | ||
38 | /* This function tries to claim the stream for a specific file descriptor. | 38 | /* This function tries to claim the stream for a specific file descriptor. |
39 | If no one else is using this stream then the stream is claimed and | 39 | If no one else is using this stream then the stream is claimed and |
40 | associated VBI streams are also automatically claimed. | 40 | associated VBI and IDX streams are also automatically claimed. |
41 | Possible error returns: -EBUSY if someone else has claimed | 41 | Possible error returns: -EBUSY if someone else has claimed |
42 | the stream or 0 on success. */ | 42 | the stream or 0 on success. */ |
43 | static int cx18_claim_stream(struct cx18_open_id *id, int type) | 43 | int cx18_claim_stream(struct cx18_open_id *id, int type) |
44 | { | 44 | { |
45 | struct cx18 *cx = id->cx; | 45 | struct cx18 *cx = id->cx; |
46 | struct cx18_stream *s = &cx->streams[type]; | 46 | struct cx18_stream *s = &cx->streams[type]; |
47 | struct cx18_stream *s_vbi; | 47 | struct cx18_stream *s_assoc; |
48 | int vbi_type; | 48 | |
49 | /* Nothing should ever try to directly claim the IDX stream */ | ||
50 | if (type == CX18_ENC_STREAM_TYPE_IDX) { | ||
51 | CX18_WARN("MPEG Index stream cannot be claimed " | ||
52 | "directly, but something tried.\n"); | ||
53 | return -EINVAL; | ||
54 | } | ||
49 | 55 | ||
50 | if (test_and_set_bit(CX18_F_S_CLAIMED, &s->s_flags)) { | 56 | if (test_and_set_bit(CX18_F_S_CLAIMED, &s->s_flags)) { |
51 | /* someone already claimed this stream */ | 57 | /* someone already claimed this stream */ |
@@ -67,32 +73,47 @@ static int cx18_claim_stream(struct cx18_open_id *id, int type) | |||
67 | } | 73 | } |
68 | s->id = id->open_id; | 74 | s->id = id->open_id; |
69 | 75 | ||
70 | /* CX18_ENC_STREAM_TYPE_MPG needs to claim CX18_ENC_STREAM_TYPE_VBI | 76 | /* |
71 | (provided VBI insertion is on and sliced VBI is selected), for all | 77 | * CX18_ENC_STREAM_TYPE_MPG needs to claim: |
72 | other streams we're done */ | 78 | * CX18_ENC_STREAM_TYPE_VBI, if VBI insertion is on for sliced VBI, or |
73 | if (type == CX18_ENC_STREAM_TYPE_MPG && | 79 | * CX18_ENC_STREAM_TYPE_IDX, if VBI insertion is off for sliced VBI |
74 | cx->vbi.insert_mpeg && !cx18_raw_vbi(cx)) { | 80 | * (We don't yet fix up MPEG Index entries for our inserted packets). |
75 | vbi_type = CX18_ENC_STREAM_TYPE_VBI; | 81 | * |
76 | } else { | 82 | * For all other streams we're done. |
83 | */ | ||
84 | if (type != CX18_ENC_STREAM_TYPE_MPG) | ||
77 | return 0; | 85 | return 0; |
78 | } | ||
79 | s_vbi = &cx->streams[vbi_type]; | ||
80 | 86 | ||
81 | set_bit(CX18_F_S_CLAIMED, &s_vbi->s_flags); | 87 | s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_IDX]; |
88 | if (cx->vbi.insert_mpeg && !cx18_raw_vbi(cx)) | ||
89 | s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_VBI]; | ||
90 | else if (!cx18_stream_enabled(s_assoc)) | ||
91 | return 0; | ||
92 | |||
93 | set_bit(CX18_F_S_CLAIMED, &s_assoc->s_flags); | ||
82 | 94 | ||
83 | /* mark that it is used internally */ | 95 | /* mark that it is used internally */ |
84 | set_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags); | 96 | set_bit(CX18_F_S_INTERNAL_USE, &s_assoc->s_flags); |
85 | return 0; | 97 | return 0; |
86 | } | 98 | } |
99 | EXPORT_SYMBOL(cx18_claim_stream); | ||
87 | 100 | ||
88 | /* This function releases a previously claimed stream. It will take into | 101 | /* This function releases a previously claimed stream. It will take into |
89 | account associated VBI streams. */ | 102 | account associated VBI streams. */ |
90 | static void cx18_release_stream(struct cx18_stream *s) | 103 | void cx18_release_stream(struct cx18_stream *s) |
91 | { | 104 | { |
92 | struct cx18 *cx = s->cx; | 105 | struct cx18 *cx = s->cx; |
93 | struct cx18_stream *s_vbi; | 106 | struct cx18_stream *s_assoc; |
94 | 107 | ||
95 | s->id = -1; | 108 | s->id = -1; |
109 | if (s->type == CX18_ENC_STREAM_TYPE_IDX) { | ||
110 | /* | ||
111 | * The IDX stream is only used internally, and can | ||
112 | * only be indirectly unclaimed by unclaiming the MPG stream. | ||
113 | */ | ||
114 | return; | ||
115 | } | ||
116 | |||
96 | if (s->type == CX18_ENC_STREAM_TYPE_VBI && | 117 | if (s->type == CX18_ENC_STREAM_TYPE_VBI && |
97 | test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags)) { | 118 | test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags)) { |
98 | /* this stream is still in use internally */ | 119 | /* this stream is still in use internally */ |
@@ -105,25 +126,36 @@ static void cx18_release_stream(struct cx18_stream *s) | |||
105 | 126 | ||
106 | cx18_flush_queues(s); | 127 | cx18_flush_queues(s); |
107 | 128 | ||
108 | /* CX18_ENC_STREAM_TYPE_MPG needs to release CX18_ENC_STREAM_TYPE_VBI, | 129 | /* |
109 | for all other streams we're done */ | 130 | * CX18_ENC_STREAM_TYPE_MPG needs to release the |
110 | if (s->type == CX18_ENC_STREAM_TYPE_MPG) | 131 | * CX18_ENC_STREAM_TYPE_VBI and/or CX18_ENC_STREAM_TYPE_IDX streams. |
111 | s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI]; | 132 | * |
112 | else | 133 | * For all other streams we're done. |
134 | */ | ||
135 | if (s->type != CX18_ENC_STREAM_TYPE_MPG) | ||
113 | return; | 136 | return; |
114 | 137 | ||
115 | /* clear internal use flag */ | 138 | /* Unclaim the associated MPEG Index stream */ |
116 | if (!test_and_clear_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags)) { | 139 | s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_IDX]; |
117 | /* was already cleared */ | 140 | if (test_and_clear_bit(CX18_F_S_INTERNAL_USE, &s_assoc->s_flags)) { |
118 | return; | 141 | clear_bit(CX18_F_S_CLAIMED, &s_assoc->s_flags); |
142 | cx18_flush_queues(s_assoc); | ||
119 | } | 143 | } |
120 | if (s_vbi->id != -1) { | 144 | |
121 | /* VBI stream still claimed by a file descriptor */ | 145 | /* Unclaim the associated VBI stream */ |
122 | return; | 146 | s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_VBI]; |
147 | if (test_and_clear_bit(CX18_F_S_INTERNAL_USE, &s_assoc->s_flags)) { | ||
148 | if (s_assoc->id == -1) { | ||
149 | /* | ||
150 | * The VBI stream is not still claimed by a file | ||
151 | * descriptor, so completely unclaim it. | ||
152 | */ | ||
153 | clear_bit(CX18_F_S_CLAIMED, &s_assoc->s_flags); | ||
154 | cx18_flush_queues(s_assoc); | ||
155 | } | ||
123 | } | 156 | } |
124 | clear_bit(CX18_F_S_CLAIMED, &s_vbi->s_flags); | ||
125 | cx18_flush_queues(s_vbi); | ||
126 | } | 157 | } |
158 | EXPORT_SYMBOL(cx18_release_stream); | ||
127 | 159 | ||
128 | static void cx18_dualwatch(struct cx18 *cx) | 160 | static void cx18_dualwatch(struct cx18 *cx) |
129 | { | 161 | { |
@@ -177,9 +209,7 @@ static struct cx18_mdl *cx18_get_mdl(struct cx18_stream *s, int non_block, | |||
177 | *err = 0; | 209 | *err = 0; |
178 | while (1) { | 210 | while (1) { |
179 | if (s->type == CX18_ENC_STREAM_TYPE_MPG) { | 211 | if (s->type == CX18_ENC_STREAM_TYPE_MPG) { |
180 | /* Process pending program info updates and pending | 212 | /* Process pending program updates and VBI data */ |
181 | VBI data */ | ||
182 | |||
183 | if (time_after(jiffies, cx->dualwatch_jiffies + msecs_to_jiffies(1000))) { | 213 | if (time_after(jiffies, cx->dualwatch_jiffies + msecs_to_jiffies(1000))) { |
184 | cx->dualwatch_jiffies = jiffies; | 214 | cx->dualwatch_jiffies = jiffies; |
185 | cx18_dualwatch(cx); | 215 | cx18_dualwatch(cx); |
@@ -362,18 +392,6 @@ static size_t cx18_copy_buf_to_user(struct cx18_stream *s, | |||
362 | return len; | 392 | return len; |
363 | } | 393 | } |
364 | 394 | ||
365 | /** | ||
366 | * list_entry_is_past_end - check if a previous loop cursor is off list end | ||
367 | * @pos: the type * previously used as a loop cursor. | ||
368 | * @head: the head for your list. | ||
369 | * @member: the name of the list_struct within the struct. | ||
370 | * | ||
371 | * Check if the entry's list_head is the head of the list, thus it's not a | ||
372 | * real entry but was the loop cursor that walked past the end | ||
373 | */ | ||
374 | #define list_entry_is_past_end(pos, head, member) \ | ||
375 | (&pos->member == (head)) | ||
376 | |||
377 | static size_t cx18_copy_mdl_to_user(struct cx18_stream *s, | 395 | static size_t cx18_copy_mdl_to_user(struct cx18_stream *s, |
378 | struct cx18_mdl *mdl, char __user *ubuf, size_t ucount) | 396 | struct cx18_mdl *mdl, char __user *ubuf, size_t ucount) |
379 | { | 397 | { |
@@ -498,6 +516,7 @@ int cx18_start_capture(struct cx18_open_id *id) | |||
498 | struct cx18 *cx = id->cx; | 516 | struct cx18 *cx = id->cx; |
499 | struct cx18_stream *s = &cx->streams[id->type]; | 517 | struct cx18_stream *s = &cx->streams[id->type]; |
500 | struct cx18_stream *s_vbi; | 518 | struct cx18_stream *s_vbi; |
519 | struct cx18_stream *s_idx; | ||
501 | 520 | ||
502 | if (s->type == CX18_ENC_STREAM_TYPE_RAD) { | 521 | if (s->type == CX18_ENC_STREAM_TYPE_RAD) { |
503 | /* you cannot read from these stream types. */ | 522 | /* you cannot read from these stream types. */ |
@@ -516,25 +535,33 @@ int cx18_start_capture(struct cx18_open_id *id) | |||
516 | return 0; | 535 | return 0; |
517 | } | 536 | } |
518 | 537 | ||
519 | /* Start VBI capture if required */ | 538 | /* Start associated VBI or IDX stream capture if required */ |
520 | s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI]; | 539 | s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI]; |
521 | if (s->type == CX18_ENC_STREAM_TYPE_MPG && | 540 | s_idx = &cx->streams[CX18_ENC_STREAM_TYPE_IDX]; |
522 | test_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags) && | 541 | if (s->type == CX18_ENC_STREAM_TYPE_MPG) { |
523 | !test_and_set_bit(CX18_F_S_STREAMING, &s_vbi->s_flags)) { | 542 | /* |
524 | /* Note: the CX18_ENC_STREAM_TYPE_VBI is claimed | 543 | * The VBI and IDX streams should have been claimed |
525 | automatically when the MPG stream is claimed. | 544 | * automatically, if for internal use, when the MPG stream was |
526 | We only need to start the VBI capturing. */ | 545 | * claimed. We only need to start these streams capturing. |
527 | if (cx18_start_v4l2_encode_stream(s_vbi)) { | 546 | */ |
528 | CX18_DEBUG_WARN("VBI capture start failed\n"); | 547 | if (test_bit(CX18_F_S_INTERNAL_USE, &s_idx->s_flags) && |
529 | 548 | !test_and_set_bit(CX18_F_S_STREAMING, &s_idx->s_flags)) { | |
530 | /* Failure, clean up and return an error */ | 549 | if (cx18_start_v4l2_encode_stream(s_idx)) { |
531 | clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags); | 550 | CX18_DEBUG_WARN("IDX capture start failed\n"); |
532 | clear_bit(CX18_F_S_STREAMING, &s->s_flags); | 551 | clear_bit(CX18_F_S_STREAMING, &s_idx->s_flags); |
533 | /* also releases the associated VBI stream */ | 552 | goto start_failed; |
534 | cx18_release_stream(s); | 553 | } |
535 | return -EIO; | 554 | CX18_DEBUG_INFO("IDX capture started\n"); |
555 | } | ||
556 | if (test_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags) && | ||
557 | !test_and_set_bit(CX18_F_S_STREAMING, &s_vbi->s_flags)) { | ||
558 | if (cx18_start_v4l2_encode_stream(s_vbi)) { | ||
559 | CX18_DEBUG_WARN("VBI capture start failed\n"); | ||
560 | clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags); | ||
561 | goto start_failed; | ||
562 | } | ||
563 | CX18_DEBUG_INFO("VBI insertion started\n"); | ||
536 | } | 564 | } |
537 | CX18_DEBUG_INFO("VBI insertion started\n"); | ||
538 | } | 565 | } |
539 | 566 | ||
540 | /* Tell the card to start capturing */ | 567 | /* Tell the card to start capturing */ |
@@ -547,19 +574,29 @@ int cx18_start_capture(struct cx18_open_id *id) | |||
547 | return 0; | 574 | return 0; |
548 | } | 575 | } |
549 | 576 | ||
550 | /* failure, clean up */ | 577 | start_failed: |
551 | CX18_DEBUG_WARN("Failed to start capturing for stream %s\n", s->name); | 578 | CX18_DEBUG_WARN("Failed to start capturing for stream %s\n", s->name); |
552 | 579 | ||
553 | /* Note: the CX18_ENC_STREAM_TYPE_VBI is released | 580 | /* |
554 | automatically when the MPG stream is released. | 581 | * The associated VBI and IDX streams for internal use are released |
555 | We only need to stop the VBI capturing. */ | 582 | * automatically when the MPG stream is released. We only need to stop |
556 | if (s->type == CX18_ENC_STREAM_TYPE_MPG && | 583 | * the associated stream. |
557 | test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags)) { | 584 | */ |
558 | cx18_stop_v4l2_encode_stream(s_vbi, 0); | 585 | if (s->type == CX18_ENC_STREAM_TYPE_MPG) { |
559 | clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags); | 586 | /* Stop the IDX stream which is always for internal use */ |
587 | if (test_bit(CX18_F_S_STREAMING, &s_idx->s_flags)) { | ||
588 | cx18_stop_v4l2_encode_stream(s_idx, 0); | ||
589 | clear_bit(CX18_F_S_STREAMING, &s_idx->s_flags); | ||
590 | } | ||
591 | /* Stop the VBI stream, if only running for internal use */ | ||
592 | if (test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags) && | ||
593 | !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) { | ||
594 | cx18_stop_v4l2_encode_stream(s_vbi, 0); | ||
595 | clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags); | ||
596 | } | ||
560 | } | 597 | } |
561 | clear_bit(CX18_F_S_STREAMING, &s->s_flags); | 598 | clear_bit(CX18_F_S_STREAMING, &s->s_flags); |
562 | cx18_release_stream(s); | 599 | cx18_release_stream(s); /* Also releases associated streams */ |
563 | return -EIO; | 600 | return -EIO; |
564 | } | 601 | } |
565 | 602 | ||
@@ -618,6 +655,8 @@ void cx18_stop_capture(struct cx18_open_id *id, int gop_end) | |||
618 | { | 655 | { |
619 | struct cx18 *cx = id->cx; | 656 | struct cx18 *cx = id->cx; |
620 | struct cx18_stream *s = &cx->streams[id->type]; | 657 | struct cx18_stream *s = &cx->streams[id->type]; |
658 | struct cx18_stream *s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI]; | ||
659 | struct cx18_stream *s_idx = &cx->streams[CX18_ENC_STREAM_TYPE_IDX]; | ||
621 | 660 | ||
622 | CX18_DEBUG_IOCTL("close() of %s\n", s->name); | 661 | CX18_DEBUG_IOCTL("close() of %s\n", s->name); |
623 | 662 | ||
@@ -625,17 +664,19 @@ void cx18_stop_capture(struct cx18_open_id *id, int gop_end) | |||
625 | 664 | ||
626 | /* Stop capturing */ | 665 | /* Stop capturing */ |
627 | if (test_bit(CX18_F_S_STREAMING, &s->s_flags)) { | 666 | if (test_bit(CX18_F_S_STREAMING, &s->s_flags)) { |
628 | struct cx18_stream *s_vbi = | ||
629 | &cx->streams[CX18_ENC_STREAM_TYPE_VBI]; | ||
630 | |||
631 | CX18_DEBUG_INFO("close stopping capture\n"); | 667 | CX18_DEBUG_INFO("close stopping capture\n"); |
632 | /* Special case: a running VBI capture for VBI insertion | 668 | if (id->type == CX18_ENC_STREAM_TYPE_MPG) { |
633 | in the mpeg stream. Need to stop that too. */ | 669 | /* Stop internal use associated VBI and IDX streams */ |
634 | if (id->type == CX18_ENC_STREAM_TYPE_MPG && | 670 | if (test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags) && |
635 | test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags) && | 671 | !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) { |
636 | !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) { | 672 | CX18_DEBUG_INFO("close stopping embedded VBI " |
637 | CX18_DEBUG_INFO("close stopping embedded VBI capture\n"); | 673 | "capture\n"); |
638 | cx18_stop_v4l2_encode_stream(s_vbi, 0); | 674 | cx18_stop_v4l2_encode_stream(s_vbi, 0); |
675 | } | ||
676 | if (test_bit(CX18_F_S_STREAMING, &s_idx->s_flags)) { | ||
677 | CX18_DEBUG_INFO("close stopping IDX capture\n"); | ||
678 | cx18_stop_v4l2_encode_stream(s_idx, 0); | ||
679 | } | ||
639 | } | 680 | } |
640 | if (id->type == CX18_ENC_STREAM_TYPE_VBI && | 681 | if (id->type == CX18_ENC_STREAM_TYPE_VBI && |
641 | test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags)) | 682 | test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags)) |
diff --git a/drivers/media/video/cx18/cx18-fileops.h b/drivers/media/video/cx18/cx18-fileops.h index 92e2d5dab936..5c8fcb884f0a 100644 --- a/drivers/media/video/cx18/cx18-fileops.h +++ b/drivers/media/video/cx18/cx18-fileops.h | |||
@@ -34,3 +34,6 @@ void cx18_stop_capture(struct cx18_open_id *id, int gop_end); | |||
34 | void cx18_mute(struct cx18 *cx); | 34 | void cx18_mute(struct cx18 *cx); |
35 | void cx18_unmute(struct cx18 *cx); | 35 | void cx18_unmute(struct cx18 *cx); |
36 | 36 | ||
37 | /* Shared with cx18-alsa module */ | ||
38 | int cx18_claim_stream(struct cx18_open_id *id, int type); | ||
39 | void cx18_release_stream(struct cx18_stream *s); | ||
diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c index 3e4fc192fdec..b81dd0ea8eb9 100644 --- a/drivers/media/video/cx18/cx18-ioctl.c +++ b/drivers/media/video/cx18/cx18-ioctl.c | |||
@@ -775,10 +775,143 @@ static int cx18_g_sliced_vbi_cap(struct file *file, void *fh, | |||
775 | return 0; | 775 | return 0; |
776 | } | 776 | } |
777 | 777 | ||
778 | static int _cx18_process_idx_data(struct cx18_buffer *buf, | ||
779 | struct v4l2_enc_idx *idx) | ||
780 | { | ||
781 | int consumed, remaining; | ||
782 | struct v4l2_enc_idx_entry *e_idx; | ||
783 | struct cx18_enc_idx_entry *e_buf; | ||
784 | |||
785 | /* Frame type lookup: 1=I, 2=P, 4=B */ | ||
786 | const int mapping[8] = { | ||
787 | -1, V4L2_ENC_IDX_FRAME_I, V4L2_ENC_IDX_FRAME_P, | ||
788 | -1, V4L2_ENC_IDX_FRAME_B, -1, -1, -1 | ||
789 | }; | ||
790 | |||
791 | /* | ||
792 | * Assumption here is that a buf holds an integral number of | ||
793 | * struct cx18_enc_idx_entry objects and is properly aligned. | ||
794 | * This is enforced by the module options on IDX buffer sizes. | ||
795 | */ | ||
796 | remaining = buf->bytesused - buf->readpos; | ||
797 | consumed = 0; | ||
798 | e_idx = &idx->entry[idx->entries]; | ||
799 | e_buf = (struct cx18_enc_idx_entry *) &buf->buf[buf->readpos]; | ||
800 | |||
801 | while (remaining >= sizeof(struct cx18_enc_idx_entry) && | ||
802 | idx->entries < V4L2_ENC_IDX_ENTRIES) { | ||
803 | |||
804 | e_idx->offset = (((u64) le32_to_cpu(e_buf->offset_high)) << 32) | ||
805 | | le32_to_cpu(e_buf->offset_low); | ||
806 | |||
807 | e_idx->pts = (((u64) (le32_to_cpu(e_buf->pts_high) & 1)) << 32) | ||
808 | | le32_to_cpu(e_buf->pts_low); | ||
809 | |||
810 | e_idx->length = le32_to_cpu(e_buf->length); | ||
811 | |||
812 | e_idx->flags = mapping[le32_to_cpu(e_buf->flags) & 0x7]; | ||
813 | |||
814 | e_idx->reserved[0] = 0; | ||
815 | e_idx->reserved[1] = 0; | ||
816 | |||
817 | idx->entries++; | ||
818 | e_idx = &idx->entry[idx->entries]; | ||
819 | e_buf++; | ||
820 | |||
821 | remaining -= sizeof(struct cx18_enc_idx_entry); | ||
822 | consumed += sizeof(struct cx18_enc_idx_entry); | ||
823 | } | ||
824 | |||
825 | /* Swallow any partial entries at the end, if there are any */ | ||
826 | if (remaining > 0 && remaining < sizeof(struct cx18_enc_idx_entry)) | ||
827 | consumed += remaining; | ||
828 | |||
829 | buf->readpos += consumed; | ||
830 | return consumed; | ||
831 | } | ||
832 | |||
833 | static int cx18_process_idx_data(struct cx18_stream *s, struct cx18_mdl *mdl, | ||
834 | struct v4l2_enc_idx *idx) | ||
835 | { | ||
836 | if (s->type != CX18_ENC_STREAM_TYPE_IDX) | ||
837 | return -EINVAL; | ||
838 | |||
839 | if (mdl->curr_buf == NULL) | ||
840 | mdl->curr_buf = list_first_entry(&mdl->buf_list, | ||
841 | struct cx18_buffer, list); | ||
842 | |||
843 | if (list_entry_is_past_end(mdl->curr_buf, &mdl->buf_list, list)) { | ||
844 | /* | ||
845 | * For some reason we've exhausted the buffers, but the MDL | ||
846 | * object still said some data was unread. | ||
847 | * Fix that and bail out. | ||
848 | */ | ||
849 | mdl->readpos = mdl->bytesused; | ||
850 | return 0; | ||
851 | } | ||
852 | |||
853 | list_for_each_entry_from(mdl->curr_buf, &mdl->buf_list, list) { | ||
854 | |||
855 | /* Skip any empty buffers in the MDL */ | ||
856 | if (mdl->curr_buf->readpos >= mdl->curr_buf->bytesused) | ||
857 | continue; | ||
858 | |||
859 | mdl->readpos += _cx18_process_idx_data(mdl->curr_buf, idx); | ||
860 | |||
861 | /* exit when MDL drained or request satisfied */ | ||
862 | if (idx->entries >= V4L2_ENC_IDX_ENTRIES || | ||
863 | mdl->curr_buf->readpos < mdl->curr_buf->bytesused || | ||
864 | mdl->readpos >= mdl->bytesused) | ||
865 | break; | ||
866 | } | ||
867 | return 0; | ||
868 | } | ||
869 | |||
778 | static int cx18_g_enc_index(struct file *file, void *fh, | 870 | static int cx18_g_enc_index(struct file *file, void *fh, |
779 | struct v4l2_enc_idx *idx) | 871 | struct v4l2_enc_idx *idx) |
780 | { | 872 | { |
781 | return -EINVAL; | 873 | struct cx18 *cx = ((struct cx18_open_id *)fh)->cx; |
874 | struct cx18_stream *s = &cx->streams[CX18_ENC_STREAM_TYPE_IDX]; | ||
875 | s32 tmp; | ||
876 | struct cx18_mdl *mdl; | ||
877 | |||
878 | if (!cx18_stream_enabled(s)) /* Module options inhibited IDX stream */ | ||
879 | return -EINVAL; | ||
880 | |||
881 | /* Compute the best case number of entries we can buffer */ | ||
882 | tmp = s->buffers - | ||
883 | s->bufs_per_mdl * CX18_ENC_STREAM_TYPE_IDX_FW_MDL_MIN; | ||
884 | if (tmp <= 0) | ||
885 | tmp = 1; | ||
886 | tmp = tmp * s->buf_size / sizeof(struct cx18_enc_idx_entry); | ||
887 | |||
888 | /* Fill out the header of the return structure */ | ||
889 | idx->entries = 0; | ||
890 | idx->entries_cap = tmp; | ||
891 | memset(idx->reserved, 0, sizeof(idx->reserved)); | ||
892 | |||
893 | /* Pull IDX MDLs and buffers from q_full and populate the entries */ | ||
894 | do { | ||
895 | mdl = cx18_dequeue(s, &s->q_full); | ||
896 | if (mdl == NULL) /* No more IDX data right now */ | ||
897 | break; | ||
898 | |||
899 | /* Extract the Index entry data from the MDL and buffers */ | ||
900 | cx18_process_idx_data(s, mdl, idx); | ||
901 | if (mdl->readpos < mdl->bytesused) { | ||
902 | /* We finished with data remaining, push the MDL back */ | ||
903 | cx18_push(s, mdl, &s->q_full); | ||
904 | break; | ||
905 | } | ||
906 | |||
907 | /* We drained this MDL, schedule it to go to the firmware */ | ||
908 | cx18_enqueue(s, mdl, &s->q_free); | ||
909 | |||
910 | } while (idx->entries < V4L2_ENC_IDX_ENTRIES); | ||
911 | |||
912 | /* Tell the work handler to send free IDX MDLs to the firmware */ | ||
913 | cx18_stream_load_fw_queue(s); | ||
914 | return 0; | ||
782 | } | 915 | } |
783 | 916 | ||
784 | static int cx18_encoder_cmd(struct file *file, void *fh, | 917 | static int cx18_encoder_cmd(struct file *file, void *fh, |
diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c index f231dd09c720..6dcce297752f 100644 --- a/drivers/media/video/cx18/cx18-mailbox.c +++ b/drivers/media/video/cx18/cx18-mailbox.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include "cx18-mailbox.h" | 29 | #include "cx18-mailbox.h" |
30 | #include "cx18-queue.h" | 30 | #include "cx18-queue.h" |
31 | #include "cx18-streams.h" | 31 | #include "cx18-streams.h" |
32 | #include "cx18-alsa-pcm.h" /* FIXME make configurable */ | ||
32 | 33 | ||
33 | static const char *rpu_str[] = { "APU", "CPU", "EPU", "HPU" }; | 34 | static const char *rpu_str[] = { "APU", "CPU", "EPU", "HPU" }; |
34 | 35 | ||
@@ -157,6 +158,34 @@ static void cx18_mdl_send_to_dvb(struct cx18_stream *s, struct cx18_mdl *mdl) | |||
157 | } | 158 | } |
158 | } | 159 | } |
159 | 160 | ||
161 | |||
162 | static void cx18_mdl_send_to_alsa(struct cx18 *cx, struct cx18_stream *s, | ||
163 | struct cx18_mdl *mdl) | ||
164 | { | ||
165 | struct cx18_buffer *buf; | ||
166 | |||
167 | if (mdl->bytesused == 0) | ||
168 | return; | ||
169 | |||
170 | /* We ignore mdl and buf readpos accounting here - it doesn't matter */ | ||
171 | |||
172 | /* The likely case */ | ||
173 | if (list_is_singular(&mdl->buf_list)) { | ||
174 | buf = list_first_entry(&mdl->buf_list, struct cx18_buffer, | ||
175 | list); | ||
176 | if (buf->bytesused) | ||
177 | cx->pcm_announce_callback(cx->alsa, buf->buf, | ||
178 | buf->bytesused); | ||
179 | return; | ||
180 | } | ||
181 | |||
182 | list_for_each_entry(buf, &mdl->buf_list, list) { | ||
183 | if (buf->bytesused == 0) | ||
184 | break; | ||
185 | cx->pcm_announce_callback(cx->alsa, buf->buf, buf->bytesused); | ||
186 | } | ||
187 | } | ||
188 | |||
160 | static void epu_dma_done(struct cx18 *cx, struct cx18_in_work_order *order) | 189 | static void epu_dma_done(struct cx18 *cx, struct cx18_in_work_order *order) |
161 | { | 190 | { |
162 | u32 handle, mdl_ack_count, id; | 191 | u32 handle, mdl_ack_count, id; |
@@ -223,11 +252,21 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_in_work_order *order) | |||
223 | CX18_DEBUG_HI_DMA("%s recv bytesused = %d\n", | 252 | CX18_DEBUG_HI_DMA("%s recv bytesused = %d\n", |
224 | s->name, mdl->bytesused); | 253 | s->name, mdl->bytesused); |
225 | 254 | ||
226 | if (s->type != CX18_ENC_STREAM_TYPE_TS) | 255 | if (s->type == CX18_ENC_STREAM_TYPE_TS) { |
227 | cx18_enqueue(s, mdl, &s->q_full); | ||
228 | else { | ||
229 | cx18_mdl_send_to_dvb(s, mdl); | 256 | cx18_mdl_send_to_dvb(s, mdl); |
230 | cx18_enqueue(s, mdl, &s->q_free); | 257 | cx18_enqueue(s, mdl, &s->q_free); |
258 | } else if (s->type == CX18_ENC_STREAM_TYPE_PCM) { | ||
259 | /* Pass the data to cx18-alsa */ | ||
260 | if (cx->pcm_announce_callback != NULL) { | ||
261 | cx18_mdl_send_to_alsa(cx, s, mdl); | ||
262 | cx18_enqueue(s, mdl, &s->q_free); | ||
263 | } else { | ||
264 | cx18_enqueue(s, mdl, &s->q_full); | ||
265 | } | ||
266 | } else { | ||
267 | cx18_enqueue(s, mdl, &s->q_full); | ||
268 | if (s->type == CX18_ENC_STREAM_TYPE_IDX) | ||
269 | cx18_stream_rotate_idx_mdls(cx); | ||
231 | } | 270 | } |
232 | } | 271 | } |
233 | /* Put as many MDLs as possible back into fw use */ | 272 | /* Put as many MDLs as possible back into fw use */ |
diff --git a/drivers/media/video/cx18/cx18-queue.c b/drivers/media/video/cx18/cx18-queue.c index 63304823cef5..aefc8c8cf3c1 100644 --- a/drivers/media/video/cx18/cx18-queue.c +++ b/drivers/media/video/cx18/cx18-queue.c | |||
@@ -419,6 +419,9 @@ void cx18_stream_free(struct cx18_stream *s) | |||
419 | { | 419 | { |
420 | struct cx18_mdl *mdl; | 420 | struct cx18_mdl *mdl; |
421 | struct cx18_buffer *buf; | 421 | struct cx18_buffer *buf; |
422 | struct cx18 *cx = s->cx; | ||
423 | |||
424 | CX18_DEBUG_INFO("Deallocating buffers for %s stream\n", s->name); | ||
422 | 425 | ||
423 | /* move all buffers to buf_pool and all MDLs to q_idle */ | 426 | /* move all buffers to buf_pool and all MDLs to q_idle */ |
424 | cx18_unload_queues(s); | 427 | cx18_unload_queues(s); |
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index 987a9308d938..054450f65a60 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c | |||
@@ -319,11 +319,27 @@ void cx18_streams_cleanup(struct cx18 *cx, int unregister) | |||
319 | 319 | ||
320 | /* Teardown all streams */ | 320 | /* Teardown all streams */ |
321 | for (type = 0; type < CX18_MAX_STREAMS; type++) { | 321 | for (type = 0; type < CX18_MAX_STREAMS; type++) { |
322 | if (cx->streams[type].dvb.enabled) { | 322 | |
323 | cx18_dvb_unregister(&cx->streams[type]); | 323 | /* No struct video_device, but can have buffers allocated */ |
324 | cx->streams[type].dvb.enabled = false; | 324 | if (type == CX18_ENC_STREAM_TYPE_TS) { |
325 | if (cx->streams[type].dvb.enabled) { | ||
326 | cx18_dvb_unregister(&cx->streams[type]); | ||
327 | cx->streams[type].dvb.enabled = false; | ||
328 | cx18_stream_free(&cx->streams[type]); | ||
329 | } | ||
330 | continue; | ||
331 | } | ||
332 | |||
333 | /* No struct video_device, but can have buffers allocated */ | ||
334 | if (type == CX18_ENC_STREAM_TYPE_IDX) { | ||
335 | if (cx->stream_buffers[type] != 0) { | ||
336 | cx->stream_buffers[type] = 0; | ||
337 | cx18_stream_free(&cx->streams[type]); | ||
338 | } | ||
339 | continue; | ||
325 | } | 340 | } |
326 | 341 | ||
342 | /* If struct video_device exists, can have buffers allocated */ | ||
327 | vdev = cx->streams[type].video_dev; | 343 | vdev = cx->streams[type].video_dev; |
328 | 344 | ||
329 | cx->streams[type].video_dev = NULL; | 345 | cx->streams[type].video_dev = NULL; |
@@ -447,6 +463,32 @@ static void cx18_vbi_setup(struct cx18_stream *s) | |||
447 | cx18_api(cx, CX18_CPU_SET_RAW_VBI_PARAM, 6, data); | 463 | cx18_api(cx, CX18_CPU_SET_RAW_VBI_PARAM, 6, data); |
448 | } | 464 | } |
449 | 465 | ||
466 | void cx18_stream_rotate_idx_mdls(struct cx18 *cx) | ||
467 | { | ||
468 | struct cx18_stream *s = &cx->streams[CX18_ENC_STREAM_TYPE_IDX]; | ||
469 | struct cx18_mdl *mdl; | ||
470 | |||
471 | if (!cx18_stream_enabled(s)) | ||
472 | return; | ||
473 | |||
474 | /* Return if the firmware is not running low on MDLs */ | ||
475 | if ((atomic_read(&s->q_free.depth) + atomic_read(&s->q_busy.depth)) >= | ||
476 | CX18_ENC_STREAM_TYPE_IDX_FW_MDL_MIN) | ||
477 | return; | ||
478 | |||
479 | /* Return if there are no MDLs to rotate back to the firmware */ | ||
480 | if (atomic_read(&s->q_full.depth) < 2) | ||
481 | return; | ||
482 | |||
483 | /* | ||
484 | * Take the oldest IDX MDL still holding data, and discard its index | ||
485 | * entries by scheduling the MDL to go back to the firmware | ||
486 | */ | ||
487 | mdl = cx18_dequeue(s, &s->q_full); | ||
488 | if (mdl != NULL) | ||
489 | cx18_enqueue(s, mdl, &s->q_free); | ||
490 | } | ||
491 | |||
450 | static | 492 | static |
451 | struct cx18_queue *_cx18_stream_put_mdl_fw(struct cx18_stream *s, | 493 | struct cx18_queue *_cx18_stream_put_mdl_fw(struct cx18_stream *s, |
452 | struct cx18_mdl *mdl) | 494 | struct cx18_mdl *mdl) |
@@ -546,8 +588,9 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) | |||
546 | struct cx18 *cx = s->cx; | 588 | struct cx18 *cx = s->cx; |
547 | int captype = 0; | 589 | int captype = 0; |
548 | struct cx18_api_func_private priv; | 590 | struct cx18_api_func_private priv; |
591 | struct cx18_stream *s_idx; | ||
549 | 592 | ||
550 | if (s->video_dev == NULL && s->dvb.enabled == 0) | 593 | if (!cx18_stream_enabled(s)) |
551 | return -EINVAL; | 594 | return -EINVAL; |
552 | 595 | ||
553 | CX18_DEBUG_INFO("Start encoder stream %s\n", s->name); | 596 | CX18_DEBUG_INFO("Start encoder stream %s\n", s->name); |
@@ -561,6 +604,9 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) | |||
561 | cx->search_pack_header = 0; | 604 | cx->search_pack_header = 0; |
562 | break; | 605 | break; |
563 | 606 | ||
607 | case CX18_ENC_STREAM_TYPE_IDX: | ||
608 | captype = CAPTURE_CHANNEL_TYPE_INDEX; | ||
609 | break; | ||
564 | case CX18_ENC_STREAM_TYPE_TS: | 610 | case CX18_ENC_STREAM_TYPE_TS: |
565 | captype = CAPTURE_CHANNEL_TYPE_TS; | 611 | captype = CAPTURE_CHANNEL_TYPE_TS; |
566 | break; | 612 | break; |
@@ -635,11 +681,13 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) | |||
635 | cx18_vbi_setup(s); | 681 | cx18_vbi_setup(s); |
636 | 682 | ||
637 | /* | 683 | /* |
638 | * assign program index info. | 684 | * Select to receive I, P, and B frame index entries, if the |
639 | * Mask 7: select I/P/B, Num_req: 400 max | 685 | * index stream is enabled. Otherwise disable index entry |
640 | * FIXME - currently we have this hardcoded as disabled | 686 | * generation. |
641 | */ | 687 | */ |
642 | cx18_vapi_result(cx, data, CX18_CPU_SET_INDEXTABLE, 1, 0); | 688 | s_idx = &cx->streams[CX18_ENC_STREAM_TYPE_IDX]; |
689 | cx18_vapi_result(cx, data, CX18_CPU_SET_INDEXTABLE, 2, | ||
690 | s->handle, cx18_stream_enabled(s_idx) ? 7 : 0); | ||
643 | 691 | ||
644 | /* Call out to the common CX2341x API setup for user controls */ | 692 | /* Call out to the common CX2341x API setup for user controls */ |
645 | priv.cx = cx; | 693 | priv.cx = cx; |
@@ -697,6 +745,7 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) | |||
697 | atomic_inc(&cx->tot_capturing); | 745 | atomic_inc(&cx->tot_capturing); |
698 | return 0; | 746 | return 0; |
699 | } | 747 | } |
748 | EXPORT_SYMBOL(cx18_start_v4l2_encode_stream); | ||
700 | 749 | ||
701 | void cx18_stop_all_captures(struct cx18 *cx) | 750 | void cx18_stop_all_captures(struct cx18 *cx) |
702 | { | 751 | { |
@@ -705,7 +754,7 @@ void cx18_stop_all_captures(struct cx18 *cx) | |||
705 | for (i = CX18_MAX_STREAMS - 1; i >= 0; i--) { | 754 | for (i = CX18_MAX_STREAMS - 1; i >= 0; i--) { |
706 | struct cx18_stream *s = &cx->streams[i]; | 755 | struct cx18_stream *s = &cx->streams[i]; |
707 | 756 | ||
708 | if (s->video_dev == NULL && s->dvb.enabled == 0) | 757 | if (!cx18_stream_enabled(s)) |
709 | continue; | 758 | continue; |
710 | if (test_bit(CX18_F_S_STREAMING, &s->s_flags)) | 759 | if (test_bit(CX18_F_S_STREAMING, &s->s_flags)) |
711 | cx18_stop_v4l2_encode_stream(s, 0); | 760 | cx18_stop_v4l2_encode_stream(s, 0); |
@@ -717,7 +766,7 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end) | |||
717 | struct cx18 *cx = s->cx; | 766 | struct cx18 *cx = s->cx; |
718 | unsigned long then; | 767 | unsigned long then; |
719 | 768 | ||
720 | if (s->video_dev == NULL && s->dvb.enabled == 0) | 769 | if (!cx18_stream_enabled(s)) |
721 | return -EINVAL; | 770 | return -EINVAL; |
722 | 771 | ||
723 | /* This function assumes that you are allowed to stop the capture | 772 | /* This function assumes that you are allowed to stop the capture |
@@ -762,6 +811,7 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end) | |||
762 | 811 | ||
763 | return 0; | 812 | return 0; |
764 | } | 813 | } |
814 | EXPORT_SYMBOL(cx18_stop_v4l2_encode_stream); | ||
765 | 815 | ||
766 | u32 cx18_find_handle(struct cx18 *cx) | 816 | u32 cx18_find_handle(struct cx18 *cx) |
767 | { | 817 | { |
@@ -789,7 +839,7 @@ struct cx18_stream *cx18_handle_to_stream(struct cx18 *cx, u32 handle) | |||
789 | s = &cx->streams[i]; | 839 | s = &cx->streams[i]; |
790 | if (s->handle != handle) | 840 | if (s->handle != handle) |
791 | continue; | 841 | continue; |
792 | if (s->video_dev || s->dvb.enabled) | 842 | if (cx18_stream_enabled(s)) |
793 | return s; | 843 | return s; |
794 | } | 844 | } |
795 | return NULL; | 845 | return NULL; |
diff --git a/drivers/media/video/cx18/cx18-streams.h b/drivers/media/video/cx18/cx18-streams.h index 4a01db5e5a35..0bff0fa29763 100644 --- a/drivers/media/video/cx18/cx18-streams.h +++ b/drivers/media/video/cx18/cx18-streams.h | |||
@@ -28,6 +28,16 @@ int cx18_streams_setup(struct cx18 *cx); | |||
28 | int cx18_streams_register(struct cx18 *cx); | 28 | int cx18_streams_register(struct cx18 *cx); |
29 | void cx18_streams_cleanup(struct cx18 *cx, int unregister); | 29 | void cx18_streams_cleanup(struct cx18 *cx, int unregister); |
30 | 30 | ||
31 | #define CX18_ENC_STREAM_TYPE_IDX_FW_MDL_MIN (3) | ||
32 | void cx18_stream_rotate_idx_mdls(struct cx18 *cx); | ||
33 | |||
34 | static inline bool cx18_stream_enabled(struct cx18_stream *s) | ||
35 | { | ||
36 | return s->video_dev || s->dvb.enabled || | ||
37 | (s->type == CX18_ENC_STREAM_TYPE_IDX && | ||
38 | s->cx->stream_buffers[CX18_ENC_STREAM_TYPE_IDX] != 0); | ||
39 | } | ||
40 | |||
31 | /* Related to submission of mdls to firmware */ | 41 | /* Related to submission of mdls to firmware */ |
32 | static inline void cx18_stream_load_fw_queue(struct cx18_stream *s) | 42 | static inline void cx18_stream_load_fw_queue(struct cx18_stream *s) |
33 | { | 43 | { |
diff --git a/drivers/media/video/cx18/cx18-version.h b/drivers/media/video/cx18/cx18-version.h index 9c0b5bb1b019..3e1aec4bcfde 100644 --- a/drivers/media/video/cx18/cx18-version.h +++ b/drivers/media/video/cx18/cx18-version.h | |||
@@ -24,7 +24,7 @@ | |||
24 | 24 | ||
25 | #define CX18_DRIVER_NAME "cx18" | 25 | #define CX18_DRIVER_NAME "cx18" |
26 | #define CX18_DRIVER_VERSION_MAJOR 1 | 26 | #define CX18_DRIVER_VERSION_MAJOR 1 |
27 | #define CX18_DRIVER_VERSION_MINOR 3 | 27 | #define CX18_DRIVER_VERSION_MINOR 4 |
28 | #define CX18_DRIVER_VERSION_PATCHLEVEL 0 | 28 | #define CX18_DRIVER_VERSION_PATCHLEVEL 0 |
29 | 29 | ||
30 | #define CX18_VERSION __stringify(CX18_DRIVER_VERSION_MAJOR) "." __stringify(CX18_DRIVER_VERSION_MINOR) "." __stringify(CX18_DRIVER_VERSION_PATCHLEVEL) | 30 | #define CX18_VERSION __stringify(CX18_DRIVER_VERSION_MAJOR) "." __stringify(CX18_DRIVER_VERSION_MINOR) "." __stringify(CX18_DRIVER_VERSION_PATCHLEVEL) |
diff --git a/drivers/media/video/cx18/cx23418.h b/drivers/media/video/cx18/cx23418.h index 868806effdcf..2c00980acfcb 100644 --- a/drivers/media/video/cx18/cx23418.h +++ b/drivers/media/video/cx18/cx23418.h | |||
@@ -191,7 +191,8 @@ | |||
191 | #define CX18_CPU_SET_MEDIAN_CORING (CPU_CMD_MASK_CAPTURE | 0x000E) | 191 | #define CX18_CPU_SET_MEDIAN_CORING (CPU_CMD_MASK_CAPTURE | 0x000E) |
192 | 192 | ||
193 | /* Description: This command set the picture type mask for index file | 193 | /* Description: This command set the picture type mask for index file |
194 | IN[0] - 0 = disable index file output | 194 | IN[0] - Task handle (ignored by firmware) |
195 | IN[1] - 0 = disable index file output | ||
195 | 1 = output I picture | 196 | 1 = output I picture |
196 | 2 = P picture | 197 | 2 = P picture |
197 | 4 = B picture | 198 | 4 = B picture |
diff --git a/drivers/media/video/cx231xx/cx231xx-dvb.c b/drivers/media/video/cx231xx/cx231xx-dvb.c index c5082a4e8ced..64e025e2bdf1 100644 --- a/drivers/media/video/cx231xx/cx231xx-dvb.c +++ b/drivers/media/video/cx231xx/cx231xx-dvb.c | |||
@@ -464,9 +464,9 @@ static int dvb_init(struct cx231xx *dev) | |||
464 | /* define general-purpose callback pointer */ | 464 | /* define general-purpose callback pointer */ |
465 | dvb->frontend->callback = cx231xx_tuner_callback; | 465 | dvb->frontend->callback = cx231xx_tuner_callback; |
466 | 466 | ||
467 | if (dvb_attach(xc5000_attach, dev->dvb->frontend, | 467 | if (!dvb_attach(xc5000_attach, dev->dvb->frontend, |
468 | &dev->i2c_bus[1].i2c_adap, | 468 | &dev->i2c_bus[1].i2c_adap, |
469 | &cnxt_rde250_tunerconfig) < 0) { | 469 | &cnxt_rde250_tunerconfig)) { |
470 | result = -EINVAL; | 470 | result = -EINVAL; |
471 | goto out_free; | 471 | goto out_free; |
472 | } | 472 | } |
@@ -486,9 +486,9 @@ static int dvb_init(struct cx231xx *dev) | |||
486 | /* define general-purpose callback pointer */ | 486 | /* define general-purpose callback pointer */ |
487 | dvb->frontend->callback = cx231xx_tuner_callback; | 487 | dvb->frontend->callback = cx231xx_tuner_callback; |
488 | 488 | ||
489 | if (dvb_attach(xc5000_attach, dev->dvb->frontend, | 489 | if (!dvb_attach(xc5000_attach, dev->dvb->frontend, |
490 | &dev->i2c_bus[1].i2c_adap, | 490 | &dev->i2c_bus[1].i2c_adap, |
491 | &cnxt_rde250_tunerconfig) < 0) { | 491 | &cnxt_rde250_tunerconfig)) { |
492 | result = -EINVAL; | 492 | result = -EINVAL; |
493 | goto out_free; | 493 | goto out_free; |
494 | } | 494 | } |
diff --git a/drivers/media/video/cx231xx/cx231xx-input.c b/drivers/media/video/cx231xx/cx231xx-input.c index 15826f98b688..c5771db3bfce 100644 --- a/drivers/media/video/cx231xx/cx231xx-input.c +++ b/drivers/media/video/cx231xx/cx231xx-input.c | |||
@@ -216,7 +216,7 @@ int cx231xx_ir_init(struct cx231xx *dev) | |||
216 | cx231xx_ir_start(ir); | 216 | cx231xx_ir_start(ir); |
217 | 217 | ||
218 | /* all done */ | 218 | /* all done */ |
219 | err = ir_input_register(ir->input, dev->board.ir_codes); | 219 | err = ir_input_register(ir->input, dev->board.ir_codes, NULL); |
220 | if (err) | 220 | if (err) |
221 | goto err_out_stop; | 221 | goto err_out_stop; |
222 | 222 | ||
diff --git a/drivers/media/video/cx23885/cx23885-417.c b/drivers/media/video/cx23885/cx23885-417.c index 88c0d2481118..2ab97ad7b6fb 100644 --- a/drivers/media/video/cx23885/cx23885-417.c +++ b/drivers/media/video/cx23885/cx23885-417.c | |||
@@ -681,7 +681,7 @@ static char *cmd_to_str(int cmd) | |||
681 | case CX2341X_ENC_SET_VIDEO_ID: | 681 | case CX2341X_ENC_SET_VIDEO_ID: |
682 | return "SET_VIDEO_ID"; | 682 | return "SET_VIDEO_ID"; |
683 | case CX2341X_ENC_SET_PCR_ID: | 683 | case CX2341X_ENC_SET_PCR_ID: |
684 | return "SET_PCR_PID"; | 684 | return "SET_PCR_ID"; |
685 | case CX2341X_ENC_SET_FRAME_RATE: | 685 | case CX2341X_ENC_SET_FRAME_RATE: |
686 | return "SET_FRAME_RATE"; | 686 | return "SET_FRAME_RATE"; |
687 | case CX2341X_ENC_SET_FRAME_SIZE: | 687 | case CX2341X_ENC_SET_FRAME_SIZE: |
@@ -693,7 +693,7 @@ static char *cmd_to_str(int cmd) | |||
693 | case CX2341X_ENC_SET_ASPECT_RATIO: | 693 | case CX2341X_ENC_SET_ASPECT_RATIO: |
694 | return "SET_ASPECT_RATIO"; | 694 | return "SET_ASPECT_RATIO"; |
695 | case CX2341X_ENC_SET_DNR_FILTER_MODE: | 695 | case CX2341X_ENC_SET_DNR_FILTER_MODE: |
696 | return "SET_DNR_FILTER_PROPS"; | 696 | return "SET_DNR_FILTER_MODE"; |
697 | case CX2341X_ENC_SET_DNR_FILTER_PROPS: | 697 | case CX2341X_ENC_SET_DNR_FILTER_PROPS: |
698 | return "SET_DNR_FILTER_PROPS"; | 698 | return "SET_DNR_FILTER_PROPS"; |
699 | case CX2341X_ENC_SET_CORING_LEVELS: | 699 | case CX2341X_ENC_SET_CORING_LEVELS: |
diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index 1ec48169277d..d639186f645d 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c | |||
@@ -274,6 +274,31 @@ struct cx23885_board cx23885_boards[] = { | |||
274 | .portb = CX23885_MPEG_DVB, | 274 | .portb = CX23885_MPEG_DVB, |
275 | .portc = CX23885_MPEG_DVB, | 275 | .portc = CX23885_MPEG_DVB, |
276 | }, | 276 | }, |
277 | [CX23885_BOARD_LEADTEK_WINFAST_PXTV1200] = { | ||
278 | .name = "LEADTEK WinFast PxTV1200", | ||
279 | .porta = CX23885_ANALOG_VIDEO, | ||
280 | .tuner_type = TUNER_XC2028, | ||
281 | .tuner_addr = 0x61, | ||
282 | .input = {{ | ||
283 | .type = CX23885_VMUX_TELEVISION, | ||
284 | .vmux = CX25840_VIN2_CH1 | | ||
285 | CX25840_VIN5_CH2 | | ||
286 | CX25840_NONE0_CH3, | ||
287 | }, { | ||
288 | .type = CX23885_VMUX_COMPOSITE1, | ||
289 | .vmux = CX25840_COMPOSITE1, | ||
290 | }, { | ||
291 | .type = CX23885_VMUX_SVIDEO, | ||
292 | .vmux = CX25840_SVIDEO_LUMA3 | | ||
293 | CX25840_SVIDEO_CHROMA4, | ||
294 | }, { | ||
295 | .type = CX23885_VMUX_COMPONENT, | ||
296 | .vmux = CX25840_VIN7_CH1 | | ||
297 | CX25840_VIN6_CH2 | | ||
298 | CX25840_VIN8_CH3 | | ||
299 | CX25840_COMPONENT_ON, | ||
300 | } }, | ||
301 | }, | ||
277 | }; | 302 | }; |
278 | const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); | 303 | const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); |
279 | 304 | ||
@@ -417,6 +442,10 @@ struct cx23885_subid cx23885_subids[] = { | |||
417 | .subvendor = 0x14f1, | 442 | .subvendor = 0x14f1, |
418 | .subdevice = 0x8578, | 443 | .subdevice = 0x8578, |
419 | .card = CX23885_BOARD_MYGICA_X8558PRO, | 444 | .card = CX23885_BOARD_MYGICA_X8558PRO, |
445 | }, { | ||
446 | .subvendor = 0x107d, | ||
447 | .subdevice = 0x6f22, | ||
448 | .card = CX23885_BOARD_LEADTEK_WINFAST_PXTV1200, | ||
420 | }, | 449 | }, |
421 | }; | 450 | }; |
422 | const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); | 451 | const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); |
@@ -617,6 +646,7 @@ int cx23885_tuner_callback(void *priv, int component, int command, int arg) | |||
617 | case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: | 646 | case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: |
618 | case CX23885_BOARD_COMPRO_VIDEOMATE_E650F: | 647 | case CX23885_BOARD_COMPRO_VIDEOMATE_E650F: |
619 | case CX23885_BOARD_COMPRO_VIDEOMATE_E800: | 648 | case CX23885_BOARD_COMPRO_VIDEOMATE_E800: |
649 | case CX23885_BOARD_LEADTEK_WINFAST_PXTV1200: | ||
620 | /* Tuner Reset Command */ | 650 | /* Tuner Reset Command */ |
621 | bitmask = 0x04; | 651 | bitmask = 0x04; |
622 | break; | 652 | break; |
@@ -769,6 +799,7 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) | |||
769 | case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: | 799 | case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: |
770 | case CX23885_BOARD_COMPRO_VIDEOMATE_E650F: | 800 | case CX23885_BOARD_COMPRO_VIDEOMATE_E650F: |
771 | case CX23885_BOARD_COMPRO_VIDEOMATE_E800: | 801 | case CX23885_BOARD_COMPRO_VIDEOMATE_E800: |
802 | case CX23885_BOARD_LEADTEK_WINFAST_PXTV1200: | ||
772 | /* GPIO-2 xc3028 tuner reset */ | 803 | /* GPIO-2 xc3028 tuner reset */ |
773 | 804 | ||
774 | /* The following GPIO's are on the internal AVCore (cx25840) */ | 805 | /* The following GPIO's are on the internal AVCore (cx25840) */ |
@@ -1076,6 +1107,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) | |||
1076 | case CX23885_BOARD_MYGICA_X8506: | 1107 | case CX23885_BOARD_MYGICA_X8506: |
1077 | case CX23885_BOARD_MAGICPRO_PROHDTVE2: | 1108 | case CX23885_BOARD_MAGICPRO_PROHDTVE2: |
1078 | case CX23885_BOARD_HAUPPAUGE_HVR1290: | 1109 | case CX23885_BOARD_HAUPPAUGE_HVR1290: |
1110 | case CX23885_BOARD_LEADTEK_WINFAST_PXTV1200: | ||
1079 | dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, | 1111 | dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, |
1080 | &dev->i2c_bus[2].i2c_adap, | 1112 | &dev->i2c_bus[2].i2c_adap, |
1081 | "cx25840", "cx25840", 0x88 >> 1, NULL); | 1113 | "cx25840", "cx25840", 0x88 >> 1, NULL); |
diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index e45d2df08138..939079d7bbb9 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c | |||
@@ -542,6 +542,9 @@ static struct atbm8830_config mygica_x8558pro_atbm8830_cfg1 = { | |||
542 | .osc_clk_freq = 30400, /* in kHz */ | 542 | .osc_clk_freq = 30400, /* in kHz */ |
543 | .if_freq = 0, /* zero IF */ | 543 | .if_freq = 0, /* zero IF */ |
544 | .zif_swap_iq = 1, | 544 | .zif_swap_iq = 1, |
545 | .agc_min = 0x2E, | ||
546 | .agc_max = 0xFF, | ||
547 | .agc_hold_loop = 0, | ||
545 | }; | 548 | }; |
546 | 549 | ||
547 | static struct max2165_config mygic_x8558pro_max2165_cfg1 = { | 550 | static struct max2165_config mygic_x8558pro_max2165_cfg1 = { |
@@ -558,6 +561,9 @@ static struct atbm8830_config mygica_x8558pro_atbm8830_cfg2 = { | |||
558 | .osc_clk_freq = 30400, /* in kHz */ | 561 | .osc_clk_freq = 30400, /* in kHz */ |
559 | .if_freq = 0, /* zero IF */ | 562 | .if_freq = 0, /* zero IF */ |
560 | .zif_swap_iq = 1, | 563 | .zif_swap_iq = 1, |
564 | .agc_min = 0x2E, | ||
565 | .agc_max = 0xFF, | ||
566 | .agc_hold_loop = 0, | ||
561 | }; | 567 | }; |
562 | 568 | ||
563 | static struct max2165_config mygic_x8558pro_max2165_cfg2 = { | 569 | static struct max2165_config mygic_x8558pro_max2165_cfg2 = { |
@@ -994,15 +1000,8 @@ static int dvb_register(struct cx23885_tsport *port) | |||
994 | netup_get_card_info(&dev->i2c_bus[0].i2c_adap, &cinfo); | 1000 | netup_get_card_info(&dev->i2c_bus[0].i2c_adap, &cinfo); |
995 | memcpy(port->frontends.adapter.proposed_mac, | 1001 | memcpy(port->frontends.adapter.proposed_mac, |
996 | cinfo.port[port->nr - 1].mac, 6); | 1002 | cinfo.port[port->nr - 1].mac, 6); |
997 | printk(KERN_INFO "NetUP Dual DVB-S2 CI card port%d MAC=" | 1003 | printk(KERN_INFO "NetUP Dual DVB-S2 CI card port%d MAC=%pM\n", |
998 | "%02X:%02X:%02X:%02X:%02X:%02X\n", | 1004 | port->nr, port->frontends.adapter.proposed_mac); |
999 | port->nr, | ||
1000 | port->frontends.adapter.proposed_mac[0], | ||
1001 | port->frontends.adapter.proposed_mac[1], | ||
1002 | port->frontends.adapter.proposed_mac[2], | ||
1003 | port->frontends.adapter.proposed_mac[3], | ||
1004 | port->frontends.adapter.proposed_mac[4], | ||
1005 | port->frontends.adapter.proposed_mac[5]); | ||
1006 | 1005 | ||
1007 | netup_ci_init(port); | 1006 | netup_ci_init(port); |
1008 | break; | 1007 | break; |
diff --git a/drivers/media/video/cx23885/cx23885-input.c b/drivers/media/video/cx23885/cx23885-input.c index 768eec92ccf9..9c6620f86dca 100644 --- a/drivers/media/video/cx23885/cx23885-input.c +++ b/drivers/media/video/cx23885/cx23885-input.c | |||
@@ -397,7 +397,7 @@ int cx23885_input_init(struct cx23885_dev *dev) | |||
397 | dev->ir_input = ir; | 397 | dev->ir_input = ir; |
398 | cx23885_input_ir_start(dev); | 398 | cx23885_input_ir_start(dev); |
399 | 399 | ||
400 | ret = ir_input_register(ir->dev, ir_codes); | 400 | ret = ir_input_register(ir->dev, ir_codes, NULL); |
401 | if (ret) | 401 | if (ret) |
402 | goto err_out_stop; | 402 | goto err_out_stop; |
403 | 403 | ||
diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c index 8934d61cf660..2d3ac8b83dc3 100644 --- a/drivers/media/video/cx23885/cx23885-video.c +++ b/drivers/media/video/cx23885/cx23885-video.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <media/v4l2-common.h> | 36 | #include <media/v4l2-common.h> |
37 | #include <media/v4l2-ioctl.h> | 37 | #include <media/v4l2-ioctl.h> |
38 | #include "cx23885-ioctl.h" | 38 | #include "cx23885-ioctl.h" |
39 | #include "tuner-xc2028.h" | ||
39 | 40 | ||
40 | MODULE_DESCRIPTION("v4l2 driver module for cx23885 based TV cards"); | 41 | MODULE_DESCRIPTION("v4l2 driver module for cx23885 based TV cards"); |
41 | MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>"); | 42 | MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>"); |
@@ -1505,6 +1506,18 @@ int cx23885_video_register(struct cx23885_dev *dev) | |||
1505 | tun_setup.tuner_callback = cx23885_tuner_callback; | 1506 | tun_setup.tuner_callback = cx23885_tuner_callback; |
1506 | 1507 | ||
1507 | v4l2_subdev_call(sd, tuner, s_type_addr, &tun_setup); | 1508 | v4l2_subdev_call(sd, tuner, s_type_addr, &tun_setup); |
1509 | |||
1510 | if (dev->board == CX23885_BOARD_LEADTEK_WINFAST_PXTV1200) { | ||
1511 | struct xc2028_ctrl ctrl = { | ||
1512 | .fname = XC2028_DEFAULT_FIRMWARE, | ||
1513 | .max_len = 64 | ||
1514 | }; | ||
1515 | struct v4l2_priv_tun_config cfg = { | ||
1516 | .tuner = dev->tuner_type, | ||
1517 | .priv = &ctrl | ||
1518 | }; | ||
1519 | v4l2_subdev_call(sd, tuner, s_config, &cfg); | ||
1520 | } | ||
1508 | } | 1521 | } |
1509 | } | 1522 | } |
1510 | 1523 | ||
diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index 08b3f6b136a0..0e3a98d243c5 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h | |||
@@ -81,6 +81,7 @@ | |||
81 | #define CX23885_BOARD_COMPRO_VIDEOMATE_E800 25 | 81 | #define CX23885_BOARD_COMPRO_VIDEOMATE_E800 25 |
82 | #define CX23885_BOARD_HAUPPAUGE_HVR1290 26 | 82 | #define CX23885_BOARD_HAUPPAUGE_HVR1290 26 |
83 | #define CX23885_BOARD_MYGICA_X8558PRO 27 | 83 | #define CX23885_BOARD_MYGICA_X8558PRO 27 |
84 | #define CX23885_BOARD_LEADTEK_WINFAST_PXTV1200 28 | ||
84 | 85 | ||
85 | #define GPIO_0 0x00000001 | 86 | #define GPIO_0 0x00000001 |
86 | #define GPIO_1 0x00000002 | 87 | #define GPIO_1 0x00000002 |
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 385ecd58f1c0..f2461cd3de5a 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c | |||
@@ -734,10 +734,8 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp | |||
734 | v4l_dbg(1, cx25840_debug, client, "vid_input 0x%x\n", | 734 | v4l_dbg(1, cx25840_debug, client, "vid_input 0x%x\n", |
735 | vid_input); | 735 | vid_input); |
736 | reg = vid_input & 0xff; | 736 | reg = vid_input & 0xff; |
737 | if ((vid_input & CX25840_SVIDEO_ON) == CX25840_SVIDEO_ON) | 737 | is_composite = !is_component && |
738 | is_composite = 0; | 738 | ((vid_input & CX25840_SVIDEO_ON) != CX25840_SVIDEO_ON); |
739 | else if ((vid_input & CX25840_COMPONENT_ON) == 0) | ||
740 | is_composite = 1; | ||
741 | 739 | ||
742 | v4l_dbg(1, cx25840_debug, client, "mux cfg 0x%x comp=%d\n", | 740 | v4l_dbg(1, cx25840_debug, client, "mux cfg 0x%x comp=%d\n", |
743 | reg, is_composite); | 741 | reg, is_composite); |
@@ -1347,30 +1345,59 @@ static int cx25840_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register * | |||
1347 | } | 1345 | } |
1348 | #endif | 1346 | #endif |
1349 | 1347 | ||
1348 | static int cx25840_s_audio_stream(struct v4l2_subdev *sd, int enable) | ||
1349 | { | ||
1350 | struct cx25840_state *state = to_state(sd); | ||
1351 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
1352 | u8 v; | ||
1353 | |||
1354 | if (is_cx2583x(state) || is_cx2388x(state) || is_cx231xx(state)) | ||
1355 | return 0; | ||
1356 | |||
1357 | v4l_dbg(1, cx25840_debug, client, "%s audio output\n", | ||
1358 | enable ? "enable" : "disable"); | ||
1359 | |||
1360 | if (enable) { | ||
1361 | v = cx25840_read(client, 0x115) | 0x80; | ||
1362 | cx25840_write(client, 0x115, v); | ||
1363 | v = cx25840_read(client, 0x116) | 0x03; | ||
1364 | cx25840_write(client, 0x116, v); | ||
1365 | } else { | ||
1366 | v = cx25840_read(client, 0x115) & ~(0x80); | ||
1367 | cx25840_write(client, 0x115, v); | ||
1368 | v = cx25840_read(client, 0x116) & ~(0x03); | ||
1369 | cx25840_write(client, 0x116, v); | ||
1370 | } | ||
1371 | return 0; | ||
1372 | } | ||
1373 | |||
1350 | static int cx25840_s_stream(struct v4l2_subdev *sd, int enable) | 1374 | static int cx25840_s_stream(struct v4l2_subdev *sd, int enable) |
1351 | { | 1375 | { |
1352 | struct cx25840_state *state = to_state(sd); | 1376 | struct cx25840_state *state = to_state(sd); |
1353 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 1377 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
1378 | u8 v; | ||
1354 | 1379 | ||
1355 | v4l_dbg(1, cx25840_debug, client, "%s output\n", | 1380 | v4l_dbg(1, cx25840_debug, client, "%s video output\n", |
1356 | enable ? "enable" : "disable"); | 1381 | enable ? "enable" : "disable"); |
1357 | if (enable) { | 1382 | if (enable) { |
1358 | if (is_cx2388x(state) || is_cx231xx(state)) { | 1383 | if (is_cx2388x(state) || is_cx231xx(state)) { |
1359 | u8 v = (cx25840_read(client, 0x421) | 0x0b); | 1384 | v = cx25840_read(client, 0x421) | 0x0b; |
1360 | cx25840_write(client, 0x421, v); | 1385 | cx25840_write(client, 0x421, v); |
1361 | } else { | 1386 | } else { |
1362 | cx25840_write(client, 0x115, | 1387 | v = cx25840_read(client, 0x115) | 0x0c; |
1363 | is_cx2583x(state) ? 0x0c : 0x8c); | 1388 | cx25840_write(client, 0x115, v); |
1364 | cx25840_write(client, 0x116, | 1389 | v = cx25840_read(client, 0x116) | 0x04; |
1365 | is_cx2583x(state) ? 0x04 : 0x07); | 1390 | cx25840_write(client, 0x116, v); |
1366 | } | 1391 | } |
1367 | } else { | 1392 | } else { |
1368 | if (is_cx2388x(state) || is_cx231xx(state)) { | 1393 | if (is_cx2388x(state) || is_cx231xx(state)) { |
1369 | u8 v = cx25840_read(client, 0x421) & ~(0x0b); | 1394 | v = cx25840_read(client, 0x421) & ~(0x0b); |
1370 | cx25840_write(client, 0x421, v); | 1395 | cx25840_write(client, 0x421, v); |
1371 | } else { | 1396 | } else { |
1372 | cx25840_write(client, 0x115, 0x00); | 1397 | v = cx25840_read(client, 0x115) & ~(0x0c); |
1373 | cx25840_write(client, 0x116, 0x00); | 1398 | cx25840_write(client, 0x115, v); |
1399 | v = cx25840_read(client, 0x116) & ~(0x04); | ||
1400 | cx25840_write(client, 0x116, v); | ||
1374 | } | 1401 | } |
1375 | } | 1402 | } |
1376 | return 0; | 1403 | return 0; |
@@ -1601,6 +1628,7 @@ static const struct v4l2_subdev_tuner_ops cx25840_tuner_ops = { | |||
1601 | static const struct v4l2_subdev_audio_ops cx25840_audio_ops = { | 1628 | static const struct v4l2_subdev_audio_ops cx25840_audio_ops = { |
1602 | .s_clock_freq = cx25840_s_clock_freq, | 1629 | .s_clock_freq = cx25840_s_clock_freq, |
1603 | .s_routing = cx25840_s_audio_routing, | 1630 | .s_routing = cx25840_s_audio_routing, |
1631 | .s_stream = cx25840_s_audio_stream, | ||
1604 | }; | 1632 | }; |
1605 | 1633 | ||
1606 | static const struct v4l2_subdev_video_ops cx25840_video_ops = { | 1634 | static const struct v4l2_subdev_video_ops cx25840_video_ops = { |
diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c index 5a67445dd6ed..64b350df78e3 100644 --- a/drivers/media/video/cx88/cx88-alsa.c +++ b/drivers/media/video/cx88/cx88-alsa.c | |||
@@ -583,16 +583,18 @@ static int snd_cx88_volume_put(struct snd_kcontrol *kcontrol, | |||
583 | { | 583 | { |
584 | snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); | 584 | snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); |
585 | struct cx88_core *core=chip->core; | 585 | struct cx88_core *core=chip->core; |
586 | int v, b; | 586 | int left, right, v, b; |
587 | int changed = 0; | 587 | int changed = 0; |
588 | u32 old; | 588 | u32 old; |
589 | 589 | ||
590 | b = value->value.integer.value[1] - value->value.integer.value[0]; | 590 | left = value->value.integer.value[0] & 0x3f; |
591 | right = value->value.integer.value[1] & 0x3f; | ||
592 | b = right - left; | ||
591 | if (b < 0) { | 593 | if (b < 0) { |
592 | v = 0x3f - value->value.integer.value[0]; | 594 | v = 0x3f - left; |
593 | b = (-b) | 0x40; | 595 | b = (-b) | 0x40; |
594 | } else { | 596 | } else { |
595 | v = 0x3f - value->value.integer.value[1]; | 597 | v = 0x3f - right; |
596 | } | 598 | } |
597 | /* Do we really know this will always be called with IRQs on? */ | 599 | /* Do we really know this will always be called with IRQs on? */ |
598 | spin_lock_irq(&chip->reg_lock); | 600 | spin_lock_irq(&chip->reg_lock); |
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index d844f2aaa01d..eaf0ee7de832 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c | |||
@@ -1466,6 +1466,18 @@ static const struct cx88_board cx88_boards[] = { | |||
1466 | .audioroute = 8, | 1466 | .audioroute = 8, |
1467 | }, | 1467 | }, |
1468 | }, | 1468 | }, |
1469 | [CX88_BOARD_SAMSUNG_SMT_7020] = { | ||
1470 | .name = "Samsung SMT 7020 DVB-S", | ||
1471 | .tuner_type = TUNER_ABSENT, | ||
1472 | .radio_type = UNSET, | ||
1473 | .tuner_addr = ADDR_UNSET, | ||
1474 | .radio_addr = ADDR_UNSET, | ||
1475 | .input = { { | ||
1476 | .type = CX88_VMUX_DVB, | ||
1477 | .vmux = 0, | ||
1478 | } }, | ||
1479 | .mpeg = CX88_MPEG_DVB, | ||
1480 | }, | ||
1469 | [CX88_BOARD_ADSTECH_PTV_390] = { | 1481 | [CX88_BOARD_ADSTECH_PTV_390] = { |
1470 | .name = "ADS Tech Instant Video PCI", | 1482 | .name = "ADS Tech Instant Video PCI", |
1471 | .tuner_type = TUNER_ABSENT, | 1483 | .tuner_type = TUNER_ABSENT, |
@@ -2355,6 +2367,14 @@ static const struct cx88_subid cx88_subids[] = { | |||
2355 | .subvendor = 0x0070, | 2367 | .subvendor = 0x0070, |
2356 | .subdevice = 0x1404, | 2368 | .subdevice = 0x1404, |
2357 | .card = CX88_BOARD_HAUPPAUGE_HVR3000, | 2369 | .card = CX88_BOARD_HAUPPAUGE_HVR3000, |
2370 | }, { | ||
2371 | .subvendor = 0x18ac, | ||
2372 | .subdevice = 0xdc00, | ||
2373 | .card = CX88_BOARD_SAMSUNG_SMT_7020, | ||
2374 | }, { | ||
2375 | .subvendor = 0x18ac, | ||
2376 | .subdevice = 0xdccd, | ||
2377 | .card = CX88_BOARD_SAMSUNG_SMT_7020, | ||
2358 | },{ | 2378 | },{ |
2359 | .subvendor = 0x1461, | 2379 | .subvendor = 0x1461, |
2360 | .subdevice = 0xc111, /* AverMedia M150-D */ | 2380 | .subdevice = 0xc111, /* AverMedia M150-D */ |
@@ -2633,6 +2653,9 @@ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data) | |||
2633 | case 98559: /* WinTV-HVR1100LP (Video no IR, Retail - Low Profile) */ | 2653 | case 98559: /* WinTV-HVR1100LP (Video no IR, Retail - Low Profile) */ |
2634 | /* known */ | 2654 | /* known */ |
2635 | break; | 2655 | break; |
2656 | case CX88_BOARD_SAMSUNG_SMT_7020: | ||
2657 | cx_set(MO_GP0_IO, 0x008989FF); | ||
2658 | break; | ||
2636 | default: | 2659 | default: |
2637 | warn_printk(core, "warning: unknown hauppauge model #%d\n", | 2660 | warn_printk(core, "warning: unknown hauppauge model #%d\n", |
2638 | tv.model); | 2661 | tv.model); |
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index b14296923250..94ab862f0219 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c | |||
@@ -674,6 +674,194 @@ static int cx8802_alloc_frontends(struct cx8802_dev *dev) | |||
674 | return 0; | 674 | return 0; |
675 | } | 675 | } |
676 | 676 | ||
677 | |||
678 | |||
679 | static u8 samsung_smt_7020_inittab[] = { | ||
680 | 0x01, 0x15, | ||
681 | 0x02, 0x00, | ||
682 | 0x03, 0x00, | ||
683 | 0x04, 0x7D, | ||
684 | 0x05, 0x0F, | ||
685 | 0x06, 0x02, | ||
686 | 0x07, 0x00, | ||
687 | 0x08, 0x60, | ||
688 | |||
689 | 0x0A, 0xC2, | ||
690 | 0x0B, 0x00, | ||
691 | 0x0C, 0x01, | ||
692 | 0x0D, 0x81, | ||
693 | 0x0E, 0x44, | ||
694 | 0x0F, 0x09, | ||
695 | 0x10, 0x3C, | ||
696 | 0x11, 0x84, | ||
697 | 0x12, 0xDA, | ||
698 | 0x13, 0x99, | ||
699 | 0x14, 0x8D, | ||
700 | 0x15, 0xCE, | ||
701 | 0x16, 0xE8, | ||
702 | 0x17, 0x43, | ||
703 | 0x18, 0x1C, | ||
704 | 0x19, 0x1B, | ||
705 | 0x1A, 0x1D, | ||
706 | |||
707 | 0x1C, 0x12, | ||
708 | 0x1D, 0x00, | ||
709 | 0x1E, 0x00, | ||
710 | 0x1F, 0x00, | ||
711 | 0x20, 0x00, | ||
712 | 0x21, 0x00, | ||
713 | 0x22, 0x00, | ||
714 | 0x23, 0x00, | ||
715 | |||
716 | 0x28, 0x02, | ||
717 | 0x29, 0x28, | ||
718 | 0x2A, 0x14, | ||
719 | 0x2B, 0x0F, | ||
720 | 0x2C, 0x09, | ||
721 | 0x2D, 0x05, | ||
722 | |||
723 | 0x31, 0x1F, | ||
724 | 0x32, 0x19, | ||
725 | 0x33, 0xFC, | ||
726 | 0x34, 0x13, | ||
727 | 0xff, 0xff, | ||
728 | }; | ||
729 | |||
730 | |||
731 | static int samsung_smt_7020_tuner_set_params(struct dvb_frontend *fe, | ||
732 | struct dvb_frontend_parameters *params) | ||
733 | { | ||
734 | struct cx8802_dev *dev = fe->dvb->priv; | ||
735 | u8 buf[4]; | ||
736 | u32 div; | ||
737 | struct i2c_msg msg = { | ||
738 | .addr = 0x61, | ||
739 | .flags = 0, | ||
740 | .buf = buf, | ||
741 | .len = sizeof(buf) }; | ||
742 | |||
743 | div = params->frequency / 125; | ||
744 | |||
745 | buf[0] = (div >> 8) & 0x7f; | ||
746 | buf[1] = div & 0xff; | ||
747 | buf[2] = 0x84; /* 0xC4 */ | ||
748 | buf[3] = 0x00; | ||
749 | |||
750 | if (params->frequency < 1500000) | ||
751 | buf[3] |= 0x10; | ||
752 | |||
753 | if (fe->ops.i2c_gate_ctrl) | ||
754 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
755 | |||
756 | if (i2c_transfer(&dev->core->i2c_adap, &msg, 1) != 1) | ||
757 | return -EIO; | ||
758 | |||
759 | return 0; | ||
760 | } | ||
761 | |||
762 | static int samsung_smt_7020_set_tone(struct dvb_frontend *fe, | ||
763 | fe_sec_tone_mode_t tone) | ||
764 | { | ||
765 | struct cx8802_dev *dev = fe->dvb->priv; | ||
766 | struct cx88_core *core = dev->core; | ||
767 | |||
768 | cx_set(MO_GP0_IO, 0x0800); | ||
769 | |||
770 | switch (tone) { | ||
771 | case SEC_TONE_ON: | ||
772 | cx_set(MO_GP0_IO, 0x08); | ||
773 | break; | ||
774 | case SEC_TONE_OFF: | ||
775 | cx_clear(MO_GP0_IO, 0x08); | ||
776 | break; | ||
777 | default: | ||
778 | return -EINVAL; | ||
779 | } | ||
780 | |||
781 | return 0; | ||
782 | } | ||
783 | |||
784 | static int samsung_smt_7020_set_voltage(struct dvb_frontend *fe, | ||
785 | fe_sec_voltage_t voltage) | ||
786 | { | ||
787 | struct cx8802_dev *dev = fe->dvb->priv; | ||
788 | struct cx88_core *core = dev->core; | ||
789 | |||
790 | u8 data; | ||
791 | struct i2c_msg msg = { | ||
792 | .addr = 8, | ||
793 | .flags = 0, | ||
794 | .buf = &data, | ||
795 | .len = sizeof(data) }; | ||
796 | |||
797 | cx_set(MO_GP0_IO, 0x8000); | ||
798 | |||
799 | switch (voltage) { | ||
800 | case SEC_VOLTAGE_OFF: | ||
801 | break; | ||
802 | case SEC_VOLTAGE_13: | ||
803 | data = ISL6421_EN1 | ISL6421_LLC1; | ||
804 | cx_clear(MO_GP0_IO, 0x80); | ||
805 | break; | ||
806 | case SEC_VOLTAGE_18: | ||
807 | data = ISL6421_EN1 | ISL6421_LLC1 | ISL6421_VSEL1; | ||
808 | cx_clear(MO_GP0_IO, 0x80); | ||
809 | break; | ||
810 | default: | ||
811 | return -EINVAL; | ||
812 | }; | ||
813 | |||
814 | return (i2c_transfer(&dev->core->i2c_adap, &msg, 1) == 1) ? 0 : -EIO; | ||
815 | } | ||
816 | |||
817 | static int samsung_smt_7020_stv0299_set_symbol_rate(struct dvb_frontend *fe, | ||
818 | u32 srate, u32 ratio) | ||
819 | { | ||
820 | u8 aclk = 0; | ||
821 | u8 bclk = 0; | ||
822 | |||
823 | if (srate < 1500000) { | ||
824 | aclk = 0xb7; | ||
825 | bclk = 0x47; | ||
826 | } else if (srate < 3000000) { | ||
827 | aclk = 0xb7; | ||
828 | bclk = 0x4b; | ||
829 | } else if (srate < 7000000) { | ||
830 | aclk = 0xb7; | ||
831 | bclk = 0x4f; | ||
832 | } else if (srate < 14000000) { | ||
833 | aclk = 0xb7; | ||
834 | bclk = 0x53; | ||
835 | } else if (srate < 30000000) { | ||
836 | aclk = 0xb6; | ||
837 | bclk = 0x53; | ||
838 | } else if (srate < 45000000) { | ||
839 | aclk = 0xb4; | ||
840 | bclk = 0x51; | ||
841 | } | ||
842 | |||
843 | stv0299_writereg(fe, 0x13, aclk); | ||
844 | stv0299_writereg(fe, 0x14, bclk); | ||
845 | stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff); | ||
846 | stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff); | ||
847 | stv0299_writereg(fe, 0x21, ratio & 0xf0); | ||
848 | |||
849 | return 0; | ||
850 | } | ||
851 | |||
852 | |||
853 | static struct stv0299_config samsung_stv0299_config = { | ||
854 | .demod_address = 0x68, | ||
855 | .inittab = samsung_smt_7020_inittab, | ||
856 | .mclk = 88000000UL, | ||
857 | .invert = 0, | ||
858 | .skip_reinit = 0, | ||
859 | .lock_output = STV0299_LOCKOUTPUT_LK, | ||
860 | .volt13_op0_op1 = STV0299_VOLT13_OP1, | ||
861 | .min_delay_ms = 100, | ||
862 | .set_symbol_rate = samsung_smt_7020_stv0299_set_symbol_rate, | ||
863 | }; | ||
864 | |||
677 | static int dvb_register(struct cx8802_dev *dev) | 865 | static int dvb_register(struct cx8802_dev *dev) |
678 | { | 866 | { |
679 | struct cx88_core *core = dev->core; | 867 | struct cx88_core *core = dev->core; |
@@ -1203,6 +1391,32 @@ static int dvb_register(struct cx8802_dev *dev) | |||
1203 | } | 1391 | } |
1204 | break; | 1392 | break; |
1205 | } | 1393 | } |
1394 | case CX88_BOARD_SAMSUNG_SMT_7020: | ||
1395 | dev->ts_gen_cntrl = 0x08; | ||
1396 | |||
1397 | cx_set(MO_GP0_IO, 0x0101); | ||
1398 | |||
1399 | cx_clear(MO_GP0_IO, 0x01); | ||
1400 | mdelay(100); | ||
1401 | cx_set(MO_GP0_IO, 0x01); | ||
1402 | mdelay(200); | ||
1403 | |||
1404 | fe0->dvb.frontend = dvb_attach(stv0299_attach, | ||
1405 | &samsung_stv0299_config, | ||
1406 | &dev->core->i2c_adap); | ||
1407 | if (fe0->dvb.frontend) { | ||
1408 | fe0->dvb.frontend->ops.tuner_ops.set_params = | ||
1409 | samsung_smt_7020_tuner_set_params; | ||
1410 | fe0->dvb.frontend->tuner_priv = | ||
1411 | &dev->core->i2c_adap; | ||
1412 | fe0->dvb.frontend->ops.set_voltage = | ||
1413 | samsung_smt_7020_set_voltage; | ||
1414 | fe0->dvb.frontend->ops.set_tone = | ||
1415 | samsung_smt_7020_set_tone; | ||
1416 | } | ||
1417 | |||
1418 | break; | ||
1419 | |||
1206 | default: | 1420 | default: |
1207 | printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n", | 1421 | printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n", |
1208 | core->name); | 1422 | core->name); |
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index f9fda18b410c..de180d4d5a21 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c | |||
@@ -192,7 +192,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | |||
192 | struct cx88_IR *ir; | 192 | struct cx88_IR *ir; |
193 | struct input_dev *input_dev; | 193 | struct input_dev *input_dev; |
194 | struct ir_scancode_table *ir_codes = NULL; | 194 | struct ir_scancode_table *ir_codes = NULL; |
195 | int ir_type = IR_TYPE_OTHER; | 195 | u64 ir_type = IR_TYPE_OTHER; |
196 | int err = -ENOMEM; | 196 | int err = -ENOMEM; |
197 | 197 | ||
198 | ir = kzalloc(sizeof(*ir), GFP_KERNEL); | 198 | ir = kzalloc(sizeof(*ir), GFP_KERNEL); |
@@ -383,7 +383,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | |||
383 | cx88_ir_start(core, ir); | 383 | cx88_ir_start(core, ir); |
384 | 384 | ||
385 | /* all done */ | 385 | /* all done */ |
386 | err = ir_input_register(ir->input, ir_codes); | 386 | err = ir_input_register(ir->input, ir_codes, NULL); |
387 | if (err) | 387 | if (err) |
388 | goto err_out_stop; | 388 | goto err_out_stop; |
389 | 389 | ||
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index bb5104893411..338af77f7f01 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/video/cx88/cx88-mpeg.c | |||
@@ -110,6 +110,9 @@ static int cx8802_start_dma(struct cx8802_dev *dev, | |||
110 | case CX88_BOARD_PCHDTV_HD5500: | 110 | case CX88_BOARD_PCHDTV_HD5500: |
111 | cx_write(TS_SOP_STAT, 1<<13); | 111 | cx_write(TS_SOP_STAT, 1<<13); |
112 | break; | 112 | break; |
113 | case CX88_BOARD_SAMSUNG_SMT_7020: | ||
114 | cx_write(TS_SOP_STAT, 0x00); | ||
115 | break; | ||
113 | case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: | 116 | case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: |
114 | case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: | 117 | case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: |
115 | cx_write(MO_PINMUX_IO, 0x88); /* Enable MPEG parallel IO and video signal pins */ | 118 | cx_write(MO_PINMUX_IO, 0x88); /* Enable MPEG parallel IO and video signal pins */ |
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index b1499bf604ea..48b6c04fb497 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h | |||
@@ -239,6 +239,7 @@ extern struct sram_channel cx88_sram_channels[]; | |||
239 | #define CX88_BOARD_WINFAST_DTV1800H 81 | 239 | #define CX88_BOARD_WINFAST_DTV1800H 81 |
240 | #define CX88_BOARD_WINFAST_DTV2000H_J 82 | 240 | #define CX88_BOARD_WINFAST_DTV2000H_J 82 |
241 | #define CX88_BOARD_PROF_7301 83 | 241 | #define CX88_BOARD_PROF_7301 83 |
242 | #define CX88_BOARD_SAMSUNG_SMT_7020 84 | ||
242 | 243 | ||
243 | enum cx88_itype { | 244 | enum cx88_itype { |
244 | CX88_VMUX_COMPOSITE1 = 1, | 245 | CX88_VMUX_COMPOSITE1 = 1, |
diff --git a/drivers/media/video/dabusb.c b/drivers/media/video/dabusb.c index ee43876adb06..9b413a35e048 100644 --- a/drivers/media/video/dabusb.c +++ b/drivers/media/video/dabusb.c | |||
@@ -913,6 +913,8 @@ static void __exit dabusb_cleanup (void) | |||
913 | MODULE_AUTHOR( DRIVER_AUTHOR ); | 913 | MODULE_AUTHOR( DRIVER_AUTHOR ); |
914 | MODULE_DESCRIPTION( DRIVER_DESC ); | 914 | MODULE_DESCRIPTION( DRIVER_DESC ); |
915 | MODULE_LICENSE("GPL"); | 915 | MODULE_LICENSE("GPL"); |
916 | MODULE_FIRMWARE("dabusb/firmware.fw"); | ||
917 | MODULE_FIRMWARE("dabusb/bitstream.bin"); | ||
916 | 918 | ||
917 | module_param(buffers, int, 0); | 919 | module_param(buffers, int, 0); |
918 | MODULE_PARM_DESC (buffers, "Number of buffers (default=256)"); | 920 | MODULE_PARM_DESC (buffers, "Number of buffers (default=256)"); |
diff --git a/drivers/media/video/davinci/Makefile b/drivers/media/video/davinci/Makefile index 1a8b8f3f182e..a37955745aaa 100644 --- a/drivers/media/video/davinci/Makefile +++ b/drivers/media/video/davinci/Makefile | |||
@@ -15,3 +15,4 @@ obj-$(CONFIG_VIDEO_VPSS_SYSTEM) += vpss.o | |||
15 | obj-$(CONFIG_VIDEO_VPFE_CAPTURE) += vpfe_capture.o | 15 | obj-$(CONFIG_VIDEO_VPFE_CAPTURE) += vpfe_capture.o |
16 | obj-$(CONFIG_VIDEO_DM6446_CCDC) += dm644x_ccdc.o | 16 | obj-$(CONFIG_VIDEO_DM6446_CCDC) += dm644x_ccdc.o |
17 | obj-$(CONFIG_VIDEO_DM355_CCDC) += dm355_ccdc.o | 17 | obj-$(CONFIG_VIDEO_DM355_CCDC) += dm355_ccdc.o |
18 | obj-$(CONFIG_VIDEO_ISIF) += isif.o | ||
diff --git a/drivers/media/video/davinci/dm355_ccdc.c b/drivers/media/video/davinci/dm355_ccdc.c index 314390016370..c29ac88ffd78 100644 --- a/drivers/media/video/davinci/dm355_ccdc.c +++ b/drivers/media/video/davinci/dm355_ccdc.c | |||
@@ -37,8 +37,12 @@ | |||
37 | #include <linux/platform_device.h> | 37 | #include <linux/platform_device.h> |
38 | #include <linux/uaccess.h> | 38 | #include <linux/uaccess.h> |
39 | #include <linux/videodev2.h> | 39 | #include <linux/videodev2.h> |
40 | #include <linux/clk.h> | ||
41 | #include <linux/err.h> | ||
42 | |||
40 | #include <media/davinci/dm355_ccdc.h> | 43 | #include <media/davinci/dm355_ccdc.h> |
41 | #include <media/davinci/vpss.h> | 44 | #include <media/davinci/vpss.h> |
45 | |||
42 | #include "dm355_ccdc_regs.h" | 46 | #include "dm355_ccdc_regs.h" |
43 | #include "ccdc_hw_device.h" | 47 | #include "ccdc_hw_device.h" |
44 | 48 | ||
@@ -46,67 +50,75 @@ MODULE_LICENSE("GPL"); | |||
46 | MODULE_DESCRIPTION("CCDC Driver for DM355"); | 50 | MODULE_DESCRIPTION("CCDC Driver for DM355"); |
47 | MODULE_AUTHOR("Texas Instruments"); | 51 | MODULE_AUTHOR("Texas Instruments"); |
48 | 52 | ||
49 | static struct device *dev; | 53 | static struct ccdc_oper_config { |
50 | 54 | struct device *dev; | |
51 | /* Object for CCDC raw mode */ | 55 | /* CCDC interface type */ |
52 | static struct ccdc_params_raw ccdc_hw_params_raw = { | 56 | enum vpfe_hw_if_type if_type; |
53 | .pix_fmt = CCDC_PIXFMT_RAW, | 57 | /* Raw Bayer configuration */ |
54 | .frm_fmt = CCDC_FRMFMT_PROGRESSIVE, | 58 | struct ccdc_params_raw bayer; |
55 | .win = CCDC_WIN_VGA, | 59 | /* YCbCr configuration */ |
56 | .fid_pol = VPFE_PINPOL_POSITIVE, | 60 | struct ccdc_params_ycbcr ycbcr; |
57 | .vd_pol = VPFE_PINPOL_POSITIVE, | 61 | /* Master clock */ |
58 | .hd_pol = VPFE_PINPOL_POSITIVE, | 62 | struct clk *mclk; |
59 | .gain = { | 63 | /* slave clock */ |
60 | .r_ye = 256, | 64 | struct clk *sclk; |
61 | .gb_g = 256, | 65 | /* ccdc base address */ |
62 | .gr_cy = 256, | 66 | void __iomem *base_addr; |
63 | .b_mg = 256 | 67 | } ccdc_cfg = { |
64 | }, | 68 | /* Raw configurations */ |
65 | .config_params = { | 69 | .bayer = { |
66 | .datasft = 2, | 70 | .pix_fmt = CCDC_PIXFMT_RAW, |
67 | .data_sz = CCDC_DATA_10BITS, | 71 | .frm_fmt = CCDC_FRMFMT_PROGRESSIVE, |
68 | .mfilt1 = CCDC_NO_MEDIAN_FILTER1, | 72 | .win = CCDC_WIN_VGA, |
69 | .mfilt2 = CCDC_NO_MEDIAN_FILTER2, | 73 | .fid_pol = VPFE_PINPOL_POSITIVE, |
70 | .alaw = { | 74 | .vd_pol = VPFE_PINPOL_POSITIVE, |
71 | .gama_wd = 2, | 75 | .hd_pol = VPFE_PINPOL_POSITIVE, |
76 | .gain = { | ||
77 | .r_ye = 256, | ||
78 | .gb_g = 256, | ||
79 | .gr_cy = 256, | ||
80 | .b_mg = 256 | ||
72 | }, | 81 | }, |
73 | .blk_clamp = { | 82 | .config_params = { |
74 | .sample_pixel = 1, | 83 | .datasft = 2, |
75 | .dc_sub = 25 | 84 | .mfilt1 = CCDC_NO_MEDIAN_FILTER1, |
76 | }, | 85 | .mfilt2 = CCDC_NO_MEDIAN_FILTER2, |
77 | .col_pat_field0 = { | 86 | .alaw = { |
78 | .olop = CCDC_GREEN_BLUE, | 87 | .gama_wd = 2, |
79 | .olep = CCDC_BLUE, | 88 | }, |
80 | .elop = CCDC_RED, | 89 | .blk_clamp = { |
81 | .elep = CCDC_GREEN_RED | 90 | .sample_pixel = 1, |
82 | }, | 91 | .dc_sub = 25 |
83 | .col_pat_field1 = { | 92 | }, |
84 | .olop = CCDC_GREEN_BLUE, | 93 | .col_pat_field0 = { |
85 | .olep = CCDC_BLUE, | 94 | .olop = CCDC_GREEN_BLUE, |
86 | .elop = CCDC_RED, | 95 | .olep = CCDC_BLUE, |
87 | .elep = CCDC_GREEN_RED | 96 | .elop = CCDC_RED, |
97 | .elep = CCDC_GREEN_RED | ||
98 | }, | ||
99 | .col_pat_field1 = { | ||
100 | .olop = CCDC_GREEN_BLUE, | ||
101 | .olep = CCDC_BLUE, | ||
102 | .elop = CCDC_RED, | ||
103 | .elep = CCDC_GREEN_RED | ||
104 | }, | ||
88 | }, | 105 | }, |
89 | }, | 106 | }, |
107 | /* YCbCr configuration */ | ||
108 | .ycbcr = { | ||
109 | .win = CCDC_WIN_PAL, | ||
110 | .pix_fmt = CCDC_PIXFMT_YCBCR_8BIT, | ||
111 | .frm_fmt = CCDC_FRMFMT_INTERLACED, | ||
112 | .fid_pol = VPFE_PINPOL_POSITIVE, | ||
113 | .vd_pol = VPFE_PINPOL_POSITIVE, | ||
114 | .hd_pol = VPFE_PINPOL_POSITIVE, | ||
115 | .bt656_enable = 1, | ||
116 | .pix_order = CCDC_PIXORDER_CBYCRY, | ||
117 | .buf_type = CCDC_BUFTYPE_FLD_INTERLEAVED | ||
118 | }, | ||
90 | }; | 119 | }; |
91 | 120 | ||
92 | 121 | ||
93 | /* Object for CCDC ycbcr mode */ | ||
94 | static struct ccdc_params_ycbcr ccdc_hw_params_ycbcr = { | ||
95 | .win = CCDC_WIN_PAL, | ||
96 | .pix_fmt = CCDC_PIXFMT_YCBCR_8BIT, | ||
97 | .frm_fmt = CCDC_FRMFMT_INTERLACED, | ||
98 | .fid_pol = VPFE_PINPOL_POSITIVE, | ||
99 | .vd_pol = VPFE_PINPOL_POSITIVE, | ||
100 | .hd_pol = VPFE_PINPOL_POSITIVE, | ||
101 | .bt656_enable = 1, | ||
102 | .pix_order = CCDC_PIXORDER_CBYCRY, | ||
103 | .buf_type = CCDC_BUFTYPE_FLD_INTERLEAVED | ||
104 | }; | ||
105 | |||
106 | static enum vpfe_hw_if_type ccdc_if_type; | ||
107 | static void *__iomem ccdc_base_addr; | ||
108 | static int ccdc_addr_size; | ||
109 | |||
110 | /* Raw Bayer formats */ | 122 | /* Raw Bayer formats */ |
111 | static u32 ccdc_raw_bayer_pix_formats[] = | 123 | static u32 ccdc_raw_bayer_pix_formats[] = |
112 | {V4L2_PIX_FMT_SBGGR8, V4L2_PIX_FMT_SBGGR16}; | 124 | {V4L2_PIX_FMT_SBGGR8, V4L2_PIX_FMT_SBGGR16}; |
@@ -118,18 +130,12 @@ static u32 ccdc_raw_yuv_pix_formats[] = | |||
118 | /* register access routines */ | 130 | /* register access routines */ |
119 | static inline u32 regr(u32 offset) | 131 | static inline u32 regr(u32 offset) |
120 | { | 132 | { |
121 | return __raw_readl(ccdc_base_addr + offset); | 133 | return __raw_readl(ccdc_cfg.base_addr + offset); |
122 | } | 134 | } |
123 | 135 | ||
124 | static inline void regw(u32 val, u32 offset) | 136 | static inline void regw(u32 val, u32 offset) |
125 | { | 137 | { |
126 | __raw_writel(val, ccdc_base_addr + offset); | 138 | __raw_writel(val, ccdc_cfg.base_addr + offset); |
127 | } | ||
128 | |||
129 | static void ccdc_set_ccdc_base(void *addr, int size) | ||
130 | { | ||
131 | ccdc_base_addr = addr; | ||
132 | ccdc_addr_size = size; | ||
133 | } | 139 | } |
134 | 140 | ||
135 | static void ccdc_enable(int en) | 141 | static void ccdc_enable(int en) |
@@ -153,12 +159,12 @@ static void ccdc_enable_output_to_sdram(int en) | |||
153 | static void ccdc_config_gain_offset(void) | 159 | static void ccdc_config_gain_offset(void) |
154 | { | 160 | { |
155 | /* configure gain */ | 161 | /* configure gain */ |
156 | regw(ccdc_hw_params_raw.gain.r_ye, RYEGAIN); | 162 | regw(ccdc_cfg.bayer.gain.r_ye, RYEGAIN); |
157 | regw(ccdc_hw_params_raw.gain.gr_cy, GRCYGAIN); | 163 | regw(ccdc_cfg.bayer.gain.gr_cy, GRCYGAIN); |
158 | regw(ccdc_hw_params_raw.gain.gb_g, GBGGAIN); | 164 | regw(ccdc_cfg.bayer.gain.gb_g, GBGGAIN); |
159 | regw(ccdc_hw_params_raw.gain.b_mg, BMGGAIN); | 165 | regw(ccdc_cfg.bayer.gain.b_mg, BMGGAIN); |
160 | /* configure offset */ | 166 | /* configure offset */ |
161 | regw(ccdc_hw_params_raw.ccdc_offset, OFFSET); | 167 | regw(ccdc_cfg.bayer.ccdc_offset, OFFSET); |
162 | } | 168 | } |
163 | 169 | ||
164 | /* | 170 | /* |
@@ -169,7 +175,7 @@ static int ccdc_restore_defaults(void) | |||
169 | { | 175 | { |
170 | int i; | 176 | int i; |
171 | 177 | ||
172 | dev_dbg(dev, "\nstarting ccdc_restore_defaults..."); | 178 | dev_dbg(ccdc_cfg.dev, "\nstarting ccdc_restore_defaults..."); |
173 | /* set all registers to zero */ | 179 | /* set all registers to zero */ |
174 | for (i = 0; i <= CCDC_REG_LAST; i += 4) | 180 | for (i = 0; i <= CCDC_REG_LAST; i += 4) |
175 | regw(0, i); | 181 | regw(0, i); |
@@ -180,30 +186,29 @@ static int ccdc_restore_defaults(void) | |||
180 | regw(CULH_DEFAULT, CULH); | 186 | regw(CULH_DEFAULT, CULH); |
181 | regw(CULV_DEFAULT, CULV); | 187 | regw(CULV_DEFAULT, CULV); |
182 | /* Set default Gain and Offset */ | 188 | /* Set default Gain and Offset */ |
183 | ccdc_hw_params_raw.gain.r_ye = GAIN_DEFAULT; | 189 | ccdc_cfg.bayer.gain.r_ye = GAIN_DEFAULT; |
184 | ccdc_hw_params_raw.gain.gb_g = GAIN_DEFAULT; | 190 | ccdc_cfg.bayer.gain.gb_g = GAIN_DEFAULT; |
185 | ccdc_hw_params_raw.gain.gr_cy = GAIN_DEFAULT; | 191 | ccdc_cfg.bayer.gain.gr_cy = GAIN_DEFAULT; |
186 | ccdc_hw_params_raw.gain.b_mg = GAIN_DEFAULT; | 192 | ccdc_cfg.bayer.gain.b_mg = GAIN_DEFAULT; |
187 | ccdc_config_gain_offset(); | 193 | ccdc_config_gain_offset(); |
188 | regw(OUTCLIP_DEFAULT, OUTCLIP); | 194 | regw(OUTCLIP_DEFAULT, OUTCLIP); |
189 | regw(LSCCFG2_DEFAULT, LSCCFG2); | 195 | regw(LSCCFG2_DEFAULT, LSCCFG2); |
190 | /* select ccdc input */ | 196 | /* select ccdc input */ |
191 | if (vpss_select_ccdc_source(VPSS_CCDCIN)) { | 197 | if (vpss_select_ccdc_source(VPSS_CCDCIN)) { |
192 | dev_dbg(dev, "\ncouldn't select ccdc input source"); | 198 | dev_dbg(ccdc_cfg.dev, "\ncouldn't select ccdc input source"); |
193 | return -EFAULT; | 199 | return -EFAULT; |
194 | } | 200 | } |
195 | /* select ccdc clock */ | 201 | /* select ccdc clock */ |
196 | if (vpss_enable_clock(VPSS_CCDC_CLOCK, 1) < 0) { | 202 | if (vpss_enable_clock(VPSS_CCDC_CLOCK, 1) < 0) { |
197 | dev_dbg(dev, "\ncouldn't enable ccdc clock"); | 203 | dev_dbg(ccdc_cfg.dev, "\ncouldn't enable ccdc clock"); |
198 | return -EFAULT; | 204 | return -EFAULT; |
199 | } | 205 | } |
200 | dev_dbg(dev, "\nEnd of ccdc_restore_defaults..."); | 206 | dev_dbg(ccdc_cfg.dev, "\nEnd of ccdc_restore_defaults..."); |
201 | return 0; | 207 | return 0; |
202 | } | 208 | } |
203 | 209 | ||
204 | static int ccdc_open(struct device *device) | 210 | static int ccdc_open(struct device *device) |
205 | { | 211 | { |
206 | dev = device; | ||
207 | return ccdc_restore_defaults(); | 212 | return ccdc_restore_defaults(); |
208 | } | 213 | } |
209 | 214 | ||
@@ -226,7 +231,7 @@ static void ccdc_setwin(struct v4l2_rect *image_win, | |||
226 | int vert_start, vert_nr_lines; | 231 | int vert_start, vert_nr_lines; |
227 | int mid_img = 0; | 232 | int mid_img = 0; |
228 | 233 | ||
229 | dev_dbg(dev, "\nStarting ccdc_setwin..."); | 234 | dev_dbg(ccdc_cfg.dev, "\nStarting ccdc_setwin..."); |
230 | 235 | ||
231 | /* | 236 | /* |
232 | * ppc - per pixel count. indicates how many pixels per cell | 237 | * ppc - per pixel count. indicates how many pixels per cell |
@@ -260,45 +265,46 @@ static void ccdc_setwin(struct v4l2_rect *image_win, | |||
260 | regw(vert_start & CCDC_START_VER_ONE_MASK, SLV0); | 265 | regw(vert_start & CCDC_START_VER_ONE_MASK, SLV0); |
261 | regw(vert_start & CCDC_START_VER_TWO_MASK, SLV1); | 266 | regw(vert_start & CCDC_START_VER_TWO_MASK, SLV1); |
262 | regw(vert_nr_lines & CCDC_NUM_LINES_VER, NLV); | 267 | regw(vert_nr_lines & CCDC_NUM_LINES_VER, NLV); |
263 | dev_dbg(dev, "\nEnd of ccdc_setwin..."); | 268 | dev_dbg(ccdc_cfg.dev, "\nEnd of ccdc_setwin..."); |
264 | } | 269 | } |
265 | 270 | ||
266 | static int validate_ccdc_param(struct ccdc_config_params_raw *ccdcparam) | 271 | static int validate_ccdc_param(struct ccdc_config_params_raw *ccdcparam) |
267 | { | 272 | { |
268 | if (ccdcparam->datasft < CCDC_DATA_NO_SHIFT || | 273 | if (ccdcparam->datasft < CCDC_DATA_NO_SHIFT || |
269 | ccdcparam->datasft > CCDC_DATA_SHIFT_6BIT) { | 274 | ccdcparam->datasft > CCDC_DATA_SHIFT_6BIT) { |
270 | dev_dbg(dev, "Invalid value of data shift\n"); | 275 | dev_dbg(ccdc_cfg.dev, "Invalid value of data shift\n"); |
271 | return -EINVAL; | 276 | return -EINVAL; |
272 | } | 277 | } |
273 | 278 | ||
274 | if (ccdcparam->mfilt1 < CCDC_NO_MEDIAN_FILTER1 || | 279 | if (ccdcparam->mfilt1 < CCDC_NO_MEDIAN_FILTER1 || |
275 | ccdcparam->mfilt1 > CCDC_MEDIAN_FILTER1) { | 280 | ccdcparam->mfilt1 > CCDC_MEDIAN_FILTER1) { |
276 | dev_dbg(dev, "Invalid value of median filter1\n"); | 281 | dev_dbg(ccdc_cfg.dev, "Invalid value of median filter1\n"); |
277 | return -EINVAL; | 282 | return -EINVAL; |
278 | } | 283 | } |
279 | 284 | ||
280 | if (ccdcparam->mfilt2 < CCDC_NO_MEDIAN_FILTER2 || | 285 | if (ccdcparam->mfilt2 < CCDC_NO_MEDIAN_FILTER2 || |
281 | ccdcparam->mfilt2 > CCDC_MEDIAN_FILTER2) { | 286 | ccdcparam->mfilt2 > CCDC_MEDIAN_FILTER2) { |
282 | dev_dbg(dev, "Invalid value of median filter2\n"); | 287 | dev_dbg(ccdc_cfg.dev, "Invalid value of median filter2\n"); |
283 | return -EINVAL; | 288 | return -EINVAL; |
284 | } | 289 | } |
285 | 290 | ||
286 | if ((ccdcparam->med_filt_thres < 0) || | 291 | if ((ccdcparam->med_filt_thres < 0) || |
287 | (ccdcparam->med_filt_thres > CCDC_MED_FILT_THRESH)) { | 292 | (ccdcparam->med_filt_thres > CCDC_MED_FILT_THRESH)) { |
288 | dev_dbg(dev, "Invalid value of median filter threshold\n"); | 293 | dev_dbg(ccdc_cfg.dev, |
294 | "Invalid value of median filter thresold\n"); | ||
289 | return -EINVAL; | 295 | return -EINVAL; |
290 | } | 296 | } |
291 | 297 | ||
292 | if (ccdcparam->data_sz < CCDC_DATA_16BITS || | 298 | if (ccdcparam->data_sz < CCDC_DATA_16BITS || |
293 | ccdcparam->data_sz > CCDC_DATA_8BITS) { | 299 | ccdcparam->data_sz > CCDC_DATA_8BITS) { |
294 | dev_dbg(dev, "Invalid value of data size\n"); | 300 | dev_dbg(ccdc_cfg.dev, "Invalid value of data size\n"); |
295 | return -EINVAL; | 301 | return -EINVAL; |
296 | } | 302 | } |
297 | 303 | ||
298 | if (ccdcparam->alaw.enable) { | 304 | if (ccdcparam->alaw.enable) { |
299 | if (ccdcparam->alaw.gama_wd < CCDC_GAMMA_BITS_13_4 || | 305 | if (ccdcparam->alaw.gama_wd < CCDC_GAMMA_BITS_13_4 || |
300 | ccdcparam->alaw.gama_wd > CCDC_GAMMA_BITS_09_0) { | 306 | ccdcparam->alaw.gama_wd > CCDC_GAMMA_BITS_09_0) { |
301 | dev_dbg(dev, "Invalid value of ALAW\n"); | 307 | dev_dbg(ccdc_cfg.dev, "Invalid value of ALAW\n"); |
302 | return -EINVAL; | 308 | return -EINVAL; |
303 | } | 309 | } |
304 | } | 310 | } |
@@ -306,12 +312,14 @@ static int validate_ccdc_param(struct ccdc_config_params_raw *ccdcparam) | |||
306 | if (ccdcparam->blk_clamp.b_clamp_enable) { | 312 | if (ccdcparam->blk_clamp.b_clamp_enable) { |
307 | if (ccdcparam->blk_clamp.sample_pixel < CCDC_SAMPLE_1PIXELS || | 313 | if (ccdcparam->blk_clamp.sample_pixel < CCDC_SAMPLE_1PIXELS || |
308 | ccdcparam->blk_clamp.sample_pixel > CCDC_SAMPLE_16PIXELS) { | 314 | ccdcparam->blk_clamp.sample_pixel > CCDC_SAMPLE_16PIXELS) { |
309 | dev_dbg(dev, "Invalid value of sample pixel\n"); | 315 | dev_dbg(ccdc_cfg.dev, |
316 | "Invalid value of sample pixel\n"); | ||
310 | return -EINVAL; | 317 | return -EINVAL; |
311 | } | 318 | } |
312 | if (ccdcparam->blk_clamp.sample_ln < CCDC_SAMPLE_1LINES || | 319 | if (ccdcparam->blk_clamp.sample_ln < CCDC_SAMPLE_1LINES || |
313 | ccdcparam->blk_clamp.sample_ln > CCDC_SAMPLE_16LINES) { | 320 | ccdcparam->blk_clamp.sample_ln > CCDC_SAMPLE_16LINES) { |
314 | dev_dbg(dev, "Invalid value of sample lines\n"); | 321 | dev_dbg(ccdc_cfg.dev, |
322 | "Invalid value of sample lines\n"); | ||
315 | return -EINVAL; | 323 | return -EINVAL; |
316 | } | 324 | } |
317 | } | 325 | } |
@@ -325,18 +333,18 @@ static int ccdc_set_params(void __user *params) | |||
325 | int x; | 333 | int x; |
326 | 334 | ||
327 | /* only raw module parameters can be set through the IOCTL */ | 335 | /* only raw module parameters can be set through the IOCTL */ |
328 | if (ccdc_if_type != VPFE_RAW_BAYER) | 336 | if (ccdc_cfg.if_type != VPFE_RAW_BAYER) |
329 | return -EINVAL; | 337 | return -EINVAL; |
330 | 338 | ||
331 | x = copy_from_user(&ccdc_raw_params, params, sizeof(ccdc_raw_params)); | 339 | x = copy_from_user(&ccdc_raw_params, params, sizeof(ccdc_raw_params)); |
332 | if (x) { | 340 | if (x) { |
333 | dev_dbg(dev, "ccdc_set_params: error in copying ccdc" | 341 | dev_dbg(ccdc_cfg.dev, "ccdc_set_params: error in copying ccdc" |
334 | "params, %d\n", x); | 342 | "params, %d\n", x); |
335 | return -EFAULT; | 343 | return -EFAULT; |
336 | } | 344 | } |
337 | 345 | ||
338 | if (!validate_ccdc_param(&ccdc_raw_params)) { | 346 | if (!validate_ccdc_param(&ccdc_raw_params)) { |
339 | memcpy(&ccdc_hw_params_raw.config_params, | 347 | memcpy(&ccdc_cfg.bayer.config_params, |
340 | &ccdc_raw_params, | 348 | &ccdc_raw_params, |
341 | sizeof(ccdc_raw_params)); | 349 | sizeof(ccdc_raw_params)); |
342 | return 0; | 350 | return 0; |
@@ -347,11 +355,11 @@ static int ccdc_set_params(void __user *params) | |||
347 | /* This function will configure CCDC for YCbCr video capture */ | 355 | /* This function will configure CCDC for YCbCr video capture */ |
348 | static void ccdc_config_ycbcr(void) | 356 | static void ccdc_config_ycbcr(void) |
349 | { | 357 | { |
350 | struct ccdc_params_ycbcr *params = &ccdc_hw_params_ycbcr; | 358 | struct ccdc_params_ycbcr *params = &ccdc_cfg.ycbcr; |
351 | u32 temp; | 359 | u32 temp; |
352 | 360 | ||
353 | /* first set the CCDC power on defaults values in all registers */ | 361 | /* first set the CCDC power on defaults values in all registers */ |
354 | dev_dbg(dev, "\nStarting ccdc_config_ycbcr..."); | 362 | dev_dbg(ccdc_cfg.dev, "\nStarting ccdc_config_ycbcr..."); |
355 | ccdc_restore_defaults(); | 363 | ccdc_restore_defaults(); |
356 | 364 | ||
357 | /* configure pixel format & video frame format */ | 365 | /* configure pixel format & video frame format */ |
@@ -403,7 +411,7 @@ static void ccdc_config_ycbcr(void) | |||
403 | regw(CCDC_SDOFST_FIELD_INTERLEAVED, SDOFST); | 411 | regw(CCDC_SDOFST_FIELD_INTERLEAVED, SDOFST); |
404 | } | 412 | } |
405 | 413 | ||
406 | dev_dbg(dev, "\nEnd of ccdc_config_ycbcr...\n"); | 414 | dev_dbg(ccdc_cfg.dev, "\nEnd of ccdc_config_ycbcr...\n"); |
407 | } | 415 | } |
408 | 416 | ||
409 | /* | 417 | /* |
@@ -483,7 +491,7 @@ int ccdc_write_dfc_entry(int index, struct ccdc_vertical_dft *dfc) | |||
483 | */ | 491 | */ |
484 | 492 | ||
485 | if (count) { | 493 | if (count) { |
486 | dev_err(dev, "defect table write timeout !!!\n"); | 494 | dev_err(ccdc_cfg.dev, "defect table write timeout !!!\n"); |
487 | return -1; | 495 | return -1; |
488 | } | 496 | } |
489 | return 0; | 497 | return 0; |
@@ -605,12 +613,12 @@ static void ccdc_config_color_patterns(struct ccdc_col_pat *pat0, | |||
605 | /* This function will configure CCDC for Raw mode image capture */ | 613 | /* This function will configure CCDC for Raw mode image capture */ |
606 | static int ccdc_config_raw(void) | 614 | static int ccdc_config_raw(void) |
607 | { | 615 | { |
608 | struct ccdc_params_raw *params = &ccdc_hw_params_raw; | 616 | struct ccdc_params_raw *params = &ccdc_cfg.bayer; |
609 | struct ccdc_config_params_raw *config_params = | 617 | struct ccdc_config_params_raw *config_params = |
610 | &ccdc_hw_params_raw.config_params; | 618 | &ccdc_cfg.bayer.config_params; |
611 | unsigned int val; | 619 | unsigned int val; |
612 | 620 | ||
613 | dev_dbg(dev, "\nStarting ccdc_config_raw..."); | 621 | dev_dbg(ccdc_cfg.dev, "\nStarting ccdc_config_raw..."); |
614 | 622 | ||
615 | /* restore power on defaults to register */ | 623 | /* restore power on defaults to register */ |
616 | ccdc_restore_defaults(); | 624 | ccdc_restore_defaults(); |
@@ -659,7 +667,7 @@ static int ccdc_config_raw(void) | |||
659 | val |= (config_params->datasft & CCDC_DATASFT_MASK) << | 667 | val |= (config_params->datasft & CCDC_DATASFT_MASK) << |
660 | CCDC_DATASFT_SHIFT; | 668 | CCDC_DATASFT_SHIFT; |
661 | regw(val , MODESET); | 669 | regw(val , MODESET); |
662 | dev_dbg(dev, "\nWriting 0x%x to MODESET...\n", val); | 670 | dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to MODESET...\n", val); |
663 | 671 | ||
664 | /* Configure the Median Filter threshold */ | 672 | /* Configure the Median Filter threshold */ |
665 | regw((config_params->med_filt_thres) & CCDC_MED_FILT_THRESH, MEDFILT); | 673 | regw((config_params->med_filt_thres) & CCDC_MED_FILT_THRESH, MEDFILT); |
@@ -681,7 +689,7 @@ static int ccdc_config_raw(void) | |||
681 | (config_params->mfilt2 << CCDC_MFILT2_SHIFT)); | 689 | (config_params->mfilt2 << CCDC_MFILT2_SHIFT)); |
682 | 690 | ||
683 | regw(val, GAMMAWD); | 691 | regw(val, GAMMAWD); |
684 | dev_dbg(dev, "\nWriting 0x%x to GAMMAWD...\n", val); | 692 | dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to GAMMAWD...\n", val); |
685 | 693 | ||
686 | /* configure video window */ | 694 | /* configure video window */ |
687 | ccdc_setwin(¶ms->win, params->frm_fmt, 1); | 695 | ccdc_setwin(¶ms->win, params->frm_fmt, 1); |
@@ -706,7 +714,7 @@ static int ccdc_config_raw(void) | |||
706 | /* Configure the Gain & offset control */ | 714 | /* Configure the Gain & offset control */ |
707 | ccdc_config_gain_offset(); | 715 | ccdc_config_gain_offset(); |
708 | 716 | ||
709 | dev_dbg(dev, "\nWriting %x to COLPTN...\n", val); | 717 | dev_dbg(ccdc_cfg.dev, "\nWriting %x to COLPTN...\n", val); |
710 | 718 | ||
711 | /* Configure DATAOFST register */ | 719 | /* Configure DATAOFST register */ |
712 | val = (config_params->data_offset.horz_offset & CCDC_DATAOFST_MASK) << | 720 | val = (config_params->data_offset.horz_offset & CCDC_DATAOFST_MASK) << |
@@ -726,7 +734,7 @@ static int ccdc_config_raw(void) | |||
726 | CCDC_HSIZE_VAL_MASK; | 734 | CCDC_HSIZE_VAL_MASK; |
727 | 735 | ||
728 | /* adjust to multiple of 32 */ | 736 | /* adjust to multiple of 32 */ |
729 | dev_dbg(dev, "\nWriting 0x%x to HSIZE...\n", | 737 | dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to HSIZE...\n", |
730 | (((params->win.width) + 31) >> 5) & | 738 | (((params->win.width) + 31) >> 5) & |
731 | CCDC_HSIZE_VAL_MASK); | 739 | CCDC_HSIZE_VAL_MASK); |
732 | } else { | 740 | } else { |
@@ -734,7 +742,7 @@ static int ccdc_config_raw(void) | |||
734 | val |= (((params->win.width * 2) + 31) >> 5) & | 742 | val |= (((params->win.width * 2) + 31) >> 5) & |
735 | CCDC_HSIZE_VAL_MASK; | 743 | CCDC_HSIZE_VAL_MASK; |
736 | 744 | ||
737 | dev_dbg(dev, "\nWriting 0x%x to HSIZE...\n", | 745 | dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to HSIZE...\n", |
738 | (((params->win.width * 2) + 31) >> 5) & | 746 | (((params->win.width * 2) + 31) >> 5) & |
739 | CCDC_HSIZE_VAL_MASK); | 747 | CCDC_HSIZE_VAL_MASK); |
740 | } | 748 | } |
@@ -745,34 +753,34 @@ static int ccdc_config_raw(void) | |||
745 | if (params->image_invert_enable) { | 753 | if (params->image_invert_enable) { |
746 | /* For interlace inverse mode */ | 754 | /* For interlace inverse mode */ |
747 | regw(CCDC_SDOFST_INTERLACE_INVERSE, SDOFST); | 755 | regw(CCDC_SDOFST_INTERLACE_INVERSE, SDOFST); |
748 | dev_dbg(dev, "\nWriting %x to SDOFST...\n", | 756 | dev_dbg(ccdc_cfg.dev, "\nWriting %x to SDOFST...\n", |
749 | CCDC_SDOFST_INTERLACE_INVERSE); | 757 | CCDC_SDOFST_INTERLACE_INVERSE); |
750 | } else { | 758 | } else { |
751 | /* For interlace non inverse mode */ | 759 | /* For interlace non inverse mode */ |
752 | regw(CCDC_SDOFST_INTERLACE_NORMAL, SDOFST); | 760 | regw(CCDC_SDOFST_INTERLACE_NORMAL, SDOFST); |
753 | dev_dbg(dev, "\nWriting %x to SDOFST...\n", | 761 | dev_dbg(ccdc_cfg.dev, "\nWriting %x to SDOFST...\n", |
754 | CCDC_SDOFST_INTERLACE_NORMAL); | 762 | CCDC_SDOFST_INTERLACE_NORMAL); |
755 | } | 763 | } |
756 | } else if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE) { | 764 | } else if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE) { |
757 | if (params->image_invert_enable) { | 765 | if (params->image_invert_enable) { |
758 | /* For progessive inverse mode */ | 766 | /* For progessive inverse mode */ |
759 | regw(CCDC_SDOFST_PROGRESSIVE_INVERSE, SDOFST); | 767 | regw(CCDC_SDOFST_PROGRESSIVE_INVERSE, SDOFST); |
760 | dev_dbg(dev, "\nWriting %x to SDOFST...\n", | 768 | dev_dbg(ccdc_cfg.dev, "\nWriting %x to SDOFST...\n", |
761 | CCDC_SDOFST_PROGRESSIVE_INVERSE); | 769 | CCDC_SDOFST_PROGRESSIVE_INVERSE); |
762 | } else { | 770 | } else { |
763 | /* For progessive non inverse mode */ | 771 | /* For progessive non inverse mode */ |
764 | regw(CCDC_SDOFST_PROGRESSIVE_NORMAL, SDOFST); | 772 | regw(CCDC_SDOFST_PROGRESSIVE_NORMAL, SDOFST); |
765 | dev_dbg(dev, "\nWriting %x to SDOFST...\n", | 773 | dev_dbg(ccdc_cfg.dev, "\nWriting %x to SDOFST...\n", |
766 | CCDC_SDOFST_PROGRESSIVE_NORMAL); | 774 | CCDC_SDOFST_PROGRESSIVE_NORMAL); |
767 | } | 775 | } |
768 | } | 776 | } |
769 | dev_dbg(dev, "\nend of ccdc_config_raw..."); | 777 | dev_dbg(ccdc_cfg.dev, "\nend of ccdc_config_raw..."); |
770 | return 0; | 778 | return 0; |
771 | } | 779 | } |
772 | 780 | ||
773 | static int ccdc_configure(void) | 781 | static int ccdc_configure(void) |
774 | { | 782 | { |
775 | if (ccdc_if_type == VPFE_RAW_BAYER) | 783 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) |
776 | return ccdc_config_raw(); | 784 | return ccdc_config_raw(); |
777 | else | 785 | else |
778 | ccdc_config_ycbcr(); | 786 | ccdc_config_ycbcr(); |
@@ -781,23 +789,23 @@ static int ccdc_configure(void) | |||
781 | 789 | ||
782 | static int ccdc_set_buftype(enum ccdc_buftype buf_type) | 790 | static int ccdc_set_buftype(enum ccdc_buftype buf_type) |
783 | { | 791 | { |
784 | if (ccdc_if_type == VPFE_RAW_BAYER) | 792 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) |
785 | ccdc_hw_params_raw.buf_type = buf_type; | 793 | ccdc_cfg.bayer.buf_type = buf_type; |
786 | else | 794 | else |
787 | ccdc_hw_params_ycbcr.buf_type = buf_type; | 795 | ccdc_cfg.ycbcr.buf_type = buf_type; |
788 | return 0; | 796 | return 0; |
789 | } | 797 | } |
790 | static enum ccdc_buftype ccdc_get_buftype(void) | 798 | static enum ccdc_buftype ccdc_get_buftype(void) |
791 | { | 799 | { |
792 | if (ccdc_if_type == VPFE_RAW_BAYER) | 800 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) |
793 | return ccdc_hw_params_raw.buf_type; | 801 | return ccdc_cfg.bayer.buf_type; |
794 | return ccdc_hw_params_ycbcr.buf_type; | 802 | return ccdc_cfg.ycbcr.buf_type; |
795 | } | 803 | } |
796 | 804 | ||
797 | static int ccdc_enum_pix(u32 *pix, int i) | 805 | static int ccdc_enum_pix(u32 *pix, int i) |
798 | { | 806 | { |
799 | int ret = -EINVAL; | 807 | int ret = -EINVAL; |
800 | if (ccdc_if_type == VPFE_RAW_BAYER) { | 808 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) { |
801 | if (i < ARRAY_SIZE(ccdc_raw_bayer_pix_formats)) { | 809 | if (i < ARRAY_SIZE(ccdc_raw_bayer_pix_formats)) { |
802 | *pix = ccdc_raw_bayer_pix_formats[i]; | 810 | *pix = ccdc_raw_bayer_pix_formats[i]; |
803 | ret = 0; | 811 | ret = 0; |
@@ -813,20 +821,19 @@ static int ccdc_enum_pix(u32 *pix, int i) | |||
813 | 821 | ||
814 | static int ccdc_set_pixel_format(u32 pixfmt) | 822 | static int ccdc_set_pixel_format(u32 pixfmt) |
815 | { | 823 | { |
816 | struct ccdc_a_law *alaw = | 824 | struct ccdc_a_law *alaw = &ccdc_cfg.bayer.config_params.alaw; |
817 | &ccdc_hw_params_raw.config_params.alaw; | ||
818 | 825 | ||
819 | if (ccdc_if_type == VPFE_RAW_BAYER) { | 826 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) { |
820 | ccdc_hw_params_raw.pix_fmt = CCDC_PIXFMT_RAW; | 827 | ccdc_cfg.bayer.pix_fmt = CCDC_PIXFMT_RAW; |
821 | if (pixfmt == V4L2_PIX_FMT_SBGGR8) | 828 | if (pixfmt == V4L2_PIX_FMT_SBGGR8) |
822 | alaw->enable = 1; | 829 | alaw->enable = 1; |
823 | else if (pixfmt != V4L2_PIX_FMT_SBGGR16) | 830 | else if (pixfmt != V4L2_PIX_FMT_SBGGR16) |
824 | return -EINVAL; | 831 | return -EINVAL; |
825 | } else { | 832 | } else { |
826 | if (pixfmt == V4L2_PIX_FMT_YUYV) | 833 | if (pixfmt == V4L2_PIX_FMT_YUYV) |
827 | ccdc_hw_params_ycbcr.pix_order = CCDC_PIXORDER_YCBYCR; | 834 | ccdc_cfg.ycbcr.pix_order = CCDC_PIXORDER_YCBYCR; |
828 | else if (pixfmt == V4L2_PIX_FMT_UYVY) | 835 | else if (pixfmt == V4L2_PIX_FMT_UYVY) |
829 | ccdc_hw_params_ycbcr.pix_order = CCDC_PIXORDER_CBYCRY; | 836 | ccdc_cfg.ycbcr.pix_order = CCDC_PIXORDER_CBYCRY; |
830 | else | 837 | else |
831 | return -EINVAL; | 838 | return -EINVAL; |
832 | } | 839 | } |
@@ -834,17 +841,16 @@ static int ccdc_set_pixel_format(u32 pixfmt) | |||
834 | } | 841 | } |
835 | static u32 ccdc_get_pixel_format(void) | 842 | static u32 ccdc_get_pixel_format(void) |
836 | { | 843 | { |
837 | struct ccdc_a_law *alaw = | 844 | struct ccdc_a_law *alaw = &ccdc_cfg.bayer.config_params.alaw; |
838 | &ccdc_hw_params_raw.config_params.alaw; | ||
839 | u32 pixfmt; | 845 | u32 pixfmt; |
840 | 846 | ||
841 | if (ccdc_if_type == VPFE_RAW_BAYER) | 847 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) |
842 | if (alaw->enable) | 848 | if (alaw->enable) |
843 | pixfmt = V4L2_PIX_FMT_SBGGR8; | 849 | pixfmt = V4L2_PIX_FMT_SBGGR8; |
844 | else | 850 | else |
845 | pixfmt = V4L2_PIX_FMT_SBGGR16; | 851 | pixfmt = V4L2_PIX_FMT_SBGGR16; |
846 | else { | 852 | else { |
847 | if (ccdc_hw_params_ycbcr.pix_order == CCDC_PIXORDER_YCBYCR) | 853 | if (ccdc_cfg.ycbcr.pix_order == CCDC_PIXORDER_YCBYCR) |
848 | pixfmt = V4L2_PIX_FMT_YUYV; | 854 | pixfmt = V4L2_PIX_FMT_YUYV; |
849 | else | 855 | else |
850 | pixfmt = V4L2_PIX_FMT_UYVY; | 856 | pixfmt = V4L2_PIX_FMT_UYVY; |
@@ -853,53 +859,53 @@ static u32 ccdc_get_pixel_format(void) | |||
853 | } | 859 | } |
854 | static int ccdc_set_image_window(struct v4l2_rect *win) | 860 | static int ccdc_set_image_window(struct v4l2_rect *win) |
855 | { | 861 | { |
856 | if (ccdc_if_type == VPFE_RAW_BAYER) | 862 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) |
857 | ccdc_hw_params_raw.win = *win; | 863 | ccdc_cfg.bayer.win = *win; |
858 | else | 864 | else |
859 | ccdc_hw_params_ycbcr.win = *win; | 865 | ccdc_cfg.ycbcr.win = *win; |
860 | return 0; | 866 | return 0; |
861 | } | 867 | } |
862 | 868 | ||
863 | static void ccdc_get_image_window(struct v4l2_rect *win) | 869 | static void ccdc_get_image_window(struct v4l2_rect *win) |
864 | { | 870 | { |
865 | if (ccdc_if_type == VPFE_RAW_BAYER) | 871 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) |
866 | *win = ccdc_hw_params_raw.win; | 872 | *win = ccdc_cfg.bayer.win; |
867 | else | 873 | else |
868 | *win = ccdc_hw_params_ycbcr.win; | 874 | *win = ccdc_cfg.ycbcr.win; |
869 | } | 875 | } |
870 | 876 | ||
871 | static unsigned int ccdc_get_line_length(void) | 877 | static unsigned int ccdc_get_line_length(void) |
872 | { | 878 | { |
873 | struct ccdc_config_params_raw *config_params = | 879 | struct ccdc_config_params_raw *config_params = |
874 | &ccdc_hw_params_raw.config_params; | 880 | &ccdc_cfg.bayer.config_params; |
875 | unsigned int len; | 881 | unsigned int len; |
876 | 882 | ||
877 | if (ccdc_if_type == VPFE_RAW_BAYER) { | 883 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) { |
878 | if ((config_params->alaw.enable) || | 884 | if ((config_params->alaw.enable) || |
879 | (config_params->data_sz == CCDC_DATA_8BITS)) | 885 | (config_params->data_sz == CCDC_DATA_8BITS)) |
880 | len = ccdc_hw_params_raw.win.width; | 886 | len = ccdc_cfg.bayer.win.width; |
881 | else | 887 | else |
882 | len = ccdc_hw_params_raw.win.width * 2; | 888 | len = ccdc_cfg.bayer.win.width * 2; |
883 | } else | 889 | } else |
884 | len = ccdc_hw_params_ycbcr.win.width * 2; | 890 | len = ccdc_cfg.ycbcr.win.width * 2; |
885 | return ALIGN(len, 32); | 891 | return ALIGN(len, 32); |
886 | } | 892 | } |
887 | 893 | ||
888 | static int ccdc_set_frame_format(enum ccdc_frmfmt frm_fmt) | 894 | static int ccdc_set_frame_format(enum ccdc_frmfmt frm_fmt) |
889 | { | 895 | { |
890 | if (ccdc_if_type == VPFE_RAW_BAYER) | 896 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) |
891 | ccdc_hw_params_raw.frm_fmt = frm_fmt; | 897 | ccdc_cfg.bayer.frm_fmt = frm_fmt; |
892 | else | 898 | else |
893 | ccdc_hw_params_ycbcr.frm_fmt = frm_fmt; | 899 | ccdc_cfg.ycbcr.frm_fmt = frm_fmt; |
894 | return 0; | 900 | return 0; |
895 | } | 901 | } |
896 | 902 | ||
897 | static enum ccdc_frmfmt ccdc_get_frame_format(void) | 903 | static enum ccdc_frmfmt ccdc_get_frame_format(void) |
898 | { | 904 | { |
899 | if (ccdc_if_type == VPFE_RAW_BAYER) | 905 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) |
900 | return ccdc_hw_params_raw.frm_fmt; | 906 | return ccdc_cfg.bayer.frm_fmt; |
901 | else | 907 | else |
902 | return ccdc_hw_params_ycbcr.frm_fmt; | 908 | return ccdc_cfg.ycbcr.frm_fmt; |
903 | } | 909 | } |
904 | 910 | ||
905 | static int ccdc_getfid(void) | 911 | static int ccdc_getfid(void) |
@@ -916,14 +922,14 @@ static inline void ccdc_setfbaddr(unsigned long addr) | |||
916 | 922 | ||
917 | static int ccdc_set_hw_if_params(struct vpfe_hw_if_param *params) | 923 | static int ccdc_set_hw_if_params(struct vpfe_hw_if_param *params) |
918 | { | 924 | { |
919 | ccdc_if_type = params->if_type; | 925 | ccdc_cfg.if_type = params->if_type; |
920 | 926 | ||
921 | switch (params->if_type) { | 927 | switch (params->if_type) { |
922 | case VPFE_BT656: | 928 | case VPFE_BT656: |
923 | case VPFE_YCBCR_SYNC_16: | 929 | case VPFE_YCBCR_SYNC_16: |
924 | case VPFE_YCBCR_SYNC_8: | 930 | case VPFE_YCBCR_SYNC_8: |
925 | ccdc_hw_params_ycbcr.vd_pol = params->vdpol; | 931 | ccdc_cfg.ycbcr.vd_pol = params->vdpol; |
926 | ccdc_hw_params_ycbcr.hd_pol = params->hdpol; | 932 | ccdc_cfg.ycbcr.hd_pol = params->hdpol; |
927 | break; | 933 | break; |
928 | default: | 934 | default: |
929 | /* TODO add support for raw bayer here */ | 935 | /* TODO add support for raw bayer here */ |
@@ -938,7 +944,6 @@ static struct ccdc_hw_device ccdc_hw_dev = { | |||
938 | .hw_ops = { | 944 | .hw_ops = { |
939 | .open = ccdc_open, | 945 | .open = ccdc_open, |
940 | .close = ccdc_close, | 946 | .close = ccdc_close, |
941 | .set_ccdc_base = ccdc_set_ccdc_base, | ||
942 | .enable = ccdc_enable, | 947 | .enable = ccdc_enable, |
943 | .enable_out_to_sdram = ccdc_enable_output_to_sdram, | 948 | .enable_out_to_sdram = ccdc_enable_output_to_sdram, |
944 | .set_hw_if_params = ccdc_set_hw_if_params, | 949 | .set_hw_if_params = ccdc_set_hw_if_params, |
@@ -959,19 +964,118 @@ static struct ccdc_hw_device ccdc_hw_dev = { | |||
959 | }, | 964 | }, |
960 | }; | 965 | }; |
961 | 966 | ||
962 | static int __init dm355_ccdc_init(void) | 967 | static int __init dm355_ccdc_probe(struct platform_device *pdev) |
963 | { | 968 | { |
964 | printk(KERN_NOTICE "dm355_ccdc_init\n"); | 969 | void (*setup_pinmux)(void); |
965 | if (vpfe_register_ccdc_device(&ccdc_hw_dev) < 0) | 970 | struct resource *res; |
966 | return -1; | 971 | int status = 0; |
967 | printk(KERN_NOTICE "%s is registered with vpfe.\n", | 972 | |
968 | ccdc_hw_dev.name); | 973 | /* |
974 | * first try to register with vpfe. If not correct platform, then we | ||
975 | * don't have to iomap | ||
976 | */ | ||
977 | status = vpfe_register_ccdc_device(&ccdc_hw_dev); | ||
978 | if (status < 0) | ||
979 | return status; | ||
980 | |||
981 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
982 | if (!res) { | ||
983 | status = -ENODEV; | ||
984 | goto fail_nores; | ||
985 | } | ||
986 | |||
987 | res = request_mem_region(res->start, resource_size(res), res->name); | ||
988 | if (!res) { | ||
989 | status = -EBUSY; | ||
990 | goto fail_nores; | ||
991 | } | ||
992 | |||
993 | ccdc_cfg.base_addr = ioremap_nocache(res->start, resource_size(res)); | ||
994 | if (!ccdc_cfg.base_addr) { | ||
995 | status = -ENOMEM; | ||
996 | goto fail_nomem; | ||
997 | } | ||
998 | |||
999 | /* Get and enable Master clock */ | ||
1000 | ccdc_cfg.mclk = clk_get(&pdev->dev, "master"); | ||
1001 | if (IS_ERR(ccdc_cfg.mclk)) { | ||
1002 | status = PTR_ERR(ccdc_cfg.mclk); | ||
1003 | goto fail_nomap; | ||
1004 | } | ||
1005 | if (clk_enable(ccdc_cfg.mclk)) { | ||
1006 | status = -ENODEV; | ||
1007 | goto fail_mclk; | ||
1008 | } | ||
1009 | |||
1010 | /* Get and enable Slave clock */ | ||
1011 | ccdc_cfg.sclk = clk_get(&pdev->dev, "slave"); | ||
1012 | if (IS_ERR(ccdc_cfg.sclk)) { | ||
1013 | status = PTR_ERR(ccdc_cfg.sclk); | ||
1014 | goto fail_mclk; | ||
1015 | } | ||
1016 | if (clk_enable(ccdc_cfg.sclk)) { | ||
1017 | status = -ENODEV; | ||
1018 | goto fail_sclk; | ||
1019 | } | ||
1020 | |||
1021 | /* Platform data holds setup_pinmux function ptr */ | ||
1022 | if (NULL == pdev->dev.platform_data) { | ||
1023 | status = -ENODEV; | ||
1024 | goto fail_sclk; | ||
1025 | } | ||
1026 | setup_pinmux = pdev->dev.platform_data; | ||
1027 | /* | ||
1028 | * setup Mux configuration for ccdc which may be different for | ||
1029 | * different SoCs using this CCDC | ||
1030 | */ | ||
1031 | setup_pinmux(); | ||
1032 | ccdc_cfg.dev = &pdev->dev; | ||
1033 | printk(KERN_NOTICE "%s is registered with vpfe.\n", ccdc_hw_dev.name); | ||
969 | return 0; | 1034 | return 0; |
1035 | fail_sclk: | ||
1036 | clk_put(ccdc_cfg.sclk); | ||
1037 | fail_mclk: | ||
1038 | clk_put(ccdc_cfg.mclk); | ||
1039 | fail_nomap: | ||
1040 | iounmap(ccdc_cfg.base_addr); | ||
1041 | fail_nomem: | ||
1042 | release_mem_region(res->start, resource_size(res)); | ||
1043 | fail_nores: | ||
1044 | vpfe_unregister_ccdc_device(&ccdc_hw_dev); | ||
1045 | return status; | ||
970 | } | 1046 | } |
971 | 1047 | ||
972 | static void __exit dm355_ccdc_exit(void) | 1048 | static int dm355_ccdc_remove(struct platform_device *pdev) |
973 | { | 1049 | { |
1050 | struct resource *res; | ||
1051 | |||
1052 | clk_put(ccdc_cfg.mclk); | ||
1053 | clk_put(ccdc_cfg.sclk); | ||
1054 | iounmap(ccdc_cfg.base_addr); | ||
1055 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1056 | if (res) | ||
1057 | release_mem_region(res->start, resource_size(res)); | ||
974 | vpfe_unregister_ccdc_device(&ccdc_hw_dev); | 1058 | vpfe_unregister_ccdc_device(&ccdc_hw_dev); |
1059 | return 0; | ||
1060 | } | ||
1061 | |||
1062 | static struct platform_driver dm355_ccdc_driver = { | ||
1063 | .driver = { | ||
1064 | .name = "dm355_ccdc", | ||
1065 | .owner = THIS_MODULE, | ||
1066 | }, | ||
1067 | .remove = __devexit_p(dm355_ccdc_remove), | ||
1068 | .probe = dm355_ccdc_probe, | ||
1069 | }; | ||
1070 | |||
1071 | static int __init dm355_ccdc_init(void) | ||
1072 | { | ||
1073 | return platform_driver_register(&dm355_ccdc_driver); | ||
1074 | } | ||
1075 | |||
1076 | static void __exit dm355_ccdc_exit(void) | ||
1077 | { | ||
1078 | platform_driver_unregister(&dm355_ccdc_driver); | ||
975 | } | 1079 | } |
976 | 1080 | ||
977 | module_init(dm355_ccdc_init); | 1081 | module_init(dm355_ccdc_init); |
diff --git a/drivers/media/video/davinci/dm644x_ccdc.c b/drivers/media/video/davinci/dm644x_ccdc.c index d5fa193f32d2..0c394cade22a 100644 --- a/drivers/media/video/davinci/dm644x_ccdc.c +++ b/drivers/media/video/davinci/dm644x_ccdc.c | |||
@@ -37,8 +37,12 @@ | |||
37 | #include <linux/platform_device.h> | 37 | #include <linux/platform_device.h> |
38 | #include <linux/uaccess.h> | 38 | #include <linux/uaccess.h> |
39 | #include <linux/videodev2.h> | 39 | #include <linux/videodev2.h> |
40 | #include <linux/clk.h> | ||
41 | #include <linux/err.h> | ||
42 | |||
40 | #include <media/davinci/dm644x_ccdc.h> | 43 | #include <media/davinci/dm644x_ccdc.h> |
41 | #include <media/davinci/vpss.h> | 44 | #include <media/davinci/vpss.h> |
45 | |||
42 | #include "dm644x_ccdc_regs.h" | 46 | #include "dm644x_ccdc_regs.h" |
43 | #include "ccdc_hw_device.h" | 47 | #include "ccdc_hw_device.h" |
44 | 48 | ||
@@ -46,32 +50,44 @@ MODULE_LICENSE("GPL"); | |||
46 | MODULE_DESCRIPTION("CCDC Driver for DM6446"); | 50 | MODULE_DESCRIPTION("CCDC Driver for DM6446"); |
47 | MODULE_AUTHOR("Texas Instruments"); | 51 | MODULE_AUTHOR("Texas Instruments"); |
48 | 52 | ||
49 | static struct device *dev; | 53 | static struct ccdc_oper_config { |
50 | 54 | struct device *dev; | |
51 | /* Object for CCDC raw mode */ | 55 | /* CCDC interface type */ |
52 | static struct ccdc_params_raw ccdc_hw_params_raw = { | 56 | enum vpfe_hw_if_type if_type; |
53 | .pix_fmt = CCDC_PIXFMT_RAW, | 57 | /* Raw Bayer configuration */ |
54 | .frm_fmt = CCDC_FRMFMT_PROGRESSIVE, | 58 | struct ccdc_params_raw bayer; |
55 | .win = CCDC_WIN_VGA, | 59 | /* YCbCr configuration */ |
56 | .fid_pol = VPFE_PINPOL_POSITIVE, | 60 | struct ccdc_params_ycbcr ycbcr; |
57 | .vd_pol = VPFE_PINPOL_POSITIVE, | 61 | /* Master clock */ |
58 | .hd_pol = VPFE_PINPOL_POSITIVE, | 62 | struct clk *mclk; |
59 | .config_params = { | 63 | /* slave clock */ |
60 | .data_sz = CCDC_DATA_10BITS, | 64 | struct clk *sclk; |
65 | /* ccdc base address */ | ||
66 | void __iomem *base_addr; | ||
67 | } ccdc_cfg = { | ||
68 | /* Raw configurations */ | ||
69 | .bayer = { | ||
70 | .pix_fmt = CCDC_PIXFMT_RAW, | ||
71 | .frm_fmt = CCDC_FRMFMT_PROGRESSIVE, | ||
72 | .win = CCDC_WIN_VGA, | ||
73 | .fid_pol = VPFE_PINPOL_POSITIVE, | ||
74 | .vd_pol = VPFE_PINPOL_POSITIVE, | ||
75 | .hd_pol = VPFE_PINPOL_POSITIVE, | ||
76 | .config_params = { | ||
77 | .data_sz = CCDC_DATA_10BITS, | ||
78 | }, | ||
79 | }, | ||
80 | .ycbcr = { | ||
81 | .pix_fmt = CCDC_PIXFMT_YCBCR_8BIT, | ||
82 | .frm_fmt = CCDC_FRMFMT_INTERLACED, | ||
83 | .win = CCDC_WIN_PAL, | ||
84 | .fid_pol = VPFE_PINPOL_POSITIVE, | ||
85 | .vd_pol = VPFE_PINPOL_POSITIVE, | ||
86 | .hd_pol = VPFE_PINPOL_POSITIVE, | ||
87 | .bt656_enable = 1, | ||
88 | .pix_order = CCDC_PIXORDER_CBYCRY, | ||
89 | .buf_type = CCDC_BUFTYPE_FLD_INTERLEAVED | ||
61 | }, | 90 | }, |
62 | }; | ||
63 | |||
64 | /* Object for CCDC ycbcr mode */ | ||
65 | static struct ccdc_params_ycbcr ccdc_hw_params_ycbcr = { | ||
66 | .pix_fmt = CCDC_PIXFMT_YCBCR_8BIT, | ||
67 | .frm_fmt = CCDC_FRMFMT_INTERLACED, | ||
68 | .win = CCDC_WIN_PAL, | ||
69 | .fid_pol = VPFE_PINPOL_POSITIVE, | ||
70 | .vd_pol = VPFE_PINPOL_POSITIVE, | ||
71 | .hd_pol = VPFE_PINPOL_POSITIVE, | ||
72 | .bt656_enable = 1, | ||
73 | .pix_order = CCDC_PIXORDER_CBYCRY, | ||
74 | .buf_type = CCDC_BUFTYPE_FLD_INTERLEAVED | ||
75 | }; | 91 | }; |
76 | 92 | ||
77 | #define CCDC_MAX_RAW_YUV_FORMATS 2 | 93 | #define CCDC_MAX_RAW_YUV_FORMATS 2 |
@@ -84,25 +100,15 @@ static u32 ccdc_raw_bayer_pix_formats[] = | |||
84 | static u32 ccdc_raw_yuv_pix_formats[] = | 100 | static u32 ccdc_raw_yuv_pix_formats[] = |
85 | {V4L2_PIX_FMT_UYVY, V4L2_PIX_FMT_YUYV}; | 101 | {V4L2_PIX_FMT_UYVY, V4L2_PIX_FMT_YUYV}; |
86 | 102 | ||
87 | static void *__iomem ccdc_base_addr; | ||
88 | static int ccdc_addr_size; | ||
89 | static enum vpfe_hw_if_type ccdc_if_type; | ||
90 | |||
91 | /* register access routines */ | 103 | /* register access routines */ |
92 | static inline u32 regr(u32 offset) | 104 | static inline u32 regr(u32 offset) |
93 | { | 105 | { |
94 | return __raw_readl(ccdc_base_addr + offset); | 106 | return __raw_readl(ccdc_cfg.base_addr + offset); |
95 | } | 107 | } |
96 | 108 | ||
97 | static inline void regw(u32 val, u32 offset) | 109 | static inline void regw(u32 val, u32 offset) |
98 | { | 110 | { |
99 | __raw_writel(val, ccdc_base_addr + offset); | 111 | __raw_writel(val, ccdc_cfg.base_addr + offset); |
100 | } | ||
101 | |||
102 | static void ccdc_set_ccdc_base(void *addr, int size) | ||
103 | { | ||
104 | ccdc_base_addr = addr; | ||
105 | ccdc_addr_size = size; | ||
106 | } | 112 | } |
107 | 113 | ||
108 | static void ccdc_enable(int flag) | 114 | static void ccdc_enable(int flag) |
@@ -132,7 +138,7 @@ void ccdc_setwin(struct v4l2_rect *image_win, | |||
132 | int vert_start, vert_nr_lines; | 138 | int vert_start, vert_nr_lines; |
133 | int val = 0, mid_img = 0; | 139 | int val = 0, mid_img = 0; |
134 | 140 | ||
135 | dev_dbg(dev, "\nStarting ccdc_setwin..."); | 141 | dev_dbg(ccdc_cfg.dev, "\nStarting ccdc_setwin..."); |
136 | /* | 142 | /* |
137 | * ppc - per pixel count. indicates how many pixels per cell | 143 | * ppc - per pixel count. indicates how many pixels per cell |
138 | * output to SDRAM. example, for ycbcr, it is one y and one c, so 2. | 144 | * output to SDRAM. example, for ycbcr, it is one y and one c, so 2. |
@@ -171,7 +177,7 @@ void ccdc_setwin(struct v4l2_rect *image_win, | |||
171 | regw((vert_start << CCDC_VERT_START_SLV0_SHIFT) | vert_start, | 177 | regw((vert_start << CCDC_VERT_START_SLV0_SHIFT) | vert_start, |
172 | CCDC_VERT_START); | 178 | CCDC_VERT_START); |
173 | regw(vert_nr_lines, CCDC_VERT_LINES); | 179 | regw(vert_nr_lines, CCDC_VERT_LINES); |
174 | dev_dbg(dev, "\nEnd of ccdc_setwin..."); | 180 | dev_dbg(ccdc_cfg.dev, "\nEnd of ccdc_setwin..."); |
175 | } | 181 | } |
176 | 182 | ||
177 | static void ccdc_readregs(void) | 183 | static void ccdc_readregs(void) |
@@ -179,39 +185,39 @@ static void ccdc_readregs(void) | |||
179 | unsigned int val = 0; | 185 | unsigned int val = 0; |
180 | 186 | ||
181 | val = regr(CCDC_ALAW); | 187 | val = regr(CCDC_ALAW); |
182 | dev_notice(dev, "\nReading 0x%x to ALAW...\n", val); | 188 | dev_notice(ccdc_cfg.dev, "\nReading 0x%x to ALAW...\n", val); |
183 | val = regr(CCDC_CLAMP); | 189 | val = regr(CCDC_CLAMP); |
184 | dev_notice(dev, "\nReading 0x%x to CLAMP...\n", val); | 190 | dev_notice(ccdc_cfg.dev, "\nReading 0x%x to CLAMP...\n", val); |
185 | val = regr(CCDC_DCSUB); | 191 | val = regr(CCDC_DCSUB); |
186 | dev_notice(dev, "\nReading 0x%x to DCSUB...\n", val); | 192 | dev_notice(ccdc_cfg.dev, "\nReading 0x%x to DCSUB...\n", val); |
187 | val = regr(CCDC_BLKCMP); | 193 | val = regr(CCDC_BLKCMP); |
188 | dev_notice(dev, "\nReading 0x%x to BLKCMP...\n", val); | 194 | dev_notice(ccdc_cfg.dev, "\nReading 0x%x to BLKCMP...\n", val); |
189 | val = regr(CCDC_FPC_ADDR); | 195 | val = regr(CCDC_FPC_ADDR); |
190 | dev_notice(dev, "\nReading 0x%x to FPC_ADDR...\n", val); | 196 | dev_notice(ccdc_cfg.dev, "\nReading 0x%x to FPC_ADDR...\n", val); |
191 | val = regr(CCDC_FPC); | 197 | val = regr(CCDC_FPC); |
192 | dev_notice(dev, "\nReading 0x%x to FPC...\n", val); | 198 | dev_notice(ccdc_cfg.dev, "\nReading 0x%x to FPC...\n", val); |
193 | val = regr(CCDC_FMTCFG); | 199 | val = regr(CCDC_FMTCFG); |
194 | dev_notice(dev, "\nReading 0x%x to FMTCFG...\n", val); | 200 | dev_notice(ccdc_cfg.dev, "\nReading 0x%x to FMTCFG...\n", val); |
195 | val = regr(CCDC_COLPTN); | 201 | val = regr(CCDC_COLPTN); |
196 | dev_notice(dev, "\nReading 0x%x to COLPTN...\n", val); | 202 | dev_notice(ccdc_cfg.dev, "\nReading 0x%x to COLPTN...\n", val); |
197 | val = regr(CCDC_FMT_HORZ); | 203 | val = regr(CCDC_FMT_HORZ); |
198 | dev_notice(dev, "\nReading 0x%x to FMT_HORZ...\n", val); | 204 | dev_notice(ccdc_cfg.dev, "\nReading 0x%x to FMT_HORZ...\n", val); |
199 | val = regr(CCDC_FMT_VERT); | 205 | val = regr(CCDC_FMT_VERT); |
200 | dev_notice(dev, "\nReading 0x%x to FMT_VERT...\n", val); | 206 | dev_notice(ccdc_cfg.dev, "\nReading 0x%x to FMT_VERT...\n", val); |
201 | val = regr(CCDC_HSIZE_OFF); | 207 | val = regr(CCDC_HSIZE_OFF); |
202 | dev_notice(dev, "\nReading 0x%x to HSIZE_OFF...\n", val); | 208 | dev_notice(ccdc_cfg.dev, "\nReading 0x%x to HSIZE_OFF...\n", val); |
203 | val = regr(CCDC_SDOFST); | 209 | val = regr(CCDC_SDOFST); |
204 | dev_notice(dev, "\nReading 0x%x to SDOFST...\n", val); | 210 | dev_notice(ccdc_cfg.dev, "\nReading 0x%x to SDOFST...\n", val); |
205 | val = regr(CCDC_VP_OUT); | 211 | val = regr(CCDC_VP_OUT); |
206 | dev_notice(dev, "\nReading 0x%x to VP_OUT...\n", val); | 212 | dev_notice(ccdc_cfg.dev, "\nReading 0x%x to VP_OUT...\n", val); |
207 | val = regr(CCDC_SYN_MODE); | 213 | val = regr(CCDC_SYN_MODE); |
208 | dev_notice(dev, "\nReading 0x%x to SYN_MODE...\n", val); | 214 | dev_notice(ccdc_cfg.dev, "\nReading 0x%x to SYN_MODE...\n", val); |
209 | val = regr(CCDC_HORZ_INFO); | 215 | val = regr(CCDC_HORZ_INFO); |
210 | dev_notice(dev, "\nReading 0x%x to HORZ_INFO...\n", val); | 216 | dev_notice(ccdc_cfg.dev, "\nReading 0x%x to HORZ_INFO...\n", val); |
211 | val = regr(CCDC_VERT_START); | 217 | val = regr(CCDC_VERT_START); |
212 | dev_notice(dev, "\nReading 0x%x to VERT_START...\n", val); | 218 | dev_notice(ccdc_cfg.dev, "\nReading 0x%x to VERT_START...\n", val); |
213 | val = regr(CCDC_VERT_LINES); | 219 | val = regr(CCDC_VERT_LINES); |
214 | dev_notice(dev, "\nReading 0x%x to VERT_LINES...\n", val); | 220 | dev_notice(ccdc_cfg.dev, "\nReading 0x%x to VERT_LINES...\n", val); |
215 | } | 221 | } |
216 | 222 | ||
217 | static int validate_ccdc_param(struct ccdc_config_params_raw *ccdcparam) | 223 | static int validate_ccdc_param(struct ccdc_config_params_raw *ccdcparam) |
@@ -220,7 +226,7 @@ static int validate_ccdc_param(struct ccdc_config_params_raw *ccdcparam) | |||
220 | if ((ccdcparam->alaw.gama_wd > CCDC_GAMMA_BITS_09_0) || | 226 | if ((ccdcparam->alaw.gama_wd > CCDC_GAMMA_BITS_09_0) || |
221 | (ccdcparam->alaw.gama_wd < CCDC_GAMMA_BITS_15_6) || | 227 | (ccdcparam->alaw.gama_wd < CCDC_GAMMA_BITS_15_6) || |
222 | (ccdcparam->alaw.gama_wd < ccdcparam->data_sz)) { | 228 | (ccdcparam->alaw.gama_wd < ccdcparam->data_sz)) { |
223 | dev_dbg(dev, "\nInvalid data line select"); | 229 | dev_dbg(ccdc_cfg.dev, "\nInvalid data line select"); |
224 | return -1; | 230 | return -1; |
225 | } | 231 | } |
226 | } | 232 | } |
@@ -230,7 +236,7 @@ static int validate_ccdc_param(struct ccdc_config_params_raw *ccdcparam) | |||
230 | static int ccdc_update_raw_params(struct ccdc_config_params_raw *raw_params) | 236 | static int ccdc_update_raw_params(struct ccdc_config_params_raw *raw_params) |
231 | { | 237 | { |
232 | struct ccdc_config_params_raw *config_params = | 238 | struct ccdc_config_params_raw *config_params = |
233 | &ccdc_hw_params_raw.config_params; | 239 | &ccdc_cfg.bayer.config_params; |
234 | unsigned int *fpc_virtaddr = NULL; | 240 | unsigned int *fpc_virtaddr = NULL; |
235 | unsigned int *fpc_physaddr = NULL; | 241 | unsigned int *fpc_physaddr = NULL; |
236 | 242 | ||
@@ -266,7 +272,7 @@ static int ccdc_update_raw_params(struct ccdc_config_params_raw *raw_params) | |||
266 | FP_NUM_BYTES)); | 272 | FP_NUM_BYTES)); |
267 | 273 | ||
268 | if (fpc_virtaddr == NULL) { | 274 | if (fpc_virtaddr == NULL) { |
269 | dev_dbg(dev, | 275 | dev_dbg(ccdc_cfg.dev, |
270 | "\nUnable to allocate memory for FPC"); | 276 | "\nUnable to allocate memory for FPC"); |
271 | return -EFAULT; | 277 | return -EFAULT; |
272 | } | 278 | } |
@@ -279,7 +285,7 @@ static int ccdc_update_raw_params(struct ccdc_config_params_raw *raw_params) | |||
279 | if (copy_from_user(fpc_virtaddr, | 285 | if (copy_from_user(fpc_virtaddr, |
280 | (void __user *)raw_params->fault_pxl.fpc_table_addr, | 286 | (void __user *)raw_params->fault_pxl.fpc_table_addr, |
281 | config_params->fault_pxl.fp_num * FP_NUM_BYTES)) { | 287 | config_params->fault_pxl.fp_num * FP_NUM_BYTES)) { |
282 | dev_dbg(dev, "\n copy_from_user failed"); | 288 | dev_dbg(ccdc_cfg.dev, "\n copy_from_user failed"); |
283 | return -EFAULT; | 289 | return -EFAULT; |
284 | } | 290 | } |
285 | config_params->fault_pxl.fpc_table_addr = (unsigned int)fpc_physaddr; | 291 | config_params->fault_pxl.fpc_table_addr = (unsigned int)fpc_physaddr; |
@@ -289,7 +295,7 @@ static int ccdc_update_raw_params(struct ccdc_config_params_raw *raw_params) | |||
289 | static int ccdc_close(struct device *dev) | 295 | static int ccdc_close(struct device *dev) |
290 | { | 296 | { |
291 | struct ccdc_config_params_raw *config_params = | 297 | struct ccdc_config_params_raw *config_params = |
292 | &ccdc_hw_params_raw.config_params; | 298 | &ccdc_cfg.bayer.config_params; |
293 | unsigned int *fpc_physaddr = NULL, *fpc_virtaddr = NULL; | 299 | unsigned int *fpc_physaddr = NULL, *fpc_virtaddr = NULL; |
294 | 300 | ||
295 | fpc_physaddr = (unsigned int *)config_params->fault_pxl.fpc_table_addr; | 301 | fpc_physaddr = (unsigned int *)config_params->fault_pxl.fpc_table_addr; |
@@ -323,9 +329,8 @@ static void ccdc_restore_defaults(void) | |||
323 | 329 | ||
324 | static int ccdc_open(struct device *device) | 330 | static int ccdc_open(struct device *device) |
325 | { | 331 | { |
326 | dev = device; | ||
327 | ccdc_restore_defaults(); | 332 | ccdc_restore_defaults(); |
328 | if (ccdc_if_type == VPFE_RAW_BAYER) | 333 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) |
329 | ccdc_enable_vport(1); | 334 | ccdc_enable_vport(1); |
330 | return 0; | 335 | return 0; |
331 | } | 336 | } |
@@ -341,12 +346,12 @@ static int ccdc_set_params(void __user *params) | |||
341 | struct ccdc_config_params_raw ccdc_raw_params; | 346 | struct ccdc_config_params_raw ccdc_raw_params; |
342 | int x; | 347 | int x; |
343 | 348 | ||
344 | if (ccdc_if_type != VPFE_RAW_BAYER) | 349 | if (ccdc_cfg.if_type != VPFE_RAW_BAYER) |
345 | return -EINVAL; | 350 | return -EINVAL; |
346 | 351 | ||
347 | x = copy_from_user(&ccdc_raw_params, params, sizeof(ccdc_raw_params)); | 352 | x = copy_from_user(&ccdc_raw_params, params, sizeof(ccdc_raw_params)); |
348 | if (x) { | 353 | if (x) { |
349 | dev_dbg(dev, "ccdc_set_params: error in copying" | 354 | dev_dbg(ccdc_cfg.dev, "ccdc_set_params: error in copying" |
350 | "ccdc params, %d\n", x); | 355 | "ccdc params, %d\n", x); |
351 | return -EFAULT; | 356 | return -EFAULT; |
352 | } | 357 | } |
@@ -364,10 +369,10 @@ static int ccdc_set_params(void __user *params) | |||
364 | */ | 369 | */ |
365 | void ccdc_config_ycbcr(void) | 370 | void ccdc_config_ycbcr(void) |
366 | { | 371 | { |
367 | struct ccdc_params_ycbcr *params = &ccdc_hw_params_ycbcr; | 372 | struct ccdc_params_ycbcr *params = &ccdc_cfg.ycbcr; |
368 | u32 syn_mode; | 373 | u32 syn_mode; |
369 | 374 | ||
370 | dev_dbg(dev, "\nStarting ccdc_config_ycbcr..."); | 375 | dev_dbg(ccdc_cfg.dev, "\nStarting ccdc_config_ycbcr..."); |
371 | /* | 376 | /* |
372 | * first restore the CCDC registers to default values | 377 | * first restore the CCDC registers to default values |
373 | * This is important since we assume default values to be set in | 378 | * This is important since we assume default values to be set in |
@@ -428,7 +433,7 @@ void ccdc_config_ycbcr(void) | |||
428 | regw(CCDC_SDOFST_FIELD_INTERLEAVED, CCDC_SDOFST); | 433 | regw(CCDC_SDOFST_FIELD_INTERLEAVED, CCDC_SDOFST); |
429 | 434 | ||
430 | ccdc_sbl_reset(); | 435 | ccdc_sbl_reset(); |
431 | dev_dbg(dev, "\nEnd of ccdc_config_ycbcr...\n"); | 436 | dev_dbg(ccdc_cfg.dev, "\nEnd of ccdc_config_ycbcr...\n"); |
432 | ccdc_readregs(); | 437 | ccdc_readregs(); |
433 | } | 438 | } |
434 | 439 | ||
@@ -440,9 +445,9 @@ static void ccdc_config_black_clamp(struct ccdc_black_clamp *bclamp) | |||
440 | /* configure DCSub */ | 445 | /* configure DCSub */ |
441 | val = (bclamp->dc_sub) & CCDC_BLK_DC_SUB_MASK; | 446 | val = (bclamp->dc_sub) & CCDC_BLK_DC_SUB_MASK; |
442 | regw(val, CCDC_DCSUB); | 447 | regw(val, CCDC_DCSUB); |
443 | dev_dbg(dev, "\nWriting 0x%x to DCSUB...\n", val); | 448 | dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to DCSUB...\n", val); |
444 | regw(CCDC_CLAMP_DEFAULT_VAL, CCDC_CLAMP); | 449 | regw(CCDC_CLAMP_DEFAULT_VAL, CCDC_CLAMP); |
445 | dev_dbg(dev, "\nWriting 0x0000 to CLAMP...\n"); | 450 | dev_dbg(ccdc_cfg.dev, "\nWriting 0x0000 to CLAMP...\n"); |
446 | return; | 451 | return; |
447 | } | 452 | } |
448 | /* | 453 | /* |
@@ -457,10 +462,10 @@ static void ccdc_config_black_clamp(struct ccdc_black_clamp *bclamp) | |||
457 | ((bclamp->sample_pixel & CCDC_BLK_SAMPLE_LN_MASK) << | 462 | ((bclamp->sample_pixel & CCDC_BLK_SAMPLE_LN_MASK) << |
458 | CCDC_BLK_SAMPLE_LN_SHIFT) | CCDC_BLK_CLAMP_ENABLE); | 463 | CCDC_BLK_SAMPLE_LN_SHIFT) | CCDC_BLK_CLAMP_ENABLE); |
459 | regw(val, CCDC_CLAMP); | 464 | regw(val, CCDC_CLAMP); |
460 | dev_dbg(dev, "\nWriting 0x%x to CLAMP...\n", val); | 465 | dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to CLAMP...\n", val); |
461 | /* If Black clamping is enable then make dcsub 0 */ | 466 | /* If Black clamping is enable then make dcsub 0 */ |
462 | regw(CCDC_DCSUB_DEFAULT_VAL, CCDC_DCSUB); | 467 | regw(CCDC_DCSUB_DEFAULT_VAL, CCDC_DCSUB); |
463 | dev_dbg(dev, "\nWriting 0x00000000 to DCSUB...\n"); | 468 | dev_dbg(ccdc_cfg.dev, "\nWriting 0x00000000 to DCSUB...\n"); |
464 | } | 469 | } |
465 | 470 | ||
466 | static void ccdc_config_black_compense(struct ccdc_black_compensation *bcomp) | 471 | static void ccdc_config_black_compense(struct ccdc_black_compensation *bcomp) |
@@ -490,17 +495,17 @@ static void ccdc_config_fpc(struct ccdc_fault_pixel *fpc) | |||
490 | 495 | ||
491 | /* Configure Fault pixel if needed */ | 496 | /* Configure Fault pixel if needed */ |
492 | regw(fpc->fpc_table_addr, CCDC_FPC_ADDR); | 497 | regw(fpc->fpc_table_addr, CCDC_FPC_ADDR); |
493 | dev_dbg(dev, "\nWriting 0x%x to FPC_ADDR...\n", | 498 | dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to FPC_ADDR...\n", |
494 | (fpc->fpc_table_addr)); | 499 | (fpc->fpc_table_addr)); |
495 | /* Write the FPC params with FPC disable */ | 500 | /* Write the FPC params with FPC disable */ |
496 | val = fpc->fp_num & CCDC_FPC_FPC_NUM_MASK; | 501 | val = fpc->fp_num & CCDC_FPC_FPC_NUM_MASK; |
497 | regw(val, CCDC_FPC); | 502 | regw(val, CCDC_FPC); |
498 | 503 | ||
499 | dev_dbg(dev, "\nWriting 0x%x to FPC...\n", val); | 504 | dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to FPC...\n", val); |
500 | /* read the FPC register */ | 505 | /* read the FPC register */ |
501 | val = regr(CCDC_FPC) | CCDC_FPC_ENABLE; | 506 | val = regr(CCDC_FPC) | CCDC_FPC_ENABLE; |
502 | regw(val, CCDC_FPC); | 507 | regw(val, CCDC_FPC); |
503 | dev_dbg(dev, "\nWriting 0x%x to FPC...\n", val); | 508 | dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to FPC...\n", val); |
504 | } | 509 | } |
505 | 510 | ||
506 | /* | 511 | /* |
@@ -509,13 +514,13 @@ static void ccdc_config_fpc(struct ccdc_fault_pixel *fpc) | |||
509 | */ | 514 | */ |
510 | void ccdc_config_raw(void) | 515 | void ccdc_config_raw(void) |
511 | { | 516 | { |
512 | struct ccdc_params_raw *params = &ccdc_hw_params_raw; | 517 | struct ccdc_params_raw *params = &ccdc_cfg.bayer; |
513 | struct ccdc_config_params_raw *config_params = | 518 | struct ccdc_config_params_raw *config_params = |
514 | &ccdc_hw_params_raw.config_params; | 519 | &ccdc_cfg.bayer.config_params; |
515 | unsigned int syn_mode = 0; | 520 | unsigned int syn_mode = 0; |
516 | unsigned int val; | 521 | unsigned int val; |
517 | 522 | ||
518 | dev_dbg(dev, "\nStarting ccdc_config_raw..."); | 523 | dev_dbg(ccdc_cfg.dev, "\nStarting ccdc_config_raw..."); |
519 | 524 | ||
520 | /* Reset CCDC */ | 525 | /* Reset CCDC */ |
521 | ccdc_restore_defaults(); | 526 | ccdc_restore_defaults(); |
@@ -545,7 +550,7 @@ void ccdc_config_raw(void) | |||
545 | val = ((config_params->alaw.gama_wd & | 550 | val = ((config_params->alaw.gama_wd & |
546 | CCDC_ALAW_GAMA_WD_MASK) | CCDC_ALAW_ENABLE); | 551 | CCDC_ALAW_GAMA_WD_MASK) | CCDC_ALAW_ENABLE); |
547 | regw(val, CCDC_ALAW); | 552 | regw(val, CCDC_ALAW); |
548 | dev_dbg(dev, "\nWriting 0x%x to ALAW...\n", val); | 553 | dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to ALAW...\n", val); |
549 | } | 554 | } |
550 | 555 | ||
551 | /* Configure video window */ | 556 | /* Configure video window */ |
@@ -582,11 +587,11 @@ void ccdc_config_raw(void) | |||
582 | /* Write value in FMTCFG */ | 587 | /* Write value in FMTCFG */ |
583 | regw(val, CCDC_FMTCFG); | 588 | regw(val, CCDC_FMTCFG); |
584 | 589 | ||
585 | dev_dbg(dev, "\nWriting 0x%x to FMTCFG...\n", val); | 590 | dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to FMTCFG...\n", val); |
586 | /* Configure the color pattern according to mt9t001 sensor */ | 591 | /* Configure the color pattern according to mt9t001 sensor */ |
587 | regw(CCDC_COLPTN_VAL, CCDC_COLPTN); | 592 | regw(CCDC_COLPTN_VAL, CCDC_COLPTN); |
588 | 593 | ||
589 | dev_dbg(dev, "\nWriting 0xBB11BB11 to COLPTN...\n"); | 594 | dev_dbg(ccdc_cfg.dev, "\nWriting 0xBB11BB11 to COLPTN...\n"); |
590 | /* | 595 | /* |
591 | * Configure Data formatter(Video port) pixel selection | 596 | * Configure Data formatter(Video port) pixel selection |
592 | * (FMT_HORZ, FMT_VERT) | 597 | * (FMT_HORZ, FMT_VERT) |
@@ -596,7 +601,7 @@ void ccdc_config_raw(void) | |||
596 | (params->win.width & CCDC_FMT_HORZ_FMTLNH_MASK); | 601 | (params->win.width & CCDC_FMT_HORZ_FMTLNH_MASK); |
597 | regw(val, CCDC_FMT_HORZ); | 602 | regw(val, CCDC_FMT_HORZ); |
598 | 603 | ||
599 | dev_dbg(dev, "\nWriting 0x%x to FMT_HORZ...\n", val); | 604 | dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to FMT_HORZ...\n", val); |
600 | val = (params->win.top & CCDC_FMT_VERT_FMTSLV_MASK) | 605 | val = (params->win.top & CCDC_FMT_VERT_FMTSLV_MASK) |
601 | << CCDC_FMT_VERT_FMTSLV_SHIFT; | 606 | << CCDC_FMT_VERT_FMTSLV_SHIFT; |
602 | if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE) | 607 | if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE) |
@@ -604,13 +609,13 @@ void ccdc_config_raw(void) | |||
604 | else | 609 | else |
605 | val |= (params->win.height >> 1) & CCDC_FMT_VERT_FMTLNV_MASK; | 610 | val |= (params->win.height >> 1) & CCDC_FMT_VERT_FMTLNV_MASK; |
606 | 611 | ||
607 | dev_dbg(dev, "\nparams->win.height 0x%x ...\n", | 612 | dev_dbg(ccdc_cfg.dev, "\nparams->win.height 0x%x ...\n", |
608 | params->win.height); | 613 | params->win.height); |
609 | regw(val, CCDC_FMT_VERT); | 614 | regw(val, CCDC_FMT_VERT); |
610 | 615 | ||
611 | dev_dbg(dev, "\nWriting 0x%x to FMT_VERT...\n", val); | 616 | dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to FMT_VERT...\n", val); |
612 | 617 | ||
613 | dev_dbg(dev, "\nbelow regw(val, FMT_VERT)..."); | 618 | dev_dbg(ccdc_cfg.dev, "\nbelow regw(val, FMT_VERT)..."); |
614 | 619 | ||
615 | /* | 620 | /* |
616 | * Configure Horizontal offset register. If pack 8 is enabled then | 621 | * Configure Horizontal offset register. If pack 8 is enabled then |
@@ -631,17 +636,17 @@ void ccdc_config_raw(void) | |||
631 | if (params->image_invert_enable) { | 636 | if (params->image_invert_enable) { |
632 | /* For intelace inverse mode */ | 637 | /* For intelace inverse mode */ |
633 | regw(CCDC_INTERLACED_IMAGE_INVERT, CCDC_SDOFST); | 638 | regw(CCDC_INTERLACED_IMAGE_INVERT, CCDC_SDOFST); |
634 | dev_dbg(dev, "\nWriting 0x4B6D to SDOFST...\n"); | 639 | dev_dbg(ccdc_cfg.dev, "\nWriting 0x4B6D to SDOFST..\n"); |
635 | } | 640 | } |
636 | 641 | ||
637 | else { | 642 | else { |
638 | /* For intelace non inverse mode */ | 643 | /* For intelace non inverse mode */ |
639 | regw(CCDC_INTERLACED_NO_IMAGE_INVERT, CCDC_SDOFST); | 644 | regw(CCDC_INTERLACED_NO_IMAGE_INVERT, CCDC_SDOFST); |
640 | dev_dbg(dev, "\nWriting 0x0249 to SDOFST...\n"); | 645 | dev_dbg(ccdc_cfg.dev, "\nWriting 0x0249 to SDOFST..\n"); |
641 | } | 646 | } |
642 | } else if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE) { | 647 | } else if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE) { |
643 | regw(CCDC_PROGRESSIVE_NO_IMAGE_INVERT, CCDC_SDOFST); | 648 | regw(CCDC_PROGRESSIVE_NO_IMAGE_INVERT, CCDC_SDOFST); |
644 | dev_dbg(dev, "\nWriting 0x0000 to SDOFST...\n"); | 649 | dev_dbg(ccdc_cfg.dev, "\nWriting 0x0000 to SDOFST...\n"); |
645 | } | 650 | } |
646 | 651 | ||
647 | /* | 652 | /* |
@@ -662,18 +667,18 @@ void ccdc_config_raw(void) | |||
662 | val |= (params->win.left) & CCDC_VP_OUT_HORZ_ST_MASK; | 667 | val |= (params->win.left) & CCDC_VP_OUT_HORZ_ST_MASK; |
663 | regw(val, CCDC_VP_OUT); | 668 | regw(val, CCDC_VP_OUT); |
664 | 669 | ||
665 | dev_dbg(dev, "\nWriting 0x%x to VP_OUT...\n", val); | 670 | dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to VP_OUT...\n", val); |
666 | regw(syn_mode, CCDC_SYN_MODE); | 671 | regw(syn_mode, CCDC_SYN_MODE); |
667 | dev_dbg(dev, "\nWriting 0x%x to SYN_MODE...\n", syn_mode); | 672 | dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to SYN_MODE...\n", syn_mode); |
668 | 673 | ||
669 | ccdc_sbl_reset(); | 674 | ccdc_sbl_reset(); |
670 | dev_dbg(dev, "\nend of ccdc_config_raw..."); | 675 | dev_dbg(ccdc_cfg.dev, "\nend of ccdc_config_raw..."); |
671 | ccdc_readregs(); | 676 | ccdc_readregs(); |
672 | } | 677 | } |
673 | 678 | ||
674 | static int ccdc_configure(void) | 679 | static int ccdc_configure(void) |
675 | { | 680 | { |
676 | if (ccdc_if_type == VPFE_RAW_BAYER) | 681 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) |
677 | ccdc_config_raw(); | 682 | ccdc_config_raw(); |
678 | else | 683 | else |
679 | ccdc_config_ycbcr(); | 684 | ccdc_config_ycbcr(); |
@@ -682,24 +687,24 @@ static int ccdc_configure(void) | |||
682 | 687 | ||
683 | static int ccdc_set_buftype(enum ccdc_buftype buf_type) | 688 | static int ccdc_set_buftype(enum ccdc_buftype buf_type) |
684 | { | 689 | { |
685 | if (ccdc_if_type == VPFE_RAW_BAYER) | 690 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) |
686 | ccdc_hw_params_raw.buf_type = buf_type; | 691 | ccdc_cfg.bayer.buf_type = buf_type; |
687 | else | 692 | else |
688 | ccdc_hw_params_ycbcr.buf_type = buf_type; | 693 | ccdc_cfg.ycbcr.buf_type = buf_type; |
689 | return 0; | 694 | return 0; |
690 | } | 695 | } |
691 | 696 | ||
692 | static enum ccdc_buftype ccdc_get_buftype(void) | 697 | static enum ccdc_buftype ccdc_get_buftype(void) |
693 | { | 698 | { |
694 | if (ccdc_if_type == VPFE_RAW_BAYER) | 699 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) |
695 | return ccdc_hw_params_raw.buf_type; | 700 | return ccdc_cfg.bayer.buf_type; |
696 | return ccdc_hw_params_ycbcr.buf_type; | 701 | return ccdc_cfg.ycbcr.buf_type; |
697 | } | 702 | } |
698 | 703 | ||
699 | static int ccdc_enum_pix(u32 *pix, int i) | 704 | static int ccdc_enum_pix(u32 *pix, int i) |
700 | { | 705 | { |
701 | int ret = -EINVAL; | 706 | int ret = -EINVAL; |
702 | if (ccdc_if_type == VPFE_RAW_BAYER) { | 707 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) { |
703 | if (i < ARRAY_SIZE(ccdc_raw_bayer_pix_formats)) { | 708 | if (i < ARRAY_SIZE(ccdc_raw_bayer_pix_formats)) { |
704 | *pix = ccdc_raw_bayer_pix_formats[i]; | 709 | *pix = ccdc_raw_bayer_pix_formats[i]; |
705 | ret = 0; | 710 | ret = 0; |
@@ -715,17 +720,17 @@ static int ccdc_enum_pix(u32 *pix, int i) | |||
715 | 720 | ||
716 | static int ccdc_set_pixel_format(u32 pixfmt) | 721 | static int ccdc_set_pixel_format(u32 pixfmt) |
717 | { | 722 | { |
718 | if (ccdc_if_type == VPFE_RAW_BAYER) { | 723 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) { |
719 | ccdc_hw_params_raw.pix_fmt = CCDC_PIXFMT_RAW; | 724 | ccdc_cfg.bayer.pix_fmt = CCDC_PIXFMT_RAW; |
720 | if (pixfmt == V4L2_PIX_FMT_SBGGR8) | 725 | if (pixfmt == V4L2_PIX_FMT_SBGGR8) |
721 | ccdc_hw_params_raw.config_params.alaw.enable = 1; | 726 | ccdc_cfg.bayer.config_params.alaw.enable = 1; |
722 | else if (pixfmt != V4L2_PIX_FMT_SBGGR16) | 727 | else if (pixfmt != V4L2_PIX_FMT_SBGGR16) |
723 | return -EINVAL; | 728 | return -EINVAL; |
724 | } else { | 729 | } else { |
725 | if (pixfmt == V4L2_PIX_FMT_YUYV) | 730 | if (pixfmt == V4L2_PIX_FMT_YUYV) |
726 | ccdc_hw_params_ycbcr.pix_order = CCDC_PIXORDER_YCBYCR; | 731 | ccdc_cfg.ycbcr.pix_order = CCDC_PIXORDER_YCBYCR; |
727 | else if (pixfmt == V4L2_PIX_FMT_UYVY) | 732 | else if (pixfmt == V4L2_PIX_FMT_UYVY) |
728 | ccdc_hw_params_ycbcr.pix_order = CCDC_PIXORDER_CBYCRY; | 733 | ccdc_cfg.ycbcr.pix_order = CCDC_PIXORDER_CBYCRY; |
729 | else | 734 | else |
730 | return -EINVAL; | 735 | return -EINVAL; |
731 | } | 736 | } |
@@ -734,17 +739,16 @@ static int ccdc_set_pixel_format(u32 pixfmt) | |||
734 | 739 | ||
735 | static u32 ccdc_get_pixel_format(void) | 740 | static u32 ccdc_get_pixel_format(void) |
736 | { | 741 | { |
737 | struct ccdc_a_law *alaw = | 742 | struct ccdc_a_law *alaw = &ccdc_cfg.bayer.config_params.alaw; |
738 | &ccdc_hw_params_raw.config_params.alaw; | ||
739 | u32 pixfmt; | 743 | u32 pixfmt; |
740 | 744 | ||
741 | if (ccdc_if_type == VPFE_RAW_BAYER) | 745 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) |
742 | if (alaw->enable) | 746 | if (alaw->enable) |
743 | pixfmt = V4L2_PIX_FMT_SBGGR8; | 747 | pixfmt = V4L2_PIX_FMT_SBGGR8; |
744 | else | 748 | else |
745 | pixfmt = V4L2_PIX_FMT_SBGGR16; | 749 | pixfmt = V4L2_PIX_FMT_SBGGR16; |
746 | else { | 750 | else { |
747 | if (ccdc_hw_params_ycbcr.pix_order == CCDC_PIXORDER_YCBYCR) | 751 | if (ccdc_cfg.ycbcr.pix_order == CCDC_PIXORDER_YCBYCR) |
748 | pixfmt = V4L2_PIX_FMT_YUYV; | 752 | pixfmt = V4L2_PIX_FMT_YUYV; |
749 | else | 753 | else |
750 | pixfmt = V4L2_PIX_FMT_UYVY; | 754 | pixfmt = V4L2_PIX_FMT_UYVY; |
@@ -754,53 +758,53 @@ static u32 ccdc_get_pixel_format(void) | |||
754 | 758 | ||
755 | static int ccdc_set_image_window(struct v4l2_rect *win) | 759 | static int ccdc_set_image_window(struct v4l2_rect *win) |
756 | { | 760 | { |
757 | if (ccdc_if_type == VPFE_RAW_BAYER) | 761 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) |
758 | ccdc_hw_params_raw.win = *win; | 762 | ccdc_cfg.bayer.win = *win; |
759 | else | 763 | else |
760 | ccdc_hw_params_ycbcr.win = *win; | 764 | ccdc_cfg.ycbcr.win = *win; |
761 | return 0; | 765 | return 0; |
762 | } | 766 | } |
763 | 767 | ||
764 | static void ccdc_get_image_window(struct v4l2_rect *win) | 768 | static void ccdc_get_image_window(struct v4l2_rect *win) |
765 | { | 769 | { |
766 | if (ccdc_if_type == VPFE_RAW_BAYER) | 770 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) |
767 | *win = ccdc_hw_params_raw.win; | 771 | *win = ccdc_cfg.bayer.win; |
768 | else | 772 | else |
769 | *win = ccdc_hw_params_ycbcr.win; | 773 | *win = ccdc_cfg.ycbcr.win; |
770 | } | 774 | } |
771 | 775 | ||
772 | static unsigned int ccdc_get_line_length(void) | 776 | static unsigned int ccdc_get_line_length(void) |
773 | { | 777 | { |
774 | struct ccdc_config_params_raw *config_params = | 778 | struct ccdc_config_params_raw *config_params = |
775 | &ccdc_hw_params_raw.config_params; | 779 | &ccdc_cfg.bayer.config_params; |
776 | unsigned int len; | 780 | unsigned int len; |
777 | 781 | ||
778 | if (ccdc_if_type == VPFE_RAW_BAYER) { | 782 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) { |
779 | if ((config_params->alaw.enable) || | 783 | if ((config_params->alaw.enable) || |
780 | (config_params->data_sz == CCDC_DATA_8BITS)) | 784 | (config_params->data_sz == CCDC_DATA_8BITS)) |
781 | len = ccdc_hw_params_raw.win.width; | 785 | len = ccdc_cfg.bayer.win.width; |
782 | else | 786 | else |
783 | len = ccdc_hw_params_raw.win.width * 2; | 787 | len = ccdc_cfg.bayer.win.width * 2; |
784 | } else | 788 | } else |
785 | len = ccdc_hw_params_ycbcr.win.width * 2; | 789 | len = ccdc_cfg.ycbcr.win.width * 2; |
786 | return ALIGN(len, 32); | 790 | return ALIGN(len, 32); |
787 | } | 791 | } |
788 | 792 | ||
789 | static int ccdc_set_frame_format(enum ccdc_frmfmt frm_fmt) | 793 | static int ccdc_set_frame_format(enum ccdc_frmfmt frm_fmt) |
790 | { | 794 | { |
791 | if (ccdc_if_type == VPFE_RAW_BAYER) | 795 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) |
792 | ccdc_hw_params_raw.frm_fmt = frm_fmt; | 796 | ccdc_cfg.bayer.frm_fmt = frm_fmt; |
793 | else | 797 | else |
794 | ccdc_hw_params_ycbcr.frm_fmt = frm_fmt; | 798 | ccdc_cfg.ycbcr.frm_fmt = frm_fmt; |
795 | return 0; | 799 | return 0; |
796 | } | 800 | } |
797 | 801 | ||
798 | static enum ccdc_frmfmt ccdc_get_frame_format(void) | 802 | static enum ccdc_frmfmt ccdc_get_frame_format(void) |
799 | { | 803 | { |
800 | if (ccdc_if_type == VPFE_RAW_BAYER) | 804 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) |
801 | return ccdc_hw_params_raw.frm_fmt; | 805 | return ccdc_cfg.bayer.frm_fmt; |
802 | else | 806 | else |
803 | return ccdc_hw_params_ycbcr.frm_fmt; | 807 | return ccdc_cfg.ycbcr.frm_fmt; |
804 | } | 808 | } |
805 | 809 | ||
806 | static int ccdc_getfid(void) | 810 | static int ccdc_getfid(void) |
@@ -816,14 +820,14 @@ static inline void ccdc_setfbaddr(unsigned long addr) | |||
816 | 820 | ||
817 | static int ccdc_set_hw_if_params(struct vpfe_hw_if_param *params) | 821 | static int ccdc_set_hw_if_params(struct vpfe_hw_if_param *params) |
818 | { | 822 | { |
819 | ccdc_if_type = params->if_type; | 823 | ccdc_cfg.if_type = params->if_type; |
820 | 824 | ||
821 | switch (params->if_type) { | 825 | switch (params->if_type) { |
822 | case VPFE_BT656: | 826 | case VPFE_BT656: |
823 | case VPFE_YCBCR_SYNC_16: | 827 | case VPFE_YCBCR_SYNC_16: |
824 | case VPFE_YCBCR_SYNC_8: | 828 | case VPFE_YCBCR_SYNC_8: |
825 | ccdc_hw_params_ycbcr.vd_pol = params->vdpol; | 829 | ccdc_cfg.ycbcr.vd_pol = params->vdpol; |
826 | ccdc_hw_params_ycbcr.hd_pol = params->hdpol; | 830 | ccdc_cfg.ycbcr.hd_pol = params->hdpol; |
827 | break; | 831 | break; |
828 | default: | 832 | default: |
829 | /* TODO add support for raw bayer here */ | 833 | /* TODO add support for raw bayer here */ |
@@ -838,7 +842,6 @@ static struct ccdc_hw_device ccdc_hw_dev = { | |||
838 | .hw_ops = { | 842 | .hw_ops = { |
839 | .open = ccdc_open, | 843 | .open = ccdc_open, |
840 | .close = ccdc_close, | 844 | .close = ccdc_close, |
841 | .set_ccdc_base = ccdc_set_ccdc_base, | ||
842 | .reset = ccdc_sbl_reset, | 845 | .reset = ccdc_sbl_reset, |
843 | .enable = ccdc_enable, | 846 | .enable = ccdc_enable, |
844 | .set_hw_if_params = ccdc_set_hw_if_params, | 847 | .set_hw_if_params = ccdc_set_hw_if_params, |
@@ -859,19 +862,105 @@ static struct ccdc_hw_device ccdc_hw_dev = { | |||
859 | }, | 862 | }, |
860 | }; | 863 | }; |
861 | 864 | ||
862 | static int __init dm644x_ccdc_init(void) | 865 | static int __init dm644x_ccdc_probe(struct platform_device *pdev) |
863 | { | 866 | { |
864 | printk(KERN_NOTICE "dm644x_ccdc_init\n"); | 867 | struct resource *res; |
865 | if (vpfe_register_ccdc_device(&ccdc_hw_dev) < 0) | 868 | int status = 0; |
866 | return -1; | 869 | |
867 | printk(KERN_NOTICE "%s is registered with vpfe.\n", | 870 | /* |
868 | ccdc_hw_dev.name); | 871 | * first try to register with vpfe. If not correct platform, then we |
872 | * don't have to iomap | ||
873 | */ | ||
874 | status = vpfe_register_ccdc_device(&ccdc_hw_dev); | ||
875 | if (status < 0) | ||
876 | return status; | ||
877 | |||
878 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
879 | if (!res) { | ||
880 | status = -ENODEV; | ||
881 | goto fail_nores; | ||
882 | } | ||
883 | |||
884 | res = request_mem_region(res->start, resource_size(res), res->name); | ||
885 | if (!res) { | ||
886 | status = -EBUSY; | ||
887 | goto fail_nores; | ||
888 | } | ||
889 | |||
890 | ccdc_cfg.base_addr = ioremap_nocache(res->start, resource_size(res)); | ||
891 | if (!ccdc_cfg.base_addr) { | ||
892 | status = -ENOMEM; | ||
893 | goto fail_nomem; | ||
894 | } | ||
895 | |||
896 | /* Get and enable Master clock */ | ||
897 | ccdc_cfg.mclk = clk_get(&pdev->dev, "master"); | ||
898 | if (IS_ERR(ccdc_cfg.mclk)) { | ||
899 | status = PTR_ERR(ccdc_cfg.mclk); | ||
900 | goto fail_nomap; | ||
901 | } | ||
902 | if (clk_enable(ccdc_cfg.mclk)) { | ||
903 | status = -ENODEV; | ||
904 | goto fail_mclk; | ||
905 | } | ||
906 | |||
907 | /* Get and enable Slave clock */ | ||
908 | ccdc_cfg.sclk = clk_get(&pdev->dev, "slave"); | ||
909 | if (IS_ERR(ccdc_cfg.sclk)) { | ||
910 | status = PTR_ERR(ccdc_cfg.sclk); | ||
911 | goto fail_mclk; | ||
912 | } | ||
913 | if (clk_enable(ccdc_cfg.sclk)) { | ||
914 | status = -ENODEV; | ||
915 | goto fail_sclk; | ||
916 | } | ||
917 | ccdc_cfg.dev = &pdev->dev; | ||
918 | printk(KERN_NOTICE "%s is registered with vpfe.\n", ccdc_hw_dev.name); | ||
869 | return 0; | 919 | return 0; |
920 | fail_sclk: | ||
921 | clk_put(ccdc_cfg.sclk); | ||
922 | fail_mclk: | ||
923 | clk_put(ccdc_cfg.mclk); | ||
924 | fail_nomap: | ||
925 | iounmap(ccdc_cfg.base_addr); | ||
926 | fail_nomem: | ||
927 | release_mem_region(res->start, resource_size(res)); | ||
928 | fail_nores: | ||
929 | vpfe_unregister_ccdc_device(&ccdc_hw_dev); | ||
930 | return status; | ||
870 | } | 931 | } |
871 | 932 | ||
872 | static void __exit dm644x_ccdc_exit(void) | 933 | static int dm644x_ccdc_remove(struct platform_device *pdev) |
873 | { | 934 | { |
935 | struct resource *res; | ||
936 | |||
937 | clk_put(ccdc_cfg.mclk); | ||
938 | clk_put(ccdc_cfg.sclk); | ||
939 | iounmap(ccdc_cfg.base_addr); | ||
940 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
941 | if (res) | ||
942 | release_mem_region(res->start, resource_size(res)); | ||
874 | vpfe_unregister_ccdc_device(&ccdc_hw_dev); | 943 | vpfe_unregister_ccdc_device(&ccdc_hw_dev); |
944 | return 0; | ||
945 | } | ||
946 | |||
947 | static struct platform_driver dm644x_ccdc_driver = { | ||
948 | .driver = { | ||
949 | .name = "dm644x_ccdc", | ||
950 | .owner = THIS_MODULE, | ||
951 | }, | ||
952 | .remove = __devexit_p(dm644x_ccdc_remove), | ||
953 | .probe = dm644x_ccdc_probe, | ||
954 | }; | ||
955 | |||
956 | static int __init dm644x_ccdc_init(void) | ||
957 | { | ||
958 | return platform_driver_register(&dm644x_ccdc_driver); | ||
959 | } | ||
960 | |||
961 | static void __exit dm644x_ccdc_exit(void) | ||
962 | { | ||
963 | platform_driver_unregister(&dm644x_ccdc_driver); | ||
875 | } | 964 | } |
876 | 965 | ||
877 | module_init(dm644x_ccdc_init); | 966 | module_init(dm644x_ccdc_init); |
diff --git a/drivers/media/video/davinci/isif.c b/drivers/media/video/davinci/isif.c new file mode 100644 index 000000000000..29c29c668596 --- /dev/null +++ b/drivers/media/video/davinci/isif.c | |||
@@ -0,0 +1,1172 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2008-2009 Texas Instruments Inc | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
17 | * | ||
18 | * Image Sensor Interface (ISIF) driver | ||
19 | * | ||
20 | * This driver is for configuring the ISIF IP available on DM365 or any other | ||
21 | * TI SoCs. This is used for capturing yuv or bayer video or image data | ||
22 | * from a decoder or sensor. This IP is similar to the CCDC IP on DM355 | ||
23 | * and DM6446, but with enhanced or additional ip blocks. The driver | ||
24 | * configures the ISIF upon commands from the vpfe bridge driver through | ||
25 | * ccdc_hw_device interface. | ||
26 | * | ||
27 | * TODO: 1) Raw bayer parameter settings and bayer capture | ||
28 | * 2) Add support for control ioctl | ||
29 | */ | ||
30 | #include <linux/delay.h> | ||
31 | #include <linux/platform_device.h> | ||
32 | #include <linux/uaccess.h> | ||
33 | #include <linux/io.h> | ||
34 | #include <linux/videodev2.h> | ||
35 | #include <linux/clk.h> | ||
36 | #include <linux/err.h> | ||
37 | |||
38 | #include <mach/mux.h> | ||
39 | |||
40 | #include <media/davinci/isif.h> | ||
41 | #include <media/davinci/vpss.h> | ||
42 | |||
43 | #include "isif_regs.h" | ||
44 | #include "ccdc_hw_device.h" | ||
45 | |||
46 | /* Defaults for module configuration parameters */ | ||
47 | static struct isif_config_params_raw isif_config_defaults = { | ||
48 | .linearize = { | ||
49 | .en = 0, | ||
50 | .corr_shft = ISIF_NO_SHIFT, | ||
51 | .scale_fact = {1, 0}, | ||
52 | }, | ||
53 | .df_csc = { | ||
54 | .df_or_csc = 0, | ||
55 | .csc = { | ||
56 | .en = 0, | ||
57 | }, | ||
58 | }, | ||
59 | .dfc = { | ||
60 | .en = 0, | ||
61 | }, | ||
62 | .bclamp = { | ||
63 | .en = 0, | ||
64 | }, | ||
65 | .gain_offset = { | ||
66 | .gain = { | ||
67 | .r_ye = {1, 0}, | ||
68 | .gr_cy = {1, 0}, | ||
69 | .gb_g = {1, 0}, | ||
70 | .b_mg = {1, 0}, | ||
71 | }, | ||
72 | }, | ||
73 | .culling = { | ||
74 | .hcpat_odd = 0xff, | ||
75 | .hcpat_even = 0xff, | ||
76 | .vcpat = 0xff, | ||
77 | }, | ||
78 | .compress = { | ||
79 | .alg = ISIF_ALAW, | ||
80 | }, | ||
81 | }; | ||
82 | |||
83 | /* ISIF operation configuration */ | ||
84 | static struct isif_oper_config { | ||
85 | struct device *dev; | ||
86 | enum vpfe_hw_if_type if_type; | ||
87 | struct isif_ycbcr_config ycbcr; | ||
88 | struct isif_params_raw bayer; | ||
89 | enum isif_data_pack data_pack; | ||
90 | /* Master clock */ | ||
91 | struct clk *mclk; | ||
92 | /* ISIF base address */ | ||
93 | void __iomem *base_addr; | ||
94 | /* ISIF Linear Table 0 */ | ||
95 | void __iomem *linear_tbl0_addr; | ||
96 | /* ISIF Linear Table 1 */ | ||
97 | void __iomem *linear_tbl1_addr; | ||
98 | } isif_cfg = { | ||
99 | .ycbcr = { | ||
100 | .pix_fmt = CCDC_PIXFMT_YCBCR_8BIT, | ||
101 | .frm_fmt = CCDC_FRMFMT_INTERLACED, | ||
102 | .win = ISIF_WIN_NTSC, | ||
103 | .fid_pol = VPFE_PINPOL_POSITIVE, | ||
104 | .vd_pol = VPFE_PINPOL_POSITIVE, | ||
105 | .hd_pol = VPFE_PINPOL_POSITIVE, | ||
106 | .pix_order = CCDC_PIXORDER_CBYCRY, | ||
107 | .buf_type = CCDC_BUFTYPE_FLD_INTERLEAVED, | ||
108 | }, | ||
109 | .bayer = { | ||
110 | .pix_fmt = CCDC_PIXFMT_RAW, | ||
111 | .frm_fmt = CCDC_FRMFMT_PROGRESSIVE, | ||
112 | .win = ISIF_WIN_VGA, | ||
113 | .fid_pol = VPFE_PINPOL_POSITIVE, | ||
114 | .vd_pol = VPFE_PINPOL_POSITIVE, | ||
115 | .hd_pol = VPFE_PINPOL_POSITIVE, | ||
116 | .gain = { | ||
117 | .r_ye = {1, 0}, | ||
118 | .gr_cy = {1, 0}, | ||
119 | .gb_g = {1, 0}, | ||
120 | .b_mg = {1, 0}, | ||
121 | }, | ||
122 | .cfa_pat = ISIF_CFA_PAT_MOSAIC, | ||
123 | .data_msb = ISIF_BIT_MSB_11, | ||
124 | .config_params = { | ||
125 | .data_shift = ISIF_NO_SHIFT, | ||
126 | .col_pat_field0 = { | ||
127 | .olop = ISIF_GREEN_BLUE, | ||
128 | .olep = ISIF_BLUE, | ||
129 | .elop = ISIF_RED, | ||
130 | .elep = ISIF_GREEN_RED, | ||
131 | }, | ||
132 | .col_pat_field1 = { | ||
133 | .olop = ISIF_GREEN_BLUE, | ||
134 | .olep = ISIF_BLUE, | ||
135 | .elop = ISIF_RED, | ||
136 | .elep = ISIF_GREEN_RED, | ||
137 | }, | ||
138 | .test_pat_gen = 0, | ||
139 | }, | ||
140 | }, | ||
141 | .data_pack = ISIF_DATA_PACK8, | ||
142 | }; | ||
143 | |||
144 | /* Raw Bayer formats */ | ||
145 | static const u32 isif_raw_bayer_pix_formats[] = { | ||
146 | V4L2_PIX_FMT_SBGGR8, V4L2_PIX_FMT_SBGGR16}; | ||
147 | |||
148 | /* Raw YUV formats */ | ||
149 | static const u32 isif_raw_yuv_pix_formats[] = { | ||
150 | V4L2_PIX_FMT_UYVY, V4L2_PIX_FMT_YUYV}; | ||
151 | |||
152 | /* register access routines */ | ||
153 | static inline u32 regr(u32 offset) | ||
154 | { | ||
155 | return __raw_readl(isif_cfg.base_addr + offset); | ||
156 | } | ||
157 | |||
158 | static inline void regw(u32 val, u32 offset) | ||
159 | { | ||
160 | __raw_writel(val, isif_cfg.base_addr + offset); | ||
161 | } | ||
162 | |||
163 | /* reg_modify() - read, modify and write register */ | ||
164 | static inline u32 reg_modify(u32 mask, u32 val, u32 offset) | ||
165 | { | ||
166 | u32 new_val = (regr(offset) & ~mask) | (val & mask); | ||
167 | |||
168 | regw(new_val, offset); | ||
169 | return new_val; | ||
170 | } | ||
171 | |||
172 | static inline void regw_lin_tbl(u32 val, u32 offset, int i) | ||
173 | { | ||
174 | if (!i) | ||
175 | __raw_writel(val, isif_cfg.linear_tbl0_addr + offset); | ||
176 | else | ||
177 | __raw_writel(val, isif_cfg.linear_tbl1_addr + offset); | ||
178 | } | ||
179 | |||
180 | static void isif_disable_all_modules(void) | ||
181 | { | ||
182 | /* disable BC */ | ||
183 | regw(0, CLAMPCFG); | ||
184 | /* disable vdfc */ | ||
185 | regw(0, DFCCTL); | ||
186 | /* disable CSC */ | ||
187 | regw(0, CSCCTL); | ||
188 | /* disable linearization */ | ||
189 | regw(0, LINCFG0); | ||
190 | /* disable other modules here as they are supported */ | ||
191 | } | ||
192 | |||
193 | static void isif_enable(int en) | ||
194 | { | ||
195 | if (!en) { | ||
196 | /* Before disable isif, disable all ISIF modules */ | ||
197 | isif_disable_all_modules(); | ||
198 | /* | ||
199 | * wait for next VD. Assume lowest scan rate is 12 Hz. So | ||
200 | * 100 msec delay is good enough | ||
201 | */ | ||
202 | msleep(100); | ||
203 | } | ||
204 | reg_modify(ISIF_SYNCEN_VDHDEN_MASK, en, SYNCEN); | ||
205 | } | ||
206 | |||
207 | static void isif_enable_output_to_sdram(int en) | ||
208 | { | ||
209 | reg_modify(ISIF_SYNCEN_WEN_MASK, en << ISIF_SYNCEN_WEN_SHIFT, SYNCEN); | ||
210 | } | ||
211 | |||
212 | static void isif_config_culling(struct isif_cul *cul) | ||
213 | { | ||
214 | u32 val; | ||
215 | |||
216 | /* Horizontal pattern */ | ||
217 | val = (cul->hcpat_even << CULL_PAT_EVEN_LINE_SHIFT) | cul->hcpat_odd; | ||
218 | regw(val, CULH); | ||
219 | |||
220 | /* vertical pattern */ | ||
221 | regw(cul->vcpat, CULV); | ||
222 | |||
223 | /* LPF */ | ||
224 | reg_modify(ISIF_LPF_MASK << ISIF_LPF_SHIFT, | ||
225 | cul->en_lpf << ISIF_LPF_SHIFT, MODESET); | ||
226 | } | ||
227 | |||
228 | static void isif_config_gain_offset(void) | ||
229 | { | ||
230 | struct isif_gain_offsets_adj *gain_off_p = | ||
231 | &isif_cfg.bayer.config_params.gain_offset; | ||
232 | u32 val; | ||
233 | |||
234 | val = (!!gain_off_p->gain_sdram_en << GAIN_SDRAM_EN_SHIFT) | | ||
235 | (!!gain_off_p->gain_ipipe_en << GAIN_IPIPE_EN_SHIFT) | | ||
236 | (!!gain_off_p->gain_h3a_en << GAIN_H3A_EN_SHIFT) | | ||
237 | (!!gain_off_p->offset_sdram_en << OFST_SDRAM_EN_SHIFT) | | ||
238 | (!!gain_off_p->offset_ipipe_en << OFST_IPIPE_EN_SHIFT) | | ||
239 | (!!gain_off_p->offset_h3a_en << OFST_H3A_EN_SHIFT); | ||
240 | |||
241 | reg_modify(GAIN_OFFSET_EN_MASK, val, CGAMMAWD); | ||
242 | |||
243 | val = (gain_off_p->gain.r_ye.integer << GAIN_INTEGER_SHIFT) | | ||
244 | gain_off_p->gain.r_ye.decimal; | ||
245 | regw(val, CRGAIN); | ||
246 | |||
247 | val = (gain_off_p->gain.gr_cy.integer << GAIN_INTEGER_SHIFT) | | ||
248 | gain_off_p->gain.gr_cy.decimal; | ||
249 | regw(val, CGRGAIN); | ||
250 | |||
251 | val = (gain_off_p->gain.gb_g.integer << GAIN_INTEGER_SHIFT) | | ||
252 | gain_off_p->gain.gb_g.decimal; | ||
253 | regw(val, CGBGAIN); | ||
254 | |||
255 | val = (gain_off_p->gain.b_mg.integer << GAIN_INTEGER_SHIFT) | | ||
256 | gain_off_p->gain.b_mg.decimal; | ||
257 | regw(val, CBGAIN); | ||
258 | |||
259 | regw(gain_off_p->offset, COFSTA); | ||
260 | } | ||
261 | |||
262 | static void isif_restore_defaults(void) | ||
263 | { | ||
264 | enum vpss_ccdc_source_sel source = VPSS_CCDCIN; | ||
265 | |||
266 | dev_dbg(isif_cfg.dev, "\nstarting isif_restore_defaults..."); | ||
267 | isif_cfg.bayer.config_params = isif_config_defaults; | ||
268 | /* Enable clock to ISIF, IPIPEIF and BL */ | ||
269 | vpss_enable_clock(VPSS_CCDC_CLOCK, 1); | ||
270 | vpss_enable_clock(VPSS_IPIPEIF_CLOCK, 1); | ||
271 | vpss_enable_clock(VPSS_BL_CLOCK, 1); | ||
272 | /* Set default offset and gain */ | ||
273 | isif_config_gain_offset(); | ||
274 | vpss_select_ccdc_source(source); | ||
275 | dev_dbg(isif_cfg.dev, "\nEnd of isif_restore_defaults..."); | ||
276 | } | ||
277 | |||
278 | static int isif_open(struct device *device) | ||
279 | { | ||
280 | isif_restore_defaults(); | ||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | /* This function will configure the window size to be capture in ISIF reg */ | ||
285 | static void isif_setwin(struct v4l2_rect *image_win, | ||
286 | enum ccdc_frmfmt frm_fmt, int ppc) | ||
287 | { | ||
288 | int horz_start, horz_nr_pixels; | ||
289 | int vert_start, vert_nr_lines; | ||
290 | int mid_img = 0; | ||
291 | |||
292 | dev_dbg(isif_cfg.dev, "\nStarting isif_setwin..."); | ||
293 | /* | ||
294 | * ppc - per pixel count. indicates how many pixels per cell | ||
295 | * output to SDRAM. example, for ycbcr, it is one y and one c, so 2. | ||
296 | * raw capture this is 1 | ||
297 | */ | ||
298 | horz_start = image_win->left << (ppc - 1); | ||
299 | horz_nr_pixels = ((image_win->width) << (ppc - 1)) - 1; | ||
300 | |||
301 | /* Writing the horizontal info into the registers */ | ||
302 | regw(horz_start & START_PX_HOR_MASK, SPH); | ||
303 | regw(horz_nr_pixels & NUM_PX_HOR_MASK, LNH); | ||
304 | vert_start = image_win->top; | ||
305 | |||
306 | if (frm_fmt == CCDC_FRMFMT_INTERLACED) { | ||
307 | vert_nr_lines = (image_win->height >> 1) - 1; | ||
308 | vert_start >>= 1; | ||
309 | /* To account for VD since line 0 doesn't have any data */ | ||
310 | vert_start += 1; | ||
311 | } else { | ||
312 | /* To account for VD since line 0 doesn't have any data */ | ||
313 | vert_start += 1; | ||
314 | vert_nr_lines = image_win->height - 1; | ||
315 | /* configure VDINT0 and VDINT1 */ | ||
316 | mid_img = vert_start + (image_win->height / 2); | ||
317 | regw(mid_img, VDINT1); | ||
318 | } | ||
319 | |||
320 | regw(0, VDINT0); | ||
321 | regw(vert_start & START_VER_ONE_MASK, SLV0); | ||
322 | regw(vert_start & START_VER_TWO_MASK, SLV1); | ||
323 | regw(vert_nr_lines & NUM_LINES_VER, LNV); | ||
324 | } | ||
325 | |||
326 | static void isif_config_bclamp(struct isif_black_clamp *bc) | ||
327 | { | ||
328 | u32 val; | ||
329 | |||
330 | /* | ||
331 | * DC Offset is always added to image data irrespective of bc enable | ||
332 | * status | ||
333 | */ | ||
334 | regw(bc->dc_offset, CLDCOFST); | ||
335 | |||
336 | if (bc->en) { | ||
337 | val = bc->bc_mode_color << ISIF_BC_MODE_COLOR_SHIFT; | ||
338 | |||
339 | /* Enable BC and horizontal clamp caculation paramaters */ | ||
340 | val = val | 1 | (bc->horz.mode << ISIF_HORZ_BC_MODE_SHIFT); | ||
341 | |||
342 | regw(val, CLAMPCFG); | ||
343 | |||
344 | if (bc->horz.mode != ISIF_HORZ_BC_DISABLE) { | ||
345 | /* | ||
346 | * Window count for calculation | ||
347 | * Base window selection | ||
348 | * pixel limit | ||
349 | * Horizontal size of window | ||
350 | * vertical size of the window | ||
351 | * Horizontal start position of the window | ||
352 | * Vertical start position of the window | ||
353 | */ | ||
354 | val = bc->horz.win_count_calc | | ||
355 | ((!!bc->horz.base_win_sel_calc) << | ||
356 | ISIF_HORZ_BC_WIN_SEL_SHIFT) | | ||
357 | ((!!bc->horz.clamp_pix_limit) << | ||
358 | ISIF_HORZ_BC_PIX_LIMIT_SHIFT) | | ||
359 | (bc->horz.win_h_sz_calc << | ||
360 | ISIF_HORZ_BC_WIN_H_SIZE_SHIFT) | | ||
361 | (bc->horz.win_v_sz_calc << | ||
362 | ISIF_HORZ_BC_WIN_V_SIZE_SHIFT); | ||
363 | regw(val, CLHWIN0); | ||
364 | |||
365 | regw(bc->horz.win_start_h_calc, CLHWIN1); | ||
366 | regw(bc->horz.win_start_v_calc, CLHWIN2); | ||
367 | } | ||
368 | |||
369 | /* vertical clamp caculation paramaters */ | ||
370 | |||
371 | /* Reset clamp value sel for previous line */ | ||
372 | val |= | ||
373 | (bc->vert.reset_val_sel << ISIF_VERT_BC_RST_VAL_SEL_SHIFT) | | ||
374 | (bc->vert.line_ave_coef << ISIF_VERT_BC_LINE_AVE_COEF_SHIFT); | ||
375 | regw(val, CLVWIN0); | ||
376 | |||
377 | /* Optical Black horizontal start position */ | ||
378 | regw(bc->vert.ob_start_h, CLVWIN1); | ||
379 | /* Optical Black vertical start position */ | ||
380 | regw(bc->vert.ob_start_v, CLVWIN2); | ||
381 | /* Optical Black vertical size for calculation */ | ||
382 | regw(bc->vert.ob_v_sz_calc, CLVWIN3); | ||
383 | /* Vertical start position for BC subtraction */ | ||
384 | regw(bc->vert_start_sub, CLSV); | ||
385 | } | ||
386 | } | ||
387 | |||
388 | static void isif_config_linearization(struct isif_linearize *linearize) | ||
389 | { | ||
390 | u32 val, i; | ||
391 | |||
392 | if (!linearize->en) { | ||
393 | regw(0, LINCFG0); | ||
394 | return; | ||
395 | } | ||
396 | |||
397 | /* shift value for correction & enable linearization (set lsb) */ | ||
398 | val = (linearize->corr_shft << ISIF_LIN_CORRSFT_SHIFT) | 1; | ||
399 | regw(val, LINCFG0); | ||
400 | |||
401 | /* Scale factor */ | ||
402 | val = ((!!linearize->scale_fact.integer) << | ||
403 | ISIF_LIN_SCALE_FACT_INTEG_SHIFT) | | ||
404 | linearize->scale_fact.decimal; | ||
405 | regw(val, LINCFG1); | ||
406 | |||
407 | for (i = 0; i < ISIF_LINEAR_TAB_SIZE; i++) { | ||
408 | if (i % 2) | ||
409 | regw_lin_tbl(linearize->table[i], ((i >> 1) << 2), 1); | ||
410 | else | ||
411 | regw_lin_tbl(linearize->table[i], ((i >> 1) << 2), 0); | ||
412 | } | ||
413 | } | ||
414 | |||
415 | static int isif_config_dfc(struct isif_dfc *vdfc) | ||
416 | { | ||
417 | /* initialize retries to loop for max ~ 250 usec */ | ||
418 | u32 val, count, retries = loops_per_jiffy / (4000/HZ); | ||
419 | int i; | ||
420 | |||
421 | if (!vdfc->en) | ||
422 | return 0; | ||
423 | |||
424 | /* Correction mode */ | ||
425 | val = (vdfc->corr_mode << ISIF_VDFC_CORR_MOD_SHIFT); | ||
426 | |||
427 | /* Correct whole line or partial */ | ||
428 | if (vdfc->corr_whole_line) | ||
429 | val |= 1 << ISIF_VDFC_CORR_WHOLE_LN_SHIFT; | ||
430 | |||
431 | /* level shift value */ | ||
432 | val |= vdfc->def_level_shift << ISIF_VDFC_LEVEL_SHFT_SHIFT; | ||
433 | |||
434 | regw(val, DFCCTL); | ||
435 | |||
436 | /* Defect saturation level */ | ||
437 | regw(vdfc->def_sat_level, VDFSATLV); | ||
438 | |||
439 | regw(vdfc->table[0].pos_vert, DFCMEM0); | ||
440 | regw(vdfc->table[0].pos_horz, DFCMEM1); | ||
441 | if (vdfc->corr_mode == ISIF_VDFC_NORMAL || | ||
442 | vdfc->corr_mode == ISIF_VDFC_HORZ_INTERPOL_IF_SAT) { | ||
443 | regw(vdfc->table[0].level_at_pos, DFCMEM2); | ||
444 | regw(vdfc->table[0].level_up_pixels, DFCMEM3); | ||
445 | regw(vdfc->table[0].level_low_pixels, DFCMEM4); | ||
446 | } | ||
447 | |||
448 | /* set DFCMARST and set DFCMWR */ | ||
449 | val = regr(DFCMEMCTL) | (1 << ISIF_DFCMEMCTL_DFCMARST_SHIFT) | 1; | ||
450 | regw(val, DFCMEMCTL); | ||
451 | |||
452 | count = retries; | ||
453 | while (count && (regr(DFCMEMCTL) & 0x1)) | ||
454 | count--; | ||
455 | |||
456 | if (!count) { | ||
457 | dev_dbg(isif_cfg.dev, "defect table write timeout !!!\n"); | ||
458 | return -1; | ||
459 | } | ||
460 | |||
461 | for (i = 1; i < vdfc->num_vdefects; i++) { | ||
462 | regw(vdfc->table[i].pos_vert, DFCMEM0); | ||
463 | regw(vdfc->table[i].pos_horz, DFCMEM1); | ||
464 | if (vdfc->corr_mode == ISIF_VDFC_NORMAL || | ||
465 | vdfc->corr_mode == ISIF_VDFC_HORZ_INTERPOL_IF_SAT) { | ||
466 | regw(vdfc->table[i].level_at_pos, DFCMEM2); | ||
467 | regw(vdfc->table[i].level_up_pixels, DFCMEM3); | ||
468 | regw(vdfc->table[i].level_low_pixels, DFCMEM4); | ||
469 | } | ||
470 | val = regr(DFCMEMCTL); | ||
471 | /* clear DFCMARST and set DFCMWR */ | ||
472 | val &= ~BIT(ISIF_DFCMEMCTL_DFCMARST_SHIFT); | ||
473 | val |= 1; | ||
474 | regw(val, DFCMEMCTL); | ||
475 | |||
476 | count = retries; | ||
477 | while (count && (regr(DFCMEMCTL) & 0x1)) | ||
478 | count--; | ||
479 | |||
480 | if (!count) { | ||
481 | dev_err(isif_cfg.dev, | ||
482 | "defect table write timeout !!!\n"); | ||
483 | return -1; | ||
484 | } | ||
485 | } | ||
486 | if (vdfc->num_vdefects < ISIF_VDFC_TABLE_SIZE) { | ||
487 | /* Extra cycle needed */ | ||
488 | regw(0, DFCMEM0); | ||
489 | regw(0x1FFF, DFCMEM1); | ||
490 | regw(1, DFCMEMCTL); | ||
491 | } | ||
492 | |||
493 | /* enable VDFC */ | ||
494 | reg_modify((1 << ISIF_VDFC_EN_SHIFT), (1 << ISIF_VDFC_EN_SHIFT), | ||
495 | DFCCTL); | ||
496 | return 0; | ||
497 | } | ||
498 | |||
499 | static void isif_config_csc(struct isif_df_csc *df_csc) | ||
500 | { | ||
501 | u32 val1 = 0, val2 = 0, i; | ||
502 | |||
503 | if (!df_csc->csc.en) { | ||
504 | regw(0, CSCCTL); | ||
505 | return; | ||
506 | } | ||
507 | for (i = 0; i < ISIF_CSC_NUM_COEFF; i++) { | ||
508 | if ((i % 2) == 0) { | ||
509 | /* CSCM - LSB */ | ||
510 | val1 = (df_csc->csc.coeff[i].integer << | ||
511 | ISIF_CSC_COEF_INTEG_SHIFT) | | ||
512 | df_csc->csc.coeff[i].decimal; | ||
513 | } else { | ||
514 | |||
515 | /* CSCM - MSB */ | ||
516 | val2 = (df_csc->csc.coeff[i].integer << | ||
517 | ISIF_CSC_COEF_INTEG_SHIFT) | | ||
518 | df_csc->csc.coeff[i].decimal; | ||
519 | val2 <<= ISIF_CSCM_MSB_SHIFT; | ||
520 | val2 |= val1; | ||
521 | regw(val2, (CSCM0 + ((i - 1) << 1))); | ||
522 | } | ||
523 | } | ||
524 | |||
525 | /* program the active area */ | ||
526 | regw(df_csc->start_pix, FMTSPH); | ||
527 | /* | ||
528 | * one extra pixel as required for CSC. Actually number of | ||
529 | * pixel - 1 should be configured in this register. So we | ||
530 | * need to subtract 1 before writing to FMTSPH, but we will | ||
531 | * not do this since csc requires one extra pixel | ||
532 | */ | ||
533 | regw(df_csc->num_pixels, FMTLNH); | ||
534 | regw(df_csc->start_line, FMTSLV); | ||
535 | /* | ||
536 | * one extra line as required for CSC. See reason documented for | ||
537 | * num_pixels | ||
538 | */ | ||
539 | regw(df_csc->num_lines, FMTLNV); | ||
540 | |||
541 | /* Enable CSC */ | ||
542 | regw(1, CSCCTL); | ||
543 | } | ||
544 | |||
545 | static int isif_config_raw(void) | ||
546 | { | ||
547 | struct isif_params_raw *params = &isif_cfg.bayer; | ||
548 | struct isif_config_params_raw *module_params = | ||
549 | &isif_cfg.bayer.config_params; | ||
550 | struct vpss_pg_frame_size frame_size; | ||
551 | struct vpss_sync_pol sync; | ||
552 | u32 val; | ||
553 | |||
554 | dev_dbg(isif_cfg.dev, "\nStarting isif_config_raw..\n"); | ||
555 | |||
556 | /* | ||
557 | * Configure CCDCFG register:- | ||
558 | * Set CCD Not to swap input since input is RAW data | ||
559 | * Set FID detection function to Latch at V-Sync | ||
560 | * Set WENLOG - isif valid area | ||
561 | * Set TRGSEL | ||
562 | * Set EXTRG | ||
563 | * Packed to 8 or 16 bits | ||
564 | */ | ||
565 | |||
566 | val = ISIF_YCINSWP_RAW | ISIF_CCDCFG_FIDMD_LATCH_VSYNC | | ||
567 | ISIF_CCDCFG_WENLOG_AND | ISIF_CCDCFG_TRGSEL_WEN | | ||
568 | ISIF_CCDCFG_EXTRG_DISABLE | isif_cfg.data_pack; | ||
569 | |||
570 | dev_dbg(isif_cfg.dev, "Writing 0x%x to ...CCDCFG \n", val); | ||
571 | regw(val, CCDCFG); | ||
572 | |||
573 | /* | ||
574 | * Configure the vertical sync polarity(MODESET.VDPOL) | ||
575 | * Configure the horizontal sync polarity (MODESET.HDPOL) | ||
576 | * Configure frame id polarity (MODESET.FLDPOL) | ||
577 | * Configure data polarity | ||
578 | * Configure External WEN Selection | ||
579 | * Configure frame format(progressive or interlace) | ||
580 | * Configure pixel format (Input mode) | ||
581 | * Configure the data shift | ||
582 | */ | ||
583 | |||
584 | val = ISIF_VDHDOUT_INPUT | (params->vd_pol << ISIF_VD_POL_SHIFT) | | ||
585 | (params->hd_pol << ISIF_HD_POL_SHIFT) | | ||
586 | (params->fid_pol << ISIF_FID_POL_SHIFT) | | ||
587 | (ISIF_DATAPOL_NORMAL << ISIF_DATAPOL_SHIFT) | | ||
588 | (ISIF_EXWEN_DISABLE << ISIF_EXWEN_SHIFT) | | ||
589 | (params->frm_fmt << ISIF_FRM_FMT_SHIFT) | | ||
590 | (params->pix_fmt << ISIF_INPUT_SHIFT) | | ||
591 | (params->config_params.data_shift << ISIF_DATASFT_SHIFT); | ||
592 | |||
593 | regw(val, MODESET); | ||
594 | dev_dbg(isif_cfg.dev, "Writing 0x%x to MODESET...\n", val); | ||
595 | |||
596 | /* | ||
597 | * Configure GAMMAWD register | ||
598 | * CFA pattern setting | ||
599 | */ | ||
600 | val = params->cfa_pat << ISIF_GAMMAWD_CFA_SHIFT; | ||
601 | |||
602 | /* Gamma msb */ | ||
603 | if (module_params->compress.alg == ISIF_ALAW) | ||
604 | val |= ISIF_ALAW_ENABLE; | ||
605 | |||
606 | val |= (params->data_msb << ISIF_ALAW_GAMA_WD_SHIFT); | ||
607 | regw(val, CGAMMAWD); | ||
608 | |||
609 | /* Configure DPCM compression settings */ | ||
610 | if (module_params->compress.alg == ISIF_DPCM) { | ||
611 | val = BIT(ISIF_DPCM_EN_SHIFT) | | ||
612 | (module_params->compress.pred << | ||
613 | ISIF_DPCM_PREDICTOR_SHIFT); | ||
614 | } | ||
615 | |||
616 | regw(val, MISC); | ||
617 | |||
618 | /* Configure Gain & Offset */ | ||
619 | isif_config_gain_offset(); | ||
620 | |||
621 | /* Configure Color pattern */ | ||
622 | val = (params->config_params.col_pat_field0.olop) | | ||
623 | (params->config_params.col_pat_field0.olep << 2) | | ||
624 | (params->config_params.col_pat_field0.elop << 4) | | ||
625 | (params->config_params.col_pat_field0.elep << 6) | | ||
626 | (params->config_params.col_pat_field1.olop << 8) | | ||
627 | (params->config_params.col_pat_field1.olep << 10) | | ||
628 | (params->config_params.col_pat_field1.elop << 12) | | ||
629 | (params->config_params.col_pat_field1.elep << 14); | ||
630 | regw(val, CCOLP); | ||
631 | dev_dbg(isif_cfg.dev, "Writing %x to CCOLP ...\n", val); | ||
632 | |||
633 | /* Configure HSIZE register */ | ||
634 | val = (!!params->horz_flip_en) << ISIF_HSIZE_FLIP_SHIFT; | ||
635 | |||
636 | /* calculate line offset in 32 bytes based on pack value */ | ||
637 | if (isif_cfg.data_pack == ISIF_PACK_8BIT) | ||
638 | val |= ((params->win.width + 31) >> 5); | ||
639 | else if (isif_cfg.data_pack == ISIF_PACK_12BIT) | ||
640 | val |= (((params->win.width + | ||
641 | (params->win.width >> 2)) + 31) >> 5); | ||
642 | else | ||
643 | val |= (((params->win.width * 2) + 31) >> 5); | ||
644 | regw(val, HSIZE); | ||
645 | |||
646 | /* Configure SDOFST register */ | ||
647 | if (params->frm_fmt == CCDC_FRMFMT_INTERLACED) { | ||
648 | if (params->image_invert_en) { | ||
649 | /* For interlace inverse mode */ | ||
650 | regw(0x4B6D, SDOFST); | ||
651 | dev_dbg(isif_cfg.dev, "Writing 0x4B6D to SDOFST...\n"); | ||
652 | } else { | ||
653 | /* For interlace non inverse mode */ | ||
654 | regw(0x0B6D, SDOFST); | ||
655 | dev_dbg(isif_cfg.dev, "Writing 0x0B6D to SDOFST...\n"); | ||
656 | } | ||
657 | } else if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE) { | ||
658 | if (params->image_invert_en) { | ||
659 | /* For progressive inverse mode */ | ||
660 | regw(0x4000, SDOFST); | ||
661 | dev_dbg(isif_cfg.dev, "Writing 0x4000 to SDOFST...\n"); | ||
662 | } else { | ||
663 | /* For progressive non inverse mode */ | ||
664 | regw(0x0000, SDOFST); | ||
665 | dev_dbg(isif_cfg.dev, "Writing 0x0000 to SDOFST...\n"); | ||
666 | } | ||
667 | } | ||
668 | |||
669 | /* Configure video window */ | ||
670 | isif_setwin(¶ms->win, params->frm_fmt, 1); | ||
671 | |||
672 | /* Configure Black Clamp */ | ||
673 | isif_config_bclamp(&module_params->bclamp); | ||
674 | |||
675 | /* Configure Vertical Defection Pixel Correction */ | ||
676 | if (isif_config_dfc(&module_params->dfc) < 0) | ||
677 | return -EFAULT; | ||
678 | |||
679 | if (!module_params->df_csc.df_or_csc) | ||
680 | /* Configure Color Space Conversion */ | ||
681 | isif_config_csc(&module_params->df_csc); | ||
682 | |||
683 | isif_config_linearization(&module_params->linearize); | ||
684 | |||
685 | /* Configure Culling */ | ||
686 | isif_config_culling(&module_params->culling); | ||
687 | |||
688 | /* Configure horizontal and vertical offsets(DFC,LSC,Gain) */ | ||
689 | regw(module_params->horz_offset, DATAHOFST); | ||
690 | regw(module_params->vert_offset, DATAVOFST); | ||
691 | |||
692 | /* Setup test pattern if enabled */ | ||
693 | if (params->config_params.test_pat_gen) { | ||
694 | /* Use the HD/VD pol settings from user */ | ||
695 | sync.ccdpg_hdpol = params->hd_pol; | ||
696 | sync.ccdpg_vdpol = params->vd_pol; | ||
697 | dm365_vpss_set_sync_pol(sync); | ||
698 | frame_size.hlpfr = isif_cfg.bayer.win.width; | ||
699 | frame_size.pplen = isif_cfg.bayer.win.height; | ||
700 | dm365_vpss_set_pg_frame_size(frame_size); | ||
701 | vpss_select_ccdc_source(VPSS_PGLPBK); | ||
702 | } | ||
703 | |||
704 | dev_dbg(isif_cfg.dev, "\nEnd of isif_config_ycbcr...\n"); | ||
705 | return 0; | ||
706 | } | ||
707 | |||
708 | static int isif_set_buftype(enum ccdc_buftype buf_type) | ||
709 | { | ||
710 | if (isif_cfg.if_type == VPFE_RAW_BAYER) | ||
711 | isif_cfg.bayer.buf_type = buf_type; | ||
712 | else | ||
713 | isif_cfg.ycbcr.buf_type = buf_type; | ||
714 | |||
715 | return 0; | ||
716 | |||
717 | } | ||
718 | static enum ccdc_buftype isif_get_buftype(void) | ||
719 | { | ||
720 | if (isif_cfg.if_type == VPFE_RAW_BAYER) | ||
721 | return isif_cfg.bayer.buf_type; | ||
722 | |||
723 | return isif_cfg.ycbcr.buf_type; | ||
724 | } | ||
725 | |||
726 | static int isif_enum_pix(u32 *pix, int i) | ||
727 | { | ||
728 | int ret = -EINVAL; | ||
729 | |||
730 | if (isif_cfg.if_type == VPFE_RAW_BAYER) { | ||
731 | if (i < ARRAY_SIZE(isif_raw_bayer_pix_formats)) { | ||
732 | *pix = isif_raw_bayer_pix_formats[i]; | ||
733 | ret = 0; | ||
734 | } | ||
735 | } else { | ||
736 | if (i < ARRAY_SIZE(isif_raw_yuv_pix_formats)) { | ||
737 | *pix = isif_raw_yuv_pix_formats[i]; | ||
738 | ret = 0; | ||
739 | } | ||
740 | } | ||
741 | |||
742 | return ret; | ||
743 | } | ||
744 | |||
745 | static int isif_set_pixel_format(unsigned int pixfmt) | ||
746 | { | ||
747 | if (isif_cfg.if_type == VPFE_RAW_BAYER) { | ||
748 | if (pixfmt == V4L2_PIX_FMT_SBGGR8) { | ||
749 | if ((isif_cfg.bayer.config_params.compress.alg != | ||
750 | ISIF_ALAW) && | ||
751 | (isif_cfg.bayer.config_params.compress.alg != | ||
752 | ISIF_DPCM)) { | ||
753 | dev_dbg(isif_cfg.dev, | ||
754 | "Either configure A-Law or DPCM\n"); | ||
755 | return -EINVAL; | ||
756 | } | ||
757 | isif_cfg.data_pack = ISIF_PACK_8BIT; | ||
758 | } else if (pixfmt == V4L2_PIX_FMT_SBGGR16) { | ||
759 | isif_cfg.bayer.config_params.compress.alg = | ||
760 | ISIF_NO_COMPRESSION; | ||
761 | isif_cfg.data_pack = ISIF_PACK_16BIT; | ||
762 | } else | ||
763 | return -EINVAL; | ||
764 | isif_cfg.bayer.pix_fmt = CCDC_PIXFMT_RAW; | ||
765 | } else { | ||
766 | if (pixfmt == V4L2_PIX_FMT_YUYV) | ||
767 | isif_cfg.ycbcr.pix_order = CCDC_PIXORDER_YCBYCR; | ||
768 | else if (pixfmt == V4L2_PIX_FMT_UYVY) | ||
769 | isif_cfg.ycbcr.pix_order = CCDC_PIXORDER_CBYCRY; | ||
770 | else | ||
771 | return -EINVAL; | ||
772 | isif_cfg.data_pack = ISIF_PACK_8BIT; | ||
773 | } | ||
774 | return 0; | ||
775 | } | ||
776 | |||
777 | static u32 isif_get_pixel_format(void) | ||
778 | { | ||
779 | u32 pixfmt; | ||
780 | |||
781 | if (isif_cfg.if_type == VPFE_RAW_BAYER) | ||
782 | if (isif_cfg.bayer.config_params.compress.alg == ISIF_ALAW || | ||
783 | isif_cfg.bayer.config_params.compress.alg == ISIF_DPCM) | ||
784 | pixfmt = V4L2_PIX_FMT_SBGGR8; | ||
785 | else | ||
786 | pixfmt = V4L2_PIX_FMT_SBGGR16; | ||
787 | else { | ||
788 | if (isif_cfg.ycbcr.pix_order == CCDC_PIXORDER_YCBYCR) | ||
789 | pixfmt = V4L2_PIX_FMT_YUYV; | ||
790 | else | ||
791 | pixfmt = V4L2_PIX_FMT_UYVY; | ||
792 | } | ||
793 | return pixfmt; | ||
794 | } | ||
795 | |||
796 | static int isif_set_image_window(struct v4l2_rect *win) | ||
797 | { | ||
798 | if (isif_cfg.if_type == VPFE_RAW_BAYER) { | ||
799 | isif_cfg.bayer.win.top = win->top; | ||
800 | isif_cfg.bayer.win.left = win->left; | ||
801 | isif_cfg.bayer.win.width = win->width; | ||
802 | isif_cfg.bayer.win.height = win->height; | ||
803 | } else { | ||
804 | isif_cfg.ycbcr.win.top = win->top; | ||
805 | isif_cfg.ycbcr.win.left = win->left; | ||
806 | isif_cfg.ycbcr.win.width = win->width; | ||
807 | isif_cfg.ycbcr.win.height = win->height; | ||
808 | } | ||
809 | return 0; | ||
810 | } | ||
811 | |||
812 | static void isif_get_image_window(struct v4l2_rect *win) | ||
813 | { | ||
814 | if (isif_cfg.if_type == VPFE_RAW_BAYER) | ||
815 | *win = isif_cfg.bayer.win; | ||
816 | else | ||
817 | *win = isif_cfg.ycbcr.win; | ||
818 | } | ||
819 | |||
820 | static unsigned int isif_get_line_length(void) | ||
821 | { | ||
822 | unsigned int len; | ||
823 | |||
824 | if (isif_cfg.if_type == VPFE_RAW_BAYER) { | ||
825 | if (isif_cfg.data_pack == ISIF_PACK_8BIT) | ||
826 | len = ((isif_cfg.bayer.win.width)); | ||
827 | else if (isif_cfg.data_pack == ISIF_PACK_12BIT) | ||
828 | len = (((isif_cfg.bayer.win.width * 2) + | ||
829 | (isif_cfg.bayer.win.width >> 2))); | ||
830 | else | ||
831 | len = (((isif_cfg.bayer.win.width * 2))); | ||
832 | } else | ||
833 | len = (((isif_cfg.ycbcr.win.width * 2))); | ||
834 | return ALIGN(len, 32); | ||
835 | } | ||
836 | |||
837 | static int isif_set_frame_format(enum ccdc_frmfmt frm_fmt) | ||
838 | { | ||
839 | if (isif_cfg.if_type == VPFE_RAW_BAYER) | ||
840 | isif_cfg.bayer.frm_fmt = frm_fmt; | ||
841 | else | ||
842 | isif_cfg.ycbcr.frm_fmt = frm_fmt; | ||
843 | return 0; | ||
844 | } | ||
845 | static enum ccdc_frmfmt isif_get_frame_format(void) | ||
846 | { | ||
847 | if (isif_cfg.if_type == VPFE_RAW_BAYER) | ||
848 | return isif_cfg.bayer.frm_fmt; | ||
849 | return isif_cfg.ycbcr.frm_fmt; | ||
850 | } | ||
851 | |||
852 | static int isif_getfid(void) | ||
853 | { | ||
854 | return (regr(MODESET) >> 15) & 0x1; | ||
855 | } | ||
856 | |||
857 | /* misc operations */ | ||
858 | static void isif_setfbaddr(unsigned long addr) | ||
859 | { | ||
860 | regw((addr >> 21) & 0x07ff, CADU); | ||
861 | regw((addr >> 5) & 0x0ffff, CADL); | ||
862 | } | ||
863 | |||
864 | static int isif_set_hw_if_params(struct vpfe_hw_if_param *params) | ||
865 | { | ||
866 | isif_cfg.if_type = params->if_type; | ||
867 | |||
868 | switch (params->if_type) { | ||
869 | case VPFE_BT656: | ||
870 | case VPFE_BT656_10BIT: | ||
871 | case VPFE_YCBCR_SYNC_8: | ||
872 | isif_cfg.ycbcr.pix_fmt = CCDC_PIXFMT_YCBCR_8BIT; | ||
873 | isif_cfg.ycbcr.pix_order = CCDC_PIXORDER_CBYCRY; | ||
874 | break; | ||
875 | case VPFE_BT1120: | ||
876 | case VPFE_YCBCR_SYNC_16: | ||
877 | isif_cfg.ycbcr.pix_fmt = CCDC_PIXFMT_YCBCR_16BIT; | ||
878 | isif_cfg.ycbcr.pix_order = CCDC_PIXORDER_CBYCRY; | ||
879 | break; | ||
880 | case VPFE_RAW_BAYER: | ||
881 | isif_cfg.bayer.pix_fmt = CCDC_PIXFMT_RAW; | ||
882 | break; | ||
883 | default: | ||
884 | dev_dbg(isif_cfg.dev, "Invalid interface type\n"); | ||
885 | return -EINVAL; | ||
886 | } | ||
887 | |||
888 | return 0; | ||
889 | } | ||
890 | |||
891 | /* This function will configure ISIF for YCbCr parameters. */ | ||
892 | static int isif_config_ycbcr(void) | ||
893 | { | ||
894 | struct isif_ycbcr_config *params = &isif_cfg.ycbcr; | ||
895 | struct vpss_pg_frame_size frame_size; | ||
896 | u32 modeset = 0, ccdcfg = 0; | ||
897 | struct vpss_sync_pol sync; | ||
898 | |||
899 | dev_dbg(isif_cfg.dev, "\nStarting isif_config_ycbcr..."); | ||
900 | |||
901 | /* configure pixel format or input mode */ | ||
902 | modeset = modeset | (params->pix_fmt << ISIF_INPUT_SHIFT) | | ||
903 | (params->frm_fmt << ISIF_FRM_FMT_SHIFT) | | ||
904 | (params->fid_pol << ISIF_FID_POL_SHIFT) | | ||
905 | (params->hd_pol << ISIF_HD_POL_SHIFT) | | ||
906 | (params->vd_pol << ISIF_VD_POL_SHIFT); | ||
907 | |||
908 | /* pack the data to 8-bit ISIFCFG */ | ||
909 | switch (isif_cfg.if_type) { | ||
910 | case VPFE_BT656: | ||
911 | if (params->pix_fmt != CCDC_PIXFMT_YCBCR_8BIT) { | ||
912 | dev_dbg(isif_cfg.dev, "Invalid pix_fmt(input mode)\n"); | ||
913 | return -EINVAL; | ||
914 | } | ||
915 | modeset |= (VPFE_PINPOL_NEGATIVE << ISIF_VD_POL_SHIFT); | ||
916 | regw(3, REC656IF); | ||
917 | ccdcfg = ccdcfg | ISIF_DATA_PACK8 | ISIF_YCINSWP_YCBCR; | ||
918 | break; | ||
919 | case VPFE_BT656_10BIT: | ||
920 | if (params->pix_fmt != CCDC_PIXFMT_YCBCR_8BIT) { | ||
921 | dev_dbg(isif_cfg.dev, "Invalid pix_fmt(input mode)\n"); | ||
922 | return -EINVAL; | ||
923 | } | ||
924 | /* setup BT.656, embedded sync */ | ||
925 | regw(3, REC656IF); | ||
926 | /* enable 10 bit mode in ccdcfg */ | ||
927 | ccdcfg = ccdcfg | ISIF_DATA_PACK8 | ISIF_YCINSWP_YCBCR | | ||
928 | ISIF_BW656_ENABLE; | ||
929 | break; | ||
930 | case VPFE_BT1120: | ||
931 | if (params->pix_fmt != CCDC_PIXFMT_YCBCR_16BIT) { | ||
932 | dev_dbg(isif_cfg.dev, "Invalid pix_fmt(input mode)\n"); | ||
933 | return -EINVAL; | ||
934 | } | ||
935 | regw(3, REC656IF); | ||
936 | break; | ||
937 | |||
938 | case VPFE_YCBCR_SYNC_8: | ||
939 | ccdcfg |= ISIF_DATA_PACK8; | ||
940 | ccdcfg |= ISIF_YCINSWP_YCBCR; | ||
941 | if (params->pix_fmt != CCDC_PIXFMT_YCBCR_8BIT) { | ||
942 | dev_dbg(isif_cfg.dev, "Invalid pix_fmt(input mode)\n"); | ||
943 | return -EINVAL; | ||
944 | } | ||
945 | break; | ||
946 | case VPFE_YCBCR_SYNC_16: | ||
947 | if (params->pix_fmt != CCDC_PIXFMT_YCBCR_16BIT) { | ||
948 | dev_dbg(isif_cfg.dev, "Invalid pix_fmt(input mode)\n"); | ||
949 | return -EINVAL; | ||
950 | } | ||
951 | break; | ||
952 | default: | ||
953 | /* should never come here */ | ||
954 | dev_dbg(isif_cfg.dev, "Invalid interface type\n"); | ||
955 | return -EINVAL; | ||
956 | } | ||
957 | |||
958 | regw(modeset, MODESET); | ||
959 | |||
960 | /* Set up pix order */ | ||
961 | ccdcfg |= params->pix_order << ISIF_PIX_ORDER_SHIFT; | ||
962 | |||
963 | regw(ccdcfg, CCDCFG); | ||
964 | |||
965 | /* configure video window */ | ||
966 | if ((isif_cfg.if_type == VPFE_BT1120) || | ||
967 | (isif_cfg.if_type == VPFE_YCBCR_SYNC_16)) | ||
968 | isif_setwin(¶ms->win, params->frm_fmt, 1); | ||
969 | else | ||
970 | isif_setwin(¶ms->win, params->frm_fmt, 2); | ||
971 | |||
972 | /* | ||
973 | * configure the horizontal line offset | ||
974 | * this is done by rounding up width to a multiple of 16 pixels | ||
975 | * and multiply by two to account for y:cb:cr 4:2:2 data | ||
976 | */ | ||
977 | regw(((((params->win.width * 2) + 31) & 0xffffffe0) >> 5), HSIZE); | ||
978 | |||
979 | /* configure the memory line offset */ | ||
980 | if ((params->frm_fmt == CCDC_FRMFMT_INTERLACED) && | ||
981 | (params->buf_type == CCDC_BUFTYPE_FLD_INTERLEAVED)) | ||
982 | /* two fields are interleaved in memory */ | ||
983 | regw(0x00000249, SDOFST); | ||
984 | |||
985 | /* Setup test pattern if enabled */ | ||
986 | if (isif_cfg.bayer.config_params.test_pat_gen) { | ||
987 | sync.ccdpg_hdpol = params->hd_pol; | ||
988 | sync.ccdpg_vdpol = params->vd_pol; | ||
989 | dm365_vpss_set_sync_pol(sync); | ||
990 | dm365_vpss_set_pg_frame_size(frame_size); | ||
991 | } | ||
992 | return 0; | ||
993 | } | ||
994 | |||
995 | static int isif_configure(void) | ||
996 | { | ||
997 | if (isif_cfg.if_type == VPFE_RAW_BAYER) | ||
998 | return isif_config_raw(); | ||
999 | return isif_config_ycbcr(); | ||
1000 | } | ||
1001 | |||
1002 | static int isif_close(struct device *device) | ||
1003 | { | ||
1004 | /* copy defaults to module params */ | ||
1005 | isif_cfg.bayer.config_params = isif_config_defaults; | ||
1006 | return 0; | ||
1007 | } | ||
1008 | |||
1009 | static struct ccdc_hw_device isif_hw_dev = { | ||
1010 | .name = "ISIF", | ||
1011 | .owner = THIS_MODULE, | ||
1012 | .hw_ops = { | ||
1013 | .open = isif_open, | ||
1014 | .close = isif_close, | ||
1015 | .enable = isif_enable, | ||
1016 | .enable_out_to_sdram = isif_enable_output_to_sdram, | ||
1017 | .set_hw_if_params = isif_set_hw_if_params, | ||
1018 | .configure = isif_configure, | ||
1019 | .set_buftype = isif_set_buftype, | ||
1020 | .get_buftype = isif_get_buftype, | ||
1021 | .enum_pix = isif_enum_pix, | ||
1022 | .set_pixel_format = isif_set_pixel_format, | ||
1023 | .get_pixel_format = isif_get_pixel_format, | ||
1024 | .set_frame_format = isif_set_frame_format, | ||
1025 | .get_frame_format = isif_get_frame_format, | ||
1026 | .set_image_window = isif_set_image_window, | ||
1027 | .get_image_window = isif_get_image_window, | ||
1028 | .get_line_length = isif_get_line_length, | ||
1029 | .setfbaddr = isif_setfbaddr, | ||
1030 | .getfid = isif_getfid, | ||
1031 | }, | ||
1032 | }; | ||
1033 | |||
1034 | static int __init isif_probe(struct platform_device *pdev) | ||
1035 | { | ||
1036 | void (*setup_pinmux)(void); | ||
1037 | struct resource *res; | ||
1038 | void *__iomem addr; | ||
1039 | int status = 0, i; | ||
1040 | |||
1041 | /* | ||
1042 | * first try to register with vpfe. If not correct platform, then we | ||
1043 | * don't have to iomap | ||
1044 | */ | ||
1045 | status = vpfe_register_ccdc_device(&isif_hw_dev); | ||
1046 | if (status < 0) | ||
1047 | return status; | ||
1048 | |||
1049 | /* Get and enable Master clock */ | ||
1050 | isif_cfg.mclk = clk_get(&pdev->dev, "master"); | ||
1051 | if (IS_ERR(isif_cfg.mclk)) { | ||
1052 | status = PTR_ERR(isif_cfg.mclk); | ||
1053 | goto fail_mclk; | ||
1054 | } | ||
1055 | if (clk_enable(isif_cfg.mclk)) { | ||
1056 | status = -ENODEV; | ||
1057 | goto fail_mclk; | ||
1058 | } | ||
1059 | |||
1060 | /* Platform data holds setup_pinmux function ptr */ | ||
1061 | if (NULL == pdev->dev.platform_data) { | ||
1062 | status = -ENODEV; | ||
1063 | goto fail_mclk; | ||
1064 | } | ||
1065 | setup_pinmux = pdev->dev.platform_data; | ||
1066 | /* | ||
1067 | * setup Mux configuration for ccdc which may be different for | ||
1068 | * different SoCs using this CCDC | ||
1069 | */ | ||
1070 | setup_pinmux(); | ||
1071 | |||
1072 | i = 0; | ||
1073 | /* Get the ISIF base address, linearization table0 and table1 addr. */ | ||
1074 | while (i < 3) { | ||
1075 | res = platform_get_resource(pdev, IORESOURCE_MEM, i); | ||
1076 | if (!res) { | ||
1077 | status = -ENODEV; | ||
1078 | goto fail_nobase_res; | ||
1079 | } | ||
1080 | res = request_mem_region(res->start, resource_size(res), | ||
1081 | res->name); | ||
1082 | if (!res) { | ||
1083 | status = -EBUSY; | ||
1084 | goto fail_nobase_res; | ||
1085 | } | ||
1086 | addr = ioremap_nocache(res->start, resource_size(res)); | ||
1087 | if (!addr) { | ||
1088 | status = -ENOMEM; | ||
1089 | goto fail_base_iomap; | ||
1090 | } | ||
1091 | switch (i) { | ||
1092 | case 0: | ||
1093 | /* ISIF base address */ | ||
1094 | isif_cfg.base_addr = addr; | ||
1095 | break; | ||
1096 | case 1: | ||
1097 | /* ISIF linear tbl0 address */ | ||
1098 | isif_cfg.linear_tbl0_addr = addr; | ||
1099 | break; | ||
1100 | default: | ||
1101 | /* ISIF linear tbl0 address */ | ||
1102 | isif_cfg.linear_tbl1_addr = addr; | ||
1103 | break; | ||
1104 | } | ||
1105 | i++; | ||
1106 | } | ||
1107 | isif_cfg.dev = &pdev->dev; | ||
1108 | |||
1109 | printk(KERN_NOTICE "%s is registered with vpfe.\n", | ||
1110 | isif_hw_dev.name); | ||
1111 | return 0; | ||
1112 | fail_base_iomap: | ||
1113 | release_mem_region(res->start, resource_size(res)); | ||
1114 | i--; | ||
1115 | fail_nobase_res: | ||
1116 | if (isif_cfg.base_addr) | ||
1117 | iounmap(isif_cfg.base_addr); | ||
1118 | if (isif_cfg.linear_tbl0_addr) | ||
1119 | iounmap(isif_cfg.linear_tbl0_addr); | ||
1120 | |||
1121 | while (i >= 0) { | ||
1122 | res = platform_get_resource(pdev, IORESOURCE_MEM, i); | ||
1123 | release_mem_region(res->start, resource_size(res)); | ||
1124 | i--; | ||
1125 | } | ||
1126 | fail_mclk: | ||
1127 | clk_put(isif_cfg.mclk); | ||
1128 | vpfe_unregister_ccdc_device(&isif_hw_dev); | ||
1129 | return status; | ||
1130 | } | ||
1131 | |||
1132 | static int isif_remove(struct platform_device *pdev) | ||
1133 | { | ||
1134 | struct resource *res; | ||
1135 | int i = 0; | ||
1136 | |||
1137 | iounmap(isif_cfg.base_addr); | ||
1138 | iounmap(isif_cfg.linear_tbl0_addr); | ||
1139 | iounmap(isif_cfg.linear_tbl1_addr); | ||
1140 | while (i < 3) { | ||
1141 | res = platform_get_resource(pdev, IORESOURCE_MEM, i); | ||
1142 | if (res) | ||
1143 | release_mem_region(res->start, resource_size(res)); | ||
1144 | i++; | ||
1145 | } | ||
1146 | vpfe_unregister_ccdc_device(&isif_hw_dev); | ||
1147 | return 0; | ||
1148 | } | ||
1149 | |||
1150 | static struct platform_driver isif_driver = { | ||
1151 | .driver = { | ||
1152 | .name = "isif", | ||
1153 | .owner = THIS_MODULE, | ||
1154 | }, | ||
1155 | .remove = __devexit_p(isif_remove), | ||
1156 | .probe = isif_probe, | ||
1157 | }; | ||
1158 | |||
1159 | static int __init isif_init(void) | ||
1160 | { | ||
1161 | return platform_driver_register(&isif_driver); | ||
1162 | } | ||
1163 | |||
1164 | static void isif_exit(void) | ||
1165 | { | ||
1166 | platform_driver_unregister(&isif_driver); | ||
1167 | } | ||
1168 | |||
1169 | module_init(isif_init); | ||
1170 | module_exit(isif_exit); | ||
1171 | |||
1172 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/video/davinci/isif_regs.h b/drivers/media/video/davinci/isif_regs.h new file mode 100644 index 000000000000..f7b8893a2957 --- /dev/null +++ b/drivers/media/video/davinci/isif_regs.h | |||
@@ -0,0 +1,269 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2008-2009 Texas Instruments Inc | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
17 | */ | ||
18 | #ifndef _ISIF_REGS_H | ||
19 | #define _ISIF_REGS_H | ||
20 | |||
21 | /* ISIF registers relative offsets */ | ||
22 | #define SYNCEN 0x00 | ||
23 | #define MODESET 0x04 | ||
24 | #define HDW 0x08 | ||
25 | #define VDW 0x0c | ||
26 | #define PPLN 0x10 | ||
27 | #define LPFR 0x14 | ||
28 | #define SPH 0x18 | ||
29 | #define LNH 0x1c | ||
30 | #define SLV0 0x20 | ||
31 | #define SLV1 0x24 | ||
32 | #define LNV 0x28 | ||
33 | #define CULH 0x2c | ||
34 | #define CULV 0x30 | ||
35 | #define HSIZE 0x34 | ||
36 | #define SDOFST 0x38 | ||
37 | #define CADU 0x3c | ||
38 | #define CADL 0x40 | ||
39 | #define LINCFG0 0x44 | ||
40 | #define LINCFG1 0x48 | ||
41 | #define CCOLP 0x4c | ||
42 | #define CRGAIN 0x50 | ||
43 | #define CGRGAIN 0x54 | ||
44 | #define CGBGAIN 0x58 | ||
45 | #define CBGAIN 0x5c | ||
46 | #define COFSTA 0x60 | ||
47 | #define FLSHCFG0 0x64 | ||
48 | #define FLSHCFG1 0x68 | ||
49 | #define FLSHCFG2 0x6c | ||
50 | #define VDINT0 0x70 | ||
51 | #define VDINT1 0x74 | ||
52 | #define VDINT2 0x78 | ||
53 | #define MISC 0x7c | ||
54 | #define CGAMMAWD 0x80 | ||
55 | #define REC656IF 0x84 | ||
56 | #define CCDCFG 0x88 | ||
57 | /***************************************************** | ||
58 | * Defect Correction registers | ||
59 | *****************************************************/ | ||
60 | #define DFCCTL 0x8c | ||
61 | #define VDFSATLV 0x90 | ||
62 | #define DFCMEMCTL 0x94 | ||
63 | #define DFCMEM0 0x98 | ||
64 | #define DFCMEM1 0x9c | ||
65 | #define DFCMEM2 0xa0 | ||
66 | #define DFCMEM3 0xa4 | ||
67 | #define DFCMEM4 0xa8 | ||
68 | /**************************************************** | ||
69 | * Black Clamp registers | ||
70 | ****************************************************/ | ||
71 | #define CLAMPCFG 0xac | ||
72 | #define CLDCOFST 0xb0 | ||
73 | #define CLSV 0xb4 | ||
74 | #define CLHWIN0 0xb8 | ||
75 | #define CLHWIN1 0xbc | ||
76 | #define CLHWIN2 0xc0 | ||
77 | #define CLVRV 0xc4 | ||
78 | #define CLVWIN0 0xc8 | ||
79 | #define CLVWIN1 0xcc | ||
80 | #define CLVWIN2 0xd0 | ||
81 | #define CLVWIN3 0xd4 | ||
82 | /**************************************************** | ||
83 | * Lense Shading Correction | ||
84 | ****************************************************/ | ||
85 | #define DATAHOFST 0xd8 | ||
86 | #define DATAVOFST 0xdc | ||
87 | #define LSCHVAL 0xe0 | ||
88 | #define LSCVVAL 0xe4 | ||
89 | #define TWODLSCCFG 0xe8 | ||
90 | #define TWODLSCOFST 0xec | ||
91 | #define TWODLSCINI 0xf0 | ||
92 | #define TWODLSCGRBU 0xf4 | ||
93 | #define TWODLSCGRBL 0xf8 | ||
94 | #define TWODLSCGROF 0xfc | ||
95 | #define TWODLSCORBU 0x100 | ||
96 | #define TWODLSCORBL 0x104 | ||
97 | #define TWODLSCOROF 0x108 | ||
98 | #define TWODLSCIRQEN 0x10c | ||
99 | #define TWODLSCIRQST 0x110 | ||
100 | /**************************************************** | ||
101 | * Data formatter | ||
102 | ****************************************************/ | ||
103 | #define FMTCFG 0x114 | ||
104 | #define FMTPLEN 0x118 | ||
105 | #define FMTSPH 0x11c | ||
106 | #define FMTLNH 0x120 | ||
107 | #define FMTSLV 0x124 | ||
108 | #define FMTLNV 0x128 | ||
109 | #define FMTRLEN 0x12c | ||
110 | #define FMTHCNT 0x130 | ||
111 | #define FMTAPTR_BASE 0x134 | ||
112 | /* Below macro for addresses FMTAPTR0 - FMTAPTR15 */ | ||
113 | #define FMTAPTR(i) (FMTAPTR_BASE + (i * 4)) | ||
114 | #define FMTPGMVF0 0x174 | ||
115 | #define FMTPGMVF1 0x178 | ||
116 | #define FMTPGMAPU0 0x17c | ||
117 | #define FMTPGMAPU1 0x180 | ||
118 | #define FMTPGMAPS0 0x184 | ||
119 | #define FMTPGMAPS1 0x188 | ||
120 | #define FMTPGMAPS2 0x18c | ||
121 | #define FMTPGMAPS3 0x190 | ||
122 | #define FMTPGMAPS4 0x194 | ||
123 | #define FMTPGMAPS5 0x198 | ||
124 | #define FMTPGMAPS6 0x19c | ||
125 | #define FMTPGMAPS7 0x1a0 | ||
126 | /************************************************ | ||
127 | * Color Space Converter | ||
128 | ************************************************/ | ||
129 | #define CSCCTL 0x1a4 | ||
130 | #define CSCM0 0x1a8 | ||
131 | #define CSCM1 0x1ac | ||
132 | #define CSCM2 0x1b0 | ||
133 | #define CSCM3 0x1b4 | ||
134 | #define CSCM4 0x1b8 | ||
135 | #define CSCM5 0x1bc | ||
136 | #define CSCM6 0x1c0 | ||
137 | #define CSCM7 0x1c4 | ||
138 | #define OBWIN0 0x1c8 | ||
139 | #define OBWIN1 0x1cc | ||
140 | #define OBWIN2 0x1d0 | ||
141 | #define OBWIN3 0x1d4 | ||
142 | #define OBVAL0 0x1d8 | ||
143 | #define OBVAL1 0x1dc | ||
144 | #define OBVAL2 0x1e0 | ||
145 | #define OBVAL3 0x1e4 | ||
146 | #define OBVAL4 0x1e8 | ||
147 | #define OBVAL5 0x1ec | ||
148 | #define OBVAL6 0x1f0 | ||
149 | #define OBVAL7 0x1f4 | ||
150 | #define CLKCTL 0x1f8 | ||
151 | |||
152 | /* Masks & Shifts below */ | ||
153 | #define START_PX_HOR_MASK 0x7FFF | ||
154 | #define NUM_PX_HOR_MASK 0x7FFF | ||
155 | #define START_VER_ONE_MASK 0x7FFF | ||
156 | #define START_VER_TWO_MASK 0x7FFF | ||
157 | #define NUM_LINES_VER 0x7FFF | ||
158 | |||
159 | /* gain - offset masks */ | ||
160 | #define GAIN_INTEGER_SHIFT 9 | ||
161 | #define OFFSET_MASK 0xFFF | ||
162 | #define GAIN_SDRAM_EN_SHIFT 12 | ||
163 | #define GAIN_IPIPE_EN_SHIFT 13 | ||
164 | #define GAIN_H3A_EN_SHIFT 14 | ||
165 | #define OFST_SDRAM_EN_SHIFT 8 | ||
166 | #define OFST_IPIPE_EN_SHIFT 9 | ||
167 | #define OFST_H3A_EN_SHIFT 10 | ||
168 | #define GAIN_OFFSET_EN_MASK 0x7700 | ||
169 | |||
170 | /* Culling */ | ||
171 | #define CULL_PAT_EVEN_LINE_SHIFT 8 | ||
172 | |||
173 | /* CCDCFG register */ | ||
174 | #define ISIF_YCINSWP_RAW (0x00 << 4) | ||
175 | #define ISIF_YCINSWP_YCBCR (0x01 << 4) | ||
176 | #define ISIF_CCDCFG_FIDMD_LATCH_VSYNC (0x00 << 6) | ||
177 | #define ISIF_CCDCFG_WENLOG_AND (0x00 << 8) | ||
178 | #define ISIF_CCDCFG_TRGSEL_WEN (0x00 << 9) | ||
179 | #define ISIF_CCDCFG_EXTRG_DISABLE (0x00 << 10) | ||
180 | #define ISIF_LATCH_ON_VSYNC_DISABLE (0x01 << 15) | ||
181 | #define ISIF_LATCH_ON_VSYNC_ENABLE (0x00 << 15) | ||
182 | #define ISIF_DATA_PACK_MASK 3 | ||
183 | #define ISIF_DATA_PACK16 0 | ||
184 | #define ISIF_DATA_PACK12 1 | ||
185 | #define ISIF_DATA_PACK8 2 | ||
186 | #define ISIF_PIX_ORDER_SHIFT 11 | ||
187 | #define ISIF_BW656_ENABLE (0x01 << 5) | ||
188 | |||
189 | /* MODESET registers */ | ||
190 | #define ISIF_VDHDOUT_INPUT (0x00 << 0) | ||
191 | #define ISIF_INPUT_SHIFT 12 | ||
192 | #define ISIF_RAW_INPUT_MODE 0 | ||
193 | #define ISIF_FID_POL_SHIFT 4 | ||
194 | #define ISIF_HD_POL_SHIFT 3 | ||
195 | #define ISIF_VD_POL_SHIFT 2 | ||
196 | #define ISIF_DATAPOL_NORMAL 0 | ||
197 | #define ISIF_DATAPOL_SHIFT 6 | ||
198 | #define ISIF_EXWEN_DISABLE 0 | ||
199 | #define ISIF_EXWEN_SHIFT 5 | ||
200 | #define ISIF_FRM_FMT_SHIFT 7 | ||
201 | #define ISIF_DATASFT_SHIFT 8 | ||
202 | #define ISIF_LPF_SHIFT 14 | ||
203 | #define ISIF_LPF_MASK 1 | ||
204 | |||
205 | /* GAMMAWD registers */ | ||
206 | #define ISIF_ALAW_GAMA_WD_MASK 0xF | ||
207 | #define ISIF_ALAW_GAMA_WD_SHIFT 1 | ||
208 | #define ISIF_ALAW_ENABLE 1 | ||
209 | #define ISIF_GAMMAWD_CFA_SHIFT 5 | ||
210 | |||
211 | /* HSIZE registers */ | ||
212 | #define ISIF_HSIZE_FLIP_MASK 1 | ||
213 | #define ISIF_HSIZE_FLIP_SHIFT 12 | ||
214 | |||
215 | /* MISC registers */ | ||
216 | #define ISIF_DPCM_EN_SHIFT 12 | ||
217 | #define ISIF_DPCM_PREDICTOR_SHIFT 13 | ||
218 | |||
219 | /* Black clamp related */ | ||
220 | #define ISIF_BC_MODE_COLOR_SHIFT 4 | ||
221 | #define ISIF_HORZ_BC_MODE_SHIFT 1 | ||
222 | #define ISIF_HORZ_BC_WIN_SEL_SHIFT 5 | ||
223 | #define ISIF_HORZ_BC_PIX_LIMIT_SHIFT 6 | ||
224 | #define ISIF_HORZ_BC_WIN_H_SIZE_SHIFT 8 | ||
225 | #define ISIF_HORZ_BC_WIN_V_SIZE_SHIFT 12 | ||
226 | #define ISIF_VERT_BC_RST_VAL_SEL_SHIFT 4 | ||
227 | #define ISIF_VERT_BC_LINE_AVE_COEF_SHIFT 8 | ||
228 | |||
229 | /* VDFC registers */ | ||
230 | #define ISIF_VDFC_EN_SHIFT 4 | ||
231 | #define ISIF_VDFC_CORR_MOD_SHIFT 5 | ||
232 | #define ISIF_VDFC_CORR_WHOLE_LN_SHIFT 7 | ||
233 | #define ISIF_VDFC_LEVEL_SHFT_SHIFT 8 | ||
234 | #define ISIF_VDFC_POS_MASK 0x1FFF | ||
235 | #define ISIF_DFCMEMCTL_DFCMARST_SHIFT 2 | ||
236 | |||
237 | /* CSC registers */ | ||
238 | #define ISIF_CSC_COEF_INTEG_MASK 7 | ||
239 | #define ISIF_CSC_COEF_DECIMAL_MASK 0x1f | ||
240 | #define ISIF_CSC_COEF_INTEG_SHIFT 5 | ||
241 | #define ISIF_CSCM_MSB_SHIFT 8 | ||
242 | #define ISIF_DF_CSC_SPH_MASK 0x1FFF | ||
243 | #define ISIF_DF_CSC_LNH_MASK 0x1FFF | ||
244 | #define ISIF_DF_CSC_SLV_MASK 0x1FFF | ||
245 | #define ISIF_DF_CSC_LNV_MASK 0x1FFF | ||
246 | #define ISIF_DF_NUMLINES 0x7FFF | ||
247 | #define ISIF_DF_NUMPIX 0x1FFF | ||
248 | |||
249 | /* Offsets for LSC/DFC/Gain */ | ||
250 | #define ISIF_DATA_H_OFFSET_MASK 0x1FFF | ||
251 | #define ISIF_DATA_V_OFFSET_MASK 0x1FFF | ||
252 | |||
253 | /* Linearization */ | ||
254 | #define ISIF_LIN_CORRSFT_SHIFT 4 | ||
255 | #define ISIF_LIN_SCALE_FACT_INTEG_SHIFT 10 | ||
256 | |||
257 | |||
258 | /* Pattern registers */ | ||
259 | #define ISIF_PG_EN (1 << 3) | ||
260 | #define ISIF_SEL_PG_SRC (3 << 4) | ||
261 | #define ISIF_PG_VD_POL_SHIFT 0 | ||
262 | #define ISIF_PG_HD_POL_SHIFT 1 | ||
263 | |||
264 | /*random other junk*/ | ||
265 | #define ISIF_SYNCEN_VDHDEN_MASK (1 << 0) | ||
266 | #define ISIF_SYNCEN_WEN_MASK (1 << 1) | ||
267 | #define ISIF_SYNCEN_WEN_SHIFT 1 | ||
268 | |||
269 | #endif | ||
diff --git a/drivers/media/video/davinci/vpfe_capture.c b/drivers/media/video/davinci/vpfe_capture.c index de22bc9faf21..885cd54499cf 100644 --- a/drivers/media/video/davinci/vpfe_capture.c +++ b/drivers/media/video/davinci/vpfe_capture.c | |||
@@ -107,9 +107,6 @@ struct ccdc_config { | |||
107 | int vpfe_probed; | 107 | int vpfe_probed; |
108 | /* name of ccdc device */ | 108 | /* name of ccdc device */ |
109 | char name[32]; | 109 | char name[32]; |
110 | /* for storing mem maps for CCDC */ | ||
111 | int ccdc_addr_size; | ||
112 | void *__iomem ccdc_addr; | ||
113 | }; | 110 | }; |
114 | 111 | ||
115 | /* data structures */ | 112 | /* data structures */ |
@@ -229,7 +226,6 @@ int vpfe_register_ccdc_device(struct ccdc_hw_device *dev) | |||
229 | BUG_ON(!dev->hw_ops.set_image_window); | 226 | BUG_ON(!dev->hw_ops.set_image_window); |
230 | BUG_ON(!dev->hw_ops.get_image_window); | 227 | BUG_ON(!dev->hw_ops.get_image_window); |
231 | BUG_ON(!dev->hw_ops.get_line_length); | 228 | BUG_ON(!dev->hw_ops.get_line_length); |
232 | BUG_ON(!dev->hw_ops.setfbaddr); | ||
233 | BUG_ON(!dev->hw_ops.getfid); | 229 | BUG_ON(!dev->hw_ops.getfid); |
234 | 230 | ||
235 | mutex_lock(&ccdc_lock); | 231 | mutex_lock(&ccdc_lock); |
@@ -240,25 +236,23 @@ int vpfe_register_ccdc_device(struct ccdc_hw_device *dev) | |||
240 | * walk through it during vpfe probe | 236 | * walk through it during vpfe probe |
241 | */ | 237 | */ |
242 | printk(KERN_ERR "vpfe capture not initialized\n"); | 238 | printk(KERN_ERR "vpfe capture not initialized\n"); |
243 | ret = -1; | 239 | ret = -EFAULT; |
244 | goto unlock; | 240 | goto unlock; |
245 | } | 241 | } |
246 | 242 | ||
247 | if (strcmp(dev->name, ccdc_cfg->name)) { | 243 | if (strcmp(dev->name, ccdc_cfg->name)) { |
248 | /* ignore this ccdc */ | 244 | /* ignore this ccdc */ |
249 | ret = -1; | 245 | ret = -EINVAL; |
250 | goto unlock; | 246 | goto unlock; |
251 | } | 247 | } |
252 | 248 | ||
253 | if (ccdc_dev) { | 249 | if (ccdc_dev) { |
254 | printk(KERN_ERR "ccdc already registered\n"); | 250 | printk(KERN_ERR "ccdc already registered\n"); |
255 | ret = -1; | 251 | ret = -EINVAL; |
256 | goto unlock; | 252 | goto unlock; |
257 | } | 253 | } |
258 | 254 | ||
259 | ccdc_dev = dev; | 255 | ccdc_dev = dev; |
260 | dev->hw_ops.set_ccdc_base(ccdc_cfg->ccdc_addr, | ||
261 | ccdc_cfg->ccdc_addr_size); | ||
262 | unlock: | 256 | unlock: |
263 | mutex_unlock(&ccdc_lock); | 257 | mutex_unlock(&ccdc_lock); |
264 | return ret; | 258 | return ret; |
@@ -1786,61 +1780,6 @@ static struct vpfe_device *vpfe_initialize(void) | |||
1786 | return vpfe_dev; | 1780 | return vpfe_dev; |
1787 | } | 1781 | } |
1788 | 1782 | ||
1789 | static void vpfe_disable_clock(struct vpfe_device *vpfe_dev) | ||
1790 | { | ||
1791 | struct vpfe_config *vpfe_cfg = vpfe_dev->cfg; | ||
1792 | |||
1793 | clk_disable(vpfe_cfg->vpssclk); | ||
1794 | clk_put(vpfe_cfg->vpssclk); | ||
1795 | clk_disable(vpfe_cfg->slaveclk); | ||
1796 | clk_put(vpfe_cfg->slaveclk); | ||
1797 | v4l2_info(vpfe_dev->pdev->driver, | ||
1798 | "vpfe vpss master & slave clocks disabled\n"); | ||
1799 | } | ||
1800 | |||
1801 | static int vpfe_enable_clock(struct vpfe_device *vpfe_dev) | ||
1802 | { | ||
1803 | struct vpfe_config *vpfe_cfg = vpfe_dev->cfg; | ||
1804 | int ret = -ENOENT; | ||
1805 | |||
1806 | vpfe_cfg->vpssclk = clk_get(vpfe_dev->pdev, "vpss_master"); | ||
1807 | if (NULL == vpfe_cfg->vpssclk) { | ||
1808 | v4l2_err(vpfe_dev->pdev->driver, "No clock defined for" | ||
1809 | "vpss_master\n"); | ||
1810 | return ret; | ||
1811 | } | ||
1812 | |||
1813 | if (clk_enable(vpfe_cfg->vpssclk)) { | ||
1814 | v4l2_err(vpfe_dev->pdev->driver, | ||
1815 | "vpfe vpss master clock not enabled\n"); | ||
1816 | goto out; | ||
1817 | } | ||
1818 | v4l2_info(vpfe_dev->pdev->driver, | ||
1819 | "vpfe vpss master clock enabled\n"); | ||
1820 | |||
1821 | vpfe_cfg->slaveclk = clk_get(vpfe_dev->pdev, "vpss_slave"); | ||
1822 | if (NULL == vpfe_cfg->slaveclk) { | ||
1823 | v4l2_err(vpfe_dev->pdev->driver, | ||
1824 | "No clock defined for vpss slave\n"); | ||
1825 | goto out; | ||
1826 | } | ||
1827 | |||
1828 | if (clk_enable(vpfe_cfg->slaveclk)) { | ||
1829 | v4l2_err(vpfe_dev->pdev->driver, | ||
1830 | "vpfe vpss slave clock not enabled\n"); | ||
1831 | goto out; | ||
1832 | } | ||
1833 | v4l2_info(vpfe_dev->pdev->driver, "vpfe vpss slave clock enabled\n"); | ||
1834 | return 0; | ||
1835 | out: | ||
1836 | if (vpfe_cfg->vpssclk) | ||
1837 | clk_put(vpfe_cfg->vpssclk); | ||
1838 | if (vpfe_cfg->slaveclk) | ||
1839 | clk_put(vpfe_cfg->slaveclk); | ||
1840 | |||
1841 | return -1; | ||
1842 | } | ||
1843 | |||
1844 | /* | 1783 | /* |
1845 | * vpfe_probe : This function creates device entries by register | 1784 | * vpfe_probe : This function creates device entries by register |
1846 | * itself to the V4L2 driver and initializes fields of each | 1785 | * itself to the V4L2 driver and initializes fields of each |
@@ -1870,7 +1809,7 @@ static __init int vpfe_probe(struct platform_device *pdev) | |||
1870 | 1809 | ||
1871 | if (NULL == pdev->dev.platform_data) { | 1810 | if (NULL == pdev->dev.platform_data) { |
1872 | v4l2_err(pdev->dev.driver, "Unable to get vpfe config\n"); | 1811 | v4l2_err(pdev->dev.driver, "Unable to get vpfe config\n"); |
1873 | ret = -ENOENT; | 1812 | ret = -ENODEV; |
1874 | goto probe_free_dev_mem; | 1813 | goto probe_free_dev_mem; |
1875 | } | 1814 | } |
1876 | 1815 | ||
@@ -1884,18 +1823,13 @@ static __init int vpfe_probe(struct platform_device *pdev) | |||
1884 | goto probe_free_dev_mem; | 1823 | goto probe_free_dev_mem; |
1885 | } | 1824 | } |
1886 | 1825 | ||
1887 | /* enable vpss clocks */ | ||
1888 | ret = vpfe_enable_clock(vpfe_dev); | ||
1889 | if (ret) | ||
1890 | goto probe_free_dev_mem; | ||
1891 | |||
1892 | mutex_lock(&ccdc_lock); | 1826 | mutex_lock(&ccdc_lock); |
1893 | /* Allocate memory for ccdc configuration */ | 1827 | /* Allocate memory for ccdc configuration */ |
1894 | ccdc_cfg = kmalloc(sizeof(struct ccdc_config), GFP_KERNEL); | 1828 | ccdc_cfg = kmalloc(sizeof(struct ccdc_config), GFP_KERNEL); |
1895 | if (NULL == ccdc_cfg) { | 1829 | if (NULL == ccdc_cfg) { |
1896 | v4l2_err(pdev->dev.driver, | 1830 | v4l2_err(pdev->dev.driver, |
1897 | "Memory allocation failed for ccdc_cfg\n"); | 1831 | "Memory allocation failed for ccdc_cfg\n"); |
1898 | goto probe_disable_clock; | 1832 | goto probe_free_dev_mem; |
1899 | } | 1833 | } |
1900 | 1834 | ||
1901 | strncpy(ccdc_cfg->name, vpfe_cfg->ccdc, 32); | 1835 | strncpy(ccdc_cfg->name, vpfe_cfg->ccdc, 32); |
@@ -1904,61 +1838,34 @@ static __init int vpfe_probe(struct platform_device *pdev) | |||
1904 | if (!res1) { | 1838 | if (!res1) { |
1905 | v4l2_err(pdev->dev.driver, | 1839 | v4l2_err(pdev->dev.driver, |
1906 | "Unable to get interrupt for VINT0\n"); | 1840 | "Unable to get interrupt for VINT0\n"); |
1907 | ret = -ENOENT; | 1841 | ret = -ENODEV; |
1908 | goto probe_disable_clock; | 1842 | goto probe_free_ccdc_cfg_mem; |
1909 | } | 1843 | } |
1910 | vpfe_dev->ccdc_irq0 = res1->start; | 1844 | vpfe_dev->ccdc_irq0 = res1->start; |
1911 | 1845 | ||
1912 | /* Get VINT1 irq resource */ | 1846 | /* Get VINT1 irq resource */ |
1913 | res1 = platform_get_resource(pdev, | 1847 | res1 = platform_get_resource(pdev, IORESOURCE_IRQ, 1); |
1914 | IORESOURCE_IRQ, 1); | ||
1915 | if (!res1) { | 1848 | if (!res1) { |
1916 | v4l2_err(pdev->dev.driver, | 1849 | v4l2_err(pdev->dev.driver, |
1917 | "Unable to get interrupt for VINT1\n"); | 1850 | "Unable to get interrupt for VINT1\n"); |
1918 | ret = -ENOENT; | 1851 | ret = -ENODEV; |
1919 | goto probe_disable_clock; | 1852 | goto probe_free_ccdc_cfg_mem; |
1920 | } | 1853 | } |
1921 | vpfe_dev->ccdc_irq1 = res1->start; | 1854 | vpfe_dev->ccdc_irq1 = res1->start; |
1922 | 1855 | ||
1923 | /* Get address base of CCDC */ | ||
1924 | res1 = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1925 | if (!res1) { | ||
1926 | v4l2_err(pdev->dev.driver, | ||
1927 | "Unable to get register address map\n"); | ||
1928 | ret = -ENOENT; | ||
1929 | goto probe_disable_clock; | ||
1930 | } | ||
1931 | |||
1932 | ccdc_cfg->ccdc_addr_size = res1->end - res1->start + 1; | ||
1933 | if (!request_mem_region(res1->start, ccdc_cfg->ccdc_addr_size, | ||
1934 | pdev->dev.driver->name)) { | ||
1935 | v4l2_err(pdev->dev.driver, | ||
1936 | "Failed request_mem_region for ccdc base\n"); | ||
1937 | ret = -ENXIO; | ||
1938 | goto probe_disable_clock; | ||
1939 | } | ||
1940 | ccdc_cfg->ccdc_addr = ioremap_nocache(res1->start, | ||
1941 | ccdc_cfg->ccdc_addr_size); | ||
1942 | if (!ccdc_cfg->ccdc_addr) { | ||
1943 | v4l2_err(pdev->dev.driver, "Unable to ioremap ccdc addr\n"); | ||
1944 | ret = -ENXIO; | ||
1945 | goto probe_out_release_mem1; | ||
1946 | } | ||
1947 | |||
1948 | ret = request_irq(vpfe_dev->ccdc_irq0, vpfe_isr, IRQF_DISABLED, | 1856 | ret = request_irq(vpfe_dev->ccdc_irq0, vpfe_isr, IRQF_DISABLED, |
1949 | "vpfe_capture0", vpfe_dev); | 1857 | "vpfe_capture0", vpfe_dev); |
1950 | 1858 | ||
1951 | if (0 != ret) { | 1859 | if (0 != ret) { |
1952 | v4l2_err(pdev->dev.driver, "Unable to request interrupt\n"); | 1860 | v4l2_err(pdev->dev.driver, "Unable to request interrupt\n"); |
1953 | goto probe_out_unmap1; | 1861 | goto probe_free_ccdc_cfg_mem; |
1954 | } | 1862 | } |
1955 | 1863 | ||
1956 | /* Allocate memory for video device */ | 1864 | /* Allocate memory for video device */ |
1957 | vfd = video_device_alloc(); | 1865 | vfd = video_device_alloc(); |
1958 | if (NULL == vfd) { | 1866 | if (NULL == vfd) { |
1959 | ret = -ENOMEM; | 1867 | ret = -ENOMEM; |
1960 | v4l2_err(pdev->dev.driver, | 1868 | v4l2_err(pdev->dev.driver, "Unable to alloc video device\n"); |
1961 | "Unable to alloc video device\n"); | ||
1962 | goto probe_out_release_irq; | 1869 | goto probe_out_release_irq; |
1963 | } | 1870 | } |
1964 | 1871 | ||
@@ -2073,12 +1980,7 @@ probe_out_video_release: | |||
2073 | video_device_release(vpfe_dev->video_dev); | 1980 | video_device_release(vpfe_dev->video_dev); |
2074 | probe_out_release_irq: | 1981 | probe_out_release_irq: |
2075 | free_irq(vpfe_dev->ccdc_irq0, vpfe_dev); | 1982 | free_irq(vpfe_dev->ccdc_irq0, vpfe_dev); |
2076 | probe_out_unmap1: | 1983 | probe_free_ccdc_cfg_mem: |
2077 | iounmap(ccdc_cfg->ccdc_addr); | ||
2078 | probe_out_release_mem1: | ||
2079 | release_mem_region(res1->start, res1->end - res1->start + 1); | ||
2080 | probe_disable_clock: | ||
2081 | vpfe_disable_clock(vpfe_dev); | ||
2082 | mutex_unlock(&ccdc_lock); | 1984 | mutex_unlock(&ccdc_lock); |
2083 | kfree(ccdc_cfg); | 1985 | kfree(ccdc_cfg); |
2084 | probe_free_dev_mem: | 1986 | probe_free_dev_mem: |
@@ -2092,7 +1994,6 @@ probe_free_dev_mem: | |||
2092 | static int __devexit vpfe_remove(struct platform_device *pdev) | 1994 | static int __devexit vpfe_remove(struct platform_device *pdev) |
2093 | { | 1995 | { |
2094 | struct vpfe_device *vpfe_dev = platform_get_drvdata(pdev); | 1996 | struct vpfe_device *vpfe_dev = platform_get_drvdata(pdev); |
2095 | struct resource *res; | ||
2096 | 1997 | ||
2097 | v4l2_info(pdev->dev.driver, "vpfe_remove\n"); | 1998 | v4l2_info(pdev->dev.driver, "vpfe_remove\n"); |
2098 | 1999 | ||
@@ -2100,12 +2001,6 @@ static int __devexit vpfe_remove(struct platform_device *pdev) | |||
2100 | kfree(vpfe_dev->sd); | 2001 | kfree(vpfe_dev->sd); |
2101 | v4l2_device_unregister(&vpfe_dev->v4l2_dev); | 2002 | v4l2_device_unregister(&vpfe_dev->v4l2_dev); |
2102 | video_unregister_device(vpfe_dev->video_dev); | 2003 | video_unregister_device(vpfe_dev->video_dev); |
2103 | mutex_lock(&ccdc_lock); | ||
2104 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
2105 | release_mem_region(res->start, res->end - res->start + 1); | ||
2106 | iounmap(ccdc_cfg->ccdc_addr); | ||
2107 | mutex_unlock(&ccdc_lock); | ||
2108 | vpfe_disable_clock(vpfe_dev); | ||
2109 | kfree(vpfe_dev); | 2004 | kfree(vpfe_dev); |
2110 | kfree(ccdc_cfg); | 2005 | kfree(ccdc_cfg); |
2111 | return 0; | 2006 | return 0; |
diff --git a/drivers/media/video/davinci/vpss.c b/drivers/media/video/davinci/vpss.c index 7ee72ecd3d81..7918680917d0 100644 --- a/drivers/media/video/davinci/vpss.c +++ b/drivers/media/video/davinci/vpss.c | |||
@@ -15,7 +15,7 @@ | |||
15 | * along with this program; if not, write to the Free Software | 15 | * along with this program; if not, write to the Free Software |
16 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 16 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
17 | * | 17 | * |
18 | * common vpss driver for all video drivers. | 18 | * common vpss system module platform driver for all video drivers. |
19 | */ | 19 | */ |
20 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
21 | #include <linux/sched.h> | 21 | #include <linux/sched.h> |
@@ -35,12 +35,52 @@ MODULE_AUTHOR("Texas Instruments"); | |||
35 | /* DM644x defines */ | 35 | /* DM644x defines */ |
36 | #define DM644X_SBL_PCR_VPSS (4) | 36 | #define DM644X_SBL_PCR_VPSS (4) |
37 | 37 | ||
38 | #define DM355_VPSSBL_INTSEL 0x10 | ||
39 | #define DM355_VPSSBL_EVTSEL 0x14 | ||
38 | /* vpss BL register offsets */ | 40 | /* vpss BL register offsets */ |
39 | #define DM355_VPSSBL_CCDCMUX 0x1c | 41 | #define DM355_VPSSBL_CCDCMUX 0x1c |
40 | /* vpss CLK register offsets */ | 42 | /* vpss CLK register offsets */ |
41 | #define DM355_VPSSCLK_CLKCTRL 0x04 | 43 | #define DM355_VPSSCLK_CLKCTRL 0x04 |
42 | /* masks and shifts */ | 44 | /* masks and shifts */ |
43 | #define VPSS_HSSISEL_SHIFT 4 | 45 | #define VPSS_HSSISEL_SHIFT 4 |
46 | /* | ||
47 | * VDINT0 - vpss_int0, VDINT1 - vpss_int1, H3A - vpss_int4, | ||
48 | * IPIPE_INT1_SDR - vpss_int5 | ||
49 | */ | ||
50 | #define DM355_VPSSBL_INTSEL_DEFAULT 0xff83ff10 | ||
51 | /* VENCINT - vpss_int8 */ | ||
52 | #define DM355_VPSSBL_EVTSEL_DEFAULT 0x4 | ||
53 | |||
54 | #define DM365_ISP5_PCCR 0x04 | ||
55 | #define DM365_ISP5_INTSEL1 0x10 | ||
56 | #define DM365_ISP5_INTSEL2 0x14 | ||
57 | #define DM365_ISP5_INTSEL3 0x18 | ||
58 | #define DM365_ISP5_CCDCMUX 0x20 | ||
59 | #define DM365_ISP5_PG_FRAME_SIZE 0x28 | ||
60 | #define DM365_VPBE_CLK_CTRL 0x00 | ||
61 | /* | ||
62 | * vpss interrupts. VDINT0 - vpss_int0, VDINT1 - vpss_int1, | ||
63 | * AF - vpss_int3 | ||
64 | */ | ||
65 | #define DM365_ISP5_INTSEL1_DEFAULT 0x0b1f0100 | ||
66 | /* AEW - vpss_int6, RSZ_INT_DMA - vpss_int5 */ | ||
67 | #define DM365_ISP5_INTSEL2_DEFAULT 0x1f0a0f1f | ||
68 | /* VENC - vpss_int8 */ | ||
69 | #define DM365_ISP5_INTSEL3_DEFAULT 0x00000015 | ||
70 | |||
71 | /* masks and shifts for DM365*/ | ||
72 | #define DM365_CCDC_PG_VD_POL_SHIFT 0 | ||
73 | #define DM365_CCDC_PG_HD_POL_SHIFT 1 | ||
74 | |||
75 | #define CCD_SRC_SEL_MASK (BIT_MASK(5) | BIT_MASK(4)) | ||
76 | #define CCD_SRC_SEL_SHIFT 4 | ||
77 | |||
78 | /* Different SoC platforms supported by this driver */ | ||
79 | enum vpss_platform_type { | ||
80 | DM644X, | ||
81 | DM355, | ||
82 | DM365, | ||
83 | }; | ||
44 | 84 | ||
45 | /* | 85 | /* |
46 | * vpss operations. Depends on platform. Not all functions are available | 86 | * vpss operations. Depends on platform. Not all functions are available |
@@ -59,13 +99,9 @@ struct vpss_hw_ops { | |||
59 | 99 | ||
60 | /* vpss configuration */ | 100 | /* vpss configuration */ |
61 | struct vpss_oper_config { | 101 | struct vpss_oper_config { |
62 | __iomem void *vpss_bl_regs_base; | 102 | __iomem void *vpss_regs_base0; |
63 | __iomem void *vpss_regs_base; | 103 | __iomem void *vpss_regs_base1; |
64 | struct resource *r1; | 104 | enum vpss_platform_type platform; |
65 | resource_size_t len1; | ||
66 | struct resource *r2; | ||
67 | resource_size_t len2; | ||
68 | char vpss_name[32]; | ||
69 | spinlock_t vpss_lock; | 105 | spinlock_t vpss_lock; |
70 | struct vpss_hw_ops hw_ops; | 106 | struct vpss_hw_ops hw_ops; |
71 | }; | 107 | }; |
@@ -75,22 +111,46 @@ static struct vpss_oper_config oper_cfg; | |||
75 | /* register access routines */ | 111 | /* register access routines */ |
76 | static inline u32 bl_regr(u32 offset) | 112 | static inline u32 bl_regr(u32 offset) |
77 | { | 113 | { |
78 | return __raw_readl(oper_cfg.vpss_bl_regs_base + offset); | 114 | return __raw_readl(oper_cfg.vpss_regs_base0 + offset); |
79 | } | 115 | } |
80 | 116 | ||
81 | static inline void bl_regw(u32 val, u32 offset) | 117 | static inline void bl_regw(u32 val, u32 offset) |
82 | { | 118 | { |
83 | __raw_writel(val, oper_cfg.vpss_bl_regs_base + offset); | 119 | __raw_writel(val, oper_cfg.vpss_regs_base0 + offset); |
84 | } | 120 | } |
85 | 121 | ||
86 | static inline u32 vpss_regr(u32 offset) | 122 | static inline u32 vpss_regr(u32 offset) |
87 | { | 123 | { |
88 | return __raw_readl(oper_cfg.vpss_regs_base + offset); | 124 | return __raw_readl(oper_cfg.vpss_regs_base1 + offset); |
89 | } | 125 | } |
90 | 126 | ||
91 | static inline void vpss_regw(u32 val, u32 offset) | 127 | static inline void vpss_regw(u32 val, u32 offset) |
92 | { | 128 | { |
93 | __raw_writel(val, oper_cfg.vpss_regs_base + offset); | 129 | __raw_writel(val, oper_cfg.vpss_regs_base1 + offset); |
130 | } | ||
131 | |||
132 | /* For DM365 only */ | ||
133 | static inline u32 isp5_read(u32 offset) | ||
134 | { | ||
135 | return __raw_readl(oper_cfg.vpss_regs_base0 + offset); | ||
136 | } | ||
137 | |||
138 | /* For DM365 only */ | ||
139 | static inline void isp5_write(u32 val, u32 offset) | ||
140 | { | ||
141 | __raw_writel(val, oper_cfg.vpss_regs_base0 + offset); | ||
142 | } | ||
143 | |||
144 | static void dm365_select_ccdc_source(enum vpss_ccdc_source_sel src_sel) | ||
145 | { | ||
146 | u32 temp = isp5_read(DM365_ISP5_CCDCMUX) & ~CCD_SRC_SEL_MASK; | ||
147 | |||
148 | /* if we are using pattern generator, enable it */ | ||
149 | if (src_sel == VPSS_PGLPBK || src_sel == VPSS_CCDCPG) | ||
150 | temp |= 0x08; | ||
151 | |||
152 | temp |= (src_sel << CCD_SRC_SEL_SHIFT); | ||
153 | isp5_write(temp, DM365_ISP5_CCDCMUX); | ||
94 | } | 154 | } |
95 | 155 | ||
96 | static void dm355_select_ccdc_source(enum vpss_ccdc_source_sel src_sel) | 156 | static void dm355_select_ccdc_source(enum vpss_ccdc_source_sel src_sel) |
@@ -101,9 +161,9 @@ static void dm355_select_ccdc_source(enum vpss_ccdc_source_sel src_sel) | |||
101 | int vpss_select_ccdc_source(enum vpss_ccdc_source_sel src_sel) | 161 | int vpss_select_ccdc_source(enum vpss_ccdc_source_sel src_sel) |
102 | { | 162 | { |
103 | if (!oper_cfg.hw_ops.select_ccdc_source) | 163 | if (!oper_cfg.hw_ops.select_ccdc_source) |
104 | return -1; | 164 | return -EINVAL; |
105 | 165 | ||
106 | dm355_select_ccdc_source(src_sel); | 166 | oper_cfg.hw_ops.select_ccdc_source(src_sel); |
107 | return 0; | 167 | return 0; |
108 | } | 168 | } |
109 | EXPORT_SYMBOL(vpss_select_ccdc_source); | 169 | EXPORT_SYMBOL(vpss_select_ccdc_source); |
@@ -114,7 +174,7 @@ static int dm644x_clear_wbl_overflow(enum vpss_wbl_sel wbl_sel) | |||
114 | 174 | ||
115 | if (wbl_sel < VPSS_PCR_AEW_WBL_0 || | 175 | if (wbl_sel < VPSS_PCR_AEW_WBL_0 || |
116 | wbl_sel > VPSS_PCR_CCDC_WBL_O) | 176 | wbl_sel > VPSS_PCR_CCDC_WBL_O) |
117 | return -1; | 177 | return -EINVAL; |
118 | 178 | ||
119 | /* writing a 0 clear the overflow */ | 179 | /* writing a 0 clear the overflow */ |
120 | mask = ~(mask << wbl_sel); | 180 | mask = ~(mask << wbl_sel); |
@@ -126,7 +186,7 @@ static int dm644x_clear_wbl_overflow(enum vpss_wbl_sel wbl_sel) | |||
126 | int vpss_clear_wbl_overflow(enum vpss_wbl_sel wbl_sel) | 186 | int vpss_clear_wbl_overflow(enum vpss_wbl_sel wbl_sel) |
127 | { | 187 | { |
128 | if (!oper_cfg.hw_ops.clear_wbl_overflow) | 188 | if (!oper_cfg.hw_ops.clear_wbl_overflow) |
129 | return -1; | 189 | return -EINVAL; |
130 | 190 | ||
131 | return oper_cfg.hw_ops.clear_wbl_overflow(wbl_sel); | 191 | return oper_cfg.hw_ops.clear_wbl_overflow(wbl_sel); |
132 | } | 192 | } |
@@ -166,7 +226,7 @@ static int dm355_enable_clock(enum vpss_clock_sel clock_sel, int en) | |||
166 | default: | 226 | default: |
167 | printk(KERN_ERR "dm355_enable_clock:" | 227 | printk(KERN_ERR "dm355_enable_clock:" |
168 | " Invalid selector: %d\n", clock_sel); | 228 | " Invalid selector: %d\n", clock_sel); |
169 | return -1; | 229 | return -EINVAL; |
170 | } | 230 | } |
171 | 231 | ||
172 | spin_lock_irqsave(&oper_cfg.vpss_lock, flags); | 232 | spin_lock_irqsave(&oper_cfg.vpss_lock, flags); |
@@ -181,100 +241,221 @@ static int dm355_enable_clock(enum vpss_clock_sel clock_sel, int en) | |||
181 | return 0; | 241 | return 0; |
182 | } | 242 | } |
183 | 243 | ||
244 | static int dm365_enable_clock(enum vpss_clock_sel clock_sel, int en) | ||
245 | { | ||
246 | unsigned long flags; | ||
247 | u32 utemp, mask = 0x1, shift = 0, offset = DM365_ISP5_PCCR; | ||
248 | u32 (*read)(u32 offset) = isp5_read; | ||
249 | void(*write)(u32 val, u32 offset) = isp5_write; | ||
250 | |||
251 | switch (clock_sel) { | ||
252 | case VPSS_BL_CLOCK: | ||
253 | break; | ||
254 | case VPSS_CCDC_CLOCK: | ||
255 | shift = 1; | ||
256 | break; | ||
257 | case VPSS_H3A_CLOCK: | ||
258 | shift = 2; | ||
259 | break; | ||
260 | case VPSS_RSZ_CLOCK: | ||
261 | shift = 3; | ||
262 | break; | ||
263 | case VPSS_IPIPE_CLOCK: | ||
264 | shift = 4; | ||
265 | break; | ||
266 | case VPSS_IPIPEIF_CLOCK: | ||
267 | shift = 5; | ||
268 | break; | ||
269 | case VPSS_PCLK_INTERNAL: | ||
270 | shift = 6; | ||
271 | break; | ||
272 | case VPSS_PSYNC_CLOCK_SEL: | ||
273 | shift = 7; | ||
274 | break; | ||
275 | case VPSS_VPBE_CLOCK: | ||
276 | read = vpss_regr; | ||
277 | write = vpss_regw; | ||
278 | offset = DM365_VPBE_CLK_CTRL; | ||
279 | break; | ||
280 | case VPSS_VENC_CLOCK_SEL: | ||
281 | shift = 2; | ||
282 | read = vpss_regr; | ||
283 | write = vpss_regw; | ||
284 | offset = DM365_VPBE_CLK_CTRL; | ||
285 | break; | ||
286 | case VPSS_LDC_CLOCK: | ||
287 | shift = 3; | ||
288 | read = vpss_regr; | ||
289 | write = vpss_regw; | ||
290 | offset = DM365_VPBE_CLK_CTRL; | ||
291 | break; | ||
292 | case VPSS_FDIF_CLOCK: | ||
293 | shift = 4; | ||
294 | read = vpss_regr; | ||
295 | write = vpss_regw; | ||
296 | offset = DM365_VPBE_CLK_CTRL; | ||
297 | break; | ||
298 | case VPSS_OSD_CLOCK_SEL: | ||
299 | shift = 6; | ||
300 | read = vpss_regr; | ||
301 | write = vpss_regw; | ||
302 | offset = DM365_VPBE_CLK_CTRL; | ||
303 | break; | ||
304 | case VPSS_LDC_CLOCK_SEL: | ||
305 | shift = 7; | ||
306 | read = vpss_regr; | ||
307 | write = vpss_regw; | ||
308 | offset = DM365_VPBE_CLK_CTRL; | ||
309 | break; | ||
310 | default: | ||
311 | printk(KERN_ERR "dm365_enable_clock: Invalid selector: %d\n", | ||
312 | clock_sel); | ||
313 | return -1; | ||
314 | } | ||
315 | |||
316 | spin_lock_irqsave(&oper_cfg.vpss_lock, flags); | ||
317 | utemp = read(offset); | ||
318 | if (!en) { | ||
319 | mask = ~mask; | ||
320 | utemp &= (mask << shift); | ||
321 | } else | ||
322 | utemp |= (mask << shift); | ||
323 | |||
324 | write(utemp, offset); | ||
325 | spin_unlock_irqrestore(&oper_cfg.vpss_lock, flags); | ||
326 | |||
327 | return 0; | ||
328 | } | ||
329 | |||
184 | int vpss_enable_clock(enum vpss_clock_sel clock_sel, int en) | 330 | int vpss_enable_clock(enum vpss_clock_sel clock_sel, int en) |
185 | { | 331 | { |
186 | if (!oper_cfg.hw_ops.enable_clock) | 332 | if (!oper_cfg.hw_ops.enable_clock) |
187 | return -1; | 333 | return -EINVAL; |
188 | 334 | ||
189 | return oper_cfg.hw_ops.enable_clock(clock_sel, en); | 335 | return oper_cfg.hw_ops.enable_clock(clock_sel, en); |
190 | } | 336 | } |
191 | EXPORT_SYMBOL(vpss_enable_clock); | 337 | EXPORT_SYMBOL(vpss_enable_clock); |
192 | 338 | ||
339 | void dm365_vpss_set_sync_pol(struct vpss_sync_pol sync) | ||
340 | { | ||
341 | int val = 0; | ||
342 | val = isp5_read(DM365_ISP5_CCDCMUX); | ||
343 | |||
344 | val |= (sync.ccdpg_hdpol << DM365_CCDC_PG_HD_POL_SHIFT); | ||
345 | val |= (sync.ccdpg_vdpol << DM365_CCDC_PG_VD_POL_SHIFT); | ||
346 | |||
347 | isp5_write(val, DM365_ISP5_CCDCMUX); | ||
348 | } | ||
349 | EXPORT_SYMBOL(dm365_vpss_set_sync_pol); | ||
350 | |||
351 | void dm365_vpss_set_pg_frame_size(struct vpss_pg_frame_size frame_size) | ||
352 | { | ||
353 | int current_reg = ((frame_size.hlpfr >> 1) - 1) << 16; | ||
354 | |||
355 | current_reg |= (frame_size.pplen - 1); | ||
356 | isp5_write(current_reg, DM365_ISP5_PG_FRAME_SIZE); | ||
357 | } | ||
358 | EXPORT_SYMBOL(dm365_vpss_set_pg_frame_size); | ||
359 | |||
193 | static int __init vpss_probe(struct platform_device *pdev) | 360 | static int __init vpss_probe(struct platform_device *pdev) |
194 | { | 361 | { |
195 | int status, dm355 = 0; | 362 | struct resource *r1, *r2; |
363 | char *platform_name; | ||
364 | int status; | ||
196 | 365 | ||
197 | if (!pdev->dev.platform_data) { | 366 | if (!pdev->dev.platform_data) { |
198 | dev_err(&pdev->dev, "no platform data\n"); | 367 | dev_err(&pdev->dev, "no platform data\n"); |
199 | return -ENOENT; | 368 | return -ENOENT; |
200 | } | 369 | } |
201 | strcpy(oper_cfg.vpss_name, pdev->dev.platform_data); | ||
202 | 370 | ||
203 | if (!strcmp(oper_cfg.vpss_name, "dm355_vpss")) | 371 | platform_name = pdev->dev.platform_data; |
204 | dm355 = 1; | 372 | if (!strcmp(platform_name, "dm355_vpss")) |
205 | else if (strcmp(oper_cfg.vpss_name, "dm644x_vpss")) { | 373 | oper_cfg.platform = DM355; |
374 | else if (!strcmp(platform_name, "dm365_vpss")) | ||
375 | oper_cfg.platform = DM365; | ||
376 | else if (!strcmp(platform_name, "dm644x_vpss")) | ||
377 | oper_cfg.platform = DM644X; | ||
378 | else { | ||
206 | dev_err(&pdev->dev, "vpss driver not supported on" | 379 | dev_err(&pdev->dev, "vpss driver not supported on" |
207 | " this platform\n"); | 380 | " this platform\n"); |
208 | return -ENODEV; | 381 | return -ENODEV; |
209 | } | 382 | } |
210 | 383 | ||
211 | dev_info(&pdev->dev, "%s vpss probed\n", oper_cfg.vpss_name); | 384 | dev_info(&pdev->dev, "%s vpss probed\n", platform_name); |
212 | oper_cfg.r1 = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 385 | r1 = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
213 | if (!oper_cfg.r1) | 386 | if (!r1) |
214 | return -ENOENT; | 387 | return -ENOENT; |
215 | 388 | ||
216 | oper_cfg.len1 = oper_cfg.r1->end - oper_cfg.r1->start + 1; | 389 | r1 = request_mem_region(r1->start, resource_size(r1), r1->name); |
217 | 390 | if (!r1) | |
218 | oper_cfg.r1 = request_mem_region(oper_cfg.r1->start, oper_cfg.len1, | ||
219 | oper_cfg.r1->name); | ||
220 | if (!oper_cfg.r1) | ||
221 | return -EBUSY; | 391 | return -EBUSY; |
222 | 392 | ||
223 | oper_cfg.vpss_bl_regs_base = ioremap(oper_cfg.r1->start, oper_cfg.len1); | 393 | oper_cfg.vpss_regs_base0 = ioremap(r1->start, resource_size(r1)); |
224 | if (!oper_cfg.vpss_bl_regs_base) { | 394 | if (!oper_cfg.vpss_regs_base0) { |
225 | status = -EBUSY; | 395 | status = -EBUSY; |
226 | goto fail1; | 396 | goto fail1; |
227 | } | 397 | } |
228 | 398 | ||
229 | if (dm355) { | 399 | if (oper_cfg.platform == DM355 || oper_cfg.platform == DM365) { |
230 | oper_cfg.r2 = platform_get_resource(pdev, IORESOURCE_MEM, 1); | 400 | r2 = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
231 | if (!oper_cfg.r2) { | 401 | if (!r2) { |
232 | status = -ENOENT; | 402 | status = -ENOENT; |
233 | goto fail2; | 403 | goto fail2; |
234 | } | 404 | } |
235 | oper_cfg.len2 = oper_cfg.r2->end - oper_cfg.r2->start + 1; | 405 | r2 = request_mem_region(r2->start, resource_size(r2), r2->name); |
236 | oper_cfg.r2 = request_mem_region(oper_cfg.r2->start, | 406 | if (!r2) { |
237 | oper_cfg.len2, | ||
238 | oper_cfg.r2->name); | ||
239 | if (!oper_cfg.r2) { | ||
240 | status = -EBUSY; | 407 | status = -EBUSY; |
241 | goto fail2; | 408 | goto fail2; |
242 | } | 409 | } |
243 | 410 | ||
244 | oper_cfg.vpss_regs_base = ioremap(oper_cfg.r2->start, | 411 | oper_cfg.vpss_regs_base1 = ioremap(r2->start, |
245 | oper_cfg.len2); | 412 | resource_size(r2)); |
246 | if (!oper_cfg.vpss_regs_base) { | 413 | if (!oper_cfg.vpss_regs_base1) { |
247 | status = -EBUSY; | 414 | status = -EBUSY; |
248 | goto fail3; | 415 | goto fail3; |
249 | } | 416 | } |
250 | } | 417 | } |
251 | 418 | ||
252 | if (dm355) { | 419 | if (oper_cfg.platform == DM355) { |
253 | oper_cfg.hw_ops.enable_clock = dm355_enable_clock; | 420 | oper_cfg.hw_ops.enable_clock = dm355_enable_clock; |
254 | oper_cfg.hw_ops.select_ccdc_source = dm355_select_ccdc_source; | 421 | oper_cfg.hw_ops.select_ccdc_source = dm355_select_ccdc_source; |
422 | /* Setup vpss interrupts */ | ||
423 | bl_regw(DM355_VPSSBL_INTSEL_DEFAULT, DM355_VPSSBL_INTSEL); | ||
424 | bl_regw(DM355_VPSSBL_EVTSEL_DEFAULT, DM355_VPSSBL_EVTSEL); | ||
425 | } else if (oper_cfg.platform == DM365) { | ||
426 | oper_cfg.hw_ops.enable_clock = dm365_enable_clock; | ||
427 | oper_cfg.hw_ops.select_ccdc_source = dm365_select_ccdc_source; | ||
428 | /* Setup vpss interrupts */ | ||
429 | isp5_write(DM365_ISP5_INTSEL1_DEFAULT, DM365_ISP5_INTSEL1); | ||
430 | isp5_write(DM365_ISP5_INTSEL2_DEFAULT, DM365_ISP5_INTSEL2); | ||
431 | isp5_write(DM365_ISP5_INTSEL3_DEFAULT, DM365_ISP5_INTSEL3); | ||
255 | } else | 432 | } else |
256 | oper_cfg.hw_ops.clear_wbl_overflow = dm644x_clear_wbl_overflow; | 433 | oper_cfg.hw_ops.clear_wbl_overflow = dm644x_clear_wbl_overflow; |
257 | 434 | ||
258 | spin_lock_init(&oper_cfg.vpss_lock); | 435 | spin_lock_init(&oper_cfg.vpss_lock); |
259 | dev_info(&pdev->dev, "%s vpss probe success\n", oper_cfg.vpss_name); | 436 | dev_info(&pdev->dev, "%s vpss probe success\n", platform_name); |
260 | return 0; | 437 | return 0; |
261 | 438 | ||
262 | fail3: | 439 | fail3: |
263 | release_mem_region(oper_cfg.r2->start, oper_cfg.len2); | 440 | release_mem_region(r2->start, resource_size(r2)); |
264 | fail2: | 441 | fail2: |
265 | iounmap(oper_cfg.vpss_bl_regs_base); | 442 | iounmap(oper_cfg.vpss_regs_base0); |
266 | fail1: | 443 | fail1: |
267 | release_mem_region(oper_cfg.r1->start, oper_cfg.len1); | 444 | release_mem_region(r1->start, resource_size(r1)); |
268 | return status; | 445 | return status; |
269 | } | 446 | } |
270 | 447 | ||
271 | static int __devexit vpss_remove(struct platform_device *pdev) | 448 | static int __devexit vpss_remove(struct platform_device *pdev) |
272 | { | 449 | { |
273 | iounmap(oper_cfg.vpss_bl_regs_base); | 450 | struct resource *res; |
274 | release_mem_region(oper_cfg.r1->start, oper_cfg.len1); | 451 | |
275 | if (!strcmp(oper_cfg.vpss_name, "dm355_vpss")) { | 452 | iounmap(oper_cfg.vpss_regs_base0); |
276 | iounmap(oper_cfg.vpss_regs_base); | 453 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
277 | release_mem_region(oper_cfg.r2->start, oper_cfg.len2); | 454 | release_mem_region(res->start, resource_size(res)); |
455 | if (oper_cfg.platform == DM355 || oper_cfg.platform == DM365) { | ||
456 | iounmap(oper_cfg.vpss_regs_base1); | ||
457 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
458 | release_mem_region(res->start, resource_size(res)); | ||
278 | } | 459 | } |
279 | return 0; | 460 | return 0; |
280 | } | 461 | } |
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 25100001ffff..ecbcefb08739 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c | |||
@@ -232,6 +232,12 @@ static struct em28xx_reg_seq vc211a_enable[] = { | |||
232 | { -1, -1, -1, -1}, | 232 | { -1, -1, -1, -1}, |
233 | }; | 233 | }; |
234 | 234 | ||
235 | static struct em28xx_reg_seq dikom_dk300_digital[] = { | ||
236 | {EM28XX_R08_GPIO, 0x6e, ~EM_GPIO_4, 10}, | ||
237 | {EM2880_R04_GPO, 0x08, 0xff, 10}, | ||
238 | { -1, -1, -1, -1}, | ||
239 | }; | ||
240 | |||
235 | 241 | ||
236 | /* | 242 | /* |
237 | * Board definitions | 243 | * Board definitions |
@@ -461,21 +467,30 @@ struct em28xx_board em28xx_boards[] = { | |||
461 | .name = "Leadtek Winfast USB II Deluxe", | 467 | .name = "Leadtek Winfast USB II Deluxe", |
462 | .valid = EM28XX_BOARD_NOT_VALIDATED, | 468 | .valid = EM28XX_BOARD_NOT_VALIDATED, |
463 | .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, | 469 | .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, |
464 | .tda9887_conf = TDA9887_PRESENT, | 470 | .has_ir_i2c = 1, |
471 | .tvaudio_addr = 0x58, | ||
472 | .tda9887_conf = TDA9887_PRESENT | | ||
473 | TDA9887_PORT2_ACTIVE | | ||
474 | TDA9887_QSS, | ||
465 | .decoder = EM28XX_SAA711X, | 475 | .decoder = EM28XX_SAA711X, |
476 | .adecoder = EM28XX_TVAUDIO, | ||
466 | .input = { { | 477 | .input = { { |
467 | .type = EM28XX_VMUX_TELEVISION, | 478 | .type = EM28XX_VMUX_TELEVISION, |
468 | .vmux = SAA7115_COMPOSITE2, | 479 | .vmux = SAA7115_COMPOSITE4, |
469 | .amux = EM28XX_AMUX_VIDEO, | 480 | .amux = EM28XX_AMUX_AUX, |
470 | }, { | 481 | }, { |
471 | .type = EM28XX_VMUX_COMPOSITE1, | 482 | .type = EM28XX_VMUX_COMPOSITE1, |
472 | .vmux = SAA7115_COMPOSITE0, | 483 | .vmux = SAA7115_COMPOSITE5, |
473 | .amux = EM28XX_AMUX_LINE_IN, | 484 | .amux = EM28XX_AMUX_LINE_IN, |
474 | }, { | 485 | }, { |
475 | .type = EM28XX_VMUX_SVIDEO, | 486 | .type = EM28XX_VMUX_SVIDEO, |
476 | .vmux = SAA7115_COMPOSITE0, | 487 | .vmux = SAA7115_SVIDEO3, |
477 | .amux = EM28XX_AMUX_LINE_IN, | 488 | .amux = EM28XX_AMUX_LINE_IN, |
478 | } }, | 489 | } }, |
490 | .radio = { | ||
491 | .type = EM28XX_RADIO, | ||
492 | .amux = EM28XX_AMUX_AUX, | ||
493 | } | ||
479 | }, | 494 | }, |
480 | [EM2820_BOARD_VIDEOLOGY_20K14XUSB] = { | 495 | [EM2820_BOARD_VIDEOLOGY_20K14XUSB] = { |
481 | .name = "Videology 20K14XUSB USB2.0", | 496 | .name = "Videology 20K14XUSB USB2.0", |
@@ -730,11 +745,12 @@ struct em28xx_board em28xx_boards[] = { | |||
730 | 745 | ||
731 | [EM2880_BOARD_TERRATEC_HYBRID_XS_FR] = { | 746 | [EM2880_BOARD_TERRATEC_HYBRID_XS_FR] = { |
732 | .name = "Terratec Hybrid XS Secam", | 747 | .name = "Terratec Hybrid XS Secam", |
733 | .valid = EM28XX_BOARD_NOT_VALIDATED, | ||
734 | .has_msp34xx = 1, | 748 | .has_msp34xx = 1, |
735 | .tuner_type = TUNER_XC2028, | 749 | .tuner_type = TUNER_XC2028, |
736 | .tuner_gpio = default_tuner_gpio, | 750 | .tuner_gpio = default_tuner_gpio, |
737 | .decoder = EM28XX_TVP5150, | 751 | .decoder = EM28XX_TVP5150, |
752 | .has_dvb = 1, | ||
753 | .dvb_gpio = default_digital, | ||
738 | .input = { { | 754 | .input = { { |
739 | .type = EM28XX_VMUX_TELEVISION, | 755 | .type = EM28XX_VMUX_TELEVISION, |
740 | .vmux = TVP5150_COMPOSITE0, | 756 | .vmux = TVP5150_COMPOSITE0, |
@@ -1265,6 +1281,7 @@ struct em28xx_board em28xx_boards[] = { | |||
1265 | .decoder = EM28XX_SAA711X, | 1281 | .decoder = EM28XX_SAA711X, |
1266 | .has_dvb = 1, | 1282 | .has_dvb = 1, |
1267 | .dvb_gpio = em2882_kworld_315u_digital, | 1283 | .dvb_gpio = em2882_kworld_315u_digital, |
1284 | .ir_codes = &ir_codes_kworld_315u_table, | ||
1268 | .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, | 1285 | .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, |
1269 | .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE, | 1286 | .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE, |
1270 | /* Analog mode - still not ready */ | 1287 | /* Analog mode - still not ready */ |
@@ -1431,6 +1448,21 @@ struct em28xx_board em28xx_boards[] = { | |||
1431 | .gpio = hauppauge_wintv_hvr_900_analog, | 1448 | .gpio = hauppauge_wintv_hvr_900_analog, |
1432 | } }, | 1449 | } }, |
1433 | }, | 1450 | }, |
1451 | [EM2882_BOARD_DIKOM_DK300] = { | ||
1452 | .name = "Dikom DK300", | ||
1453 | .tuner_type = TUNER_XC2028, | ||
1454 | .tuner_gpio = default_tuner_gpio, | ||
1455 | .decoder = EM28XX_TVP5150, | ||
1456 | .mts_firmware = 1, | ||
1457 | .has_dvb = 1, | ||
1458 | .dvb_gpio = dikom_dk300_digital, | ||
1459 | .input = { { | ||
1460 | .type = EM28XX_VMUX_TELEVISION, | ||
1461 | .vmux = TVP5150_COMPOSITE0, | ||
1462 | .amux = EM28XX_AMUX_VIDEO, | ||
1463 | .gpio = default_analog, | ||
1464 | } }, | ||
1465 | }, | ||
1434 | [EM2883_BOARD_KWORLD_HYBRID_330U] = { | 1466 | [EM2883_BOARD_KWORLD_HYBRID_330U] = { |
1435 | .name = "Kworld PlusTV HD Hybrid 330", | 1467 | .name = "Kworld PlusTV HD Hybrid 330", |
1436 | .tuner_type = TUNER_XC2028, | 1468 | .tuner_type = TUNER_XC2028, |
@@ -1751,6 +1783,7 @@ static struct em28xx_hash_table em28xx_eeprom_hash[] = { | |||
1751 | {0xcee44a99, EM2882_BOARD_EVGA_INDTUBE, TUNER_XC2028}, | 1783 | {0xcee44a99, EM2882_BOARD_EVGA_INDTUBE, TUNER_XC2028}, |
1752 | {0xb8846b20, EM2881_BOARD_PINNACLE_HYBRID_PRO, TUNER_XC2028}, | 1784 | {0xb8846b20, EM2881_BOARD_PINNACLE_HYBRID_PRO, TUNER_XC2028}, |
1753 | {0x63f653bd, EM2870_BOARD_REDDO_DVB_C_USB_BOX, TUNER_ABSENT}, | 1785 | {0x63f653bd, EM2870_BOARD_REDDO_DVB_C_USB_BOX, TUNER_ABSENT}, |
1786 | {0x4e913442, EM2882_BOARD_DIKOM_DK300, TUNER_XC2028}, | ||
1754 | }; | 1787 | }; |
1755 | 1788 | ||
1756 | /* I2C devicelist hash table for devices with generic USB IDs */ | 1789 | /* I2C devicelist hash table for devices with generic USB IDs */ |
@@ -2103,6 +2136,7 @@ static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl) | |||
2103 | ctl->demod = XC3028_FE_DEFAULT; | 2136 | ctl->demod = XC3028_FE_DEFAULT; |
2104 | break; | 2137 | break; |
2105 | case EM2883_BOARD_KWORLD_HYBRID_330U: | 2138 | case EM2883_BOARD_KWORLD_HYBRID_330U: |
2139 | case EM2882_BOARD_DIKOM_DK300: | ||
2106 | ctl->demod = XC3028_FE_CHINA; | 2140 | ctl->demod = XC3028_FE_CHINA; |
2107 | ctl->fname = XC2028_DEFAULT_FIRMWARE; | 2141 | ctl->fname = XC2028_DEFAULT_FIRMWARE; |
2108 | break; | 2142 | break; |
@@ -2259,9 +2293,12 @@ static int em28xx_hint_board(struct em28xx *dev) | |||
2259 | /* ----------------------------------------------------------------------- */ | 2293 | /* ----------------------------------------------------------------------- */ |
2260 | void em28xx_register_i2c_ir(struct em28xx *dev) | 2294 | void em28xx_register_i2c_ir(struct em28xx *dev) |
2261 | { | 2295 | { |
2296 | /* Leadtek winfast tv USBII deluxe can find a non working IR-device */ | ||
2297 | /* at address 0x18, so if that address is needed for another board in */ | ||
2298 | /* the future, please put it after 0x1f. */ | ||
2262 | struct i2c_board_info info; | 2299 | struct i2c_board_info info; |
2263 | const unsigned short addr_list[] = { | 2300 | const unsigned short addr_list[] = { |
2264 | 0x30, 0x47, I2C_CLIENT_END | 2301 | 0x1f, 0x30, 0x47, I2C_CLIENT_END |
2265 | }; | 2302 | }; |
2266 | 2303 | ||
2267 | if (disable_ir) | 2304 | if (disable_ir) |
@@ -2288,6 +2325,10 @@ void em28xx_register_i2c_ir(struct em28xx *dev) | |||
2288 | dev->init_data.ir_codes = &ir_codes_rc5_hauppauge_new_table; | 2325 | dev->init_data.ir_codes = &ir_codes_rc5_hauppauge_new_table; |
2289 | dev->init_data.get_key = em28xx_get_key_em_haup; | 2326 | dev->init_data.get_key = em28xx_get_key_em_haup; |
2290 | dev->init_data.name = "i2c IR (EM2840 Hauppauge)"; | 2327 | dev->init_data.name = "i2c IR (EM2840 Hauppauge)"; |
2328 | case EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE: | ||
2329 | dev->init_data.ir_codes = &ir_codes_winfast_usbii_deluxe_table;; | ||
2330 | dev->init_data.get_key = em28xx_get_key_winfast_usbii_deluxe; | ||
2331 | dev->init_data.name = "i2c IR (EM2820 Winfast TV USBII Deluxe)"; | ||
2291 | break; | 2332 | break; |
2292 | } | 2333 | } |
2293 | 2334 | ||
@@ -2381,6 +2422,31 @@ void em28xx_card_setup(struct em28xx *dev) | |||
2381 | em28xx_gpio_set(dev, dev->board.tuner_gpio); | 2422 | em28xx_gpio_set(dev, dev->board.tuner_gpio); |
2382 | em28xx_set_mode(dev, EM28XX_ANALOG_MODE); | 2423 | em28xx_set_mode(dev, EM28XX_ANALOG_MODE); |
2383 | break; | 2424 | break; |
2425 | |||
2426 | /* | ||
2427 | * The Dikom DK300 is detected as an Kworld VS-DVB-T 323UR. | ||
2428 | * | ||
2429 | * This occurs because they share identical USB vendor and | ||
2430 | * product IDs. | ||
2431 | * | ||
2432 | * What we do here is look up the EEPROM hash of the Dikom | ||
2433 | * and if it is found then we decide that we do not have | ||
2434 | * a Kworld and reset the device to the Dikom instead. | ||
2435 | * | ||
2436 | * This solution is only valid if they do not share eeprom | ||
2437 | * hash identities which has not been determined as yet. | ||
2438 | */ | ||
2439 | case EM2882_BOARD_KWORLD_VS_DVBT: | ||
2440 | if (!em28xx_hint_board(dev)) | ||
2441 | em28xx_set_model(dev); | ||
2442 | |||
2443 | /* In cases where we had to use a board hint, the call to | ||
2444 | em28xx_set_mode() in em28xx_pre_card_setup() was a no-op, | ||
2445 | so make the call now so the analog GPIOs are set properly | ||
2446 | before probing the i2c bus. */ | ||
2447 | em28xx_gpio_set(dev, dev->board.tuner_gpio); | ||
2448 | em28xx_set_mode(dev, EM28XX_ANALOG_MODE); | ||
2449 | break; | ||
2384 | } | 2450 | } |
2385 | 2451 | ||
2386 | #if defined(CONFIG_MODULES) && defined(MODULE) | 2452 | #if defined(CONFIG_MODULES) && defined(MODULE) |
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index b311d4514bdf..5a37eccbd7d6 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c | |||
@@ -691,9 +691,15 @@ int em28xx_set_outfmt(struct em28xx *dev) | |||
691 | if (em28xx_vbi_supported(dev) == 1) { | 691 | if (em28xx_vbi_supported(dev) == 1) { |
692 | vinctrl |= EM28XX_VINCTRL_VBI_RAW; | 692 | vinctrl |= EM28XX_VINCTRL_VBI_RAW; |
693 | em28xx_write_reg(dev, EM28XX_R34_VBI_START_H, 0x00); | 693 | em28xx_write_reg(dev, EM28XX_R34_VBI_START_H, 0x00); |
694 | em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x09); | 694 | em28xx_write_reg(dev, EM28XX_R36_VBI_WIDTH, dev->vbi_width/4); |
695 | em28xx_write_reg(dev, EM28XX_R36_VBI_WIDTH, 0xb4); | 695 | em28xx_write_reg(dev, EM28XX_R37_VBI_HEIGHT, dev->vbi_height); |
696 | em28xx_write_reg(dev, EM28XX_R37_VBI_HEIGHT, 0x0c); | 696 | if (dev->norm & V4L2_STD_525_60) { |
697 | /* NTSC */ | ||
698 | em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x09); | ||
699 | } else if (dev->norm & V4L2_STD_625_50) { | ||
700 | /* PAL */ | ||
701 | em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x07); | ||
702 | } | ||
697 | } | 703 | } |
698 | 704 | ||
699 | return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, vinctrl); | 705 | return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, vinctrl); |
@@ -760,6 +766,13 @@ int em28xx_resolution_set(struct em28xx *dev) | |||
760 | width = norm_maxw(dev); | 766 | width = norm_maxw(dev); |
761 | height = norm_maxh(dev); | 767 | height = norm_maxh(dev); |
762 | 768 | ||
769 | /* Properly setup VBI */ | ||
770 | dev->vbi_width = 720; | ||
771 | if (dev->norm & V4L2_STD_525_60) | ||
772 | dev->vbi_height = 12; | ||
773 | else | ||
774 | dev->vbi_height = 18; | ||
775 | |||
763 | if (!dev->progressive) | 776 | if (!dev->progressive) |
764 | height >>= norm_maxh(dev); | 777 | height >>= norm_maxh(dev); |
765 | 778 | ||
diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index cc0505eb900f..1b96356b3ab2 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c | |||
@@ -502,7 +502,9 @@ static int dvb_init(struct em28xx *dev) | |||
502 | } | 502 | } |
503 | break; | 503 | break; |
504 | case EM2880_BOARD_TERRATEC_HYBRID_XS: | 504 | case EM2880_BOARD_TERRATEC_HYBRID_XS: |
505 | case EM2880_BOARD_TERRATEC_HYBRID_XS_FR: | ||
505 | case EM2881_BOARD_PINNACLE_HYBRID_PRO: | 506 | case EM2881_BOARD_PINNACLE_HYBRID_PRO: |
507 | case EM2882_BOARD_DIKOM_DK300: | ||
506 | dvb->frontend = dvb_attach(zl10353_attach, | 508 | dvb->frontend = dvb_attach(zl10353_attach, |
507 | &em28xx_zl10353_xc3028_no_i2c_gate, | 509 | &em28xx_zl10353_xc3028_no_i2c_gate, |
508 | &dev->i2c_adap); | 510 | &dev->i2c_adap); |
@@ -606,6 +608,7 @@ static int dvb_fini(struct em28xx *dev) | |||
606 | 608 | ||
607 | if (dev->dvb) { | 609 | if (dev->dvb) { |
608 | unregister_dvb(dev->dvb); | 610 | unregister_dvb(dev->dvb); |
611 | kfree(dev->dvb); | ||
609 | dev->dvb = NULL; | 612 | dev->dvb = NULL; |
610 | } | 613 | } |
611 | 614 | ||
diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index af0d935c29be..1fb754e20875 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c | |||
@@ -75,6 +75,10 @@ struct em28xx_IR { | |||
75 | unsigned int repeat_interval; | 75 | unsigned int repeat_interval; |
76 | 76 | ||
77 | int (*get_key)(struct em28xx_IR *, struct em28xx_ir_poll_result *); | 77 | int (*get_key)(struct em28xx_IR *, struct em28xx_ir_poll_result *); |
78 | |||
79 | /* IR device properties */ | ||
80 | |||
81 | struct ir_dev_props props; | ||
78 | }; | 82 | }; |
79 | 83 | ||
80 | /********************************************************** | 84 | /********************************************************** |
@@ -180,6 +184,36 @@ int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key, | |||
180 | return 1; | 184 | return 1; |
181 | } | 185 | } |
182 | 186 | ||
187 | int em28xx_get_key_winfast_usbii_deluxe(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | ||
188 | { | ||
189 | unsigned char subaddr, keydetect, key; | ||
190 | |||
191 | struct i2c_msg msg[] = { { .addr = ir->c->addr, .flags = 0, .buf = &subaddr, .len = 1}, | ||
192 | |||
193 | { .addr = ir->c->addr, .flags = I2C_M_RD, .buf = &keydetect, .len = 1} }; | ||
194 | |||
195 | subaddr = 0x10; | ||
196 | if (2 != i2c_transfer(ir->c->adapter, msg, 2)) { | ||
197 | i2cdprintk("read error\n"); | ||
198 | return -EIO; | ||
199 | } | ||
200 | if (keydetect == 0x00) | ||
201 | return 0; | ||
202 | |||
203 | subaddr = 0x00; | ||
204 | msg[1].buf = &key; | ||
205 | if (2 != i2c_transfer(ir->c->adapter, msg, 2)) { | ||
206 | i2cdprintk("read error\n"); | ||
207 | return -EIO; | ||
208 | } | ||
209 | if (key == 0x00) | ||
210 | return 0; | ||
211 | |||
212 | *ir_key = key; | ||
213 | *ir_raw = key; | ||
214 | return 1; | ||
215 | } | ||
216 | |||
183 | /********************************************************** | 217 | /********************************************************** |
184 | Poll based get keycode functions | 218 | Poll based get keycode functions |
185 | **********************************************************/ | 219 | **********************************************************/ |
@@ -336,35 +370,28 @@ static void em28xx_ir_stop(struct em28xx_IR *ir) | |||
336 | cancel_delayed_work_sync(&ir->work); | 370 | cancel_delayed_work_sync(&ir->work); |
337 | } | 371 | } |
338 | 372 | ||
339 | int em28xx_ir_init(struct em28xx *dev) | 373 | int em28xx_ir_change_protocol(void *priv, u64 ir_type) |
340 | { | 374 | { |
341 | struct em28xx_IR *ir; | 375 | int rc = 0; |
342 | struct input_dev *input_dev; | 376 | struct em28xx_IR *ir = priv; |
343 | u8 ir_config; | 377 | struct em28xx *dev = ir->dev; |
344 | int err = -ENOMEM; | 378 | u8 ir_config = EM2874_IR_RC5; |
345 | |||
346 | if (dev->board.ir_codes == NULL) { | ||
347 | /* No remote control support */ | ||
348 | return 0; | ||
349 | } | ||
350 | |||
351 | ir = kzalloc(sizeof(*ir), GFP_KERNEL); | ||
352 | input_dev = input_allocate_device(); | ||
353 | if (!ir || !input_dev) | ||
354 | goto err_out_free; | ||
355 | |||
356 | ir->input = input_dev; | ||
357 | ir_config = EM2874_IR_RC5; | ||
358 | 379 | ||
359 | /* Adjust xclk based o IR table for RC5/NEC tables */ | 380 | /* Adjust xclk based o IR table for RC5/NEC tables */ |
360 | if (dev->board.ir_codes->ir_type == IR_TYPE_RC5) { | 381 | |
382 | dev->board.ir_codes->ir_type = IR_TYPE_OTHER; | ||
383 | if (ir_type == IR_TYPE_RC5) { | ||
361 | dev->board.xclk |= EM28XX_XCLK_IR_RC5_MODE; | 384 | dev->board.xclk |= EM28XX_XCLK_IR_RC5_MODE; |
362 | ir->full_code = 1; | 385 | ir->full_code = 1; |
363 | } else if (dev->board.ir_codes->ir_type == IR_TYPE_NEC) { | 386 | } else if (ir_type == IR_TYPE_NEC) { |
364 | dev->board.xclk &= ~EM28XX_XCLK_IR_RC5_MODE; | 387 | dev->board.xclk &= ~EM28XX_XCLK_IR_RC5_MODE; |
365 | ir_config = EM2874_IR_NEC; | 388 | ir_config = EM2874_IR_NEC; |
366 | ir->full_code = 1; | 389 | ir->full_code = 1; |
367 | } | 390 | } else |
391 | rc = -EINVAL; | ||
392 | |||
393 | dev->board.ir_codes->ir_type = ir_type; | ||
394 | |||
368 | em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, dev->board.xclk, | 395 | em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, dev->board.xclk, |
369 | EM28XX_XCLK_IR_RC5_MODE); | 396 | EM28XX_XCLK_IR_RC5_MODE); |
370 | 397 | ||
@@ -380,9 +407,42 @@ int em28xx_ir_init(struct em28xx *dev) | |||
380 | break; | 407 | break; |
381 | default: | 408 | default: |
382 | printk("Unrecognized em28xx chip id: IR not supported\n"); | 409 | printk("Unrecognized em28xx chip id: IR not supported\n"); |
383 | goto err_out_free; | 410 | rc = -EINVAL; |
411 | } | ||
412 | |||
413 | return rc; | ||
414 | } | ||
415 | |||
416 | int em28xx_ir_init(struct em28xx *dev) | ||
417 | { | ||
418 | struct em28xx_IR *ir; | ||
419 | struct input_dev *input_dev; | ||
420 | int err = -ENOMEM; | ||
421 | |||
422 | if (dev->board.ir_codes == NULL) { | ||
423 | /* No remote control support */ | ||
424 | return 0; | ||
384 | } | 425 | } |
385 | 426 | ||
427 | ir = kzalloc(sizeof(*ir), GFP_KERNEL); | ||
428 | input_dev = input_allocate_device(); | ||
429 | if (!ir || !input_dev) | ||
430 | goto err_out_free; | ||
431 | |||
432 | /* record handles to ourself */ | ||
433 | ir->dev = dev; | ||
434 | dev->ir = ir; | ||
435 | |||
436 | ir->input = input_dev; | ||
437 | |||
438 | /* | ||
439 | * em2874 supports more protocols. For now, let's just announce | ||
440 | * the two protocols that were already tested | ||
441 | */ | ||
442 | ir->props.allowed_protos = IR_TYPE_RC5 | IR_TYPE_NEC; | ||
443 | ir->props.priv = ir; | ||
444 | ir->props.change_protocol = em28xx_ir_change_protocol; | ||
445 | |||
386 | /* This is how often we ask the chip for IR information */ | 446 | /* This is how often we ask the chip for IR information */ |
387 | ir->polling = 100; /* ms */ | 447 | ir->polling = 100; /* ms */ |
388 | 448 | ||
@@ -393,6 +453,8 @@ int em28xx_ir_init(struct em28xx *dev) | |||
393 | usb_make_path(dev->udev, ir->phys, sizeof(ir->phys)); | 453 | usb_make_path(dev->udev, ir->phys, sizeof(ir->phys)); |
394 | strlcat(ir->phys, "/input0", sizeof(ir->phys)); | 454 | strlcat(ir->phys, "/input0", sizeof(ir->phys)); |
395 | 455 | ||
456 | /* Set IR protocol */ | ||
457 | em28xx_ir_change_protocol(ir, dev->board.ir_codes->ir_type); | ||
396 | err = ir_input_init(input_dev, &ir->ir, IR_TYPE_OTHER); | 458 | err = ir_input_init(input_dev, &ir->ir, IR_TYPE_OTHER); |
397 | if (err < 0) | 459 | if (err < 0) |
398 | goto err_out_free; | 460 | goto err_out_free; |
@@ -405,14 +467,13 @@ int em28xx_ir_init(struct em28xx *dev) | |||
405 | input_dev->id.product = le16_to_cpu(dev->udev->descriptor.idProduct); | 467 | input_dev->id.product = le16_to_cpu(dev->udev->descriptor.idProduct); |
406 | 468 | ||
407 | input_dev->dev.parent = &dev->udev->dev; | 469 | input_dev->dev.parent = &dev->udev->dev; |
408 | /* record handles to ourself */ | 470 | |
409 | ir->dev = dev; | ||
410 | dev->ir = ir; | ||
411 | 471 | ||
412 | em28xx_ir_start(ir); | 472 | em28xx_ir_start(ir); |
413 | 473 | ||
414 | /* all done */ | 474 | /* all done */ |
415 | err = ir_input_register(ir->input, dev->board.ir_codes); | 475 | err = ir_input_register(ir->input, dev->board.ir_codes, |
476 | &ir->props); | ||
416 | if (err) | 477 | if (err) |
417 | goto err_out_stop; | 478 | goto err_out_stop; |
418 | 479 | ||
diff --git a/drivers/media/video/em28xx/em28xx-reg.h b/drivers/media/video/em28xx/em28xx-reg.h index 058ac87639ce..91e90559642b 100644 --- a/drivers/media/video/em28xx/em28xx-reg.h +++ b/drivers/media/video/em28xx/em28xx-reg.h | |||
@@ -173,8 +173,8 @@ | |||
173 | /* em2874 IR config register (0x50) */ | 173 | /* em2874 IR config register (0x50) */ |
174 | #define EM2874_IR_NEC 0x00 | 174 | #define EM2874_IR_NEC 0x00 |
175 | #define EM2874_IR_RC5 0x04 | 175 | #define EM2874_IR_RC5 0x04 |
176 | #define EM2874_IR_RC5_MODE_0 0x08 | 176 | #define EM2874_IR_RC6_MODE_0 0x08 |
177 | #define EM2874_IR_RC5_MODE_6A 0x0b | 177 | #define EM2874_IR_RC6_MODE_6A 0x0b |
178 | 178 | ||
179 | /* em2874 Transport Stream Enable Register (0x5f) */ | 179 | /* em2874 Transport Stream Enable Register (0x5f) */ |
180 | #define EM2874_TS1_CAPTURE_ENABLE (1 << 0) | 180 | #define EM2874_TS1_CAPTURE_ENABLE (1 << 0) |
diff --git a/drivers/media/video/em28xx/em28xx-vbi.c b/drivers/media/video/em28xx/em28xx-vbi.c index 94943e5a1529..c7dce39823d8 100644 --- a/drivers/media/video/em28xx/em28xx-vbi.c +++ b/drivers/media/video/em28xx/em28xx-vbi.c | |||
@@ -71,7 +71,11 @@ free_buffer(struct videobuf_queue *vq, struct em28xx_buffer *buf) | |||
71 | static int | 71 | static int |
72 | vbi_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) | 72 | vbi_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) |
73 | { | 73 | { |
74 | *size = 720 * 12 * 2; | 74 | struct em28xx_fh *fh = q->priv_data; |
75 | struct em28xx *dev = fh->dev; | ||
76 | |||
77 | *size = dev->vbi_width * dev->vbi_height * 2; | ||
78 | |||
75 | if (0 == *count) | 79 | if (0 == *count) |
76 | *count = vbibufs; | 80 | *count = vbibufs; |
77 | if (*count < 2) | 81 | if (*count < 2) |
@@ -85,19 +89,18 @@ static int | |||
85 | vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, | 89 | vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, |
86 | enum v4l2_field field) | 90 | enum v4l2_field field) |
87 | { | 91 | { |
92 | struct em28xx_fh *fh = q->priv_data; | ||
93 | struct em28xx *dev = fh->dev; | ||
88 | struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb); | 94 | struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb); |
89 | int rc = 0; | 95 | int rc = 0; |
90 | unsigned int size; | ||
91 | |||
92 | size = 720 * 12 * 2; | ||
93 | 96 | ||
94 | buf->vb.size = size; | 97 | buf->vb.size = dev->vbi_width * dev->vbi_height * 2; |
95 | 98 | ||
96 | if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) | 99 | if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) |
97 | return -EINVAL; | 100 | return -EINVAL; |
98 | 101 | ||
99 | buf->vb.width = 720; | 102 | buf->vb.width = dev->vbi_width; |
100 | buf->vb.height = 12; | 103 | buf->vb.height = dev->vbi_height; |
101 | buf->vb.field = field; | 104 | buf->vb.field = field; |
102 | 105 | ||
103 | if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { | 106 | if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { |
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 849b18c94037..ac2bd935927e 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c | |||
@@ -282,7 +282,7 @@ static void em28xx_copy_vbi(struct em28xx *dev, | |||
282 | { | 282 | { |
283 | void *startwrite, *startread; | 283 | void *startwrite, *startread; |
284 | int offset; | 284 | int offset; |
285 | int bytesperline = 720; | 285 | int bytesperline = dev->vbi_width; |
286 | 286 | ||
287 | if (dev == NULL) { | 287 | if (dev == NULL) { |
288 | em28xx_isocdbg("dev is null\n"); | 288 | em28xx_isocdbg("dev is null\n"); |
@@ -323,8 +323,8 @@ static void em28xx_copy_vbi(struct em28xx *dev, | |||
323 | 323 | ||
324 | /* Make sure the bottom field populates the second half of the frame */ | 324 | /* Make sure the bottom field populates the second half of the frame */ |
325 | if (buf->top_field == 0) { | 325 | if (buf->top_field == 0) { |
326 | startwrite += bytesperline * 0x0c; | 326 | startwrite += bytesperline * dev->vbi_height; |
327 | offset += bytesperline * 0x0c; | 327 | offset += bytesperline * dev->vbi_height; |
328 | } | 328 | } |
329 | 329 | ||
330 | memcpy(startwrite, startread, len); | 330 | memcpy(startwrite, startread, len); |
@@ -578,8 +578,7 @@ static inline int em28xx_isoc_copy_vbi(struct em28xx *dev, struct urb *urb) | |||
578 | dev->cur_field = p[2]; | 578 | dev->cur_field = p[2]; |
579 | } | 579 | } |
580 | 580 | ||
581 | /* FIXME: get rid of hard-coded value */ | 581 | vbi_size = dev->vbi_width * dev->vbi_height; |
582 | vbi_size = 720 * 0x0c; | ||
583 | 582 | ||
584 | if (dev->capture_type == 0) { | 583 | if (dev->capture_type == 0) { |
585 | if (dev->vbi_read >= vbi_size) { | 584 | if (dev->vbi_read >= vbi_size) { |
@@ -1850,18 +1849,27 @@ static int vidioc_try_set_sliced_vbi_cap(struct file *file, void *priv, | |||
1850 | static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv, | 1849 | static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv, |
1851 | struct v4l2_format *format) | 1850 | struct v4l2_format *format) |
1852 | { | 1851 | { |
1853 | format->fmt.vbi.samples_per_line = 720; | 1852 | struct em28xx_fh *fh = priv; |
1853 | struct em28xx *dev = fh->dev; | ||
1854 | |||
1855 | format->fmt.vbi.samples_per_line = dev->vbi_width; | ||
1854 | format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; | 1856 | format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; |
1855 | format->fmt.vbi.offset = 0; | 1857 | format->fmt.vbi.offset = 0; |
1856 | format->fmt.vbi.flags = 0; | 1858 | format->fmt.vbi.flags = 0; |
1859 | format->fmt.vbi.sampling_rate = 6750000 * 4 / 2; | ||
1860 | format->fmt.vbi.count[0] = dev->vbi_height; | ||
1861 | format->fmt.vbi.count[1] = dev->vbi_height; | ||
1857 | 1862 | ||
1858 | /* Varies by video standard (NTSC, PAL, etc.) */ | 1863 | /* Varies by video standard (NTSC, PAL, etc.) */ |
1859 | /* FIXME: hard-coded for NTSC support */ | 1864 | if (dev->norm & V4L2_STD_525_60) { |
1860 | format->fmt.vbi.sampling_rate = 6750000 * 4 / 2; /* FIXME: ??? */ | 1865 | /* NTSC */ |
1861 | format->fmt.vbi.count[0] = 12; | 1866 | format->fmt.vbi.start[0] = 10; |
1862 | format->fmt.vbi.count[1] = 12; | 1867 | format->fmt.vbi.start[1] = 273; |
1863 | format->fmt.vbi.start[0] = 10; | 1868 | } else if (dev->norm & V4L2_STD_625_50) { |
1864 | format->fmt.vbi.start[1] = 273; | 1869 | /* PAL */ |
1870 | format->fmt.vbi.start[0] = 6; | ||
1871 | format->fmt.vbi.start[1] = 318; | ||
1872 | } | ||
1865 | 1873 | ||
1866 | return 0; | 1874 | return 0; |
1867 | } | 1875 | } |
@@ -1869,18 +1877,27 @@ static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv, | |||
1869 | static int vidioc_s_fmt_vbi_cap(struct file *file, void *priv, | 1877 | static int vidioc_s_fmt_vbi_cap(struct file *file, void *priv, |
1870 | struct v4l2_format *format) | 1878 | struct v4l2_format *format) |
1871 | { | 1879 | { |
1872 | format->fmt.vbi.samples_per_line = 720; | 1880 | struct em28xx_fh *fh = priv; |
1881 | struct em28xx *dev = fh->dev; | ||
1882 | |||
1883 | format->fmt.vbi.samples_per_line = dev->vbi_width; | ||
1873 | format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; | 1884 | format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; |
1874 | format->fmt.vbi.offset = 0; | 1885 | format->fmt.vbi.offset = 0; |
1875 | format->fmt.vbi.flags = 0; | 1886 | format->fmt.vbi.flags = 0; |
1887 | format->fmt.vbi.sampling_rate = 6750000 * 4 / 2; | ||
1888 | format->fmt.vbi.count[0] = dev->vbi_height; | ||
1889 | format->fmt.vbi.count[1] = dev->vbi_height; | ||
1876 | 1890 | ||
1877 | /* Varies by video standard (NTSC, PAL, etc.) */ | 1891 | /* Varies by video standard (NTSC, PAL, etc.) */ |
1878 | /* FIXME: hard-coded for NTSC support */ | 1892 | if (dev->norm & V4L2_STD_525_60) { |
1879 | format->fmt.vbi.sampling_rate = 6750000 * 4 / 2; /* FIXME: ??? */ | 1893 | /* NTSC */ |
1880 | format->fmt.vbi.count[0] = 12; | 1894 | format->fmt.vbi.start[0] = 10; |
1881 | format->fmt.vbi.count[1] = 12; | 1895 | format->fmt.vbi.start[1] = 273; |
1882 | format->fmt.vbi.start[0] = 10; | 1896 | } else if (dev->norm & V4L2_STD_625_50) { |
1883 | format->fmt.vbi.start[1] = 273; | 1897 | /* PAL */ |
1898 | format->fmt.vbi.start[0] = 6; | ||
1899 | format->fmt.vbi.start[1] = 318; | ||
1900 | } | ||
1884 | 1901 | ||
1885 | return 0; | 1902 | return 0; |
1886 | } | 1903 | } |
@@ -1922,7 +1939,8 @@ static int vidioc_querybuf(struct file *file, void *priv, | |||
1922 | At a minimum, it causes a crash in zvbi since it does | 1939 | At a minimum, it causes a crash in zvbi since it does |
1923 | a memcpy based on the source buffer length */ | 1940 | a memcpy based on the source buffer length */ |
1924 | int result = videobuf_querybuf(&fh->vb_vbiq, b); | 1941 | int result = videobuf_querybuf(&fh->vb_vbiq, b); |
1925 | b->length = 17280; | 1942 | b->length = dev->vbi_width * dev->vbi_height * 2; |
1943 | |||
1926 | return result; | 1944 | return result; |
1927 | } | 1945 | } |
1928 | } | 1946 | } |
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 80d9b4fa1b97..ba6fe5daff84 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h | |||
@@ -111,6 +111,7 @@ | |||
111 | #define EM2861_BOARD_GADMEI_UTV330PLUS 72 | 111 | #define EM2861_BOARD_GADMEI_UTV330PLUS 72 |
112 | #define EM2870_BOARD_REDDO_DVB_C_USB_BOX 73 | 112 | #define EM2870_BOARD_REDDO_DVB_C_USB_BOX 73 |
113 | #define EM2800_BOARD_VC211A 74 | 113 | #define EM2800_BOARD_VC211A 74 |
114 | #define EM2882_BOARD_DIKOM_DK300 75 | ||
114 | 115 | ||
115 | /* Limits minimum and default number of buffers */ | 116 | /* Limits minimum and default number of buffers */ |
116 | #define EM28XX_MIN_BUF 4 | 117 | #define EM28XX_MIN_BUF 4 |
@@ -552,7 +553,8 @@ struct em28xx { | |||
552 | int capture_type; | 553 | int capture_type; |
553 | int vbi_read; | 554 | int vbi_read; |
554 | unsigned char cur_field; | 555 | unsigned char cur_field; |
555 | 556 | unsigned int vbi_width; | |
557 | unsigned int vbi_height; /* lines per field */ | ||
556 | 558 | ||
557 | struct work_struct request_module_wk; | 559 | struct work_struct request_module_wk; |
558 | 560 | ||
@@ -693,6 +695,8 @@ int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw); | |||
693 | int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw); | 695 | int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw); |
694 | int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key, | 696 | int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key, |
695 | u32 *ir_raw); | 697 | u32 *ir_raw); |
698 | int em28xx_get_key_winfast_usbii_deluxe(struct IR_i2c *ir, u32 *ir_key, | ||
699 | u32 *ir_raw); | ||
696 | void em28xx_register_snapshot_button(struct em28xx *dev); | 700 | void em28xx_register_snapshot_button(struct em28xx *dev); |
697 | void em28xx_deregister_snapshot_button(struct em28xx *dev); | 701 | void em28xx_deregister_snapshot_button(struct em28xx *dev); |
698 | 702 | ||
diff --git a/drivers/media/video/et61x251/Kconfig b/drivers/media/video/et61x251/Kconfig index dcc1a0335440..87981b078fe6 100644 --- a/drivers/media/video/et61x251/Kconfig +++ b/drivers/media/video/et61x251/Kconfig | |||
@@ -1,7 +1,11 @@ | |||
1 | config USB_ET61X251 | 1 | config USB_ET61X251 |
2 | tristate "USB ET61X[12]51 PC Camera Controller support" | 2 | tristate "USB ET61X[12]51 PC Camera Controller support (DEPRECATED)" |
3 | depends on VIDEO_V4L2 | 3 | depends on VIDEO_V4L2 |
4 | default n | ||
4 | ---help--- | 5 | ---help--- |
6 | This driver is DEPRECATED please use the gspca zc3xx module | ||
7 | instead. | ||
8 | |||
5 | Say Y here if you want support for cameras based on Etoms ET61X151 | 9 | Say Y here if you want support for cameras based on Etoms ET61X151 |
6 | or ET61X251 PC Camera Controllers. | 10 | or ET61X251 PC Camera Controllers. |
7 | 11 | ||
diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig index 609d65b0b10d..e0060c1f0544 100644 --- a/drivers/media/video/gspca/Kconfig +++ b/drivers/media/video/gspca/Kconfig | |||
@@ -21,6 +21,15 @@ source "drivers/media/video/gspca/m5602/Kconfig" | |||
21 | source "drivers/media/video/gspca/stv06xx/Kconfig" | 21 | source "drivers/media/video/gspca/stv06xx/Kconfig" |
22 | source "drivers/media/video/gspca/gl860/Kconfig" | 22 | source "drivers/media/video/gspca/gl860/Kconfig" |
23 | 23 | ||
24 | config USB_GSPCA_BENQ | ||
25 | tristate "Benq USB Camera Driver" | ||
26 | depends on VIDEO_V4L2 && USB_GSPCA | ||
27 | help | ||
28 | Say Y here if you want support for the Benq DC E300 camera. | ||
29 | |||
30 | To compile this driver as a module, choose M here: the | ||
31 | module will be called gspca_benq. | ||
32 | |||
24 | config USB_GSPCA_CONEX | 33 | config USB_GSPCA_CONEX |
25 | tristate "Conexant Camera Driver" | 34 | tristate "Conexant Camera Driver" |
26 | depends on VIDEO_V4L2 && USB_GSPCA | 35 | depends on VIDEO_V4L2 && USB_GSPCA |
@@ -30,6 +39,17 @@ config USB_GSPCA_CONEX | |||
30 | To compile this driver as a module, choose M here: the | 39 | To compile this driver as a module, choose M here: the |
31 | module will be called gspca_conex. | 40 | module will be called gspca_conex. |
32 | 41 | ||
42 | config USB_GSPCA_CPIA1 | ||
43 | tristate "cpia CPiA (version 1) Camera Driver" | ||
44 | depends on VIDEO_V4L2 && USB_GSPCA | ||
45 | help | ||
46 | Say Y here if you want support for USB cameras based on the cpia | ||
47 | CPiA chip. Note that you need atleast version 0.6.4 of libv4l for | ||
48 | applications to understand the videoformat generated by this driver. | ||
49 | |||
50 | To compile this driver as a module, choose M here: the | ||
51 | module will be called gspca_cpia1. | ||
52 | |||
33 | config USB_GSPCA_ETOMS | 53 | config USB_GSPCA_ETOMS |
34 | tristate "Etoms USB Camera Driver" | 54 | tristate "Etoms USB Camera Driver" |
35 | depends on VIDEO_V4L2 && USB_GSPCA | 55 | depends on VIDEO_V4L2 && USB_GSPCA |
@@ -86,15 +106,25 @@ config USB_GSPCA_OV519 | |||
86 | module will be called gspca_ov519. | 106 | module will be called gspca_ov519. |
87 | 107 | ||
88 | config USB_GSPCA_OV534 | 108 | config USB_GSPCA_OV534 |
89 | tristate "OV534 USB Camera Driver" | 109 | tristate "OV534 OV772x USB Camera Driver" |
90 | depends on VIDEO_V4L2 && USB_GSPCA | 110 | depends on VIDEO_V4L2 && USB_GSPCA |
91 | help | 111 | help |
92 | Say Y here if you want support for cameras based on the OV534 chip. | 112 | Say Y here if you want support for cameras based on the OV534 chip |
93 | (e.g. Sony Playstation EYE) | 113 | and sensor OV772x (e.g. Sony Playstation EYE) |
94 | 114 | ||
95 | To compile this driver as a module, choose M here: the | 115 | To compile this driver as a module, choose M here: the |
96 | module will be called gspca_ov534. | 116 | module will be called gspca_ov534. |
97 | 117 | ||
118 | config USB_GSPCA_OV534_9 | ||
119 | tristate "OV534 OV965x USB Camera Driver" | ||
120 | depends on VIDEO_V4L2 && USB_GSPCA | ||
121 | help | ||
122 | Say Y here if you want support for cameras based on the OV534 chip | ||
123 | and sensor OV965x (e.g. Hercules Dualpix) | ||
124 | |||
125 | To compile this driver as a module, choose M here: the | ||
126 | module will be called gspca_ov534_9. | ||
127 | |||
98 | config USB_GSPCA_PAC207 | 128 | config USB_GSPCA_PAC207 |
99 | tristate "Pixart PAC207 USB Camera Driver" | 129 | tristate "Pixart PAC207 USB Camera Driver" |
100 | depends on VIDEO_V4L2 && USB_GSPCA | 130 | depends on VIDEO_V4L2 && USB_GSPCA |
@@ -122,6 +152,16 @@ config USB_GSPCA_PAC7311 | |||
122 | To compile this driver as a module, choose M here: the | 152 | To compile this driver as a module, choose M here: the |
123 | module will be called gspca_pac7311. | 153 | module will be called gspca_pac7311. |
124 | 154 | ||
155 | config USB_GSPCA_SN9C2028 | ||
156 | tristate "SONIX Dual-Mode USB Camera Driver" | ||
157 | depends on VIDEO_V4L2 && USB_GSPCA | ||
158 | help | ||
159 | Say Y here if you want streaming support for Sonix SN9C2028 cameras. | ||
160 | These are supported as stillcams in libgphoto2/camlibs/sonix. | ||
161 | |||
162 | To compile this driver as a module, choose M here: the | ||
163 | module will be called gspca_sn9c2028. | ||
164 | |||
125 | config USB_GSPCA_SN9C20X | 165 | config USB_GSPCA_SN9C20X |
126 | tristate "SN9C20X USB Camera Driver" | 166 | tristate "SN9C20X USB Camera Driver" |
127 | depends on VIDEO_V4L2 && USB_GSPCA | 167 | depends on VIDEO_V4L2 && USB_GSPCA |
diff --git a/drivers/media/video/gspca/Makefile b/drivers/media/video/gspca/Makefile index ff2c7279d82e..6e4cf1ce01c9 100644 --- a/drivers/media/video/gspca/Makefile +++ b/drivers/media/video/gspca/Makefile | |||
@@ -1,5 +1,7 @@ | |||
1 | obj-$(CONFIG_USB_GSPCA) += gspca_main.o | 1 | obj-$(CONFIG_USB_GSPCA) += gspca_main.o |
2 | obj-$(CONFIG_USB_GSPCA_BENQ) += gspca_benq.o | ||
2 | obj-$(CONFIG_USB_GSPCA_CONEX) += gspca_conex.o | 3 | obj-$(CONFIG_USB_GSPCA_CONEX) += gspca_conex.o |
4 | obj-$(CONFIG_USB_GSPCA_CPIA1) += gspca_cpia1.o | ||
3 | obj-$(CONFIG_USB_GSPCA_ETOMS) += gspca_etoms.o | 5 | obj-$(CONFIG_USB_GSPCA_ETOMS) += gspca_etoms.o |
4 | obj-$(CONFIG_USB_GSPCA_FINEPIX) += gspca_finepix.o | 6 | obj-$(CONFIG_USB_GSPCA_FINEPIX) += gspca_finepix.o |
5 | obj-$(CONFIG_USB_GSPCA_JEILINJ) += gspca_jeilinj.o | 7 | obj-$(CONFIG_USB_GSPCA_JEILINJ) += gspca_jeilinj.o |
@@ -7,9 +9,11 @@ obj-$(CONFIG_USB_GSPCA_MARS) += gspca_mars.o | |||
7 | obj-$(CONFIG_USB_GSPCA_MR97310A) += gspca_mr97310a.o | 9 | obj-$(CONFIG_USB_GSPCA_MR97310A) += gspca_mr97310a.o |
8 | obj-$(CONFIG_USB_GSPCA_OV519) += gspca_ov519.o | 10 | obj-$(CONFIG_USB_GSPCA_OV519) += gspca_ov519.o |
9 | obj-$(CONFIG_USB_GSPCA_OV534) += gspca_ov534.o | 11 | obj-$(CONFIG_USB_GSPCA_OV534) += gspca_ov534.o |
12 | obj-$(CONFIG_USB_GSPCA_OV534_9) += gspca_ov534_9.o | ||
10 | obj-$(CONFIG_USB_GSPCA_PAC207) += gspca_pac207.o | 13 | obj-$(CONFIG_USB_GSPCA_PAC207) += gspca_pac207.o |
11 | obj-$(CONFIG_USB_GSPCA_PAC7302) += gspca_pac7302.o | 14 | obj-$(CONFIG_USB_GSPCA_PAC7302) += gspca_pac7302.o |
12 | obj-$(CONFIG_USB_GSPCA_PAC7311) += gspca_pac7311.o | 15 | obj-$(CONFIG_USB_GSPCA_PAC7311) += gspca_pac7311.o |
16 | obj-$(CONFIG_USB_GSPCA_SN9C2028) += gspca_sn9c2028.o | ||
13 | obj-$(CONFIG_USB_GSPCA_SN9C20X) += gspca_sn9c20x.o | 17 | obj-$(CONFIG_USB_GSPCA_SN9C20X) += gspca_sn9c20x.o |
14 | obj-$(CONFIG_USB_GSPCA_SONIXB) += gspca_sonixb.o | 18 | obj-$(CONFIG_USB_GSPCA_SONIXB) += gspca_sonixb.o |
15 | obj-$(CONFIG_USB_GSPCA_SONIXJ) += gspca_sonixj.o | 19 | obj-$(CONFIG_USB_GSPCA_SONIXJ) += gspca_sonixj.o |
@@ -30,7 +34,9 @@ obj-$(CONFIG_USB_GSPCA_VC032X) += gspca_vc032x.o | |||
30 | obj-$(CONFIG_USB_GSPCA_ZC3XX) += gspca_zc3xx.o | 34 | obj-$(CONFIG_USB_GSPCA_ZC3XX) += gspca_zc3xx.o |
31 | 35 | ||
32 | gspca_main-objs := gspca.o | 36 | gspca_main-objs := gspca.o |
37 | gspca_benq-objs := benq.o | ||
33 | gspca_conex-objs := conex.o | 38 | gspca_conex-objs := conex.o |
39 | gspca_cpia1-objs := cpia1.o | ||
34 | gspca_etoms-objs := etoms.o | 40 | gspca_etoms-objs := etoms.o |
35 | gspca_finepix-objs := finepix.o | 41 | gspca_finepix-objs := finepix.o |
36 | gspca_jeilinj-objs := jeilinj.o | 42 | gspca_jeilinj-objs := jeilinj.o |
@@ -38,9 +44,11 @@ gspca_mars-objs := mars.o | |||
38 | gspca_mr97310a-objs := mr97310a.o | 44 | gspca_mr97310a-objs := mr97310a.o |
39 | gspca_ov519-objs := ov519.o | 45 | gspca_ov519-objs := ov519.o |
40 | gspca_ov534-objs := ov534.o | 46 | gspca_ov534-objs := ov534.o |
47 | gspca_ov534_9-objs := ov534_9.o | ||
41 | gspca_pac207-objs := pac207.o | 48 | gspca_pac207-objs := pac207.o |
42 | gspca_pac7302-objs := pac7302.o | 49 | gspca_pac7302-objs := pac7302.o |
43 | gspca_pac7311-objs := pac7311.o | 50 | gspca_pac7311-objs := pac7311.o |
51 | gspca_sn9c2028-objs := sn9c2028.o | ||
44 | gspca_sn9c20x-objs := sn9c20x.o | 52 | gspca_sn9c20x-objs := sn9c20x.o |
45 | gspca_sonixb-objs := sonixb.o | 53 | gspca_sonixb-objs := sonixb.o |
46 | gspca_sonixj-objs := sonixj.o | 54 | gspca_sonixj-objs := sonixj.o |
diff --git a/drivers/media/video/gspca/benq.c b/drivers/media/video/gspca/benq.c new file mode 100644 index 000000000000..43ac4af8d3ed --- /dev/null +++ b/drivers/media/video/gspca/benq.c | |||
@@ -0,0 +1,322 @@ | |||
1 | /* | ||
2 | * Benq DC E300 subdriver | ||
3 | * | ||
4 | * Copyright (C) 2009 Jean-Francois Moine (http://moinejf.free.fr) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #define MODULE_NAME "benq" | ||
22 | |||
23 | #include "gspca.h" | ||
24 | |||
25 | MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); | ||
26 | MODULE_DESCRIPTION("Benq DC E300 USB Camera Driver"); | ||
27 | MODULE_LICENSE("GPL"); | ||
28 | |||
29 | /* specific webcam descriptor */ | ||
30 | struct sd { | ||
31 | struct gspca_dev gspca_dev; /* !! must be the first item */ | ||
32 | }; | ||
33 | |||
34 | /* V4L2 controls supported by the driver */ | ||
35 | static const struct ctrl sd_ctrls[] = { | ||
36 | }; | ||
37 | |||
38 | static const struct v4l2_pix_format vga_mode[] = { | ||
39 | {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | ||
40 | .bytesperline = 320, | ||
41 | .sizeimage = 320 * 240 * 3 / 8 + 590, | ||
42 | .colorspace = V4L2_COLORSPACE_JPEG}, | ||
43 | }; | ||
44 | |||
45 | static void sd_isoc_irq(struct urb *urb); | ||
46 | |||
47 | /* -- write a register -- */ | ||
48 | static void reg_w(struct gspca_dev *gspca_dev, | ||
49 | u16 value, u16 index) | ||
50 | { | ||
51 | struct usb_device *dev = gspca_dev->dev; | ||
52 | int ret; | ||
53 | |||
54 | if (gspca_dev->usb_err < 0) | ||
55 | return; | ||
56 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | ||
57 | 0x02, | ||
58 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
59 | value, | ||
60 | index, | ||
61 | NULL, | ||
62 | 0, | ||
63 | 500); | ||
64 | if (ret < 0) { | ||
65 | PDEBUG(D_ERR, "reg_w err %d", ret); | ||
66 | gspca_dev->usb_err = ret; | ||
67 | } | ||
68 | } | ||
69 | |||
70 | /* this function is called at probe time */ | ||
71 | static int sd_config(struct gspca_dev *gspca_dev, | ||
72 | const struct usb_device_id *id) | ||
73 | { | ||
74 | gspca_dev->cam.cam_mode = vga_mode; | ||
75 | gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode); | ||
76 | gspca_dev->cam.no_urb_create = 1; | ||
77 | gspca_dev->cam.reverse_alts = 1; | ||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | /* this function is called at probe and resume time */ | ||
82 | static int sd_init(struct gspca_dev *gspca_dev) | ||
83 | { | ||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | static int sd_isoc_init(struct gspca_dev *gspca_dev) | ||
88 | { | ||
89 | int ret; | ||
90 | |||
91 | ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, | ||
92 | gspca_dev->nbalt - 1); | ||
93 | if (ret < 0) { | ||
94 | err("usb_set_interface failed"); | ||
95 | return ret; | ||
96 | } | ||
97 | /* reg_w(gspca_dev, 0x0003, 0x0002); */ | ||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | /* -- start the camera -- */ | ||
102 | static int sd_start(struct gspca_dev *gspca_dev) | ||
103 | { | ||
104 | struct urb *urb; | ||
105 | int i, n; | ||
106 | |||
107 | /* create 4 URBs - 2 on endpoint 0x83 and 2 on 0x082 */ | ||
108 | #if MAX_NURBS < 4 | ||
109 | #error "Not enough URBs in the gspca table" | ||
110 | #endif | ||
111 | #define SD_PKT_SZ 64 | ||
112 | #define SD_NPKT 32 | ||
113 | for (n = 0; n < 4; n++) { | ||
114 | urb = usb_alloc_urb(SD_NPKT, GFP_KERNEL); | ||
115 | if (!urb) { | ||
116 | err("usb_alloc_urb failed"); | ||
117 | return -ENOMEM; | ||
118 | } | ||
119 | gspca_dev->urb[n] = urb; | ||
120 | urb->transfer_buffer = usb_buffer_alloc(gspca_dev->dev, | ||
121 | SD_PKT_SZ * SD_NPKT, | ||
122 | GFP_KERNEL, | ||
123 | &urb->transfer_dma); | ||
124 | |||
125 | if (urb->transfer_buffer == NULL) { | ||
126 | err("usb_buffer_alloc failed"); | ||
127 | return -ENOMEM; | ||
128 | } | ||
129 | urb->dev = gspca_dev->dev; | ||
130 | urb->context = gspca_dev; | ||
131 | urb->transfer_buffer_length = SD_PKT_SZ * SD_NPKT; | ||
132 | urb->pipe = usb_rcvisocpipe(gspca_dev->dev, | ||
133 | n & 1 ? 0x82 : 0x83); | ||
134 | urb->transfer_flags = URB_ISO_ASAP | ||
135 | | URB_NO_TRANSFER_DMA_MAP; | ||
136 | urb->interval = 1; | ||
137 | urb->complete = sd_isoc_irq; | ||
138 | urb->number_of_packets = SD_NPKT; | ||
139 | for (i = 0; i < SD_NPKT; i++) { | ||
140 | urb->iso_frame_desc[i].length = SD_PKT_SZ; | ||
141 | urb->iso_frame_desc[i].offset = SD_PKT_SZ * i; | ||
142 | } | ||
143 | } | ||
144 | |||
145 | return gspca_dev->usb_err; | ||
146 | } | ||
147 | |||
148 | static void sd_stopN(struct gspca_dev *gspca_dev) | ||
149 | { | ||
150 | reg_w(gspca_dev, 0x003c, 0x0003); | ||
151 | reg_w(gspca_dev, 0x003c, 0x0004); | ||
152 | reg_w(gspca_dev, 0x003c, 0x0005); | ||
153 | reg_w(gspca_dev, 0x003c, 0x0006); | ||
154 | reg_w(gspca_dev, 0x003c, 0x0007); | ||
155 | usb_set_interface(gspca_dev->dev, gspca_dev->iface, gspca_dev->nbalt - 1); | ||
156 | } | ||
157 | |||
158 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | ||
159 | u8 *data, /* isoc packet */ | ||
160 | int len) /* iso packet length */ | ||
161 | { | ||
162 | /* unused */ | ||
163 | } | ||
164 | |||
165 | /* reception of an URB */ | ||
166 | static void sd_isoc_irq(struct urb *urb) | ||
167 | { | ||
168 | struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context; | ||
169 | struct urb *urb0; | ||
170 | u8 *data; | ||
171 | int i, st; | ||
172 | |||
173 | PDEBUG(D_PACK, "sd isoc irq"); | ||
174 | if (!gspca_dev->streaming) | ||
175 | return; | ||
176 | if (urb->status != 0) { | ||
177 | if (urb->status == -ESHUTDOWN) | ||
178 | return; /* disconnection */ | ||
179 | #ifdef CONFIG_PM | ||
180 | if (gspca_dev->frozen) | ||
181 | return; | ||
182 | #endif | ||
183 | PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status); | ||
184 | return; | ||
185 | } | ||
186 | |||
187 | /* if this is a control URN (ep 0x83), wait */ | ||
188 | if (urb == gspca_dev->urb[0] || urb == gspca_dev->urb[2]) | ||
189 | return; | ||
190 | |||
191 | /* scan both received URBs */ | ||
192 | if (urb == gspca_dev->urb[1]) | ||
193 | urb0 = gspca_dev->urb[0]; | ||
194 | else | ||
195 | urb0 = gspca_dev->urb[2]; | ||
196 | for (i = 0; i < urb->number_of_packets; i++) { | ||
197 | |||
198 | /* check the packet status and length */ | ||
199 | if (urb0->iso_frame_desc[i].actual_length != SD_PKT_SZ | ||
200 | || urb->iso_frame_desc[i].actual_length != SD_PKT_SZ) { | ||
201 | PDEBUG(D_ERR, "ISOC bad lengths %d / %d", | ||
202 | urb0->iso_frame_desc[i].actual_length, | ||
203 | urb->iso_frame_desc[i].actual_length); | ||
204 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
205 | continue; | ||
206 | } | ||
207 | st = urb0->iso_frame_desc[i].status; | ||
208 | if (st == 0) | ||
209 | st = urb->iso_frame_desc[i].status; | ||
210 | if (st) { | ||
211 | PDEBUG(D_ERR, | ||
212 | "ISOC data error: [%d] status=%d", | ||
213 | i, st); | ||
214 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
215 | continue; | ||
216 | } | ||
217 | |||
218 | /* | ||
219 | * The images are received in URBs of different endpoints | ||
220 | * (0x83 and 0x82). | ||
221 | * Image pieces in URBs of ep 0x83 are continuated in URBs of | ||
222 | * ep 0x82 of the same index. | ||
223 | * The packets in the URBs of endpoint 0x83 start with: | ||
224 | * - 80 ba/bb 00 00 = start of image followed by 'ff d8' | ||
225 | * - 04 ba/bb oo oo = image piece | ||
226 | * where 'oo oo' is the image offset | ||
227 | (not cheked) | ||
228 | * - (other -> bad frame) | ||
229 | * The images are JPEG encoded with full header and | ||
230 | * normal ff escape. | ||
231 | * The end of image ('ff d9') may occur in any URB. | ||
232 | * (not cheked) | ||
233 | */ | ||
234 | data = (u8 *) urb0->transfer_buffer | ||
235 | + urb0->iso_frame_desc[i].offset; | ||
236 | if (data[0] == 0x80 && (data[1] & 0xfe) == 0xba) { | ||
237 | |||
238 | /* new image */ | ||
239 | gspca_frame_add(gspca_dev, LAST_PACKET, | ||
240 | NULL, 0); | ||
241 | gspca_frame_add(gspca_dev, FIRST_PACKET, | ||
242 | data + 4, SD_PKT_SZ - 4); | ||
243 | } else if (data[0] == 0x04 && (data[1] & 0xfe) == 0xba) { | ||
244 | gspca_frame_add(gspca_dev, INTER_PACKET, | ||
245 | data + 4, SD_PKT_SZ - 4); | ||
246 | } else { | ||
247 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
248 | continue; | ||
249 | } | ||
250 | data = (u8 *) urb->transfer_buffer | ||
251 | + urb->iso_frame_desc[i].offset; | ||
252 | gspca_frame_add(gspca_dev, INTER_PACKET, | ||
253 | data, SD_PKT_SZ); | ||
254 | } | ||
255 | |||
256 | /* resubmit the URBs */ | ||
257 | st = usb_submit_urb(urb0, GFP_ATOMIC); | ||
258 | if (st < 0) | ||
259 | PDEBUG(D_ERR|D_PACK, "usb_submit_urb(0) ret %d", st); | ||
260 | st = usb_submit_urb(urb, GFP_ATOMIC); | ||
261 | if (st < 0) | ||
262 | PDEBUG(D_ERR|D_PACK, "usb_submit_urb() ret %d", st); | ||
263 | } | ||
264 | |||
265 | /* sub-driver description */ | ||
266 | static const struct sd_desc sd_desc = { | ||
267 | .name = MODULE_NAME, | ||
268 | .ctrls = sd_ctrls, | ||
269 | .nctrls = ARRAY_SIZE(sd_ctrls), | ||
270 | .config = sd_config, | ||
271 | .init = sd_init, | ||
272 | .isoc_init = sd_isoc_init, | ||
273 | .start = sd_start, | ||
274 | .stopN = sd_stopN, | ||
275 | .pkt_scan = sd_pkt_scan, | ||
276 | }; | ||
277 | |||
278 | /* -- module initialisation -- */ | ||
279 | static const __devinitdata struct usb_device_id device_table[] = { | ||
280 | {USB_DEVICE(0x04a5, 0x3035)}, | ||
281 | {} | ||
282 | }; | ||
283 | MODULE_DEVICE_TABLE(usb, device_table); | ||
284 | |||
285 | /* -- device connect -- */ | ||
286 | static int sd_probe(struct usb_interface *intf, | ||
287 | const struct usb_device_id *id) | ||
288 | { | ||
289 | return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), | ||
290 | THIS_MODULE); | ||
291 | } | ||
292 | |||
293 | static struct usb_driver sd_driver = { | ||
294 | .name = MODULE_NAME, | ||
295 | .id_table = device_table, | ||
296 | .probe = sd_probe, | ||
297 | .disconnect = gspca_disconnect, | ||
298 | #ifdef CONFIG_PM | ||
299 | .suspend = gspca_suspend, | ||
300 | .resume = gspca_resume, | ||
301 | #endif | ||
302 | }; | ||
303 | |||
304 | /* -- module insert / remove -- */ | ||
305 | static int __init sd_mod_init(void) | ||
306 | { | ||
307 | int ret; | ||
308 | |||
309 | ret = usb_register(&sd_driver); | ||
310 | if (ret < 0) | ||
311 | return ret; | ||
312 | info("registered"); | ||
313 | return 0; | ||
314 | } | ||
315 | static void __exit sd_mod_exit(void) | ||
316 | { | ||
317 | usb_deregister(&sd_driver); | ||
318 | info("deregistered"); | ||
319 | } | ||
320 | |||
321 | module_init(sd_mod_init); | ||
322 | module_exit(sd_mod_exit); | ||
diff --git a/drivers/media/video/gspca/coarse_expo_autogain.h b/drivers/media/video/gspca/coarse_expo_autogain.h new file mode 100644 index 000000000000..1cb9d941eaf6 --- /dev/null +++ b/drivers/media/video/gspca/coarse_expo_autogain.h | |||
@@ -0,0 +1,116 @@ | |||
1 | /* | ||
2 | * Auto gain algorithm for camera's with a coarse exposure control | ||
3 | * | ||
4 | * Copyright (C) 2010 Hans de Goede <hdegoede@redhat.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | /* Autogain + exposure algorithm for cameras with a coarse exposure control | ||
22 | (usually this means we can only control the clockdiv to change exposure) | ||
23 | As changing the clockdiv so that the fps drops from 30 to 15 fps for | ||
24 | example, will lead to a huge exposure change (it effectively doubles), | ||
25 | this algorithm normally tries to only adjust the gain (between 40 and | ||
26 | 80 %) and if that does not help, only then changes exposure. This leads | ||
27 | to a much more stable image then using the knee algorithm which at | ||
28 | certain points of the knee graph will only try to adjust exposure, | ||
29 | which leads to oscilating as one exposure step is huge. | ||
30 | |||
31 | Note this assumes that the sd struct for the cam in question has | ||
32 | exp_too_high_cnt and exp_too_high_cnt int members for use by this function. | ||
33 | |||
34 | Returns 0 if no changes were made, 1 if the gain and or exposure settings | ||
35 | where changed. */ | ||
36 | static int gspca_coarse_grained_expo_autogain(struct gspca_dev *gspca_dev, | ||
37 | int avg_lum, int desired_avg_lum, int deadzone) | ||
38 | { | ||
39 | int i, steps, gain, orig_gain, exposure, orig_exposure; | ||
40 | int gain_low, gain_high; | ||
41 | const struct ctrl *gain_ctrl = NULL; | ||
42 | const struct ctrl *exposure_ctrl = NULL; | ||
43 | struct sd *sd = (struct sd *) gspca_dev; | ||
44 | int retval = 0; | ||
45 | |||
46 | for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) { | ||
47 | if (gspca_dev->ctrl_dis & (1 << i)) | ||
48 | continue; | ||
49 | if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_GAIN) | ||
50 | gain_ctrl = &gspca_dev->sd_desc->ctrls[i]; | ||
51 | if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_EXPOSURE) | ||
52 | exposure_ctrl = &gspca_dev->sd_desc->ctrls[i]; | ||
53 | } | ||
54 | if (!gain_ctrl || !exposure_ctrl) { | ||
55 | PDEBUG(D_ERR, "Error: gspca_coarse_grained_expo_autogain " | ||
56 | "called on cam without gain or exposure"); | ||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | if (gain_ctrl->get(gspca_dev, &gain) || | ||
61 | exposure_ctrl->get(gspca_dev, &exposure)) | ||
62 | return 0; | ||
63 | |||
64 | orig_gain = gain; | ||
65 | orig_exposure = exposure; | ||
66 | gain_low = | ||
67 | (gain_ctrl->qctrl.maximum - gain_ctrl->qctrl.minimum) / 5 * 2; | ||
68 | gain_low += gain_ctrl->qctrl.minimum; | ||
69 | gain_high = | ||
70 | (gain_ctrl->qctrl.maximum - gain_ctrl->qctrl.minimum) / 5 * 4; | ||
71 | gain_high += gain_ctrl->qctrl.minimum; | ||
72 | |||
73 | /* If we are of a multiple of deadzone, do multiple steps to reach the | ||
74 | desired lumination fast (with the risc of a slight overshoot) */ | ||
75 | steps = (desired_avg_lum - avg_lum) / deadzone; | ||
76 | |||
77 | PDEBUG(D_FRAM, "autogain: lum: %d, desired: %d, steps: %d", | ||
78 | avg_lum, desired_avg_lum, steps); | ||
79 | |||
80 | if ((gain + steps) > gain_high && | ||
81 | sd->exposure < exposure_ctrl->qctrl.maximum) { | ||
82 | gain = gain_high; | ||
83 | sd->exp_too_low_cnt++; | ||
84 | } else if ((gain + steps) < gain_low && | ||
85 | sd->exposure > exposure_ctrl->qctrl.minimum) { | ||
86 | gain = gain_low; | ||
87 | sd->exp_too_high_cnt++; | ||
88 | } else { | ||
89 | gain += steps; | ||
90 | if (gain > gain_ctrl->qctrl.maximum) | ||
91 | gain = gain_ctrl->qctrl.maximum; | ||
92 | else if (gain < gain_ctrl->qctrl.minimum) | ||
93 | gain = gain_ctrl->qctrl.minimum; | ||
94 | sd->exp_too_high_cnt = 0; | ||
95 | sd->exp_too_low_cnt = 0; | ||
96 | } | ||
97 | |||
98 | if (sd->exp_too_high_cnt > 3) { | ||
99 | exposure--; | ||
100 | sd->exp_too_high_cnt = 0; | ||
101 | } else if (sd->exp_too_low_cnt > 3) { | ||
102 | exposure++; | ||
103 | sd->exp_too_low_cnt = 0; | ||
104 | } | ||
105 | |||
106 | if (gain != orig_gain) { | ||
107 | gain_ctrl->set(gspca_dev, gain); | ||
108 | retval = 1; | ||
109 | } | ||
110 | if (exposure != orig_exposure) { | ||
111 | exposure_ctrl->set(gspca_dev, exposure); | ||
112 | retval = 1; | ||
113 | } | ||
114 | |||
115 | return retval; | ||
116 | } | ||
diff --git a/drivers/media/video/gspca/conex.c b/drivers/media/video/gspca/conex.c index c98b5d69c438..19fe6b24c9a3 100644 --- a/drivers/media/video/gspca/conex.c +++ b/drivers/media/video/gspca/conex.c | |||
@@ -52,7 +52,7 @@ static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | |||
52 | static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); | 52 | static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); |
53 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); | 53 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); |
54 | 54 | ||
55 | static struct ctrl sd_ctrls[] = { | 55 | static const struct ctrl sd_ctrls[] = { |
56 | { | 56 | { |
57 | { | 57 | { |
58 | .id = V4L2_CID_BRIGHTNESS, | 58 | .id = V4L2_CID_BRIGHTNESS, |
@@ -1032,7 +1032,7 @@ static int sd_get_jcomp(struct gspca_dev *gspca_dev, | |||
1032 | } | 1032 | } |
1033 | 1033 | ||
1034 | /* sub-driver description */ | 1034 | /* sub-driver description */ |
1035 | static struct sd_desc sd_desc = { | 1035 | static const struct sd_desc sd_desc = { |
1036 | .name = MODULE_NAME, | 1036 | .name = MODULE_NAME, |
1037 | .ctrls = sd_ctrls, | 1037 | .ctrls = sd_ctrls, |
1038 | .nctrls = ARRAY_SIZE(sd_ctrls), | 1038 | .nctrls = ARRAY_SIZE(sd_ctrls), |
diff --git a/drivers/media/video/gspca/cpia1.c b/drivers/media/video/gspca/cpia1.c new file mode 100644 index 000000000000..82945ed5cbe5 --- /dev/null +++ b/drivers/media/video/gspca/cpia1.c | |||
@@ -0,0 +1,2022 @@ | |||
1 | /* | ||
2 | * cpia CPiA (1) gspca driver | ||
3 | * | ||
4 | * Copyright (C) 2010 Hans de Goede <hdgoede@redhat.com> | ||
5 | * | ||
6 | * This module is adapted from the in kernel v4l1 cpia driver which is : | ||
7 | * | ||
8 | * (C) Copyright 1999-2000 Peter Pregler | ||
9 | * (C) Copyright 1999-2000 Scott J. Bertin | ||
10 | * (C) Copyright 1999-2000 Johannes Erdfelt <johannes@erdfelt.com> | ||
11 | * (C) Copyright 2000 STMicroelectronics | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
26 | * | ||
27 | */ | ||
28 | |||
29 | #define MODULE_NAME "cpia1" | ||
30 | |||
31 | #include "gspca.h" | ||
32 | |||
33 | MODULE_AUTHOR("Hans de Goede <hdgoede@redhat.com>"); | ||
34 | MODULE_DESCRIPTION("Vision CPiA"); | ||
35 | MODULE_LICENSE("GPL"); | ||
36 | |||
37 | /* constant value's */ | ||
38 | #define MAGIC_0 0x19 | ||
39 | #define MAGIC_1 0x68 | ||
40 | #define DATA_IN 0xC0 | ||
41 | #define DATA_OUT 0x40 | ||
42 | #define VIDEOSIZE_QCIF 0 /* 176x144 */ | ||
43 | #define VIDEOSIZE_CIF 1 /* 352x288 */ | ||
44 | #define SUBSAMPLE_420 0 | ||
45 | #define SUBSAMPLE_422 1 | ||
46 | #define YUVORDER_YUYV 0 | ||
47 | #define YUVORDER_UYVY 1 | ||
48 | #define NOT_COMPRESSED 0 | ||
49 | #define COMPRESSED 1 | ||
50 | #define NO_DECIMATION 0 | ||
51 | #define DECIMATION_ENAB 1 | ||
52 | #define EOI 0xff /* End Of Image */ | ||
53 | #define EOL 0xfd /* End Of Line */ | ||
54 | #define FRAME_HEADER_SIZE 64 | ||
55 | |||
56 | /* Image grab modes */ | ||
57 | #define CPIA_GRAB_SINGLE 0 | ||
58 | #define CPIA_GRAB_CONTINEOUS 1 | ||
59 | |||
60 | /* Compression parameters */ | ||
61 | #define CPIA_COMPRESSION_NONE 0 | ||
62 | #define CPIA_COMPRESSION_AUTO 1 | ||
63 | #define CPIA_COMPRESSION_MANUAL 2 | ||
64 | #define CPIA_COMPRESSION_TARGET_QUALITY 0 | ||
65 | #define CPIA_COMPRESSION_TARGET_FRAMERATE 1 | ||
66 | |||
67 | /* Return offsets for GetCameraState */ | ||
68 | #define SYSTEMSTATE 0 | ||
69 | #define GRABSTATE 1 | ||
70 | #define STREAMSTATE 2 | ||
71 | #define FATALERROR 3 | ||
72 | #define CMDERROR 4 | ||
73 | #define DEBUGFLAGS 5 | ||
74 | #define VPSTATUS 6 | ||
75 | #define ERRORCODE 7 | ||
76 | |||
77 | /* SystemState */ | ||
78 | #define UNINITIALISED_STATE 0 | ||
79 | #define PASS_THROUGH_STATE 1 | ||
80 | #define LO_POWER_STATE 2 | ||
81 | #define HI_POWER_STATE 3 | ||
82 | #define WARM_BOOT_STATE 4 | ||
83 | |||
84 | /* GrabState */ | ||
85 | #define GRAB_IDLE 0 | ||
86 | #define GRAB_ACTIVE 1 | ||
87 | #define GRAB_DONE 2 | ||
88 | |||
89 | /* StreamState */ | ||
90 | #define STREAM_NOT_READY 0 | ||
91 | #define STREAM_READY 1 | ||
92 | #define STREAM_OPEN 2 | ||
93 | #define STREAM_PAUSED 3 | ||
94 | #define STREAM_FINISHED 4 | ||
95 | |||
96 | /* Fatal Error, CmdError, and DebugFlags */ | ||
97 | #define CPIA_FLAG 1 | ||
98 | #define SYSTEM_FLAG 2 | ||
99 | #define INT_CTRL_FLAG 4 | ||
100 | #define PROCESS_FLAG 8 | ||
101 | #define COM_FLAG 16 | ||
102 | #define VP_CTRL_FLAG 32 | ||
103 | #define CAPTURE_FLAG 64 | ||
104 | #define DEBUG_FLAG 128 | ||
105 | |||
106 | /* VPStatus */ | ||
107 | #define VP_STATE_OK 0x00 | ||
108 | |||
109 | #define VP_STATE_FAILED_VIDEOINIT 0x01 | ||
110 | #define VP_STATE_FAILED_AECACBINIT 0x02 | ||
111 | #define VP_STATE_AEC_MAX 0x04 | ||
112 | #define VP_STATE_ACB_BMAX 0x08 | ||
113 | |||
114 | #define VP_STATE_ACB_RMIN 0x10 | ||
115 | #define VP_STATE_ACB_GMIN 0x20 | ||
116 | #define VP_STATE_ACB_RMAX 0x40 | ||
117 | #define VP_STATE_ACB_GMAX 0x80 | ||
118 | |||
119 | /* default (minimum) compensation values */ | ||
120 | #define COMP_RED 220 | ||
121 | #define COMP_GREEN1 214 | ||
122 | #define COMP_GREEN2 COMP_GREEN1 | ||
123 | #define COMP_BLUE 230 | ||
124 | |||
125 | /* exposure status */ | ||
126 | #define EXPOSURE_VERY_LIGHT 0 | ||
127 | #define EXPOSURE_LIGHT 1 | ||
128 | #define EXPOSURE_NORMAL 2 | ||
129 | #define EXPOSURE_DARK 3 | ||
130 | #define EXPOSURE_VERY_DARK 4 | ||
131 | |||
132 | #define CPIA_MODULE_CPIA (0 << 5) | ||
133 | #define CPIA_MODULE_SYSTEM (1 << 5) | ||
134 | #define CPIA_MODULE_VP_CTRL (5 << 5) | ||
135 | #define CPIA_MODULE_CAPTURE (6 << 5) | ||
136 | #define CPIA_MODULE_DEBUG (7 << 5) | ||
137 | |||
138 | #define INPUT (DATA_IN << 8) | ||
139 | #define OUTPUT (DATA_OUT << 8) | ||
140 | |||
141 | #define CPIA_COMMAND_GetCPIAVersion (INPUT | CPIA_MODULE_CPIA | 1) | ||
142 | #define CPIA_COMMAND_GetPnPID (INPUT | CPIA_MODULE_CPIA | 2) | ||
143 | #define CPIA_COMMAND_GetCameraStatus (INPUT | CPIA_MODULE_CPIA | 3) | ||
144 | #define CPIA_COMMAND_GotoHiPower (OUTPUT | CPIA_MODULE_CPIA | 4) | ||
145 | #define CPIA_COMMAND_GotoLoPower (OUTPUT | CPIA_MODULE_CPIA | 5) | ||
146 | #define CPIA_COMMAND_GotoSuspend (OUTPUT | CPIA_MODULE_CPIA | 7) | ||
147 | #define CPIA_COMMAND_GotoPassThrough (OUTPUT | CPIA_MODULE_CPIA | 8) | ||
148 | #define CPIA_COMMAND_ModifyCameraStatus (OUTPUT | CPIA_MODULE_CPIA | 10) | ||
149 | |||
150 | #define CPIA_COMMAND_ReadVCRegs (INPUT | CPIA_MODULE_SYSTEM | 1) | ||
151 | #define CPIA_COMMAND_WriteVCReg (OUTPUT | CPIA_MODULE_SYSTEM | 2) | ||
152 | #define CPIA_COMMAND_ReadMCPorts (INPUT | CPIA_MODULE_SYSTEM | 3) | ||
153 | #define CPIA_COMMAND_WriteMCPort (OUTPUT | CPIA_MODULE_SYSTEM | 4) | ||
154 | #define CPIA_COMMAND_SetBaudRate (OUTPUT | CPIA_MODULE_SYSTEM | 5) | ||
155 | #define CPIA_COMMAND_SetECPTiming (OUTPUT | CPIA_MODULE_SYSTEM | 6) | ||
156 | #define CPIA_COMMAND_ReadIDATA (INPUT | CPIA_MODULE_SYSTEM | 7) | ||
157 | #define CPIA_COMMAND_WriteIDATA (OUTPUT | CPIA_MODULE_SYSTEM | 8) | ||
158 | #define CPIA_COMMAND_GenericCall (OUTPUT | CPIA_MODULE_SYSTEM | 9) | ||
159 | #define CPIA_COMMAND_I2CStart (OUTPUT | CPIA_MODULE_SYSTEM | 10) | ||
160 | #define CPIA_COMMAND_I2CStop (OUTPUT | CPIA_MODULE_SYSTEM | 11) | ||
161 | #define CPIA_COMMAND_I2CWrite (OUTPUT | CPIA_MODULE_SYSTEM | 12) | ||
162 | #define CPIA_COMMAND_I2CRead (INPUT | CPIA_MODULE_SYSTEM | 13) | ||
163 | |||
164 | #define CPIA_COMMAND_GetVPVersion (INPUT | CPIA_MODULE_VP_CTRL | 1) | ||
165 | #define CPIA_COMMAND_ResetFrameCounter (INPUT | CPIA_MODULE_VP_CTRL | 2) | ||
166 | #define CPIA_COMMAND_SetColourParams (OUTPUT | CPIA_MODULE_VP_CTRL | 3) | ||
167 | #define CPIA_COMMAND_SetExposure (OUTPUT | CPIA_MODULE_VP_CTRL | 4) | ||
168 | #define CPIA_COMMAND_SetColourBalance (OUTPUT | CPIA_MODULE_VP_CTRL | 6) | ||
169 | #define CPIA_COMMAND_SetSensorFPS (OUTPUT | CPIA_MODULE_VP_CTRL | 7) | ||
170 | #define CPIA_COMMAND_SetVPDefaults (OUTPUT | CPIA_MODULE_VP_CTRL | 8) | ||
171 | #define CPIA_COMMAND_SetApcor (OUTPUT | CPIA_MODULE_VP_CTRL | 9) | ||
172 | #define CPIA_COMMAND_SetFlickerCtrl (OUTPUT | CPIA_MODULE_VP_CTRL | 10) | ||
173 | #define CPIA_COMMAND_SetVLOffset (OUTPUT | CPIA_MODULE_VP_CTRL | 11) | ||
174 | #define CPIA_COMMAND_GetColourParams (INPUT | CPIA_MODULE_VP_CTRL | 16) | ||
175 | #define CPIA_COMMAND_GetColourBalance (INPUT | CPIA_MODULE_VP_CTRL | 17) | ||
176 | #define CPIA_COMMAND_GetExposure (INPUT | CPIA_MODULE_VP_CTRL | 18) | ||
177 | #define CPIA_COMMAND_SetSensorMatrix (OUTPUT | CPIA_MODULE_VP_CTRL | 19) | ||
178 | #define CPIA_COMMAND_ColourBars (OUTPUT | CPIA_MODULE_VP_CTRL | 25) | ||
179 | #define CPIA_COMMAND_ReadVPRegs (INPUT | CPIA_MODULE_VP_CTRL | 30) | ||
180 | #define CPIA_COMMAND_WriteVPReg (OUTPUT | CPIA_MODULE_VP_CTRL | 31) | ||
181 | |||
182 | #define CPIA_COMMAND_GrabFrame (OUTPUT | CPIA_MODULE_CAPTURE | 1) | ||
183 | #define CPIA_COMMAND_UploadFrame (OUTPUT | CPIA_MODULE_CAPTURE | 2) | ||
184 | #define CPIA_COMMAND_SetGrabMode (OUTPUT | CPIA_MODULE_CAPTURE | 3) | ||
185 | #define CPIA_COMMAND_InitStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 4) | ||
186 | #define CPIA_COMMAND_FiniStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 5) | ||
187 | #define CPIA_COMMAND_StartStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 6) | ||
188 | #define CPIA_COMMAND_EndStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 7) | ||
189 | #define CPIA_COMMAND_SetFormat (OUTPUT | CPIA_MODULE_CAPTURE | 8) | ||
190 | #define CPIA_COMMAND_SetROI (OUTPUT | CPIA_MODULE_CAPTURE | 9) | ||
191 | #define CPIA_COMMAND_SetCompression (OUTPUT | CPIA_MODULE_CAPTURE | 10) | ||
192 | #define CPIA_COMMAND_SetCompressionTarget (OUTPUT | CPIA_MODULE_CAPTURE | 11) | ||
193 | #define CPIA_COMMAND_SetYUVThresh (OUTPUT | CPIA_MODULE_CAPTURE | 12) | ||
194 | #define CPIA_COMMAND_SetCompressionParams (OUTPUT | CPIA_MODULE_CAPTURE | 13) | ||
195 | #define CPIA_COMMAND_DiscardFrame (OUTPUT | CPIA_MODULE_CAPTURE | 14) | ||
196 | #define CPIA_COMMAND_GrabReset (OUTPUT | CPIA_MODULE_CAPTURE | 15) | ||
197 | |||
198 | #define CPIA_COMMAND_OutputRS232 (OUTPUT | CPIA_MODULE_DEBUG | 1) | ||
199 | #define CPIA_COMMAND_AbortProcess (OUTPUT | CPIA_MODULE_DEBUG | 4) | ||
200 | #define CPIA_COMMAND_SetDramPage (OUTPUT | CPIA_MODULE_DEBUG | 5) | ||
201 | #define CPIA_COMMAND_StartDramUpload (OUTPUT | CPIA_MODULE_DEBUG | 6) | ||
202 | #define CPIA_COMMAND_StartDummyDtream (OUTPUT | CPIA_MODULE_DEBUG | 8) | ||
203 | #define CPIA_COMMAND_AbortStream (OUTPUT | CPIA_MODULE_DEBUG | 9) | ||
204 | #define CPIA_COMMAND_DownloadDRAM (OUTPUT | CPIA_MODULE_DEBUG | 10) | ||
205 | #define CPIA_COMMAND_Null (OUTPUT | CPIA_MODULE_DEBUG | 11) | ||
206 | |||
207 | #define ROUND_UP_EXP_FOR_FLICKER 15 | ||
208 | |||
209 | /* Constants for automatic frame rate adjustment */ | ||
210 | #define MAX_EXP 302 | ||
211 | #define MAX_EXP_102 255 | ||
212 | #define LOW_EXP 140 | ||
213 | #define VERY_LOW_EXP 70 | ||
214 | #define TC 94 | ||
215 | #define EXP_ACC_DARK 50 | ||
216 | #define EXP_ACC_LIGHT 90 | ||
217 | #define HIGH_COMP_102 160 | ||
218 | #define MAX_COMP 239 | ||
219 | #define DARK_TIME 3 | ||
220 | #define LIGHT_TIME 3 | ||
221 | |||
222 | #define FIRMWARE_VERSION(x, y) (sd->params.version.firmwareVersion == (x) && \ | ||
223 | sd->params.version.firmwareRevision == (y)) | ||
224 | |||
225 | /* Developer's Guide Table 5 p 3-34 | ||
226 | * indexed by [mains][sensorFps.baserate][sensorFps.divisor]*/ | ||
227 | static u8 flicker_jumps[2][2][4] = | ||
228 | { { { 76, 38, 19, 9 }, { 92, 46, 23, 11 } }, | ||
229 | { { 64, 32, 16, 8 }, { 76, 38, 19, 9} } | ||
230 | }; | ||
231 | |||
232 | struct cam_params { | ||
233 | struct { | ||
234 | u8 firmwareVersion; | ||
235 | u8 firmwareRevision; | ||
236 | u8 vcVersion; | ||
237 | u8 vcRevision; | ||
238 | } version; | ||
239 | struct { | ||
240 | u16 vendor; | ||
241 | u16 product; | ||
242 | u16 deviceRevision; | ||
243 | } pnpID; | ||
244 | struct { | ||
245 | u8 vpVersion; | ||
246 | u8 vpRevision; | ||
247 | u16 cameraHeadID; | ||
248 | } vpVersion; | ||
249 | struct { | ||
250 | u8 systemState; | ||
251 | u8 grabState; | ||
252 | u8 streamState; | ||
253 | u8 fatalError; | ||
254 | u8 cmdError; | ||
255 | u8 debugFlags; | ||
256 | u8 vpStatus; | ||
257 | u8 errorCode; | ||
258 | } status; | ||
259 | struct { | ||
260 | u8 brightness; | ||
261 | u8 contrast; | ||
262 | u8 saturation; | ||
263 | } colourParams; | ||
264 | struct { | ||
265 | u8 gainMode; | ||
266 | u8 expMode; | ||
267 | u8 compMode; | ||
268 | u8 centreWeight; | ||
269 | u8 gain; | ||
270 | u8 fineExp; | ||
271 | u8 coarseExpLo; | ||
272 | u8 coarseExpHi; | ||
273 | u8 redComp; | ||
274 | u8 green1Comp; | ||
275 | u8 green2Comp; | ||
276 | u8 blueComp; | ||
277 | } exposure; | ||
278 | struct { | ||
279 | u8 balanceMode; | ||
280 | u8 redGain; | ||
281 | u8 greenGain; | ||
282 | u8 blueGain; | ||
283 | } colourBalance; | ||
284 | struct { | ||
285 | u8 divisor; | ||
286 | u8 baserate; | ||
287 | } sensorFps; | ||
288 | struct { | ||
289 | u8 gain1; | ||
290 | u8 gain2; | ||
291 | u8 gain4; | ||
292 | u8 gain8; | ||
293 | } apcor; | ||
294 | struct { | ||
295 | u8 disabled; | ||
296 | u8 flickerMode; | ||
297 | u8 coarseJump; | ||
298 | u8 allowableOverExposure; | ||
299 | } flickerControl; | ||
300 | struct { | ||
301 | u8 gain1; | ||
302 | u8 gain2; | ||
303 | u8 gain4; | ||
304 | u8 gain8; | ||
305 | } vlOffset; | ||
306 | struct { | ||
307 | u8 mode; | ||
308 | u8 decimation; | ||
309 | } compression; | ||
310 | struct { | ||
311 | u8 frTargeting; | ||
312 | u8 targetFR; | ||
313 | u8 targetQ; | ||
314 | } compressionTarget; | ||
315 | struct { | ||
316 | u8 yThreshold; | ||
317 | u8 uvThreshold; | ||
318 | } yuvThreshold; | ||
319 | struct { | ||
320 | u8 hysteresis; | ||
321 | u8 threshMax; | ||
322 | u8 smallStep; | ||
323 | u8 largeStep; | ||
324 | u8 decimationHysteresis; | ||
325 | u8 frDiffStepThresh; | ||
326 | u8 qDiffStepThresh; | ||
327 | u8 decimationThreshMod; | ||
328 | } compressionParams; | ||
329 | struct { | ||
330 | u8 videoSize; /* CIF/QCIF */ | ||
331 | u8 subSample; | ||
332 | u8 yuvOrder; | ||
333 | } format; | ||
334 | struct { /* Intel QX3 specific data */ | ||
335 | u8 qx3_detected; /* a QX3 is present */ | ||
336 | u8 toplight; /* top light lit , R/W */ | ||
337 | u8 bottomlight; /* bottom light lit, R/W */ | ||
338 | u8 button; /* snapshot button pressed (R/O) */ | ||
339 | u8 cradled; /* microscope is in cradle (R/O) */ | ||
340 | } qx3; | ||
341 | struct { | ||
342 | u8 colStart; /* skip first 8*colStart pixels */ | ||
343 | u8 colEnd; /* finish at 8*colEnd pixels */ | ||
344 | u8 rowStart; /* skip first 4*rowStart lines */ | ||
345 | u8 rowEnd; /* finish at 4*rowEnd lines */ | ||
346 | } roi; | ||
347 | u8 ecpTiming; | ||
348 | u8 streamStartLine; | ||
349 | }; | ||
350 | |||
351 | /* specific webcam descriptor */ | ||
352 | struct sd { | ||
353 | struct gspca_dev gspca_dev; /* !! must be the first item */ | ||
354 | struct cam_params params; /* camera settings */ | ||
355 | |||
356 | atomic_t cam_exposure; | ||
357 | atomic_t fps; | ||
358 | int exposure_count; | ||
359 | u8 exposure_status; | ||
360 | u8 mainsFreq; /* 0 = 50hz, 1 = 60hz */ | ||
361 | u8 first_frame; | ||
362 | u8 freq; | ||
363 | }; | ||
364 | |||
365 | /* V4L2 controls supported by the driver */ | ||
366 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | ||
367 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
368 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | ||
369 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | ||
370 | static int sd_setsaturation(struct gspca_dev *gspca_dev, __s32 val); | ||
371 | static int sd_getsaturation(struct gspca_dev *gspca_dev, __s32 *val); | ||
372 | static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); | ||
373 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); | ||
374 | static int sd_setcomptarget(struct gspca_dev *gspca_dev, __s32 val); | ||
375 | static int sd_getcomptarget(struct gspca_dev *gspca_dev, __s32 *val); | ||
376 | |||
377 | static struct ctrl sd_ctrls[] = { | ||
378 | { | ||
379 | { | ||
380 | .id = V4L2_CID_BRIGHTNESS, | ||
381 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
382 | .name = "Brightness", | ||
383 | .minimum = 0, | ||
384 | .maximum = 100, | ||
385 | .step = 1, | ||
386 | #define BRIGHTNESS_DEF 50 | ||
387 | .default_value = BRIGHTNESS_DEF, | ||
388 | .flags = 0, | ||
389 | }, | ||
390 | .set = sd_setbrightness, | ||
391 | .get = sd_getbrightness, | ||
392 | }, | ||
393 | { | ||
394 | { | ||
395 | .id = V4L2_CID_CONTRAST, | ||
396 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
397 | .name = "Contrast", | ||
398 | .minimum = 0, | ||
399 | .maximum = 96, | ||
400 | .step = 8, | ||
401 | #define CONTRAST_DEF 48 | ||
402 | .default_value = CONTRAST_DEF, | ||
403 | }, | ||
404 | .set = sd_setcontrast, | ||
405 | .get = sd_getcontrast, | ||
406 | }, | ||
407 | { | ||
408 | { | ||
409 | .id = V4L2_CID_SATURATION, | ||
410 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
411 | .name = "Saturation", | ||
412 | .minimum = 0, | ||
413 | .maximum = 100, | ||
414 | .step = 1, | ||
415 | #define SATURATION_DEF 50 | ||
416 | .default_value = SATURATION_DEF, | ||
417 | }, | ||
418 | .set = sd_setsaturation, | ||
419 | .get = sd_getsaturation, | ||
420 | }, | ||
421 | { | ||
422 | { | ||
423 | .id = V4L2_CID_POWER_LINE_FREQUENCY, | ||
424 | .type = V4L2_CTRL_TYPE_MENU, | ||
425 | .name = "Light frequency filter", | ||
426 | .minimum = 0, | ||
427 | .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */ | ||
428 | .step = 1, | ||
429 | #define FREQ_DEF 1 | ||
430 | .default_value = FREQ_DEF, | ||
431 | }, | ||
432 | .set = sd_setfreq, | ||
433 | .get = sd_getfreq, | ||
434 | }, | ||
435 | { | ||
436 | { | ||
437 | #define V4L2_CID_COMP_TARGET V4L2_CID_PRIVATE_BASE | ||
438 | .id = V4L2_CID_COMP_TARGET, | ||
439 | .type = V4L2_CTRL_TYPE_MENU, | ||
440 | .name = "Compression Target", | ||
441 | .minimum = 0, | ||
442 | .maximum = 1, | ||
443 | .step = 1, | ||
444 | #define COMP_TARGET_DEF CPIA_COMPRESSION_TARGET_QUALITY | ||
445 | .default_value = COMP_TARGET_DEF, | ||
446 | }, | ||
447 | .set = sd_setcomptarget, | ||
448 | .get = sd_getcomptarget, | ||
449 | }, | ||
450 | }; | ||
451 | |||
452 | static const struct v4l2_pix_format mode[] = { | ||
453 | {160, 120, V4L2_PIX_FMT_CPIA1, V4L2_FIELD_NONE, | ||
454 | /* The sizeimage is trial and error, as with low framerates | ||
455 | the camera will pad out usb frames, making the image | ||
456 | data larger then strictly necessary */ | ||
457 | .bytesperline = 160, | ||
458 | .sizeimage = 65536, | ||
459 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
460 | .priv = 3}, | ||
461 | {176, 144, V4L2_PIX_FMT_CPIA1, V4L2_FIELD_NONE, | ||
462 | .bytesperline = 172, | ||
463 | .sizeimage = 65536, | ||
464 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
465 | .priv = 2}, | ||
466 | {320, 240, V4L2_PIX_FMT_CPIA1, V4L2_FIELD_NONE, | ||
467 | .bytesperline = 320, | ||
468 | .sizeimage = 262144, | ||
469 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
470 | .priv = 1}, | ||
471 | {352, 288, V4L2_PIX_FMT_CPIA1, V4L2_FIELD_NONE, | ||
472 | .bytesperline = 352, | ||
473 | .sizeimage = 262144, | ||
474 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
475 | .priv = 0}, | ||
476 | }; | ||
477 | |||
478 | /********************************************************************** | ||
479 | * | ||
480 | * General functions | ||
481 | * | ||
482 | **********************************************************************/ | ||
483 | |||
484 | static int cpia_usb_transferCmd(struct gspca_dev *gspca_dev, u8 *command) | ||
485 | { | ||
486 | u8 requesttype; | ||
487 | unsigned int pipe; | ||
488 | int ret, databytes = command[6] | (command[7] << 8); | ||
489 | /* Sometimes we see spurious EPIPE errors */ | ||
490 | int retries = 3; | ||
491 | |||
492 | if (command[0] == DATA_IN) { | ||
493 | pipe = usb_rcvctrlpipe(gspca_dev->dev, 0); | ||
494 | requesttype = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE; | ||
495 | } else if (command[0] == DATA_OUT) { | ||
496 | pipe = usb_sndctrlpipe(gspca_dev->dev, 0); | ||
497 | requesttype = USB_TYPE_VENDOR | USB_RECIP_DEVICE; | ||
498 | } else { | ||
499 | PDEBUG(D_ERR, "Unexpected first byte of command: %x", | ||
500 | command[0]); | ||
501 | return -EINVAL; | ||
502 | } | ||
503 | |||
504 | retry: | ||
505 | ret = usb_control_msg(gspca_dev->dev, pipe, | ||
506 | command[1], | ||
507 | requesttype, | ||
508 | command[2] | (command[3] << 8), | ||
509 | command[4] | (command[5] << 8), | ||
510 | gspca_dev->usb_buf, databytes, 1000); | ||
511 | |||
512 | if (ret < 0) | ||
513 | PDEBUG(D_ERR, "usb_control_msg %02x, error %d", command[1], | ||
514 | ret); | ||
515 | |||
516 | if (ret == -EPIPE && retries > 0) { | ||
517 | retries--; | ||
518 | goto retry; | ||
519 | } | ||
520 | |||
521 | return (ret < 0) ? ret : 0; | ||
522 | } | ||
523 | |||
524 | /* send an arbitrary command to the camera */ | ||
525 | static int do_command(struct gspca_dev *gspca_dev, u16 command, | ||
526 | u8 a, u8 b, u8 c, u8 d) | ||
527 | { | ||
528 | struct sd *sd = (struct sd *) gspca_dev; | ||
529 | int ret, datasize; | ||
530 | u8 cmd[8]; | ||
531 | |||
532 | switch (command) { | ||
533 | case CPIA_COMMAND_GetCPIAVersion: | ||
534 | case CPIA_COMMAND_GetPnPID: | ||
535 | case CPIA_COMMAND_GetCameraStatus: | ||
536 | case CPIA_COMMAND_GetVPVersion: | ||
537 | case CPIA_COMMAND_GetColourParams: | ||
538 | case CPIA_COMMAND_GetColourBalance: | ||
539 | case CPIA_COMMAND_GetExposure: | ||
540 | datasize = 8; | ||
541 | break; | ||
542 | case CPIA_COMMAND_ReadMCPorts: | ||
543 | case CPIA_COMMAND_ReadVCRegs: | ||
544 | datasize = 4; | ||
545 | break; | ||
546 | default: | ||
547 | datasize = 0; | ||
548 | break; | ||
549 | } | ||
550 | |||
551 | cmd[0] = command >> 8; | ||
552 | cmd[1] = command & 0xff; | ||
553 | cmd[2] = a; | ||
554 | cmd[3] = b; | ||
555 | cmd[4] = c; | ||
556 | cmd[5] = d; | ||
557 | cmd[6] = datasize; | ||
558 | cmd[7] = 0; | ||
559 | |||
560 | ret = cpia_usb_transferCmd(gspca_dev, cmd); | ||
561 | if (ret) | ||
562 | return ret; | ||
563 | |||
564 | switch (command) { | ||
565 | case CPIA_COMMAND_GetCPIAVersion: | ||
566 | sd->params.version.firmwareVersion = gspca_dev->usb_buf[0]; | ||
567 | sd->params.version.firmwareRevision = gspca_dev->usb_buf[1]; | ||
568 | sd->params.version.vcVersion = gspca_dev->usb_buf[2]; | ||
569 | sd->params.version.vcRevision = gspca_dev->usb_buf[3]; | ||
570 | break; | ||
571 | case CPIA_COMMAND_GetPnPID: | ||
572 | sd->params.pnpID.vendor = | ||
573 | gspca_dev->usb_buf[0] | (gspca_dev->usb_buf[1] << 8); | ||
574 | sd->params.pnpID.product = | ||
575 | gspca_dev->usb_buf[2] | (gspca_dev->usb_buf[3] << 8); | ||
576 | sd->params.pnpID.deviceRevision = | ||
577 | gspca_dev->usb_buf[4] | (gspca_dev->usb_buf[5] << 8); | ||
578 | break; | ||
579 | case CPIA_COMMAND_GetCameraStatus: | ||
580 | sd->params.status.systemState = gspca_dev->usb_buf[0]; | ||
581 | sd->params.status.grabState = gspca_dev->usb_buf[1]; | ||
582 | sd->params.status.streamState = gspca_dev->usb_buf[2]; | ||
583 | sd->params.status.fatalError = gspca_dev->usb_buf[3]; | ||
584 | sd->params.status.cmdError = gspca_dev->usb_buf[4]; | ||
585 | sd->params.status.debugFlags = gspca_dev->usb_buf[5]; | ||
586 | sd->params.status.vpStatus = gspca_dev->usb_buf[6]; | ||
587 | sd->params.status.errorCode = gspca_dev->usb_buf[7]; | ||
588 | break; | ||
589 | case CPIA_COMMAND_GetVPVersion: | ||
590 | sd->params.vpVersion.vpVersion = gspca_dev->usb_buf[0]; | ||
591 | sd->params.vpVersion.vpRevision = gspca_dev->usb_buf[1]; | ||
592 | sd->params.vpVersion.cameraHeadID = | ||
593 | gspca_dev->usb_buf[2] | (gspca_dev->usb_buf[3] << 8); | ||
594 | break; | ||
595 | case CPIA_COMMAND_GetColourParams: | ||
596 | sd->params.colourParams.brightness = gspca_dev->usb_buf[0]; | ||
597 | sd->params.colourParams.contrast = gspca_dev->usb_buf[1]; | ||
598 | sd->params.colourParams.saturation = gspca_dev->usb_buf[2]; | ||
599 | break; | ||
600 | case CPIA_COMMAND_GetColourBalance: | ||
601 | sd->params.colourBalance.redGain = gspca_dev->usb_buf[0]; | ||
602 | sd->params.colourBalance.greenGain = gspca_dev->usb_buf[1]; | ||
603 | sd->params.colourBalance.blueGain = gspca_dev->usb_buf[2]; | ||
604 | break; | ||
605 | case CPIA_COMMAND_GetExposure: | ||
606 | sd->params.exposure.gain = gspca_dev->usb_buf[0]; | ||
607 | sd->params.exposure.fineExp = gspca_dev->usb_buf[1]; | ||
608 | sd->params.exposure.coarseExpLo = gspca_dev->usb_buf[2]; | ||
609 | sd->params.exposure.coarseExpHi = gspca_dev->usb_buf[3]; | ||
610 | sd->params.exposure.redComp = gspca_dev->usb_buf[4]; | ||
611 | sd->params.exposure.green1Comp = gspca_dev->usb_buf[5]; | ||
612 | sd->params.exposure.green2Comp = gspca_dev->usb_buf[6]; | ||
613 | sd->params.exposure.blueComp = gspca_dev->usb_buf[7]; | ||
614 | break; | ||
615 | |||
616 | case CPIA_COMMAND_ReadMCPorts: | ||
617 | if (!sd->params.qx3.qx3_detected) | ||
618 | break; | ||
619 | /* test button press */ | ||
620 | sd->params.qx3.button = ((gspca_dev->usb_buf[1] & 0x02) == 0); | ||
621 | if (sd->params.qx3.button) { | ||
622 | /* button pressed - unlock the latch */ | ||
623 | do_command(gspca_dev, CPIA_COMMAND_WriteMCPort, | ||
624 | 3, 0xDF, 0xDF, 0); | ||
625 | do_command(gspca_dev, CPIA_COMMAND_WriteMCPort, | ||
626 | 3, 0xFF, 0xFF, 0); | ||
627 | } | ||
628 | |||
629 | /* test whether microscope is cradled */ | ||
630 | sd->params.qx3.cradled = ((gspca_dev->usb_buf[2] & 0x40) == 0); | ||
631 | break; | ||
632 | } | ||
633 | |||
634 | return 0; | ||
635 | } | ||
636 | |||
637 | /* send a command to the camera with an additional data transaction */ | ||
638 | static int do_command_extended(struct gspca_dev *gspca_dev, u16 command, | ||
639 | u8 a, u8 b, u8 c, u8 d, | ||
640 | u8 e, u8 f, u8 g, u8 h, | ||
641 | u8 i, u8 j, u8 k, u8 l) | ||
642 | { | ||
643 | u8 cmd[8]; | ||
644 | |||
645 | cmd[0] = command >> 8; | ||
646 | cmd[1] = command & 0xff; | ||
647 | cmd[2] = a; | ||
648 | cmd[3] = b; | ||
649 | cmd[4] = c; | ||
650 | cmd[5] = d; | ||
651 | cmd[6] = 8; | ||
652 | cmd[7] = 0; | ||
653 | gspca_dev->usb_buf[0] = e; | ||
654 | gspca_dev->usb_buf[1] = f; | ||
655 | gspca_dev->usb_buf[2] = g; | ||
656 | gspca_dev->usb_buf[3] = h; | ||
657 | gspca_dev->usb_buf[4] = i; | ||
658 | gspca_dev->usb_buf[5] = j; | ||
659 | gspca_dev->usb_buf[6] = k; | ||
660 | gspca_dev->usb_buf[7] = l; | ||
661 | |||
662 | return cpia_usb_transferCmd(gspca_dev, cmd); | ||
663 | } | ||
664 | |||
665 | /* find_over_exposure | ||
666 | * Finds a suitable value of OverExposure for use with SetFlickerCtrl | ||
667 | * Some calculation is required because this value changes with the brightness | ||
668 | * set with SetColourParameters | ||
669 | * | ||
670 | * Parameters: Brightness - last brightness value set with SetColourParameters | ||
671 | * | ||
672 | * Returns: OverExposure value to use with SetFlickerCtrl | ||
673 | */ | ||
674 | #define FLICKER_MAX_EXPOSURE 250 | ||
675 | #define FLICKER_ALLOWABLE_OVER_EXPOSURE 146 | ||
676 | #define FLICKER_BRIGHTNESS_CONSTANT 59 | ||
677 | static int find_over_exposure(int brightness) | ||
678 | { | ||
679 | int MaxAllowableOverExposure, OverExposure; | ||
680 | |||
681 | MaxAllowableOverExposure = FLICKER_MAX_EXPOSURE - brightness - | ||
682 | FLICKER_BRIGHTNESS_CONSTANT; | ||
683 | |||
684 | if (MaxAllowableOverExposure < FLICKER_ALLOWABLE_OVER_EXPOSURE) | ||
685 | OverExposure = MaxAllowableOverExposure; | ||
686 | else | ||
687 | OverExposure = FLICKER_ALLOWABLE_OVER_EXPOSURE; | ||
688 | |||
689 | return OverExposure; | ||
690 | } | ||
691 | #undef FLICKER_MAX_EXPOSURE | ||
692 | #undef FLICKER_ALLOWABLE_OVER_EXPOSURE | ||
693 | #undef FLICKER_BRIGHTNESS_CONSTANT | ||
694 | |||
695 | /* initialise cam_data structure */ | ||
696 | static void reset_camera_params(struct gspca_dev *gspca_dev) | ||
697 | { | ||
698 | struct sd *sd = (struct sd *) gspca_dev; | ||
699 | struct cam_params *params = &sd->params; | ||
700 | |||
701 | /* The following parameter values are the defaults from | ||
702 | * "Software Developer's Guide for CPiA Cameras". Any changes | ||
703 | * to the defaults are noted in comments. */ | ||
704 | params->colourParams.brightness = BRIGHTNESS_DEF; | ||
705 | params->colourParams.contrast = CONTRAST_DEF; | ||
706 | params->colourParams.saturation = SATURATION_DEF; | ||
707 | params->exposure.gainMode = 4; | ||
708 | params->exposure.expMode = 2; /* AEC */ | ||
709 | params->exposure.compMode = 1; | ||
710 | params->exposure.centreWeight = 1; | ||
711 | params->exposure.gain = 0; | ||
712 | params->exposure.fineExp = 0; | ||
713 | params->exposure.coarseExpLo = 185; | ||
714 | params->exposure.coarseExpHi = 0; | ||
715 | params->exposure.redComp = COMP_RED; | ||
716 | params->exposure.green1Comp = COMP_GREEN1; | ||
717 | params->exposure.green2Comp = COMP_GREEN2; | ||
718 | params->exposure.blueComp = COMP_BLUE; | ||
719 | params->colourBalance.balanceMode = 2; /* ACB */ | ||
720 | params->colourBalance.redGain = 32; | ||
721 | params->colourBalance.greenGain = 6; | ||
722 | params->colourBalance.blueGain = 92; | ||
723 | params->apcor.gain1 = 0x18; | ||
724 | params->apcor.gain2 = 0x16; | ||
725 | params->apcor.gain4 = 0x24; | ||
726 | params->apcor.gain8 = 0x34; | ||
727 | params->flickerControl.flickerMode = 0; | ||
728 | params->flickerControl.disabled = 1; | ||
729 | |||
730 | params->flickerControl.coarseJump = | ||
731 | flicker_jumps[sd->mainsFreq] | ||
732 | [params->sensorFps.baserate] | ||
733 | [params->sensorFps.divisor]; | ||
734 | params->flickerControl.allowableOverExposure = | ||
735 | find_over_exposure(params->colourParams.brightness); | ||
736 | params->vlOffset.gain1 = 20; | ||
737 | params->vlOffset.gain2 = 24; | ||
738 | params->vlOffset.gain4 = 26; | ||
739 | params->vlOffset.gain8 = 26; | ||
740 | params->compressionParams.hysteresis = 3; | ||
741 | params->compressionParams.threshMax = 11; | ||
742 | params->compressionParams.smallStep = 1; | ||
743 | params->compressionParams.largeStep = 3; | ||
744 | params->compressionParams.decimationHysteresis = 2; | ||
745 | params->compressionParams.frDiffStepThresh = 5; | ||
746 | params->compressionParams.qDiffStepThresh = 3; | ||
747 | params->compressionParams.decimationThreshMod = 2; | ||
748 | /* End of default values from Software Developer's Guide */ | ||
749 | |||
750 | /* Set Sensor FPS to 15fps. This seems better than 30fps | ||
751 | * for indoor lighting. */ | ||
752 | params->sensorFps.divisor = 1; | ||
753 | params->sensorFps.baserate = 1; | ||
754 | |||
755 | params->yuvThreshold.yThreshold = 6; /* From windows driver */ | ||
756 | params->yuvThreshold.uvThreshold = 6; /* From windows driver */ | ||
757 | |||
758 | params->format.subSample = SUBSAMPLE_420; | ||
759 | params->format.yuvOrder = YUVORDER_YUYV; | ||
760 | |||
761 | params->compression.mode = CPIA_COMPRESSION_AUTO; | ||
762 | params->compression.decimation = NO_DECIMATION; | ||
763 | |||
764 | params->compressionTarget.frTargeting = COMP_TARGET_DEF; | ||
765 | params->compressionTarget.targetFR = 15; /* From windows driver */ | ||
766 | params->compressionTarget.targetQ = 5; /* From windows driver */ | ||
767 | |||
768 | params->qx3.qx3_detected = 0; | ||
769 | params->qx3.toplight = 0; | ||
770 | params->qx3.bottomlight = 0; | ||
771 | params->qx3.button = 0; | ||
772 | params->qx3.cradled = 0; | ||
773 | } | ||
774 | |||
775 | static void printstatus(struct cam_params *params) | ||
776 | { | ||
777 | PDEBUG(D_PROBE, "status: %02x %02x %02x %02x %02x %02x %02x %02x", | ||
778 | params->status.systemState, params->status.grabState, | ||
779 | params->status.streamState, params->status.fatalError, | ||
780 | params->status.cmdError, params->status.debugFlags, | ||
781 | params->status.vpStatus, params->status.errorCode); | ||
782 | } | ||
783 | |||
784 | static int goto_low_power(struct gspca_dev *gspca_dev) | ||
785 | { | ||
786 | struct sd *sd = (struct sd *) gspca_dev; | ||
787 | int ret; | ||
788 | |||
789 | ret = do_command(gspca_dev, CPIA_COMMAND_GotoLoPower, 0, 0, 0, 0); | ||
790 | if (ret) | ||
791 | return ret; | ||
792 | |||
793 | do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0); | ||
794 | if (ret) | ||
795 | return ret; | ||
796 | |||
797 | if (sd->params.status.systemState != LO_POWER_STATE) { | ||
798 | if (sd->params.status.systemState != WARM_BOOT_STATE) { | ||
799 | PDEBUG(D_ERR, | ||
800 | "unexpected state after lo power cmd: %02x", | ||
801 | sd->params.status.systemState); | ||
802 | printstatus(&sd->params); | ||
803 | } | ||
804 | return -EIO; | ||
805 | } | ||
806 | |||
807 | PDEBUG(D_CONF, "camera now in LOW power state"); | ||
808 | return 0; | ||
809 | } | ||
810 | |||
811 | static int goto_high_power(struct gspca_dev *gspca_dev) | ||
812 | { | ||
813 | struct sd *sd = (struct sd *) gspca_dev; | ||
814 | int ret; | ||
815 | |||
816 | ret = do_command(gspca_dev, CPIA_COMMAND_GotoHiPower, 0, 0, 0, 0); | ||
817 | if (ret) | ||
818 | return ret; | ||
819 | |||
820 | msleep_interruptible(40); /* windows driver does it too */ | ||
821 | |||
822 | if (signal_pending(current)) | ||
823 | return -EINTR; | ||
824 | |||
825 | do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0); | ||
826 | if (ret) | ||
827 | return ret; | ||
828 | |||
829 | if (sd->params.status.systemState != HI_POWER_STATE) { | ||
830 | PDEBUG(D_ERR, "unexpected state after hi power cmd: %02x", | ||
831 | sd->params.status.systemState); | ||
832 | printstatus(&sd->params); | ||
833 | return -EIO; | ||
834 | } | ||
835 | |||
836 | PDEBUG(D_CONF, "camera now in HIGH power state"); | ||
837 | return 0; | ||
838 | } | ||
839 | |||
840 | static int get_version_information(struct gspca_dev *gspca_dev) | ||
841 | { | ||
842 | int ret; | ||
843 | |||
844 | /* GetCPIAVersion */ | ||
845 | ret = do_command(gspca_dev, CPIA_COMMAND_GetCPIAVersion, 0, 0, 0, 0); | ||
846 | if (ret) | ||
847 | return ret; | ||
848 | |||
849 | /* GetPnPID */ | ||
850 | return do_command(gspca_dev, CPIA_COMMAND_GetPnPID, 0, 0, 0, 0); | ||
851 | } | ||
852 | |||
853 | static int save_camera_state(struct gspca_dev *gspca_dev) | ||
854 | { | ||
855 | int ret; | ||
856 | |||
857 | ret = do_command(gspca_dev, CPIA_COMMAND_GetColourBalance, 0, 0, 0, 0); | ||
858 | if (ret) | ||
859 | return ret; | ||
860 | |||
861 | return do_command(gspca_dev, CPIA_COMMAND_GetExposure, 0, 0, 0, 0); | ||
862 | } | ||
863 | |||
864 | int command_setformat(struct gspca_dev *gspca_dev) | ||
865 | { | ||
866 | struct sd *sd = (struct sd *) gspca_dev; | ||
867 | int ret; | ||
868 | |||
869 | ret = do_command(gspca_dev, CPIA_COMMAND_SetFormat, | ||
870 | sd->params.format.videoSize, | ||
871 | sd->params.format.subSample, | ||
872 | sd->params.format.yuvOrder, 0); | ||
873 | if (ret) | ||
874 | return ret; | ||
875 | |||
876 | return do_command(gspca_dev, CPIA_COMMAND_SetROI, | ||
877 | sd->params.roi.colStart, sd->params.roi.colEnd, | ||
878 | sd->params.roi.rowStart, sd->params.roi.rowEnd); | ||
879 | } | ||
880 | |||
881 | int command_setcolourparams(struct gspca_dev *gspca_dev) | ||
882 | { | ||
883 | struct sd *sd = (struct sd *) gspca_dev; | ||
884 | return do_command(gspca_dev, CPIA_COMMAND_SetColourParams, | ||
885 | sd->params.colourParams.brightness, | ||
886 | sd->params.colourParams.contrast, | ||
887 | sd->params.colourParams.saturation, 0); | ||
888 | } | ||
889 | |||
890 | int command_setapcor(struct gspca_dev *gspca_dev) | ||
891 | { | ||
892 | struct sd *sd = (struct sd *) gspca_dev; | ||
893 | return do_command(gspca_dev, CPIA_COMMAND_SetApcor, | ||
894 | sd->params.apcor.gain1, | ||
895 | sd->params.apcor.gain2, | ||
896 | sd->params.apcor.gain4, | ||
897 | sd->params.apcor.gain8); | ||
898 | } | ||
899 | |||
900 | int command_setvloffset(struct gspca_dev *gspca_dev) | ||
901 | { | ||
902 | struct sd *sd = (struct sd *) gspca_dev; | ||
903 | return do_command(gspca_dev, CPIA_COMMAND_SetVLOffset, | ||
904 | sd->params.vlOffset.gain1, | ||
905 | sd->params.vlOffset.gain2, | ||
906 | sd->params.vlOffset.gain4, | ||
907 | sd->params.vlOffset.gain8); | ||
908 | } | ||
909 | |||
910 | int command_setexposure(struct gspca_dev *gspca_dev) | ||
911 | { | ||
912 | struct sd *sd = (struct sd *) gspca_dev; | ||
913 | int ret; | ||
914 | |||
915 | ret = do_command_extended(gspca_dev, CPIA_COMMAND_SetExposure, | ||
916 | sd->params.exposure.gainMode, | ||
917 | 1, | ||
918 | sd->params.exposure.compMode, | ||
919 | sd->params.exposure.centreWeight, | ||
920 | sd->params.exposure.gain, | ||
921 | sd->params.exposure.fineExp, | ||
922 | sd->params.exposure.coarseExpLo, | ||
923 | sd->params.exposure.coarseExpHi, | ||
924 | sd->params.exposure.redComp, | ||
925 | sd->params.exposure.green1Comp, | ||
926 | sd->params.exposure.green2Comp, | ||
927 | sd->params.exposure.blueComp); | ||
928 | if (ret) | ||
929 | return ret; | ||
930 | |||
931 | if (sd->params.exposure.expMode != 1) { | ||
932 | ret = do_command_extended(gspca_dev, CPIA_COMMAND_SetExposure, | ||
933 | 0, | ||
934 | sd->params.exposure.expMode, | ||
935 | 0, 0, | ||
936 | sd->params.exposure.gain, | ||
937 | sd->params.exposure.fineExp, | ||
938 | sd->params.exposure.coarseExpLo, | ||
939 | sd->params.exposure.coarseExpHi, | ||
940 | 0, 0, 0, 0); | ||
941 | } | ||
942 | |||
943 | return ret; | ||
944 | } | ||
945 | |||
946 | int command_setcolourbalance(struct gspca_dev *gspca_dev) | ||
947 | { | ||
948 | struct sd *sd = (struct sd *) gspca_dev; | ||
949 | |||
950 | if (sd->params.colourBalance.balanceMode == 1) { | ||
951 | int ret; | ||
952 | |||
953 | ret = do_command(gspca_dev, CPIA_COMMAND_SetColourBalance, | ||
954 | 1, | ||
955 | sd->params.colourBalance.redGain, | ||
956 | sd->params.colourBalance.greenGain, | ||
957 | sd->params.colourBalance.blueGain); | ||
958 | if (ret) | ||
959 | return ret; | ||
960 | |||
961 | return do_command(gspca_dev, CPIA_COMMAND_SetColourBalance, | ||
962 | 3, 0, 0, 0); | ||
963 | } | ||
964 | if (sd->params.colourBalance.balanceMode == 2) { | ||
965 | return do_command(gspca_dev, CPIA_COMMAND_SetColourBalance, | ||
966 | 2, 0, 0, 0); | ||
967 | } | ||
968 | if (sd->params.colourBalance.balanceMode == 3) { | ||
969 | return do_command(gspca_dev, CPIA_COMMAND_SetColourBalance, | ||
970 | 3, 0, 0, 0); | ||
971 | } | ||
972 | |||
973 | return -EINVAL; | ||
974 | } | ||
975 | |||
976 | int command_setcompressiontarget(struct gspca_dev *gspca_dev) | ||
977 | { | ||
978 | struct sd *sd = (struct sd *) gspca_dev; | ||
979 | |||
980 | return do_command(gspca_dev, CPIA_COMMAND_SetCompressionTarget, | ||
981 | sd->params.compressionTarget.frTargeting, | ||
982 | sd->params.compressionTarget.targetFR, | ||
983 | sd->params.compressionTarget.targetQ, 0); | ||
984 | } | ||
985 | |||
986 | int command_setyuvtresh(struct gspca_dev *gspca_dev) | ||
987 | { | ||
988 | struct sd *sd = (struct sd *) gspca_dev; | ||
989 | |||
990 | return do_command(gspca_dev, CPIA_COMMAND_SetYUVThresh, | ||
991 | sd->params.yuvThreshold.yThreshold, | ||
992 | sd->params.yuvThreshold.uvThreshold, 0, 0); | ||
993 | } | ||
994 | |||
995 | int command_setcompressionparams(struct gspca_dev *gspca_dev) | ||
996 | { | ||
997 | struct sd *sd = (struct sd *) gspca_dev; | ||
998 | |||
999 | return do_command_extended(gspca_dev, | ||
1000 | CPIA_COMMAND_SetCompressionParams, | ||
1001 | 0, 0, 0, 0, | ||
1002 | sd->params.compressionParams.hysteresis, | ||
1003 | sd->params.compressionParams.threshMax, | ||
1004 | sd->params.compressionParams.smallStep, | ||
1005 | sd->params.compressionParams.largeStep, | ||
1006 | sd->params.compressionParams.decimationHysteresis, | ||
1007 | sd->params.compressionParams.frDiffStepThresh, | ||
1008 | sd->params.compressionParams.qDiffStepThresh, | ||
1009 | sd->params.compressionParams.decimationThreshMod); | ||
1010 | } | ||
1011 | |||
1012 | int command_setcompression(struct gspca_dev *gspca_dev) | ||
1013 | { | ||
1014 | struct sd *sd = (struct sd *) gspca_dev; | ||
1015 | |||
1016 | return do_command(gspca_dev, CPIA_COMMAND_SetCompression, | ||
1017 | sd->params.compression.mode, | ||
1018 | sd->params.compression.decimation, 0, 0); | ||
1019 | } | ||
1020 | |||
1021 | int command_setsensorfps(struct gspca_dev *gspca_dev) | ||
1022 | { | ||
1023 | struct sd *sd = (struct sd *) gspca_dev; | ||
1024 | |||
1025 | return do_command(gspca_dev, CPIA_COMMAND_SetSensorFPS, | ||
1026 | sd->params.sensorFps.divisor, | ||
1027 | sd->params.sensorFps.baserate, 0, 0); | ||
1028 | } | ||
1029 | |||
1030 | int command_setflickerctrl(struct gspca_dev *gspca_dev) | ||
1031 | { | ||
1032 | struct sd *sd = (struct sd *) gspca_dev; | ||
1033 | |||
1034 | return do_command(gspca_dev, CPIA_COMMAND_SetFlickerCtrl, | ||
1035 | sd->params.flickerControl.flickerMode, | ||
1036 | sd->params.flickerControl.coarseJump, | ||
1037 | sd->params.flickerControl.allowableOverExposure, | ||
1038 | 0); | ||
1039 | } | ||
1040 | |||
1041 | int command_setecptiming(struct gspca_dev *gspca_dev) | ||
1042 | { | ||
1043 | struct sd *sd = (struct sd *) gspca_dev; | ||
1044 | |||
1045 | return do_command(gspca_dev, CPIA_COMMAND_SetECPTiming, | ||
1046 | sd->params.ecpTiming, 0, 0, 0); | ||
1047 | } | ||
1048 | |||
1049 | int command_pause(struct gspca_dev *gspca_dev) | ||
1050 | { | ||
1051 | return do_command(gspca_dev, CPIA_COMMAND_EndStreamCap, 0, 0, 0, 0); | ||
1052 | } | ||
1053 | |||
1054 | int command_resume(struct gspca_dev *gspca_dev) | ||
1055 | { | ||
1056 | struct sd *sd = (struct sd *) gspca_dev; | ||
1057 | |||
1058 | return do_command(gspca_dev, CPIA_COMMAND_InitStreamCap, | ||
1059 | 0, sd->params.streamStartLine, 0, 0); | ||
1060 | } | ||
1061 | |||
1062 | int command_setlights(struct gspca_dev *gspca_dev) | ||
1063 | { | ||
1064 | struct sd *sd = (struct sd *) gspca_dev; | ||
1065 | int ret, p1, p2; | ||
1066 | |||
1067 | if (!sd->params.qx3.qx3_detected) | ||
1068 | return 0; | ||
1069 | |||
1070 | p1 = (sd->params.qx3.bottomlight == 0) << 1; | ||
1071 | p2 = (sd->params.qx3.toplight == 0) << 3; | ||
1072 | |||
1073 | ret = do_command(gspca_dev, CPIA_COMMAND_WriteVCReg, | ||
1074 | 0x90, 0x8F, 0x50, 0); | ||
1075 | if (ret) | ||
1076 | return ret; | ||
1077 | |||
1078 | return do_command(gspca_dev, CPIA_COMMAND_WriteMCPort, 2, 0, | ||
1079 | p1 | p2 | 0xE0, 0); | ||
1080 | } | ||
1081 | |||
1082 | static int set_flicker(struct gspca_dev *gspca_dev, int on, int apply) | ||
1083 | { | ||
1084 | /* Everything in here is from the Windows driver */ | ||
1085 | /* define for compgain calculation */ | ||
1086 | #if 0 | ||
1087 | #define COMPGAIN(base, curexp, newexp) \ | ||
1088 | (u8) ((((float) base - 128.0) * ((float) curexp / (float) newexp)) + 128.5) | ||
1089 | #define EXP_FROM_COMP(basecomp, curcomp, curexp) \ | ||
1090 | (u16)((float)curexp * (float)(u8)(curcomp + 128) / \ | ||
1091 | (float)(u8)(basecomp - 128)) | ||
1092 | #else | ||
1093 | /* equivalent functions without floating point math */ | ||
1094 | #define COMPGAIN(base, curexp, newexp) \ | ||
1095 | (u8)(128 + (((u32)(2*(base-128)*curexp + newexp)) / (2 * newexp))) | ||
1096 | #define EXP_FROM_COMP(basecomp, curcomp, curexp) \ | ||
1097 | (u16)(((u32)(curexp * (u8)(curcomp + 128)) / (u8)(basecomp - 128))) | ||
1098 | #endif | ||
1099 | |||
1100 | struct sd *sd = (struct sd *) gspca_dev; | ||
1101 | int currentexp = sd->params.exposure.coarseExpLo + | ||
1102 | sd->params.exposure.coarseExpHi * 256; | ||
1103 | int ret, startexp; | ||
1104 | |||
1105 | if (on) { | ||
1106 | int cj = sd->params.flickerControl.coarseJump; | ||
1107 | sd->params.flickerControl.flickerMode = 1; | ||
1108 | sd->params.flickerControl.disabled = 0; | ||
1109 | if (sd->params.exposure.expMode != 2) { | ||
1110 | sd->params.exposure.expMode = 2; | ||
1111 | sd->exposure_status = EXPOSURE_NORMAL; | ||
1112 | } | ||
1113 | currentexp = currentexp << sd->params.exposure.gain; | ||
1114 | sd->params.exposure.gain = 0; | ||
1115 | /* round down current exposure to nearest value */ | ||
1116 | startexp = (currentexp + ROUND_UP_EXP_FOR_FLICKER) / cj; | ||
1117 | if (startexp < 1) | ||
1118 | startexp = 1; | ||
1119 | startexp = (startexp * cj) - 1; | ||
1120 | if (FIRMWARE_VERSION(1, 2)) | ||
1121 | while (startexp > MAX_EXP_102) | ||
1122 | startexp -= cj; | ||
1123 | else | ||
1124 | while (startexp > MAX_EXP) | ||
1125 | startexp -= cj; | ||
1126 | sd->params.exposure.coarseExpLo = startexp & 0xff; | ||
1127 | sd->params.exposure.coarseExpHi = startexp >> 8; | ||
1128 | if (currentexp > startexp) { | ||
1129 | if (currentexp > (2 * startexp)) | ||
1130 | currentexp = 2 * startexp; | ||
1131 | sd->params.exposure.redComp = | ||
1132 | COMPGAIN(COMP_RED, currentexp, startexp); | ||
1133 | sd->params.exposure.green1Comp = | ||
1134 | COMPGAIN(COMP_GREEN1, currentexp, startexp); | ||
1135 | sd->params.exposure.green2Comp = | ||
1136 | COMPGAIN(COMP_GREEN2, currentexp, startexp); | ||
1137 | sd->params.exposure.blueComp = | ||
1138 | COMPGAIN(COMP_BLUE, currentexp, startexp); | ||
1139 | } else { | ||
1140 | sd->params.exposure.redComp = COMP_RED; | ||
1141 | sd->params.exposure.green1Comp = COMP_GREEN1; | ||
1142 | sd->params.exposure.green2Comp = COMP_GREEN2; | ||
1143 | sd->params.exposure.blueComp = COMP_BLUE; | ||
1144 | } | ||
1145 | if (FIRMWARE_VERSION(1, 2)) | ||
1146 | sd->params.exposure.compMode = 0; | ||
1147 | else | ||
1148 | sd->params.exposure.compMode = 1; | ||
1149 | |||
1150 | sd->params.apcor.gain1 = 0x18; | ||
1151 | sd->params.apcor.gain2 = 0x18; | ||
1152 | sd->params.apcor.gain4 = 0x16; | ||
1153 | sd->params.apcor.gain8 = 0x14; | ||
1154 | } else { | ||
1155 | sd->params.flickerControl.flickerMode = 0; | ||
1156 | sd->params.flickerControl.disabled = 1; | ||
1157 | /* Average equivalent coarse for each comp channel */ | ||
1158 | startexp = EXP_FROM_COMP(COMP_RED, | ||
1159 | sd->params.exposure.redComp, currentexp); | ||
1160 | startexp += EXP_FROM_COMP(COMP_GREEN1, | ||
1161 | sd->params.exposure.green1Comp, currentexp); | ||
1162 | startexp += EXP_FROM_COMP(COMP_GREEN2, | ||
1163 | sd->params.exposure.green2Comp, currentexp); | ||
1164 | startexp += EXP_FROM_COMP(COMP_BLUE, | ||
1165 | sd->params.exposure.blueComp, currentexp); | ||
1166 | startexp = startexp >> 2; | ||
1167 | while (startexp > MAX_EXP && sd->params.exposure.gain < | ||
1168 | sd->params.exposure.gainMode - 1) { | ||
1169 | startexp = startexp >> 1; | ||
1170 | ++sd->params.exposure.gain; | ||
1171 | } | ||
1172 | if (FIRMWARE_VERSION(1, 2) && startexp > MAX_EXP_102) | ||
1173 | startexp = MAX_EXP_102; | ||
1174 | if (startexp > MAX_EXP) | ||
1175 | startexp = MAX_EXP; | ||
1176 | sd->params.exposure.coarseExpLo = startexp & 0xff; | ||
1177 | sd->params.exposure.coarseExpHi = startexp >> 8; | ||
1178 | sd->params.exposure.redComp = COMP_RED; | ||
1179 | sd->params.exposure.green1Comp = COMP_GREEN1; | ||
1180 | sd->params.exposure.green2Comp = COMP_GREEN2; | ||
1181 | sd->params.exposure.blueComp = COMP_BLUE; | ||
1182 | sd->params.exposure.compMode = 1; | ||
1183 | sd->params.apcor.gain1 = 0x18; | ||
1184 | sd->params.apcor.gain2 = 0x16; | ||
1185 | sd->params.apcor.gain4 = 0x24; | ||
1186 | sd->params.apcor.gain8 = 0x34; | ||
1187 | } | ||
1188 | sd->params.vlOffset.gain1 = 20; | ||
1189 | sd->params.vlOffset.gain2 = 24; | ||
1190 | sd->params.vlOffset.gain4 = 26; | ||
1191 | sd->params.vlOffset.gain8 = 26; | ||
1192 | |||
1193 | if (apply) { | ||
1194 | ret = command_setexposure(gspca_dev); | ||
1195 | if (ret) | ||
1196 | return ret; | ||
1197 | |||
1198 | ret = command_setapcor(gspca_dev); | ||
1199 | if (ret) | ||
1200 | return ret; | ||
1201 | |||
1202 | ret = command_setvloffset(gspca_dev); | ||
1203 | if (ret) | ||
1204 | return ret; | ||
1205 | |||
1206 | ret = command_setflickerctrl(gspca_dev); | ||
1207 | if (ret) | ||
1208 | return ret; | ||
1209 | } | ||
1210 | |||
1211 | return 0; | ||
1212 | #undef EXP_FROM_COMP | ||
1213 | #undef COMPGAIN | ||
1214 | } | ||
1215 | |||
1216 | /* monitor the exposure and adjust the sensor frame rate if needed */ | ||
1217 | static void monitor_exposure(struct gspca_dev *gspca_dev) | ||
1218 | { | ||
1219 | struct sd *sd = (struct sd *) gspca_dev; | ||
1220 | u8 exp_acc, bcomp, gain, coarseL, cmd[8]; | ||
1221 | int ret, light_exp, dark_exp, very_dark_exp; | ||
1222 | int old_exposure, new_exposure, framerate; | ||
1223 | int setfps = 0, setexp = 0, setflicker = 0; | ||
1224 | |||
1225 | /* get necessary stats and register settings from camera */ | ||
1226 | /* do_command can't handle this, so do it ourselves */ | ||
1227 | cmd[0] = CPIA_COMMAND_ReadVPRegs >> 8; | ||
1228 | cmd[1] = CPIA_COMMAND_ReadVPRegs & 0xff; | ||
1229 | cmd[2] = 30; | ||
1230 | cmd[3] = 4; | ||
1231 | cmd[4] = 9; | ||
1232 | cmd[5] = 8; | ||
1233 | cmd[6] = 8; | ||
1234 | cmd[7] = 0; | ||
1235 | ret = cpia_usb_transferCmd(gspca_dev, cmd); | ||
1236 | if (ret) { | ||
1237 | PDEBUG(D_ERR, "ReadVPRegs(30,4,9,8) - failed: %d", ret); | ||
1238 | return; | ||
1239 | } | ||
1240 | exp_acc = gspca_dev->usb_buf[0]; | ||
1241 | bcomp = gspca_dev->usb_buf[1]; | ||
1242 | gain = gspca_dev->usb_buf[2]; | ||
1243 | coarseL = gspca_dev->usb_buf[3]; | ||
1244 | |||
1245 | light_exp = sd->params.colourParams.brightness + | ||
1246 | TC - 50 + EXP_ACC_LIGHT; | ||
1247 | if (light_exp > 255) | ||
1248 | light_exp = 255; | ||
1249 | dark_exp = sd->params.colourParams.brightness + | ||
1250 | TC - 50 - EXP_ACC_DARK; | ||
1251 | if (dark_exp < 0) | ||
1252 | dark_exp = 0; | ||
1253 | very_dark_exp = dark_exp / 2; | ||
1254 | |||
1255 | old_exposure = sd->params.exposure.coarseExpHi * 256 + | ||
1256 | sd->params.exposure.coarseExpLo; | ||
1257 | |||
1258 | if (!sd->params.flickerControl.disabled) { | ||
1259 | /* Flicker control on */ | ||
1260 | int max_comp = FIRMWARE_VERSION(1, 2) ? MAX_COMP : | ||
1261 | HIGH_COMP_102; | ||
1262 | bcomp += 128; /* decode */ | ||
1263 | if (bcomp >= max_comp && exp_acc < dark_exp) { | ||
1264 | /* dark */ | ||
1265 | if (exp_acc < very_dark_exp) { | ||
1266 | /* very dark */ | ||
1267 | if (sd->exposure_status == EXPOSURE_VERY_DARK) | ||
1268 | ++sd->exposure_count; | ||
1269 | else { | ||
1270 | sd->exposure_status = | ||
1271 | EXPOSURE_VERY_DARK; | ||
1272 | sd->exposure_count = 1; | ||
1273 | } | ||
1274 | } else { | ||
1275 | /* just dark */ | ||
1276 | if (sd->exposure_status == EXPOSURE_DARK) | ||
1277 | ++sd->exposure_count; | ||
1278 | else { | ||
1279 | sd->exposure_status = EXPOSURE_DARK; | ||
1280 | sd->exposure_count = 1; | ||
1281 | } | ||
1282 | } | ||
1283 | } else if (old_exposure <= LOW_EXP || exp_acc > light_exp) { | ||
1284 | /* light */ | ||
1285 | if (old_exposure <= VERY_LOW_EXP) { | ||
1286 | /* very light */ | ||
1287 | if (sd->exposure_status == EXPOSURE_VERY_LIGHT) | ||
1288 | ++sd->exposure_count; | ||
1289 | else { | ||
1290 | sd->exposure_status = | ||
1291 | EXPOSURE_VERY_LIGHT; | ||
1292 | sd->exposure_count = 1; | ||
1293 | } | ||
1294 | } else { | ||
1295 | /* just light */ | ||
1296 | if (sd->exposure_status == EXPOSURE_LIGHT) | ||
1297 | ++sd->exposure_count; | ||
1298 | else { | ||
1299 | sd->exposure_status = EXPOSURE_LIGHT; | ||
1300 | sd->exposure_count = 1; | ||
1301 | } | ||
1302 | } | ||
1303 | } else { | ||
1304 | /* not dark or light */ | ||
1305 | sd->exposure_status = EXPOSURE_NORMAL; | ||
1306 | } | ||
1307 | } else { | ||
1308 | /* Flicker control off */ | ||
1309 | if (old_exposure >= MAX_EXP && exp_acc < dark_exp) { | ||
1310 | /* dark */ | ||
1311 | if (exp_acc < very_dark_exp) { | ||
1312 | /* very dark */ | ||
1313 | if (sd->exposure_status == EXPOSURE_VERY_DARK) | ||
1314 | ++sd->exposure_count; | ||
1315 | else { | ||
1316 | sd->exposure_status = | ||
1317 | EXPOSURE_VERY_DARK; | ||
1318 | sd->exposure_count = 1; | ||
1319 | } | ||
1320 | } else { | ||
1321 | /* just dark */ | ||
1322 | if (sd->exposure_status == EXPOSURE_DARK) | ||
1323 | ++sd->exposure_count; | ||
1324 | else { | ||
1325 | sd->exposure_status = EXPOSURE_DARK; | ||
1326 | sd->exposure_count = 1; | ||
1327 | } | ||
1328 | } | ||
1329 | } else if (old_exposure <= LOW_EXP || exp_acc > light_exp) { | ||
1330 | /* light */ | ||
1331 | if (old_exposure <= VERY_LOW_EXP) { | ||
1332 | /* very light */ | ||
1333 | if (sd->exposure_status == EXPOSURE_VERY_LIGHT) | ||
1334 | ++sd->exposure_count; | ||
1335 | else { | ||
1336 | sd->exposure_status = | ||
1337 | EXPOSURE_VERY_LIGHT; | ||
1338 | sd->exposure_count = 1; | ||
1339 | } | ||
1340 | } else { | ||
1341 | /* just light */ | ||
1342 | if (sd->exposure_status == EXPOSURE_LIGHT) | ||
1343 | ++sd->exposure_count; | ||
1344 | else { | ||
1345 | sd->exposure_status = EXPOSURE_LIGHT; | ||
1346 | sd->exposure_count = 1; | ||
1347 | } | ||
1348 | } | ||
1349 | } else { | ||
1350 | /* not dark or light */ | ||
1351 | sd->exposure_status = EXPOSURE_NORMAL; | ||
1352 | } | ||
1353 | } | ||
1354 | |||
1355 | framerate = atomic_read(&sd->fps); | ||
1356 | if (framerate > 30 || framerate < 1) | ||
1357 | framerate = 1; | ||
1358 | |||
1359 | if (!sd->params.flickerControl.disabled) { | ||
1360 | /* Flicker control on */ | ||
1361 | if ((sd->exposure_status == EXPOSURE_VERY_DARK || | ||
1362 | sd->exposure_status == EXPOSURE_DARK) && | ||
1363 | sd->exposure_count >= DARK_TIME * framerate && | ||
1364 | sd->params.sensorFps.divisor < 3) { | ||
1365 | |||
1366 | /* dark for too long */ | ||
1367 | ++sd->params.sensorFps.divisor; | ||
1368 | setfps = 1; | ||
1369 | |||
1370 | sd->params.flickerControl.coarseJump = | ||
1371 | flicker_jumps[sd->mainsFreq] | ||
1372 | [sd->params.sensorFps.baserate] | ||
1373 | [sd->params.sensorFps.divisor]; | ||
1374 | setflicker = 1; | ||
1375 | |||
1376 | new_exposure = sd->params.flickerControl.coarseJump-1; | ||
1377 | while (new_exposure < old_exposure / 2) | ||
1378 | new_exposure += | ||
1379 | sd->params.flickerControl.coarseJump; | ||
1380 | sd->params.exposure.coarseExpLo = new_exposure & 0xff; | ||
1381 | sd->params.exposure.coarseExpHi = new_exposure >> 8; | ||
1382 | setexp = 1; | ||
1383 | sd->exposure_status = EXPOSURE_NORMAL; | ||
1384 | PDEBUG(D_CONF, "Automatically decreasing sensor_fps"); | ||
1385 | |||
1386 | } else if ((sd->exposure_status == EXPOSURE_VERY_LIGHT || | ||
1387 | sd->exposure_status == EXPOSURE_LIGHT) && | ||
1388 | sd->exposure_count >= LIGHT_TIME * framerate && | ||
1389 | sd->params.sensorFps.divisor > 0) { | ||
1390 | |||
1391 | /* light for too long */ | ||
1392 | int max_exp = FIRMWARE_VERSION(1, 2) ? MAX_EXP_102 : | ||
1393 | MAX_EXP; | ||
1394 | --sd->params.sensorFps.divisor; | ||
1395 | setfps = 1; | ||
1396 | |||
1397 | sd->params.flickerControl.coarseJump = | ||
1398 | flicker_jumps[sd->mainsFreq] | ||
1399 | [sd->params.sensorFps.baserate] | ||
1400 | [sd->params.sensorFps.divisor]; | ||
1401 | setflicker = 1; | ||
1402 | |||
1403 | new_exposure = sd->params.flickerControl.coarseJump-1; | ||
1404 | while (new_exposure < 2 * old_exposure && | ||
1405 | new_exposure + | ||
1406 | sd->params.flickerControl.coarseJump < max_exp) | ||
1407 | new_exposure += | ||
1408 | sd->params.flickerControl.coarseJump; | ||
1409 | sd->params.exposure.coarseExpLo = new_exposure & 0xff; | ||
1410 | sd->params.exposure.coarseExpHi = new_exposure >> 8; | ||
1411 | setexp = 1; | ||
1412 | sd->exposure_status = EXPOSURE_NORMAL; | ||
1413 | PDEBUG(D_CONF, "Automatically increasing sensor_fps"); | ||
1414 | } | ||
1415 | } else { | ||
1416 | /* Flicker control off */ | ||
1417 | if ((sd->exposure_status == EXPOSURE_VERY_DARK || | ||
1418 | sd->exposure_status == EXPOSURE_DARK) && | ||
1419 | sd->exposure_count >= DARK_TIME * framerate && | ||
1420 | sd->params.sensorFps.divisor < 3) { | ||
1421 | |||
1422 | /* dark for too long */ | ||
1423 | ++sd->params.sensorFps.divisor; | ||
1424 | setfps = 1; | ||
1425 | |||
1426 | if (sd->params.exposure.gain > 0) { | ||
1427 | --sd->params.exposure.gain; | ||
1428 | setexp = 1; | ||
1429 | } | ||
1430 | sd->exposure_status = EXPOSURE_NORMAL; | ||
1431 | PDEBUG(D_CONF, "Automatically decreasing sensor_fps"); | ||
1432 | |||
1433 | } else if ((sd->exposure_status == EXPOSURE_VERY_LIGHT || | ||
1434 | sd->exposure_status == EXPOSURE_LIGHT) && | ||
1435 | sd->exposure_count >= LIGHT_TIME * framerate && | ||
1436 | sd->params.sensorFps.divisor > 0) { | ||
1437 | |||
1438 | /* light for too long */ | ||
1439 | --sd->params.sensorFps.divisor; | ||
1440 | setfps = 1; | ||
1441 | |||
1442 | if (sd->params.exposure.gain < | ||
1443 | sd->params.exposure.gainMode - 1) { | ||
1444 | ++sd->params.exposure.gain; | ||
1445 | setexp = 1; | ||
1446 | } | ||
1447 | sd->exposure_status = EXPOSURE_NORMAL; | ||
1448 | PDEBUG(D_CONF, "Automatically increasing sensor_fps"); | ||
1449 | } | ||
1450 | } | ||
1451 | |||
1452 | if (setexp) | ||
1453 | command_setexposure(gspca_dev); | ||
1454 | |||
1455 | if (setfps) | ||
1456 | command_setsensorfps(gspca_dev); | ||
1457 | |||
1458 | if (setflicker) | ||
1459 | command_setflickerctrl(gspca_dev); | ||
1460 | } | ||
1461 | |||
1462 | /*-----------------------------------------------------------------*/ | ||
1463 | /* if flicker is switched off, this function switches it back on.It checks, | ||
1464 | however, that conditions are suitable before restarting it. | ||
1465 | This should only be called for firmware version 1.2. | ||
1466 | |||
1467 | It also adjust the colour balance when an exposure step is detected - as | ||
1468 | long as flicker is running | ||
1469 | */ | ||
1470 | static void restart_flicker(struct gspca_dev *gspca_dev) | ||
1471 | { | ||
1472 | struct sd *sd = (struct sd *) gspca_dev; | ||
1473 | int cam_exposure, old_exp; | ||
1474 | |||
1475 | if (!FIRMWARE_VERSION(1, 2)) | ||
1476 | return; | ||
1477 | |||
1478 | cam_exposure = atomic_read(&sd->cam_exposure); | ||
1479 | |||
1480 | if (sd->params.flickerControl.flickerMode == 0 || | ||
1481 | cam_exposure == 0) | ||
1482 | return; | ||
1483 | |||
1484 | old_exp = sd->params.exposure.coarseExpLo + | ||
1485 | sd->params.exposure.coarseExpHi*256; | ||
1486 | /* | ||
1487 | see how far away camera exposure is from a valid | ||
1488 | flicker exposure value | ||
1489 | */ | ||
1490 | cam_exposure %= sd->params.flickerControl.coarseJump; | ||
1491 | if (!sd->params.flickerControl.disabled && | ||
1492 | cam_exposure <= sd->params.flickerControl.coarseJump - 3) { | ||
1493 | /* Flicker control auto-disabled */ | ||
1494 | sd->params.flickerControl.disabled = 1; | ||
1495 | } | ||
1496 | |||
1497 | if (sd->params.flickerControl.disabled && | ||
1498 | old_exp > sd->params.flickerControl.coarseJump + | ||
1499 | ROUND_UP_EXP_FOR_FLICKER) { | ||
1500 | /* exposure is now high enough to switch | ||
1501 | flicker control back on */ | ||
1502 | set_flicker(gspca_dev, 1, 1); | ||
1503 | } | ||
1504 | } | ||
1505 | |||
1506 | /* this function is called at probe time */ | ||
1507 | static int sd_config(struct gspca_dev *gspca_dev, | ||
1508 | const struct usb_device_id *id) | ||
1509 | { | ||
1510 | struct cam *cam; | ||
1511 | |||
1512 | reset_camera_params(gspca_dev); | ||
1513 | |||
1514 | PDEBUG(D_PROBE, "cpia CPiA camera detected (vid/pid 0x%04X:0x%04X)", | ||
1515 | id->idVendor, id->idProduct); | ||
1516 | |||
1517 | cam = &gspca_dev->cam; | ||
1518 | cam->cam_mode = mode; | ||
1519 | cam->nmodes = ARRAY_SIZE(mode); | ||
1520 | |||
1521 | sd_setfreq(gspca_dev, FREQ_DEF); | ||
1522 | |||
1523 | return 0; | ||
1524 | } | ||
1525 | |||
1526 | /* -- start the camera -- */ | ||
1527 | static int sd_start(struct gspca_dev *gspca_dev) | ||
1528 | { | ||
1529 | struct sd *sd = (struct sd *) gspca_dev; | ||
1530 | int priv, ret; | ||
1531 | |||
1532 | /* Start the camera in low power mode */ | ||
1533 | if (goto_low_power(gspca_dev)) { | ||
1534 | if (sd->params.status.systemState != WARM_BOOT_STATE) { | ||
1535 | PDEBUG(D_ERR, "unexpected systemstate: %02x", | ||
1536 | sd->params.status.systemState); | ||
1537 | printstatus(&sd->params); | ||
1538 | return -ENODEV; | ||
1539 | } | ||
1540 | |||
1541 | /* FIXME: this is just dirty trial and error */ | ||
1542 | ret = goto_high_power(gspca_dev); | ||
1543 | if (ret) | ||
1544 | return ret; | ||
1545 | |||
1546 | ret = do_command(gspca_dev, CPIA_COMMAND_DiscardFrame, | ||
1547 | 0, 0, 0, 0); | ||
1548 | if (ret) | ||
1549 | return ret; | ||
1550 | |||
1551 | ret = goto_low_power(gspca_dev); | ||
1552 | if (ret) | ||
1553 | return ret; | ||
1554 | } | ||
1555 | |||
1556 | /* procedure described in developer's guide p3-28 */ | ||
1557 | |||
1558 | /* Check the firmware version. */ | ||
1559 | sd->params.version.firmwareVersion = 0; | ||
1560 | get_version_information(gspca_dev); | ||
1561 | if (sd->params.version.firmwareVersion != 1) { | ||
1562 | PDEBUG(D_ERR, "only firmware version 1 is supported (got: %d)", | ||
1563 | sd->params.version.firmwareVersion); | ||
1564 | return -ENODEV; | ||
1565 | } | ||
1566 | |||
1567 | /* A bug in firmware 1-02 limits gainMode to 2 */ | ||
1568 | if (sd->params.version.firmwareRevision <= 2 && | ||
1569 | sd->params.exposure.gainMode > 2) { | ||
1570 | sd->params.exposure.gainMode = 2; | ||
1571 | } | ||
1572 | |||
1573 | /* set QX3 detected flag */ | ||
1574 | sd->params.qx3.qx3_detected = (sd->params.pnpID.vendor == 0x0813 && | ||
1575 | sd->params.pnpID.product == 0x0001); | ||
1576 | |||
1577 | /* The fatal error checking should be done after | ||
1578 | * the camera powers up (developer's guide p 3-38) */ | ||
1579 | |||
1580 | /* Set streamState before transition to high power to avoid bug | ||
1581 | * in firmware 1-02 */ | ||
1582 | ret = do_command(gspca_dev, CPIA_COMMAND_ModifyCameraStatus, | ||
1583 | STREAMSTATE, 0, STREAM_NOT_READY, 0); | ||
1584 | if (ret) | ||
1585 | return ret; | ||
1586 | |||
1587 | /* GotoHiPower */ | ||
1588 | ret = goto_high_power(gspca_dev); | ||
1589 | if (ret) | ||
1590 | return ret; | ||
1591 | |||
1592 | /* Check the camera status */ | ||
1593 | ret = do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0); | ||
1594 | if (ret) | ||
1595 | return ret; | ||
1596 | |||
1597 | if (sd->params.status.fatalError) { | ||
1598 | PDEBUG(D_ERR, "fatal_error: %04x, vp_status: %04x", | ||
1599 | sd->params.status.fatalError, | ||
1600 | sd->params.status.vpStatus); | ||
1601 | return -EIO; | ||
1602 | } | ||
1603 | |||
1604 | /* VPVersion can't be retrieved before the camera is in HiPower, | ||
1605 | * so get it here instead of in get_version_information. */ | ||
1606 | ret = do_command(gspca_dev, CPIA_COMMAND_GetVPVersion, 0, 0, 0, 0); | ||
1607 | if (ret) | ||
1608 | return ret; | ||
1609 | |||
1610 | /* Determine video mode settings */ | ||
1611 | sd->params.streamStartLine = 120; | ||
1612 | |||
1613 | priv = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; | ||
1614 | if (priv & 0x01) { /* crop */ | ||
1615 | sd->params.roi.colStart = 2; | ||
1616 | sd->params.roi.rowStart = 6; | ||
1617 | } else { | ||
1618 | sd->params.roi.colStart = 0; | ||
1619 | sd->params.roi.rowStart = 0; | ||
1620 | } | ||
1621 | |||
1622 | if (priv & 0x02) { /* quarter */ | ||
1623 | sd->params.format.videoSize = VIDEOSIZE_QCIF; | ||
1624 | sd->params.roi.colStart /= 2; | ||
1625 | sd->params.roi.rowStart /= 2; | ||
1626 | sd->params.streamStartLine /= 2; | ||
1627 | } else | ||
1628 | sd->params.format.videoSize = VIDEOSIZE_CIF; | ||
1629 | |||
1630 | sd->params.roi.colEnd = sd->params.roi.colStart + | ||
1631 | (gspca_dev->width >> 3); | ||
1632 | sd->params.roi.rowEnd = sd->params.roi.rowStart + | ||
1633 | (gspca_dev->height >> 2); | ||
1634 | |||
1635 | /* And now set the camera to a known state */ | ||
1636 | ret = do_command(gspca_dev, CPIA_COMMAND_SetGrabMode, | ||
1637 | CPIA_GRAB_CONTINEOUS, 0, 0, 0); | ||
1638 | if (ret) | ||
1639 | return ret; | ||
1640 | /* We start with compression disabled, as we need one uncompressed | ||
1641 | frame to handle later compressed frames */ | ||
1642 | ret = do_command(gspca_dev, CPIA_COMMAND_SetCompression, | ||
1643 | CPIA_COMPRESSION_NONE, | ||
1644 | NO_DECIMATION, 0, 0); | ||
1645 | if (ret) | ||
1646 | return ret; | ||
1647 | ret = command_setcompressiontarget(gspca_dev); | ||
1648 | if (ret) | ||
1649 | return ret; | ||
1650 | ret = command_setcolourparams(gspca_dev); | ||
1651 | if (ret) | ||
1652 | return ret; | ||
1653 | ret = command_setformat(gspca_dev); | ||
1654 | if (ret) | ||
1655 | return ret; | ||
1656 | ret = command_setyuvtresh(gspca_dev); | ||
1657 | if (ret) | ||
1658 | return ret; | ||
1659 | ret = command_setecptiming(gspca_dev); | ||
1660 | if (ret) | ||
1661 | return ret; | ||
1662 | ret = command_setcompressionparams(gspca_dev); | ||
1663 | if (ret) | ||
1664 | return ret; | ||
1665 | ret = command_setexposure(gspca_dev); | ||
1666 | if (ret) | ||
1667 | return ret; | ||
1668 | ret = command_setcolourbalance(gspca_dev); | ||
1669 | if (ret) | ||
1670 | return ret; | ||
1671 | ret = command_setsensorfps(gspca_dev); | ||
1672 | if (ret) | ||
1673 | return ret; | ||
1674 | ret = command_setapcor(gspca_dev); | ||
1675 | if (ret) | ||
1676 | return ret; | ||
1677 | ret = command_setflickerctrl(gspca_dev); | ||
1678 | if (ret) | ||
1679 | return ret; | ||
1680 | ret = command_setvloffset(gspca_dev); | ||
1681 | if (ret) | ||
1682 | return ret; | ||
1683 | |||
1684 | /* Start stream */ | ||
1685 | ret = command_resume(gspca_dev); | ||
1686 | if (ret) | ||
1687 | return ret; | ||
1688 | |||
1689 | /* Wait 6 frames before turning compression on for the sensor to get | ||
1690 | all settings and AEC/ACB to settle */ | ||
1691 | sd->first_frame = 6; | ||
1692 | sd->exposure_status = EXPOSURE_NORMAL; | ||
1693 | sd->exposure_count = 0; | ||
1694 | atomic_set(&sd->cam_exposure, 0); | ||
1695 | atomic_set(&sd->fps, 0); | ||
1696 | |||
1697 | return 0; | ||
1698 | } | ||
1699 | |||
1700 | static void sd_stopN(struct gspca_dev *gspca_dev) | ||
1701 | { | ||
1702 | command_pause(gspca_dev); | ||
1703 | |||
1704 | /* save camera state for later open (developers guide ch 3.5.3) */ | ||
1705 | save_camera_state(gspca_dev); | ||
1706 | |||
1707 | /* GotoLoPower */ | ||
1708 | goto_low_power(gspca_dev); | ||
1709 | |||
1710 | /* Update the camera status */ | ||
1711 | do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0); | ||
1712 | } | ||
1713 | |||
1714 | /* this function is called at probe and resume time */ | ||
1715 | static int sd_init(struct gspca_dev *gspca_dev) | ||
1716 | { | ||
1717 | struct sd *sd = (struct sd *) gspca_dev; | ||
1718 | int ret; | ||
1719 | |||
1720 | /* Start / Stop the camera to make sure we are talking to | ||
1721 | a supported camera, and to get some information from it | ||
1722 | to print. */ | ||
1723 | ret = sd_start(gspca_dev); | ||
1724 | if (ret) | ||
1725 | return ret; | ||
1726 | |||
1727 | sd_stopN(gspca_dev); | ||
1728 | |||
1729 | PDEBUG(D_PROBE, "CPIA Version: %d.%02d (%d.%d)", | ||
1730 | sd->params.version.firmwareVersion, | ||
1731 | sd->params.version.firmwareRevision, | ||
1732 | sd->params.version.vcVersion, | ||
1733 | sd->params.version.vcRevision); | ||
1734 | PDEBUG(D_PROBE, "CPIA PnP-ID: %04x:%04x:%04x", | ||
1735 | sd->params.pnpID.vendor, sd->params.pnpID.product, | ||
1736 | sd->params.pnpID.deviceRevision); | ||
1737 | PDEBUG(D_PROBE, "VP-Version: %d.%d %04x", | ||
1738 | sd->params.vpVersion.vpVersion, | ||
1739 | sd->params.vpVersion.vpRevision, | ||
1740 | sd->params.vpVersion.cameraHeadID); | ||
1741 | |||
1742 | return 0; | ||
1743 | } | ||
1744 | |||
1745 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | ||
1746 | u8 *data, | ||
1747 | int len) | ||
1748 | { | ||
1749 | struct sd *sd = (struct sd *) gspca_dev; | ||
1750 | |||
1751 | /* Check for SOF */ | ||
1752 | if (len >= 64 && | ||
1753 | data[0] == MAGIC_0 && data[1] == MAGIC_1 && | ||
1754 | data[16] == sd->params.format.videoSize && | ||
1755 | data[17] == sd->params.format.subSample && | ||
1756 | data[18] == sd->params.format.yuvOrder && | ||
1757 | data[24] == sd->params.roi.colStart && | ||
1758 | data[25] == sd->params.roi.colEnd && | ||
1759 | data[26] == sd->params.roi.rowStart && | ||
1760 | data[27] == sd->params.roi.rowEnd) { | ||
1761 | struct gspca_frame *frame = gspca_get_i_frame(gspca_dev); | ||
1762 | |||
1763 | atomic_set(&sd->cam_exposure, data[39] * 2); | ||
1764 | atomic_set(&sd->fps, data[41]); | ||
1765 | |||
1766 | if (frame == NULL) { | ||
1767 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
1768 | return; | ||
1769 | } | ||
1770 | |||
1771 | /* Check for proper EOF for last frame */ | ||
1772 | if ((frame->data_end - frame->data) > 4 && | ||
1773 | frame->data_end[-4] == 0xff && | ||
1774 | frame->data_end[-3] == 0xff && | ||
1775 | frame->data_end[-2] == 0xff && | ||
1776 | frame->data_end[-1] == 0xff) | ||
1777 | gspca_frame_add(gspca_dev, LAST_PACKET, | ||
1778 | NULL, 0); | ||
1779 | |||
1780 | gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); | ||
1781 | return; | ||
1782 | } | ||
1783 | |||
1784 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); | ||
1785 | } | ||
1786 | |||
1787 | static void sd_dq_callback(struct gspca_dev *gspca_dev) | ||
1788 | { | ||
1789 | struct sd *sd = (struct sd *) gspca_dev; | ||
1790 | |||
1791 | /* Set the normal compression settings once we have captured a | ||
1792 | few uncompressed frames (and AEC has hopefully settled) */ | ||
1793 | if (sd->first_frame) { | ||
1794 | sd->first_frame--; | ||
1795 | if (sd->first_frame == 0) | ||
1796 | command_setcompression(gspca_dev); | ||
1797 | } | ||
1798 | |||
1799 | /* Switch flicker control back on if it got turned off */ | ||
1800 | restart_flicker(gspca_dev); | ||
1801 | |||
1802 | /* If AEC is enabled, monitor the exposure and | ||
1803 | adjust the sensor frame rate if needed */ | ||
1804 | if (sd->params.exposure.expMode == 2) | ||
1805 | monitor_exposure(gspca_dev); | ||
1806 | |||
1807 | /* Update our knowledge of the camera state */ | ||
1808 | do_command(gspca_dev, CPIA_COMMAND_GetExposure, 0, 0, 0, 0); | ||
1809 | if (sd->params.qx3.qx3_detected) | ||
1810 | do_command(gspca_dev, CPIA_COMMAND_ReadMCPorts, 0, 0, 0, 0); | ||
1811 | } | ||
1812 | |||
1813 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | ||
1814 | { | ||
1815 | struct sd *sd = (struct sd *) gspca_dev; | ||
1816 | int ret; | ||
1817 | |||
1818 | sd->params.colourParams.brightness = val; | ||
1819 | sd->params.flickerControl.allowableOverExposure = | ||
1820 | find_over_exposure(sd->params.colourParams.brightness); | ||
1821 | if (gspca_dev->streaming) { | ||
1822 | ret = command_setcolourparams(gspca_dev); | ||
1823 | if (ret) | ||
1824 | return ret; | ||
1825 | return command_setflickerctrl(gspca_dev); | ||
1826 | } | ||
1827 | return 0; | ||
1828 | } | ||
1829 | |||
1830 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) | ||
1831 | { | ||
1832 | struct sd *sd = (struct sd *) gspca_dev; | ||
1833 | |||
1834 | *val = sd->params.colourParams.brightness; | ||
1835 | return 0; | ||
1836 | } | ||
1837 | |||
1838 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) | ||
1839 | { | ||
1840 | struct sd *sd = (struct sd *) gspca_dev; | ||
1841 | |||
1842 | sd->params.colourParams.contrast = val; | ||
1843 | if (gspca_dev->streaming) | ||
1844 | return command_setcolourparams(gspca_dev); | ||
1845 | |||
1846 | return 0; | ||
1847 | } | ||
1848 | |||
1849 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) | ||
1850 | { | ||
1851 | struct sd *sd = (struct sd *) gspca_dev; | ||
1852 | |||
1853 | *val = sd->params.colourParams.contrast; | ||
1854 | return 0; | ||
1855 | } | ||
1856 | |||
1857 | static int sd_setsaturation(struct gspca_dev *gspca_dev, __s32 val) | ||
1858 | { | ||
1859 | struct sd *sd = (struct sd *) gspca_dev; | ||
1860 | |||
1861 | sd->params.colourParams.saturation = val; | ||
1862 | if (gspca_dev->streaming) | ||
1863 | return command_setcolourparams(gspca_dev); | ||
1864 | |||
1865 | return 0; | ||
1866 | } | ||
1867 | |||
1868 | static int sd_getsaturation(struct gspca_dev *gspca_dev, __s32 *val) | ||
1869 | { | ||
1870 | struct sd *sd = (struct sd *) gspca_dev; | ||
1871 | |||
1872 | *val = sd->params.colourParams.saturation; | ||
1873 | return 0; | ||
1874 | } | ||
1875 | |||
1876 | static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val) | ||
1877 | { | ||
1878 | struct sd *sd = (struct sd *) gspca_dev; | ||
1879 | int on; | ||
1880 | |||
1881 | switch (val) { | ||
1882 | case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */ | ||
1883 | on = 0; | ||
1884 | break; | ||
1885 | case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */ | ||
1886 | on = 1; | ||
1887 | sd->mainsFreq = 0; | ||
1888 | break; | ||
1889 | case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */ | ||
1890 | on = 1; | ||
1891 | sd->mainsFreq = 1; | ||
1892 | break; | ||
1893 | default: | ||
1894 | return -EINVAL; | ||
1895 | } | ||
1896 | |||
1897 | sd->freq = val; | ||
1898 | sd->params.flickerControl.coarseJump = | ||
1899 | flicker_jumps[sd->mainsFreq] | ||
1900 | [sd->params.sensorFps.baserate] | ||
1901 | [sd->params.sensorFps.divisor]; | ||
1902 | |||
1903 | return set_flicker(gspca_dev, on, gspca_dev->streaming); | ||
1904 | } | ||
1905 | |||
1906 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val) | ||
1907 | { | ||
1908 | struct sd *sd = (struct sd *) gspca_dev; | ||
1909 | |||
1910 | *val = sd->freq; | ||
1911 | return 0; | ||
1912 | } | ||
1913 | |||
1914 | static int sd_setcomptarget(struct gspca_dev *gspca_dev, __s32 val) | ||
1915 | { | ||
1916 | struct sd *sd = (struct sd *) gspca_dev; | ||
1917 | |||
1918 | sd->params.compressionTarget.frTargeting = val; | ||
1919 | if (gspca_dev->streaming) | ||
1920 | return command_setcompressiontarget(gspca_dev); | ||
1921 | |||
1922 | return 0; | ||
1923 | } | ||
1924 | |||
1925 | static int sd_getcomptarget(struct gspca_dev *gspca_dev, __s32 *val) | ||
1926 | { | ||
1927 | struct sd *sd = (struct sd *) gspca_dev; | ||
1928 | |||
1929 | *val = sd->params.compressionTarget.frTargeting; | ||
1930 | return 0; | ||
1931 | } | ||
1932 | |||
1933 | static int sd_querymenu(struct gspca_dev *gspca_dev, | ||
1934 | struct v4l2_querymenu *menu) | ||
1935 | { | ||
1936 | switch (menu->id) { | ||
1937 | case V4L2_CID_POWER_LINE_FREQUENCY: | ||
1938 | switch (menu->index) { | ||
1939 | case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */ | ||
1940 | strcpy((char *) menu->name, "NoFliker"); | ||
1941 | return 0; | ||
1942 | case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */ | ||
1943 | strcpy((char *) menu->name, "50 Hz"); | ||
1944 | return 0; | ||
1945 | case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */ | ||
1946 | strcpy((char *) menu->name, "60 Hz"); | ||
1947 | return 0; | ||
1948 | } | ||
1949 | break; | ||
1950 | case V4L2_CID_COMP_TARGET: | ||
1951 | switch (menu->index) { | ||
1952 | case CPIA_COMPRESSION_TARGET_QUALITY: | ||
1953 | strcpy((char *) menu->name, "Quality"); | ||
1954 | return 0; | ||
1955 | case CPIA_COMPRESSION_TARGET_FRAMERATE: | ||
1956 | strcpy((char *) menu->name, "Framerate"); | ||
1957 | return 0; | ||
1958 | } | ||
1959 | break; | ||
1960 | } | ||
1961 | return -EINVAL; | ||
1962 | } | ||
1963 | |||
1964 | /* sub-driver description */ | ||
1965 | static const struct sd_desc sd_desc = { | ||
1966 | .name = MODULE_NAME, | ||
1967 | .ctrls = sd_ctrls, | ||
1968 | .nctrls = ARRAY_SIZE(sd_ctrls), | ||
1969 | .config = sd_config, | ||
1970 | .init = sd_init, | ||
1971 | .start = sd_start, | ||
1972 | .stopN = sd_stopN, | ||
1973 | .dq_callback = sd_dq_callback, | ||
1974 | .pkt_scan = sd_pkt_scan, | ||
1975 | .querymenu = sd_querymenu, | ||
1976 | }; | ||
1977 | |||
1978 | /* -- module initialisation -- */ | ||
1979 | static const __devinitdata struct usb_device_id device_table[] = { | ||
1980 | {USB_DEVICE(0x0553, 0x0002)}, | ||
1981 | {USB_DEVICE(0x0813, 0x0001)}, | ||
1982 | {} | ||
1983 | }; | ||
1984 | MODULE_DEVICE_TABLE(usb, device_table); | ||
1985 | |||
1986 | /* -- device connect -- */ | ||
1987 | static int sd_probe(struct usb_interface *intf, | ||
1988 | const struct usb_device_id *id) | ||
1989 | { | ||
1990 | return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), | ||
1991 | THIS_MODULE); | ||
1992 | } | ||
1993 | |||
1994 | static struct usb_driver sd_driver = { | ||
1995 | .name = MODULE_NAME, | ||
1996 | .id_table = device_table, | ||
1997 | .probe = sd_probe, | ||
1998 | .disconnect = gspca_disconnect, | ||
1999 | #ifdef CONFIG_PM | ||
2000 | .suspend = gspca_suspend, | ||
2001 | .resume = gspca_resume, | ||
2002 | #endif | ||
2003 | }; | ||
2004 | |||
2005 | /* -- module insert / remove -- */ | ||
2006 | static int __init sd_mod_init(void) | ||
2007 | { | ||
2008 | int ret; | ||
2009 | ret = usb_register(&sd_driver); | ||
2010 | if (ret < 0) | ||
2011 | return ret; | ||
2012 | PDEBUG(D_PROBE, "registered"); | ||
2013 | return 0; | ||
2014 | } | ||
2015 | static void __exit sd_mod_exit(void) | ||
2016 | { | ||
2017 | usb_deregister(&sd_driver); | ||
2018 | PDEBUG(D_PROBE, "deregistered"); | ||
2019 | } | ||
2020 | |||
2021 | module_init(sd_mod_init); | ||
2022 | module_exit(sd_mod_exit); | ||
diff --git a/drivers/media/video/gspca/etoms.c b/drivers/media/video/gspca/etoms.c index fdf4c0ec5e7a..ecd4d743d2bc 100644 --- a/drivers/media/video/gspca/etoms.c +++ b/drivers/media/video/gspca/etoms.c | |||
@@ -52,7 +52,7 @@ static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); | |||
52 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); | 52 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); |
53 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); | 53 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); |
54 | 54 | ||
55 | static struct ctrl sd_ctrls[] = { | 55 | static const struct ctrl sd_ctrls[] = { |
56 | { | 56 | { |
57 | { | 57 | { |
58 | .id = V4L2_CID_BRIGHTNESS, | 58 | .id = V4L2_CID_BRIGHTNESS, |
@@ -851,7 +851,7 @@ static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) | |||
851 | } | 851 | } |
852 | 852 | ||
853 | /* sub-driver description */ | 853 | /* sub-driver description */ |
854 | static struct sd_desc sd_desc = { | 854 | static const struct sd_desc sd_desc = { |
855 | .name = MODULE_NAME, | 855 | .name = MODULE_NAME, |
856 | .ctrls = sd_ctrls, | 856 | .ctrls = sd_ctrls, |
857 | .nctrls = ARRAY_SIZE(sd_ctrls), | 857 | .nctrls = ARRAY_SIZE(sd_ctrls), |
diff --git a/drivers/media/video/gspca/gl860/gl860.c b/drivers/media/video/gspca/gl860/gl860.c index 4878c8f66543..9e42476c0eaf 100644 --- a/drivers/media/video/gspca/gl860/gl860.c +++ b/drivers/media/video/gspca/gl860/gl860.c | |||
@@ -161,7 +161,7 @@ static int gl860_build_control_table(struct gspca_dev *gspca_dev) | |||
161 | 161 | ||
162 | /*==================== sud-driver structure initialisation =================*/ | 162 | /*==================== sud-driver structure initialisation =================*/ |
163 | 163 | ||
164 | static struct sd_desc sd_desc_mi1320 = { | 164 | static const struct sd_desc sd_desc_mi1320 = { |
165 | .name = MODULE_NAME, | 165 | .name = MODULE_NAME, |
166 | .ctrls = sd_ctrls_mi1320, | 166 | .ctrls = sd_ctrls_mi1320, |
167 | .nctrls = GL860_NCTRLS, | 167 | .nctrls = GL860_NCTRLS, |
@@ -174,7 +174,7 @@ static struct sd_desc sd_desc_mi1320 = { | |||
174 | .dq_callback = sd_callback, | 174 | .dq_callback = sd_callback, |
175 | }; | 175 | }; |
176 | 176 | ||
177 | static struct sd_desc sd_desc_mi2020 = { | 177 | static const struct sd_desc sd_desc_mi2020 = { |
178 | .name = MODULE_NAME, | 178 | .name = MODULE_NAME, |
179 | .ctrls = sd_ctrls_mi2020, | 179 | .ctrls = sd_ctrls_mi2020, |
180 | .nctrls = GL860_NCTRLS, | 180 | .nctrls = GL860_NCTRLS, |
@@ -187,7 +187,7 @@ static struct sd_desc sd_desc_mi2020 = { | |||
187 | .dq_callback = sd_callback, | 187 | .dq_callback = sd_callback, |
188 | }; | 188 | }; |
189 | 189 | ||
190 | static struct sd_desc sd_desc_mi2020b = { | 190 | static const struct sd_desc sd_desc_mi2020b = { |
191 | .name = MODULE_NAME, | 191 | .name = MODULE_NAME, |
192 | .ctrls = sd_ctrls_mi2020b, | 192 | .ctrls = sd_ctrls_mi2020b, |
193 | .nctrls = GL860_NCTRLS, | 193 | .nctrls = GL860_NCTRLS, |
@@ -200,7 +200,7 @@ static struct sd_desc sd_desc_mi2020b = { | |||
200 | .dq_callback = sd_callback, | 200 | .dq_callback = sd_callback, |
201 | }; | 201 | }; |
202 | 202 | ||
203 | static struct sd_desc sd_desc_ov2640 = { | 203 | static const struct sd_desc sd_desc_ov2640 = { |
204 | .name = MODULE_NAME, | 204 | .name = MODULE_NAME, |
205 | .ctrls = sd_ctrls_ov2640, | 205 | .ctrls = sd_ctrls_ov2640, |
206 | .nctrls = GL860_NCTRLS, | 206 | .nctrls = GL860_NCTRLS, |
@@ -213,7 +213,7 @@ static struct sd_desc sd_desc_ov2640 = { | |||
213 | .dq_callback = sd_callback, | 213 | .dq_callback = sd_callback, |
214 | }; | 214 | }; |
215 | 215 | ||
216 | static struct sd_desc sd_desc_ov9655 = { | 216 | static const struct sd_desc sd_desc_ov9655 = { |
217 | .name = MODULE_NAME, | 217 | .name = MODULE_NAME, |
218 | .ctrls = sd_ctrls_ov9655, | 218 | .ctrls = sd_ctrls_ov9655, |
219 | .nctrls = GL860_NCTRLS, | 219 | .nctrls = GL860_NCTRLS, |
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index bd6214d4ab3b..222af479150b 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c | |||
@@ -3,6 +3,9 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 2008-2009 Jean-Francois Moine (http://moinejf.free.fr) | 4 | * Copyright (C) 2008-2009 Jean-Francois Moine (http://moinejf.free.fr) |
5 | * | 5 | * |
6 | * Camera button input handling by Márton Németh | ||
7 | * Copyright (C) 2009-2010 Márton Németh <nm127@freemail.hu> | ||
8 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | 9 | * This program is free software; you can redistribute it and/or modify it |
7 | * under the terms of the GNU General Public License as published by the | 10 | * under the terms of the GNU General Public License as published by the |
8 | * Free Software Foundation; either version 2 of the License, or (at your | 11 | * Free Software Foundation; either version 2 of the License, or (at your |
@@ -37,6 +40,11 @@ | |||
37 | 40 | ||
38 | #include "gspca.h" | 41 | #include "gspca.h" |
39 | 42 | ||
43 | #ifdef CONFIG_INPUT | ||
44 | #include <linux/input.h> | ||
45 | #include <linux/usb/input.h> | ||
46 | #endif | ||
47 | |||
40 | /* global values */ | 48 | /* global values */ |
41 | #define DEF_NURBS 3 /* default number of URBs */ | 49 | #define DEF_NURBS 3 /* default number of URBs */ |
42 | #if DEF_NURBS > MAX_NURBS | 50 | #if DEF_NURBS > MAX_NURBS |
@@ -47,7 +55,7 @@ MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); | |||
47 | MODULE_DESCRIPTION("GSPCA USB Camera Driver"); | 55 | MODULE_DESCRIPTION("GSPCA USB Camera Driver"); |
48 | MODULE_LICENSE("GPL"); | 56 | MODULE_LICENSE("GPL"); |
49 | 57 | ||
50 | #define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 8, 0) | 58 | #define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 9, 0) |
51 | 59 | ||
52 | #ifdef GSPCA_DEBUG | 60 | #ifdef GSPCA_DEBUG |
53 | int gspca_debug = D_ERR | D_PROBE; | 61 | int gspca_debug = D_ERR | D_PROBE; |
@@ -104,15 +112,185 @@ static const struct vm_operations_struct gspca_vm_ops = { | |||
104 | .close = gspca_vm_close, | 112 | .close = gspca_vm_close, |
105 | }; | 113 | }; |
106 | 114 | ||
115 | /* | ||
116 | * Input and interrupt endpoint handling functions | ||
117 | */ | ||
118 | #ifdef CONFIG_INPUT | ||
119 | static void int_irq(struct urb *urb) | ||
120 | { | ||
121 | struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context; | ||
122 | int ret; | ||
123 | |||
124 | ret = urb->status; | ||
125 | switch (ret) { | ||
126 | case 0: | ||
127 | if (gspca_dev->sd_desc->int_pkt_scan(gspca_dev, | ||
128 | urb->transfer_buffer, urb->actual_length) < 0) { | ||
129 | PDEBUG(D_ERR, "Unknown packet received"); | ||
130 | } | ||
131 | break; | ||
132 | |||
133 | case -ENOENT: | ||
134 | case -ECONNRESET: | ||
135 | case -ENODEV: | ||
136 | case -ESHUTDOWN: | ||
137 | /* Stop is requested either by software or hardware is gone, | ||
138 | * keep the ret value non-zero and don't resubmit later. | ||
139 | */ | ||
140 | break; | ||
141 | |||
142 | default: | ||
143 | PDEBUG(D_ERR, "URB error %i, resubmitting", urb->status); | ||
144 | urb->status = 0; | ||
145 | ret = 0; | ||
146 | } | ||
147 | |||
148 | if (ret == 0) { | ||
149 | ret = usb_submit_urb(urb, GFP_ATOMIC); | ||
150 | if (ret < 0) | ||
151 | PDEBUG(D_ERR, "Resubmit URB failed with error %i", ret); | ||
152 | } | ||
153 | } | ||
154 | |||
155 | static int gspca_input_connect(struct gspca_dev *dev) | ||
156 | { | ||
157 | struct input_dev *input_dev; | ||
158 | int err = 0; | ||
159 | |||
160 | dev->input_dev = NULL; | ||
161 | if (dev->sd_desc->int_pkt_scan || dev->sd_desc->other_input) { | ||
162 | input_dev = input_allocate_device(); | ||
163 | if (!input_dev) | ||
164 | return -ENOMEM; | ||
165 | |||
166 | usb_make_path(dev->dev, dev->phys, sizeof(dev->phys)); | ||
167 | strlcat(dev->phys, "/input0", sizeof(dev->phys)); | ||
168 | |||
169 | input_dev->name = dev->sd_desc->name; | ||
170 | input_dev->phys = dev->phys; | ||
171 | |||
172 | usb_to_input_id(dev->dev, &input_dev->id); | ||
173 | |||
174 | input_dev->evbit[0] = BIT_MASK(EV_KEY); | ||
175 | input_dev->keybit[BIT_WORD(KEY_CAMERA)] = BIT_MASK(KEY_CAMERA); | ||
176 | input_dev->dev.parent = &dev->dev->dev; | ||
177 | |||
178 | err = input_register_device(input_dev); | ||
179 | if (err) { | ||
180 | PDEBUG(D_ERR, "Input device registration failed " | ||
181 | "with error %i", err); | ||
182 | input_dev->dev.parent = NULL; | ||
183 | input_free_device(input_dev); | ||
184 | } else { | ||
185 | dev->input_dev = input_dev; | ||
186 | } | ||
187 | } | ||
188 | |||
189 | return err; | ||
190 | } | ||
191 | |||
192 | static int alloc_and_submit_int_urb(struct gspca_dev *gspca_dev, | ||
193 | struct usb_endpoint_descriptor *ep) | ||
194 | { | ||
195 | unsigned int buffer_len; | ||
196 | int interval; | ||
197 | struct urb *urb; | ||
198 | struct usb_device *dev; | ||
199 | void *buffer = NULL; | ||
200 | int ret = -EINVAL; | ||
201 | |||
202 | buffer_len = ep->wMaxPacketSize; | ||
203 | interval = ep->bInterval; | ||
204 | PDEBUG(D_PROBE, "found int in endpoint: 0x%x, " | ||
205 | "buffer_len=%u, interval=%u", | ||
206 | ep->bEndpointAddress, buffer_len, interval); | ||
207 | |||
208 | dev = gspca_dev->dev; | ||
209 | |||
210 | urb = usb_alloc_urb(0, GFP_KERNEL); | ||
211 | if (!urb) { | ||
212 | ret = -ENOMEM; | ||
213 | goto error; | ||
214 | } | ||
215 | |||
216 | buffer = usb_buffer_alloc(dev, ep->wMaxPacketSize, | ||
217 | GFP_KERNEL, &urb->transfer_dma); | ||
218 | if (!buffer) { | ||
219 | ret = -ENOMEM; | ||
220 | goto error_buffer; | ||
221 | } | ||
222 | usb_fill_int_urb(urb, dev, | ||
223 | usb_rcvintpipe(dev, ep->bEndpointAddress), | ||
224 | buffer, buffer_len, | ||
225 | int_irq, (void *)gspca_dev, interval); | ||
226 | gspca_dev->int_urb = urb; | ||
227 | ret = usb_submit_urb(urb, GFP_KERNEL); | ||
228 | if (ret < 0) { | ||
229 | PDEBUG(D_ERR, "submit URB failed with error %i", ret); | ||
230 | goto error_submit; | ||
231 | } | ||
232 | return ret; | ||
233 | |||
234 | error_submit: | ||
235 | usb_buffer_free(dev, | ||
236 | urb->transfer_buffer_length, | ||
237 | urb->transfer_buffer, | ||
238 | urb->transfer_dma); | ||
239 | error_buffer: | ||
240 | usb_free_urb(urb); | ||
241 | error: | ||
242 | return ret; | ||
243 | } | ||
244 | |||
245 | static void gspca_input_create_urb(struct gspca_dev *gspca_dev) | ||
246 | { | ||
247 | struct usb_interface *intf; | ||
248 | struct usb_host_interface *intf_desc; | ||
249 | struct usb_endpoint_descriptor *ep; | ||
250 | int i; | ||
251 | |||
252 | if (gspca_dev->sd_desc->int_pkt_scan) { | ||
253 | intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface); | ||
254 | intf_desc = intf->cur_altsetting; | ||
255 | for (i = 0; i < intf_desc->desc.bNumEndpoints; i++) { | ||
256 | ep = &intf_desc->endpoint[i].desc; | ||
257 | if (usb_endpoint_dir_in(ep) && | ||
258 | usb_endpoint_xfer_int(ep)) { | ||
259 | |||
260 | alloc_and_submit_int_urb(gspca_dev, ep); | ||
261 | break; | ||
262 | } | ||
263 | } | ||
264 | } | ||
265 | } | ||
266 | |||
267 | static void gspca_input_destroy_urb(struct gspca_dev *gspca_dev) | ||
268 | { | ||
269 | struct urb *urb; | ||
270 | |||
271 | urb = gspca_dev->int_urb; | ||
272 | if (urb) { | ||
273 | gspca_dev->int_urb = NULL; | ||
274 | usb_kill_urb(urb); | ||
275 | usb_buffer_free(gspca_dev->dev, | ||
276 | urb->transfer_buffer_length, | ||
277 | urb->transfer_buffer, | ||
278 | urb->transfer_dma); | ||
279 | usb_free_urb(urb); | ||
280 | } | ||
281 | } | ||
282 | #else | ||
283 | #define gspca_input_connect(gspca_dev) 0 | ||
284 | #define gspca_input_create_urb(gspca_dev) | ||
285 | #define gspca_input_destroy_urb(gspca_dev) | ||
286 | #endif | ||
287 | |||
107 | /* get the current input frame buffer */ | 288 | /* get the current input frame buffer */ |
108 | struct gspca_frame *gspca_get_i_frame(struct gspca_dev *gspca_dev) | 289 | struct gspca_frame *gspca_get_i_frame(struct gspca_dev *gspca_dev) |
109 | { | 290 | { |
110 | struct gspca_frame *frame; | 291 | struct gspca_frame *frame; |
111 | int i; | ||
112 | 292 | ||
113 | i = gspca_dev->fr_i; | 293 | frame = gspca_dev->cur_frame; |
114 | i = gspca_dev->fr_queue[i]; | ||
115 | frame = &gspca_dev->frame[i]; | ||
116 | if ((frame->v4l2_buf.flags & BUF_ALL_FLAGS) | 294 | if ((frame->v4l2_buf.flags & BUF_ALL_FLAGS) |
117 | != V4L2_BUF_FLAG_QUEUED) | 295 | != V4L2_BUF_FLAG_QUEUED) |
118 | return NULL; | 296 | return NULL; |
@@ -486,11 +664,13 @@ static struct usb_host_endpoint *get_ep(struct gspca_dev *gspca_dev) | |||
486 | i, ep->desc.bEndpointAddress); | 664 | i, ep->desc.bEndpointAddress); |
487 | gspca_dev->alt = i; /* memorize the current alt setting */ | 665 | gspca_dev->alt = i; /* memorize the current alt setting */ |
488 | if (gspca_dev->nbalt > 1) { | 666 | if (gspca_dev->nbalt > 1) { |
667 | gspca_input_destroy_urb(gspca_dev); | ||
489 | ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i); | 668 | ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i); |
490 | if (ret < 0) { | 669 | if (ret < 0) { |
491 | err("set alt %d err %d", i, ret); | 670 | err("set alt %d err %d", i, ret); |
492 | return NULL; | 671 | ep = NULL; |
493 | } | 672 | } |
673 | gspca_input_create_urb(gspca_dev); | ||
494 | } | 674 | } |
495 | return ep; | 675 | return ep; |
496 | } | 676 | } |
@@ -534,26 +714,22 @@ static int create_urbs(struct gspca_dev *gspca_dev, | |||
534 | nurbs = 1; | 714 | nurbs = 1; |
535 | } | 715 | } |
536 | 716 | ||
537 | gspca_dev->nurbs = nurbs; | ||
538 | for (n = 0; n < nurbs; n++) { | 717 | for (n = 0; n < nurbs; n++) { |
539 | urb = usb_alloc_urb(npkt, GFP_KERNEL); | 718 | urb = usb_alloc_urb(npkt, GFP_KERNEL); |
540 | if (!urb) { | 719 | if (!urb) { |
541 | err("usb_alloc_urb failed"); | 720 | err("usb_alloc_urb failed"); |
542 | destroy_urbs(gspca_dev); | ||
543 | return -ENOMEM; | 721 | return -ENOMEM; |
544 | } | 722 | } |
723 | gspca_dev->urb[n] = urb; | ||
545 | urb->transfer_buffer = usb_buffer_alloc(gspca_dev->dev, | 724 | urb->transfer_buffer = usb_buffer_alloc(gspca_dev->dev, |
546 | bsize, | 725 | bsize, |
547 | GFP_KERNEL, | 726 | GFP_KERNEL, |
548 | &urb->transfer_dma); | 727 | &urb->transfer_dma); |
549 | 728 | ||
550 | if (urb->transfer_buffer == NULL) { | 729 | if (urb->transfer_buffer == NULL) { |
551 | usb_free_urb(urb); | 730 | err("usb_buffer_alloc failed"); |
552 | err("usb_buffer_urb failed"); | ||
553 | destroy_urbs(gspca_dev); | ||
554 | return -ENOMEM; | 731 | return -ENOMEM; |
555 | } | 732 | } |
556 | gspca_dev->urb[n] = urb; | ||
557 | urb->dev = gspca_dev->dev; | 733 | urb->dev = gspca_dev->dev; |
558 | urb->context = gspca_dev; | 734 | urb->context = gspca_dev; |
559 | urb->transfer_buffer_length = bsize; | 735 | urb->transfer_buffer_length = bsize; |
@@ -585,6 +761,7 @@ static int create_urbs(struct gspca_dev *gspca_dev, | |||
585 | static int gspca_init_transfer(struct gspca_dev *gspca_dev) | 761 | static int gspca_init_transfer(struct gspca_dev *gspca_dev) |
586 | { | 762 | { |
587 | struct usb_host_endpoint *ep; | 763 | struct usb_host_endpoint *ep; |
764 | struct urb *urb; | ||
588 | int n, ret; | 765 | int n, ret; |
589 | 766 | ||
590 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) | 767 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) |
@@ -595,6 +772,8 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) | |||
595 | goto out; | 772 | goto out; |
596 | } | 773 | } |
597 | 774 | ||
775 | gspca_dev->usb_err = 0; | ||
776 | |||
598 | /* set the higher alternate setting and | 777 | /* set the higher alternate setting and |
599 | * loop until urb submit succeeds */ | 778 | * loop until urb submit succeeds */ |
600 | if (gspca_dev->cam.reverse_alts) | 779 | if (gspca_dev->cam.reverse_alts) |
@@ -613,10 +792,15 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) | |||
613 | goto out; | 792 | goto out; |
614 | } | 793 | } |
615 | for (;;) { | 794 | for (;;) { |
616 | PDEBUG(D_STREAM, "init transfer alt %d", gspca_dev->alt); | 795 | if (!gspca_dev->cam.no_urb_create) { |
617 | ret = create_urbs(gspca_dev, ep); | 796 | PDEBUG(D_STREAM, "init transfer alt %d", |
618 | if (ret < 0) | 797 | gspca_dev->alt); |
619 | goto out; | 798 | ret = create_urbs(gspca_dev, ep); |
799 | if (ret < 0) { | ||
800 | destroy_urbs(gspca_dev); | ||
801 | goto out; | ||
802 | } | ||
803 | } | ||
620 | 804 | ||
621 | /* clear the bulk endpoint */ | 805 | /* clear the bulk endpoint */ |
622 | if (gspca_dev->cam.bulk) | 806 | if (gspca_dev->cam.bulk) |
@@ -636,8 +820,11 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) | |||
636 | break; | 820 | break; |
637 | 821 | ||
638 | /* submit the URBs */ | 822 | /* submit the URBs */ |
639 | for (n = 0; n < gspca_dev->nurbs; n++) { | 823 | for (n = 0; n < MAX_NURBS; n++) { |
640 | ret = usb_submit_urb(gspca_dev->urb[n], GFP_KERNEL); | 824 | urb = gspca_dev->urb[n]; |
825 | if (urb == NULL) | ||
826 | break; | ||
827 | ret = usb_submit_urb(urb, GFP_KERNEL); | ||
641 | if (ret < 0) | 828 | if (ret < 0) |
642 | break; | 829 | break; |
643 | } | 830 | } |
@@ -694,7 +881,9 @@ static void gspca_stream_off(struct gspca_dev *gspca_dev) | |||
694 | if (gspca_dev->sd_desc->stopN) | 881 | if (gspca_dev->sd_desc->stopN) |
695 | gspca_dev->sd_desc->stopN(gspca_dev); | 882 | gspca_dev->sd_desc->stopN(gspca_dev); |
696 | destroy_urbs(gspca_dev); | 883 | destroy_urbs(gspca_dev); |
884 | gspca_input_destroy_urb(gspca_dev); | ||
697 | gspca_set_alt0(gspca_dev); | 885 | gspca_set_alt0(gspca_dev); |
886 | gspca_input_create_urb(gspca_dev); | ||
698 | } | 887 | } |
699 | 888 | ||
700 | /* always call stop0 to free the subdriver's resources */ | 889 | /* always call stop0 to free the subdriver's resources */ |
@@ -2060,11 +2249,12 @@ int gspca_dev_probe(struct usb_interface *intf, | |||
2060 | PDEBUG(D_ERR, "Too many config"); | 2249 | PDEBUG(D_ERR, "Too many config"); |
2061 | return -ENODEV; | 2250 | return -ENODEV; |
2062 | } | 2251 | } |
2252 | |||
2253 | /* the USB video interface must be the first one */ | ||
2063 | interface = &intf->cur_altsetting->desc; | 2254 | interface = &intf->cur_altsetting->desc; |
2064 | if (interface->bInterfaceNumber > 0) { | 2255 | if (dev->config->desc.bNumInterfaces != 1 && |
2065 | PDEBUG(D_ERR, "intf != 0"); | 2256 | interface->bInterfaceNumber != 0) |
2066 | return -ENODEV; | 2257 | return -ENODEV; |
2067 | } | ||
2068 | 2258 | ||
2069 | /* create the device */ | 2259 | /* create the device */ |
2070 | if (dev_size < sizeof *gspca_dev) | 2260 | if (dev_size < sizeof *gspca_dev) |
@@ -2096,6 +2286,10 @@ int gspca_dev_probe(struct usb_interface *intf, | |||
2096 | goto out; | 2286 | goto out; |
2097 | gspca_set_default_mode(gspca_dev); | 2287 | gspca_set_default_mode(gspca_dev); |
2098 | 2288 | ||
2289 | ret = gspca_input_connect(gspca_dev); | ||
2290 | if (ret) | ||
2291 | goto out; | ||
2292 | |||
2099 | mutex_init(&gspca_dev->usb_lock); | 2293 | mutex_init(&gspca_dev->usb_lock); |
2100 | mutex_init(&gspca_dev->read_lock); | 2294 | mutex_init(&gspca_dev->read_lock); |
2101 | mutex_init(&gspca_dev->queue_lock); | 2295 | mutex_init(&gspca_dev->queue_lock); |
@@ -2116,8 +2310,15 @@ int gspca_dev_probe(struct usb_interface *intf, | |||
2116 | 2310 | ||
2117 | usb_set_intfdata(intf, gspca_dev); | 2311 | usb_set_intfdata(intf, gspca_dev); |
2118 | PDEBUG(D_PROBE, "%s created", video_device_node_name(&gspca_dev->vdev)); | 2312 | PDEBUG(D_PROBE, "%s created", video_device_node_name(&gspca_dev->vdev)); |
2313 | |||
2314 | gspca_input_create_urb(gspca_dev); | ||
2315 | |||
2119 | return 0; | 2316 | return 0; |
2120 | out: | 2317 | out: |
2318 | #ifdef CONFIG_INPUT | ||
2319 | if (gspca_dev->input_dev) | ||
2320 | input_unregister_device(gspca_dev->input_dev); | ||
2321 | #endif | ||
2121 | kfree(gspca_dev->usb_buf); | 2322 | kfree(gspca_dev->usb_buf); |
2122 | kfree(gspca_dev); | 2323 | kfree(gspca_dev); |
2123 | return ret; | 2324 | return ret; |
@@ -2133,6 +2334,9 @@ EXPORT_SYMBOL(gspca_dev_probe); | |||
2133 | void gspca_disconnect(struct usb_interface *intf) | 2334 | void gspca_disconnect(struct usb_interface *intf) |
2134 | { | 2335 | { |
2135 | struct gspca_dev *gspca_dev = usb_get_intfdata(intf); | 2336 | struct gspca_dev *gspca_dev = usb_get_intfdata(intf); |
2337 | #ifdef CONFIG_INPUT | ||
2338 | struct input_dev *input_dev; | ||
2339 | #endif | ||
2136 | 2340 | ||
2137 | PDEBUG(D_PROBE, "%s disconnect", | 2341 | PDEBUG(D_PROBE, "%s disconnect", |
2138 | video_device_node_name(&gspca_dev->vdev)); | 2342 | video_device_node_name(&gspca_dev->vdev)); |
@@ -2144,6 +2348,15 @@ void gspca_disconnect(struct usb_interface *intf) | |||
2144 | wake_up_interruptible(&gspca_dev->wq); | 2348 | wake_up_interruptible(&gspca_dev->wq); |
2145 | } | 2349 | } |
2146 | 2350 | ||
2351 | #ifdef CONFIG_INPUT | ||
2352 | gspca_input_destroy_urb(gspca_dev); | ||
2353 | input_dev = gspca_dev->input_dev; | ||
2354 | if (input_dev) { | ||
2355 | gspca_dev->input_dev = NULL; | ||
2356 | input_unregister_device(input_dev); | ||
2357 | } | ||
2358 | #endif | ||
2359 | |||
2147 | /* the device is freed at exit of this function */ | 2360 | /* the device is freed at exit of this function */ |
2148 | gspca_dev->dev = NULL; | 2361 | gspca_dev->dev = NULL; |
2149 | mutex_unlock(&gspca_dev->usb_lock); | 2362 | mutex_unlock(&gspca_dev->usb_lock); |
@@ -2169,6 +2382,7 @@ int gspca_suspend(struct usb_interface *intf, pm_message_t message) | |||
2169 | if (gspca_dev->sd_desc->stopN) | 2382 | if (gspca_dev->sd_desc->stopN) |
2170 | gspca_dev->sd_desc->stopN(gspca_dev); | 2383 | gspca_dev->sd_desc->stopN(gspca_dev); |
2171 | destroy_urbs(gspca_dev); | 2384 | destroy_urbs(gspca_dev); |
2385 | gspca_input_destroy_urb(gspca_dev); | ||
2172 | gspca_set_alt0(gspca_dev); | 2386 | gspca_set_alt0(gspca_dev); |
2173 | if (gspca_dev->sd_desc->stop0) | 2387 | if (gspca_dev->sd_desc->stop0) |
2174 | gspca_dev->sd_desc->stop0(gspca_dev); | 2388 | gspca_dev->sd_desc->stop0(gspca_dev); |
@@ -2182,6 +2396,7 @@ int gspca_resume(struct usb_interface *intf) | |||
2182 | 2396 | ||
2183 | gspca_dev->frozen = 0; | 2397 | gspca_dev->frozen = 0; |
2184 | gspca_dev->sd_desc->init(gspca_dev); | 2398 | gspca_dev->sd_desc->init(gspca_dev); |
2399 | gspca_input_create_urb(gspca_dev); | ||
2185 | if (gspca_dev->streaming) | 2400 | if (gspca_dev->streaming) |
2186 | return gspca_init_transfer(gspca_dev); | 2401 | return gspca_init_transfer(gspca_dev); |
2187 | return 0; | 2402 | return 0; |
@@ -2205,6 +2420,8 @@ int gspca_auto_gain_n_exposure(struct gspca_dev *gspca_dev, int avg_lum, | |||
2205 | int retval = 0; | 2420 | int retval = 0; |
2206 | 2421 | ||
2207 | for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) { | 2422 | for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) { |
2423 | if (gspca_dev->ctrl_dis & (1 << i)) | ||
2424 | continue; | ||
2208 | if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_GAIN) | 2425 | if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_GAIN) |
2209 | gain_ctrl = &gspca_dev->sd_desc->ctrls[i]; | 2426 | gain_ctrl = &gspca_dev->sd_desc->ctrls[i]; |
2210 | if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_EXPOSURE) | 2427 | if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_EXPOSURE) |
diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index 59c7941da999..02c696a22be0 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h | |||
@@ -48,26 +48,27 @@ extern int gspca_debug; | |||
48 | 48 | ||
49 | /* used to list framerates supported by a camera mode (resolution) */ | 49 | /* used to list framerates supported by a camera mode (resolution) */ |
50 | struct framerates { | 50 | struct framerates { |
51 | int *rates; | 51 | const u8 *rates; |
52 | int nrates; | 52 | int nrates; |
53 | }; | 53 | }; |
54 | 54 | ||
55 | /* device information - set at probe time */ | 55 | /* device information - set at probe time */ |
56 | struct cam { | 56 | struct cam { |
57 | int bulk_size; /* buffer size when image transfer by bulk */ | ||
58 | const struct v4l2_pix_format *cam_mode; /* size nmodes */ | 57 | const struct v4l2_pix_format *cam_mode; /* size nmodes */ |
59 | char nmodes; | ||
60 | const struct framerates *mode_framerates; /* must have size nmode, | 58 | const struct framerates *mode_framerates; /* must have size nmode, |
61 | * just like cam_mode */ | 59 | * just like cam_mode */ |
62 | __u8 bulk_nurbs; /* number of URBs in bulk mode | 60 | u32 bulk_size; /* buffer size when image transfer by bulk */ |
61 | u32 input_flags; /* value for ENUM_INPUT status flags */ | ||
62 | u8 nmodes; /* size of cam_mode */ | ||
63 | u8 no_urb_create; /* don't create transfer URBs */ | ||
64 | u8 bulk_nurbs; /* number of URBs in bulk mode | ||
63 | * - cannot be > MAX_NURBS | 65 | * - cannot be > MAX_NURBS |
64 | * - when 0 and bulk_size != 0 means | 66 | * - when 0 and bulk_size != 0 means |
65 | * 1 URB and submit done by subdriver */ | 67 | * 1 URB and submit done by subdriver */ |
66 | u8 bulk; /* image transfer by 0:isoc / 1:bulk */ | 68 | u8 bulk; /* image transfer by 0:isoc / 1:bulk */ |
67 | u8 npkt; /* number of packets in an ISOC message | 69 | u8 npkt; /* number of packets in an ISOC message |
68 | * 0 is the default value: 32 packets */ | 70 | * 0 is the default value: 32 packets */ |
69 | u32 input_flags; /* value for ENUM_INPUT status flags */ | 71 | u8 reverse_alts; /* Alt settings are in high to low order */ |
70 | char reverse_alts; /* Alt settings are in high to low order */ | ||
71 | }; | 72 | }; |
72 | 73 | ||
73 | struct gspca_dev; | 74 | struct gspca_dev; |
@@ -90,6 +91,9 @@ typedef int (*cam_qmnu_op) (struct gspca_dev *, | |||
90 | typedef void (*cam_pkt_op) (struct gspca_dev *gspca_dev, | 91 | typedef void (*cam_pkt_op) (struct gspca_dev *gspca_dev, |
91 | u8 *data, | 92 | u8 *data, |
92 | int len); | 93 | int len); |
94 | typedef int (*cam_int_pkt_op) (struct gspca_dev *gspca_dev, | ||
95 | u8 *data, | ||
96 | int len); | ||
93 | 97 | ||
94 | struct ctrl { | 98 | struct ctrl { |
95 | struct v4l2_queryctrl qctrl; | 99 | struct v4l2_queryctrl qctrl; |
@@ -125,6 +129,12 @@ struct sd_desc { | |||
125 | cam_reg_op get_register; | 129 | cam_reg_op get_register; |
126 | #endif | 130 | #endif |
127 | cam_ident_op get_chip_ident; | 131 | cam_ident_op get_chip_ident; |
132 | #ifdef CONFIG_INPUT | ||
133 | cam_int_pkt_op int_pkt_scan; | ||
134 | /* other_input makes the gspca core create gspca_dev->input even when | ||
135 | int_pkt_scan is NULL, for cams with non interrupt driven buttons */ | ||
136 | u8 other_input; | ||
137 | #endif | ||
128 | }; | 138 | }; |
129 | 139 | ||
130 | /* packet types when moving from iso buf to frame buf */ | 140 | /* packet types when moving from iso buf to frame buf */ |
@@ -147,6 +157,10 @@ struct gspca_dev { | |||
147 | struct module *module; /* subdriver handling the device */ | 157 | struct module *module; /* subdriver handling the device */ |
148 | struct usb_device *dev; | 158 | struct usb_device *dev; |
149 | struct file *capt_file; /* file doing video capture */ | 159 | struct file *capt_file; /* file doing video capture */ |
160 | #ifdef CONFIG_INPUT | ||
161 | struct input_dev *input_dev; | ||
162 | char phys[64]; /* physical device path */ | ||
163 | #endif | ||
150 | 164 | ||
151 | struct cam cam; /* device information */ | 165 | struct cam cam; /* device information */ |
152 | const struct sd_desc *sd_desc; /* subdriver description */ | 166 | const struct sd_desc *sd_desc; /* subdriver description */ |
@@ -156,6 +170,9 @@ struct gspca_dev { | |||
156 | #define USB_BUF_SZ 64 | 170 | #define USB_BUF_SZ 64 |
157 | __u8 *usb_buf; /* buffer for USB exchanges */ | 171 | __u8 *usb_buf; /* buffer for USB exchanges */ |
158 | struct urb *urb[MAX_NURBS]; | 172 | struct urb *urb[MAX_NURBS]; |
173 | #ifdef CONFIG_INPUT | ||
174 | struct urb *int_urb; | ||
175 | #endif | ||
159 | 176 | ||
160 | __u8 *frbuf; /* buffer for nframes */ | 177 | __u8 *frbuf; /* buffer for nframes */ |
161 | struct gspca_frame frame[GSPCA_MAX_FRAMES]; | 178 | struct gspca_frame frame[GSPCA_MAX_FRAMES]; |
@@ -187,7 +204,6 @@ struct gspca_dev { | |||
187 | char users; /* number of opens */ | 204 | char users; /* number of opens */ |
188 | char present; /* device connected */ | 205 | char present; /* device connected */ |
189 | char nbufread; /* number of buffers for read() */ | 206 | char nbufread; /* number of buffers for read() */ |
190 | char nurbs; /* number of allocated URBs */ | ||
191 | char memory; /* memory type (V4L2_MEMORY_xxx) */ | 207 | char memory; /* memory type (V4L2_MEMORY_xxx) */ |
192 | __u8 iface; /* USB interface number */ | 208 | __u8 iface; /* USB interface number */ |
193 | __u8 alt; /* USB alternate setting */ | 209 | __u8 alt; /* USB alternate setting */ |
diff --git a/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/drivers/media/video/gspca/m5602/m5602_mt9m111.c index 8d071dff6944..c0722fa64606 100644 --- a/drivers/media/video/gspca/m5602/m5602_mt9m111.c +++ b/drivers/media/video/gspca/m5602/m5602_mt9m111.c | |||
@@ -48,7 +48,7 @@ static struct v4l2_pix_format mt9m111_modes[] = { | |||
48 | } | 48 | } |
49 | }; | 49 | }; |
50 | 50 | ||
51 | const static struct ctrl mt9m111_ctrls[] = { | 51 | static const struct ctrl mt9m111_ctrls[] = { |
52 | #define VFLIP_IDX 0 | 52 | #define VFLIP_IDX 0 |
53 | { | 53 | { |
54 | { | 54 | { |
@@ -171,7 +171,7 @@ int mt9m111_probe(struct sd *sd) | |||
171 | return -ENODEV; | 171 | return -ENODEV; |
172 | } | 172 | } |
173 | 173 | ||
174 | info("Probing for a mt9m111 sensor"); | 174 | PDEBUG(D_PROBE, "Probing for a mt9m111 sensor"); |
175 | 175 | ||
176 | /* Do the preinit */ | 176 | /* Do the preinit */ |
177 | for (i = 0; i < ARRAY_SIZE(preinit_mt9m111); i++) { | 177 | for (i = 0; i < ARRAY_SIZE(preinit_mt9m111); i++) { |
diff --git a/drivers/media/video/gspca/m5602/m5602_ov7660.c b/drivers/media/video/gspca/m5602/m5602_ov7660.c index 2a28b74cb3f9..62c1cbf06666 100644 --- a/drivers/media/video/gspca/m5602/m5602_ov7660.c +++ b/drivers/media/video/gspca/m5602/m5602_ov7660.c | |||
@@ -33,7 +33,7 @@ static int ov7660_set_hflip(struct gspca_dev *gspca_dev, __s32 val); | |||
33 | static int ov7660_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); | 33 | static int ov7660_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); |
34 | static int ov7660_set_vflip(struct gspca_dev *gspca_dev, __s32 val); | 34 | static int ov7660_set_vflip(struct gspca_dev *gspca_dev, __s32 val); |
35 | 35 | ||
36 | const static struct ctrl ov7660_ctrls[] = { | 36 | static const struct ctrl ov7660_ctrls[] = { |
37 | #define GAIN_IDX 1 | 37 | #define GAIN_IDX 1 |
38 | { | 38 | { |
39 | { | 39 | { |
diff --git a/drivers/media/video/gspca/m5602/m5602_ov7660.h b/drivers/media/video/gspca/m5602/m5602_ov7660.h index f5588ebe667c..4d9dcf29da2e 100644 --- a/drivers/media/video/gspca/m5602/m5602_ov7660.h +++ b/drivers/media/video/gspca/m5602/m5602_ov7660.h | |||
@@ -94,7 +94,7 @@ int ov7660_start(struct sd *sd); | |||
94 | int ov7660_stop(struct sd *sd); | 94 | int ov7660_stop(struct sd *sd); |
95 | void ov7660_disconnect(struct sd *sd); | 95 | void ov7660_disconnect(struct sd *sd); |
96 | 96 | ||
97 | const static struct m5602_sensor ov7660 = { | 97 | static const struct m5602_sensor ov7660 = { |
98 | .name = "ov7660", | 98 | .name = "ov7660", |
99 | .i2c_slave_id = 0x42, | 99 | .i2c_slave_id = 0x42, |
100 | .i2c_regW = 1, | 100 | .i2c_regW = 1, |
diff --git a/drivers/media/video/gspca/m5602/m5602_ov9650.c b/drivers/media/video/gspca/m5602/m5602_ov9650.c index 923cdd5f7a6b..069ba0044f8b 100644 --- a/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/drivers/media/video/gspca/m5602/m5602_ov9650.c | |||
@@ -307,7 +307,7 @@ int ov9650_probe(struct sd *sd) | |||
307 | return -ENODEV; | 307 | return -ENODEV; |
308 | } | 308 | } |
309 | 309 | ||
310 | info("Probing for an ov9650 sensor"); | 310 | PDEBUG(D_PROBE, "Probing for an ov9650 sensor"); |
311 | 311 | ||
312 | /* Run the pre-init before probing the sensor */ | 312 | /* Run the pre-init before probing the sensor */ |
313 | for (i = 0; i < ARRAY_SIZE(preinit_ov9650) && !err; i++) { | 313 | for (i = 0; i < ARRAY_SIZE(preinit_ov9650) && !err; i++) { |
diff --git a/drivers/media/video/gspca/m5602/m5602_po1030.c b/drivers/media/video/gspca/m5602/m5602_po1030.c index 8d74d8065b79..925b87d66f40 100644 --- a/drivers/media/video/gspca/m5602/m5602_po1030.c +++ b/drivers/media/video/gspca/m5602/m5602_po1030.c | |||
@@ -205,7 +205,7 @@ int po1030_probe(struct sd *sd) | |||
205 | return -ENODEV; | 205 | return -ENODEV; |
206 | } | 206 | } |
207 | 207 | ||
208 | info("Probing for a po1030 sensor"); | 208 | PDEBUG(D_PROBE, "Probing for a po1030 sensor"); |
209 | 209 | ||
210 | /* Run the pre-init to actually probe the unit */ | 210 | /* Run the pre-init to actually probe the unit */ |
211 | for (i = 0; i < ARRAY_SIZE(preinit_po1030); i++) { | 211 | for (i = 0; i < ARRAY_SIZE(preinit_po1030); i++) { |
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index 1b536f7d30cf..da0a38c78708 100644 --- a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c | |||
@@ -248,7 +248,7 @@ int s5k4aa_probe(struct sd *sd) | |||
248 | return -ENODEV; | 248 | return -ENODEV; |
249 | } | 249 | } |
250 | 250 | ||
251 | info("Probing for a s5k4aa sensor"); | 251 | PDEBUG(D_PROBE, "Probing for a s5k4aa sensor"); |
252 | 252 | ||
253 | /* Preinit the sensor */ | 253 | /* Preinit the sensor */ |
254 | for (i = 0; i < ARRAY_SIZE(preinit_s5k4aa) && !err; i++) { | 254 | for (i = 0; i < ARRAY_SIZE(preinit_s5k4aa) && !err; i++) { |
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/drivers/media/video/gspca/m5602/m5602_s5k83a.c index 6b89f33a4ce0..fbd91545497a 100644 --- a/drivers/media/video/gspca/m5602/m5602_s5k83a.c +++ b/drivers/media/video/gspca/m5602/m5602_s5k83a.c | |||
@@ -143,7 +143,7 @@ int s5k83a_probe(struct sd *sd) | |||
143 | return -ENODEV; | 143 | return -ENODEV; |
144 | } | 144 | } |
145 | 145 | ||
146 | info("Probing for a s5k83a sensor"); | 146 | PDEBUG(D_PROBE, "Probing for a s5k83a sensor"); |
147 | 147 | ||
148 | /* Preinit the sensor */ | 148 | /* Preinit the sensor */ |
149 | for (i = 0; i < ARRAY_SIZE(preinit_s5k83a) && !err; i++) { | 149 | for (i = 0; i < ARRAY_SIZE(preinit_s5k83a) && !err; i++) { |
diff --git a/drivers/media/video/gspca/mars.c b/drivers/media/video/gspca/mars.c index 9cf8d68c71bf..3d9229e22b25 100644 --- a/drivers/media/video/gspca/mars.c +++ b/drivers/media/video/gspca/mars.c | |||
@@ -54,7 +54,7 @@ static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val); | |||
54 | static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val); | 54 | static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val); |
55 | static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); | 55 | static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); |
56 | 56 | ||
57 | static struct ctrl sd_ctrls[] = { | 57 | static const struct ctrl sd_ctrls[] = { |
58 | { | 58 | { |
59 | { | 59 | { |
60 | .id = V4L2_CID_BRIGHTNESS, | 60 | .id = V4L2_CID_BRIGHTNESS, |
diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c index 9154870e07d2..33744e724eaa 100644 --- a/drivers/media/video/gspca/mr97310a.c +++ b/drivers/media/video/gspca/mr97310a.c | |||
@@ -57,6 +57,14 @@ | |||
57 | #define MR97310A_GAIN_MAX 31 | 57 | #define MR97310A_GAIN_MAX 31 |
58 | #define MR97310A_GAIN_DEFAULT 25 | 58 | #define MR97310A_GAIN_DEFAULT 25 |
59 | 59 | ||
60 | #define MR97310A_CONTRAST_MIN 0 | ||
61 | #define MR97310A_CONTRAST_MAX 31 | ||
62 | #define MR97310A_CONTRAST_DEFAULT 23 | ||
63 | |||
64 | #define MR97310A_CS_GAIN_MIN 0 | ||
65 | #define MR97310A_CS_GAIN_MAX 0x7ff | ||
66 | #define MR97310A_CS_GAIN_DEFAULT 0x110 | ||
67 | |||
60 | #define MR97310A_MIN_CLOCKDIV_MIN 3 | 68 | #define MR97310A_MIN_CLOCKDIV_MIN 3 |
61 | #define MR97310A_MIN_CLOCKDIV_MAX 8 | 69 | #define MR97310A_MIN_CLOCKDIV_MAX 8 |
62 | #define MR97310A_MIN_CLOCKDIV_DEFAULT 3 | 70 | #define MR97310A_MIN_CLOCKDIV_DEFAULT 3 |
@@ -82,7 +90,8 @@ struct sd { | |||
82 | 90 | ||
83 | int brightness; | 91 | int brightness; |
84 | u16 exposure; | 92 | u16 exposure; |
85 | u8 gain; | 93 | u32 gain; |
94 | u8 contrast; | ||
86 | u8 min_clockdiv; | 95 | u8 min_clockdiv; |
87 | }; | 96 | }; |
88 | 97 | ||
@@ -98,6 +107,8 @@ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | |||
98 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | 107 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); |
99 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); | 108 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); |
100 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); | 109 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); |
110 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | ||
111 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | ||
101 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); | 112 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); |
102 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); | 113 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); |
103 | static int sd_setmin_clockdiv(struct gspca_dev *gspca_dev, __s32 val); | 114 | static int sd_setmin_clockdiv(struct gspca_dev *gspca_dev, __s32 val); |
@@ -105,11 +116,13 @@ static int sd_getmin_clockdiv(struct gspca_dev *gspca_dev, __s32 *val); | |||
105 | static void setbrightness(struct gspca_dev *gspca_dev); | 116 | static void setbrightness(struct gspca_dev *gspca_dev); |
106 | static void setexposure(struct gspca_dev *gspca_dev); | 117 | static void setexposure(struct gspca_dev *gspca_dev); |
107 | static void setgain(struct gspca_dev *gspca_dev); | 118 | static void setgain(struct gspca_dev *gspca_dev); |
119 | static void setcontrast(struct gspca_dev *gspca_dev); | ||
108 | 120 | ||
109 | /* V4L2 controls supported by the driver */ | 121 | /* V4L2 controls supported by the driver */ |
110 | static struct ctrl sd_ctrls[] = { | 122 | static const struct ctrl sd_ctrls[] = { |
111 | /* Separate brightness control description for Argus QuickClix as it has | 123 | /* Separate brightness control description for Argus QuickClix as it has |
112 | different limits from the other mr97310a cameras */ | 124 | * different limits from the other mr97310a cameras, and separate gain |
125 | * control for Sakar CyberPix camera. */ | ||
113 | { | 126 | { |
114 | #define NORM_BRIGHTNESS_IDX 0 | 127 | #define NORM_BRIGHTNESS_IDX 0 |
115 | { | 128 | { |
@@ -171,7 +184,37 @@ static struct ctrl sd_ctrls[] = { | |||
171 | .get = sd_getgain, | 184 | .get = sd_getgain, |
172 | }, | 185 | }, |
173 | { | 186 | { |
174 | #define MIN_CLOCKDIV_IDX 4 | 187 | #define SAKAR_CS_GAIN_IDX 4 |
188 | { | ||
189 | .id = V4L2_CID_GAIN, | ||
190 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
191 | .name = "Gain", | ||
192 | .minimum = MR97310A_CS_GAIN_MIN, | ||
193 | .maximum = MR97310A_CS_GAIN_MAX, | ||
194 | .step = 1, | ||
195 | .default_value = MR97310A_CS_GAIN_DEFAULT, | ||
196 | .flags = 0, | ||
197 | }, | ||
198 | .set = sd_setgain, | ||
199 | .get = sd_getgain, | ||
200 | }, | ||
201 | { | ||
202 | #define CONTRAST_IDX 5 | ||
203 | { | ||
204 | .id = V4L2_CID_CONTRAST, | ||
205 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
206 | .name = "Contrast", | ||
207 | .minimum = MR97310A_CONTRAST_MIN, | ||
208 | .maximum = MR97310A_CONTRAST_MAX, | ||
209 | .step = 1, | ||
210 | .default_value = MR97310A_CONTRAST_DEFAULT, | ||
211 | .flags = 0, | ||
212 | }, | ||
213 | .set = sd_setcontrast, | ||
214 | .get = sd_getcontrast, | ||
215 | }, | ||
216 | { | ||
217 | #define MIN_CLOCKDIV_IDX 6 | ||
175 | { | 218 | { |
176 | .id = V4L2_CID_PRIVATE_BASE, | 219 | .id = V4L2_CID_PRIVATE_BASE, |
177 | .type = V4L2_CTRL_TYPE_INTEGER, | 220 | .type = V4L2_CTRL_TYPE_INTEGER, |
@@ -327,7 +370,6 @@ static int zero_the_pointer(struct gspca_dev *gspca_dev) | |||
327 | if (err_code < 0) | 370 | if (err_code < 0) |
328 | return err_code; | 371 | return err_code; |
329 | 372 | ||
330 | err_code = mr_write(gspca_dev, 1); | ||
331 | data[0] = 0x19; | 373 | data[0] = 0x19; |
332 | data[1] = 0x51; | 374 | data[1] = 0x51; |
333 | err_code = mr_write(gspca_dev, 2); | 375 | err_code = mr_write(gspca_dev, 2); |
@@ -437,6 +479,7 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
437 | { | 479 | { |
438 | struct sd *sd = (struct sd *) gspca_dev; | 480 | struct sd *sd = (struct sd *) gspca_dev; |
439 | struct cam *cam; | 481 | struct cam *cam; |
482 | int gain_default = MR97310A_GAIN_DEFAULT; | ||
440 | int err_code; | 483 | int err_code; |
441 | 484 | ||
442 | cam = &gspca_dev->cam; | 485 | cam = &gspca_dev->cam; |
@@ -460,12 +503,14 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
460 | if (err_code < 0) | 503 | if (err_code < 0) |
461 | return err_code; | 504 | return err_code; |
462 | 505 | ||
506 | /* Now, the query for sensor type. */ | ||
507 | err_code = cam_get_response16(gspca_dev, 0x07, 1); | ||
508 | if (err_code < 0) | ||
509 | return err_code; | ||
510 | |||
463 | if (id->idProduct == 0x0110 || id->idProduct == 0x010e) { | 511 | if (id->idProduct == 0x0110 || id->idProduct == 0x010e) { |
464 | sd->cam_type = CAM_TYPE_CIF; | 512 | sd->cam_type = CAM_TYPE_CIF; |
465 | cam->nmodes--; | 513 | cam->nmodes--; |
466 | err_code = cam_get_response16(gspca_dev, 0x06, 1); | ||
467 | if (err_code < 0) | ||
468 | return err_code; | ||
469 | /* | 514 | /* |
470 | * All but one of the known CIF cameras share the same USB ID, | 515 | * All but one of the known CIF cameras share the same USB ID, |
471 | * but two different init routines are in use, and the control | 516 | * but two different init routines are in use, and the control |
@@ -473,12 +518,12 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
473 | * of the two known varieties is connected! | 518 | * of the two known varieties is connected! |
474 | * | 519 | * |
475 | * A list of known CIF cameras follows. They all report either | 520 | * A list of known CIF cameras follows. They all report either |
476 | * 0002 for type 0 or 0003 for type 1. | 521 | * 0200 for type 0 or 0300 for type 1. |
477 | * If you have another to report, please do | 522 | * If you have another to report, please do |
478 | * | 523 | * |
479 | * Name sd->sensor_type reported by | 524 | * Name sd->sensor_type reported by |
480 | * | 525 | * |
481 | * Sakar Spy-shot 0 T. Kilgore | 526 | * Sakar 56379 Spy-shot 0 T. Kilgore |
482 | * Innovage 0 T. Kilgore | 527 | * Innovage 0 T. Kilgore |
483 | * Vivitar Mini 0 H. De Goede | 528 | * Vivitar Mini 0 H. De Goede |
484 | * Vivitar Mini 0 E. Rodriguez | 529 | * Vivitar Mini 0 E. Rodriguez |
@@ -487,7 +532,7 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
487 | * Philips dig. keych. 1 T. Kilgore | 532 | * Philips dig. keych. 1 T. Kilgore |
488 | * Trust Spyc@m 100 1 A. Jacobs | 533 | * Trust Spyc@m 100 1 A. Jacobs |
489 | */ | 534 | */ |
490 | switch (gspca_dev->usb_buf[1]) { | 535 | switch (gspca_dev->usb_buf[0]) { |
491 | case 2: | 536 | case 2: |
492 | sd->sensor_type = 0; | 537 | sd->sensor_type = 0; |
493 | break; | 538 | break; |
@@ -504,20 +549,19 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
504 | } else { | 549 | } else { |
505 | sd->cam_type = CAM_TYPE_VGA; | 550 | sd->cam_type = CAM_TYPE_VGA; |
506 | 551 | ||
507 | err_code = cam_get_response16(gspca_dev, 0x07, 1); | ||
508 | if (err_code < 0) | ||
509 | return err_code; | ||
510 | |||
511 | /* | 552 | /* |
512 | * Here is a table of the responses to the previous command | 553 | * Here is a table of the responses to the query for sensor |
513 | * from the known MR97310A VGA cameras. | 554 | * type, from the known MR97310A VGA cameras. Six different |
555 | * cameras of which five share the same USB ID. | ||
514 | * | 556 | * |
515 | * Name gspca_dev->usb_buf[] sd->sensor_type | 557 | * Name gspca_dev->usb_buf[] sd->sensor_type |
516 | * sd->do_lcd_stop | 558 | * sd->do_lcd_stop |
517 | * Aiptek Pencam VGA+ 0300 0 1 | 559 | * Aiptek Pencam VGA+ 0300 0 1 |
518 | * ION digital 0350 0 1 | 560 | * ION digital 0300 0 1 |
519 | * Argus DC-1620 0450 1 0 | 561 | * Argus DC-1620 0450 1 0 |
520 | * Argus QuickClix 0420 1 1 | 562 | * Argus QuickClix 0420 1 1 |
563 | * Sakar 77379 Digital 0350 0 1 | ||
564 | * Sakar 1638x CyberPix 0120 0 2 | ||
521 | * | 565 | * |
522 | * Based upon these results, we assume default settings | 566 | * Based upon these results, we assume default settings |
523 | * and then correct as necessary, as follows. | 567 | * and then correct as necessary, as follows. |
@@ -527,10 +571,12 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
527 | sd->sensor_type = 1; | 571 | sd->sensor_type = 1; |
528 | sd->do_lcd_stop = 0; | 572 | sd->do_lcd_stop = 0; |
529 | sd->adj_colors = 0; | 573 | sd->adj_colors = 0; |
530 | if ((gspca_dev->usb_buf[0] != 0x03) && | 574 | if (gspca_dev->usb_buf[0] == 0x01) { |
575 | sd->sensor_type = 2; | ||
576 | } else if ((gspca_dev->usb_buf[0] != 0x03) && | ||
531 | (gspca_dev->usb_buf[0] != 0x04)) { | 577 | (gspca_dev->usb_buf[0] != 0x04)) { |
532 | PDEBUG(D_ERR, "Unknown VGA Sensor id Byte 0: %02x", | 578 | PDEBUG(D_ERR, "Unknown VGA Sensor id Byte 0: %02x", |
533 | gspca_dev->usb_buf[1]); | 579 | gspca_dev->usb_buf[0]); |
534 | PDEBUG(D_ERR, "Defaults assumed, may not work"); | 580 | PDEBUG(D_ERR, "Defaults assumed, may not work"); |
535 | PDEBUG(D_ERR, "Please report this"); | 581 | PDEBUG(D_ERR, "Please report this"); |
536 | } | 582 | } |
@@ -560,7 +606,7 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
560 | PDEBUG(D_PROBE, "MR97310A VGA camera detected, sensor: %d", | 606 | PDEBUG(D_PROBE, "MR97310A VGA camera detected, sensor: %d", |
561 | sd->sensor_type); | 607 | sd->sensor_type); |
562 | } | 608 | } |
563 | /* Stop streaming as we've started it to probe the sensor type. */ | 609 | /* Stop streaming as we've started it only to probe the sensor type. */ |
564 | sd_stopN(gspca_dev); | 610 | sd_stopN(gspca_dev); |
565 | 611 | ||
566 | if (force_sensor_type != -1) { | 612 | if (force_sensor_type != -1) { |
@@ -574,9 +620,13 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
574 | /* No brightness for sensor_type 0 */ | 620 | /* No brightness for sensor_type 0 */ |
575 | if (sd->sensor_type == 0) | 621 | if (sd->sensor_type == 0) |
576 | gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) | | 622 | gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) | |
577 | (1 << ARGUS_QC_BRIGHTNESS_IDX); | 623 | (1 << ARGUS_QC_BRIGHTNESS_IDX) | |
624 | (1 << CONTRAST_IDX) | | ||
625 | (1 << SAKAR_CS_GAIN_IDX); | ||
578 | else | 626 | else |
579 | gspca_dev->ctrl_dis = (1 << ARGUS_QC_BRIGHTNESS_IDX) | | 627 | gspca_dev->ctrl_dis = (1 << ARGUS_QC_BRIGHTNESS_IDX) | |
628 | (1 << CONTRAST_IDX) | | ||
629 | (1 << SAKAR_CS_GAIN_IDX) | | ||
580 | (1 << MIN_CLOCKDIV_IDX); | 630 | (1 << MIN_CLOCKDIV_IDX); |
581 | } else { | 631 | } else { |
582 | /* All controls need to be disabled if VGA sensor_type is 0 */ | 632 | /* All controls need to be disabled if VGA sensor_type is 0 */ |
@@ -585,17 +635,30 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
585 | (1 << ARGUS_QC_BRIGHTNESS_IDX) | | 635 | (1 << ARGUS_QC_BRIGHTNESS_IDX) | |
586 | (1 << EXPOSURE_IDX) | | 636 | (1 << EXPOSURE_IDX) | |
587 | (1 << GAIN_IDX) | | 637 | (1 << GAIN_IDX) | |
638 | (1 << CONTRAST_IDX) | | ||
639 | (1 << SAKAR_CS_GAIN_IDX) | | ||
588 | (1 << MIN_CLOCKDIV_IDX); | 640 | (1 << MIN_CLOCKDIV_IDX); |
589 | else if (sd->do_lcd_stop) | 641 | else if (sd->sensor_type == 2) { |
642 | gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) | | ||
643 | (1 << ARGUS_QC_BRIGHTNESS_IDX) | | ||
644 | (1 << GAIN_IDX) | | ||
645 | (1 << MIN_CLOCKDIV_IDX); | ||
646 | gain_default = MR97310A_CS_GAIN_DEFAULT; | ||
647 | } else if (sd->do_lcd_stop) | ||
590 | /* Argus QuickClix has different brightness limits */ | 648 | /* Argus QuickClix has different brightness limits */ |
591 | gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX); | 649 | gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) | |
650 | (1 << CONTRAST_IDX) | | ||
651 | (1 << SAKAR_CS_GAIN_IDX); | ||
592 | else | 652 | else |
593 | gspca_dev->ctrl_dis = (1 << ARGUS_QC_BRIGHTNESS_IDX); | 653 | gspca_dev->ctrl_dis = (1 << ARGUS_QC_BRIGHTNESS_IDX) | |
654 | (1 << CONTRAST_IDX) | | ||
655 | (1 << SAKAR_CS_GAIN_IDX); | ||
594 | } | 656 | } |
595 | 657 | ||
596 | sd->brightness = MR97310A_BRIGHTNESS_DEFAULT; | 658 | sd->brightness = MR97310A_BRIGHTNESS_DEFAULT; |
597 | sd->exposure = MR97310A_EXPOSURE_DEFAULT; | 659 | sd->exposure = MR97310A_EXPOSURE_DEFAULT; |
598 | sd->gain = MR97310A_GAIN_DEFAULT; | 660 | sd->gain = gain_default; |
661 | sd->contrast = MR97310A_CONTRAST_DEFAULT; | ||
599 | sd->min_clockdiv = MR97310A_MIN_CLOCKDIV_DEFAULT; | 662 | sd->min_clockdiv = MR97310A_MIN_CLOCKDIV_DEFAULT; |
600 | 663 | ||
601 | return 0; | 664 | return 0; |
@@ -697,6 +760,12 @@ static int start_cif_cam(struct gspca_dev *gspca_dev) | |||
697 | {0x13, 0x00, {0x01}, 1}, | 760 | {0x13, 0x00, {0x01}, 1}, |
698 | {0, 0, {0}, 0} | 761 | {0, 0, {0}, 0} |
699 | }; | 762 | }; |
763 | /* Without this command the cam won't work with USB-UHCI */ | ||
764 | gspca_dev->usb_buf[0] = 0x0a; | ||
765 | gspca_dev->usb_buf[1] = 0x00; | ||
766 | err_code = mr_write(gspca_dev, 2); | ||
767 | if (err_code < 0) | ||
768 | return err_code; | ||
700 | err_code = sensor_write_regs(gspca_dev, cif_sensor1_init_data, | 769 | err_code = sensor_write_regs(gspca_dev, cif_sensor1_init_data, |
701 | ARRAY_SIZE(cif_sensor1_init_data)); | 770 | ARRAY_SIZE(cif_sensor1_init_data)); |
702 | } | 771 | } |
@@ -717,6 +786,10 @@ static int start_vga_cam(struct gspca_dev *gspca_dev) | |||
717 | data[5] = 0x00; | 786 | data[5] = 0x00; |
718 | data[10] = 0x91; | 787 | data[10] = 0x91; |
719 | } | 788 | } |
789 | if (sd->sensor_type == 2) { | ||
790 | data[5] = 0x00; | ||
791 | data[10] = 0x18; | ||
792 | } | ||
720 | 793 | ||
721 | switch (gspca_dev->width) { | 794 | switch (gspca_dev->width) { |
722 | case 160: | 795 | case 160: |
@@ -731,6 +804,10 @@ static int start_vga_cam(struct gspca_dev *gspca_dev) | |||
731 | data[4] = 0x78; /* reg 3, V size/4 */ | 804 | data[4] = 0x78; /* reg 3, V size/4 */ |
732 | data[6] = 0x04; /* reg 5, H start */ | 805 | data[6] = 0x04; /* reg 5, H start */ |
733 | data[8] = 0x03; /* reg 7, V start */ | 806 | data[8] = 0x03; /* reg 7, V start */ |
807 | if (sd->sensor_type == 2) { | ||
808 | data[6] = 2; | ||
809 | data[8] = 1; | ||
810 | } | ||
734 | if (sd->do_lcd_stop) | 811 | if (sd->do_lcd_stop) |
735 | data[8] = 0x04; /* Bayer tile shifted */ | 812 | data[8] = 0x04; /* Bayer tile shifted */ |
736 | break; | 813 | break; |
@@ -753,7 +830,6 @@ static int start_vga_cam(struct gspca_dev *gspca_dev) | |||
753 | return err_code; | 830 | return err_code; |
754 | 831 | ||
755 | if (!sd->sensor_type) { | 832 | if (!sd->sensor_type) { |
756 | /* The only known sensor_type 0 cam is the Argus DC-1620 */ | ||
757 | const struct sensor_w_data vga_sensor0_init_data[] = { | 833 | const struct sensor_w_data vga_sensor0_init_data[] = { |
758 | {0x01, 0x00, {0x0c, 0x00, 0x04}, 3}, | 834 | {0x01, 0x00, {0x0c, 0x00, 0x04}, 3}, |
759 | {0x14, 0x00, {0x01, 0xe4, 0x02, 0x84}, 4}, | 835 | {0x14, 0x00, {0x01, 0xe4, 0x02, 0x84}, 4}, |
@@ -764,7 +840,7 @@ static int start_vga_cam(struct gspca_dev *gspca_dev) | |||
764 | }; | 840 | }; |
765 | err_code = sensor_write_regs(gspca_dev, vga_sensor0_init_data, | 841 | err_code = sensor_write_regs(gspca_dev, vga_sensor0_init_data, |
766 | ARRAY_SIZE(vga_sensor0_init_data)); | 842 | ARRAY_SIZE(vga_sensor0_init_data)); |
767 | } else { /* sd->sensor_type = 1 */ | 843 | } else if (sd->sensor_type == 1) { |
768 | const struct sensor_w_data color_adj[] = { | 844 | const struct sensor_w_data color_adj[] = { |
769 | {0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00, | 845 | {0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00, |
770 | /* adjusted blue, green, red gain correct | 846 | /* adjusted blue, green, red gain correct |
@@ -802,6 +878,48 @@ static int start_vga_cam(struct gspca_dev *gspca_dev) | |||
802 | 878 | ||
803 | err_code = sensor_write_regs(gspca_dev, vga_sensor1_init_data, | 879 | err_code = sensor_write_regs(gspca_dev, vga_sensor1_init_data, |
804 | ARRAY_SIZE(vga_sensor1_init_data)); | 880 | ARRAY_SIZE(vga_sensor1_init_data)); |
881 | } else { /* sensor type == 2 */ | ||
882 | const struct sensor_w_data vga_sensor2_init_data[] = { | ||
883 | |||
884 | {0x01, 0x00, {0x48}, 1}, | ||
885 | {0x02, 0x00, {0x22}, 1}, | ||
886 | /* Reg 3 msb and 4 is lsb of the exposure setting*/ | ||
887 | {0x05, 0x00, {0x10}, 1}, | ||
888 | {0x06, 0x00, {0x00}, 1}, | ||
889 | {0x07, 0x00, {0x00}, 1}, | ||
890 | {0x08, 0x00, {0x00}, 1}, | ||
891 | {0x09, 0x00, {0x00}, 1}, | ||
892 | /* The following are used in the gain control | ||
893 | * which is BTW completely borked in the OEM driver | ||
894 | * The values for each color go from 0 to 0x7ff | ||
895 | *{0x0a, 0x00, {0x01}, 1}, green1 gain msb | ||
896 | *{0x0b, 0x00, {0x10}, 1}, green1 gain lsb | ||
897 | *{0x0c, 0x00, {0x01}, 1}, red gain msb | ||
898 | *{0x0d, 0x00, {0x10}, 1}, red gain lsb | ||
899 | *{0x0e, 0x00, {0x01}, 1}, blue gain msb | ||
900 | *{0x0f, 0x00, {0x10}, 1}, blue gain lsb | ||
901 | *{0x10, 0x00, {0x01}, 1}, green2 gain msb | ||
902 | *{0x11, 0x00, {0x10}, 1}, green2 gain lsb | ||
903 | */ | ||
904 | {0x12, 0x00, {0x00}, 1}, | ||
905 | {0x13, 0x00, {0x04}, 1}, /* weird effect on colors */ | ||
906 | {0x14, 0x00, {0x00}, 1}, | ||
907 | {0x15, 0x00, {0x06}, 1}, | ||
908 | {0x16, 0x00, {0x01}, 1}, | ||
909 | {0x17, 0x00, {0xe2}, 1}, /* vertical alignment */ | ||
910 | {0x18, 0x00, {0x02}, 1}, | ||
911 | {0x19, 0x00, {0x82}, 1}, /* don't mess with */ | ||
912 | {0x1a, 0x00, {0x00}, 1}, | ||
913 | {0x1b, 0x00, {0x20}, 1}, | ||
914 | /* {0x1c, 0x00, {0x17}, 1}, contrast control */ | ||
915 | {0x1d, 0x00, {0x80}, 1}, /* moving causes a mess */ | ||
916 | {0x1e, 0x00, {0x08}, 1}, /* moving jams the camera */ | ||
917 | {0x1f, 0x00, {0x0c}, 1}, | ||
918 | {0x20, 0x00, {0x00}, 1}, | ||
919 | {0, 0, {0}, 0} | ||
920 | }; | ||
921 | err_code = sensor_write_regs(gspca_dev, vga_sensor2_init_data, | ||
922 | ARRAY_SIZE(vga_sensor2_init_data)); | ||
805 | } | 923 | } |
806 | return err_code; | 924 | return err_code; |
807 | } | 925 | } |
@@ -834,6 +952,7 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
834 | return err_code; | 952 | return err_code; |
835 | 953 | ||
836 | setbrightness(gspca_dev); | 954 | setbrightness(gspca_dev); |
955 | setcontrast(gspca_dev); | ||
837 | setexposure(gspca_dev); | 956 | setexposure(gspca_dev); |
838 | setgain(gspca_dev); | 957 | setgain(gspca_dev); |
839 | 958 | ||
@@ -893,7 +1012,7 @@ static void setbrightness(struct gspca_dev *gspca_dev) | |||
893 | static void setexposure(struct gspca_dev *gspca_dev) | 1012 | static void setexposure(struct gspca_dev *gspca_dev) |
894 | { | 1013 | { |
895 | struct sd *sd = (struct sd *) gspca_dev; | 1014 | struct sd *sd = (struct sd *) gspca_dev; |
896 | int exposure; | 1015 | int exposure = MR97310A_EXPOSURE_DEFAULT; |
897 | u8 buf[2]; | 1016 | u8 buf[2]; |
898 | 1017 | ||
899 | if (gspca_dev->ctrl_dis & (1 << EXPOSURE_IDX)) | 1018 | if (gspca_dev->ctrl_dis & (1 << EXPOSURE_IDX)) |
@@ -905,6 +1024,11 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
905 | exposure = (sd->exposure * 9267) / 10000 + 300; | 1024 | exposure = (sd->exposure * 9267) / 10000 + 300; |
906 | sensor_write1(gspca_dev, 3, exposure >> 4); | 1025 | sensor_write1(gspca_dev, 3, exposure >> 4); |
907 | sensor_write1(gspca_dev, 4, exposure & 0x0f); | 1026 | sensor_write1(gspca_dev, 4, exposure & 0x0f); |
1027 | } else if (sd->sensor_type == 2) { | ||
1028 | exposure = sd->exposure; | ||
1029 | exposure >>= 3; | ||
1030 | sensor_write1(gspca_dev, 3, exposure >> 8); | ||
1031 | sensor_write1(gspca_dev, 4, exposure & 0xff); | ||
908 | } else { | 1032 | } else { |
909 | /* We have both a clock divider and an exposure register. | 1033 | /* We have both a clock divider and an exposure register. |
910 | We first calculate the clock divider, as that determines | 1034 | We first calculate the clock divider, as that determines |
@@ -943,17 +1067,34 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
943 | static void setgain(struct gspca_dev *gspca_dev) | 1067 | static void setgain(struct gspca_dev *gspca_dev) |
944 | { | 1068 | { |
945 | struct sd *sd = (struct sd *) gspca_dev; | 1069 | struct sd *sd = (struct sd *) gspca_dev; |
1070 | u8 gainreg; | ||
946 | 1071 | ||
947 | if (gspca_dev->ctrl_dis & (1 << GAIN_IDX)) | 1072 | if ((gspca_dev->ctrl_dis & (1 << GAIN_IDX)) && |
1073 | (gspca_dev->ctrl_dis & (1 << SAKAR_CS_GAIN_IDX))) | ||
948 | return; | 1074 | return; |
949 | 1075 | ||
950 | if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1) { | 1076 | if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1) |
951 | sensor_write1(gspca_dev, 0x0e, sd->gain); | 1077 | sensor_write1(gspca_dev, 0x0e, sd->gain); |
952 | } else { | 1078 | else if (sd->cam_type == CAM_TYPE_VGA && sd->sensor_type == 2) |
1079 | for (gainreg = 0x0a; gainreg < 0x11; gainreg += 2) { | ||
1080 | sensor_write1(gspca_dev, gainreg, sd->gain >> 8); | ||
1081 | sensor_write1(gspca_dev, gainreg + 1, sd->gain & 0xff); | ||
1082 | } | ||
1083 | else | ||
953 | sensor_write1(gspca_dev, 0x10, sd->gain); | 1084 | sensor_write1(gspca_dev, 0x10, sd->gain); |
954 | } | ||
955 | } | 1085 | } |
956 | 1086 | ||
1087 | static void setcontrast(struct gspca_dev *gspca_dev) | ||
1088 | { | ||
1089 | struct sd *sd = (struct sd *) gspca_dev; | ||
1090 | |||
1091 | if (gspca_dev->ctrl_dis & (1 << CONTRAST_IDX)) | ||
1092 | return; | ||
1093 | |||
1094 | sensor_write1(gspca_dev, 0x1c, sd->contrast); | ||
1095 | } | ||
1096 | |||
1097 | |||
957 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | 1098 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) |
958 | { | 1099 | { |
959 | struct sd *sd = (struct sd *) gspca_dev; | 1100 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -1008,6 +1149,25 @@ static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) | |||
1008 | return 0; | 1149 | return 0; |
1009 | } | 1150 | } |
1010 | 1151 | ||
1152 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) | ||
1153 | { | ||
1154 | struct sd *sd = (struct sd *) gspca_dev; | ||
1155 | |||
1156 | sd->contrast = val; | ||
1157 | if (gspca_dev->streaming) | ||
1158 | setcontrast(gspca_dev); | ||
1159 | return 0; | ||
1160 | } | ||
1161 | |||
1162 | |||
1163 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) | ||
1164 | { | ||
1165 | struct sd *sd = (struct sd *) gspca_dev; | ||
1166 | |||
1167 | *val = sd->contrast; | ||
1168 | return 0; | ||
1169 | } | ||
1170 | |||
1011 | static int sd_setmin_clockdiv(struct gspca_dev *gspca_dev, __s32 val) | 1171 | static int sd_setmin_clockdiv(struct gspca_dev *gspca_dev, __s32 val) |
1012 | { | 1172 | { |
1013 | struct sd *sd = (struct sd *) gspca_dev; | 1173 | struct sd *sd = (struct sd *) gspca_dev; |
diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index b4f965731244..bc4ced6c013b 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c | |||
@@ -38,6 +38,7 @@ | |||
38 | */ | 38 | */ |
39 | #define MODULE_NAME "ov519" | 39 | #define MODULE_NAME "ov519" |
40 | 40 | ||
41 | #include <linux/input.h> | ||
41 | #include "gspca.h" | 42 | #include "gspca.h" |
42 | 43 | ||
43 | MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); | 44 | MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); |
@@ -70,6 +71,9 @@ struct sd { | |||
70 | char invert_led; | 71 | char invert_led; |
71 | #define BRIDGE_INVERT_LED 8 | 72 | #define BRIDGE_INVERT_LED 8 |
72 | 73 | ||
74 | char snapshot_pressed; | ||
75 | char snapshot_needs_reset; | ||
76 | |||
73 | /* Determined by sensor type */ | 77 | /* Determined by sensor type */ |
74 | __u8 sif; | 78 | __u8 sif; |
75 | 79 | ||
@@ -99,10 +103,12 @@ struct sd { | |||
99 | #define SEN_OV66308AF 5 | 103 | #define SEN_OV66308AF 5 |
100 | #define SEN_OV7610 6 | 104 | #define SEN_OV7610 6 |
101 | #define SEN_OV7620 7 | 105 | #define SEN_OV7620 7 |
102 | #define SEN_OV7640 8 | 106 | #define SEN_OV7620AE 8 |
103 | #define SEN_OV7670 9 | 107 | #define SEN_OV7640 9 |
104 | #define SEN_OV76BE 10 | 108 | #define SEN_OV7648 10 |
105 | #define SEN_OV8610 11 | 109 | #define SEN_OV7670 11 |
110 | #define SEN_OV76BE 12 | ||
111 | #define SEN_OV8610 13 | ||
106 | 112 | ||
107 | u8 sensor_addr; | 113 | u8 sensor_addr; |
108 | int sensor_width; | 114 | int sensor_width; |
@@ -139,6 +145,7 @@ static void setautobrightness(struct sd *sd); | |||
139 | static void setfreq(struct sd *sd); | 145 | static void setfreq(struct sd *sd); |
140 | 146 | ||
141 | static const struct ctrl sd_ctrls[] = { | 147 | static const struct ctrl sd_ctrls[] = { |
148 | #define BRIGHTNESS_IDX 0 | ||
142 | { | 149 | { |
143 | { | 150 | { |
144 | .id = V4L2_CID_BRIGHTNESS, | 151 | .id = V4L2_CID_BRIGHTNESS, |
@@ -153,6 +160,7 @@ static const struct ctrl sd_ctrls[] = { | |||
153 | .set = sd_setbrightness, | 160 | .set = sd_setbrightness, |
154 | .get = sd_getbrightness, | 161 | .get = sd_getbrightness, |
155 | }, | 162 | }, |
163 | #define CONTRAST_IDX 1 | ||
156 | { | 164 | { |
157 | { | 165 | { |
158 | .id = V4L2_CID_CONTRAST, | 166 | .id = V4L2_CID_CONTRAST, |
@@ -167,6 +175,7 @@ static const struct ctrl sd_ctrls[] = { | |||
167 | .set = sd_setcontrast, | 175 | .set = sd_setcontrast, |
168 | .get = sd_getcontrast, | 176 | .get = sd_getcontrast, |
169 | }, | 177 | }, |
178 | #define COLOR_IDX 2 | ||
170 | { | 179 | { |
171 | { | 180 | { |
172 | .id = V4L2_CID_SATURATION, | 181 | .id = V4L2_CID_SATURATION, |
@@ -2554,7 +2563,7 @@ static int ov7xx0_configure(struct sd *sd) | |||
2554 | /* I don't know what's different about the 76BE yet. */ | 2563 | /* I don't know what's different about the 76BE yet. */ |
2555 | if (i2c_r(sd, 0x15) & 1) { | 2564 | if (i2c_r(sd, 0x15) & 1) { |
2556 | PDEBUG(D_PROBE, "Sensor is an OV7620AE"); | 2565 | PDEBUG(D_PROBE, "Sensor is an OV7620AE"); |
2557 | sd->sensor = SEN_OV7620; | 2566 | sd->sensor = SEN_OV7620AE; |
2558 | } else { | 2567 | } else { |
2559 | PDEBUG(D_PROBE, "Sensor is an OV76BE"); | 2568 | PDEBUG(D_PROBE, "Sensor is an OV76BE"); |
2560 | sd->sensor = SEN_OV76BE; | 2569 | sd->sensor = SEN_OV76BE; |
@@ -2588,7 +2597,7 @@ static int ov7xx0_configure(struct sd *sd) | |||
2588 | break; | 2597 | break; |
2589 | case 0x48: | 2598 | case 0x48: |
2590 | PDEBUG(D_PROBE, "Sensor is an OV7648"); | 2599 | PDEBUG(D_PROBE, "Sensor is an OV7648"); |
2591 | sd->sensor = SEN_OV7640; /* FIXME */ | 2600 | sd->sensor = SEN_OV7648; |
2592 | break; | 2601 | break; |
2593 | default: | 2602 | default: |
2594 | PDEBUG(D_PROBE, "Unknown sensor: 0x76%x", low); | 2603 | PDEBUG(D_PROBE, "Unknown sensor: 0x76%x", low); |
@@ -2680,6 +2689,36 @@ static void ov51x_led_control(struct sd *sd, int on) | |||
2680 | } | 2689 | } |
2681 | } | 2690 | } |
2682 | 2691 | ||
2692 | static void sd_reset_snapshot(struct gspca_dev *gspca_dev) | ||
2693 | { | ||
2694 | struct sd *sd = (struct sd *) gspca_dev; | ||
2695 | |||
2696 | if (!sd->snapshot_needs_reset) | ||
2697 | return; | ||
2698 | |||
2699 | /* Note it is important that we clear sd->snapshot_needs_reset, | ||
2700 | before actually clearing the snapshot state in the bridge | ||
2701 | otherwise we might race with the pkt_scan interrupt handler */ | ||
2702 | sd->snapshot_needs_reset = 0; | ||
2703 | |||
2704 | switch (sd->bridge) { | ||
2705 | case BRIDGE_OV511: | ||
2706 | case BRIDGE_OV511PLUS: | ||
2707 | reg_w(sd, R51x_SYS_SNAP, 0x02); | ||
2708 | reg_w(sd, R51x_SYS_SNAP, 0x00); | ||
2709 | break; | ||
2710 | case BRIDGE_OV518: | ||
2711 | case BRIDGE_OV518PLUS: | ||
2712 | reg_w(sd, R51x_SYS_SNAP, 0x02); /* Reset */ | ||
2713 | reg_w(sd, R51x_SYS_SNAP, 0x01); /* Enable */ | ||
2714 | break; | ||
2715 | case BRIDGE_OV519: | ||
2716 | reg_w(sd, R51x_SYS_RESET, 0x40); | ||
2717 | reg_w(sd, R51x_SYS_RESET, 0x00); | ||
2718 | break; | ||
2719 | } | ||
2720 | } | ||
2721 | |||
2683 | static int ov51x_upload_quan_tables(struct sd *sd) | 2722 | static int ov51x_upload_quan_tables(struct sd *sd) |
2684 | { | 2723 | { |
2685 | const unsigned char yQuanTable511[] = { | 2724 | const unsigned char yQuanTable511[] = { |
@@ -3115,7 +3154,11 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
3115 | (1 << OV7670_FREQ_IDX); | 3154 | (1 << OV7670_FREQ_IDX); |
3116 | } | 3155 | } |
3117 | sd->quality = QUALITY_DEF; | 3156 | sd->quality = QUALITY_DEF; |
3118 | if (sd->sensor == SEN_OV7640 || sd->sensor == SEN_OV7670) | 3157 | if (sd->sensor == SEN_OV7640 || |
3158 | sd->sensor == SEN_OV7648) | ||
3159 | gspca_dev->ctrl_dis |= (1 << AUTOBRIGHT_IDX) | | ||
3160 | (1 << CONTRAST_IDX); | ||
3161 | if (sd->sensor == SEN_OV7670) | ||
3119 | gspca_dev->ctrl_dis |= 1 << AUTOBRIGHT_IDX; | 3162 | gspca_dev->ctrl_dis |= 1 << AUTOBRIGHT_IDX; |
3120 | /* OV8610 Frequency filter control should work but needs testing */ | 3163 | /* OV8610 Frequency filter control should work but needs testing */ |
3121 | if (sd->sensor == SEN_OV8610) | 3164 | if (sd->sensor == SEN_OV8610) |
@@ -3169,10 +3212,12 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
3169 | return -EIO; | 3212 | return -EIO; |
3170 | break; | 3213 | break; |
3171 | case SEN_OV7620: | 3214 | case SEN_OV7620: |
3215 | case SEN_OV7620AE: | ||
3172 | if (write_i2c_regvals(sd, norm_7620, ARRAY_SIZE(norm_7620))) | 3216 | if (write_i2c_regvals(sd, norm_7620, ARRAY_SIZE(norm_7620))) |
3173 | return -EIO; | 3217 | return -EIO; |
3174 | break; | 3218 | break; |
3175 | case SEN_OV7640: | 3219 | case SEN_OV7640: |
3220 | case SEN_OV7648: | ||
3176 | if (write_i2c_regvals(sd, norm_7640, ARRAY_SIZE(norm_7640))) | 3221 | if (write_i2c_regvals(sd, norm_7640, ARRAY_SIZE(norm_7640))) |
3177 | return -EIO; | 3222 | return -EIO; |
3178 | break; | 3223 | break; |
@@ -3246,7 +3291,9 @@ static int ov511_mode_init_regs(struct sd *sd) | |||
3246 | /* Note once the FIXME's in mode_init_ov_sensor_regs() are fixed | 3291 | /* Note once the FIXME's in mode_init_ov_sensor_regs() are fixed |
3247 | for more sensors we need to do this for them too */ | 3292 | for more sensors we need to do this for them too */ |
3248 | case SEN_OV7620: | 3293 | case SEN_OV7620: |
3294 | case SEN_OV7620AE: | ||
3249 | case SEN_OV7640: | 3295 | case SEN_OV7640: |
3296 | case SEN_OV7648: | ||
3250 | case SEN_OV76BE: | 3297 | case SEN_OV76BE: |
3251 | if (sd->gspca_dev.width == 320) | 3298 | if (sd->gspca_dev.width == 320) |
3252 | interlaced = 1; | 3299 | interlaced = 1; |
@@ -3377,7 +3424,7 @@ static int ov518_mode_init_regs(struct sd *sd) | |||
3377 | 3424 | ||
3378 | if (sd->bridge == BRIDGE_OV518PLUS) { | 3425 | if (sd->bridge == BRIDGE_OV518PLUS) { |
3379 | switch (sd->sensor) { | 3426 | switch (sd->sensor) { |
3380 | case SEN_OV7620: | 3427 | case SEN_OV7620AE: |
3381 | if (sd->gspca_dev.width == 320) { | 3428 | if (sd->gspca_dev.width == 320) { |
3382 | reg_w(sd, 0x20, 0x00); | 3429 | reg_w(sd, 0x20, 0x00); |
3383 | reg_w(sd, 0x21, 0x19); | 3430 | reg_w(sd, 0x21, 0x19); |
@@ -3386,6 +3433,10 @@ static int ov518_mode_init_regs(struct sd *sd) | |||
3386 | reg_w(sd, 0x21, 0x1f); | 3433 | reg_w(sd, 0x21, 0x1f); |
3387 | } | 3434 | } |
3388 | break; | 3435 | break; |
3436 | case SEN_OV7620: | ||
3437 | reg_w(sd, 0x20, 0x00); | ||
3438 | reg_w(sd, 0x21, 0x19); | ||
3439 | break; | ||
3389 | default: | 3440 | default: |
3390 | reg_w(sd, 0x21, 0x19); | 3441 | reg_w(sd, 0x21, 0x19); |
3391 | } | 3442 | } |
@@ -3488,7 +3539,8 @@ static int ov519_mode_init_regs(struct sd *sd) | |||
3488 | if (write_regvals(sd, mode_init_519, | 3539 | if (write_regvals(sd, mode_init_519, |
3489 | ARRAY_SIZE(mode_init_519))) | 3540 | ARRAY_SIZE(mode_init_519))) |
3490 | return -EIO; | 3541 | return -EIO; |
3491 | if (sd->sensor == SEN_OV7640) { | 3542 | if (sd->sensor == SEN_OV7640 || |
3543 | sd->sensor == SEN_OV7648) { | ||
3492 | /* Select 8-bit input mode */ | 3544 | /* Select 8-bit input mode */ |
3493 | reg_w_mask(sd, OV519_R20_DFR, 0x10, 0x10); | 3545 | reg_w_mask(sd, OV519_R20_DFR, 0x10, 0x10); |
3494 | } | 3546 | } |
@@ -3503,6 +3555,9 @@ static int ov519_mode_init_regs(struct sd *sd) | |||
3503 | if (sd->sensor == SEN_OV7670 && | 3555 | if (sd->sensor == SEN_OV7670 && |
3504 | sd->gspca_dev.cam.cam_mode[sd->gspca_dev.curr_mode].priv) | 3556 | sd->gspca_dev.cam.cam_mode[sd->gspca_dev.curr_mode].priv) |
3505 | reg_w(sd, OV519_R12_X_OFFSETL, 0x04); | 3557 | reg_w(sd, OV519_R12_X_OFFSETL, 0x04); |
3558 | else if (sd->sensor == SEN_OV7648 && | ||
3559 | sd->gspca_dev.cam.cam_mode[sd->gspca_dev.curr_mode].priv) | ||
3560 | reg_w(sd, OV519_R12_X_OFFSETL, 0x01); | ||
3506 | else | 3561 | else |
3507 | reg_w(sd, OV519_R12_X_OFFSETL, 0x00); | 3562 | reg_w(sd, OV519_R12_X_OFFSETL, 0x00); |
3508 | reg_w(sd, OV519_R13_X_OFFSETH, 0x00); | 3563 | reg_w(sd, OV519_R13_X_OFFSETH, 0x00); |
@@ -3520,6 +3575,7 @@ static int ov519_mode_init_regs(struct sd *sd) | |||
3520 | sd->clockdiv = 0; | 3575 | sd->clockdiv = 0; |
3521 | switch (sd->sensor) { | 3576 | switch (sd->sensor) { |
3522 | case SEN_OV7640: | 3577 | case SEN_OV7640: |
3578 | case SEN_OV7648: | ||
3523 | switch (sd->frame_rate) { | 3579 | switch (sd->frame_rate) { |
3524 | default: | 3580 | default: |
3525 | /* case 30: */ | 3581 | /* case 30: */ |
@@ -3649,6 +3705,7 @@ static int mode_init_ov_sensor_regs(struct sd *sd) | |||
3649 | i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */ | 3705 | i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */ |
3650 | break; | 3706 | break; |
3651 | case SEN_OV7620: | 3707 | case SEN_OV7620: |
3708 | case SEN_OV7620AE: | ||
3652 | case SEN_OV76BE: | 3709 | case SEN_OV76BE: |
3653 | i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); | 3710 | i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); |
3654 | i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20); | 3711 | i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20); |
@@ -3663,13 +3720,16 @@ static int mode_init_ov_sensor_regs(struct sd *sd) | |||
3663 | i2c_w(sd, 0x35, qvga ? 0x1e : 0x9e); | 3720 | i2c_w(sd, 0x35, qvga ? 0x1e : 0x9e); |
3664 | break; | 3721 | break; |
3665 | case SEN_OV7640: | 3722 | case SEN_OV7640: |
3723 | case SEN_OV7648: | ||
3666 | i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); | 3724 | i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); |
3667 | i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20); | 3725 | i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20); |
3668 | /* i2c_w(sd, 0x24, qvga ? 0x20 : 0x3a); */ | 3726 | /* Setting this undocumented bit in qvga mode removes a very |
3669 | /* i2c_w(sd, 0x25, qvga ? 0x30 : 0x60); */ | 3727 | annoying vertical shaking of the image */ |
3670 | /* i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40); */ | 3728 | i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40); |
3671 | /* i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0); */ | 3729 | /* Unknown */ |
3672 | /* i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20); */ | 3730 | i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0); |
3731 | /* Allow higher automatic gain (to allow higher framerates) */ | ||
3732 | i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20); | ||
3673 | i2c_w_mask(sd, 0x12, 0x04, 0x04); /* AWB: 1 */ | 3733 | i2c_w_mask(sd, 0x12, 0x04, 0x04); /* AWB: 1 */ |
3674 | break; | 3734 | break; |
3675 | case SEN_OV7670: | 3735 | case SEN_OV7670: |
@@ -3795,11 +3855,13 @@ static int set_ov_sensor_window(struct sd *sd) | |||
3795 | } | 3855 | } |
3796 | break; | 3856 | break; |
3797 | case SEN_OV7620: | 3857 | case SEN_OV7620: |
3858 | case SEN_OV7620AE: | ||
3798 | hwsbase = 0x2f; /* From 7620.SET (spec is wrong) */ | 3859 | hwsbase = 0x2f; /* From 7620.SET (spec is wrong) */ |
3799 | hwebase = 0x2f; | 3860 | hwebase = 0x2f; |
3800 | vwsbase = vwebase = 0x05; | 3861 | vwsbase = vwebase = 0x05; |
3801 | break; | 3862 | break; |
3802 | case SEN_OV7640: | 3863 | case SEN_OV7640: |
3864 | case SEN_OV7648: | ||
3803 | hwsbase = 0x1a; | 3865 | hwsbase = 0x1a; |
3804 | hwebase = 0x1a; | 3866 | hwebase = 0x1a; |
3805 | vwsbase = vwebase = 0x03; | 3867 | vwsbase = vwebase = 0x03; |
@@ -3893,6 +3955,12 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
3893 | setautobrightness(sd); | 3955 | setautobrightness(sd); |
3894 | setfreq(sd); | 3956 | setfreq(sd); |
3895 | 3957 | ||
3958 | /* Force clear snapshot state in case the snapshot button was | ||
3959 | pressed while we weren't streaming */ | ||
3960 | sd->snapshot_needs_reset = 1; | ||
3961 | sd_reset_snapshot(gspca_dev); | ||
3962 | sd->snapshot_pressed = 0; | ||
3963 | |||
3896 | ret = ov51x_restart(sd); | 3964 | ret = ov51x_restart(sd); |
3897 | if (ret < 0) | 3965 | if (ret < 0) |
3898 | goto out; | 3966 | goto out; |
@@ -3919,6 +3987,34 @@ static void sd_stop0(struct gspca_dev *gspca_dev) | |||
3919 | w9968cf_stop0(sd); | 3987 | w9968cf_stop0(sd); |
3920 | } | 3988 | } |
3921 | 3989 | ||
3990 | static void ov51x_handle_button(struct gspca_dev *gspca_dev, u8 state) | ||
3991 | { | ||
3992 | struct sd *sd = (struct sd *) gspca_dev; | ||
3993 | |||
3994 | if (sd->snapshot_pressed != state) { | ||
3995 | #ifdef CONFIG_INPUT | ||
3996 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, state); | ||
3997 | input_sync(gspca_dev->input_dev); | ||
3998 | #endif | ||
3999 | if (state) | ||
4000 | sd->snapshot_needs_reset = 1; | ||
4001 | |||
4002 | sd->snapshot_pressed = state; | ||
4003 | } else { | ||
4004 | /* On the ov511 / ov519 we need to reset the button state | ||
4005 | multiple times, as resetting does not work as long as the | ||
4006 | button stays pressed */ | ||
4007 | switch (sd->bridge) { | ||
4008 | case BRIDGE_OV511: | ||
4009 | case BRIDGE_OV511PLUS: | ||
4010 | case BRIDGE_OV519: | ||
4011 | if (state) | ||
4012 | sd->snapshot_needs_reset = 1; | ||
4013 | break; | ||
4014 | } | ||
4015 | } | ||
4016 | } | ||
4017 | |||
3922 | static void ov511_pkt_scan(struct gspca_dev *gspca_dev, | 4018 | static void ov511_pkt_scan(struct gspca_dev *gspca_dev, |
3923 | u8 *in, /* isoc packet */ | 4019 | u8 *in, /* isoc packet */ |
3924 | int len) /* iso packet length */ | 4020 | int len) /* iso packet length */ |
@@ -3940,6 +4036,7 @@ static void ov511_pkt_scan(struct gspca_dev *gspca_dev, | |||
3940 | */ | 4036 | */ |
3941 | if (!(in[0] | in[1] | in[2] | in[3] | in[4] | in[5] | in[6] | in[7]) && | 4037 | if (!(in[0] | in[1] | in[2] | in[3] | in[4] | in[5] | in[6] | in[7]) && |
3942 | (in[8] & 0x08)) { | 4038 | (in[8] & 0x08)) { |
4039 | ov51x_handle_button(gspca_dev, (in[8] >> 2) & 1); | ||
3943 | if (in[8] & 0x80) { | 4040 | if (in[8] & 0x80) { |
3944 | /* Frame end */ | 4041 | /* Frame end */ |
3945 | if ((in[9] + 1) * 8 != gspca_dev->width || | 4042 | if ((in[9] + 1) * 8 != gspca_dev->width || |
@@ -3977,6 +4074,7 @@ static void ov518_pkt_scan(struct gspca_dev *gspca_dev, | |||
3977 | /* A false positive here is likely, until OVT gives me | 4074 | /* A false positive here is likely, until OVT gives me |
3978 | * the definitive SOF/EOF format */ | 4075 | * the definitive SOF/EOF format */ |
3979 | if ((!(data[0] | data[1] | data[2] | data[3] | data[5])) && data[6]) { | 4076 | if ((!(data[0] | data[1] | data[2] | data[3] | data[5])) && data[6]) { |
4077 | ov51x_handle_button(gspca_dev, (data[6] >> 1) & 1); | ||
3980 | gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); | 4078 | gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); |
3981 | gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0); | 4079 | gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0); |
3982 | sd->packet_nr = 0; | 4080 | sd->packet_nr = 0; |
@@ -4024,6 +4122,9 @@ static void ov519_pkt_scan(struct gspca_dev *gspca_dev, | |||
4024 | if (data[0] == 0xff && data[1] == 0xff && data[2] == 0xff) { | 4122 | if (data[0] == 0xff && data[1] == 0xff && data[2] == 0xff) { |
4025 | switch (data[3]) { | 4123 | switch (data[3]) { |
4026 | case 0x50: /* start of frame */ | 4124 | case 0x50: /* start of frame */ |
4125 | /* Don't check the button state here, as the state | ||
4126 | usually (always ?) changes at EOF and checking it | ||
4127 | here leads to unnecessary snapshot state resets. */ | ||
4027 | #define HDRSZ 16 | 4128 | #define HDRSZ 16 |
4028 | data += HDRSZ; | 4129 | data += HDRSZ; |
4029 | len -= HDRSZ; | 4130 | len -= HDRSZ; |
@@ -4035,6 +4136,7 @@ static void ov519_pkt_scan(struct gspca_dev *gspca_dev, | |||
4035 | gspca_dev->last_packet_type = DISCARD_PACKET; | 4136 | gspca_dev->last_packet_type = DISCARD_PACKET; |
4036 | return; | 4137 | return; |
4037 | case 0x51: /* end of frame */ | 4138 | case 0x51: /* end of frame */ |
4139 | ov51x_handle_button(gspca_dev, data[11] & 1); | ||
4038 | if (data[9] != 0) | 4140 | if (data[9] != 0) |
4039 | gspca_dev->last_packet_type = DISCARD_PACKET; | 4141 | gspca_dev->last_packet_type = DISCARD_PACKET; |
4040 | gspca_frame_add(gspca_dev, LAST_PACKET, | 4142 | gspca_frame_add(gspca_dev, LAST_PACKET, |
@@ -4103,9 +4205,11 @@ static void setbrightness(struct gspca_dev *gspca_dev) | |||
4103 | case SEN_OV6630: | 4205 | case SEN_OV6630: |
4104 | case SEN_OV66308AF: | 4206 | case SEN_OV66308AF: |
4105 | case SEN_OV7640: | 4207 | case SEN_OV7640: |
4208 | case SEN_OV7648: | ||
4106 | i2c_w(sd, OV7610_REG_BRT, val); | 4209 | i2c_w(sd, OV7610_REG_BRT, val); |
4107 | break; | 4210 | break; |
4108 | case SEN_OV7620: | 4211 | case SEN_OV7620: |
4212 | case SEN_OV7620AE: | ||
4109 | /* 7620 doesn't like manual changes when in auto mode */ | 4213 | /* 7620 doesn't like manual changes when in auto mode */ |
4110 | if (!sd->autobrightness) | 4214 | if (!sd->autobrightness) |
4111 | i2c_w(sd, OV7610_REG_BRT, val); | 4215 | i2c_w(sd, OV7610_REG_BRT, val); |
@@ -4142,7 +4246,8 @@ static void setcontrast(struct gspca_dev *gspca_dev) | |||
4142 | i2c_w(sd, 0x64, ctab[val >> 5]); | 4246 | i2c_w(sd, 0x64, ctab[val >> 5]); |
4143 | break; | 4247 | break; |
4144 | } | 4248 | } |
4145 | case SEN_OV7620: { | 4249 | case SEN_OV7620: |
4250 | case SEN_OV7620AE: { | ||
4146 | static const __u8 ctab[] = { | 4251 | static const __u8 ctab[] = { |
4147 | 0x01, 0x05, 0x09, 0x11, 0x15, 0x35, 0x37, 0x57, | 4252 | 0x01, 0x05, 0x09, 0x11, 0x15, 0x35, 0x37, 0x57, |
4148 | 0x5b, 0xa5, 0xa7, 0xc7, 0xc9, 0xcf, 0xef, 0xff | 4253 | 0x5b, 0xa5, 0xa7, 0xc7, 0xc9, 0xcf, 0xef, 0xff |
@@ -4152,10 +4257,6 @@ static void setcontrast(struct gspca_dev *gspca_dev) | |||
4152 | i2c_w(sd, 0x64, ctab[val >> 4]); | 4257 | i2c_w(sd, 0x64, ctab[val >> 4]); |
4153 | break; | 4258 | break; |
4154 | } | 4259 | } |
4155 | case SEN_OV7640: | ||
4156 | /* Use gain control instead. */ | ||
4157 | i2c_w(sd, OV7610_REG_GAIN, val >> 2); | ||
4158 | break; | ||
4159 | case SEN_OV7670: | 4260 | case SEN_OV7670: |
4160 | /* check that this isn't just the same as ov7610 */ | 4261 | /* check that this isn't just the same as ov7610 */ |
4161 | i2c_w(sd, OV7670_REG_CONTRAS, val >> 1); | 4262 | i2c_w(sd, OV7670_REG_CONTRAS, val >> 1); |
@@ -4179,6 +4280,7 @@ static void setcolors(struct gspca_dev *gspca_dev) | |||
4179 | i2c_w(sd, OV7610_REG_SAT, val); | 4280 | i2c_w(sd, OV7610_REG_SAT, val); |
4180 | break; | 4281 | break; |
4181 | case SEN_OV7620: | 4282 | case SEN_OV7620: |
4283 | case SEN_OV7620AE: | ||
4182 | /* Use UV gamma control instead. Bits 0 & 7 are reserved. */ | 4284 | /* Use UV gamma control instead. Bits 0 & 7 are reserved. */ |
4183 | /* rc = ov_i2c_write(sd->dev, 0x62, (val >> 9) & 0x7e); | 4285 | /* rc = ov_i2c_write(sd->dev, 0x62, (val >> 9) & 0x7e); |
4184 | if (rc < 0) | 4286 | if (rc < 0) |
@@ -4186,6 +4288,7 @@ static void setcolors(struct gspca_dev *gspca_dev) | |||
4186 | i2c_w(sd, OV7610_REG_SAT, val); | 4288 | i2c_w(sd, OV7610_REG_SAT, val); |
4187 | break; | 4289 | break; |
4188 | case SEN_OV7640: | 4290 | case SEN_OV7640: |
4291 | case SEN_OV7648: | ||
4189 | i2c_w(sd, OV7610_REG_SAT, val & 0xf0); | 4292 | i2c_w(sd, OV7610_REG_SAT, val & 0xf0); |
4190 | break; | 4293 | break; |
4191 | case SEN_OV7670: | 4294 | case SEN_OV7670: |
@@ -4198,7 +4301,8 @@ static void setcolors(struct gspca_dev *gspca_dev) | |||
4198 | 4301 | ||
4199 | static void setautobrightness(struct sd *sd) | 4302 | static void setautobrightness(struct sd *sd) |
4200 | { | 4303 | { |
4201 | if (sd->sensor == SEN_OV7640 || sd->sensor == SEN_OV7670 || | 4304 | if (sd->sensor == SEN_OV7640 || sd->sensor == SEN_OV7648 || |
4305 | sd->sensor == SEN_OV7670 || | ||
4202 | sd->sensor == SEN_OV2610 || sd->sensor == SEN_OV3610) | 4306 | sd->sensor == SEN_OV2610 || sd->sensor == SEN_OV3610) |
4203 | return; | 4307 | return; |
4204 | 4308 | ||
@@ -4475,9 +4579,13 @@ static const struct sd_desc sd_desc = { | |||
4475 | .stopN = sd_stopN, | 4579 | .stopN = sd_stopN, |
4476 | .stop0 = sd_stop0, | 4580 | .stop0 = sd_stop0, |
4477 | .pkt_scan = sd_pkt_scan, | 4581 | .pkt_scan = sd_pkt_scan, |
4582 | .dq_callback = sd_reset_snapshot, | ||
4478 | .querymenu = sd_querymenu, | 4583 | .querymenu = sd_querymenu, |
4479 | .get_jcomp = sd_get_jcomp, | 4584 | .get_jcomp = sd_get_jcomp, |
4480 | .set_jcomp = sd_set_jcomp, | 4585 | .set_jcomp = sd_set_jcomp, |
4586 | #ifdef CONFIG_INPUT | ||
4587 | .other_input = 1, | ||
4588 | #endif | ||
4481 | }; | 4589 | }; |
4482 | 4590 | ||
4483 | /* -- module initialisation -- */ | 4591 | /* -- module initialisation -- */ |
@@ -4494,7 +4602,8 @@ static const __devinitdata struct usb_device_id device_table[] = { | |||
4494 | .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, | 4602 | .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, |
4495 | {USB_DEVICE(0x045e, 0x028c), .driver_info = BRIDGE_OV519 }, | 4603 | {USB_DEVICE(0x045e, 0x028c), .driver_info = BRIDGE_OV519 }, |
4496 | {USB_DEVICE(0x054c, 0x0154), .driver_info = BRIDGE_OV519 }, | 4604 | {USB_DEVICE(0x054c, 0x0154), .driver_info = BRIDGE_OV519 }, |
4497 | {USB_DEVICE(0x054c, 0x0155), .driver_info = BRIDGE_OV519 }, | 4605 | {USB_DEVICE(0x054c, 0x0155), |
4606 | .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, | ||
4498 | {USB_DEVICE(0x05a9, 0x0511), .driver_info = BRIDGE_OV511 }, | 4607 | {USB_DEVICE(0x05a9, 0x0511), .driver_info = BRIDGE_OV511 }, |
4499 | {USB_DEVICE(0x05a9, 0x0518), .driver_info = BRIDGE_OV518 }, | 4608 | {USB_DEVICE(0x05a9, 0x0518), .driver_info = BRIDGE_OV518 }, |
4500 | {USB_DEVICE(0x05a9, 0x0519), .driver_info = BRIDGE_OV519 }, | 4609 | {USB_DEVICE(0x05a9, 0x0519), .driver_info = BRIDGE_OV519 }, |
diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index 0a6b8f07a69d..957e05e2d08f 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * ov534 gspca driver | 2 | * ov534-ov772x gspca driver |
3 | * | 3 | * |
4 | * Copyright (C) 2008 Antonio Ospite <ospite@studenti.unina.it> | 4 | * Copyright (C) 2008 Antonio Ospite <ospite@studenti.unina.it> |
5 | * Copyright (C) 2008 Jim Paris <jim@jtan.com> | 5 | * Copyright (C) 2008 Jim Paris <jim@jtan.com> |
@@ -68,12 +68,7 @@ struct sd { | |||
68 | s8 sharpness; | 68 | s8 sharpness; |
69 | u8 hflip; | 69 | u8 hflip; |
70 | u8 vflip; | 70 | u8 vflip; |
71 | u8 satur; | ||
72 | u8 lightfreq; | ||
73 | 71 | ||
74 | u8 sensor; | ||
75 | #define SENSOR_OV772X 0 | ||
76 | #define SENSOR_OV965X 1 | ||
77 | }; | 72 | }; |
78 | 73 | ||
79 | /* V4L2 controls supported by the driver */ | 74 | /* V4L2 controls supported by the driver */ |
@@ -101,12 +96,8 @@ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | |||
101 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | 96 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); |
102 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | 97 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); |
103 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | 98 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); |
104 | static int sd_setsatur(struct gspca_dev *gspca_dev, __s32 val); | ||
105 | static int sd_getsatur(struct gspca_dev *gspca_dev, __s32 *val); | ||
106 | static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); | ||
107 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); | ||
108 | 99 | ||
109 | static struct ctrl sd_ctrls_ov772x[] = { | 100 | static const struct ctrl sd_ctrls[] = { |
110 | { /* 0 */ | 101 | { /* 0 */ |
111 | { | 102 | { |
112 | .id = V4L2_CID_BRIGHTNESS, | 103 | .id = V4L2_CID_BRIGHTNESS, |
@@ -115,8 +106,8 @@ static struct ctrl sd_ctrls_ov772x[] = { | |||
115 | .minimum = 0, | 106 | .minimum = 0, |
116 | .maximum = 255, | 107 | .maximum = 255, |
117 | .step = 1, | 108 | .step = 1, |
118 | #define BRIGHTNESS_77_DEF 20 | 109 | #define BRIGHTNESS_DEF 20 |
119 | .default_value = BRIGHTNESS_77_DEF, | 110 | .default_value = BRIGHTNESS_DEF, |
120 | }, | 111 | }, |
121 | .set = sd_setbrightness, | 112 | .set = sd_setbrightness, |
122 | .get = sd_getbrightness, | 113 | .get = sd_getbrightness, |
@@ -129,8 +120,8 @@ static struct ctrl sd_ctrls_ov772x[] = { | |||
129 | .minimum = 0, | 120 | .minimum = 0, |
130 | .maximum = 255, | 121 | .maximum = 255, |
131 | .step = 1, | 122 | .step = 1, |
132 | #define CONTRAST_77_DEF 37 | 123 | #define CONTRAST_DEF 37 |
133 | .default_value = CONTRAST_77_DEF, | 124 | .default_value = CONTRAST_DEF, |
134 | }, | 125 | }, |
135 | .set = sd_setcontrast, | 126 | .set = sd_setcontrast, |
136 | .get = sd_getcontrast, | 127 | .get = sd_getcontrast, |
@@ -157,8 +148,8 @@ static struct ctrl sd_ctrls_ov772x[] = { | |||
157 | .minimum = 0, | 148 | .minimum = 0, |
158 | .maximum = 255, | 149 | .maximum = 255, |
159 | .step = 1, | 150 | .step = 1, |
160 | #define EXPO_77_DEF 120 | 151 | #define EXPO_DEF 120 |
161 | .default_value = EXPO_77_DEF, | 152 | .default_value = EXPO_DEF, |
162 | }, | 153 | }, |
163 | .set = sd_setexposure, | 154 | .set = sd_setexposure, |
164 | .get = sd_getexposure, | 155 | .get = sd_getexposure, |
@@ -213,13 +204,13 @@ static struct ctrl sd_ctrls_ov772x[] = { | |||
213 | .minimum = 0, | 204 | .minimum = 0, |
214 | .maximum = 1, | 205 | .maximum = 1, |
215 | .step = 1, | 206 | .step = 1, |
216 | #define AUTOGAIN_77_DEF 0 | 207 | #define AUTOGAIN_DEF 0 |
217 | .default_value = AUTOGAIN_77_DEF, | 208 | .default_value = AUTOGAIN_DEF, |
218 | }, | 209 | }, |
219 | .set = sd_setautogain, | 210 | .set = sd_setautogain, |
220 | .get = sd_getautogain, | 211 | .get = sd_getautogain, |
221 | }, | 212 | }, |
222 | #define AWB_77_IDX 8 | 213 | #define AWB_IDX 8 |
223 | { /* 8 */ | 214 | { /* 8 */ |
224 | { | 215 | { |
225 | .id = V4L2_CID_AUTO_WHITE_BALANCE, | 216 | .id = V4L2_CID_AUTO_WHITE_BALANCE, |
@@ -242,8 +233,8 @@ static struct ctrl sd_ctrls_ov772x[] = { | |||
242 | .minimum = 0, | 233 | .minimum = 0, |
243 | .maximum = 63, | 234 | .maximum = 63, |
244 | .step = 1, | 235 | .step = 1, |
245 | #define SHARPNESS_77_DEF 0 | 236 | #define SHARPNESS_DEF 0 |
246 | .default_value = SHARPNESS_77_DEF, | 237 | .default_value = SHARPNESS_DEF, |
247 | }, | 238 | }, |
248 | .set = sd_setsharpness, | 239 | .set = sd_setsharpness, |
249 | .get = sd_getsharpness, | 240 | .get = sd_getsharpness, |
@@ -277,107 +268,6 @@ static struct ctrl sd_ctrls_ov772x[] = { | |||
277 | .get = sd_getvflip, | 268 | .get = sd_getvflip, |
278 | }, | 269 | }, |
279 | }; | 270 | }; |
280 | static struct ctrl sd_ctrls_ov965x[] = { | ||
281 | { /* 0 */ | ||
282 | { | ||
283 | .id = V4L2_CID_BRIGHTNESS, | ||
284 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
285 | .name = "Brightness", | ||
286 | .minimum = 0, | ||
287 | .maximum = 15, | ||
288 | .step = 1, | ||
289 | #define BRIGHTNESS_96_DEF 7 | ||
290 | .default_value = BRIGHTNESS_96_DEF, | ||
291 | }, | ||
292 | .set = sd_setbrightness, | ||
293 | .get = sd_getbrightness, | ||
294 | }, | ||
295 | { /* 1 */ | ||
296 | { | ||
297 | .id = V4L2_CID_CONTRAST, | ||
298 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
299 | .name = "Contrast", | ||
300 | .minimum = 0, | ||
301 | .maximum = 15, | ||
302 | .step = 1, | ||
303 | #define CONTRAST_96_DEF 3 | ||
304 | .default_value = CONTRAST_96_DEF, | ||
305 | }, | ||
306 | .set = sd_setcontrast, | ||
307 | .get = sd_getcontrast, | ||
308 | }, | ||
309 | { /* 2 */ | ||
310 | { | ||
311 | .id = V4L2_CID_AUTOGAIN, | ||
312 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
313 | .name = "Autogain", | ||
314 | .minimum = 0, | ||
315 | .maximum = 1, | ||
316 | .step = 1, | ||
317 | #define AUTOGAIN_96_DEF 1 | ||
318 | .default_value = AUTOGAIN_96_DEF, | ||
319 | }, | ||
320 | .set = sd_setautogain, | ||
321 | .get = sd_getautogain, | ||
322 | }, | ||
323 | #define EXPO_96_IDX 3 | ||
324 | { /* 3 */ | ||
325 | { | ||
326 | .id = V4L2_CID_EXPOSURE, | ||
327 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
328 | .name = "Exposure", | ||
329 | .minimum = 0, | ||
330 | .maximum = 3, | ||
331 | .step = 1, | ||
332 | #define EXPO_96_DEF 0 | ||
333 | .default_value = EXPO_96_DEF, | ||
334 | }, | ||
335 | .set = sd_setexposure, | ||
336 | .get = sd_getexposure, | ||
337 | }, | ||
338 | { /* 4 */ | ||
339 | { | ||
340 | .id = V4L2_CID_SHARPNESS, | ||
341 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
342 | .name = "Sharpness", | ||
343 | .minimum = -1, /* -1 = auto */ | ||
344 | .maximum = 4, | ||
345 | .step = 1, | ||
346 | #define SHARPNESS_96_DEF -1 | ||
347 | .default_value = SHARPNESS_96_DEF, | ||
348 | }, | ||
349 | .set = sd_setsharpness, | ||
350 | .get = sd_getsharpness, | ||
351 | }, | ||
352 | { /* 5 */ | ||
353 | { | ||
354 | .id = V4L2_CID_SATURATION, | ||
355 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
356 | .name = "Saturation", | ||
357 | .minimum = 0, | ||
358 | .maximum = 4, | ||
359 | .step = 1, | ||
360 | #define SATUR_DEF 2 | ||
361 | .default_value = SATUR_DEF, | ||
362 | }, | ||
363 | .set = sd_setsatur, | ||
364 | .get = sd_getsatur, | ||
365 | }, | ||
366 | { | ||
367 | { | ||
368 | .id = V4L2_CID_POWER_LINE_FREQUENCY, | ||
369 | .type = V4L2_CTRL_TYPE_MENU, | ||
370 | .name = "Light frequency filter", | ||
371 | .minimum = 0, | ||
372 | .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */ | ||
373 | .step = 1, | ||
374 | #define FREQ_DEF 0 | ||
375 | .default_value = FREQ_DEF, | ||
376 | }, | ||
377 | .set = sd_setfreq, | ||
378 | .get = sd_getfreq, | ||
379 | }, | ||
380 | }; | ||
381 | 271 | ||
382 | static const struct v4l2_pix_format ov772x_mode[] = { | 272 | static const struct v4l2_pix_format ov772x_mode[] = { |
383 | {320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE, | 273 | {320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE, |
@@ -392,35 +282,21 @@ static const struct v4l2_pix_format ov772x_mode[] = { | |||
392 | .priv = 0}, | 282 | .priv = 0}, |
393 | }; | 283 | }; |
394 | 284 | ||
395 | static const struct v4l2_pix_format ov965x_mode[] = { | 285 | static const u8 qvga_rates[] = {125, 100, 75, 60, 50, 40, 30}; |
396 | {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | 286 | static const u8 vga_rates[] = {60, 50, 40, 30, 15}; |
397 | .bytesperline = 320, | 287 | |
398 | .sizeimage = 320 * 240 * 3 / 8 + 590, | 288 | static const struct framerates ov772x_framerates[] = { |
399 | .colorspace = V4L2_COLORSPACE_JPEG, | 289 | { /* 320x240 */ |
400 | .priv = 4}, | 290 | .rates = qvga_rates, |
401 | {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | 291 | .nrates = ARRAY_SIZE(qvga_rates), |
402 | .bytesperline = 640, | 292 | }, |
403 | .sizeimage = 640 * 480 * 3 / 8 + 590, | 293 | { /* 640x480 */ |
404 | .colorspace = V4L2_COLORSPACE_JPEG, | 294 | .rates = vga_rates, |
405 | .priv = 3}, | 295 | .nrates = ARRAY_SIZE(vga_rates), |
406 | {800, 600, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | 296 | }, |
407 | .bytesperline = 800, | ||
408 | .sizeimage = 800 * 600 * 3 / 8 + 590, | ||
409 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
410 | .priv = 2}, | ||
411 | {1024, 768, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | ||
412 | .bytesperline = 1024, | ||
413 | .sizeimage = 1024 * 768 * 3 / 8 + 590, | ||
414 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
415 | .priv = 1}, | ||
416 | {1280, 1024, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | ||
417 | .bytesperline = 1280, | ||
418 | .sizeimage = 1280 * 1024 * 3 / 8 + 590, | ||
419 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
420 | .priv = 0}, | ||
421 | }; | 297 | }; |
422 | 298 | ||
423 | static const u8 bridge_init_ov772x[][2] = { | 299 | static const u8 bridge_init[][2] = { |
424 | { 0xc2, 0x0c }, | 300 | { 0xc2, 0x0c }, |
425 | { 0x88, 0xf8 }, | 301 | { 0x88, 0xf8 }, |
426 | { 0xc3, 0x69 }, | 302 | { 0xc3, 0x69 }, |
@@ -478,7 +354,7 @@ static const u8 bridge_init_ov772x[][2] = { | |||
478 | { 0xc1, 0x3c }, | 354 | { 0xc1, 0x3c }, |
479 | { 0xc2, 0x0c }, | 355 | { 0xc2, 0x0c }, |
480 | }; | 356 | }; |
481 | static const u8 sensor_init_ov772x[][2] = { | 357 | static const u8 sensor_init[][2] = { |
482 | { 0x12, 0x80 }, | 358 | { 0x12, 0x80 }, |
483 | { 0x11, 0x01 }, | 359 | { 0x11, 0x01 }, |
484 | /*fixme: better have a delay?*/ | 360 | /*fixme: better have a delay?*/ |
@@ -571,7 +447,7 @@ static const u8 sensor_init_ov772x[][2] = { | |||
571 | { 0x8e, 0x00 }, /* De-noise threshold */ | 447 | { 0x8e, 0x00 }, /* De-noise threshold */ |
572 | { 0x0c, 0xd0 } | 448 | { 0x0c, 0xd0 } |
573 | }; | 449 | }; |
574 | static const u8 bridge_start_ov772x_vga[][2] = { | 450 | static const u8 bridge_start_vga[][2] = { |
575 | {0x1c, 0x00}, | 451 | {0x1c, 0x00}, |
576 | {0x1d, 0x40}, | 452 | {0x1d, 0x40}, |
577 | {0x1d, 0x02}, | 453 | {0x1d, 0x02}, |
@@ -582,7 +458,7 @@ static const u8 bridge_start_ov772x_vga[][2] = { | |||
582 | {0xc0, 0x50}, | 458 | {0xc0, 0x50}, |
583 | {0xc1, 0x3c}, | 459 | {0xc1, 0x3c}, |
584 | }; | 460 | }; |
585 | static const u8 sensor_start_ov772x_vga[][2] = { | 461 | static const u8 sensor_start_vga[][2] = { |
586 | {0x12, 0x00}, | 462 | {0x12, 0x00}, |
587 | {0x17, 0x26}, | 463 | {0x17, 0x26}, |
588 | {0x18, 0xa0}, | 464 | {0x18, 0xa0}, |
@@ -592,7 +468,7 @@ static const u8 sensor_start_ov772x_vga[][2] = { | |||
592 | {0x2c, 0xf0}, | 468 | {0x2c, 0xf0}, |
593 | {0x65, 0x20}, | 469 | {0x65, 0x20}, |
594 | }; | 470 | }; |
595 | static const u8 bridge_start_ov772x_qvga[][2] = { | 471 | static const u8 bridge_start_qvga[][2] = { |
596 | {0x1c, 0x00}, | 472 | {0x1c, 0x00}, |
597 | {0x1d, 0x40}, | 473 | {0x1d, 0x40}, |
598 | {0x1d, 0x02}, | 474 | {0x1d, 0x02}, |
@@ -603,7 +479,7 @@ static const u8 bridge_start_ov772x_qvga[][2] = { | |||
603 | {0xc0, 0x28}, | 479 | {0xc0, 0x28}, |
604 | {0xc1, 0x1e}, | 480 | {0xc1, 0x1e}, |
605 | }; | 481 | }; |
606 | static const u8 sensor_start_ov772x_qvga[][2] = { | 482 | static const u8 sensor_start_qvga[][2] = { |
607 | {0x12, 0x40}, | 483 | {0x12, 0x40}, |
608 | {0x17, 0x3f}, | 484 | {0x17, 0x3f}, |
609 | {0x18, 0x50}, | 485 | {0x18, 0x50}, |
@@ -614,571 +490,6 @@ static const u8 sensor_start_ov772x_qvga[][2] = { | |||
614 | {0x65, 0x2f}, | 490 | {0x65, 0x2f}, |
615 | }; | 491 | }; |
616 | 492 | ||
617 | static const u8 bridge_init_ov965x[][2] = { | ||
618 | {0x88, 0xf8}, | ||
619 | {0x89, 0xff}, | ||
620 | {0x76, 0x03}, | ||
621 | {0x92, 0x03}, | ||
622 | {0x95, 0x10}, | ||
623 | {0xe2, 0x00}, | ||
624 | {0xe7, 0x3e}, | ||
625 | {0x8d, 0x1c}, | ||
626 | {0x8e, 0x00}, | ||
627 | {0x8f, 0x00}, | ||
628 | {0x1f, 0x00}, | ||
629 | {0xc3, 0xf9}, | ||
630 | {0x89, 0xff}, | ||
631 | {0x88, 0xf8}, | ||
632 | {0x76, 0x03}, | ||
633 | {0x92, 0x01}, | ||
634 | {0x93, 0x18}, | ||
635 | {0x1c, 0x0a}, | ||
636 | {0x1d, 0x48}, | ||
637 | {0xc0, 0x50}, | ||
638 | {0xc1, 0x3c}, | ||
639 | {0x34, 0x05}, | ||
640 | {0xc2, 0x0c}, | ||
641 | {0xc3, 0xf9}, | ||
642 | {0x34, 0x05}, | ||
643 | {0xe7, 0x2e}, | ||
644 | {0x31, 0xf9}, | ||
645 | {0x35, 0x02}, | ||
646 | {0xd9, 0x10}, | ||
647 | {0x25, 0x42}, | ||
648 | {0x94, 0x11}, | ||
649 | }; | ||
650 | |||
651 | static const u8 sensor_init_ov965x[][2] = { | ||
652 | {0x12, 0x80}, /* com7 - SSCB reset */ | ||
653 | {0x00, 0x00}, /* gain */ | ||
654 | {0x01, 0x80}, /* blue */ | ||
655 | {0x02, 0x80}, /* red */ | ||
656 | {0x03, 0x1b}, /* vref */ | ||
657 | {0x04, 0x03}, /* com1 - exposure low bits */ | ||
658 | {0x0b, 0x57}, /* ver */ | ||
659 | {0x0e, 0x61}, /* com5 */ | ||
660 | {0x0f, 0x42}, /* com6 */ | ||
661 | {0x11, 0x00}, /* clkrc */ | ||
662 | {0x12, 0x02}, /* com7 - 15fps VGA YUYV */ | ||
663 | {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ | ||
664 | {0x14, 0x28}, /* com9 */ | ||
665 | {0x16, 0x24}, /* reg16 */ | ||
666 | {0x17, 0x1d}, /* hstart*/ | ||
667 | {0x18, 0xbd}, /* hstop */ | ||
668 | {0x19, 0x01}, /* vstrt */ | ||
669 | {0x1a, 0x81}, /* vstop*/ | ||
670 | {0x1e, 0x04}, /* mvfp */ | ||
671 | {0x24, 0x3c}, /* aew */ | ||
672 | {0x25, 0x36}, /* aeb */ | ||
673 | {0x26, 0x71}, /* vpt */ | ||
674 | {0x27, 0x08}, /* bbias */ | ||
675 | {0x28, 0x08}, /* gbbias */ | ||
676 | {0x29, 0x15}, /* gr com */ | ||
677 | {0x2a, 0x00}, /* exhch */ | ||
678 | {0x2b, 0x00}, /* exhcl */ | ||
679 | {0x2c, 0x08}, /* rbias */ | ||
680 | {0x32, 0xff}, /* href */ | ||
681 | {0x33, 0x00}, /* chlf */ | ||
682 | {0x34, 0x3f}, /* aref1 */ | ||
683 | {0x35, 0x00}, /* aref2 */ | ||
684 | {0x36, 0xf8}, /* aref3 */ | ||
685 | {0x38, 0x72}, /* adc2 */ | ||
686 | {0x39, 0x57}, /* aref4 */ | ||
687 | {0x3a, 0x80}, /* tslb - yuyv */ | ||
688 | {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */ | ||
689 | {0x3d, 0x99}, /* com13 */ | ||
690 | {0x3f, 0xc1}, /* edge */ | ||
691 | {0x40, 0xc0}, /* com15 */ | ||
692 | {0x41, 0x40}, /* com16 */ | ||
693 | {0x42, 0xc0}, /* com17 */ | ||
694 | {0x43, 0x0a}, /* rsvd */ | ||
695 | {0x44, 0xf0}, | ||
696 | {0x45, 0x46}, | ||
697 | {0x46, 0x62}, | ||
698 | {0x47, 0x2a}, | ||
699 | {0x48, 0x3c}, | ||
700 | {0x4a, 0xfc}, | ||
701 | {0x4b, 0xfc}, | ||
702 | {0x4c, 0x7f}, | ||
703 | {0x4d, 0x7f}, | ||
704 | {0x4e, 0x7f}, | ||
705 | {0x4f, 0x98}, /* matrix */ | ||
706 | {0x50, 0x98}, | ||
707 | {0x51, 0x00}, | ||
708 | {0x52, 0x28}, | ||
709 | {0x53, 0x70}, | ||
710 | {0x54, 0x98}, | ||
711 | {0x58, 0x1a}, /* matrix coef sign */ | ||
712 | {0x59, 0x85}, /* AWB control */ | ||
713 | {0x5a, 0xa9}, | ||
714 | {0x5b, 0x64}, | ||
715 | {0x5c, 0x84}, | ||
716 | {0x5d, 0x53}, | ||
717 | {0x5e, 0x0e}, | ||
718 | {0x5f, 0xf0}, /* AWB blue limit */ | ||
719 | {0x60, 0xf0}, /* AWB red limit */ | ||
720 | {0x61, 0xf0}, /* AWB green limit */ | ||
721 | {0x62, 0x00}, /* lcc1 */ | ||
722 | {0x63, 0x00}, /* lcc2 */ | ||
723 | {0x64, 0x02}, /* lcc3 */ | ||
724 | {0x65, 0x16}, /* lcc4 */ | ||
725 | {0x66, 0x01}, /* lcc5 */ | ||
726 | {0x69, 0x02}, /* hv */ | ||
727 | {0x6b, 0x5a}, /* dbvl */ | ||
728 | {0x6c, 0x04}, | ||
729 | {0x6d, 0x55}, | ||
730 | {0x6e, 0x00}, | ||
731 | {0x6f, 0x9d}, | ||
732 | {0x70, 0x21}, /* dnsth */ | ||
733 | {0x71, 0x78}, | ||
734 | {0x72, 0x00}, /* poidx */ | ||
735 | {0x73, 0x01}, /* pckdv */ | ||
736 | {0x74, 0x3a}, /* xindx */ | ||
737 | {0x75, 0x35}, /* yindx */ | ||
738 | {0x76, 0x01}, | ||
739 | {0x77, 0x02}, | ||
740 | {0x7a, 0x12}, /* gamma curve */ | ||
741 | {0x7b, 0x08}, | ||
742 | {0x7c, 0x16}, | ||
743 | {0x7d, 0x30}, | ||
744 | {0x7e, 0x5e}, | ||
745 | {0x7f, 0x72}, | ||
746 | {0x80, 0x82}, | ||
747 | {0x81, 0x8e}, | ||
748 | {0x82, 0x9a}, | ||
749 | {0x83, 0xa4}, | ||
750 | {0x84, 0xac}, | ||
751 | {0x85, 0xb8}, | ||
752 | {0x86, 0xc3}, | ||
753 | {0x87, 0xd6}, | ||
754 | {0x88, 0xe6}, | ||
755 | {0x89, 0xf2}, | ||
756 | {0x8a, 0x03}, | ||
757 | {0x8c, 0x89}, /* com19 */ | ||
758 | {0x14, 0x28}, /* com9 */ | ||
759 | {0x90, 0x7d}, | ||
760 | {0x91, 0x7b}, | ||
761 | {0x9d, 0x03}, /* lcc6 */ | ||
762 | {0x9e, 0x04}, /* lcc7 */ | ||
763 | {0x9f, 0x7a}, | ||
764 | {0xa0, 0x79}, | ||
765 | {0xa1, 0x40}, /* aechm */ | ||
766 | {0xa4, 0x50}, /* com21 */ | ||
767 | {0xa5, 0x68}, /* com26 */ | ||
768 | {0xa6, 0x4a}, /* AWB green */ | ||
769 | {0xa8, 0xc1}, /* refa8 */ | ||
770 | {0xa9, 0xef}, /* refa9 */ | ||
771 | {0xaa, 0x92}, | ||
772 | {0xab, 0x04}, | ||
773 | {0xac, 0x80}, /* black level control */ | ||
774 | {0xad, 0x80}, | ||
775 | {0xae, 0x80}, | ||
776 | {0xaf, 0x80}, | ||
777 | {0xb2, 0xf2}, | ||
778 | {0xb3, 0x20}, | ||
779 | {0xb4, 0x20}, /* ctrlb4 */ | ||
780 | {0xb5, 0x00}, | ||
781 | {0xb6, 0xaf}, | ||
782 | {0xbb, 0xae}, | ||
783 | {0xbc, 0x7f}, /* ADC channel offsets */ | ||
784 | {0xdb, 0x7f}, | ||
785 | {0xbe, 0x7f}, | ||
786 | {0xbf, 0x7f}, | ||
787 | {0xc0, 0xe2}, | ||
788 | {0xc1, 0xc0}, | ||
789 | {0xc2, 0x01}, | ||
790 | {0xc3, 0x4e}, | ||
791 | {0xc6, 0x85}, | ||
792 | {0xc7, 0x80}, /* com24 */ | ||
793 | {0xc9, 0xe0}, | ||
794 | {0xca, 0xe8}, | ||
795 | {0xcb, 0xf0}, | ||
796 | {0xcc, 0xd8}, | ||
797 | {0xcd, 0xf1}, | ||
798 | {0x4f, 0x98}, /* matrix */ | ||
799 | {0x50, 0x98}, | ||
800 | {0x51, 0x00}, | ||
801 | {0x52, 0x28}, | ||
802 | {0x53, 0x70}, | ||
803 | {0x54, 0x98}, | ||
804 | {0x58, 0x1a}, | ||
805 | {0xff, 0x41}, /* read 41, write ff 00 */ | ||
806 | {0x41, 0x40}, /* com16 */ | ||
807 | |||
808 | {0xc5, 0x03}, /* 60 Hz banding filter */ | ||
809 | {0x6a, 0x02}, /* 50 Hz banding filter */ | ||
810 | |||
811 | {0x12, 0x62}, /* com7 - 30fps VGA YUV */ | ||
812 | {0x36, 0xfa}, /* aref3 */ | ||
813 | {0x69, 0x0a}, /* hv */ | ||
814 | {0x8c, 0x89}, /* com22 */ | ||
815 | {0x14, 0x28}, /* com9 */ | ||
816 | {0x3e, 0x0c}, | ||
817 | {0x41, 0x40}, /* com16 */ | ||
818 | {0x72, 0x00}, | ||
819 | {0x73, 0x00}, | ||
820 | {0x74, 0x3a}, | ||
821 | {0x75, 0x35}, | ||
822 | {0x76, 0x01}, | ||
823 | {0xc7, 0x80}, | ||
824 | {0x03, 0x12}, /* vref */ | ||
825 | {0x17, 0x16}, /* hstart */ | ||
826 | {0x18, 0x02}, /* hstop */ | ||
827 | {0x19, 0x01}, /* vstrt */ | ||
828 | {0x1a, 0x3d}, /* vstop */ | ||
829 | {0x32, 0xff}, /* href */ | ||
830 | {0xc0, 0xaa}, | ||
831 | }; | ||
832 | |||
833 | static const u8 bridge_init_ov965x_2[][2] = { | ||
834 | {0x94, 0xaa}, | ||
835 | {0xf1, 0x60}, | ||
836 | {0xe5, 0x04}, | ||
837 | {0xc0, 0x50}, | ||
838 | {0xc1, 0x3c}, | ||
839 | {0x8c, 0x00}, | ||
840 | {0x8d, 0x1c}, | ||
841 | {0x34, 0x05}, | ||
842 | |||
843 | {0xc2, 0x0c}, | ||
844 | {0xc3, 0xf9}, | ||
845 | {0xda, 0x01}, | ||
846 | {0x50, 0x00}, | ||
847 | {0x51, 0xa0}, | ||
848 | {0x52, 0x3c}, | ||
849 | {0x53, 0x00}, | ||
850 | {0x54, 0x00}, | ||
851 | {0x55, 0x00}, | ||
852 | {0x57, 0x00}, | ||
853 | {0x5c, 0x00}, | ||
854 | {0x5a, 0xa0}, | ||
855 | {0x5b, 0x78}, | ||
856 | {0x35, 0x02}, | ||
857 | {0xd9, 0x10}, | ||
858 | {0x94, 0x11}, | ||
859 | }; | ||
860 | |||
861 | static const u8 sensor_init_ov965x_2[][2] = { | ||
862 | {0x3b, 0xc4}, | ||
863 | {0x1e, 0x04}, /* mvfp */ | ||
864 | {0x13, 0xe0}, /* com8 */ | ||
865 | {0x00, 0x00}, /* gain */ | ||
866 | {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ | ||
867 | {0x11, 0x03}, /* clkrc */ | ||
868 | {0x6b, 0x5a}, /* dblv */ | ||
869 | {0x6a, 0x05}, | ||
870 | {0xc5, 0x07}, | ||
871 | {0xa2, 0x4b}, | ||
872 | {0xa3, 0x3e}, | ||
873 | {0x2d, 0x00}, | ||
874 | {0xff, 0x42}, /* read 42, write ff 00 */ | ||
875 | {0x42, 0xc0}, /* com17 */ | ||
876 | {0x2d, 0x00}, | ||
877 | {0xff, 0x42}, /* read 42, write ff 00 */ | ||
878 | {0x42, 0xc1}, /* com17 */ | ||
879 | /* sharpness */ | ||
880 | {0x3f, 0x01}, | ||
881 | {0xff, 0x42}, /* read 42, write ff 00 */ | ||
882 | {0x42, 0xc1}, /* com17 */ | ||
883 | /* saturation */ | ||
884 | {0x4f, 0x98}, /* matrix */ | ||
885 | {0x50, 0x98}, | ||
886 | {0x51, 0x00}, | ||
887 | {0x52, 0x28}, | ||
888 | {0x53, 0x70}, | ||
889 | {0x54, 0x98}, | ||
890 | {0x58, 0x1a}, | ||
891 | {0xff, 0x41}, /* read 41, write ff 00 */ | ||
892 | {0x41, 0x40}, /* com16 */ | ||
893 | /* contrast */ | ||
894 | {0x56, 0x40}, | ||
895 | /* brightness */ | ||
896 | {0x55, 0x8f}, | ||
897 | /* expo */ | ||
898 | {0x10, 0x25}, /* aech - exposure high bits */ | ||
899 | {0xff, 0x13}, /* read 13, write ff 00 */ | ||
900 | {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ | ||
901 | }; | ||
902 | |||
903 | static const u8 sensor_start_ov965x_1_vga[][2] = { /* same for qvga */ | ||
904 | {0x12, 0x62}, /* com7 - 30fps VGA YUV */ | ||
905 | {0x36, 0xfa}, /* aref3 */ | ||
906 | {0x69, 0x0a}, /* hv */ | ||
907 | {0x8c, 0x89}, /* com22 */ | ||
908 | {0x14, 0x28}, /* com9 */ | ||
909 | {0x3e, 0x0c}, /* com14 */ | ||
910 | {0x41, 0x40}, /* com16 */ | ||
911 | {0x72, 0x00}, | ||
912 | {0x73, 0x00}, | ||
913 | {0x74, 0x3a}, | ||
914 | {0x75, 0x35}, | ||
915 | {0x76, 0x01}, | ||
916 | {0xc7, 0x80}, /* com24 */ | ||
917 | {0x03, 0x12}, /* vref */ | ||
918 | {0x17, 0x16}, /* hstart */ | ||
919 | {0x18, 0x02}, /* hstop */ | ||
920 | {0x19, 0x01}, /* vstrt */ | ||
921 | {0x1a, 0x3d}, /* vstop */ | ||
922 | {0x32, 0xff}, /* href */ | ||
923 | {0xc0, 0xaa}, | ||
924 | }; | ||
925 | |||
926 | static const u8 sensor_start_ov965x_1_svga[][2] = { | ||
927 | {0x12, 0x02}, /* com7 - YUYV - VGA 15 full resolution */ | ||
928 | {0x36, 0xf8}, /* aref3 */ | ||
929 | {0x69, 0x02}, /* hv */ | ||
930 | {0x8c, 0x0d}, /* com22 */ | ||
931 | {0x3e, 0x0c}, /* com14 */ | ||
932 | {0x41, 0x40}, /* com16 */ | ||
933 | {0x72, 0x00}, | ||
934 | {0x73, 0x01}, | ||
935 | {0x74, 0x3a}, | ||
936 | {0x75, 0x35}, | ||
937 | {0x76, 0x01}, | ||
938 | {0xc7, 0x80}, /* com24 */ | ||
939 | {0x03, 0x1b}, /* vref */ | ||
940 | {0x17, 0x1d}, /* hstart */ | ||
941 | {0x18, 0xbd}, /* hstop */ | ||
942 | {0x19, 0x01}, /* vstrt */ | ||
943 | {0x1a, 0x81}, /* vstop */ | ||
944 | {0x32, 0xff}, /* href */ | ||
945 | {0xc0, 0xe2}, | ||
946 | }; | ||
947 | |||
948 | static const u8 sensor_start_ov965x_1_xga[][2] = { | ||
949 | {0x12, 0x02}, /* com7 */ | ||
950 | {0x36, 0xf8}, /* aref3 */ | ||
951 | {0x69, 0x02}, /* hv */ | ||
952 | {0x8c, 0x89}, /* com22 */ | ||
953 | {0x14, 0x28}, /* com9 */ | ||
954 | {0x3e, 0x0c}, /* com14 */ | ||
955 | {0x41, 0x40}, /* com16 */ | ||
956 | {0x72, 0x00}, | ||
957 | {0x73, 0x01}, | ||
958 | {0x74, 0x3a}, | ||
959 | {0x75, 0x35}, | ||
960 | {0x76, 0x01}, | ||
961 | {0xc7, 0x80}, /* com24 */ | ||
962 | {0x03, 0x1b}, /* vref */ | ||
963 | {0x17, 0x1d}, /* hstart */ | ||
964 | {0x18, 0xbd}, /* hstop */ | ||
965 | {0x19, 0x01}, /* vstrt */ | ||
966 | {0x1a, 0x81}, /* vstop */ | ||
967 | {0x32, 0xff}, /* href */ | ||
968 | {0xc0, 0xe2}, | ||
969 | }; | ||
970 | |||
971 | static const u8 sensor_start_ov965x_1_sxga[][2] = { | ||
972 | {0x12, 0x02}, /* com7 */ | ||
973 | {0x36, 0xf8}, /* aref3 */ | ||
974 | {0x69, 0x02}, /* hv */ | ||
975 | {0x8c, 0x89}, /* com22 */ | ||
976 | {0x14, 0x28}, /* com9 */ | ||
977 | {0x3e, 0x0c}, /* com14 */ | ||
978 | {0x41, 0x40}, /* com16 */ | ||
979 | {0x72, 0x00}, | ||
980 | {0x73, 0x01}, | ||
981 | {0x74, 0x3a}, | ||
982 | {0x75, 0x35}, | ||
983 | {0x76, 0x01}, | ||
984 | {0xc7, 0x80}, /* com24 */ | ||
985 | {0x03, 0x1b}, /* vref */ | ||
986 | {0x17, 0x1d}, /* hstart */ | ||
987 | {0x18, 0x02}, /* hstop */ | ||
988 | {0x19, 0x01}, /* vstrt */ | ||
989 | {0x1a, 0x81}, /* vstop */ | ||
990 | {0x32, 0xff}, /* href */ | ||
991 | {0xc0, 0xe2}, | ||
992 | }; | ||
993 | |||
994 | static const u8 bridge_start_ov965x_qvga[][2] = { | ||
995 | {0x94, 0xaa}, | ||
996 | {0xf1, 0x60}, | ||
997 | {0xe5, 0x04}, | ||
998 | {0xc0, 0x50}, | ||
999 | {0xc1, 0x3c}, | ||
1000 | {0x8c, 0x00}, | ||
1001 | {0x8d, 0x1c}, | ||
1002 | {0x34, 0x05}, | ||
1003 | |||
1004 | {0xc2, 0x4c}, | ||
1005 | {0xc3, 0xf9}, | ||
1006 | {0xda, 0x00}, | ||
1007 | {0x50, 0x00}, | ||
1008 | {0x51, 0xa0}, | ||
1009 | {0x52, 0x78}, | ||
1010 | {0x53, 0x00}, | ||
1011 | {0x54, 0x00}, | ||
1012 | {0x55, 0x00}, | ||
1013 | {0x57, 0x00}, | ||
1014 | {0x5c, 0x00}, | ||
1015 | {0x5a, 0x50}, | ||
1016 | {0x5b, 0x3c}, | ||
1017 | {0x35, 0x02}, | ||
1018 | {0xd9, 0x10}, | ||
1019 | {0x94, 0x11}, | ||
1020 | }; | ||
1021 | |||
1022 | static const u8 bridge_start_ov965x_vga[][2] = { | ||
1023 | {0x94, 0xaa}, | ||
1024 | {0xf1, 0x60}, | ||
1025 | {0xe5, 0x04}, | ||
1026 | {0xc0, 0x50}, | ||
1027 | {0xc1, 0x3c}, | ||
1028 | {0x8c, 0x00}, | ||
1029 | {0x8d, 0x1c}, | ||
1030 | {0x34, 0x05}, | ||
1031 | {0xc2, 0x0c}, | ||
1032 | {0xc3, 0xf9}, | ||
1033 | {0xda, 0x01}, | ||
1034 | {0x50, 0x00}, | ||
1035 | {0x51, 0xa0}, | ||
1036 | {0x52, 0x3c}, | ||
1037 | {0x53, 0x00}, | ||
1038 | {0x54, 0x00}, | ||
1039 | {0x55, 0x00}, | ||
1040 | {0x57, 0x00}, | ||
1041 | {0x5c, 0x00}, | ||
1042 | {0x5a, 0xa0}, | ||
1043 | {0x5b, 0x78}, | ||
1044 | {0x35, 0x02}, | ||
1045 | {0xd9, 0x10}, | ||
1046 | {0x94, 0x11}, | ||
1047 | }; | ||
1048 | |||
1049 | static const u8 bridge_start_ov965x_svga[][2] = { | ||
1050 | {0x94, 0xaa}, | ||
1051 | {0xf1, 0x60}, | ||
1052 | {0xe5, 0x04}, | ||
1053 | {0xc0, 0xa0}, | ||
1054 | {0xc1, 0x80}, | ||
1055 | {0x8c, 0x00}, | ||
1056 | {0x8d, 0x1c}, | ||
1057 | {0x34, 0x05}, | ||
1058 | {0xc2, 0x4c}, | ||
1059 | {0xc3, 0xf9}, | ||
1060 | {0x50, 0x00}, | ||
1061 | {0x51, 0x40}, | ||
1062 | {0x52, 0x00}, | ||
1063 | {0x53, 0x00}, | ||
1064 | {0x54, 0x00}, | ||
1065 | {0x55, 0x88}, | ||
1066 | {0x57, 0x00}, | ||
1067 | {0x5c, 0x00}, | ||
1068 | {0x5a, 0xc8}, | ||
1069 | {0x5b, 0x96}, | ||
1070 | {0x35, 0x02}, | ||
1071 | {0xd9, 0x10}, | ||
1072 | {0xda, 0x00}, | ||
1073 | {0x94, 0x11}, | ||
1074 | }; | ||
1075 | |||
1076 | static const u8 bridge_start_ov965x_xga[][2] = { | ||
1077 | {0x94, 0xaa}, | ||
1078 | {0xf1, 0x60}, | ||
1079 | {0xe5, 0x04}, | ||
1080 | {0xc0, 0xa0}, | ||
1081 | {0xc1, 0x80}, | ||
1082 | {0x8c, 0x00}, | ||
1083 | {0x8d, 0x1c}, | ||
1084 | {0x34, 0x05}, | ||
1085 | {0xc2, 0x4c}, | ||
1086 | {0xc3, 0xf9}, | ||
1087 | {0x50, 0x00}, | ||
1088 | {0x51, 0x40}, | ||
1089 | {0x52, 0x00}, | ||
1090 | {0x53, 0x00}, | ||
1091 | {0x54, 0x00}, | ||
1092 | {0x55, 0x88}, | ||
1093 | {0x57, 0x00}, | ||
1094 | {0x5c, 0x01}, | ||
1095 | {0x5a, 0x00}, | ||
1096 | {0x5b, 0xc0}, | ||
1097 | {0x35, 0x02}, | ||
1098 | {0xd9, 0x10}, | ||
1099 | {0xda, 0x01}, | ||
1100 | {0x94, 0x11}, | ||
1101 | }; | ||
1102 | |||
1103 | static const u8 bridge_start_ov965x_sxga[][2] = { | ||
1104 | {0x94, 0xaa}, | ||
1105 | {0xf1, 0x60}, | ||
1106 | {0xe5, 0x04}, | ||
1107 | {0xc0, 0xa0}, | ||
1108 | {0xc1, 0x80}, | ||
1109 | {0x8c, 0x00}, | ||
1110 | {0x8d, 0x1c}, | ||
1111 | {0x34, 0x05}, | ||
1112 | {0xc2, 0x0c}, | ||
1113 | {0xc3, 0xf9}, | ||
1114 | {0xda, 0x00}, | ||
1115 | {0x35, 0x02}, | ||
1116 | {0xd9, 0x10}, | ||
1117 | {0x94, 0x11}, | ||
1118 | }; | ||
1119 | |||
1120 | static const u8 sensor_start_ov965x_2_qvga[][2] = { | ||
1121 | {0x3b, 0xe4}, /* com11 - night mode 1/4 frame rate */ | ||
1122 | {0x1e, 0x04}, /* mvfp */ | ||
1123 | {0x13, 0xe0}, /* com8 */ | ||
1124 | {0x00, 0x00}, | ||
1125 | {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ | ||
1126 | {0x11, 0x01}, /* clkrc */ | ||
1127 | {0x6b, 0x5a}, /* dblv */ | ||
1128 | {0x6a, 0x02}, /* 50 Hz banding filter */ | ||
1129 | {0xc5, 0x03}, /* 60 Hz banding filter */ | ||
1130 | {0xa2, 0x96}, /* bd50 */ | ||
1131 | {0xa3, 0x7d}, /* bd60 */ | ||
1132 | |||
1133 | {0xff, 0x13}, /* read 13, write ff 00 */ | ||
1134 | {0x13, 0xe7}, | ||
1135 | {0x3a, 0x80}, /* tslb - yuyv */ | ||
1136 | }; | ||
1137 | |||
1138 | static const u8 sensor_start_ov965x_2_vga[][2] = { | ||
1139 | {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */ | ||
1140 | {0x1e, 0x04}, /* mvfp */ | ||
1141 | {0x13, 0xe0}, /* com8 */ | ||
1142 | {0x00, 0x00}, | ||
1143 | {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ | ||
1144 | {0x11, 0x03}, /* clkrc */ | ||
1145 | {0x6b, 0x5a}, /* dblv */ | ||
1146 | {0x6a, 0x05}, /* 50 Hz banding filter */ | ||
1147 | {0xc5, 0x07}, /* 60 Hz banding filter */ | ||
1148 | {0xa2, 0x4b}, /* bd50 */ | ||
1149 | {0xa3, 0x3e}, /* bd60 */ | ||
1150 | |||
1151 | {0x2d, 0x00}, /* advfl */ | ||
1152 | }; | ||
1153 | |||
1154 | static const u8 sensor_start_ov965x_2_svga[][2] = { /* same for xga */ | ||
1155 | {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */ | ||
1156 | {0x1e, 0x04}, /* mvfp */ | ||
1157 | {0x13, 0xe0}, /* com8 */ | ||
1158 | {0x00, 0x00}, | ||
1159 | {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ | ||
1160 | {0x11, 0x01}, /* clkrc */ | ||
1161 | {0x6b, 0x5a}, /* dblv */ | ||
1162 | {0x6a, 0x0c}, /* 50 Hz banding filter */ | ||
1163 | {0xc5, 0x0f}, /* 60 Hz banding filter */ | ||
1164 | {0xa2, 0x4e}, /* bd50 */ | ||
1165 | {0xa3, 0x41}, /* bd60 */ | ||
1166 | }; | ||
1167 | |||
1168 | static const u8 sensor_start_ov965x_2_sxga[][2] = { | ||
1169 | {0x13, 0xe0}, /* com8 */ | ||
1170 | {0x00, 0x00}, | ||
1171 | {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ | ||
1172 | {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */ | ||
1173 | {0x1e, 0x04}, /* mvfp */ | ||
1174 | {0x11, 0x01}, /* clkrc */ | ||
1175 | {0x6b, 0x5a}, /* dblv */ | ||
1176 | {0x6a, 0x0c}, /* 50 Hz banding filter */ | ||
1177 | {0xc5, 0x0f}, /* 60 Hz banding filter */ | ||
1178 | {0xa2, 0x4e}, /* bd50 */ | ||
1179 | {0xa3, 0x41}, /* bd60 */ | ||
1180 | }; | ||
1181 | |||
1182 | static void ov534_reg_write(struct gspca_dev *gspca_dev, u16 reg, u8 val) | 493 | static void ov534_reg_write(struct gspca_dev *gspca_dev, u16 reg, u8 val) |
1183 | { | 494 | { |
1184 | struct usb_device *udev = gspca_dev->dev; | 495 | struct usb_device *udev = gspca_dev->dev; |
@@ -1360,14 +671,14 @@ static void set_frame_rate(struct gspca_dev *gspca_dev) | |||
1360 | PDEBUG(D_PROBE, "frame_rate: %d", r->fps); | 671 | PDEBUG(D_PROBE, "frame_rate: %d", r->fps); |
1361 | } | 672 | } |
1362 | 673 | ||
1363 | static void setbrightness_77(struct gspca_dev *gspca_dev) | 674 | static void setbrightness(struct gspca_dev *gspca_dev) |
1364 | { | 675 | { |
1365 | struct sd *sd = (struct sd *) gspca_dev; | 676 | struct sd *sd = (struct sd *) gspca_dev; |
1366 | 677 | ||
1367 | sccb_reg_write(gspca_dev, 0x9B, sd->brightness); | 678 | sccb_reg_write(gspca_dev, 0x9B, sd->brightness); |
1368 | } | 679 | } |
1369 | 680 | ||
1370 | static void setcontrast_77(struct gspca_dev *gspca_dev) | 681 | static void setcontrast(struct gspca_dev *gspca_dev) |
1371 | { | 682 | { |
1372 | struct sd *sd = (struct sd *) gspca_dev; | 683 | struct sd *sd = (struct sd *) gspca_dev; |
1373 | 684 | ||
@@ -1401,7 +712,7 @@ static void setgain(struct gspca_dev *gspca_dev) | |||
1401 | sccb_reg_write(gspca_dev, 0x00, val); | 712 | sccb_reg_write(gspca_dev, 0x00, val); |
1402 | } | 713 | } |
1403 | 714 | ||
1404 | static void setexposure_77(struct gspca_dev *gspca_dev) | 715 | static void setexposure(struct gspca_dev *gspca_dev) |
1405 | { | 716 | { |
1406 | struct sd *sd = (struct sd *) gspca_dev; | 717 | struct sd *sd = (struct sd *) gspca_dev; |
1407 | u8 val; | 718 | u8 val; |
@@ -1432,7 +743,7 @@ static void sethue(struct gspca_dev *gspca_dev) | |||
1432 | sccb_reg_write(gspca_dev, 0x01, sd->hue); | 743 | sccb_reg_write(gspca_dev, 0x01, sd->hue); |
1433 | } | 744 | } |
1434 | 745 | ||
1435 | static void setautogain_77(struct gspca_dev *gspca_dev) | 746 | static void setautogain(struct gspca_dev *gspca_dev) |
1436 | { | 747 | { |
1437 | struct sd *sd = (struct sd *) gspca_dev; | 748 | struct sd *sd = (struct sd *) gspca_dev; |
1438 | 749 | ||
@@ -1457,7 +768,7 @@ static void setawb(struct gspca_dev *gspca_dev) | |||
1457 | sccb_reg_write(gspca_dev, 0x63, 0xaa); /* AWB off */ | 768 | sccb_reg_write(gspca_dev, 0x63, 0xaa); /* AWB off */ |
1458 | } | 769 | } |
1459 | 770 | ||
1460 | static void setsharpness_77(struct gspca_dev *gspca_dev) | 771 | static void setsharpness(struct gspca_dev *gspca_dev) |
1461 | { | 772 | { |
1462 | struct sd *sd = (struct sd *) gspca_dev; | 773 | struct sd *sd = (struct sd *) gspca_dev; |
1463 | u8 val; | 774 | u8 val; |
@@ -1491,132 +802,6 @@ static void setvflip(struct gspca_dev *gspca_dev) | |||
1491 | sccb_reg_read(gspca_dev, 0x0c) & 0x7f); | 802 | sccb_reg_read(gspca_dev, 0x0c) & 0x7f); |
1492 | } | 803 | } |
1493 | 804 | ||
1494 | /* ov965x specific controls */ | ||
1495 | static void setbrightness_96(struct gspca_dev *gspca_dev) | ||
1496 | { | ||
1497 | struct sd *sd = (struct sd *) gspca_dev; | ||
1498 | u8 val; | ||
1499 | |||
1500 | val = sd->brightness; | ||
1501 | if (val < 8) | ||
1502 | val = 15 - val; /* f .. 8 */ | ||
1503 | else | ||
1504 | val = val - 8; /* 0 .. 7 */ | ||
1505 | sccb_reg_write(gspca_dev, 0x55, /* brtn - brightness adjustment */ | ||
1506 | 0x0f | (val << 4)); | ||
1507 | } | ||
1508 | |||
1509 | static void setcontrast_96(struct gspca_dev *gspca_dev) | ||
1510 | { | ||
1511 | struct sd *sd = (struct sd *) gspca_dev; | ||
1512 | |||
1513 | sccb_reg_write(gspca_dev, 0x56, /* cnst1 - contrast 1 ctrl coeff */ | ||
1514 | sd->contrast << 4); | ||
1515 | } | ||
1516 | |||
1517 | static void setexposure_96(struct gspca_dev *gspca_dev) | ||
1518 | { | ||
1519 | struct sd *sd = (struct sd *) gspca_dev; | ||
1520 | u8 val; | ||
1521 | static const u8 expo[4] = {0x00, 0x25, 0x38, 0x5e}; | ||
1522 | |||
1523 | sccb_reg_write(gspca_dev, 0x10, /* aec[9:2] */ | ||
1524 | expo[sd->exposure]); | ||
1525 | val = sccb_reg_read(gspca_dev, 0x13); /* com8 */ | ||
1526 | sccb_reg_write(gspca_dev, 0xff, 0x00); | ||
1527 | sccb_reg_write(gspca_dev, 0x13, val); | ||
1528 | val = sccb_reg_read(gspca_dev, 0xa1); /* aech */ | ||
1529 | sccb_reg_write(gspca_dev, 0xff, 0x00); | ||
1530 | sccb_reg_write(gspca_dev, 0xa1, val & 0xe0); /* aec[15:10] = 0 */ | ||
1531 | } | ||
1532 | |||
1533 | static void setsharpness_96(struct gspca_dev *gspca_dev) | ||
1534 | { | ||
1535 | struct sd *sd = (struct sd *) gspca_dev; | ||
1536 | s8 val; | ||
1537 | |||
1538 | val = sd->sharpness; | ||
1539 | if (val < 0) { /* auto */ | ||
1540 | val = sccb_reg_read(gspca_dev, 0x42); /* com17 */ | ||
1541 | sccb_reg_write(gspca_dev, 0xff, 0x00); | ||
1542 | sccb_reg_write(gspca_dev, 0x42, val | 0x40); | ||
1543 | /* Edge enhancement strength auto adjust */ | ||
1544 | return; | ||
1545 | } | ||
1546 | if (val != 0) | ||
1547 | val = 1 << (val - 1); | ||
1548 | sccb_reg_write(gspca_dev, 0x3f, /* edge - edge enhance. factor */ | ||
1549 | val); | ||
1550 | val = sccb_reg_read(gspca_dev, 0x42); /* com17 */ | ||
1551 | sccb_reg_write(gspca_dev, 0xff, 0x00); | ||
1552 | sccb_reg_write(gspca_dev, 0x42, val & 0xbf); | ||
1553 | } | ||
1554 | |||
1555 | static void setautogain_96(struct gspca_dev *gspca_dev) | ||
1556 | { | ||
1557 | struct sd *sd = (struct sd *) gspca_dev; | ||
1558 | u8 val; | ||
1559 | |||
1560 | /*fixme: should adjust agc/awb/aec by different controls */ | ||
1561 | val = sd->autogain; | ||
1562 | val = sccb_reg_read(gspca_dev, 0x13); /* com8 */ | ||
1563 | sccb_reg_write(gspca_dev, 0xff, 0x00); | ||
1564 | if (sd->autogain) | ||
1565 | val |= 0x05; /* agc & aec */ | ||
1566 | else | ||
1567 | val &= 0xfa; | ||
1568 | sccb_reg_write(gspca_dev, 0x13, val); | ||
1569 | } | ||
1570 | |||
1571 | static void setsatur(struct gspca_dev *gspca_dev) | ||
1572 | { | ||
1573 | struct sd *sd = (struct sd *) gspca_dev; | ||
1574 | u8 val1, val2, val3; | ||
1575 | static const u8 matrix[5][2] = { | ||
1576 | {0x14, 0x38}, | ||
1577 | {0x1e, 0x54}, | ||
1578 | {0x28, 0x70}, | ||
1579 | {0x32, 0x8c}, | ||
1580 | {0x48, 0x90} | ||
1581 | }; | ||
1582 | |||
1583 | val1 = matrix[sd->satur][0]; | ||
1584 | val2 = matrix[sd->satur][1]; | ||
1585 | val3 = val1 + val2; | ||
1586 | sccb_reg_write(gspca_dev, 0x4f, val3); /* matrix coeff */ | ||
1587 | sccb_reg_write(gspca_dev, 0x50, val3); | ||
1588 | sccb_reg_write(gspca_dev, 0x51, 0x00); | ||
1589 | sccb_reg_write(gspca_dev, 0x52, val1); | ||
1590 | sccb_reg_write(gspca_dev, 0x53, val2); | ||
1591 | sccb_reg_write(gspca_dev, 0x54, val3); | ||
1592 | sccb_reg_write(gspca_dev, 0x58, 0x1a); /* mtxs - coeff signs */ | ||
1593 | val1 = sccb_reg_read(gspca_dev, 0x41); /* com16 */ | ||
1594 | sccb_reg_write(gspca_dev, 0xff, 0x00); | ||
1595 | sccb_reg_write(gspca_dev, 0x41, val1); | ||
1596 | } | ||
1597 | |||
1598 | static void setfreq(struct gspca_dev *gspca_dev) | ||
1599 | { | ||
1600 | struct sd *sd = (struct sd *) gspca_dev; | ||
1601 | u8 val; | ||
1602 | |||
1603 | val = sccb_reg_read(gspca_dev, 0x13); /* com8 */ | ||
1604 | sccb_reg_write(gspca_dev, 0xff, 0x00); | ||
1605 | if (sd->lightfreq == 0) { | ||
1606 | sccb_reg_write(gspca_dev, 0x13, val & 0xdf); | ||
1607 | return; | ||
1608 | } | ||
1609 | sccb_reg_write(gspca_dev, 0x13, val | 0x20); | ||
1610 | |||
1611 | val = sccb_reg_read(gspca_dev, 0x42); /* com17 */ | ||
1612 | sccb_reg_write(gspca_dev, 0xff, 0x00); | ||
1613 | if (sd->lightfreq == 1) | ||
1614 | val |= 0x01; | ||
1615 | else | ||
1616 | val &= 0xfe; | ||
1617 | sccb_reg_write(gspca_dev, 0x42, val); | ||
1618 | } | ||
1619 | |||
1620 | /* this function is called at probe time */ | 805 | /* this function is called at probe time */ |
1621 | static int sd_config(struct gspca_dev *gspca_dev, | 806 | static int sd_config(struct gspca_dev *gspca_dev, |
1622 | const struct usb_device_id *id) | 807 | const struct usb_device_id *id) |
@@ -1624,77 +809,50 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
1624 | struct sd *sd = (struct sd *) gspca_dev; | 809 | struct sd *sd = (struct sd *) gspca_dev; |
1625 | struct cam *cam; | 810 | struct cam *cam; |
1626 | 811 | ||
1627 | sd->sensor = id->driver_info; | ||
1628 | |||
1629 | cam = &gspca_dev->cam; | 812 | cam = &gspca_dev->cam; |
1630 | 813 | ||
1631 | if (sd->sensor == SENSOR_OV772X) { | 814 | cam->cam_mode = ov772x_mode; |
1632 | cam->cam_mode = ov772x_mode; | 815 | cam->nmodes = ARRAY_SIZE(ov772x_mode); |
1633 | cam->nmodes = ARRAY_SIZE(ov772x_mode); | 816 | cam->mode_framerates = ov772x_framerates; |
1634 | 817 | ||
1635 | cam->bulk = 1; | 818 | cam->bulk = 1; |
1636 | cam->bulk_size = 16384; | 819 | cam->bulk_size = 16384; |
1637 | cam->bulk_nurbs = 2; | 820 | cam->bulk_nurbs = 2; |
1638 | } else { /* ov965x */ | ||
1639 | cam->cam_mode = ov965x_mode; | ||
1640 | cam->nmodes = ARRAY_SIZE(ov965x_mode); | ||
1641 | } | ||
1642 | 821 | ||
1643 | sd->frame_rate = 30; | 822 | sd->frame_rate = 30; |
1644 | 823 | ||
1645 | if (sd->sensor == SENSOR_OV772X) { | 824 | sd->brightness = BRIGHTNESS_DEF; |
1646 | sd->brightness = BRIGHTNESS_77_DEF; | 825 | sd->contrast = CONTRAST_DEF; |
1647 | sd->contrast = CONTRAST_77_DEF; | 826 | sd->gain = GAIN_DEF; |
1648 | sd->gain = GAIN_DEF; | 827 | sd->exposure = EXPO_DEF; |
1649 | sd->exposure = EXPO_77_DEF; | 828 | sd->redblc = RED_BALANCE_DEF; |
1650 | sd->redblc = RED_BALANCE_DEF; | 829 | sd->blueblc = BLUE_BALANCE_DEF; |
1651 | sd->blueblc = BLUE_BALANCE_DEF; | 830 | sd->hue = HUE_DEF; |
1652 | sd->hue = HUE_DEF; | 831 | #if AUTOGAIN_DEF != 0 |
1653 | #if AUTOGAIN_77_DEF != 0 | 832 | sd->autogain = AUTOGAIN_DEF; |
1654 | sd->autogain = AUTOGAIN_77_DEF; | ||
1655 | #else | 833 | #else |
1656 | gspca_dev->ctrl_inac |= (1 << AWB_77_IDX); | 834 | gspca_dev->ctrl_inac |= (1 << AWB_IDX); |
1657 | #endif | 835 | #endif |
1658 | #if AWB_DEF != 0 | 836 | #if AWB_DEF != 0 |
1659 | sd->awb = AWB_DEF | 837 | sd->awb = AWB_DEF |
1660 | #endif | 838 | #endif |
1661 | #if SHARPNESS_77_DEF != 0 | 839 | #if SHARPNESS_DEF != 0 |
1662 | sd->sharpness = SHARPNESS_77_DEF; | 840 | sd->sharpness = SHARPNESS_DEF; |
1663 | #endif | 841 | #endif |
1664 | #if HFLIP_DEF != 0 | 842 | #if HFLIP_DEF != 0 |
1665 | sd->hflip = HFLIP_DEF; | 843 | sd->hflip = HFLIP_DEF; |
1666 | #endif | 844 | #endif |
1667 | #if VFLIP_DEF != 0 | 845 | #if VFLIP_DEF != 0 |
1668 | sd->vflip = VFLIP_DEF; | 846 | sd->vflip = VFLIP_DEF; |
1669 | #endif | ||
1670 | } else { | ||
1671 | sd->brightness = BRIGHTNESS_96_DEF; | ||
1672 | sd->contrast = CONTRAST_96_DEF; | ||
1673 | #if AUTOGAIN_96_DEF != 0 | ||
1674 | sd->autogain = AUTOGAIN_96_DEF; | ||
1675 | gspca_dev->ctrl_inac |= (1 << EXPO_96_IDX); | ||
1676 | #endif | 847 | #endif |
1677 | #if EXPO_96_DEF != 0 | 848 | |
1678 | sd->exposure = EXPO_96_DEF; | ||
1679 | #endif | ||
1680 | #if SHARPNESS_96_DEF != 0 | ||
1681 | sd->sharpness = SHARPNESS_96_DEF; | ||
1682 | #endif | ||
1683 | sd->satur = SATUR_DEF; | ||
1684 | sd->lightfreq = FREQ_DEF; | ||
1685 | } | ||
1686 | return 0; | 849 | return 0; |
1687 | } | 850 | } |
1688 | 851 | ||
1689 | /* this function is called at probe and resume time */ | 852 | /* this function is called at probe and resume time */ |
1690 | static int sd_init(struct gspca_dev *gspca_dev) | 853 | static int sd_init(struct gspca_dev *gspca_dev) |
1691 | { | 854 | { |
1692 | struct sd *sd = (struct sd *) gspca_dev; | ||
1693 | u16 sensor_id; | 855 | u16 sensor_id; |
1694 | static const u8 sensor_addr[2] = { | ||
1695 | 0x42, /* 0 SENSOR_OV772X */ | ||
1696 | 0x60, /* 1 SENSOR_OV965X */ | ||
1697 | }; | ||
1698 | 856 | ||
1699 | /* reset bridge */ | 857 | /* reset bridge */ |
1700 | ov534_reg_write(gspca_dev, 0xe7, 0x3a); | 858 | ov534_reg_write(gspca_dev, 0xe7, 0x3a); |
@@ -1702,8 +860,7 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
1702 | msleep(100); | 860 | msleep(100); |
1703 | 861 | ||
1704 | /* initialize the sensor address */ | 862 | /* initialize the sensor address */ |
1705 | ov534_reg_write(gspca_dev, OV534_REG_ADDRESS, | 863 | ov534_reg_write(gspca_dev, OV534_REG_ADDRESS, 0x42); |
1706 | sensor_addr[sd->sensor]); | ||
1707 | 864 | ||
1708 | /* reset sensor */ | 865 | /* reset sensor */ |
1709 | sccb_reg_write(gspca_dev, 0x12, 0x80); | 866 | sccb_reg_write(gspca_dev, 0x12, 0x80); |
@@ -1717,64 +874,46 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
1717 | PDEBUG(D_PROBE, "Sensor ID: %04x", sensor_id); | 874 | PDEBUG(D_PROBE, "Sensor ID: %04x", sensor_id); |
1718 | 875 | ||
1719 | /* initialize */ | 876 | /* initialize */ |
1720 | switch (sd->sensor) { | 877 | reg_w_array(gspca_dev, bridge_init, |
1721 | case SENSOR_OV772X: | 878 | ARRAY_SIZE(bridge_init)); |
1722 | reg_w_array(gspca_dev, bridge_init_ov772x, | 879 | ov534_set_led(gspca_dev, 1); |
1723 | ARRAY_SIZE(bridge_init_ov772x)); | 880 | sccb_w_array(gspca_dev, sensor_init, |
1724 | ov534_set_led(gspca_dev, 1); | 881 | ARRAY_SIZE(sensor_init)); |
1725 | sccb_w_array(gspca_dev, sensor_init_ov772x, | 882 | ov534_reg_write(gspca_dev, 0xe0, 0x09); |
1726 | ARRAY_SIZE(sensor_init_ov772x)); | 883 | ov534_set_led(gspca_dev, 0); |
1727 | ov534_reg_write(gspca_dev, 0xe0, 0x09); | 884 | set_frame_rate(gspca_dev); |
1728 | ov534_set_led(gspca_dev, 0); | ||
1729 | set_frame_rate(gspca_dev); | ||
1730 | break; | ||
1731 | default: | ||
1732 | /* case SENSOR_OV965X: */ | ||
1733 | reg_w_array(gspca_dev, bridge_init_ov965x, | ||
1734 | ARRAY_SIZE(bridge_init_ov965x)); | ||
1735 | sccb_w_array(gspca_dev, sensor_init_ov965x, | ||
1736 | ARRAY_SIZE(sensor_init_ov965x)); | ||
1737 | reg_w_array(gspca_dev, bridge_init_ov965x_2, | ||
1738 | ARRAY_SIZE(bridge_init_ov965x_2)); | ||
1739 | sccb_w_array(gspca_dev, sensor_init_ov965x_2, | ||
1740 | ARRAY_SIZE(sensor_init_ov965x_2)); | ||
1741 | ov534_reg_write(gspca_dev, 0xe0, 0x00); | ||
1742 | ov534_reg_write(gspca_dev, 0xe0, 0x01); | ||
1743 | ov534_set_led(gspca_dev, 0); | ||
1744 | ov534_reg_write(gspca_dev, 0xe0, 0x00); | ||
1745 | } | ||
1746 | 885 | ||
1747 | return 0; | 886 | return 0; |
1748 | } | 887 | } |
1749 | 888 | ||
1750 | static int sd_start_ov772x(struct gspca_dev *gspca_dev) | 889 | static int sd_start(struct gspca_dev *gspca_dev) |
1751 | { | 890 | { |
1752 | int mode; | 891 | int mode; |
1753 | 892 | ||
1754 | mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; | 893 | mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; |
1755 | if (mode != 0) { /* 320x240 */ | 894 | if (mode != 0) { /* 320x240 */ |
1756 | reg_w_array(gspca_dev, bridge_start_ov772x_qvga, | 895 | reg_w_array(gspca_dev, bridge_start_qvga, |
1757 | ARRAY_SIZE(bridge_start_ov772x_qvga)); | 896 | ARRAY_SIZE(bridge_start_qvga)); |
1758 | sccb_w_array(gspca_dev, sensor_start_ov772x_qvga, | 897 | sccb_w_array(gspca_dev, sensor_start_qvga, |
1759 | ARRAY_SIZE(sensor_start_ov772x_qvga)); | 898 | ARRAY_SIZE(sensor_start_qvga)); |
1760 | } else { /* 640x480 */ | 899 | } else { /* 640x480 */ |
1761 | reg_w_array(gspca_dev, bridge_start_ov772x_vga, | 900 | reg_w_array(gspca_dev, bridge_start_vga, |
1762 | ARRAY_SIZE(bridge_start_ov772x_vga)); | 901 | ARRAY_SIZE(bridge_start_vga)); |
1763 | sccb_w_array(gspca_dev, sensor_start_ov772x_vga, | 902 | sccb_w_array(gspca_dev, sensor_start_vga, |
1764 | ARRAY_SIZE(sensor_start_ov772x_vga)); | 903 | ARRAY_SIZE(sensor_start_vga)); |
1765 | } | 904 | } |
1766 | set_frame_rate(gspca_dev); | 905 | set_frame_rate(gspca_dev); |
1767 | 906 | ||
1768 | setautogain_77(gspca_dev); | 907 | setautogain(gspca_dev); |
1769 | setawb(gspca_dev); | 908 | setawb(gspca_dev); |
1770 | setgain(gspca_dev); | 909 | setgain(gspca_dev); |
1771 | setredblc(gspca_dev); | 910 | setredblc(gspca_dev); |
1772 | setblueblc(gspca_dev); | 911 | setblueblc(gspca_dev); |
1773 | sethue(gspca_dev); | 912 | sethue(gspca_dev); |
1774 | setexposure_77(gspca_dev); | 913 | setexposure(gspca_dev); |
1775 | setbrightness_77(gspca_dev); | 914 | setbrightness(gspca_dev); |
1776 | setcontrast_77(gspca_dev); | 915 | setcontrast(gspca_dev); |
1777 | setsharpness_77(gspca_dev); | 916 | setsharpness(gspca_dev); |
1778 | setvflip(gspca_dev); | 917 | setvflip(gspca_dev); |
1779 | sethflip(gspca_dev); | 918 | sethflip(gspca_dev); |
1780 | 919 | ||
@@ -1783,81 +922,12 @@ static int sd_start_ov772x(struct gspca_dev *gspca_dev) | |||
1783 | return 0; | 922 | return 0; |
1784 | } | 923 | } |
1785 | 924 | ||
1786 | static int sd_start_ov965x(struct gspca_dev *gspca_dev) | 925 | static void sd_stopN(struct gspca_dev *gspca_dev) |
1787 | { | ||
1788 | int mode; | ||
1789 | |||
1790 | mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; | ||
1791 | switch (mode) { | ||
1792 | default: | ||
1793 | /* case 4: * 320x240 */ | ||
1794 | sccb_w_array(gspca_dev, sensor_start_ov965x_1_vga, | ||
1795 | ARRAY_SIZE(sensor_start_ov965x_1_vga)); | ||
1796 | reg_w_array(gspca_dev, bridge_start_ov965x_qvga, | ||
1797 | ARRAY_SIZE(bridge_start_ov965x_qvga)); | ||
1798 | sccb_w_array(gspca_dev, sensor_start_ov965x_2_qvga, | ||
1799 | ARRAY_SIZE(sensor_start_ov965x_2_qvga)); | ||
1800 | break; | ||
1801 | case 3: /* 640x480 */ | ||
1802 | sccb_w_array(gspca_dev, sensor_start_ov965x_1_vga, | ||
1803 | ARRAY_SIZE(sensor_start_ov965x_1_vga)); | ||
1804 | reg_w_array(gspca_dev, bridge_start_ov965x_vga, | ||
1805 | ARRAY_SIZE(bridge_start_ov965x_vga)); | ||
1806 | sccb_w_array(gspca_dev, sensor_start_ov965x_2_vga, | ||
1807 | ARRAY_SIZE(sensor_start_ov965x_2_vga)); | ||
1808 | break; | ||
1809 | case 2: /* 800x600 */ | ||
1810 | sccb_w_array(gspca_dev, sensor_start_ov965x_1_svga, | ||
1811 | ARRAY_SIZE(sensor_start_ov965x_1_svga)); | ||
1812 | reg_w_array(gspca_dev, bridge_start_ov965x_svga, | ||
1813 | ARRAY_SIZE(bridge_start_ov965x_svga)); | ||
1814 | sccb_w_array(gspca_dev, sensor_start_ov965x_2_svga, | ||
1815 | ARRAY_SIZE(sensor_start_ov965x_2_svga)); | ||
1816 | break; | ||
1817 | case 1: /* 1024x768 */ | ||
1818 | sccb_w_array(gspca_dev, sensor_start_ov965x_1_xga, | ||
1819 | ARRAY_SIZE(sensor_start_ov965x_1_xga)); | ||
1820 | reg_w_array(gspca_dev, bridge_start_ov965x_xga, | ||
1821 | ARRAY_SIZE(bridge_start_ov965x_xga)); | ||
1822 | sccb_w_array(gspca_dev, sensor_start_ov965x_2_svga, | ||
1823 | ARRAY_SIZE(sensor_start_ov965x_2_svga)); | ||
1824 | break; | ||
1825 | case 0: /* 1280x1024 */ | ||
1826 | sccb_w_array(gspca_dev, sensor_start_ov965x_1_sxga, | ||
1827 | ARRAY_SIZE(sensor_start_ov965x_1_sxga)); | ||
1828 | reg_w_array(gspca_dev, bridge_start_ov965x_sxga, | ||
1829 | ARRAY_SIZE(bridge_start_ov965x_sxga)); | ||
1830 | sccb_w_array(gspca_dev, sensor_start_ov965x_2_sxga, | ||
1831 | ARRAY_SIZE(sensor_start_ov965x_2_sxga)); | ||
1832 | break; | ||
1833 | } | ||
1834 | setfreq(gspca_dev); | ||
1835 | setautogain_96(gspca_dev); | ||
1836 | setbrightness_96(gspca_dev); | ||
1837 | setcontrast_96(gspca_dev); | ||
1838 | setexposure_96(gspca_dev); | ||
1839 | setsharpness_96(gspca_dev); | ||
1840 | setsatur(gspca_dev); | ||
1841 | |||
1842 | ov534_reg_write(gspca_dev, 0xe0, 0x00); | ||
1843 | ov534_reg_write(gspca_dev, 0xe0, 0x00); | ||
1844 | ov534_set_led(gspca_dev, 1); | ||
1845 | return 0; | ||
1846 | } | ||
1847 | |||
1848 | static void sd_stopN_ov772x(struct gspca_dev *gspca_dev) | ||
1849 | { | 926 | { |
1850 | ov534_reg_write(gspca_dev, 0xe0, 0x09); | 927 | ov534_reg_write(gspca_dev, 0xe0, 0x09); |
1851 | ov534_set_led(gspca_dev, 0); | 928 | ov534_set_led(gspca_dev, 0); |
1852 | } | 929 | } |
1853 | 930 | ||
1854 | static void sd_stopN_ov965x(struct gspca_dev *gspca_dev) | ||
1855 | { | ||
1856 | ov534_reg_write(gspca_dev, 0xe0, 0x01); | ||
1857 | ov534_set_led(gspca_dev, 0); | ||
1858 | ov534_reg_write(gspca_dev, 0xe0, 0x00); | ||
1859 | } | ||
1860 | |||
1861 | /* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */ | 931 | /* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */ |
1862 | #define UVC_STREAM_EOH (1 << 7) | 932 | #define UVC_STREAM_EOH (1 << 7) |
1863 | #define UVC_STREAM_ERR (1 << 6) | 933 | #define UVC_STREAM_ERR (1 << 6) |
@@ -1875,11 +945,9 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
1875 | __u32 this_pts; | 945 | __u32 this_pts; |
1876 | u16 this_fid; | 946 | u16 this_fid; |
1877 | int remaining_len = len; | 947 | int remaining_len = len; |
1878 | int payload_len; | ||
1879 | 948 | ||
1880 | payload_len = gspca_dev->cam.bulk ? 2048 : 2040; | ||
1881 | do { | 949 | do { |
1882 | len = min(remaining_len, payload_len); | 950 | len = min(remaining_len, 2048); |
1883 | 951 | ||
1884 | /* Payloads are prefixed with a UVC-style header. We | 952 | /* Payloads are prefixed with a UVC-style header. We |
1885 | consider a frame to start when the FID toggles, or the PTS | 953 | consider a frame to start when the FID toggles, or the PTS |
@@ -1918,7 +986,17 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
1918 | data + 12, len - 12); | 986 | data + 12, len - 12); |
1919 | /* If this packet is marked as EOF, end the frame */ | 987 | /* If this packet is marked as EOF, end the frame */ |
1920 | } else if (data[1] & UVC_STREAM_EOF) { | 988 | } else if (data[1] & UVC_STREAM_EOF) { |
989 | struct gspca_frame *frame; | ||
990 | |||
1921 | sd->last_pts = 0; | 991 | sd->last_pts = 0; |
992 | frame = gspca_get_i_frame(gspca_dev); | ||
993 | if (frame == NULL) | ||
994 | goto discard; | ||
995 | if (frame->data_end - frame->data + (len - 12) != | ||
996 | gspca_dev->width * gspca_dev->height * 2) { | ||
997 | PDEBUG(D_PACK, "wrong sized frame"); | ||
998 | goto discard; | ||
999 | } | ||
1922 | gspca_frame_add(gspca_dev, LAST_PACKET, | 1000 | gspca_frame_add(gspca_dev, LAST_PACKET, |
1923 | data + 12, len - 12); | 1001 | data + 12, len - 12); |
1924 | } else { | 1002 | } else { |
@@ -1965,12 +1043,8 @@ static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val) | |||
1965 | struct sd *sd = (struct sd *) gspca_dev; | 1043 | struct sd *sd = (struct sd *) gspca_dev; |
1966 | 1044 | ||
1967 | sd->exposure = val; | 1045 | sd->exposure = val; |
1968 | if (gspca_dev->streaming) { | 1046 | if (gspca_dev->streaming) |
1969 | if (sd->sensor == SENSOR_OV772X) | 1047 | setexposure(gspca_dev); |
1970 | setexposure_77(gspca_dev); | ||
1971 | else | ||
1972 | setexposure_96(gspca_dev); | ||
1973 | } | ||
1974 | return 0; | 1048 | return 0; |
1975 | } | 1049 | } |
1976 | 1050 | ||
@@ -1987,12 +1061,8 @@ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | |||
1987 | struct sd *sd = (struct sd *) gspca_dev; | 1061 | struct sd *sd = (struct sd *) gspca_dev; |
1988 | 1062 | ||
1989 | sd->brightness = val; | 1063 | sd->brightness = val; |
1990 | if (gspca_dev->streaming) { | 1064 | if (gspca_dev->streaming) |
1991 | if (sd->sensor == SENSOR_OV772X) | 1065 | setbrightness(gspca_dev); |
1992 | setbrightness_77(gspca_dev); | ||
1993 | else | ||
1994 | setbrightness_96(gspca_dev); | ||
1995 | } | ||
1996 | return 0; | 1066 | return 0; |
1997 | } | 1067 | } |
1998 | 1068 | ||
@@ -2009,12 +1079,8 @@ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) | |||
2009 | struct sd *sd = (struct sd *) gspca_dev; | 1079 | struct sd *sd = (struct sd *) gspca_dev; |
2010 | 1080 | ||
2011 | sd->contrast = val; | 1081 | sd->contrast = val; |
2012 | if (gspca_dev->streaming) { | 1082 | if (gspca_dev->streaming) |
2013 | if (sd->sensor == SENSOR_OV772X) | 1083 | setcontrast(gspca_dev); |
2014 | setcontrast_77(gspca_dev); | ||
2015 | else | ||
2016 | setcontrast_96(gspca_dev); | ||
2017 | } | ||
2018 | return 0; | 1084 | return 0; |
2019 | } | 1085 | } |
2020 | 1086 | ||
@@ -2026,41 +1092,6 @@ static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) | |||
2026 | return 0; | 1092 | return 0; |
2027 | } | 1093 | } |
2028 | 1094 | ||
2029 | static int sd_setsatur(struct gspca_dev *gspca_dev, __s32 val) | ||
2030 | { | ||
2031 | struct sd *sd = (struct sd *) gspca_dev; | ||
2032 | |||
2033 | sd->satur = val; | ||
2034 | if (gspca_dev->streaming) | ||
2035 | setsatur(gspca_dev); | ||
2036 | return 0; | ||
2037 | } | ||
2038 | |||
2039 | static int sd_getsatur(struct gspca_dev *gspca_dev, __s32 *val) | ||
2040 | { | ||
2041 | struct sd *sd = (struct sd *) gspca_dev; | ||
2042 | |||
2043 | *val = sd->satur; | ||
2044 | return 0; | ||
2045 | } | ||
2046 | static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val) | ||
2047 | { | ||
2048 | struct sd *sd = (struct sd *) gspca_dev; | ||
2049 | |||
2050 | sd->lightfreq = val; | ||
2051 | if (gspca_dev->streaming) | ||
2052 | setfreq(gspca_dev); | ||
2053 | return 0; | ||
2054 | } | ||
2055 | |||
2056 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val) | ||
2057 | { | ||
2058 | struct sd *sd = (struct sd *) gspca_dev; | ||
2059 | |||
2060 | *val = sd->lightfreq; | ||
2061 | return 0; | ||
2062 | } | ||
2063 | |||
2064 | static int sd_setredblc(struct gspca_dev *gspca_dev, __s32 val) | 1095 | static int sd_setredblc(struct gspca_dev *gspca_dev, __s32 val) |
2065 | { | 1096 | { |
2066 | struct sd *sd = (struct sd *) gspca_dev; | 1097 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -2122,22 +1153,14 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) | |||
2122 | sd->autogain = val; | 1153 | sd->autogain = val; |
2123 | 1154 | ||
2124 | if (gspca_dev->streaming) { | 1155 | if (gspca_dev->streaming) { |
2125 | if (sd->sensor == SENSOR_OV772X) { | 1156 | |
2126 | 1157 | /* the auto white balance control works only | |
2127 | /* the auto white balance control works only | 1158 | * when auto gain is set */ |
2128 | * when auto gain is set */ | 1159 | if (val) |
2129 | if (val) | 1160 | gspca_dev->ctrl_inac &= ~(1 << AWB_IDX); |
2130 | gspca_dev->ctrl_inac &= ~(1 << AWB_77_IDX); | 1161 | else |
2131 | else | 1162 | gspca_dev->ctrl_inac |= (1 << AWB_IDX); |
2132 | gspca_dev->ctrl_inac |= (1 << AWB_77_IDX); | 1163 | setautogain(gspca_dev); |
2133 | setautogain_77(gspca_dev); | ||
2134 | } else { | ||
2135 | if (val) | ||
2136 | gspca_dev->ctrl_inac |= (1 << EXPO_96_IDX); | ||
2137 | else | ||
2138 | gspca_dev->ctrl_inac &= ~(1 << EXPO_96_IDX); | ||
2139 | setautogain_96(gspca_dev); | ||
2140 | } | ||
2141 | } | 1164 | } |
2142 | return 0; | 1165 | return 0; |
2143 | } | 1166 | } |
@@ -2173,12 +1196,8 @@ static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val) | |||
2173 | struct sd *sd = (struct sd *) gspca_dev; | 1196 | struct sd *sd = (struct sd *) gspca_dev; |
2174 | 1197 | ||
2175 | sd->sharpness = val; | 1198 | sd->sharpness = val; |
2176 | if (gspca_dev->streaming) { | 1199 | if (gspca_dev->streaming) |
2177 | if (sd->sensor == SENSOR_OV772X) | 1200 | setsharpness(gspca_dev); |
2178 | setsharpness_77(gspca_dev); | ||
2179 | else | ||
2180 | setsharpness_96(gspca_dev); | ||
2181 | } | ||
2182 | return 0; | 1201 | return 0; |
2183 | } | 1202 | } |
2184 | 1203 | ||
@@ -2257,7 +1276,7 @@ static int sd_set_streamparm(struct gspca_dev *gspca_dev, | |||
2257 | 1276 | ||
2258 | /* Set requested framerate */ | 1277 | /* Set requested framerate */ |
2259 | sd->frame_rate = tpf->denominator / tpf->numerator; | 1278 | sd->frame_rate = tpf->denominator / tpf->numerator; |
2260 | if (gspca_dev->streaming && sd->sensor == SENSOR_OV772X) | 1279 | if (gspca_dev->streaming) |
2261 | set_frame_rate(gspca_dev); | 1280 | set_frame_rate(gspca_dev); |
2262 | 1281 | ||
2263 | /* Return the actual framerate */ | 1282 | /* Return the actual framerate */ |
@@ -2267,57 +1286,23 @@ static int sd_set_streamparm(struct gspca_dev *gspca_dev, | |||
2267 | return 0; | 1286 | return 0; |
2268 | } | 1287 | } |
2269 | 1288 | ||
2270 | static int sd_querymenu(struct gspca_dev *gspca_dev, | ||
2271 | struct v4l2_querymenu *menu) | ||
2272 | { | ||
2273 | switch (menu->id) { | ||
2274 | case V4L2_CID_POWER_LINE_FREQUENCY: | ||
2275 | switch (menu->index) { | ||
2276 | case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */ | ||
2277 | strcpy((char *) menu->name, "NoFliker"); | ||
2278 | return 0; | ||
2279 | case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */ | ||
2280 | strcpy((char *) menu->name, "50 Hz"); | ||
2281 | return 0; | ||
2282 | case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */ | ||
2283 | strcpy((char *) menu->name, "60 Hz"); | ||
2284 | return 0; | ||
2285 | } | ||
2286 | break; | ||
2287 | } | ||
2288 | return -EINVAL; | ||
2289 | } | ||
2290 | |||
2291 | /* sub-driver description */ | 1289 | /* sub-driver description */ |
2292 | static const struct sd_desc sd_desc_ov772x = { | 1290 | static const struct sd_desc sd_desc = { |
2293 | .name = MODULE_NAME, | 1291 | .name = MODULE_NAME, |
2294 | .ctrls = sd_ctrls_ov772x, | 1292 | .ctrls = sd_ctrls, |
2295 | .nctrls = ARRAY_SIZE(sd_ctrls_ov772x), | 1293 | .nctrls = ARRAY_SIZE(sd_ctrls), |
2296 | .config = sd_config, | 1294 | .config = sd_config, |
2297 | .init = sd_init, | 1295 | .init = sd_init, |
2298 | .start = sd_start_ov772x, | 1296 | .start = sd_start, |
2299 | .stopN = sd_stopN_ov772x, | 1297 | .stopN = sd_stopN, |
2300 | .pkt_scan = sd_pkt_scan, | 1298 | .pkt_scan = sd_pkt_scan, |
2301 | .get_streamparm = sd_get_streamparm, | 1299 | .get_streamparm = sd_get_streamparm, |
2302 | .set_streamparm = sd_set_streamparm, | 1300 | .set_streamparm = sd_set_streamparm, |
2303 | }; | 1301 | }; |
2304 | 1302 | ||
2305 | static const struct sd_desc sd_desc_ov965x = { | ||
2306 | .name = MODULE_NAME, | ||
2307 | .ctrls = sd_ctrls_ov965x, | ||
2308 | .nctrls = ARRAY_SIZE(sd_ctrls_ov965x), | ||
2309 | .config = sd_config, | ||
2310 | .init = sd_init, | ||
2311 | .start = sd_start_ov965x, | ||
2312 | .stopN = sd_stopN_ov965x, | ||
2313 | .pkt_scan = sd_pkt_scan, | ||
2314 | .querymenu = sd_querymenu, | ||
2315 | }; | ||
2316 | |||
2317 | /* -- module initialisation -- */ | 1303 | /* -- module initialisation -- */ |
2318 | static const __devinitdata struct usb_device_id device_table[] = { | 1304 | static const __devinitdata struct usb_device_id device_table[] = { |
2319 | {USB_DEVICE(0x06f8, 0x3003), .driver_info = SENSOR_OV965X}, | 1305 | {USB_DEVICE(0x1415, 0x2000)}, |
2320 | {USB_DEVICE(0x1415, 0x2000), .driver_info = SENSOR_OV772X}, | ||
2321 | {} | 1306 | {} |
2322 | }; | 1307 | }; |
2323 | 1308 | ||
@@ -2326,11 +1311,7 @@ MODULE_DEVICE_TABLE(usb, device_table); | |||
2326 | /* -- device connect -- */ | 1311 | /* -- device connect -- */ |
2327 | static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id) | 1312 | static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id) |
2328 | { | 1313 | { |
2329 | return gspca_dev_probe(intf, id, | 1314 | return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), |
2330 | id->driver_info == SENSOR_OV772X | ||
2331 | ? &sd_desc_ov772x | ||
2332 | : &sd_desc_ov965x, | ||
2333 | sizeof(struct sd), | ||
2334 | THIS_MODULE); | 1315 | THIS_MODULE); |
2335 | } | 1316 | } |
2336 | 1317 | ||
diff --git a/drivers/media/video/gspca/ov534_9.c b/drivers/media/video/gspca/ov534_9.c new file mode 100644 index 000000000000..bbe5a030e3b4 --- /dev/null +++ b/drivers/media/video/gspca/ov534_9.c | |||
@@ -0,0 +1,1477 @@ | |||
1 | /* | ||
2 | * ov534-ov965x gspca driver | ||
3 | * | ||
4 | * Copyright (C) 2009-2010 Jean-Francois Moine http://moinejf.free.fr | ||
5 | * Copyright (C) 2008 Antonio Ospite <ospite@studenti.unina.it> | ||
6 | * Copyright (C) 2008 Jim Paris <jim@jtan.com> | ||
7 | * | ||
8 | * Based on a prototype written by Mark Ferrell <majortrips@gmail.com> | ||
9 | * USB protocol reverse engineered by Jim Paris <jim@jtan.com> | ||
10 | * https://jim.sh/svn/jim/devl/playstation/ps3/eye/test/ | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
25 | */ | ||
26 | |||
27 | #define MODULE_NAME "ov534_9" | ||
28 | |||
29 | #include "gspca.h" | ||
30 | |||
31 | #define OV534_REG_ADDRESS 0xf1 /* sensor address */ | ||
32 | #define OV534_REG_SUBADDR 0xf2 | ||
33 | #define OV534_REG_WRITE 0xf3 | ||
34 | #define OV534_REG_READ 0xf4 | ||
35 | #define OV534_REG_OPERATION 0xf5 | ||
36 | #define OV534_REG_STATUS 0xf6 | ||
37 | |||
38 | #define OV534_OP_WRITE_3 0x37 | ||
39 | #define OV534_OP_WRITE_2 0x33 | ||
40 | #define OV534_OP_READ_2 0xf9 | ||
41 | |||
42 | #define CTRL_TIMEOUT 500 | ||
43 | |||
44 | MODULE_AUTHOR("Jean-Francois Moine <moinejf@free.fr>"); | ||
45 | MODULE_DESCRIPTION("GSPCA/OV534_9 USB Camera Driver"); | ||
46 | MODULE_LICENSE("GPL"); | ||
47 | |||
48 | /* specific webcam descriptor */ | ||
49 | struct sd { | ||
50 | struct gspca_dev gspca_dev; /* !! must be the first item */ | ||
51 | __u32 last_pts; | ||
52 | u8 last_fid; | ||
53 | |||
54 | u8 brightness; | ||
55 | u8 contrast; | ||
56 | u8 autogain; | ||
57 | u8 exposure; | ||
58 | s8 sharpness; | ||
59 | u8 satur; | ||
60 | u8 freq; | ||
61 | }; | ||
62 | |||
63 | /* V4L2 controls supported by the driver */ | ||
64 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | ||
65 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
66 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | ||
67 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | ||
68 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); | ||
69 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); | ||
70 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); | ||
71 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); | ||
72 | static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val); | ||
73 | static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); | ||
74 | static int sd_setsatur(struct gspca_dev *gspca_dev, __s32 val); | ||
75 | static int sd_getsatur(struct gspca_dev *gspca_dev, __s32 *val); | ||
76 | static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); | ||
77 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); | ||
78 | |||
79 | static const struct ctrl sd_ctrls[] = { | ||
80 | { /* 0 */ | ||
81 | { | ||
82 | .id = V4L2_CID_BRIGHTNESS, | ||
83 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
84 | .name = "Brightness", | ||
85 | .minimum = 0, | ||
86 | .maximum = 15, | ||
87 | .step = 1, | ||
88 | #define BRIGHTNESS_DEF 7 | ||
89 | .default_value = BRIGHTNESS_DEF, | ||
90 | }, | ||
91 | .set = sd_setbrightness, | ||
92 | .get = sd_getbrightness, | ||
93 | }, | ||
94 | { /* 1 */ | ||
95 | { | ||
96 | .id = V4L2_CID_CONTRAST, | ||
97 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
98 | .name = "Contrast", | ||
99 | .minimum = 0, | ||
100 | .maximum = 15, | ||
101 | .step = 1, | ||
102 | #define CONTRAST_DEF 3 | ||
103 | .default_value = CONTRAST_DEF, | ||
104 | }, | ||
105 | .set = sd_setcontrast, | ||
106 | .get = sd_getcontrast, | ||
107 | }, | ||
108 | { /* 2 */ | ||
109 | { | ||
110 | .id = V4L2_CID_AUTOGAIN, | ||
111 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
112 | .name = "Autogain", | ||
113 | .minimum = 0, | ||
114 | .maximum = 1, | ||
115 | .step = 1, | ||
116 | #define AUTOGAIN_DEF 1 | ||
117 | .default_value = AUTOGAIN_DEF, | ||
118 | }, | ||
119 | .set = sd_setautogain, | ||
120 | .get = sd_getautogain, | ||
121 | }, | ||
122 | #define EXPO_IDX 3 | ||
123 | { /* 3 */ | ||
124 | { | ||
125 | .id = V4L2_CID_EXPOSURE, | ||
126 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
127 | .name = "Exposure", | ||
128 | .minimum = 0, | ||
129 | .maximum = 3, | ||
130 | .step = 1, | ||
131 | #define EXPO_DEF 0 | ||
132 | .default_value = EXPO_DEF, | ||
133 | }, | ||
134 | .set = sd_setexposure, | ||
135 | .get = sd_getexposure, | ||
136 | }, | ||
137 | { /* 4 */ | ||
138 | { | ||
139 | .id = V4L2_CID_SHARPNESS, | ||
140 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
141 | .name = "Sharpness", | ||
142 | .minimum = -1, /* -1 = auto */ | ||
143 | .maximum = 4, | ||
144 | .step = 1, | ||
145 | #define SHARPNESS_DEF -1 | ||
146 | .default_value = SHARPNESS_DEF, | ||
147 | }, | ||
148 | .set = sd_setsharpness, | ||
149 | .get = sd_getsharpness, | ||
150 | }, | ||
151 | { /* 5 */ | ||
152 | { | ||
153 | .id = V4L2_CID_SATURATION, | ||
154 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
155 | .name = "Saturation", | ||
156 | .minimum = 0, | ||
157 | .maximum = 4, | ||
158 | .step = 1, | ||
159 | #define SATUR_DEF 2 | ||
160 | .default_value = SATUR_DEF, | ||
161 | }, | ||
162 | .set = sd_setsatur, | ||
163 | .get = sd_getsatur, | ||
164 | }, | ||
165 | { | ||
166 | { | ||
167 | .id = V4L2_CID_POWER_LINE_FREQUENCY, | ||
168 | .type = V4L2_CTRL_TYPE_MENU, | ||
169 | .name = "Light frequency filter", | ||
170 | .minimum = 0, | ||
171 | .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */ | ||
172 | .step = 1, | ||
173 | #define FREQ_DEF 0 | ||
174 | .default_value = FREQ_DEF, | ||
175 | }, | ||
176 | .set = sd_setfreq, | ||
177 | .get = sd_getfreq, | ||
178 | }, | ||
179 | }; | ||
180 | |||
181 | static const struct v4l2_pix_format ov965x_mode[] = { | ||
182 | #define QVGA_MODE 0 | ||
183 | {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | ||
184 | .bytesperline = 320, | ||
185 | .sizeimage = 320 * 240 * 3 / 8 + 590, | ||
186 | .colorspace = V4L2_COLORSPACE_JPEG}, | ||
187 | #define VGA_MODE 1 | ||
188 | {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | ||
189 | .bytesperline = 640, | ||
190 | .sizeimage = 640 * 480 * 3 / 8 + 590, | ||
191 | .colorspace = V4L2_COLORSPACE_JPEG}, | ||
192 | #define SVGA_MODE 2 | ||
193 | {800, 600, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | ||
194 | .bytesperline = 800, | ||
195 | .sizeimage = 800 * 600 * 3 / 8 + 590, | ||
196 | .colorspace = V4L2_COLORSPACE_JPEG}, | ||
197 | #define XGA_MODE 3 | ||
198 | {1024, 768, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | ||
199 | .bytesperline = 1024, | ||
200 | .sizeimage = 1024 * 768 * 3 / 8 + 590, | ||
201 | .colorspace = V4L2_COLORSPACE_JPEG}, | ||
202 | #define SXGA_MODE 4 | ||
203 | {1280, 1024, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | ||
204 | .bytesperline = 1280, | ||
205 | .sizeimage = 1280 * 1024 * 3 / 8 + 590, | ||
206 | .colorspace = V4L2_COLORSPACE_JPEG}, | ||
207 | }; | ||
208 | |||
209 | static const u8 bridge_init[][2] = { | ||
210 | {0x88, 0xf8}, | ||
211 | {0x89, 0xff}, | ||
212 | {0x76, 0x03}, | ||
213 | {0x92, 0x03}, | ||
214 | {0x95, 0x10}, | ||
215 | {0xe2, 0x00}, | ||
216 | {0xe7, 0x3e}, | ||
217 | {0x8d, 0x1c}, | ||
218 | {0x8e, 0x00}, | ||
219 | {0x8f, 0x00}, | ||
220 | {0x1f, 0x00}, | ||
221 | {0xc3, 0xf9}, | ||
222 | {0x89, 0xff}, | ||
223 | {0x88, 0xf8}, | ||
224 | {0x76, 0x03}, | ||
225 | {0x92, 0x01}, | ||
226 | {0x93, 0x18}, | ||
227 | {0x1c, 0x0a}, | ||
228 | {0x1d, 0x48}, | ||
229 | {0xc0, 0x50}, | ||
230 | {0xc1, 0x3c}, | ||
231 | {0x34, 0x05}, | ||
232 | {0xc2, 0x0c}, | ||
233 | {0xc3, 0xf9}, | ||
234 | {0x34, 0x05}, | ||
235 | {0xe7, 0x2e}, | ||
236 | {0x31, 0xf9}, | ||
237 | {0x35, 0x02}, | ||
238 | {0xd9, 0x10}, | ||
239 | {0x25, 0x42}, | ||
240 | {0x94, 0x11}, | ||
241 | }; | ||
242 | |||
243 | static const u8 sensor_init[][2] = { | ||
244 | {0x12, 0x80}, /* com7 - SSCB reset */ | ||
245 | {0x00, 0x00}, /* gain */ | ||
246 | {0x01, 0x80}, /* blue */ | ||
247 | {0x02, 0x80}, /* red */ | ||
248 | {0x03, 0x1b}, /* vref */ | ||
249 | {0x04, 0x03}, /* com1 - exposure low bits */ | ||
250 | {0x0b, 0x57}, /* ver */ | ||
251 | {0x0e, 0x61}, /* com5 */ | ||
252 | {0x0f, 0x42}, /* com6 */ | ||
253 | {0x11, 0x00}, /* clkrc */ | ||
254 | {0x12, 0x02}, /* com7 - 15fps VGA YUYV */ | ||
255 | {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ | ||
256 | {0x14, 0x28}, /* com9 */ | ||
257 | {0x16, 0x24}, /* reg16 */ | ||
258 | {0x17, 0x1d}, /* hstart*/ | ||
259 | {0x18, 0xbd}, /* hstop */ | ||
260 | {0x19, 0x01}, /* vstrt */ | ||
261 | {0x1a, 0x81}, /* vstop*/ | ||
262 | {0x1e, 0x04}, /* mvfp */ | ||
263 | {0x24, 0x3c}, /* aew */ | ||
264 | {0x25, 0x36}, /* aeb */ | ||
265 | {0x26, 0x71}, /* vpt */ | ||
266 | {0x27, 0x08}, /* bbias */ | ||
267 | {0x28, 0x08}, /* gbbias */ | ||
268 | {0x29, 0x15}, /* gr com */ | ||
269 | {0x2a, 0x00}, /* exhch */ | ||
270 | {0x2b, 0x00}, /* exhcl */ | ||
271 | {0x2c, 0x08}, /* rbias */ | ||
272 | {0x32, 0xff}, /* href */ | ||
273 | {0x33, 0x00}, /* chlf */ | ||
274 | {0x34, 0x3f}, /* aref1 */ | ||
275 | {0x35, 0x00}, /* aref2 */ | ||
276 | {0x36, 0xf8}, /* aref3 */ | ||
277 | {0x38, 0x72}, /* adc2 */ | ||
278 | {0x39, 0x57}, /* aref4 */ | ||
279 | {0x3a, 0x80}, /* tslb - yuyv */ | ||
280 | {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */ | ||
281 | {0x3d, 0x99}, /* com13 */ | ||
282 | {0x3f, 0xc1}, /* edge */ | ||
283 | {0x40, 0xc0}, /* com15 */ | ||
284 | {0x41, 0x40}, /* com16 */ | ||
285 | {0x42, 0xc0}, /* com17 */ | ||
286 | {0x43, 0x0a}, /* rsvd */ | ||
287 | {0x44, 0xf0}, | ||
288 | {0x45, 0x46}, | ||
289 | {0x46, 0x62}, | ||
290 | {0x47, 0x2a}, | ||
291 | {0x48, 0x3c}, | ||
292 | {0x4a, 0xfc}, | ||
293 | {0x4b, 0xfc}, | ||
294 | {0x4c, 0x7f}, | ||
295 | {0x4d, 0x7f}, | ||
296 | {0x4e, 0x7f}, | ||
297 | {0x4f, 0x98}, /* matrix */ | ||
298 | {0x50, 0x98}, | ||
299 | {0x51, 0x00}, | ||
300 | {0x52, 0x28}, | ||
301 | {0x53, 0x70}, | ||
302 | {0x54, 0x98}, | ||
303 | {0x58, 0x1a}, /* matrix coef sign */ | ||
304 | {0x59, 0x85}, /* AWB control */ | ||
305 | {0x5a, 0xa9}, | ||
306 | {0x5b, 0x64}, | ||
307 | {0x5c, 0x84}, | ||
308 | {0x5d, 0x53}, | ||
309 | {0x5e, 0x0e}, | ||
310 | {0x5f, 0xf0}, /* AWB blue limit */ | ||
311 | {0x60, 0xf0}, /* AWB red limit */ | ||
312 | {0x61, 0xf0}, /* AWB green limit */ | ||
313 | {0x62, 0x00}, /* lcc1 */ | ||
314 | {0x63, 0x00}, /* lcc2 */ | ||
315 | {0x64, 0x02}, /* lcc3 */ | ||
316 | {0x65, 0x16}, /* lcc4 */ | ||
317 | {0x66, 0x01}, /* lcc5 */ | ||
318 | {0x69, 0x02}, /* hv */ | ||
319 | {0x6b, 0x5a}, /* dbvl */ | ||
320 | {0x6c, 0x04}, | ||
321 | {0x6d, 0x55}, | ||
322 | {0x6e, 0x00}, | ||
323 | {0x6f, 0x9d}, | ||
324 | {0x70, 0x21}, /* dnsth */ | ||
325 | {0x71, 0x78}, | ||
326 | {0x72, 0x00}, /* poidx */ | ||
327 | {0x73, 0x01}, /* pckdv */ | ||
328 | {0x74, 0x3a}, /* xindx */ | ||
329 | {0x75, 0x35}, /* yindx */ | ||
330 | {0x76, 0x01}, | ||
331 | {0x77, 0x02}, | ||
332 | {0x7a, 0x12}, /* gamma curve */ | ||
333 | {0x7b, 0x08}, | ||
334 | {0x7c, 0x16}, | ||
335 | {0x7d, 0x30}, | ||
336 | {0x7e, 0x5e}, | ||
337 | {0x7f, 0x72}, | ||
338 | {0x80, 0x82}, | ||
339 | {0x81, 0x8e}, | ||
340 | {0x82, 0x9a}, | ||
341 | {0x83, 0xa4}, | ||
342 | {0x84, 0xac}, | ||
343 | {0x85, 0xb8}, | ||
344 | {0x86, 0xc3}, | ||
345 | {0x87, 0xd6}, | ||
346 | {0x88, 0xe6}, | ||
347 | {0x89, 0xf2}, | ||
348 | {0x8a, 0x03}, | ||
349 | {0x8c, 0x89}, /* com19 */ | ||
350 | {0x14, 0x28}, /* com9 */ | ||
351 | {0x90, 0x7d}, | ||
352 | {0x91, 0x7b}, | ||
353 | {0x9d, 0x03}, /* lcc6 */ | ||
354 | {0x9e, 0x04}, /* lcc7 */ | ||
355 | {0x9f, 0x7a}, | ||
356 | {0xa0, 0x79}, | ||
357 | {0xa1, 0x40}, /* aechm */ | ||
358 | {0xa4, 0x50}, /* com21 */ | ||
359 | {0xa5, 0x68}, /* com26 */ | ||
360 | {0xa6, 0x4a}, /* AWB green */ | ||
361 | {0xa8, 0xc1}, /* refa8 */ | ||
362 | {0xa9, 0xef}, /* refa9 */ | ||
363 | {0xaa, 0x92}, | ||
364 | {0xab, 0x04}, | ||
365 | {0xac, 0x80}, /* black level control */ | ||
366 | {0xad, 0x80}, | ||
367 | {0xae, 0x80}, | ||
368 | {0xaf, 0x80}, | ||
369 | {0xb2, 0xf2}, | ||
370 | {0xb3, 0x20}, | ||
371 | {0xb4, 0x20}, /* ctrlb4 */ | ||
372 | {0xb5, 0x00}, | ||
373 | {0xb6, 0xaf}, | ||
374 | {0xbb, 0xae}, | ||
375 | {0xbc, 0x7f}, /* ADC channel offsets */ | ||
376 | {0xdb, 0x7f}, | ||
377 | {0xbe, 0x7f}, | ||
378 | {0xbf, 0x7f}, | ||
379 | {0xc0, 0xe2}, | ||
380 | {0xc1, 0xc0}, | ||
381 | {0xc2, 0x01}, | ||
382 | {0xc3, 0x4e}, | ||
383 | {0xc6, 0x85}, | ||
384 | {0xc7, 0x80}, /* com24 */ | ||
385 | {0xc9, 0xe0}, | ||
386 | {0xca, 0xe8}, | ||
387 | {0xcb, 0xf0}, | ||
388 | {0xcc, 0xd8}, | ||
389 | {0xcd, 0xf1}, | ||
390 | {0x4f, 0x98}, /* matrix */ | ||
391 | {0x50, 0x98}, | ||
392 | {0x51, 0x00}, | ||
393 | {0x52, 0x28}, | ||
394 | {0x53, 0x70}, | ||
395 | {0x54, 0x98}, | ||
396 | {0x58, 0x1a}, | ||
397 | {0xff, 0x41}, /* read 41, write ff 00 */ | ||
398 | {0x41, 0x40}, /* com16 */ | ||
399 | |||
400 | {0xc5, 0x03}, /* 60 Hz banding filter */ | ||
401 | {0x6a, 0x02}, /* 50 Hz banding filter */ | ||
402 | |||
403 | {0x12, 0x62}, /* com7 - 30fps VGA YUV */ | ||
404 | {0x36, 0xfa}, /* aref3 */ | ||
405 | {0x69, 0x0a}, /* hv */ | ||
406 | {0x8c, 0x89}, /* com22 */ | ||
407 | {0x14, 0x28}, /* com9 */ | ||
408 | {0x3e, 0x0c}, | ||
409 | {0x41, 0x40}, /* com16 */ | ||
410 | {0x72, 0x00}, | ||
411 | {0x73, 0x00}, | ||
412 | {0x74, 0x3a}, | ||
413 | {0x75, 0x35}, | ||
414 | {0x76, 0x01}, | ||
415 | {0xc7, 0x80}, | ||
416 | {0x03, 0x12}, /* vref */ | ||
417 | {0x17, 0x16}, /* hstart */ | ||
418 | {0x18, 0x02}, /* hstop */ | ||
419 | {0x19, 0x01}, /* vstrt */ | ||
420 | {0x1a, 0x3d}, /* vstop */ | ||
421 | {0x32, 0xff}, /* href */ | ||
422 | {0xc0, 0xaa}, | ||
423 | }; | ||
424 | |||
425 | static const u8 bridge_init_2[][2] = { | ||
426 | {0x94, 0xaa}, | ||
427 | {0xf1, 0x60}, | ||
428 | {0xe5, 0x04}, | ||
429 | {0xc0, 0x50}, | ||
430 | {0xc1, 0x3c}, | ||
431 | {0x8c, 0x00}, | ||
432 | {0x8d, 0x1c}, | ||
433 | {0x34, 0x05}, | ||
434 | |||
435 | {0xc2, 0x0c}, | ||
436 | {0xc3, 0xf9}, | ||
437 | {0xda, 0x01}, | ||
438 | {0x50, 0x00}, | ||
439 | {0x51, 0xa0}, | ||
440 | {0x52, 0x3c}, | ||
441 | {0x53, 0x00}, | ||
442 | {0x54, 0x00}, | ||
443 | {0x55, 0x00}, | ||
444 | {0x57, 0x00}, | ||
445 | {0x5c, 0x00}, | ||
446 | {0x5a, 0xa0}, | ||
447 | {0x5b, 0x78}, | ||
448 | {0x35, 0x02}, | ||
449 | {0xd9, 0x10}, | ||
450 | {0x94, 0x11}, | ||
451 | }; | ||
452 | |||
453 | static const u8 sensor_init_2[][2] = { | ||
454 | {0x3b, 0xc4}, | ||
455 | {0x1e, 0x04}, /* mvfp */ | ||
456 | {0x13, 0xe0}, /* com8 */ | ||
457 | {0x00, 0x00}, /* gain */ | ||
458 | {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ | ||
459 | {0x11, 0x03}, /* clkrc */ | ||
460 | {0x6b, 0x5a}, /* dblv */ | ||
461 | {0x6a, 0x05}, | ||
462 | {0xc5, 0x07}, | ||
463 | {0xa2, 0x4b}, | ||
464 | {0xa3, 0x3e}, | ||
465 | {0x2d, 0x00}, | ||
466 | {0xff, 0x42}, /* read 42, write ff 00 */ | ||
467 | {0x42, 0xc0}, /* com17 */ | ||
468 | {0x2d, 0x00}, | ||
469 | {0xff, 0x42}, /* read 42, write ff 00 */ | ||
470 | {0x42, 0xc1}, /* com17 */ | ||
471 | /* sharpness */ | ||
472 | {0x3f, 0x01}, | ||
473 | {0xff, 0x42}, /* read 42, write ff 00 */ | ||
474 | {0x42, 0xc1}, /* com17 */ | ||
475 | /* saturation */ | ||
476 | {0x4f, 0x98}, /* matrix */ | ||
477 | {0x50, 0x98}, | ||
478 | {0x51, 0x00}, | ||
479 | {0x52, 0x28}, | ||
480 | {0x53, 0x70}, | ||
481 | {0x54, 0x98}, | ||
482 | {0x58, 0x1a}, | ||
483 | {0xff, 0x41}, /* read 41, write ff 00 */ | ||
484 | {0x41, 0x40}, /* com16 */ | ||
485 | /* contrast */ | ||
486 | {0x56, 0x40}, | ||
487 | /* brightness */ | ||
488 | {0x55, 0x8f}, | ||
489 | /* expo */ | ||
490 | {0x10, 0x25}, /* aech - exposure high bits */ | ||
491 | {0xff, 0x13}, /* read 13, write ff 00 */ | ||
492 | {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ | ||
493 | }; | ||
494 | |||
495 | static const u8 sensor_start_1_vga[][2] = { /* same for qvga */ | ||
496 | {0x12, 0x62}, /* com7 - 30fps VGA YUV */ | ||
497 | {0x36, 0xfa}, /* aref3 */ | ||
498 | {0x69, 0x0a}, /* hv */ | ||
499 | {0x8c, 0x89}, /* com22 */ | ||
500 | {0x14, 0x28}, /* com9 */ | ||
501 | {0x3e, 0x0c}, /* com14 */ | ||
502 | {0x41, 0x40}, /* com16 */ | ||
503 | {0x72, 0x00}, | ||
504 | {0x73, 0x00}, | ||
505 | {0x74, 0x3a}, | ||
506 | {0x75, 0x35}, | ||
507 | {0x76, 0x01}, | ||
508 | {0xc7, 0x80}, /* com24 */ | ||
509 | {0x03, 0x12}, /* vref */ | ||
510 | {0x17, 0x16}, /* hstart */ | ||
511 | {0x18, 0x02}, /* hstop */ | ||
512 | {0x19, 0x01}, /* vstrt */ | ||
513 | {0x1a, 0x3d}, /* vstop */ | ||
514 | {0x32, 0xff}, /* href */ | ||
515 | {0xc0, 0xaa}, | ||
516 | }; | ||
517 | |||
518 | static const u8 sensor_start_1_svga[][2] = { | ||
519 | {0x12, 0x02}, /* com7 - YUYV - VGA 15 full resolution */ | ||
520 | {0x36, 0xf8}, /* aref3 */ | ||
521 | {0x69, 0x02}, /* hv */ | ||
522 | {0x8c, 0x0d}, /* com22 */ | ||
523 | {0x3e, 0x0c}, /* com14 */ | ||
524 | {0x41, 0x40}, /* com16 */ | ||
525 | {0x72, 0x00}, | ||
526 | {0x73, 0x01}, | ||
527 | {0x74, 0x3a}, | ||
528 | {0x75, 0x35}, | ||
529 | {0x76, 0x01}, | ||
530 | {0xc7, 0x80}, /* com24 */ | ||
531 | {0x03, 0x1b}, /* vref */ | ||
532 | {0x17, 0x1d}, /* hstart */ | ||
533 | {0x18, 0xbd}, /* hstop */ | ||
534 | {0x19, 0x01}, /* vstrt */ | ||
535 | {0x1a, 0x81}, /* vstop */ | ||
536 | {0x32, 0xff}, /* href */ | ||
537 | {0xc0, 0xe2}, | ||
538 | }; | ||
539 | |||
540 | static const u8 sensor_start_1_xga[][2] = { | ||
541 | {0x12, 0x02}, /* com7 */ | ||
542 | {0x36, 0xf8}, /* aref3 */ | ||
543 | {0x69, 0x02}, /* hv */ | ||
544 | {0x8c, 0x89}, /* com22 */ | ||
545 | {0x14, 0x28}, /* com9 */ | ||
546 | {0x3e, 0x0c}, /* com14 */ | ||
547 | {0x41, 0x40}, /* com16 */ | ||
548 | {0x72, 0x00}, | ||
549 | {0x73, 0x01}, | ||
550 | {0x74, 0x3a}, | ||
551 | {0x75, 0x35}, | ||
552 | {0x76, 0x01}, | ||
553 | {0xc7, 0x80}, /* com24 */ | ||
554 | {0x03, 0x1b}, /* vref */ | ||
555 | {0x17, 0x1d}, /* hstart */ | ||
556 | {0x18, 0xbd}, /* hstop */ | ||
557 | {0x19, 0x01}, /* vstrt */ | ||
558 | {0x1a, 0x81}, /* vstop */ | ||
559 | {0x32, 0xff}, /* href */ | ||
560 | {0xc0, 0xe2}, | ||
561 | }; | ||
562 | |||
563 | static const u8 sensor_start_1_sxga[][2] = { | ||
564 | {0x12, 0x02}, /* com7 */ | ||
565 | {0x36, 0xf8}, /* aref3 */ | ||
566 | {0x69, 0x02}, /* hv */ | ||
567 | {0x8c, 0x89}, /* com22 */ | ||
568 | {0x14, 0x28}, /* com9 */ | ||
569 | {0x3e, 0x0c}, /* com14 */ | ||
570 | {0x41, 0x40}, /* com16 */ | ||
571 | {0x72, 0x00}, | ||
572 | {0x73, 0x01}, | ||
573 | {0x74, 0x3a}, | ||
574 | {0x75, 0x35}, | ||
575 | {0x76, 0x01}, | ||
576 | {0xc7, 0x80}, /* com24 */ | ||
577 | {0x03, 0x1b}, /* vref */ | ||
578 | {0x17, 0x1d}, /* hstart */ | ||
579 | {0x18, 0x02}, /* hstop */ | ||
580 | {0x19, 0x01}, /* vstrt */ | ||
581 | {0x1a, 0x81}, /* vstop */ | ||
582 | {0x32, 0xff}, /* href */ | ||
583 | {0xc0, 0xe2}, | ||
584 | }; | ||
585 | |||
586 | static const u8 bridge_start_qvga[][2] = { | ||
587 | {0x94, 0xaa}, | ||
588 | {0xf1, 0x60}, | ||
589 | {0xe5, 0x04}, | ||
590 | {0xc0, 0x50}, | ||
591 | {0xc1, 0x3c}, | ||
592 | {0x8c, 0x00}, | ||
593 | {0x8d, 0x1c}, | ||
594 | {0x34, 0x05}, | ||
595 | |||
596 | {0xc2, 0x4c}, | ||
597 | {0xc3, 0xf9}, | ||
598 | {0xda, 0x00}, | ||
599 | {0x50, 0x00}, | ||
600 | {0x51, 0xa0}, | ||
601 | {0x52, 0x78}, | ||
602 | {0x53, 0x00}, | ||
603 | {0x54, 0x00}, | ||
604 | {0x55, 0x00}, | ||
605 | {0x57, 0x00}, | ||
606 | {0x5c, 0x00}, | ||
607 | {0x5a, 0x50}, | ||
608 | {0x5b, 0x3c}, | ||
609 | {0x35, 0x02}, | ||
610 | {0xd9, 0x10}, | ||
611 | {0x94, 0x11}, | ||
612 | }; | ||
613 | |||
614 | static const u8 bridge_start_vga[][2] = { | ||
615 | {0x94, 0xaa}, | ||
616 | {0xf1, 0x60}, | ||
617 | {0xe5, 0x04}, | ||
618 | {0xc0, 0x50}, | ||
619 | {0xc1, 0x3c}, | ||
620 | {0x8c, 0x00}, | ||
621 | {0x8d, 0x1c}, | ||
622 | {0x34, 0x05}, | ||
623 | {0xc2, 0x0c}, | ||
624 | {0xc3, 0xf9}, | ||
625 | {0xda, 0x01}, | ||
626 | {0x50, 0x00}, | ||
627 | {0x51, 0xa0}, | ||
628 | {0x52, 0x3c}, | ||
629 | {0x53, 0x00}, | ||
630 | {0x54, 0x00}, | ||
631 | {0x55, 0x00}, | ||
632 | {0x57, 0x00}, | ||
633 | {0x5c, 0x00}, | ||
634 | {0x5a, 0xa0}, | ||
635 | {0x5b, 0x78}, | ||
636 | {0x35, 0x02}, | ||
637 | {0xd9, 0x10}, | ||
638 | {0x94, 0x11}, | ||
639 | }; | ||
640 | |||
641 | static const u8 bridge_start_svga[][2] = { | ||
642 | {0x94, 0xaa}, | ||
643 | {0xf1, 0x60}, | ||
644 | {0xe5, 0x04}, | ||
645 | {0xc0, 0xa0}, | ||
646 | {0xc1, 0x80}, | ||
647 | {0x8c, 0x00}, | ||
648 | {0x8d, 0x1c}, | ||
649 | {0x34, 0x05}, | ||
650 | {0xc2, 0x4c}, | ||
651 | {0xc3, 0xf9}, | ||
652 | {0x50, 0x00}, | ||
653 | {0x51, 0x40}, | ||
654 | {0x52, 0x00}, | ||
655 | {0x53, 0x00}, | ||
656 | {0x54, 0x00}, | ||
657 | {0x55, 0x88}, | ||
658 | {0x57, 0x00}, | ||
659 | {0x5c, 0x00}, | ||
660 | {0x5a, 0xc8}, | ||
661 | {0x5b, 0x96}, | ||
662 | {0x35, 0x02}, | ||
663 | {0xd9, 0x10}, | ||
664 | {0xda, 0x00}, | ||
665 | {0x94, 0x11}, | ||
666 | }; | ||
667 | |||
668 | static const u8 bridge_start_xga[][2] = { | ||
669 | {0x94, 0xaa}, | ||
670 | {0xf1, 0x60}, | ||
671 | {0xe5, 0x04}, | ||
672 | {0xc0, 0xa0}, | ||
673 | {0xc1, 0x80}, | ||
674 | {0x8c, 0x00}, | ||
675 | {0x8d, 0x1c}, | ||
676 | {0x34, 0x05}, | ||
677 | {0xc2, 0x4c}, | ||
678 | {0xc3, 0xf9}, | ||
679 | {0x50, 0x00}, | ||
680 | {0x51, 0x40}, | ||
681 | {0x52, 0x00}, | ||
682 | {0x53, 0x00}, | ||
683 | {0x54, 0x00}, | ||
684 | {0x55, 0x88}, | ||
685 | {0x57, 0x00}, | ||
686 | {0x5c, 0x01}, | ||
687 | {0x5a, 0x00}, | ||
688 | {0x5b, 0xc0}, | ||
689 | {0x35, 0x02}, | ||
690 | {0xd9, 0x10}, | ||
691 | {0xda, 0x01}, | ||
692 | {0x94, 0x11}, | ||
693 | }; | ||
694 | |||
695 | static const u8 bridge_start_sxga[][2] = { | ||
696 | {0x94, 0xaa}, | ||
697 | {0xf1, 0x60}, | ||
698 | {0xe5, 0x04}, | ||
699 | {0xc0, 0xa0}, | ||
700 | {0xc1, 0x80}, | ||
701 | {0x8c, 0x00}, | ||
702 | {0x8d, 0x1c}, | ||
703 | {0x34, 0x05}, | ||
704 | {0xc2, 0x0c}, | ||
705 | {0xc3, 0xf9}, | ||
706 | {0xda, 0x00}, | ||
707 | {0x35, 0x02}, | ||
708 | {0xd9, 0x10}, | ||
709 | {0x94, 0x11}, | ||
710 | }; | ||
711 | |||
712 | static const u8 sensor_start_2_qvga[][2] = { | ||
713 | {0x3b, 0xe4}, /* com11 - night mode 1/4 frame rate */ | ||
714 | {0x1e, 0x04}, /* mvfp */ | ||
715 | {0x13, 0xe0}, /* com8 */ | ||
716 | {0x00, 0x00}, | ||
717 | {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ | ||
718 | {0x11, 0x01}, /* clkrc */ | ||
719 | {0x6b, 0x5a}, /* dblv */ | ||
720 | {0x6a, 0x02}, /* 50 Hz banding filter */ | ||
721 | {0xc5, 0x03}, /* 60 Hz banding filter */ | ||
722 | {0xa2, 0x96}, /* bd50 */ | ||
723 | {0xa3, 0x7d}, /* bd60 */ | ||
724 | |||
725 | {0xff, 0x13}, /* read 13, write ff 00 */ | ||
726 | {0x13, 0xe7}, | ||
727 | {0x3a, 0x80}, /* tslb - yuyv */ | ||
728 | }; | ||
729 | |||
730 | static const u8 sensor_start_2_vga[][2] = { | ||
731 | {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */ | ||
732 | {0x1e, 0x04}, /* mvfp */ | ||
733 | {0x13, 0xe0}, /* com8 */ | ||
734 | {0x00, 0x00}, | ||
735 | {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ | ||
736 | {0x11, 0x03}, /* clkrc */ | ||
737 | {0x6b, 0x5a}, /* dblv */ | ||
738 | {0x6a, 0x05}, /* 50 Hz banding filter */ | ||
739 | {0xc5, 0x07}, /* 60 Hz banding filter */ | ||
740 | {0xa2, 0x4b}, /* bd50 */ | ||
741 | {0xa3, 0x3e}, /* bd60 */ | ||
742 | |||
743 | {0x2d, 0x00}, /* advfl */ | ||
744 | }; | ||
745 | |||
746 | static const u8 sensor_start_2_svga[][2] = { /* same for xga */ | ||
747 | {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */ | ||
748 | {0x1e, 0x04}, /* mvfp */ | ||
749 | {0x13, 0xe0}, /* com8 */ | ||
750 | {0x00, 0x00}, | ||
751 | {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ | ||
752 | {0x11, 0x01}, /* clkrc */ | ||
753 | {0x6b, 0x5a}, /* dblv */ | ||
754 | {0x6a, 0x0c}, /* 50 Hz banding filter */ | ||
755 | {0xc5, 0x0f}, /* 60 Hz banding filter */ | ||
756 | {0xa2, 0x4e}, /* bd50 */ | ||
757 | {0xa3, 0x41}, /* bd60 */ | ||
758 | }; | ||
759 | |||
760 | static const u8 sensor_start_2_sxga[][2] = { | ||
761 | {0x13, 0xe0}, /* com8 */ | ||
762 | {0x00, 0x00}, | ||
763 | {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ | ||
764 | {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */ | ||
765 | {0x1e, 0x04}, /* mvfp */ | ||
766 | {0x11, 0x01}, /* clkrc */ | ||
767 | {0x6b, 0x5a}, /* dblv */ | ||
768 | {0x6a, 0x0c}, /* 50 Hz banding filter */ | ||
769 | {0xc5, 0x0f}, /* 60 Hz banding filter */ | ||
770 | {0xa2, 0x4e}, /* bd50 */ | ||
771 | {0xa3, 0x41}, /* bd60 */ | ||
772 | }; | ||
773 | |||
774 | static void reg_w_i(struct gspca_dev *gspca_dev, u16 reg, u8 val) | ||
775 | { | ||
776 | struct usb_device *udev = gspca_dev->dev; | ||
777 | int ret; | ||
778 | |||
779 | if (gspca_dev->usb_err < 0) | ||
780 | return; | ||
781 | gspca_dev->usb_buf[0] = val; | ||
782 | ret = usb_control_msg(udev, | ||
783 | usb_sndctrlpipe(udev, 0), | ||
784 | 0x01, | ||
785 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
786 | 0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT); | ||
787 | if (ret < 0) { | ||
788 | PDEBUG(D_ERR, "reg_w failed %d", ret); | ||
789 | gspca_dev->usb_err = ret; | ||
790 | } | ||
791 | } | ||
792 | |||
793 | static void reg_w(struct gspca_dev *gspca_dev, u16 reg, u8 val) | ||
794 | { | ||
795 | PDEBUG(D_USBO, "reg_w [%04x] = %02x", reg, val); | ||
796 | reg_w_i(gspca_dev, reg, val); | ||
797 | } | ||
798 | |||
799 | static u8 reg_r(struct gspca_dev *gspca_dev, u16 reg) | ||
800 | { | ||
801 | struct usb_device *udev = gspca_dev->dev; | ||
802 | int ret; | ||
803 | |||
804 | if (gspca_dev->usb_err < 0) | ||
805 | return 0; | ||
806 | ret = usb_control_msg(udev, | ||
807 | usb_rcvctrlpipe(udev, 0), | ||
808 | 0x01, | ||
809 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
810 | 0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT); | ||
811 | PDEBUG(D_USBI, "reg_r [%04x] -> %02x", reg, gspca_dev->usb_buf[0]); | ||
812 | if (ret < 0) { | ||
813 | PDEBUG(D_ERR, "reg_r err %d", ret); | ||
814 | gspca_dev->usb_err = ret; | ||
815 | } | ||
816 | return gspca_dev->usb_buf[0]; | ||
817 | } | ||
818 | |||
819 | static int sccb_check_status(struct gspca_dev *gspca_dev) | ||
820 | { | ||
821 | u8 data; | ||
822 | int i; | ||
823 | |||
824 | for (i = 0; i < 5; i++) { | ||
825 | data = reg_r(gspca_dev, OV534_REG_STATUS); | ||
826 | |||
827 | switch (data) { | ||
828 | case 0x00: | ||
829 | return 1; | ||
830 | case 0x04: | ||
831 | return 0; | ||
832 | case 0x03: | ||
833 | break; | ||
834 | default: | ||
835 | PDEBUG(D_USBI|D_USBO, | ||
836 | "sccb status 0x%02x, attempt %d/5", | ||
837 | data, i + 1); | ||
838 | } | ||
839 | } | ||
840 | return 0; | ||
841 | } | ||
842 | |||
843 | static void sccb_write(struct gspca_dev *gspca_dev, u8 reg, u8 val) | ||
844 | { | ||
845 | PDEBUG(D_USBO, "sccb_write [%02x] = %02x", reg, val); | ||
846 | reg_w_i(gspca_dev, OV534_REG_SUBADDR, reg); | ||
847 | reg_w_i(gspca_dev, OV534_REG_WRITE, val); | ||
848 | reg_w_i(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_3); | ||
849 | |||
850 | if (!sccb_check_status(gspca_dev)) | ||
851 | PDEBUG(D_ERR, "sccb_write failed"); | ||
852 | } | ||
853 | |||
854 | static u8 sccb_read(struct gspca_dev *gspca_dev, u16 reg) | ||
855 | { | ||
856 | reg_w(gspca_dev, OV534_REG_SUBADDR, reg); | ||
857 | reg_w(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_2); | ||
858 | if (!sccb_check_status(gspca_dev)) | ||
859 | PDEBUG(D_ERR, "sccb_read failed 1"); | ||
860 | |||
861 | reg_w(gspca_dev, OV534_REG_OPERATION, OV534_OP_READ_2); | ||
862 | if (!sccb_check_status(gspca_dev)) | ||
863 | PDEBUG(D_ERR, "sccb_read failed 2"); | ||
864 | |||
865 | return reg_r(gspca_dev, OV534_REG_READ); | ||
866 | } | ||
867 | |||
868 | /* output a bridge sequence (reg - val) */ | ||
869 | static void reg_w_array(struct gspca_dev *gspca_dev, | ||
870 | const u8 (*data)[2], int len) | ||
871 | { | ||
872 | while (--len >= 0) { | ||
873 | reg_w(gspca_dev, (*data)[0], (*data)[1]); | ||
874 | data++; | ||
875 | } | ||
876 | } | ||
877 | |||
878 | /* output a sensor sequence (reg - val) */ | ||
879 | static void sccb_w_array(struct gspca_dev *gspca_dev, | ||
880 | const u8 (*data)[2], int len) | ||
881 | { | ||
882 | while (--len >= 0) { | ||
883 | if ((*data)[0] != 0xff) { | ||
884 | sccb_write(gspca_dev, (*data)[0], (*data)[1]); | ||
885 | } else { | ||
886 | sccb_read(gspca_dev, (*data)[1]); | ||
887 | sccb_write(gspca_dev, 0xff, 0x00); | ||
888 | } | ||
889 | data++; | ||
890 | } | ||
891 | } | ||
892 | |||
893 | /* Two bits control LED: 0x21 bit 7 and 0x23 bit 7. | ||
894 | * (direction and output)? */ | ||
895 | static void set_led(struct gspca_dev *gspca_dev, int status) | ||
896 | { | ||
897 | u8 data; | ||
898 | |||
899 | PDEBUG(D_CONF, "led status: %d", status); | ||
900 | |||
901 | data = reg_r(gspca_dev, 0x21); | ||
902 | data |= 0x80; | ||
903 | reg_w(gspca_dev, 0x21, data); | ||
904 | |||
905 | data = reg_r(gspca_dev, 0x23); | ||
906 | if (status) | ||
907 | data |= 0x80; | ||
908 | else | ||
909 | data &= ~0x80; | ||
910 | |||
911 | reg_w(gspca_dev, 0x23, data); | ||
912 | |||
913 | if (!status) { | ||
914 | data = reg_r(gspca_dev, 0x21); | ||
915 | data &= ~0x80; | ||
916 | reg_w(gspca_dev, 0x21, data); | ||
917 | } | ||
918 | } | ||
919 | |||
920 | static void setbrightness(struct gspca_dev *gspca_dev) | ||
921 | { | ||
922 | struct sd *sd = (struct sd *) gspca_dev; | ||
923 | u8 val; | ||
924 | |||
925 | val = sd->brightness; | ||
926 | if (val < 8) | ||
927 | val = 15 - val; /* f .. 8 */ | ||
928 | else | ||
929 | val = val - 8; /* 0 .. 7 */ | ||
930 | sccb_write(gspca_dev, 0x55, /* brtn - brightness adjustment */ | ||
931 | 0x0f | (val << 4)); | ||
932 | } | ||
933 | |||
934 | static void setcontrast(struct gspca_dev *gspca_dev) | ||
935 | { | ||
936 | struct sd *sd = (struct sd *) gspca_dev; | ||
937 | |||
938 | sccb_write(gspca_dev, 0x56, /* cnst1 - contrast 1 ctrl coeff */ | ||
939 | sd->contrast << 4); | ||
940 | } | ||
941 | |||
942 | static void setautogain(struct gspca_dev *gspca_dev) | ||
943 | { | ||
944 | struct sd *sd = (struct sd *) gspca_dev; | ||
945 | u8 val; | ||
946 | |||
947 | /*fixme: should adjust agc/awb/aec by different controls */ | ||
948 | val = sd->autogain; | ||
949 | val = sccb_read(gspca_dev, 0x13); /* com8 */ | ||
950 | sccb_write(gspca_dev, 0xff, 0x00); | ||
951 | if (sd->autogain) | ||
952 | val |= 0x05; /* agc & aec */ | ||
953 | else | ||
954 | val &= 0xfa; | ||
955 | sccb_write(gspca_dev, 0x13, val); | ||
956 | } | ||
957 | |||
958 | static void setexposure(struct gspca_dev *gspca_dev) | ||
959 | { | ||
960 | struct sd *sd = (struct sd *) gspca_dev; | ||
961 | u8 val; | ||
962 | static const u8 expo[4] = {0x00, 0x25, 0x38, 0x5e}; | ||
963 | |||
964 | sccb_write(gspca_dev, 0x10, /* aec[9:2] */ | ||
965 | expo[sd->exposure]); | ||
966 | |||
967 | val = sccb_read(gspca_dev, 0x13); /* com8 */ | ||
968 | sccb_write(gspca_dev, 0xff, 0x00); | ||
969 | sccb_write(gspca_dev, 0x13, val); | ||
970 | |||
971 | val = sccb_read(gspca_dev, 0xa1); /* aech */ | ||
972 | sccb_write(gspca_dev, 0xff, 0x00); | ||
973 | sccb_write(gspca_dev, 0xa1, val & 0xe0); /* aec[15:10] = 0 */ | ||
974 | } | ||
975 | |||
976 | static void setsharpness(struct gspca_dev *gspca_dev) | ||
977 | { | ||
978 | struct sd *sd = (struct sd *) gspca_dev; | ||
979 | s8 val; | ||
980 | |||
981 | val = sd->sharpness; | ||
982 | if (val < 0) { /* auto */ | ||
983 | val = sccb_read(gspca_dev, 0x42); /* com17 */ | ||
984 | sccb_write(gspca_dev, 0xff, 0x00); | ||
985 | sccb_write(gspca_dev, 0x42, val | 0x40); | ||
986 | /* Edge enhancement strength auto adjust */ | ||
987 | return; | ||
988 | } | ||
989 | if (val != 0) | ||
990 | val = 1 << (val - 1); | ||
991 | sccb_write(gspca_dev, 0x3f, /* edge - edge enhance. factor */ | ||
992 | val); | ||
993 | val = sccb_read(gspca_dev, 0x42); /* com17 */ | ||
994 | sccb_write(gspca_dev, 0xff, 0x00); | ||
995 | sccb_write(gspca_dev, 0x42, val & 0xbf); | ||
996 | } | ||
997 | |||
998 | static void setsatur(struct gspca_dev *gspca_dev) | ||
999 | { | ||
1000 | struct sd *sd = (struct sd *) gspca_dev; | ||
1001 | u8 val1, val2, val3; | ||
1002 | static const u8 matrix[5][2] = { | ||
1003 | {0x14, 0x38}, | ||
1004 | {0x1e, 0x54}, | ||
1005 | {0x28, 0x70}, | ||
1006 | {0x32, 0x8c}, | ||
1007 | {0x48, 0x90} | ||
1008 | }; | ||
1009 | |||
1010 | val1 = matrix[sd->satur][0]; | ||
1011 | val2 = matrix[sd->satur][1]; | ||
1012 | val3 = val1 + val2; | ||
1013 | sccb_write(gspca_dev, 0x4f, val3); /* matrix coeff */ | ||
1014 | sccb_write(gspca_dev, 0x50, val3); | ||
1015 | sccb_write(gspca_dev, 0x51, 0x00); | ||
1016 | sccb_write(gspca_dev, 0x52, val1); | ||
1017 | sccb_write(gspca_dev, 0x53, val2); | ||
1018 | sccb_write(gspca_dev, 0x54, val3); | ||
1019 | sccb_write(gspca_dev, 0x58, 0x1a); /* mtxs - coeff signs */ | ||
1020 | |||
1021 | val1 = sccb_read(gspca_dev, 0x41); /* com16 */ | ||
1022 | sccb_write(gspca_dev, 0xff, 0x00); | ||
1023 | sccb_write(gspca_dev, 0x41, val1); | ||
1024 | } | ||
1025 | |||
1026 | static void setfreq(struct gspca_dev *gspca_dev) | ||
1027 | { | ||
1028 | struct sd *sd = (struct sd *) gspca_dev; | ||
1029 | u8 val; | ||
1030 | |||
1031 | val = sccb_read(gspca_dev, 0x13); /* com8 */ | ||
1032 | sccb_write(gspca_dev, 0xff, 0x00); | ||
1033 | if (sd->freq == 0) { | ||
1034 | sccb_write(gspca_dev, 0x13, val & 0xdf); | ||
1035 | return; | ||
1036 | } | ||
1037 | sccb_write(gspca_dev, 0x13, val | 0x20); | ||
1038 | |||
1039 | val = sccb_read(gspca_dev, 0x42); /* com17 */ | ||
1040 | sccb_write(gspca_dev, 0xff, 0x00); | ||
1041 | if (sd->freq == 1) | ||
1042 | val |= 0x01; | ||
1043 | else | ||
1044 | val &= 0xfe; | ||
1045 | sccb_write(gspca_dev, 0x42, val); | ||
1046 | } | ||
1047 | |||
1048 | /* this function is called at probe time */ | ||
1049 | static int sd_config(struct gspca_dev *gspca_dev, | ||
1050 | const struct usb_device_id *id) | ||
1051 | { | ||
1052 | struct sd *sd = (struct sd *) gspca_dev; | ||
1053 | struct cam *cam; | ||
1054 | |||
1055 | cam = &gspca_dev->cam; | ||
1056 | |||
1057 | cam->cam_mode = ov965x_mode; | ||
1058 | cam->nmodes = ARRAY_SIZE(ov965x_mode); | ||
1059 | |||
1060 | sd->brightness = BRIGHTNESS_DEF; | ||
1061 | sd->contrast = CONTRAST_DEF; | ||
1062 | #if AUTOGAIN_DEF != 0 | ||
1063 | sd->autogain = AUTOGAIN_DEF; | ||
1064 | gspca_dev->ctrl_inac |= (1 << EXPO_IDX); | ||
1065 | #endif | ||
1066 | #if EXPO_DEF != 0 | ||
1067 | sd->exposure = EXPO_DEF; | ||
1068 | #endif | ||
1069 | #if SHARPNESS_DEF != 0 | ||
1070 | sd->sharpness = SHARPNESS_DEF; | ||
1071 | #endif | ||
1072 | sd->satur = SATUR_DEF; | ||
1073 | sd->freq = FREQ_DEF; | ||
1074 | |||
1075 | return 0; | ||
1076 | } | ||
1077 | |||
1078 | /* this function is called at probe and resume time */ | ||
1079 | static int sd_init(struct gspca_dev *gspca_dev) | ||
1080 | { | ||
1081 | u16 sensor_id; | ||
1082 | |||
1083 | /* reset bridge */ | ||
1084 | reg_w(gspca_dev, 0xe7, 0x3a); | ||
1085 | reg_w(gspca_dev, 0xe0, 0x08); | ||
1086 | msleep(100); | ||
1087 | |||
1088 | /* initialize the sensor address */ | ||
1089 | reg_w(gspca_dev, OV534_REG_ADDRESS, 0x60); | ||
1090 | |||
1091 | /* reset sensor */ | ||
1092 | sccb_write(gspca_dev, 0x12, 0x80); | ||
1093 | msleep(10); | ||
1094 | |||
1095 | /* probe the sensor */ | ||
1096 | sccb_read(gspca_dev, 0x0a); | ||
1097 | sensor_id = sccb_read(gspca_dev, 0x0a) << 8; | ||
1098 | sccb_read(gspca_dev, 0x0b); | ||
1099 | sensor_id |= sccb_read(gspca_dev, 0x0b); | ||
1100 | PDEBUG(D_PROBE, "Sensor ID: %04x", sensor_id); | ||
1101 | |||
1102 | /* initialize */ | ||
1103 | reg_w_array(gspca_dev, bridge_init, | ||
1104 | ARRAY_SIZE(bridge_init)); | ||
1105 | sccb_w_array(gspca_dev, sensor_init, | ||
1106 | ARRAY_SIZE(sensor_init)); | ||
1107 | reg_w_array(gspca_dev, bridge_init_2, | ||
1108 | ARRAY_SIZE(bridge_init_2)); | ||
1109 | sccb_w_array(gspca_dev, sensor_init_2, | ||
1110 | ARRAY_SIZE(sensor_init_2)); | ||
1111 | reg_w(gspca_dev, 0xe0, 0x00); | ||
1112 | reg_w(gspca_dev, 0xe0, 0x01); | ||
1113 | set_led(gspca_dev, 0); | ||
1114 | reg_w(gspca_dev, 0xe0, 0x00); | ||
1115 | |||
1116 | return gspca_dev->usb_err; | ||
1117 | } | ||
1118 | |||
1119 | static int sd_start(struct gspca_dev *gspca_dev) | ||
1120 | { | ||
1121 | switch (gspca_dev->curr_mode) { | ||
1122 | case QVGA_MODE: /* 320x240 */ | ||
1123 | sccb_w_array(gspca_dev, sensor_start_1_vga, | ||
1124 | ARRAY_SIZE(sensor_start_1_vga)); | ||
1125 | reg_w_array(gspca_dev, bridge_start_qvga, | ||
1126 | ARRAY_SIZE(bridge_start_qvga)); | ||
1127 | sccb_w_array(gspca_dev, sensor_start_2_qvga, | ||
1128 | ARRAY_SIZE(sensor_start_2_qvga)); | ||
1129 | break; | ||
1130 | case VGA_MODE: /* 640x480 */ | ||
1131 | sccb_w_array(gspca_dev, sensor_start_1_vga, | ||
1132 | ARRAY_SIZE(sensor_start_1_vga)); | ||
1133 | reg_w_array(gspca_dev, bridge_start_vga, | ||
1134 | ARRAY_SIZE(bridge_start_vga)); | ||
1135 | sccb_w_array(gspca_dev, sensor_start_2_vga, | ||
1136 | ARRAY_SIZE(sensor_start_2_vga)); | ||
1137 | break; | ||
1138 | case SVGA_MODE: /* 800x600 */ | ||
1139 | sccb_w_array(gspca_dev, sensor_start_1_svga, | ||
1140 | ARRAY_SIZE(sensor_start_1_svga)); | ||
1141 | reg_w_array(gspca_dev, bridge_start_svga, | ||
1142 | ARRAY_SIZE(bridge_start_svga)); | ||
1143 | sccb_w_array(gspca_dev, sensor_start_2_svga, | ||
1144 | ARRAY_SIZE(sensor_start_2_svga)); | ||
1145 | break; | ||
1146 | case XGA_MODE: /* 1024x768 */ | ||
1147 | sccb_w_array(gspca_dev, sensor_start_1_xga, | ||
1148 | ARRAY_SIZE(sensor_start_1_xga)); | ||
1149 | reg_w_array(gspca_dev, bridge_start_xga, | ||
1150 | ARRAY_SIZE(bridge_start_xga)); | ||
1151 | sccb_w_array(gspca_dev, sensor_start_2_svga, | ||
1152 | ARRAY_SIZE(sensor_start_2_svga)); | ||
1153 | break; | ||
1154 | default: | ||
1155 | /* case SXGA_MODE: * 1280x1024 */ | ||
1156 | sccb_w_array(gspca_dev, sensor_start_1_sxga, | ||
1157 | ARRAY_SIZE(sensor_start_1_sxga)); | ||
1158 | reg_w_array(gspca_dev, bridge_start_sxga, | ||
1159 | ARRAY_SIZE(bridge_start_sxga)); | ||
1160 | sccb_w_array(gspca_dev, sensor_start_2_sxga, | ||
1161 | ARRAY_SIZE(sensor_start_2_sxga)); | ||
1162 | break; | ||
1163 | } | ||
1164 | setfreq(gspca_dev); | ||
1165 | setautogain(gspca_dev); | ||
1166 | setbrightness(gspca_dev); | ||
1167 | setcontrast(gspca_dev); | ||
1168 | setexposure(gspca_dev); | ||
1169 | setsharpness(gspca_dev); | ||
1170 | setsatur(gspca_dev); | ||
1171 | |||
1172 | reg_w(gspca_dev, 0xe0, 0x00); | ||
1173 | reg_w(gspca_dev, 0xe0, 0x00); | ||
1174 | set_led(gspca_dev, 1); | ||
1175 | return gspca_dev->usb_err; | ||
1176 | } | ||
1177 | |||
1178 | static void sd_stopN(struct gspca_dev *gspca_dev) | ||
1179 | { | ||
1180 | reg_w(gspca_dev, 0xe0, 0x01); | ||
1181 | set_led(gspca_dev, 0); | ||
1182 | reg_w(gspca_dev, 0xe0, 0x00); | ||
1183 | } | ||
1184 | |||
1185 | /* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */ | ||
1186 | #define UVC_STREAM_EOH (1 << 7) | ||
1187 | #define UVC_STREAM_ERR (1 << 6) | ||
1188 | #define UVC_STREAM_STI (1 << 5) | ||
1189 | #define UVC_STREAM_RES (1 << 4) | ||
1190 | #define UVC_STREAM_SCR (1 << 3) | ||
1191 | #define UVC_STREAM_PTS (1 << 2) | ||
1192 | #define UVC_STREAM_EOF (1 << 1) | ||
1193 | #define UVC_STREAM_FID (1 << 0) | ||
1194 | |||
1195 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | ||
1196 | u8 *data, int len) | ||
1197 | { | ||
1198 | struct sd *sd = (struct sd *) gspca_dev; | ||
1199 | __u32 this_pts; | ||
1200 | u8 this_fid; | ||
1201 | int remaining_len = len; | ||
1202 | |||
1203 | do { | ||
1204 | len = min(remaining_len, 2040); | ||
1205 | |||
1206 | /* Payloads are prefixed with a UVC-style header. We | ||
1207 | consider a frame to start when the FID toggles, or the PTS | ||
1208 | changes. A frame ends when EOF is set, and we've received | ||
1209 | the correct number of bytes. */ | ||
1210 | |||
1211 | /* Verify UVC header. Header length is always 12 */ | ||
1212 | if (data[0] != 12 || len < 12) { | ||
1213 | PDEBUG(D_PACK, "bad header"); | ||
1214 | goto discard; | ||
1215 | } | ||
1216 | |||
1217 | /* Check errors */ | ||
1218 | if (data[1] & UVC_STREAM_ERR) { | ||
1219 | PDEBUG(D_PACK, "payload error"); | ||
1220 | goto discard; | ||
1221 | } | ||
1222 | |||
1223 | /* Extract PTS and FID */ | ||
1224 | if (!(data[1] & UVC_STREAM_PTS)) { | ||
1225 | PDEBUG(D_PACK, "PTS not present"); | ||
1226 | goto discard; | ||
1227 | } | ||
1228 | this_pts = (data[5] << 24) | (data[4] << 16) | ||
1229 | | (data[3] << 8) | data[2]; | ||
1230 | this_fid = data[1] & UVC_STREAM_FID; | ||
1231 | |||
1232 | /* If PTS or FID has changed, start a new frame. */ | ||
1233 | if (this_pts != sd->last_pts || this_fid != sd->last_fid) { | ||
1234 | if (gspca_dev->last_packet_type == INTER_PACKET) | ||
1235 | gspca_frame_add(gspca_dev, LAST_PACKET, | ||
1236 | NULL, 0); | ||
1237 | sd->last_pts = this_pts; | ||
1238 | sd->last_fid = this_fid; | ||
1239 | gspca_frame_add(gspca_dev, FIRST_PACKET, | ||
1240 | data + 12, len - 12); | ||
1241 | /* If this packet is marked as EOF, end the frame */ | ||
1242 | } else if (data[1] & UVC_STREAM_EOF) { | ||
1243 | sd->last_pts = 0; | ||
1244 | gspca_frame_add(gspca_dev, LAST_PACKET, | ||
1245 | data + 12, len - 12); | ||
1246 | } else { | ||
1247 | |||
1248 | /* Add the data from this payload */ | ||
1249 | gspca_frame_add(gspca_dev, INTER_PACKET, | ||
1250 | data + 12, len - 12); | ||
1251 | } | ||
1252 | |||
1253 | /* Done this payload */ | ||
1254 | goto scan_next; | ||
1255 | |||
1256 | discard: | ||
1257 | /* Discard data until a new frame starts. */ | ||
1258 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
1259 | |||
1260 | scan_next: | ||
1261 | remaining_len -= len; | ||
1262 | data += len; | ||
1263 | } while (remaining_len > 0); | ||
1264 | } | ||
1265 | |||
1266 | /* controls */ | ||
1267 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | ||
1268 | { | ||
1269 | struct sd *sd = (struct sd *) gspca_dev; | ||
1270 | |||
1271 | sd->brightness = val; | ||
1272 | if (gspca_dev->streaming) | ||
1273 | setbrightness(gspca_dev); | ||
1274 | return gspca_dev->usb_err; | ||
1275 | } | ||
1276 | |||
1277 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) | ||
1278 | { | ||
1279 | struct sd *sd = (struct sd *) gspca_dev; | ||
1280 | |||
1281 | *val = sd->brightness; | ||
1282 | return 0; | ||
1283 | } | ||
1284 | |||
1285 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) | ||
1286 | { | ||
1287 | struct sd *sd = (struct sd *) gspca_dev; | ||
1288 | |||
1289 | sd->contrast = val; | ||
1290 | if (gspca_dev->streaming) | ||
1291 | setcontrast(gspca_dev); | ||
1292 | return gspca_dev->usb_err; | ||
1293 | } | ||
1294 | |||
1295 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) | ||
1296 | { | ||
1297 | struct sd *sd = (struct sd *) gspca_dev; | ||
1298 | |||
1299 | *val = sd->contrast; | ||
1300 | return 0; | ||
1301 | } | ||
1302 | |||
1303 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) | ||
1304 | { | ||
1305 | struct sd *sd = (struct sd *) gspca_dev; | ||
1306 | |||
1307 | sd->autogain = val; | ||
1308 | |||
1309 | if (gspca_dev->streaming) { | ||
1310 | if (val) | ||
1311 | gspca_dev->ctrl_inac |= (1 << EXPO_IDX); | ||
1312 | else | ||
1313 | gspca_dev->ctrl_inac &= ~(1 << EXPO_IDX); | ||
1314 | setautogain(gspca_dev); | ||
1315 | } | ||
1316 | return gspca_dev->usb_err; | ||
1317 | } | ||
1318 | |||
1319 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) | ||
1320 | { | ||
1321 | struct sd *sd = (struct sd *) gspca_dev; | ||
1322 | |||
1323 | *val = sd->autogain; | ||
1324 | return 0; | ||
1325 | } | ||
1326 | |||
1327 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val) | ||
1328 | { | ||
1329 | struct sd *sd = (struct sd *) gspca_dev; | ||
1330 | |||
1331 | sd->exposure = val; | ||
1332 | if (gspca_dev->streaming) | ||
1333 | setexposure(gspca_dev); | ||
1334 | return gspca_dev->usb_err; | ||
1335 | } | ||
1336 | |||
1337 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val) | ||
1338 | { | ||
1339 | struct sd *sd = (struct sd *) gspca_dev; | ||
1340 | |||
1341 | *val = sd->exposure; | ||
1342 | return 0; | ||
1343 | } | ||
1344 | |||
1345 | static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val) | ||
1346 | { | ||
1347 | struct sd *sd = (struct sd *) gspca_dev; | ||
1348 | |||
1349 | sd->sharpness = val; | ||
1350 | if (gspca_dev->streaming) | ||
1351 | setsharpness(gspca_dev); | ||
1352 | return gspca_dev->usb_err; | ||
1353 | } | ||
1354 | |||
1355 | static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val) | ||
1356 | { | ||
1357 | struct sd *sd = (struct sd *) gspca_dev; | ||
1358 | |||
1359 | *val = sd->sharpness; | ||
1360 | return 0; | ||
1361 | } | ||
1362 | |||
1363 | static int sd_setsatur(struct gspca_dev *gspca_dev, __s32 val) | ||
1364 | { | ||
1365 | struct sd *sd = (struct sd *) gspca_dev; | ||
1366 | |||
1367 | sd->satur = val; | ||
1368 | if (gspca_dev->streaming) | ||
1369 | setsatur(gspca_dev); | ||
1370 | return gspca_dev->usb_err; | ||
1371 | } | ||
1372 | |||
1373 | static int sd_getsatur(struct gspca_dev *gspca_dev, __s32 *val) | ||
1374 | { | ||
1375 | struct sd *sd = (struct sd *) gspca_dev; | ||
1376 | |||
1377 | *val = sd->satur; | ||
1378 | return 0; | ||
1379 | } | ||
1380 | static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val) | ||
1381 | { | ||
1382 | struct sd *sd = (struct sd *) gspca_dev; | ||
1383 | |||
1384 | sd->freq = val; | ||
1385 | if (gspca_dev->streaming) | ||
1386 | setfreq(gspca_dev); | ||
1387 | return gspca_dev->usb_err; | ||
1388 | } | ||
1389 | |||
1390 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val) | ||
1391 | { | ||
1392 | struct sd *sd = (struct sd *) gspca_dev; | ||
1393 | |||
1394 | *val = sd->freq; | ||
1395 | return 0; | ||
1396 | } | ||
1397 | |||
1398 | static int sd_querymenu(struct gspca_dev *gspca_dev, | ||
1399 | struct v4l2_querymenu *menu) | ||
1400 | { | ||
1401 | switch (menu->id) { | ||
1402 | case V4L2_CID_POWER_LINE_FREQUENCY: | ||
1403 | switch (menu->index) { | ||
1404 | case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */ | ||
1405 | strcpy((char *) menu->name, "NoFliker"); | ||
1406 | return 0; | ||
1407 | case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */ | ||
1408 | strcpy((char *) menu->name, "50 Hz"); | ||
1409 | return 0; | ||
1410 | case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */ | ||
1411 | strcpy((char *) menu->name, "60 Hz"); | ||
1412 | return 0; | ||
1413 | } | ||
1414 | break; | ||
1415 | } | ||
1416 | return -EINVAL; | ||
1417 | } | ||
1418 | |||
1419 | /* sub-driver description */ | ||
1420 | static const struct sd_desc sd_desc = { | ||
1421 | .name = MODULE_NAME, | ||
1422 | .ctrls = sd_ctrls, | ||
1423 | .nctrls = ARRAY_SIZE(sd_ctrls), | ||
1424 | .config = sd_config, | ||
1425 | .init = sd_init, | ||
1426 | .start = sd_start, | ||
1427 | .stopN = sd_stopN, | ||
1428 | .pkt_scan = sd_pkt_scan, | ||
1429 | .querymenu = sd_querymenu, | ||
1430 | }; | ||
1431 | |||
1432 | /* -- module initialisation -- */ | ||
1433 | static const __devinitdata struct usb_device_id device_table[] = { | ||
1434 | {USB_DEVICE(0x06f8, 0x3003)}, | ||
1435 | {} | ||
1436 | }; | ||
1437 | |||
1438 | MODULE_DEVICE_TABLE(usb, device_table); | ||
1439 | |||
1440 | /* -- device connect -- */ | ||
1441 | static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
1442 | { | ||
1443 | return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), | ||
1444 | THIS_MODULE); | ||
1445 | } | ||
1446 | |||
1447 | static struct usb_driver sd_driver = { | ||
1448 | .name = MODULE_NAME, | ||
1449 | .id_table = device_table, | ||
1450 | .probe = sd_probe, | ||
1451 | .disconnect = gspca_disconnect, | ||
1452 | #ifdef CONFIG_PM | ||
1453 | .suspend = gspca_suspend, | ||
1454 | .resume = gspca_resume, | ||
1455 | #endif | ||
1456 | }; | ||
1457 | |||
1458 | /* -- module insert / remove -- */ | ||
1459 | static int __init sd_mod_init(void) | ||
1460 | { | ||
1461 | int ret; | ||
1462 | |||
1463 | ret = usb_register(&sd_driver); | ||
1464 | if (ret < 0) | ||
1465 | return ret; | ||
1466 | PDEBUG(D_PROBE, "registered"); | ||
1467 | return 0; | ||
1468 | } | ||
1469 | |||
1470 | static void __exit sd_mod_exit(void) | ||
1471 | { | ||
1472 | usb_deregister(&sd_driver); | ||
1473 | PDEBUG(D_PROBE, "deregistered"); | ||
1474 | } | ||
1475 | |||
1476 | module_init(sd_mod_init); | ||
1477 | module_exit(sd_mod_exit); | ||
diff --git a/drivers/media/video/gspca/pac207.c b/drivers/media/video/gspca/pac207.c index 4706a823add0..0c87c3490b1e 100644 --- a/drivers/media/video/gspca/pac207.c +++ b/drivers/media/video/gspca/pac207.c | |||
@@ -25,6 +25,7 @@ | |||
25 | 25 | ||
26 | #define MODULE_NAME "pac207" | 26 | #define MODULE_NAME "pac207" |
27 | 27 | ||
28 | #include <linux/input.h> | ||
28 | #include "gspca.h" | 29 | #include "gspca.h" |
29 | 30 | ||
30 | MODULE_AUTHOR("Hans de Goede <hdgoede@redhat.com>"); | 31 | MODULE_AUTHOR("Hans de Goede <hdgoede@redhat.com>"); |
@@ -77,7 +78,7 @@ static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); | |||
77 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); | 78 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); |
78 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); | 79 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); |
79 | 80 | ||
80 | static struct ctrl sd_ctrls[] = { | 81 | static const struct ctrl sd_ctrls[] = { |
81 | #define SD_BRIGHTNESS 0 | 82 | #define SD_BRIGHTNESS 0 |
82 | { | 83 | { |
83 | { | 84 | { |
@@ -495,6 +496,25 @@ static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) | |||
495 | return 0; | 496 | return 0; |
496 | } | 497 | } |
497 | 498 | ||
499 | #ifdef CONFIG_INPUT | ||
500 | static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, | ||
501 | u8 *data, /* interrupt packet data */ | ||
502 | int len) /* interrput packet length */ | ||
503 | { | ||
504 | int ret = -EINVAL; | ||
505 | |||
506 | if (len == 2 && data[0] == 0x5a && data[1] == 0x5a) { | ||
507 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); | ||
508 | input_sync(gspca_dev->input_dev); | ||
509 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); | ||
510 | input_sync(gspca_dev->input_dev); | ||
511 | ret = 0; | ||
512 | } | ||
513 | |||
514 | return ret; | ||
515 | } | ||
516 | #endif | ||
517 | |||
498 | /* sub-driver description */ | 518 | /* sub-driver description */ |
499 | static const struct sd_desc sd_desc = { | 519 | static const struct sd_desc sd_desc = { |
500 | .name = MODULE_NAME, | 520 | .name = MODULE_NAME, |
@@ -506,6 +526,9 @@ static const struct sd_desc sd_desc = { | |||
506 | .stopN = sd_stopN, | 526 | .stopN = sd_stopN, |
507 | .dq_callback = pac207_do_auto_gain, | 527 | .dq_callback = pac207_do_auto_gain, |
508 | .pkt_scan = sd_pkt_scan, | 528 | .pkt_scan = sd_pkt_scan, |
529 | #ifdef CONFIG_INPUT | ||
530 | .int_pkt_scan = sd_int_pkt_scan, | ||
531 | #endif | ||
509 | }; | 532 | }; |
510 | 533 | ||
511 | /* -- module initialisation -- */ | 534 | /* -- module initialisation -- */ |
diff --git a/drivers/media/video/gspca/pac7302.c b/drivers/media/video/gspca/pac7302.c index de0b66c4b56e..2a68220d1ada 100644 --- a/drivers/media/video/gspca/pac7302.c +++ b/drivers/media/video/gspca/pac7302.c | |||
@@ -4,7 +4,9 @@ | |||
4 | * | 4 | * |
5 | * V4L2 by Jean-Francois Moine <http://moinejf.free.fr> | 5 | * V4L2 by Jean-Francois Moine <http://moinejf.free.fr> |
6 | * | 6 | * |
7 | * Separated from Pixart PAC7311 library by Márton Németh <nm127@freemail.hu> | 7 | * Separated from Pixart PAC7311 library by Márton Németh |
8 | * Camera button input handling by Márton Németh <nm127@freemail.hu> | ||
9 | * Copyright (C) 2009-2010 Márton Németh <nm127@freemail.hu> | ||
8 | * | 10 | * |
9 | * This program is free software; you can redistribute it and/or modify | 11 | * This program is free software; you can redistribute it and/or modify |
10 | * it under the terms of the GNU General Public License as published by | 12 | * it under the terms of the GNU General Public License as published by |
@@ -22,33 +24,26 @@ | |||
22 | */ | 24 | */ |
23 | 25 | ||
24 | /* Some documentation about various registers as determined by trial and error. | 26 | /* Some documentation about various registers as determined by trial and error. |
25 | When the register addresses differ between the 7202 and the 7311 the 2 | ||
26 | different addresses are written as 7302addr/7311addr, when one of the 2 | ||
27 | addresses is a - sign that register description is not valid for the | ||
28 | matching IC. | ||
29 | 27 | ||
30 | Register page 1: | 28 | Register page 1: |
31 | 29 | ||
32 | Address Description | 30 | Address Description |
33 | -/0x08 Unknown compressor related, must always be 8 except when not | ||
34 | in 640x480 resolution and page 4 reg 2 <= 3 then set it to 9 ! | ||
35 | -/0x1b Auto white balance related, bit 0 is AWB enable (inverted) | ||
36 | bits 345 seem to toggle per color gains on/off (inverted) | ||
37 | 0x78 Global control, bit 6 controls the LED (inverted) | 31 | 0x78 Global control, bit 6 controls the LED (inverted) |
38 | -/0x80 JPEG compression ratio ? Best not touched | ||
39 | 32 | ||
40 | Register page 3/4: | 33 | Register page 3: |
41 | 34 | ||
42 | Address Description | 35 | Address Description |
43 | 0x02 Clock divider 2-63, fps =~ 60 / val. Must be a multiple of 3 on | 36 | 0x02 Clock divider 3-63, fps = 90 / val. Must be a multiple of 3 on |
44 | the 7302, so one of 3, 6, 9, ..., except when between 6 and 12? | 37 | the 7302, so one of 3, 6, 9, ..., except when between 6 and 12? |
45 | -/0x0f Master gain 1-245, low value = high gain | 38 | 0x03 Variable framerate ctrl reg2==3: 0 -> ~30 fps, 255 -> ~22fps |
46 | 0x10/- Master gain 0-31 | 39 | 0x04 Another var framerate ctrl reg2==3, reg3==0: 0 -> ~30 fps, |
47 | -/0x10 Another gain 0-15, limited influence (1-2x gain I guess) | 40 | 63 -> ~27 fps, the 2 msb's must always be 1 !! |
41 | 0x05 Another var framerate ctrl reg2==3, reg3==0, reg4==0xc0: | ||
42 | 1 -> ~30 fps, 2 -> ~20 fps | ||
43 | 0x0e Exposure bits 0-7, 0-448, 0 = use full frame time | ||
44 | 0x0f Exposure bit 8, 0-448, 448 = no exposure at all | ||
45 | 0x10 Master gain 0-31 | ||
48 | 0x21 Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused | 46 | 0x21 Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused |
49 | -/0x27 Seems to toggle various gains on / off, Setting bit 7 seems to | ||
50 | completely disable the analog amplification block. Set to 0x68 | ||
51 | for max gain, 0x14 for minimal gain. | ||
52 | 47 | ||
53 | The registers are accessed in the following functions: | 48 | The registers are accessed in the following functions: |
54 | 49 | ||
@@ -68,6 +63,7 @@ | |||
68 | 63 | ||
69 | #define MODULE_NAME "pac7302" | 64 | #define MODULE_NAME "pac7302" |
70 | 65 | ||
66 | #include <linux/input.h> | ||
71 | #include <media/v4l2-chip-ident.h> | 67 | #include <media/v4l2-chip-ident.h> |
72 | #include "gspca.h" | 68 | #include "gspca.h" |
73 | 69 | ||
@@ -86,8 +82,8 @@ struct sd { | |||
86 | unsigned char red_balance; | 82 | unsigned char red_balance; |
87 | unsigned char blue_balance; | 83 | unsigned char blue_balance; |
88 | unsigned char gain; | 84 | unsigned char gain; |
89 | unsigned char exposure; | ||
90 | unsigned char autogain; | 85 | unsigned char autogain; |
86 | unsigned short exposure; | ||
91 | __u8 hflip; | 87 | __u8 hflip; |
92 | __u8 vflip; | 88 | __u8 vflip; |
93 | u8 flags; | 89 | u8 flags; |
@@ -124,8 +120,7 @@ static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); | |||
124 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); | 120 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); |
125 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); | 121 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); |
126 | 122 | ||
127 | static struct ctrl sd_ctrls[] = { | 123 | static const struct ctrl sd_ctrls[] = { |
128 | /* This control is pac7302 only */ | ||
129 | { | 124 | { |
130 | { | 125 | { |
131 | .id = V4L2_CID_BRIGHTNESS, | 126 | .id = V4L2_CID_BRIGHTNESS, |
@@ -141,7 +136,6 @@ static struct ctrl sd_ctrls[] = { | |||
141 | .set = sd_setbrightness, | 136 | .set = sd_setbrightness, |
142 | .get = sd_getbrightness, | 137 | .get = sd_getbrightness, |
143 | }, | 138 | }, |
144 | /* This control is for both the 7302 and the 7311 */ | ||
145 | { | 139 | { |
146 | { | 140 | { |
147 | .id = V4L2_CID_CONTRAST, | 141 | .id = V4L2_CID_CONTRAST, |
@@ -157,7 +151,6 @@ static struct ctrl sd_ctrls[] = { | |||
157 | .set = sd_setcontrast, | 151 | .set = sd_setcontrast, |
158 | .get = sd_getcontrast, | 152 | .get = sd_getcontrast, |
159 | }, | 153 | }, |
160 | /* This control is pac7302 only */ | ||
161 | { | 154 | { |
162 | { | 155 | { |
163 | .id = V4L2_CID_SATURATION, | 156 | .id = V4L2_CID_SATURATION, |
@@ -215,7 +208,6 @@ static struct ctrl sd_ctrls[] = { | |||
215 | .set = sd_setbluebalance, | 208 | .set = sd_setbluebalance, |
216 | .get = sd_getbluebalance, | 209 | .get = sd_getbluebalance, |
217 | }, | 210 | }, |
218 | /* All controls below are for both the 7302 and the 7311 */ | ||
219 | { | 211 | { |
220 | { | 212 | { |
221 | .id = V4L2_CID_GAIN, | 213 | .id = V4L2_CID_GAIN, |
@@ -238,11 +230,10 @@ static struct ctrl sd_ctrls[] = { | |||
238 | .type = V4L2_CTRL_TYPE_INTEGER, | 230 | .type = V4L2_CTRL_TYPE_INTEGER, |
239 | .name = "Exposure", | 231 | .name = "Exposure", |
240 | .minimum = 0, | 232 | .minimum = 0, |
241 | #define EXPOSURE_MAX 255 | 233 | .maximum = 1023, |
242 | .maximum = EXPOSURE_MAX, | ||
243 | .step = 1, | 234 | .step = 1, |
244 | #define EXPOSURE_DEF 16 /* 32 ms / 30 fps */ | 235 | #define EXPOSURE_DEF 66 /* 33 ms / 30 fps */ |
245 | #define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */ | 236 | #define EXPOSURE_KNEE 133 /* 66 ms / 15 fps */ |
246 | .default_value = EXPOSURE_DEF, | 237 | .default_value = EXPOSURE_DEF, |
247 | }, | 238 | }, |
248 | .set = sd_setexposure, | 239 | .set = sd_setexposure, |
@@ -301,7 +292,6 @@ static const struct v4l2_pix_format vga_mode[] = { | |||
301 | }; | 292 | }; |
302 | 293 | ||
303 | #define LOAD_PAGE3 255 | 294 | #define LOAD_PAGE3 255 |
304 | #define LOAD_PAGE4 254 | ||
305 | #define END_OF_SEQUENCE 0 | 295 | #define END_OF_SEQUENCE 0 |
306 | 296 | ||
307 | /* pac 7302 */ | 297 | /* pac 7302 */ |
@@ -379,7 +369,7 @@ static const __u8 start_7302[] = { | |||
379 | #define SKIP 0xaa | 369 | #define SKIP 0xaa |
380 | /* page 3 - the value SKIP says skip the index - see reg_w_page() */ | 370 | /* page 3 - the value SKIP says skip the index - see reg_w_page() */ |
381 | static const __u8 page3_7302[] = { | 371 | static const __u8 page3_7302[] = { |
382 | 0x90, 0x40, 0x03, 0x50, 0xc2, 0x01, 0x14, 0x16, | 372 | 0x90, 0x40, 0x03, 0x00, 0xc0, 0x01, 0x14, 0x16, |
383 | 0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00, | 373 | 0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00, |
384 | 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 374 | 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
385 | 0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00, | 375 | 0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00, |
@@ -388,7 +378,7 @@ static const __u8 page3_7302[] = { | |||
388 | 0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00, | 378 | 0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00, |
389 | 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 379 | 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
390 | 0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00, | 380 | 0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00, |
391 | 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00, | 381 | SKIP, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00, |
392 | 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 382 | 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
393 | 0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00, | 383 | 0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00, |
394 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 384 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
@@ -401,12 +391,14 @@ static const __u8 page3_7302[] = { | |||
401 | 0x00 | 391 | 0x00 |
402 | }; | 392 | }; |
403 | 393 | ||
404 | static int reg_w_buf(struct gspca_dev *gspca_dev, | 394 | static void reg_w_buf(struct gspca_dev *gspca_dev, |
405 | __u8 index, | 395 | __u8 index, |
406 | const char *buffer, int len) | 396 | const char *buffer, int len) |
407 | { | 397 | { |
408 | int ret; | 398 | int ret; |
409 | 399 | ||
400 | if (gspca_dev->usb_err < 0) | ||
401 | return; | ||
410 | memcpy(gspca_dev->usb_buf, buffer, len); | 402 | memcpy(gspca_dev->usb_buf, buffer, len); |
411 | ret = usb_control_msg(gspca_dev->dev, | 403 | ret = usb_control_msg(gspca_dev->dev, |
412 | usb_sndctrlpipe(gspca_dev->dev, 0), | 404 | usb_sndctrlpipe(gspca_dev->dev, 0), |
@@ -415,20 +407,23 @@ static int reg_w_buf(struct gspca_dev *gspca_dev, | |||
415 | 0, /* value */ | 407 | 0, /* value */ |
416 | index, gspca_dev->usb_buf, len, | 408 | index, gspca_dev->usb_buf, len, |
417 | 500); | 409 | 500); |
418 | if (ret < 0) | 410 | if (ret < 0) { |
419 | PDEBUG(D_ERR, "reg_w_buf(): " | 411 | PDEBUG(D_ERR, "reg_w_buf(): " |
420 | "Failed to write registers to index 0x%x, error %i", | 412 | "Failed to write registers to index 0x%x, error %i", |
421 | index, ret); | 413 | index, ret); |
422 | return ret; | 414 | gspca_dev->usb_err = ret; |
415 | } | ||
423 | } | 416 | } |
424 | 417 | ||
425 | 418 | ||
426 | static int reg_w(struct gspca_dev *gspca_dev, | 419 | static void reg_w(struct gspca_dev *gspca_dev, |
427 | __u8 index, | 420 | __u8 index, |
428 | __u8 value) | 421 | __u8 value) |
429 | { | 422 | { |
430 | int ret; | 423 | int ret; |
431 | 424 | ||
425 | if (gspca_dev->usb_err < 0) | ||
426 | return; | ||
432 | gspca_dev->usb_buf[0] = value; | 427 | gspca_dev->usb_buf[0] = value; |
433 | ret = usb_control_msg(gspca_dev->dev, | 428 | ret = usb_control_msg(gspca_dev->dev, |
434 | usb_sndctrlpipe(gspca_dev->dev, 0), | 429 | usb_sndctrlpipe(gspca_dev->dev, 0), |
@@ -436,32 +431,32 @@ static int reg_w(struct gspca_dev *gspca_dev, | |||
436 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 431 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
437 | 0, index, gspca_dev->usb_buf, 1, | 432 | 0, index, gspca_dev->usb_buf, 1, |
438 | 500); | 433 | 500); |
439 | if (ret < 0) | 434 | if (ret < 0) { |
440 | PDEBUG(D_ERR, "reg_w(): " | 435 | PDEBUG(D_ERR, "reg_w(): " |
441 | "Failed to write register to index 0x%x, value 0x%x, error %i", | 436 | "Failed to write register to index 0x%x, value 0x%x, error %i", |
442 | index, value, ret); | 437 | index, value, ret); |
443 | return ret; | 438 | gspca_dev->usb_err = ret; |
439 | } | ||
444 | } | 440 | } |
445 | 441 | ||
446 | static int reg_w_seq(struct gspca_dev *gspca_dev, | 442 | static void reg_w_seq(struct gspca_dev *gspca_dev, |
447 | const __u8 *seq, int len) | 443 | const __u8 *seq, int len) |
448 | { | 444 | { |
449 | int ret = 0; | ||
450 | while (--len >= 0) { | 445 | while (--len >= 0) { |
451 | if (0 <= ret) | 446 | reg_w(gspca_dev, seq[0], seq[1]); |
452 | ret = reg_w(gspca_dev, seq[0], seq[1]); | ||
453 | seq += 2; | 447 | seq += 2; |
454 | } | 448 | } |
455 | return ret; | ||
456 | } | 449 | } |
457 | 450 | ||
458 | /* load the beginning of a page */ | 451 | /* load the beginning of a page */ |
459 | static int reg_w_page(struct gspca_dev *gspca_dev, | 452 | static void reg_w_page(struct gspca_dev *gspca_dev, |
460 | const __u8 *page, int len) | 453 | const __u8 *page, int len) |
461 | { | 454 | { |
462 | int index; | 455 | int index; |
463 | int ret = 0; | 456 | int ret = 0; |
464 | 457 | ||
458 | if (gspca_dev->usb_err < 0) | ||
459 | return; | ||
465 | for (index = 0; index < len; index++) { | 460 | for (index = 0; index < len; index++) { |
466 | if (page[index] == SKIP) /* skip this index */ | 461 | if (page[index] == SKIP) /* skip this index */ |
467 | continue; | 462 | continue; |
@@ -477,56 +472,47 @@ static int reg_w_page(struct gspca_dev *gspca_dev, | |||
477 | "Failed to write register to index 0x%x, " | 472 | "Failed to write register to index 0x%x, " |
478 | "value 0x%x, error %i", | 473 | "value 0x%x, error %i", |
479 | index, page[index], ret); | 474 | index, page[index], ret); |
475 | gspca_dev->usb_err = ret; | ||
480 | break; | 476 | break; |
481 | } | 477 | } |
482 | } | 478 | } |
483 | return ret; | ||
484 | } | 479 | } |
485 | 480 | ||
486 | /* output a variable sequence */ | 481 | /* output a variable sequence */ |
487 | static int reg_w_var(struct gspca_dev *gspca_dev, | 482 | static void reg_w_var(struct gspca_dev *gspca_dev, |
488 | const __u8 *seq, | 483 | const __u8 *seq, |
489 | const __u8 *page3, unsigned int page3_len, | 484 | const __u8 *page3, unsigned int page3_len) |
490 | const __u8 *page4, unsigned int page4_len) | ||
491 | { | 485 | { |
492 | int index, len; | 486 | int index, len; |
493 | int ret = 0; | ||
494 | 487 | ||
495 | for (;;) { | 488 | for (;;) { |
496 | index = *seq++; | 489 | index = *seq++; |
497 | len = *seq++; | 490 | len = *seq++; |
498 | switch (len) { | 491 | switch (len) { |
499 | case END_OF_SEQUENCE: | 492 | case END_OF_SEQUENCE: |
500 | return ret; | 493 | return; |
501 | case LOAD_PAGE4: | ||
502 | ret = reg_w_page(gspca_dev, page4, page4_len); | ||
503 | break; | ||
504 | case LOAD_PAGE3: | 494 | case LOAD_PAGE3: |
505 | ret = reg_w_page(gspca_dev, page3, page3_len); | 495 | reg_w_page(gspca_dev, page3, page3_len); |
506 | break; | 496 | break; |
507 | default: | 497 | default: |
508 | if (len > USB_BUF_SZ) { | 498 | if (len > USB_BUF_SZ) { |
509 | PDEBUG(D_ERR|D_STREAM, | 499 | PDEBUG(D_ERR|D_STREAM, |
510 | "Incorrect variable sequence"); | 500 | "Incorrect variable sequence"); |
511 | return -EINVAL; | 501 | return; |
512 | } | 502 | } |
513 | while (len > 0) { | 503 | while (len > 0) { |
514 | if (len < 8) { | 504 | if (len < 8) { |
515 | ret = reg_w_buf(gspca_dev, | 505 | reg_w_buf(gspca_dev, |
516 | index, seq, len); | 506 | index, seq, len); |
517 | if (ret < 0) | ||
518 | return ret; | ||
519 | seq += len; | 507 | seq += len; |
520 | break; | 508 | break; |
521 | } | 509 | } |
522 | ret = reg_w_buf(gspca_dev, index, seq, 8); | 510 | reg_w_buf(gspca_dev, index, seq, 8); |
523 | seq += 8; | 511 | seq += 8; |
524 | index += 8; | 512 | index += 8; |
525 | len -= 8; | 513 | len -= 8; |
526 | } | 514 | } |
527 | } | 515 | } |
528 | if (ret < 0) | ||
529 | return ret; | ||
530 | } | 516 | } |
531 | /* not reached */ | 517 | /* not reached */ |
532 | } | 518 | } |
@@ -560,11 +546,10 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
560 | } | 546 | } |
561 | 547 | ||
562 | /* This function is used by pac7302 only */ | 548 | /* This function is used by pac7302 only */ |
563 | static int setbrightcont(struct gspca_dev *gspca_dev) | 549 | static void setbrightcont(struct gspca_dev *gspca_dev) |
564 | { | 550 | { |
565 | struct sd *sd = (struct sd *) gspca_dev; | 551 | struct sd *sd = (struct sd *) gspca_dev; |
566 | int i, v; | 552 | int i, v; |
567 | int ret; | ||
568 | static const __u8 max[10] = | 553 | static const __u8 max[10] = |
569 | {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb, | 554 | {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb, |
570 | 0xd4, 0xec}; | 555 | 0xd4, 0xec}; |
@@ -572,7 +557,7 @@ static int setbrightcont(struct gspca_dev *gspca_dev) | |||
572 | {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17, | 557 | {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17, |
573 | 0x11, 0x0b}; | 558 | 0x11, 0x0b}; |
574 | 559 | ||
575 | ret = reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ | 560 | reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ |
576 | for (i = 0; i < 10; i++) { | 561 | for (i = 0; i < 10; i++) { |
577 | v = max[i]; | 562 | v = max[i]; |
578 | v += (sd->brightness - BRIGHTNESS_MAX) | 563 | v += (sd->brightness - BRIGHTNESS_MAX) |
@@ -582,136 +567,121 @@ static int setbrightcont(struct gspca_dev *gspca_dev) | |||
582 | v = 0; | 567 | v = 0; |
583 | else if (v > 0xff) | 568 | else if (v > 0xff) |
584 | v = 0xff; | 569 | v = 0xff; |
585 | if (0 <= ret) | 570 | reg_w(gspca_dev, 0xa2 + i, v); |
586 | ret = reg_w(gspca_dev, 0xa2 + i, v); | ||
587 | } | 571 | } |
588 | if (0 <= ret) | 572 | reg_w(gspca_dev, 0xdc, 0x01); |
589 | ret = reg_w(gspca_dev, 0xdc, 0x01); | ||
590 | return ret; | ||
591 | } | 573 | } |
592 | 574 | ||
593 | /* This function is used by pac7302 only */ | 575 | /* This function is used by pac7302 only */ |
594 | static int setcolors(struct gspca_dev *gspca_dev) | 576 | static void setcolors(struct gspca_dev *gspca_dev) |
595 | { | 577 | { |
596 | struct sd *sd = (struct sd *) gspca_dev; | 578 | struct sd *sd = (struct sd *) gspca_dev; |
597 | int i, v; | 579 | int i, v; |
598 | int ret; | ||
599 | static const int a[9] = | 580 | static const int a[9] = |
600 | {217, -212, 0, -101, 170, -67, -38, -315, 355}; | 581 | {217, -212, 0, -101, 170, -67, -38, -315, 355}; |
601 | static const int b[9] = | 582 | static const int b[9] = |
602 | {19, 106, 0, 19, 106, 1, 19, 106, 1}; | 583 | {19, 106, 0, 19, 106, 1, 19, 106, 1}; |
603 | 584 | ||
604 | ret = reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ | 585 | reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ |
605 | if (0 <= ret) | 586 | reg_w(gspca_dev, 0x11, 0x01); |
606 | ret = reg_w(gspca_dev, 0x11, 0x01); | 587 | reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ |
607 | if (0 <= ret) | ||
608 | ret = reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ | ||
609 | for (i = 0; i < 9; i++) { | 588 | for (i = 0; i < 9; i++) { |
610 | v = a[i] * sd->colors / COLOR_MAX + b[i]; | 589 | v = a[i] * sd->colors / COLOR_MAX + b[i]; |
611 | if (0 <= ret) | 590 | reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07); |
612 | ret = reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07); | 591 | reg_w(gspca_dev, 0x0f + 2 * i + 1, v); |
613 | if (0 <= ret) | ||
614 | ret = reg_w(gspca_dev, 0x0f + 2 * i + 1, v); | ||
615 | } | 592 | } |
616 | if (0 <= ret) | 593 | reg_w(gspca_dev, 0xdc, 0x01); |
617 | ret = reg_w(gspca_dev, 0xdc, 0x01); | ||
618 | PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors); | 594 | PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors); |
619 | return ret; | ||
620 | } | 595 | } |
621 | 596 | ||
622 | static int setwhitebalance(struct gspca_dev *gspca_dev) | 597 | static void setwhitebalance(struct gspca_dev *gspca_dev) |
623 | { | 598 | { |
624 | struct sd *sd = (struct sd *) gspca_dev; | 599 | struct sd *sd = (struct sd *) gspca_dev; |
625 | int ret; | ||
626 | 600 | ||
627 | ret = reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ | 601 | reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ |
628 | if (0 <= ret) | 602 | reg_w(gspca_dev, 0xc6, sd->white_balance); |
629 | ret = reg_w(gspca_dev, 0xc6, sd->white_balance); | ||
630 | 603 | ||
631 | if (0 <= ret) | 604 | reg_w(gspca_dev, 0xdc, 0x01); |
632 | ret = reg_w(gspca_dev, 0xdc, 0x01); | ||
633 | PDEBUG(D_CONF|D_STREAM, "white_balance: %i", sd->white_balance); | 605 | PDEBUG(D_CONF|D_STREAM, "white_balance: %i", sd->white_balance); |
634 | return ret; | ||
635 | } | 606 | } |
636 | 607 | ||
637 | static int setredbalance(struct gspca_dev *gspca_dev) | 608 | static void setredbalance(struct gspca_dev *gspca_dev) |
638 | { | 609 | { |
639 | struct sd *sd = (struct sd *) gspca_dev; | 610 | struct sd *sd = (struct sd *) gspca_dev; |
640 | int ret; | ||
641 | 611 | ||
642 | ret = reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ | 612 | reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ |
643 | if (0 <= ret) | 613 | reg_w(gspca_dev, 0xc5, sd->red_balance); |
644 | ret = reg_w(gspca_dev, 0xc5, sd->red_balance); | ||
645 | 614 | ||
646 | if (0 <= ret) | 615 | reg_w(gspca_dev, 0xdc, 0x01); |
647 | ret = reg_w(gspca_dev, 0xdc, 0x01); | ||
648 | PDEBUG(D_CONF|D_STREAM, "red_balance: %i", sd->red_balance); | 616 | PDEBUG(D_CONF|D_STREAM, "red_balance: %i", sd->red_balance); |
649 | return ret; | ||
650 | } | 617 | } |
651 | 618 | ||
652 | static int setbluebalance(struct gspca_dev *gspca_dev) | 619 | static void setbluebalance(struct gspca_dev *gspca_dev) |
653 | { | 620 | { |
654 | struct sd *sd = (struct sd *) gspca_dev; | 621 | struct sd *sd = (struct sd *) gspca_dev; |
655 | int ret; | ||
656 | 622 | ||
657 | ret = reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ | 623 | reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ |
658 | if (0 <= ret) | 624 | reg_w(gspca_dev, 0xc7, sd->blue_balance); |
659 | ret = reg_w(gspca_dev, 0xc7, sd->blue_balance); | ||
660 | 625 | ||
661 | if (0 <= ret) | 626 | reg_w(gspca_dev, 0xdc, 0x01); |
662 | ret = reg_w(gspca_dev, 0xdc, 0x01); | ||
663 | PDEBUG(D_CONF|D_STREAM, "blue_balance: %i", sd->blue_balance); | 627 | PDEBUG(D_CONF|D_STREAM, "blue_balance: %i", sd->blue_balance); |
664 | return ret; | ||
665 | } | 628 | } |
666 | 629 | ||
667 | static int setgain(struct gspca_dev *gspca_dev) | 630 | static void setgain(struct gspca_dev *gspca_dev) |
668 | { | 631 | { |
669 | struct sd *sd = (struct sd *) gspca_dev; | 632 | struct sd *sd = (struct sd *) gspca_dev; |
670 | int ret; | ||
671 | 633 | ||
672 | ret = reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ | 634 | reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ |
673 | if (0 <= ret) | 635 | reg_w(gspca_dev, 0x10, sd->gain >> 3); |
674 | ret = reg_w(gspca_dev, 0x10, sd->gain >> 3); | ||
675 | 636 | ||
676 | /* load registers to sensor (Bit 0, auto clear) */ | 637 | /* load registers to sensor (Bit 0, auto clear) */ |
677 | if (0 <= ret) | 638 | reg_w(gspca_dev, 0x11, 0x01); |
678 | ret = reg_w(gspca_dev, 0x11, 0x01); | ||
679 | return ret; | ||
680 | } | 639 | } |
681 | 640 | ||
682 | static int setexposure(struct gspca_dev *gspca_dev) | 641 | static void setexposure(struct gspca_dev *gspca_dev) |
683 | { | 642 | { |
684 | struct sd *sd = (struct sd *) gspca_dev; | 643 | struct sd *sd = (struct sd *) gspca_dev; |
685 | int ret; | 644 | __u8 clockdiv; |
686 | __u8 reg; | 645 | __u16 exposure; |
687 | 646 | ||
688 | /* register 2 of frame 3/4 contains the clock divider configuring the | 647 | /* register 2 of frame 3 contains the clock divider configuring the |
689 | no fps according to the formula: 60 / reg. sd->exposure is the | 648 | no fps according to the formula: 90 / reg. sd->exposure is the |
690 | desired exposure time in ms. */ | 649 | desired exposure time in 0.5 ms. */ |
691 | reg = 120 * sd->exposure / 1000; | 650 | clockdiv = (90 * sd->exposure + 1999) / 2000; |
692 | if (reg < 2) | 651 | |
693 | reg = 2; | 652 | /* Note clockdiv = 3 also works, but when running at 30 fps, depending |
694 | else if (reg > 63) | 653 | on the scene being recorded, the camera switches to another |
695 | reg = 63; | 654 | quantization table for certain JPEG blocks, and we don't know how |
696 | 655 | to decompress these blocks. So we cap the framerate at 15 fps */ | |
697 | /* On the pac7302 reg2 MUST be a multiple of 3, so round it to | 656 | if (clockdiv < 6) |
698 | the nearest multiple of 3, except when between 6 and 12? */ | 657 | clockdiv = 6; |
699 | if (reg < 6 || reg > 12) | 658 | else if (clockdiv > 63) |
700 | reg = ((reg + 1) / 3) * 3; | 659 | clockdiv = 63; |
701 | ret = reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ | 660 | |
702 | if (0 <= ret) | 661 | /* reg2 MUST be a multiple of 3, except when between 6 and 12? |
703 | ret = reg_w(gspca_dev, 0x02, reg); | 662 | Always round up, otherwise we cannot get the desired frametime |
663 | using the partial frame time exposure control */ | ||
664 | if (clockdiv < 6 || clockdiv > 12) | ||
665 | clockdiv = ((clockdiv + 2) / 3) * 3; | ||
666 | |||
667 | /* frame exposure time in ms = 1000 * clockdiv / 90 -> | ||
668 | exposure = (sd->exposure / 2) * 448 / (1000 * clockdiv / 90) */ | ||
669 | exposure = (sd->exposure * 45 * 448) / (1000 * clockdiv); | ||
670 | /* 0 = use full frametime, 448 = no exposure, reverse it */ | ||
671 | exposure = 448 - exposure; | ||
672 | |||
673 | reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ | ||
674 | reg_w(gspca_dev, 0x02, clockdiv); | ||
675 | reg_w(gspca_dev, 0x0e, exposure & 0xff); | ||
676 | reg_w(gspca_dev, 0x0f, exposure >> 8); | ||
704 | 677 | ||
705 | /* load registers to sensor (Bit 0, auto clear) */ | 678 | /* load registers to sensor (Bit 0, auto clear) */ |
706 | if (0 <= ret) | 679 | reg_w(gspca_dev, 0x11, 0x01); |
707 | ret = reg_w(gspca_dev, 0x11, 0x01); | ||
708 | return ret; | ||
709 | } | 680 | } |
710 | 681 | ||
711 | static int sethvflip(struct gspca_dev *gspca_dev) | 682 | static void sethvflip(struct gspca_dev *gspca_dev) |
712 | { | 683 | { |
713 | struct sd *sd = (struct sd *) gspca_dev; | 684 | struct sd *sd = (struct sd *) gspca_dev; |
714 | int ret; | ||
715 | u8 data, hflip, vflip; | 685 | u8 data, hflip, vflip; |
716 | 686 | ||
717 | hflip = sd->hflip; | 687 | hflip = sd->hflip; |
@@ -721,48 +691,37 @@ static int sethvflip(struct gspca_dev *gspca_dev) | |||
721 | if (sd->flags & FL_VFLIP) | 691 | if (sd->flags & FL_VFLIP) |
722 | vflip = !vflip; | 692 | vflip = !vflip; |
723 | 693 | ||
724 | ret = reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ | 694 | reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ |
725 | data = (hflip ? 0x08 : 0x00) | (vflip ? 0x04 : 0x00); | 695 | data = (hflip ? 0x08 : 0x00) | (vflip ? 0x04 : 0x00); |
726 | if (0 <= ret) | 696 | reg_w(gspca_dev, 0x21, data); |
727 | ret = reg_w(gspca_dev, 0x21, data); | 697 | |
728 | /* load registers to sensor (Bit 0, auto clear) */ | 698 | /* load registers to sensor (Bit 0, auto clear) */ |
729 | if (0 <= ret) | 699 | reg_w(gspca_dev, 0x11, 0x01); |
730 | ret = reg_w(gspca_dev, 0x11, 0x01); | ||
731 | return ret; | ||
732 | } | 700 | } |
733 | 701 | ||
734 | /* this function is called at probe and resume time for pac7302 */ | 702 | /* this function is called at probe and resume time for pac7302 */ |
735 | static int sd_init(struct gspca_dev *gspca_dev) | 703 | static int sd_init(struct gspca_dev *gspca_dev) |
736 | { | 704 | { |
737 | return reg_w_seq(gspca_dev, init_7302, sizeof(init_7302)/2); | 705 | reg_w_seq(gspca_dev, init_7302, sizeof(init_7302)/2); |
706 | return gspca_dev->usb_err; | ||
738 | } | 707 | } |
739 | 708 | ||
740 | static int sd_start(struct gspca_dev *gspca_dev) | 709 | static int sd_start(struct gspca_dev *gspca_dev) |
741 | { | 710 | { |
742 | struct sd *sd = (struct sd *) gspca_dev; | 711 | struct sd *sd = (struct sd *) gspca_dev; |
743 | int ret = 0; | ||
744 | 712 | ||
745 | sd->sof_read = 0; | 713 | sd->sof_read = 0; |
746 | 714 | ||
747 | ret = reg_w_var(gspca_dev, start_7302, | 715 | reg_w_var(gspca_dev, start_7302, |
748 | page3_7302, sizeof(page3_7302), | 716 | page3_7302, sizeof(page3_7302)); |
749 | NULL, 0); | 717 | setbrightcont(gspca_dev); |
750 | if (0 <= ret) | 718 | setcolors(gspca_dev); |
751 | ret = setbrightcont(gspca_dev); | 719 | setwhitebalance(gspca_dev); |
752 | if (0 <= ret) | 720 | setredbalance(gspca_dev); |
753 | ret = setcolors(gspca_dev); | 721 | setbluebalance(gspca_dev); |
754 | if (0 <= ret) | 722 | setgain(gspca_dev); |
755 | ret = setwhitebalance(gspca_dev); | 723 | setexposure(gspca_dev); |
756 | if (0 <= ret) | 724 | sethvflip(gspca_dev); |
757 | ret = setredbalance(gspca_dev); | ||
758 | if (0 <= ret) | ||
759 | ret = setbluebalance(gspca_dev); | ||
760 | if (0 <= ret) | ||
761 | ret = setgain(gspca_dev); | ||
762 | if (0 <= ret) | ||
763 | ret = setexposure(gspca_dev); | ||
764 | if (0 <= ret) | ||
765 | ret = sethvflip(gspca_dev); | ||
766 | 725 | ||
767 | /* only resolution 640x480 is supported for pac7302 */ | 726 | /* only resolution 640x480 is supported for pac7302 */ |
768 | 727 | ||
@@ -771,34 +730,27 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
771 | atomic_set(&sd->avg_lum, -1); | 730 | atomic_set(&sd->avg_lum, -1); |
772 | 731 | ||
773 | /* start stream */ | 732 | /* start stream */ |
774 | if (0 <= ret) | 733 | reg_w(gspca_dev, 0xff, 0x01); |
775 | ret = reg_w(gspca_dev, 0xff, 0x01); | 734 | reg_w(gspca_dev, 0x78, 0x01); |
776 | if (0 <= ret) | ||
777 | ret = reg_w(gspca_dev, 0x78, 0x01); | ||
778 | 735 | ||
779 | return ret; | 736 | return gspca_dev->usb_err; |
780 | } | 737 | } |
781 | 738 | ||
782 | static void sd_stopN(struct gspca_dev *gspca_dev) | 739 | static void sd_stopN(struct gspca_dev *gspca_dev) |
783 | { | 740 | { |
784 | int ret; | ||
785 | 741 | ||
786 | /* stop stream */ | 742 | /* stop stream */ |
787 | ret = reg_w(gspca_dev, 0xff, 0x01); | 743 | reg_w(gspca_dev, 0xff, 0x01); |
788 | if (0 <= ret) | 744 | reg_w(gspca_dev, 0x78, 0x00); |
789 | ret = reg_w(gspca_dev, 0x78, 0x00); | ||
790 | } | 745 | } |
791 | 746 | ||
792 | /* called on streamoff with alt 0 and on disconnect for pac7302 */ | 747 | /* called on streamoff with alt 0 and on disconnect for pac7302 */ |
793 | static void sd_stop0(struct gspca_dev *gspca_dev) | 748 | static void sd_stop0(struct gspca_dev *gspca_dev) |
794 | { | 749 | { |
795 | int ret; | ||
796 | |||
797 | if (!gspca_dev->present) | 750 | if (!gspca_dev->present) |
798 | return; | 751 | return; |
799 | ret = reg_w(gspca_dev, 0xff, 0x01); | 752 | reg_w(gspca_dev, 0xff, 0x01); |
800 | if (0 <= ret) | 753 | reg_w(gspca_dev, 0x78, 0x40); |
801 | ret = reg_w(gspca_dev, 0x78, 0x40); | ||
802 | } | 754 | } |
803 | 755 | ||
804 | /* Include pac common sof detection functions */ | 756 | /* Include pac common sof detection functions */ |
@@ -808,22 +760,13 @@ static void do_autogain(struct gspca_dev *gspca_dev) | |||
808 | { | 760 | { |
809 | struct sd *sd = (struct sd *) gspca_dev; | 761 | struct sd *sd = (struct sd *) gspca_dev; |
810 | int avg_lum = atomic_read(&sd->avg_lum); | 762 | int avg_lum = atomic_read(&sd->avg_lum); |
811 | int desired_lum, deadzone; | 763 | int desired_lum; |
764 | const int deadzone = 30; | ||
812 | 765 | ||
813 | if (avg_lum == -1) | 766 | if (avg_lum == -1) |
814 | return; | 767 | return; |
815 | 768 | ||
816 | desired_lum = 270 + sd->brightness * 4; | 769 | desired_lum = 270 + sd->brightness; |
817 | /* Hack hack, with the 7202 the first exposure step is | ||
818 | pretty large, so if we're about to make the first | ||
819 | exposure increase make the deadzone large to avoid | ||
820 | oscilating */ | ||
821 | if (desired_lum > avg_lum && sd->gain == GAIN_DEF && | ||
822 | sd->exposure > EXPOSURE_DEF && | ||
823 | sd->exposure < 42) | ||
824 | deadzone = 90; | ||
825 | else | ||
826 | deadzone = 30; | ||
827 | 770 | ||
828 | if (sd->autogain_ignore_frames > 0) | 771 | if (sd->autogain_ignore_frames > 0) |
829 | sd->autogain_ignore_frames--; | 772 | sd->autogain_ignore_frames--; |
@@ -947,7 +890,7 @@ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | |||
947 | sd->brightness = val; | 890 | sd->brightness = val; |
948 | if (gspca_dev->streaming) | 891 | if (gspca_dev->streaming) |
949 | setbrightcont(gspca_dev); | 892 | setbrightcont(gspca_dev); |
950 | return 0; | 893 | return gspca_dev->usb_err; |
951 | } | 894 | } |
952 | 895 | ||
953 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) | 896 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -966,7 +909,7 @@ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) | |||
966 | if (gspca_dev->streaming) { | 909 | if (gspca_dev->streaming) { |
967 | setbrightcont(gspca_dev); | 910 | setbrightcont(gspca_dev); |
968 | } | 911 | } |
969 | return 0; | 912 | return gspca_dev->usb_err; |
970 | } | 913 | } |
971 | 914 | ||
972 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) | 915 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -984,7 +927,7 @@ static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val) | |||
984 | sd->colors = val; | 927 | sd->colors = val; |
985 | if (gspca_dev->streaming) | 928 | if (gspca_dev->streaming) |
986 | setcolors(gspca_dev); | 929 | setcolors(gspca_dev); |
987 | return 0; | 930 | return gspca_dev->usb_err; |
988 | } | 931 | } |
989 | 932 | ||
990 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) | 933 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -998,14 +941,11 @@ static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) | |||
998 | static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val) | 941 | static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val) |
999 | { | 942 | { |
1000 | struct sd *sd = (struct sd *) gspca_dev; | 943 | struct sd *sd = (struct sd *) gspca_dev; |
1001 | int ret = 0; | ||
1002 | 944 | ||
1003 | sd->white_balance = val; | 945 | sd->white_balance = val; |
1004 | if (gspca_dev->streaming) | 946 | if (gspca_dev->streaming) |
1005 | ret = setwhitebalance(gspca_dev); | 947 | setwhitebalance(gspca_dev); |
1006 | if (0 <= ret) | 948 | return gspca_dev->usb_err; |
1007 | ret = 0; | ||
1008 | return ret; | ||
1009 | } | 949 | } |
1010 | 950 | ||
1011 | static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val) | 951 | static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -1019,14 +959,11 @@ static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val) | |||
1019 | static int sd_setredbalance(struct gspca_dev *gspca_dev, __s32 val) | 959 | static int sd_setredbalance(struct gspca_dev *gspca_dev, __s32 val) |
1020 | { | 960 | { |
1021 | struct sd *sd = (struct sd *) gspca_dev; | 961 | struct sd *sd = (struct sd *) gspca_dev; |
1022 | int ret = 0; | ||
1023 | 962 | ||
1024 | sd->red_balance = val; | 963 | sd->red_balance = val; |
1025 | if (gspca_dev->streaming) | 964 | if (gspca_dev->streaming) |
1026 | ret = setredbalance(gspca_dev); | 965 | setredbalance(gspca_dev); |
1027 | if (0 <= ret) | 966 | return gspca_dev->usb_err; |
1028 | ret = 0; | ||
1029 | return ret; | ||
1030 | } | 967 | } |
1031 | 968 | ||
1032 | static int sd_getredbalance(struct gspca_dev *gspca_dev, __s32 *val) | 969 | static int sd_getredbalance(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -1040,14 +977,11 @@ static int sd_getredbalance(struct gspca_dev *gspca_dev, __s32 *val) | |||
1040 | static int sd_setbluebalance(struct gspca_dev *gspca_dev, __s32 val) | 977 | static int sd_setbluebalance(struct gspca_dev *gspca_dev, __s32 val) |
1041 | { | 978 | { |
1042 | struct sd *sd = (struct sd *) gspca_dev; | 979 | struct sd *sd = (struct sd *) gspca_dev; |
1043 | int ret = 0; | ||
1044 | 980 | ||
1045 | sd->blue_balance = val; | 981 | sd->blue_balance = val; |
1046 | if (gspca_dev->streaming) | 982 | if (gspca_dev->streaming) |
1047 | ret = setbluebalance(gspca_dev); | 983 | setbluebalance(gspca_dev); |
1048 | if (0 <= ret) | 984 | return gspca_dev->usb_err; |
1049 | ret = 0; | ||
1050 | return ret; | ||
1051 | } | 985 | } |
1052 | 986 | ||
1053 | static int sd_getbluebalance(struct gspca_dev *gspca_dev, __s32 *val) | 987 | static int sd_getbluebalance(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -1065,7 +999,7 @@ static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val) | |||
1065 | sd->gain = val; | 999 | sd->gain = val; |
1066 | if (gspca_dev->streaming) | 1000 | if (gspca_dev->streaming) |
1067 | setgain(gspca_dev); | 1001 | setgain(gspca_dev); |
1068 | return 0; | 1002 | return gspca_dev->usb_err; |
1069 | } | 1003 | } |
1070 | 1004 | ||
1071 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) | 1005 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -1083,7 +1017,7 @@ static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val) | |||
1083 | sd->exposure = val; | 1017 | sd->exposure = val; |
1084 | if (gspca_dev->streaming) | 1018 | if (gspca_dev->streaming) |
1085 | setexposure(gspca_dev); | 1019 | setexposure(gspca_dev); |
1086 | return 0; | 1020 | return gspca_dev->usb_err; |
1087 | } | 1021 | } |
1088 | 1022 | ||
1089 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val) | 1023 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -1114,7 +1048,7 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) | |||
1114 | } | 1048 | } |
1115 | } | 1049 | } |
1116 | 1050 | ||
1117 | return 0; | 1051 | return gspca_dev->usb_err; |
1118 | } | 1052 | } |
1119 | 1053 | ||
1120 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) | 1054 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -1132,7 +1066,7 @@ static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val) | |||
1132 | sd->hflip = val; | 1066 | sd->hflip = val; |
1133 | if (gspca_dev->streaming) | 1067 | if (gspca_dev->streaming) |
1134 | sethvflip(gspca_dev); | 1068 | sethvflip(gspca_dev); |
1135 | return 0; | 1069 | return gspca_dev->usb_err; |
1136 | } | 1070 | } |
1137 | 1071 | ||
1138 | static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val) | 1072 | static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -1150,7 +1084,7 @@ static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val) | |||
1150 | sd->vflip = val; | 1084 | sd->vflip = val; |
1151 | if (gspca_dev->streaming) | 1085 | if (gspca_dev->streaming) |
1152 | sethvflip(gspca_dev); | 1086 | sethvflip(gspca_dev); |
1153 | return 0; | 1087 | return gspca_dev->usb_err; |
1154 | } | 1088 | } |
1155 | 1089 | ||
1156 | static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val) | 1090 | static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -1165,7 +1099,6 @@ static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val) | |||
1165 | static int sd_dbg_s_register(struct gspca_dev *gspca_dev, | 1099 | static int sd_dbg_s_register(struct gspca_dev *gspca_dev, |
1166 | struct v4l2_dbg_register *reg) | 1100 | struct v4l2_dbg_register *reg) |
1167 | { | 1101 | { |
1168 | int ret = -EINVAL; | ||
1169 | __u8 index; | 1102 | __u8 index; |
1170 | __u8 value; | 1103 | __u8 value; |
1171 | 1104 | ||
@@ -1185,14 +1118,12 @@ static int sd_dbg_s_register(struct gspca_dev *gspca_dev, | |||
1185 | /* Note that there shall be no access to other page | 1118 | /* Note that there shall be no access to other page |
1186 | by any other function between the page swith and | 1119 | by any other function between the page swith and |
1187 | the actual register write */ | 1120 | the actual register write */ |
1188 | ret = reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ | 1121 | reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ |
1189 | if (0 <= ret) | 1122 | reg_w(gspca_dev, index, value); |
1190 | ret = reg_w(gspca_dev, index, value); | ||
1191 | 1123 | ||
1192 | if (0 <= ret) | 1124 | reg_w(gspca_dev, 0xdc, 0x01); |
1193 | ret = reg_w(gspca_dev, 0xdc, 0x01); | ||
1194 | } | 1125 | } |
1195 | return ret; | 1126 | return gspca_dev->usb_err; |
1196 | } | 1127 | } |
1197 | 1128 | ||
1198 | static int sd_chip_ident(struct gspca_dev *gspca_dev, | 1129 | static int sd_chip_ident(struct gspca_dev *gspca_dev, |
@@ -1210,8 +1141,39 @@ static int sd_chip_ident(struct gspca_dev *gspca_dev, | |||
1210 | } | 1141 | } |
1211 | #endif | 1142 | #endif |
1212 | 1143 | ||
1144 | #ifdef CONFIG_INPUT | ||
1145 | static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, | ||
1146 | u8 *data, /* interrupt packet data */ | ||
1147 | int len) /* interrput packet length */ | ||
1148 | { | ||
1149 | int ret = -EINVAL; | ||
1150 | u8 data0, data1; | ||
1151 | |||
1152 | if (len == 2) { | ||
1153 | data0 = data[0]; | ||
1154 | data1 = data[1]; | ||
1155 | if ((data0 == 0x00 && data1 == 0x11) || | ||
1156 | (data0 == 0x22 && data1 == 0x33) || | ||
1157 | (data0 == 0x44 && data1 == 0x55) || | ||
1158 | (data0 == 0x66 && data1 == 0x77) || | ||
1159 | (data0 == 0x88 && data1 == 0x99) || | ||
1160 | (data0 == 0xaa && data1 == 0xbb) || | ||
1161 | (data0 == 0xcc && data1 == 0xdd) || | ||
1162 | (data0 == 0xee && data1 == 0xff)) { | ||
1163 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); | ||
1164 | input_sync(gspca_dev->input_dev); | ||
1165 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); | ||
1166 | input_sync(gspca_dev->input_dev); | ||
1167 | ret = 0; | ||
1168 | } | ||
1169 | } | ||
1170 | |||
1171 | return ret; | ||
1172 | } | ||
1173 | #endif | ||
1174 | |||
1213 | /* sub-driver description for pac7302 */ | 1175 | /* sub-driver description for pac7302 */ |
1214 | static struct sd_desc sd_desc = { | 1176 | static const struct sd_desc sd_desc = { |
1215 | .name = MODULE_NAME, | 1177 | .name = MODULE_NAME, |
1216 | .ctrls = sd_ctrls, | 1178 | .ctrls = sd_ctrls, |
1217 | .nctrls = ARRAY_SIZE(sd_ctrls), | 1179 | .nctrls = ARRAY_SIZE(sd_ctrls), |
@@ -1226,6 +1188,9 @@ static struct sd_desc sd_desc = { | |||
1226 | .set_register = sd_dbg_s_register, | 1188 | .set_register = sd_dbg_s_register, |
1227 | .get_chip_ident = sd_chip_ident, | 1189 | .get_chip_ident = sd_chip_ident, |
1228 | #endif | 1190 | #endif |
1191 | #ifdef CONFIG_INPUT | ||
1192 | .int_pkt_scan = sd_int_pkt_scan, | ||
1193 | #endif | ||
1229 | }; | 1194 | }; |
1230 | 1195 | ||
1231 | /* -- module initialisation -- */ | 1196 | /* -- module initialisation -- */ |
diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index 42cfcdfd8f4f..44fed9686729 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c | |||
@@ -51,6 +51,7 @@ | |||
51 | 51 | ||
52 | #define MODULE_NAME "pac7311" | 52 | #define MODULE_NAME "pac7311" |
53 | 53 | ||
54 | #include <linux/input.h> | ||
54 | #include "gspca.h" | 55 | #include "gspca.h" |
55 | 56 | ||
56 | MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li"); | 57 | MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li"); |
@@ -88,7 +89,7 @@ static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); | |||
88 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); | 89 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); |
89 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); | 90 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); |
90 | 91 | ||
91 | static struct ctrl sd_ctrls[] = { | 92 | static const struct ctrl sd_ctrls[] = { |
92 | /* This control is for both the 7302 and the 7311 */ | 93 | /* This control is for both the 7302 and the 7311 */ |
93 | { | 94 | { |
94 | { | 95 | { |
@@ -200,7 +201,6 @@ static const struct v4l2_pix_format vga_mode[] = { | |||
200 | .priv = 0}, | 201 | .priv = 0}, |
201 | }; | 202 | }; |
202 | 203 | ||
203 | #define LOAD_PAGE3 255 | ||
204 | #define LOAD_PAGE4 254 | 204 | #define LOAD_PAGE4 254 |
205 | #define END_OF_SEQUENCE 0 | 205 | #define END_OF_SEQUENCE 0 |
206 | 206 | ||
@@ -259,12 +259,14 @@ static const __u8 page4_7311[] = { | |||
259 | 0x23, 0x28, 0x04, 0x11, 0x00, 0x00 | 259 | 0x23, 0x28, 0x04, 0x11, 0x00, 0x00 |
260 | }; | 260 | }; |
261 | 261 | ||
262 | static int reg_w_buf(struct gspca_dev *gspca_dev, | 262 | static void reg_w_buf(struct gspca_dev *gspca_dev, |
263 | __u8 index, | 263 | __u8 index, |
264 | const char *buffer, int len) | 264 | const char *buffer, int len) |
265 | { | 265 | { |
266 | int ret; | 266 | int ret; |
267 | 267 | ||
268 | if (gspca_dev->usb_err < 0) | ||
269 | return; | ||
268 | memcpy(gspca_dev->usb_buf, buffer, len); | 270 | memcpy(gspca_dev->usb_buf, buffer, len); |
269 | ret = usb_control_msg(gspca_dev->dev, | 271 | ret = usb_control_msg(gspca_dev->dev, |
270 | usb_sndctrlpipe(gspca_dev->dev, 0), | 272 | usb_sndctrlpipe(gspca_dev->dev, 0), |
@@ -273,20 +275,23 @@ static int reg_w_buf(struct gspca_dev *gspca_dev, | |||
273 | 0, /* value */ | 275 | 0, /* value */ |
274 | index, gspca_dev->usb_buf, len, | 276 | index, gspca_dev->usb_buf, len, |
275 | 500); | 277 | 500); |
276 | if (ret < 0) | 278 | if (ret < 0) { |
277 | PDEBUG(D_ERR, "reg_w_buf(): " | 279 | PDEBUG(D_ERR, "reg_w_buf(): " |
278 | "Failed to write registers to index 0x%x, error %i", | 280 | "Failed to write registers to index 0x%x, error %i", |
279 | index, ret); | 281 | index, ret); |
280 | return ret; | 282 | gspca_dev->usb_err = ret; |
283 | } | ||
281 | } | 284 | } |
282 | 285 | ||
283 | 286 | ||
284 | static int reg_w(struct gspca_dev *gspca_dev, | 287 | static void reg_w(struct gspca_dev *gspca_dev, |
285 | __u8 index, | 288 | __u8 index, |
286 | __u8 value) | 289 | __u8 value) |
287 | { | 290 | { |
288 | int ret; | 291 | int ret; |
289 | 292 | ||
293 | if (gspca_dev->usb_err < 0) | ||
294 | return; | ||
290 | gspca_dev->usb_buf[0] = value; | 295 | gspca_dev->usb_buf[0] = value; |
291 | ret = usb_control_msg(gspca_dev->dev, | 296 | ret = usb_control_msg(gspca_dev->dev, |
292 | usb_sndctrlpipe(gspca_dev->dev, 0), | 297 | usb_sndctrlpipe(gspca_dev->dev, 0), |
@@ -294,32 +299,32 @@ static int reg_w(struct gspca_dev *gspca_dev, | |||
294 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 299 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
295 | 0, index, gspca_dev->usb_buf, 1, | 300 | 0, index, gspca_dev->usb_buf, 1, |
296 | 500); | 301 | 500); |
297 | if (ret < 0) | 302 | if (ret < 0) { |
298 | PDEBUG(D_ERR, "reg_w(): " | 303 | PDEBUG(D_ERR, "reg_w(): " |
299 | "Failed to write register to index 0x%x, value 0x%x, error %i", | 304 | "Failed to write register to index 0x%x, value 0x%x, error %i", |
300 | index, value, ret); | 305 | index, value, ret); |
301 | return ret; | 306 | gspca_dev->usb_err = ret; |
307 | } | ||
302 | } | 308 | } |
303 | 309 | ||
304 | static int reg_w_seq(struct gspca_dev *gspca_dev, | 310 | static void reg_w_seq(struct gspca_dev *gspca_dev, |
305 | const __u8 *seq, int len) | 311 | const __u8 *seq, int len) |
306 | { | 312 | { |
307 | int ret = 0; | ||
308 | while (--len >= 0) { | 313 | while (--len >= 0) { |
309 | if (0 <= ret) | 314 | reg_w(gspca_dev, seq[0], seq[1]); |
310 | ret = reg_w(gspca_dev, seq[0], seq[1]); | ||
311 | seq += 2; | 315 | seq += 2; |
312 | } | 316 | } |
313 | return ret; | ||
314 | } | 317 | } |
315 | 318 | ||
316 | /* load the beginning of a page */ | 319 | /* load the beginning of a page */ |
317 | static int reg_w_page(struct gspca_dev *gspca_dev, | 320 | static void reg_w_page(struct gspca_dev *gspca_dev, |
318 | const __u8 *page, int len) | 321 | const __u8 *page, int len) |
319 | { | 322 | { |
320 | int index; | 323 | int index; |
321 | int ret = 0; | 324 | int ret = 0; |
322 | 325 | ||
326 | if (gspca_dev->usb_err < 0) | ||
327 | return; | ||
323 | for (index = 0; index < len; index++) { | 328 | for (index = 0; index < len; index++) { |
324 | if (page[index] == SKIP) /* skip this index */ | 329 | if (page[index] == SKIP) /* skip this index */ |
325 | continue; | 330 | continue; |
@@ -335,56 +340,47 @@ static int reg_w_page(struct gspca_dev *gspca_dev, | |||
335 | "Failed to write register to index 0x%x, " | 340 | "Failed to write register to index 0x%x, " |
336 | "value 0x%x, error %i", | 341 | "value 0x%x, error %i", |
337 | index, page[index], ret); | 342 | index, page[index], ret); |
343 | gspca_dev->usb_err = ret; | ||
338 | break; | 344 | break; |
339 | } | 345 | } |
340 | } | 346 | } |
341 | return ret; | ||
342 | } | 347 | } |
343 | 348 | ||
344 | /* output a variable sequence */ | 349 | /* output a variable sequence */ |
345 | static int reg_w_var(struct gspca_dev *gspca_dev, | 350 | static void reg_w_var(struct gspca_dev *gspca_dev, |
346 | const __u8 *seq, | 351 | const __u8 *seq, |
347 | const __u8 *page3, unsigned int page3_len, | ||
348 | const __u8 *page4, unsigned int page4_len) | 352 | const __u8 *page4, unsigned int page4_len) |
349 | { | 353 | { |
350 | int index, len; | 354 | int index, len; |
351 | int ret = 0; | ||
352 | 355 | ||
353 | for (;;) { | 356 | for (;;) { |
354 | index = *seq++; | 357 | index = *seq++; |
355 | len = *seq++; | 358 | len = *seq++; |
356 | switch (len) { | 359 | switch (len) { |
357 | case END_OF_SEQUENCE: | 360 | case END_OF_SEQUENCE: |
358 | return ret; | 361 | return; |
359 | case LOAD_PAGE4: | 362 | case LOAD_PAGE4: |
360 | ret = reg_w_page(gspca_dev, page4, page4_len); | 363 | reg_w_page(gspca_dev, page4, page4_len); |
361 | break; | ||
362 | case LOAD_PAGE3: | ||
363 | ret = reg_w_page(gspca_dev, page3, page3_len); | ||
364 | break; | 364 | break; |
365 | default: | 365 | default: |
366 | if (len > USB_BUF_SZ) { | 366 | if (len > USB_BUF_SZ) { |
367 | PDEBUG(D_ERR|D_STREAM, | 367 | PDEBUG(D_ERR|D_STREAM, |
368 | "Incorrect variable sequence"); | 368 | "Incorrect variable sequence"); |
369 | return -EINVAL; | 369 | return; |
370 | } | 370 | } |
371 | while (len > 0) { | 371 | while (len > 0) { |
372 | if (len < 8) { | 372 | if (len < 8) { |
373 | ret = reg_w_buf(gspca_dev, | 373 | reg_w_buf(gspca_dev, |
374 | index, seq, len); | 374 | index, seq, len); |
375 | if (ret < 0) | ||
376 | return ret; | ||
377 | seq += len; | 375 | seq += len; |
378 | break; | 376 | break; |
379 | } | 377 | } |
380 | ret = reg_w_buf(gspca_dev, index, seq, 8); | 378 | reg_w_buf(gspca_dev, index, seq, 8); |
381 | seq += 8; | 379 | seq += 8; |
382 | index += 8; | 380 | index += 8; |
383 | len -= 8; | 381 | len -= 8; |
384 | } | 382 | } |
385 | } | 383 | } |
386 | if (ret < 0) | ||
387 | return ret; | ||
388 | } | 384 | } |
389 | /* not reached */ | 385 | /* not reached */ |
390 | } | 386 | } |
@@ -412,46 +408,36 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
412 | } | 408 | } |
413 | 409 | ||
414 | /* This function is used by pac7311 only */ | 410 | /* This function is used by pac7311 only */ |
415 | static int setcontrast(struct gspca_dev *gspca_dev) | 411 | static void setcontrast(struct gspca_dev *gspca_dev) |
416 | { | 412 | { |
417 | struct sd *sd = (struct sd *) gspca_dev; | 413 | struct sd *sd = (struct sd *) gspca_dev; |
418 | int ret; | ||
419 | 414 | ||
420 | ret = reg_w(gspca_dev, 0xff, 0x04); | 415 | reg_w(gspca_dev, 0xff, 0x04); |
421 | if (0 <= ret) | 416 | reg_w(gspca_dev, 0x10, sd->contrast >> 4); |
422 | ret = reg_w(gspca_dev, 0x10, sd->contrast >> 4); | ||
423 | /* load registers to sensor (Bit 0, auto clear) */ | 417 | /* load registers to sensor (Bit 0, auto clear) */ |
424 | if (0 <= ret) | 418 | reg_w(gspca_dev, 0x11, 0x01); |
425 | ret = reg_w(gspca_dev, 0x11, 0x01); | ||
426 | return ret; | ||
427 | } | 419 | } |
428 | 420 | ||
429 | static int setgain(struct gspca_dev *gspca_dev) | 421 | static void setgain(struct gspca_dev *gspca_dev) |
430 | { | 422 | { |
431 | struct sd *sd = (struct sd *) gspca_dev; | 423 | struct sd *sd = (struct sd *) gspca_dev; |
432 | int gain = GAIN_MAX - sd->gain; | 424 | int gain = GAIN_MAX - sd->gain; |
433 | int ret; | ||
434 | 425 | ||
435 | if (gain < 1) | 426 | if (gain < 1) |
436 | gain = 1; | 427 | gain = 1; |
437 | else if (gain > 245) | 428 | else if (gain > 245) |
438 | gain = 245; | 429 | gain = 245; |
439 | ret = reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ | 430 | reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ |
440 | if (0 <= ret) | 431 | reg_w(gspca_dev, 0x0e, 0x00); |
441 | ret = reg_w(gspca_dev, 0x0e, 0x00); | 432 | reg_w(gspca_dev, 0x0f, gain); |
442 | if (0 <= ret) | ||
443 | ret = reg_w(gspca_dev, 0x0f, gain); | ||
444 | 433 | ||
445 | /* load registers to sensor (Bit 0, auto clear) */ | 434 | /* load registers to sensor (Bit 0, auto clear) */ |
446 | if (0 <= ret) | 435 | reg_w(gspca_dev, 0x11, 0x01); |
447 | ret = reg_w(gspca_dev, 0x11, 0x01); | ||
448 | return ret; | ||
449 | } | 436 | } |
450 | 437 | ||
451 | static int setexposure(struct gspca_dev *gspca_dev) | 438 | static void setexposure(struct gspca_dev *gspca_dev) |
452 | { | 439 | { |
453 | struct sd *sd = (struct sd *) gspca_dev; | 440 | struct sd *sd = (struct sd *) gspca_dev; |
454 | int ret; | ||
455 | __u8 reg; | 441 | __u8 reg; |
456 | 442 | ||
457 | /* register 2 of frame 3/4 contains the clock divider configuring the | 443 | /* register 2 of frame 3/4 contains the clock divider configuring the |
@@ -463,94 +449,72 @@ static int setexposure(struct gspca_dev *gspca_dev) | |||
463 | else if (reg > 63) | 449 | else if (reg > 63) |
464 | reg = 63; | 450 | reg = 63; |
465 | 451 | ||
466 | ret = reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ | 452 | reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ |
467 | if (0 <= ret) | 453 | reg_w(gspca_dev, 0x02, reg); |
468 | ret = reg_w(gspca_dev, 0x02, reg); | 454 | |
469 | /* Page 1 register 8 must always be 0x08 except when not in | 455 | /* Page 1 register 8 must always be 0x08 except when not in |
470 | 640x480 mode and Page3/4 reg 2 <= 3 then it must be 9 */ | 456 | 640x480 mode and Page3/4 reg 2 <= 3 then it must be 9 */ |
471 | if (0 <= ret) | 457 | reg_w(gspca_dev, 0xff, 0x01); |
472 | ret = reg_w(gspca_dev, 0xff, 0x01); | ||
473 | if (gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv && | 458 | if (gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv && |
474 | reg <= 3) { | 459 | reg <= 3) { |
475 | if (0 <= ret) | 460 | reg_w(gspca_dev, 0x08, 0x09); |
476 | ret = reg_w(gspca_dev, 0x08, 0x09); | ||
477 | } else { | 461 | } else { |
478 | if (0 <= ret) | 462 | reg_w(gspca_dev, 0x08, 0x08); |
479 | ret = reg_w(gspca_dev, 0x08, 0x08); | ||
480 | } | 463 | } |
481 | 464 | ||
482 | /* load registers to sensor (Bit 0, auto clear) */ | 465 | /* load registers to sensor (Bit 0, auto clear) */ |
483 | if (0 <= ret) | 466 | reg_w(gspca_dev, 0x11, 0x01); |
484 | ret = reg_w(gspca_dev, 0x11, 0x01); | ||
485 | return ret; | ||
486 | } | 467 | } |
487 | 468 | ||
488 | static int sethvflip(struct gspca_dev *gspca_dev) | 469 | static void sethvflip(struct gspca_dev *gspca_dev) |
489 | { | 470 | { |
490 | struct sd *sd = (struct sd *) gspca_dev; | 471 | struct sd *sd = (struct sd *) gspca_dev; |
491 | int ret; | ||
492 | __u8 data; | 472 | __u8 data; |
493 | 473 | ||
494 | ret = reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ | 474 | reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ |
495 | data = (sd->hflip ? 0x04 : 0x00) | (sd->vflip ? 0x08 : 0x00); | 475 | data = (sd->hflip ? 0x04 : 0x00) | (sd->vflip ? 0x08 : 0x00); |
496 | if (0 <= ret) | 476 | reg_w(gspca_dev, 0x21, data); |
497 | ret = reg_w(gspca_dev, 0x21, data); | 477 | |
498 | /* load registers to sensor (Bit 0, auto clear) */ | 478 | /* load registers to sensor (Bit 0, auto clear) */ |
499 | if (0 <= ret) | 479 | reg_w(gspca_dev, 0x11, 0x01); |
500 | ret = reg_w(gspca_dev, 0x11, 0x01); | ||
501 | return ret; | ||
502 | } | 480 | } |
503 | 481 | ||
504 | /* this function is called at probe and resume time for pac7311 */ | 482 | /* this function is called at probe and resume time for pac7311 */ |
505 | static int sd_init(struct gspca_dev *gspca_dev) | 483 | static int sd_init(struct gspca_dev *gspca_dev) |
506 | { | 484 | { |
507 | return reg_w_seq(gspca_dev, init_7311, sizeof(init_7311)/2); | 485 | reg_w_seq(gspca_dev, init_7311, sizeof(init_7311)/2); |
486 | return gspca_dev->usb_err; | ||
508 | } | 487 | } |
509 | 488 | ||
510 | static int sd_start(struct gspca_dev *gspca_dev) | 489 | static int sd_start(struct gspca_dev *gspca_dev) |
511 | { | 490 | { |
512 | struct sd *sd = (struct sd *) gspca_dev; | 491 | struct sd *sd = (struct sd *) gspca_dev; |
513 | int ret; | ||
514 | 492 | ||
515 | sd->sof_read = 0; | 493 | sd->sof_read = 0; |
516 | 494 | ||
517 | ret = reg_w_var(gspca_dev, start_7311, | 495 | reg_w_var(gspca_dev, start_7311, |
518 | NULL, 0, | ||
519 | page4_7311, sizeof(page4_7311)); | 496 | page4_7311, sizeof(page4_7311)); |
520 | if (0 <= ret) | 497 | setcontrast(gspca_dev); |
521 | ret = setcontrast(gspca_dev); | 498 | setgain(gspca_dev); |
522 | if (0 <= ret) | 499 | setexposure(gspca_dev); |
523 | ret = setgain(gspca_dev); | 500 | sethvflip(gspca_dev); |
524 | if (0 <= ret) | ||
525 | ret = setexposure(gspca_dev); | ||
526 | if (0 <= ret) | ||
527 | ret = sethvflip(gspca_dev); | ||
528 | 501 | ||
529 | /* set correct resolution */ | 502 | /* set correct resolution */ |
530 | switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) { | 503 | switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) { |
531 | case 2: /* 160x120 pac7311 */ | 504 | case 2: /* 160x120 pac7311 */ |
532 | if (0 <= ret) | 505 | reg_w(gspca_dev, 0xff, 0x01); |
533 | ret = reg_w(gspca_dev, 0xff, 0x01); | 506 | reg_w(gspca_dev, 0x17, 0x20); |
534 | if (0 <= ret) | 507 | reg_w(gspca_dev, 0x87, 0x10); |
535 | ret = reg_w(gspca_dev, 0x17, 0x20); | ||
536 | if (0 <= ret) | ||
537 | ret = reg_w(gspca_dev, 0x87, 0x10); | ||
538 | break; | 508 | break; |
539 | case 1: /* 320x240 pac7311 */ | 509 | case 1: /* 320x240 pac7311 */ |
540 | if (0 <= ret) | 510 | reg_w(gspca_dev, 0xff, 0x01); |
541 | ret = reg_w(gspca_dev, 0xff, 0x01); | 511 | reg_w(gspca_dev, 0x17, 0x30); |
542 | if (0 <= ret) | 512 | reg_w(gspca_dev, 0x87, 0x11); |
543 | ret = reg_w(gspca_dev, 0x17, 0x30); | ||
544 | if (0 <= ret) | ||
545 | ret = reg_w(gspca_dev, 0x87, 0x11); | ||
546 | break; | 513 | break; |
547 | case 0: /* 640x480 */ | 514 | case 0: /* 640x480 */ |
548 | if (0 <= ret) | 515 | reg_w(gspca_dev, 0xff, 0x01); |
549 | ret = reg_w(gspca_dev, 0xff, 0x01); | 516 | reg_w(gspca_dev, 0x17, 0x00); |
550 | if (0 <= ret) | 517 | reg_w(gspca_dev, 0x87, 0x12); |
551 | ret = reg_w(gspca_dev, 0x17, 0x00); | ||
552 | if (0 <= ret) | ||
553 | ret = reg_w(gspca_dev, 0x87, 0x12); | ||
554 | break; | 518 | break; |
555 | } | 519 | } |
556 | 520 | ||
@@ -559,37 +523,24 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
559 | atomic_set(&sd->avg_lum, -1); | 523 | atomic_set(&sd->avg_lum, -1); |
560 | 524 | ||
561 | /* start stream */ | 525 | /* start stream */ |
562 | if (0 <= ret) | 526 | reg_w(gspca_dev, 0xff, 0x01); |
563 | ret = reg_w(gspca_dev, 0xff, 0x01); | 527 | reg_w(gspca_dev, 0x78, 0x05); |
564 | if (0 <= ret) | ||
565 | ret = reg_w(gspca_dev, 0x78, 0x05); | ||
566 | 528 | ||
567 | return ret; | 529 | return gspca_dev->usb_err; |
568 | } | 530 | } |
569 | 531 | ||
570 | static void sd_stopN(struct gspca_dev *gspca_dev) | 532 | static void sd_stopN(struct gspca_dev *gspca_dev) |
571 | { | 533 | { |
572 | int ret; | 534 | reg_w(gspca_dev, 0xff, 0x04); |
573 | 535 | reg_w(gspca_dev, 0x27, 0x80); | |
574 | ret = reg_w(gspca_dev, 0xff, 0x04); | 536 | reg_w(gspca_dev, 0x28, 0xca); |
575 | if (0 <= ret) | 537 | reg_w(gspca_dev, 0x29, 0x53); |
576 | ret = reg_w(gspca_dev, 0x27, 0x80); | 538 | reg_w(gspca_dev, 0x2a, 0x0e); |
577 | if (0 <= ret) | 539 | reg_w(gspca_dev, 0xff, 0x01); |
578 | ret = reg_w(gspca_dev, 0x28, 0xca); | 540 | reg_w(gspca_dev, 0x3e, 0x20); |
579 | if (0 <= ret) | 541 | reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ |
580 | ret = reg_w(gspca_dev, 0x29, 0x53); | 542 | reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ |
581 | if (0 <= ret) | 543 | reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ |
582 | ret = reg_w(gspca_dev, 0x2a, 0x0e); | ||
583 | if (0 <= ret) | ||
584 | ret = reg_w(gspca_dev, 0xff, 0x01); | ||
585 | if (0 <= ret) | ||
586 | ret = reg_w(gspca_dev, 0x3e, 0x20); | ||
587 | if (0 <= ret) | ||
588 | ret = reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ | ||
589 | if (0 <= ret) | ||
590 | ret = reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ | ||
591 | if (0 <= ret) | ||
592 | ret = reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ | ||
593 | } | 544 | } |
594 | 545 | ||
595 | /* called on streamoff with alt 0 and on disconnect for 7311 */ | 546 | /* called on streamoff with alt 0 and on disconnect for 7311 */ |
@@ -734,7 +685,7 @@ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) | |||
734 | if (gspca_dev->streaming) { | 685 | if (gspca_dev->streaming) { |
735 | setcontrast(gspca_dev); | 686 | setcontrast(gspca_dev); |
736 | } | 687 | } |
737 | return 0; | 688 | return gspca_dev->usb_err; |
738 | } | 689 | } |
739 | 690 | ||
740 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) | 691 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -752,7 +703,7 @@ static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val) | |||
752 | sd->gain = val; | 703 | sd->gain = val; |
753 | if (gspca_dev->streaming) | 704 | if (gspca_dev->streaming) |
754 | setgain(gspca_dev); | 705 | setgain(gspca_dev); |
755 | return 0; | 706 | return gspca_dev->usb_err; |
756 | } | 707 | } |
757 | 708 | ||
758 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) | 709 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -770,7 +721,7 @@ static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val) | |||
770 | sd->exposure = val; | 721 | sd->exposure = val; |
771 | if (gspca_dev->streaming) | 722 | if (gspca_dev->streaming) |
772 | setexposure(gspca_dev); | 723 | setexposure(gspca_dev); |
773 | return 0; | 724 | return gspca_dev->usb_err; |
774 | } | 725 | } |
775 | 726 | ||
776 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val) | 727 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -801,7 +752,7 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) | |||
801 | } | 752 | } |
802 | } | 753 | } |
803 | 754 | ||
804 | return 0; | 755 | return gspca_dev->usb_err; |
805 | } | 756 | } |
806 | 757 | ||
807 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) | 758 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -819,7 +770,7 @@ static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val) | |||
819 | sd->hflip = val; | 770 | sd->hflip = val; |
820 | if (gspca_dev->streaming) | 771 | if (gspca_dev->streaming) |
821 | sethvflip(gspca_dev); | 772 | sethvflip(gspca_dev); |
822 | return 0; | 773 | return gspca_dev->usb_err; |
823 | } | 774 | } |
824 | 775 | ||
825 | static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val) | 776 | static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -837,7 +788,7 @@ static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val) | |||
837 | sd->vflip = val; | 788 | sd->vflip = val; |
838 | if (gspca_dev->streaming) | 789 | if (gspca_dev->streaming) |
839 | sethvflip(gspca_dev); | 790 | sethvflip(gspca_dev); |
840 | return 0; | 791 | return gspca_dev->usb_err; |
841 | } | 792 | } |
842 | 793 | ||
843 | static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val) | 794 | static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -848,8 +799,39 @@ static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val) | |||
848 | return 0; | 799 | return 0; |
849 | } | 800 | } |
850 | 801 | ||
802 | #ifdef CONFIG_INPUT | ||
803 | static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, | ||
804 | u8 *data, /* interrupt packet data */ | ||
805 | int len) /* interrupt packet length */ | ||
806 | { | ||
807 | int ret = -EINVAL; | ||
808 | u8 data0, data1; | ||
809 | |||
810 | if (len == 2) { | ||
811 | data0 = data[0]; | ||
812 | data1 = data[1]; | ||
813 | if ((data0 == 0x00 && data1 == 0x11) || | ||
814 | (data0 == 0x22 && data1 == 0x33) || | ||
815 | (data0 == 0x44 && data1 == 0x55) || | ||
816 | (data0 == 0x66 && data1 == 0x77) || | ||
817 | (data0 == 0x88 && data1 == 0x99) || | ||
818 | (data0 == 0xaa && data1 == 0xbb) || | ||
819 | (data0 == 0xcc && data1 == 0xdd) || | ||
820 | (data0 == 0xee && data1 == 0xff)) { | ||
821 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); | ||
822 | input_sync(gspca_dev->input_dev); | ||
823 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); | ||
824 | input_sync(gspca_dev->input_dev); | ||
825 | ret = 0; | ||
826 | } | ||
827 | } | ||
828 | |||
829 | return ret; | ||
830 | } | ||
831 | #endif | ||
832 | |||
851 | /* sub-driver description for pac7311 */ | 833 | /* sub-driver description for pac7311 */ |
852 | static struct sd_desc sd_desc = { | 834 | static const struct sd_desc sd_desc = { |
853 | .name = MODULE_NAME, | 835 | .name = MODULE_NAME, |
854 | .ctrls = sd_ctrls, | 836 | .ctrls = sd_ctrls, |
855 | .nctrls = ARRAY_SIZE(sd_ctrls), | 837 | .nctrls = ARRAY_SIZE(sd_ctrls), |
@@ -860,6 +842,9 @@ static struct sd_desc sd_desc = { | |||
860 | .stop0 = sd_stop0, | 842 | .stop0 = sd_stop0, |
861 | .pkt_scan = sd_pkt_scan, | 843 | .pkt_scan = sd_pkt_scan, |
862 | .dq_callback = do_autogain, | 844 | .dq_callback = do_autogain, |
845 | #ifdef CONFIG_INPUT | ||
846 | .int_pkt_scan = sd_int_pkt_scan, | ||
847 | #endif | ||
863 | }; | 848 | }; |
864 | 849 | ||
865 | /* -- module initialisation -- */ | 850 | /* -- module initialisation -- */ |
diff --git a/drivers/media/video/gspca/pac_common.h b/drivers/media/video/gspca/pac_common.h index 20f67d9b8c06..8462a7c1a338 100644 --- a/drivers/media/video/gspca/pac_common.h +++ b/drivers/media/video/gspca/pac_common.h | |||
@@ -24,11 +24,10 @@ | |||
24 | */ | 24 | */ |
25 | 25 | ||
26 | /* We calculate the autogain at the end of the transfer of a frame, at this | 26 | /* We calculate the autogain at the end of the transfer of a frame, at this |
27 | moment a frame with the old settings is being transmitted, and a frame is | 27 | moment a frame with the old settings is being captured and transmitted. So |
28 | being captured with the old settings. So if we adjust the autogain we must | 28 | if we adjust the gain or exposure we must ignore atleast the next frame for |
29 | ignore atleast the 2 next frames for the new settings to come into effect | 29 | the new settings to come into effect before doing any other adjustments. */ |
30 | before doing any other adjustments */ | 30 | #define PAC_AUTOGAIN_IGNORE_FRAMES 2 |
31 | #define PAC_AUTOGAIN_IGNORE_FRAMES 3 | ||
32 | 31 | ||
33 | static const unsigned char pac_sof_marker[5] = | 32 | static const unsigned char pac_sof_marker[5] = |
34 | { 0xff, 0xff, 0x00, 0xff, 0x96 }; | 33 | { 0xff, 0xff, 0x00, 0xff, 0x96 }; |
diff --git a/drivers/media/video/gspca/sn9c2028.c b/drivers/media/video/gspca/sn9c2028.c new file mode 100644 index 000000000000..dda5fd4aa69e --- /dev/null +++ b/drivers/media/video/gspca/sn9c2028.c | |||
@@ -0,0 +1,757 @@ | |||
1 | /* | ||
2 | * SN9C2028 library | ||
3 | * | ||
4 | * Copyright (C) 2009 Theodore Kilgore <kilgota@auburn.edu> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #define MODULE_NAME "sn9c2028" | ||
22 | |||
23 | #include "gspca.h" | ||
24 | |||
25 | MODULE_AUTHOR("Theodore Kilgore"); | ||
26 | MODULE_DESCRIPTION("Sonix SN9C2028 USB Camera Driver"); | ||
27 | MODULE_LICENSE("GPL"); | ||
28 | |||
29 | /* specific webcam descriptor */ | ||
30 | struct sd { | ||
31 | struct gspca_dev gspca_dev; /* !! must be the first item */ | ||
32 | u8 sof_read; | ||
33 | u16 model; | ||
34 | }; | ||
35 | |||
36 | struct init_command { | ||
37 | unsigned char instruction[6]; | ||
38 | unsigned char to_read; /* length to read. 0 means no reply requested */ | ||
39 | }; | ||
40 | |||
41 | /* V4L2 controls supported by the driver */ | ||
42 | static struct ctrl sd_ctrls[] = { | ||
43 | }; | ||
44 | |||
45 | /* How to change the resolution of any of the VGA cams is unknown */ | ||
46 | static const struct v4l2_pix_format vga_mode[] = { | ||
47 | {640, 480, V4L2_PIX_FMT_SN9C2028, V4L2_FIELD_NONE, | ||
48 | .bytesperline = 640, | ||
49 | .sizeimage = 640 * 480 * 3 / 4, | ||
50 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
51 | .priv = 0}, | ||
52 | }; | ||
53 | |||
54 | /* No way to change the resolution of the CIF cams is known */ | ||
55 | static const struct v4l2_pix_format cif_mode[] = { | ||
56 | {352, 288, V4L2_PIX_FMT_SN9C2028, V4L2_FIELD_NONE, | ||
57 | .bytesperline = 352, | ||
58 | .sizeimage = 352 * 288 * 3 / 4, | ||
59 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
60 | .priv = 0}, | ||
61 | }; | ||
62 | |||
63 | /* the bytes to write are in gspca_dev->usb_buf */ | ||
64 | static int sn9c2028_command(struct gspca_dev *gspca_dev, u8 *command) | ||
65 | { | ||
66 | int rc; | ||
67 | |||
68 | PDEBUG(D_USBO, "sending command %02x%02x%02x%02x%02x%02x", command[0], | ||
69 | command[1], command[2], command[3], command[4], command[5]); | ||
70 | |||
71 | memcpy(gspca_dev->usb_buf, command, 6); | ||
72 | rc = usb_control_msg(gspca_dev->dev, | ||
73 | usb_sndctrlpipe(gspca_dev->dev, 0), | ||
74 | USB_REQ_GET_CONFIGURATION, | ||
75 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, | ||
76 | 2, 0, gspca_dev->usb_buf, 6, 500); | ||
77 | if (rc < 0) { | ||
78 | PDEBUG(D_ERR, "command write [%02x] error %d", | ||
79 | gspca_dev->usb_buf[0], rc); | ||
80 | return rc; | ||
81 | } | ||
82 | |||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | static int sn9c2028_read1(struct gspca_dev *gspca_dev) | ||
87 | { | ||
88 | int rc; | ||
89 | |||
90 | rc = usb_control_msg(gspca_dev->dev, | ||
91 | usb_rcvctrlpipe(gspca_dev->dev, 0), | ||
92 | USB_REQ_GET_STATUS, | ||
93 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, | ||
94 | 1, 0, gspca_dev->usb_buf, 1, 500); | ||
95 | if (rc != 1) { | ||
96 | PDEBUG(D_ERR, "read1 error %d", rc); | ||
97 | return (rc < 0) ? rc : -EIO; | ||
98 | } | ||
99 | PDEBUG(D_USBI, "read1 response %02x", gspca_dev->usb_buf[0]); | ||
100 | return gspca_dev->usb_buf[0]; | ||
101 | } | ||
102 | |||
103 | static int sn9c2028_read4(struct gspca_dev *gspca_dev, u8 *reading) | ||
104 | { | ||
105 | int rc; | ||
106 | rc = usb_control_msg(gspca_dev->dev, | ||
107 | usb_rcvctrlpipe(gspca_dev->dev, 0), | ||
108 | USB_REQ_GET_STATUS, | ||
109 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, | ||
110 | 4, 0, gspca_dev->usb_buf, 4, 500); | ||
111 | if (rc != 4) { | ||
112 | PDEBUG(D_ERR, "read4 error %d", rc); | ||
113 | return (rc < 0) ? rc : -EIO; | ||
114 | } | ||
115 | memcpy(reading, gspca_dev->usb_buf, 4); | ||
116 | PDEBUG(D_USBI, "read4 response %02x%02x%02x%02x", reading[0], | ||
117 | reading[1], reading[2], reading[3]); | ||
118 | return rc; | ||
119 | } | ||
120 | |||
121 | static int sn9c2028_long_command(struct gspca_dev *gspca_dev, u8 *command) | ||
122 | { | ||
123 | int i, status; | ||
124 | __u8 reading[4]; | ||
125 | |||
126 | status = sn9c2028_command(gspca_dev, command); | ||
127 | if (status < 0) | ||
128 | return status; | ||
129 | |||
130 | status = -1; | ||
131 | for (i = 0; i < 256 && status < 2; i++) | ||
132 | status = sn9c2028_read1(gspca_dev); | ||
133 | if (status != 2) { | ||
134 | PDEBUG(D_ERR, "long command status read error %d", status); | ||
135 | return (status < 0) ? status : -EIO; | ||
136 | } | ||
137 | |||
138 | memset(reading, 0, 4); | ||
139 | status = sn9c2028_read4(gspca_dev, reading); | ||
140 | if (status < 0) | ||
141 | return status; | ||
142 | |||
143 | /* in general, the first byte of the response is the first byte of | ||
144 | * the command, or'ed with 8 */ | ||
145 | status = sn9c2028_read1(gspca_dev); | ||
146 | if (status < 0) | ||
147 | return status; | ||
148 | |||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | static int sn9c2028_short_command(struct gspca_dev *gspca_dev, u8 *command) | ||
153 | { | ||
154 | int err_code; | ||
155 | |||
156 | err_code = sn9c2028_command(gspca_dev, command); | ||
157 | if (err_code < 0) | ||
158 | return err_code; | ||
159 | |||
160 | err_code = sn9c2028_read1(gspca_dev); | ||
161 | if (err_code < 0) | ||
162 | return err_code; | ||
163 | |||
164 | return 0; | ||
165 | } | ||
166 | |||
167 | /* this function is called at probe time */ | ||
168 | static int sd_config(struct gspca_dev *gspca_dev, | ||
169 | const struct usb_device_id *id) | ||
170 | { | ||
171 | struct sd *sd = (struct sd *) gspca_dev; | ||
172 | struct cam *cam = &gspca_dev->cam; | ||
173 | |||
174 | PDEBUG(D_PROBE, "SN9C2028 camera detected (vid/pid 0x%04X:0x%04X)", | ||
175 | id->idVendor, id->idProduct); | ||
176 | |||
177 | sd->model = id->idProduct; | ||
178 | |||
179 | switch (sd->model) { | ||
180 | case 0x7005: | ||
181 | PDEBUG(D_PROBE, "Genius Smart 300 camera"); | ||
182 | break; | ||
183 | case 0x8000: | ||
184 | PDEBUG(D_PROBE, "DC31VC"); | ||
185 | break; | ||
186 | case 0x8001: | ||
187 | PDEBUG(D_PROBE, "Spy camera"); | ||
188 | break; | ||
189 | case 0x8003: | ||
190 | PDEBUG(D_PROBE, "CIF camera"); | ||
191 | break; | ||
192 | case 0x8008: | ||
193 | PDEBUG(D_PROBE, "Mini-Shotz ms-350 camera"); | ||
194 | break; | ||
195 | case 0x800a: | ||
196 | PDEBUG(D_PROBE, "Vivitar 3350b type camera"); | ||
197 | cam->input_flags = V4L2_IN_ST_VFLIP | V4L2_IN_ST_HFLIP; | ||
198 | break; | ||
199 | } | ||
200 | |||
201 | switch (sd->model) { | ||
202 | case 0x8000: | ||
203 | case 0x8001: | ||
204 | case 0x8003: | ||
205 | cam->cam_mode = cif_mode; | ||
206 | cam->nmodes = ARRAY_SIZE(cif_mode); | ||
207 | break; | ||
208 | default: | ||
209 | cam->cam_mode = vga_mode; | ||
210 | cam->nmodes = ARRAY_SIZE(vga_mode); | ||
211 | } | ||
212 | return 0; | ||
213 | } | ||
214 | |||
215 | /* this function is called at probe and resume time */ | ||
216 | static int sd_init(struct gspca_dev *gspca_dev) | ||
217 | { | ||
218 | int status = -1; | ||
219 | |||
220 | sn9c2028_read1(gspca_dev); | ||
221 | sn9c2028_read1(gspca_dev); | ||
222 | status = sn9c2028_read1(gspca_dev); | ||
223 | |||
224 | return (status < 0) ? status : 0; | ||
225 | } | ||
226 | |||
227 | static int run_start_commands(struct gspca_dev *gspca_dev, | ||
228 | struct init_command *cam_commands, int n) | ||
229 | { | ||
230 | int i, err_code = -1; | ||
231 | |||
232 | for (i = 0; i < n; i++) { | ||
233 | switch (cam_commands[i].to_read) { | ||
234 | case 4: | ||
235 | err_code = sn9c2028_long_command(gspca_dev, | ||
236 | cam_commands[i].instruction); | ||
237 | break; | ||
238 | case 1: | ||
239 | err_code = sn9c2028_short_command(gspca_dev, | ||
240 | cam_commands[i].instruction); | ||
241 | break; | ||
242 | case 0: | ||
243 | err_code = sn9c2028_command(gspca_dev, | ||
244 | cam_commands[i].instruction); | ||
245 | break; | ||
246 | } | ||
247 | if (err_code < 0) | ||
248 | return err_code; | ||
249 | } | ||
250 | return 0; | ||
251 | } | ||
252 | |||
253 | static int start_spy_cam(struct gspca_dev *gspca_dev) | ||
254 | { | ||
255 | struct init_command spy_start_commands[] = { | ||
256 | {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
257 | {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
258 | {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
259 | {{0x13, 0x22, 0x01, 0x04, 0x00, 0x00}, 4}, | ||
260 | {{0x13, 0x23, 0x01, 0x03, 0x00, 0x00}, 4}, | ||
261 | {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
262 | {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, /* width 352 */ | ||
263 | {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, /* height 288 */ | ||
264 | /* {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4}, */ | ||
265 | {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4}, | ||
266 | {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4}, /* red gain ?*/ | ||
267 | /* {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4}, */ | ||
268 | {{0x13, 0x29, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
269 | /* {{0x13, 0x29, 0x01, 0x0c, 0x00, 0x00}, 4}, */ | ||
270 | {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
271 | {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
272 | /* {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, */ | ||
273 | {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, | ||
274 | {{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4}, | ||
275 | /* {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4}, */ | ||
276 | {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4}, | ||
277 | {{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4}, | ||
278 | {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
279 | {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4}, | ||
280 | {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
281 | {{0x11, 0x02, 0x06, 0x00, 0x00, 0x00}, 4}, | ||
282 | {{0x11, 0x03, 0x13, 0x00, 0x00, 0x00}, 4}, /*don't mess with*/ | ||
283 | /*{{0x11, 0x04, 0x06, 0x00, 0x00, 0x00}, 4}, observed */ | ||
284 | {{0x11, 0x04, 0x00, 0x00, 0x00, 0x00}, 4}, /* brighter */ | ||
285 | /*{{0x11, 0x05, 0x65, 0x00, 0x00, 0x00}, 4}, observed */ | ||
286 | {{0x11, 0x05, 0x00, 0x00, 0x00, 0x00}, 4}, /* brighter */ | ||
287 | {{0x11, 0x06, 0xb1, 0x00, 0x00, 0x00}, 4}, /* observed */ | ||
288 | {{0x11, 0x07, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
289 | /*{{0x11, 0x08, 0x06, 0x00, 0x00, 0x00}, 4}, observed */ | ||
290 | {{0x11, 0x08, 0x0b, 0x00, 0x00, 0x00}, 4}, | ||
291 | {{0x11, 0x09, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
292 | {{0x11, 0x0a, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
293 | {{0x11, 0x0b, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
294 | {{0x11, 0x0c, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
295 | {{0x11, 0x0d, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
296 | {{0x11, 0x0e, 0x04, 0x00, 0x00, 0x00}, 4}, | ||
297 | /* {{0x11, 0x0f, 0x00, 0x00, 0x00, 0x00}, 4}, */ | ||
298 | /* brightness or gain. 0 is default. 4 is good | ||
299 | * indoors at night with incandescent lighting */ | ||
300 | {{0x11, 0x0f, 0x04, 0x00, 0x00, 0x00}, 4}, | ||
301 | {{0x11, 0x10, 0x06, 0x00, 0x00, 0x00}, 4}, /*hstart or hoffs*/ | ||
302 | {{0x11, 0x11, 0x06, 0x00, 0x00, 0x00}, 4}, | ||
303 | {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
304 | {{0x11, 0x14, 0x02, 0x00, 0x00, 0x00}, 4}, | ||
305 | {{0x11, 0x13, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
306 | /* {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1}, observed */ | ||
307 | {{0x1b, 0x02, 0x11, 0x00, 0x00, 0x00}, 1}, /* brighter */ | ||
308 | /* {{0x1b, 0x13, 0x01, 0x00, 0x00, 0x00}, 1}, observed */ | ||
309 | {{0x1b, 0x13, 0x11, 0x00, 0x00, 0x00}, 1}, | ||
310 | {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1}, /* compresses */ | ||
311 | /* Camera should start to capture now. */ | ||
312 | }; | ||
313 | |||
314 | return run_start_commands(gspca_dev, spy_start_commands, | ||
315 | ARRAY_SIZE(spy_start_commands)); | ||
316 | } | ||
317 | |||
318 | static int start_cif_cam(struct gspca_dev *gspca_dev) | ||
319 | { | ||
320 | struct init_command cif_start_commands[] = { | ||
321 | {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
322 | /* The entire sequence below seems redundant */ | ||
323 | /* {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
324 | {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
325 | {{0x13, 0x22, 0x01, 0x06, 0x00, 0x00}, 4}, | ||
326 | {{0x13, 0x23, 0x01, 0x02, 0x00, 0x00}, 4}, | ||
327 | {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
328 | {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, width? | ||
329 | {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, height? | ||
330 | {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4}, subsample? | ||
331 | {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
332 | {{0x13, 0x29, 0x01, 0x20, 0x00, 0x00}, 4}, | ||
333 | {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
334 | {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
335 | {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, | ||
336 | {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4}, | ||
337 | {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4}, | ||
338 | {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4}, | ||
339 | {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
340 | {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4}, | ||
341 | {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},*/ | ||
342 | {{0x1b, 0x21, 0x00, 0x00, 0x00, 0x00}, 1}, | ||
343 | {{0x1b, 0x17, 0x00, 0x00, 0x00, 0x00}, 1}, | ||
344 | {{0x1b, 0x19, 0x00, 0x00, 0x00, 0x00}, 1}, | ||
345 | {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1}, | ||
346 | {{0x1b, 0x03, 0x5a, 0x00, 0x00, 0x00}, 1}, | ||
347 | {{0x1b, 0x04, 0x27, 0x00, 0x00, 0x00}, 1}, | ||
348 | {{0x1b, 0x05, 0x01, 0x00, 0x00, 0x00}, 1}, | ||
349 | {{0x1b, 0x12, 0x14, 0x00, 0x00, 0x00}, 1}, | ||
350 | {{0x1b, 0x13, 0x00, 0x00, 0x00, 0x00}, 1}, | ||
351 | {{0x1b, 0x14, 0x00, 0x00, 0x00, 0x00}, 1}, | ||
352 | {{0x1b, 0x15, 0x00, 0x00, 0x00, 0x00}, 1}, | ||
353 | {{0x1b, 0x16, 0x00, 0x00, 0x00, 0x00}, 1}, | ||
354 | {{0x1b, 0x77, 0xa2, 0x00, 0x00, 0x00}, 1}, | ||
355 | {{0x1b, 0x06, 0x0f, 0x00, 0x00, 0x00}, 1}, | ||
356 | {{0x1b, 0x07, 0x14, 0x00, 0x00, 0x00}, 1}, | ||
357 | {{0x1b, 0x08, 0x0f, 0x00, 0x00, 0x00}, 1}, | ||
358 | {{0x1b, 0x09, 0x10, 0x00, 0x00, 0x00}, 1}, | ||
359 | {{0x1b, 0x0e, 0x00, 0x00, 0x00, 0x00}, 1}, | ||
360 | {{0x1b, 0x0f, 0x00, 0x00, 0x00, 0x00}, 1}, | ||
361 | {{0x1b, 0x12, 0x07, 0x00, 0x00, 0x00}, 1}, | ||
362 | {{0x1b, 0x10, 0x1f, 0x00, 0x00, 0x00}, 1}, | ||
363 | {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1}, | ||
364 | {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 1}, /* width/8 */ | ||
365 | {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 1}, /* height/8 */ | ||
366 | /* {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4}, subsample? | ||
367 | * {{0x13, 0x28, 0x01, 0x1e, 0x00, 0x00}, 4}, does nothing | ||
368 | * {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, */ | ||
369 | /* {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4}, | ||
370 | * causes subsampling | ||
371 | * but not a change in the resolution setting! */ | ||
372 | {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, | ||
373 | {{0x13, 0x2d, 0x01, 0x01, 0x00, 0x00}, 4}, | ||
374 | {{0x13, 0x2e, 0x01, 0x08, 0x00, 0x00}, 4}, | ||
375 | {{0x13, 0x2f, 0x01, 0x06, 0x00, 0x00}, 4}, | ||
376 | {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
377 | {{0x1b, 0x04, 0x6d, 0x00, 0x00, 0x00}, 1}, | ||
378 | {{0x1b, 0x05, 0x03, 0x00, 0x00, 0x00}, 1}, | ||
379 | {{0x20, 0x36, 0x06, 0x00, 0x00, 0x00}, 1}, | ||
380 | {{0x1b, 0x0e, 0x01, 0x00, 0x00, 0x00}, 1}, | ||
381 | {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
382 | {{0x1b, 0x0f, 0x00, 0x00, 0x00, 0x00}, 1}, | ||
383 | {{0x20, 0x36, 0x05, 0x00, 0x00, 0x00}, 1}, | ||
384 | {{0x1b, 0x10, 0x0f, 0x00, 0x00, 0x00}, 1}, | ||
385 | {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1}, | ||
386 | {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1}, | ||
387 | {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1},/* use compression */ | ||
388 | /* Camera should start to capture now. */ | ||
389 | }; | ||
390 | |||
391 | return run_start_commands(gspca_dev, cif_start_commands, | ||
392 | ARRAY_SIZE(cif_start_commands)); | ||
393 | } | ||
394 | |||
395 | static int start_ms350_cam(struct gspca_dev *gspca_dev) | ||
396 | { | ||
397 | struct init_command ms350_start_commands[] = { | ||
398 | {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
399 | {{0x16, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
400 | {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
401 | {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
402 | {{0x13, 0x22, 0x01, 0x04, 0x00, 0x00}, 4}, | ||
403 | {{0x13, 0x23, 0x01, 0x03, 0x00, 0x00}, 4}, | ||
404 | {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
405 | {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, | ||
406 | {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, | ||
407 | {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4}, | ||
408 | {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4}, | ||
409 | {{0x13, 0x29, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
410 | {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
411 | {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
412 | {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, | ||
413 | {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4}, | ||
414 | {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4}, | ||
415 | {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4}, | ||
416 | {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
417 | {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4}, | ||
418 | {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
419 | {{0x11, 0x00, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
420 | {{0x11, 0x01, 0x70, 0x00, 0x00, 0x00}, 4}, | ||
421 | {{0x11, 0x02, 0x05, 0x00, 0x00, 0x00}, 4}, | ||
422 | {{0x11, 0x03, 0x5d, 0x00, 0x00, 0x00}, 4}, | ||
423 | {{0x11, 0x04, 0x07, 0x00, 0x00, 0x00}, 4}, | ||
424 | {{0x11, 0x05, 0x25, 0x00, 0x00, 0x00}, 4}, | ||
425 | {{0x11, 0x06, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
426 | {{0x11, 0x07, 0x09, 0x00, 0x00, 0x00}, 4}, | ||
427 | {{0x11, 0x08, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
428 | {{0x11, 0x09, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
429 | {{0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
430 | {{0x11, 0x0b, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
431 | {{0x11, 0x0c, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
432 | {{0x11, 0x0d, 0x0c, 0x00, 0x00, 0x00}, 4}, | ||
433 | {{0x11, 0x0e, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
434 | {{0x11, 0x0f, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
435 | {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
436 | {{0x11, 0x11, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
437 | {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
438 | {{0x11, 0x13, 0x63, 0x00, 0x00, 0x00}, 4}, | ||
439 | {{0x11, 0x15, 0x70, 0x00, 0x00, 0x00}, 4}, | ||
440 | {{0x11, 0x18, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
441 | {{0x11, 0x11, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
442 | {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, /* width */ | ||
443 | {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, /* height */ | ||
444 | {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4}, /* vstart? */ | ||
445 | {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4}, | ||
446 | {{0x13, 0x29, 0x01, 0x40, 0x00, 0x00}, 4}, /* hstart? */ | ||
447 | {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, | ||
448 | {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4}, | ||
449 | {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4}, | ||
450 | {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4}, | ||
451 | {{0x1b, 0x02, 0x05, 0x00, 0x00, 0x00}, 1}, | ||
452 | {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1}, | ||
453 | {{0x20, 0x18, 0x00, 0x00, 0x00, 0x00}, 1}, | ||
454 | {{0x1b, 0x02, 0x0a, 0x00, 0x00, 0x00}, 1}, | ||
455 | {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 0}, | ||
456 | /* Camera should start to capture now. */ | ||
457 | }; | ||
458 | |||
459 | return run_start_commands(gspca_dev, ms350_start_commands, | ||
460 | ARRAY_SIZE(ms350_start_commands)); | ||
461 | } | ||
462 | |||
463 | static int start_genius_cam(struct gspca_dev *gspca_dev) | ||
464 | { | ||
465 | struct init_command genius_start_commands[] = { | ||
466 | {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
467 | {{0x16, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
468 | {{0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
469 | {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, | ||
470 | {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, | ||
471 | /* "preliminary" width and height settings */ | ||
472 | {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4}, | ||
473 | {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, | ||
474 | {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4}, | ||
475 | {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, | ||
476 | {{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4}, | ||
477 | {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4}, | ||
478 | {{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4}, | ||
479 | {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
480 | {{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4}, | ||
481 | {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
482 | {{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4}, | ||
483 | {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
484 | {{0x11, 0x11, 0x64, 0x00, 0x00, 0x00}, 4}, | ||
485 | {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
486 | {{0x11, 0x13, 0x91, 0x00, 0x00, 0x00}, 4}, | ||
487 | {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
488 | {{0x11, 0x15, 0x20, 0x00, 0x00, 0x00}, 4}, | ||
489 | {{0x11, 0x16, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
490 | {{0x11, 0x17, 0x60, 0x00, 0x00, 0x00}, 4}, | ||
491 | {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
492 | {{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4}, | ||
493 | {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
494 | {{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4}, | ||
495 | {{0x11, 0x25, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
496 | {{0x11, 0x26, 0x02, 0x00, 0x00, 0x00}, 4}, | ||
497 | {{0x11, 0x27, 0x88, 0x00, 0x00, 0x00}, 4}, | ||
498 | {{0x11, 0x30, 0x38, 0x00, 0x00, 0x00}, 4}, | ||
499 | {{0x11, 0x31, 0x2a, 0x00, 0x00, 0x00}, 4}, | ||
500 | {{0x11, 0x32, 0x2a, 0x00, 0x00, 0x00}, 4}, | ||
501 | {{0x11, 0x33, 0x2a, 0x00, 0x00, 0x00}, 4}, | ||
502 | {{0x11, 0x34, 0x02, 0x00, 0x00, 0x00}, 4}, | ||
503 | {{0x11, 0x5b, 0x0a, 0x00, 0x00, 0x00}, 4}, | ||
504 | {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, /* real width */ | ||
505 | {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, /* real height */ | ||
506 | {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4}, | ||
507 | {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, | ||
508 | {{0x13, 0x29, 0x01, 0x62, 0x00, 0x00}, 4}, | ||
509 | {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, | ||
510 | {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4}, | ||
511 | {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4}, | ||
512 | {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4}, | ||
513 | {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
514 | {{0x11, 0x21, 0x2a, 0x00, 0x00, 0x00}, 4}, | ||
515 | {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
516 | {{0x11, 0x23, 0x28, 0x00, 0x00, 0x00}, 4}, | ||
517 | {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
518 | {{0x11, 0x11, 0x04, 0x00, 0x00, 0x00}, 4}, | ||
519 | {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
520 | {{0x11, 0x13, 0x03, 0x00, 0x00, 0x00}, 4}, | ||
521 | {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
522 | {{0x11, 0x15, 0xe0, 0x00, 0x00, 0x00}, 4}, | ||
523 | {{0x11, 0x16, 0x02, 0x00, 0x00, 0x00}, 4}, | ||
524 | {{0x11, 0x17, 0x80, 0x00, 0x00, 0x00}, 4}, | ||
525 | {{0x1c, 0x20, 0x00, 0x2a, 0x00, 0x00}, 1}, | ||
526 | {{0x1c, 0x20, 0x00, 0x2a, 0x00, 0x00}, 1}, | ||
527 | {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 0} | ||
528 | /* Camera should start to capture now. */ | ||
529 | }; | ||
530 | |||
531 | return run_start_commands(gspca_dev, genius_start_commands, | ||
532 | ARRAY_SIZE(genius_start_commands)); | ||
533 | } | ||
534 | |||
535 | static int start_vivitar_cam(struct gspca_dev *gspca_dev) | ||
536 | { | ||
537 | struct init_command vivitar_start_commands[] = { | ||
538 | {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
539 | {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
540 | {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
541 | {{0x13, 0x22, 0x01, 0x01, 0x00, 0x00}, 4}, | ||
542 | {{0x13, 0x23, 0x01, 0x01, 0x00, 0x00}, 4}, | ||
543 | {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
544 | {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, | ||
545 | {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, | ||
546 | {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, | ||
547 | {{0x13, 0x28, 0x01, 0x0a, 0x00, 0x00}, 4}, | ||
548 | /* | ||
549 | * Above is changed from OEM 0x0b. Fixes Bayer tiling. | ||
550 | * Presumably gives a vertical shift of one row. | ||
551 | */ | ||
552 | {{0x13, 0x29, 0x01, 0x20, 0x00, 0x00}, 4}, | ||
553 | /* Above seems to do horizontal shift. */ | ||
554 | {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
555 | {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
556 | {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, | ||
557 | {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4}, | ||
558 | {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4}, | ||
559 | {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4}, | ||
560 | /* Above three commands seem to relate to brightness. */ | ||
561 | {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
562 | {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4}, | ||
563 | {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
564 | {{0x1b, 0x12, 0x80, 0x00, 0x00, 0x00}, 1}, | ||
565 | {{0x1b, 0x01, 0x77, 0x00, 0x00, 0x00}, 1}, | ||
566 | {{0x1b, 0x02, 0x3a, 0x00, 0x00, 0x00}, 1}, | ||
567 | {{0x1b, 0x12, 0x78, 0x00, 0x00, 0x00}, 1}, | ||
568 | {{0x1b, 0x13, 0x00, 0x00, 0x00, 0x00}, 1}, | ||
569 | {{0x1b, 0x14, 0x80, 0x00, 0x00, 0x00}, 1}, | ||
570 | {{0x1b, 0x15, 0x34, 0x00, 0x00, 0x00}, 1}, | ||
571 | {{0x1b, 0x1b, 0x04, 0x00, 0x00, 0x00}, 1}, | ||
572 | {{0x1b, 0x20, 0x44, 0x00, 0x00, 0x00}, 1}, | ||
573 | {{0x1b, 0x23, 0xee, 0x00, 0x00, 0x00}, 1}, | ||
574 | {{0x1b, 0x26, 0xa0, 0x00, 0x00, 0x00}, 1}, | ||
575 | {{0x1b, 0x27, 0x9a, 0x00, 0x00, 0x00}, 1}, | ||
576 | {{0x1b, 0x28, 0xa0, 0x00, 0x00, 0x00}, 1}, | ||
577 | {{0x1b, 0x29, 0x30, 0x00, 0x00, 0x00}, 1}, | ||
578 | {{0x1b, 0x2a, 0x80, 0x00, 0x00, 0x00}, 1}, | ||
579 | {{0x1b, 0x2b, 0x00, 0x00, 0x00, 0x00}, 1}, | ||
580 | {{0x1b, 0x2f, 0x3d, 0x00, 0x00, 0x00}, 1}, | ||
581 | {{0x1b, 0x30, 0x24, 0x00, 0x00, 0x00}, 1}, | ||
582 | {{0x1b, 0x32, 0x86, 0x00, 0x00, 0x00}, 1}, | ||
583 | {{0x1b, 0x60, 0xa9, 0x00, 0x00, 0x00}, 1}, | ||
584 | {{0x1b, 0x61, 0x42, 0x00, 0x00, 0x00}, 1}, | ||
585 | {{0x1b, 0x65, 0x00, 0x00, 0x00, 0x00}, 1}, | ||
586 | {{0x1b, 0x69, 0x38, 0x00, 0x00, 0x00}, 1}, | ||
587 | {{0x1b, 0x6f, 0x88, 0x00, 0x00, 0x00}, 1}, | ||
588 | {{0x1b, 0x70, 0x0b, 0x00, 0x00, 0x00}, 1}, | ||
589 | {{0x1b, 0x71, 0x00, 0x00, 0x00, 0x00}, 1}, | ||
590 | {{0x1b, 0x74, 0x21, 0x00, 0x00, 0x00}, 1}, | ||
591 | {{0x1b, 0x75, 0x86, 0x00, 0x00, 0x00}, 1}, | ||
592 | {{0x1b, 0x76, 0x00, 0x00, 0x00, 0x00}, 1}, | ||
593 | {{0x1b, 0x7d, 0xf3, 0x00, 0x00, 0x00}, 1}, | ||
594 | {{0x1b, 0x17, 0x1c, 0x00, 0x00, 0x00}, 1}, | ||
595 | {{0x1b, 0x18, 0xc0, 0x00, 0x00, 0x00}, 1}, | ||
596 | {{0x1b, 0x19, 0x05, 0x00, 0x00, 0x00}, 1}, | ||
597 | {{0x1b, 0x1a, 0xf6, 0x00, 0x00, 0x00}, 1}, | ||
598 | /* {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, | ||
599 | {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, | ||
600 | {{0x13, 0x28, 0x01, 0x0b, 0x00, 0x00}, 4}, */ | ||
601 | {{0x20, 0x36, 0x06, 0x00, 0x00, 0x00}, 1}, | ||
602 | {{0x1b, 0x10, 0x26, 0x00, 0x00, 0x00}, 1}, | ||
603 | {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
604 | {{0x1b, 0x76, 0x03, 0x00, 0x00, 0x00}, 1}, | ||
605 | {{0x20, 0x36, 0x05, 0x00, 0x00, 0x00}, 1}, | ||
606 | {{0x1b, 0x00, 0x3f, 0x00, 0x00, 0x00}, 1}, | ||
607 | /* Above is brightness; OEM driver setting is 0x10 */ | ||
608 | {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
609 | {{0x20, 0x29, 0x30, 0x00, 0x00, 0x00}, 1}, | ||
610 | {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1} | ||
611 | }; | ||
612 | |||
613 | return run_start_commands(gspca_dev, vivitar_start_commands, | ||
614 | ARRAY_SIZE(vivitar_start_commands)); | ||
615 | } | ||
616 | |||
617 | static int sd_start(struct gspca_dev *gspca_dev) | ||
618 | { | ||
619 | struct sd *sd = (struct sd *) gspca_dev; | ||
620 | int err_code; | ||
621 | |||
622 | sd->sof_read = 0; | ||
623 | |||
624 | switch (sd->model) { | ||
625 | case 0x7005: | ||
626 | err_code = start_genius_cam(gspca_dev); | ||
627 | break; | ||
628 | case 0x8001: | ||
629 | err_code = start_spy_cam(gspca_dev); | ||
630 | break; | ||
631 | case 0x8003: | ||
632 | err_code = start_cif_cam(gspca_dev); | ||
633 | break; | ||
634 | case 0x8008: | ||
635 | err_code = start_ms350_cam(gspca_dev); | ||
636 | break; | ||
637 | case 0x800a: | ||
638 | err_code = start_vivitar_cam(gspca_dev); | ||
639 | break; | ||
640 | default: | ||
641 | PDEBUG(D_ERR, "Starting unknown camera, please report this"); | ||
642 | return -ENXIO; | ||
643 | } | ||
644 | |||
645 | return err_code; | ||
646 | } | ||
647 | |||
648 | static void sd_stopN(struct gspca_dev *gspca_dev) | ||
649 | { | ||
650 | int result; | ||
651 | __u8 data[6]; | ||
652 | |||
653 | result = sn9c2028_read1(gspca_dev); | ||
654 | if (result < 0) | ||
655 | PDEBUG(D_ERR, "Camera Stop read failed"); | ||
656 | |||
657 | memset(data, 0, 6); | ||
658 | data[0] = 0x14; | ||
659 | result = sn9c2028_command(gspca_dev, data); | ||
660 | if (result < 0) | ||
661 | PDEBUG(D_ERR, "Camera Stop command failed"); | ||
662 | } | ||
663 | |||
664 | /* Include sn9c2028 sof detection functions */ | ||
665 | #include "sn9c2028.h" | ||
666 | |||
667 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | ||
668 | __u8 *data, /* isoc packet */ | ||
669 | int len) /* iso packet length */ | ||
670 | { | ||
671 | unsigned char *sof; | ||
672 | |||
673 | sof = sn9c2028_find_sof(gspca_dev, data, len); | ||
674 | if (sof) { | ||
675 | int n; | ||
676 | |||
677 | /* finish decoding current frame */ | ||
678 | n = sof - data; | ||
679 | if (n > sizeof sn9c2028_sof_marker) | ||
680 | n -= sizeof sn9c2028_sof_marker; | ||
681 | else | ||
682 | n = 0; | ||
683 | gspca_frame_add(gspca_dev, LAST_PACKET, data, n); | ||
684 | /* Start next frame. */ | ||
685 | gspca_frame_add(gspca_dev, FIRST_PACKET, | ||
686 | sn9c2028_sof_marker, sizeof sn9c2028_sof_marker); | ||
687 | len -= sof - data; | ||
688 | data = sof; | ||
689 | } | ||
690 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); | ||
691 | } | ||
692 | |||
693 | /* sub-driver description */ | ||
694 | static const struct sd_desc sd_desc = { | ||
695 | .name = MODULE_NAME, | ||
696 | .ctrls = sd_ctrls, | ||
697 | .nctrls = ARRAY_SIZE(sd_ctrls), | ||
698 | .config = sd_config, | ||
699 | .init = sd_init, | ||
700 | .start = sd_start, | ||
701 | .stopN = sd_stopN, | ||
702 | .pkt_scan = sd_pkt_scan, | ||
703 | }; | ||
704 | |||
705 | /* -- module initialisation -- */ | ||
706 | static const __devinitdata struct usb_device_id device_table[] = { | ||
707 | {USB_DEVICE(0x0458, 0x7005)}, /* Genius Smart 300, version 2 */ | ||
708 | /* The Genius Smart is untested. I can't find an owner ! */ | ||
709 | /* {USB_DEVICE(0x0c45, 0x8000)}, DC31VC, Don't know this camera */ | ||
710 | {USB_DEVICE(0x0c45, 0x8001)}, /* Wild Planet digital spy cam */ | ||
711 | {USB_DEVICE(0x0c45, 0x8003)}, /* Several small CIF cameras */ | ||
712 | /* {USB_DEVICE(0x0c45, 0x8006)}, Unknown VGA camera */ | ||
713 | {USB_DEVICE(0x0c45, 0x8008)}, /* Mini-Shotz ms-350 */ | ||
714 | {USB_DEVICE(0x0c45, 0x800a)}, /* Vivicam 3350B */ | ||
715 | {} | ||
716 | }; | ||
717 | MODULE_DEVICE_TABLE(usb, device_table); | ||
718 | |||
719 | /* -- device connect -- */ | ||
720 | static int sd_probe(struct usb_interface *intf, | ||
721 | const struct usb_device_id *id) | ||
722 | { | ||
723 | return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), | ||
724 | THIS_MODULE); | ||
725 | } | ||
726 | |||
727 | static struct usb_driver sd_driver = { | ||
728 | .name = MODULE_NAME, | ||
729 | .id_table = device_table, | ||
730 | .probe = sd_probe, | ||
731 | .disconnect = gspca_disconnect, | ||
732 | #ifdef CONFIG_PM | ||
733 | .suspend = gspca_suspend, | ||
734 | .resume = gspca_resume, | ||
735 | #endif | ||
736 | }; | ||
737 | |||
738 | /* -- module insert / remove -- */ | ||
739 | static int __init sd_mod_init(void) | ||
740 | { | ||
741 | int ret; | ||
742 | |||
743 | ret = usb_register(&sd_driver); | ||
744 | if (ret < 0) | ||
745 | return ret; | ||
746 | PDEBUG(D_PROBE, "registered"); | ||
747 | return 0; | ||
748 | } | ||
749 | |||
750 | static void __exit sd_mod_exit(void) | ||
751 | { | ||
752 | usb_deregister(&sd_driver); | ||
753 | PDEBUG(D_PROBE, "deregistered"); | ||
754 | } | ||
755 | |||
756 | module_init(sd_mod_init); | ||
757 | module_exit(sd_mod_exit); | ||
diff --git a/drivers/media/video/gspca/sn9c2028.h b/drivers/media/video/gspca/sn9c2028.h new file mode 100644 index 000000000000..8fd1d3e05665 --- /dev/null +++ b/drivers/media/video/gspca/sn9c2028.h | |||
@@ -0,0 +1,51 @@ | |||
1 | /* | ||
2 | * SN9C2028 common functions | ||
3 | * | ||
4 | * Copyright (C) 2009 Theodore Kilgore <kilgota@auburn,edu> | ||
5 | * | ||
6 | * Based closely upon the file gspca/pac_common.h | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | static const unsigned char sn9c2028_sof_marker[5] = | ||
25 | { 0xff, 0xff, 0x00, 0xc4, 0xc4 }; | ||
26 | |||
27 | static unsigned char *sn9c2028_find_sof(struct gspca_dev *gspca_dev, | ||
28 | unsigned char *m, int len) | ||
29 | { | ||
30 | struct sd *sd = (struct sd *) gspca_dev; | ||
31 | int i; | ||
32 | |||
33 | /* Search for the SOF marker (fixed part) in the header */ | ||
34 | for (i = 0; i < len; i++) { | ||
35 | if (m[i] == sn9c2028_sof_marker[sd->sof_read]) { | ||
36 | sd->sof_read++; | ||
37 | if (sd->sof_read == sizeof(sn9c2028_sof_marker)) { | ||
38 | PDEBUG(D_FRAM, | ||
39 | "SOF found, bytes to analyze: %u." | ||
40 | " Frame starts at byte #%u", | ||
41 | len, i + 1); | ||
42 | sd->sof_read = 0; | ||
43 | return m + i + 1; | ||
44 | } | ||
45 | } else { | ||
46 | sd->sof_read = 0; | ||
47 | } | ||
48 | } | ||
49 | |||
50 | return NULL; | ||
51 | } | ||
diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c index 0ca1c06652b1..4a1bc08f82b9 100644 --- a/drivers/media/video/gspca/sn9c20x.c +++ b/drivers/media/video/gspca/sn9c20x.c | |||
@@ -129,7 +129,7 @@ static int sd_getexposure(struct gspca_dev *gspca_dev, s32 *val); | |||
129 | static int sd_setautoexposure(struct gspca_dev *gspca_dev, s32 val); | 129 | static int sd_setautoexposure(struct gspca_dev *gspca_dev, s32 val); |
130 | static int sd_getautoexposure(struct gspca_dev *gspca_dev, s32 *val); | 130 | static int sd_getautoexposure(struct gspca_dev *gspca_dev, s32 *val); |
131 | 131 | ||
132 | static struct ctrl sd_ctrls[] = { | 132 | static const struct ctrl sd_ctrls[] = { |
133 | { | 133 | { |
134 | #define BRIGHTNESS_IDX 0 | 134 | #define BRIGHTNESS_IDX 0 |
135 | { | 135 | { |
@@ -1506,36 +1506,36 @@ static int set_cmatrix(struct gspca_dev *gspca_dev) | |||
1506 | struct sd *sd = (struct sd *) gspca_dev; | 1506 | struct sd *sd = (struct sd *) gspca_dev; |
1507 | s32 hue_coord, hue_index = 180 + sd->hue; | 1507 | s32 hue_coord, hue_index = 180 + sd->hue; |
1508 | u8 cmatrix[21]; | 1508 | u8 cmatrix[21]; |
1509 | memset(cmatrix, 0, 21); | ||
1510 | 1509 | ||
1510 | memset(cmatrix, 0, sizeof cmatrix); | ||
1511 | cmatrix[2] = (sd->contrast * 0x25 / 0x100) + 0x26; | 1511 | cmatrix[2] = (sd->contrast * 0x25 / 0x100) + 0x26; |
1512 | cmatrix[0] = 0x13 + (cmatrix[2] - 0x26) * 0x13 / 0x25; | 1512 | cmatrix[0] = 0x13 + (cmatrix[2] - 0x26) * 0x13 / 0x25; |
1513 | cmatrix[4] = 0x07 + (cmatrix[2] - 0x26) * 0x07 / 0x25; | 1513 | cmatrix[4] = 0x07 + (cmatrix[2] - 0x26) * 0x07 / 0x25; |
1514 | cmatrix[18] = sd->brightness - 0x80; | 1514 | cmatrix[18] = sd->brightness - 0x80; |
1515 | 1515 | ||
1516 | hue_coord = (hsv_red_x[hue_index] * sd->saturation) >> 8; | 1516 | hue_coord = (hsv_red_x[hue_index] * sd->saturation) >> 8; |
1517 | cmatrix[6] = (unsigned char)(hue_coord & 0xff); | 1517 | cmatrix[6] = hue_coord; |
1518 | cmatrix[7] = (unsigned char)((hue_coord >> 8) & 0x0f); | 1518 | cmatrix[7] = (hue_coord >> 8) & 0x0f; |
1519 | 1519 | ||
1520 | hue_coord = (hsv_red_y[hue_index] * sd->saturation) >> 8; | 1520 | hue_coord = (hsv_red_y[hue_index] * sd->saturation) >> 8; |
1521 | cmatrix[8] = (unsigned char)(hue_coord & 0xff); | 1521 | cmatrix[8] = hue_coord; |
1522 | cmatrix[9] = (unsigned char)((hue_coord >> 8) & 0x0f); | 1522 | cmatrix[9] = (hue_coord >> 8) & 0x0f; |
1523 | 1523 | ||
1524 | hue_coord = (hsv_green_x[hue_index] * sd->saturation) >> 8; | 1524 | hue_coord = (hsv_green_x[hue_index] * sd->saturation) >> 8; |
1525 | cmatrix[10] = (unsigned char)(hue_coord & 0xff); | 1525 | cmatrix[10] = hue_coord; |
1526 | cmatrix[11] = (unsigned char)((hue_coord >> 8) & 0x0f); | 1526 | cmatrix[11] = (hue_coord >> 8) & 0x0f; |
1527 | 1527 | ||
1528 | hue_coord = (hsv_green_y[hue_index] * sd->saturation) >> 8; | 1528 | hue_coord = (hsv_green_y[hue_index] * sd->saturation) >> 8; |
1529 | cmatrix[12] = (unsigned char)(hue_coord & 0xff); | 1529 | cmatrix[12] = hue_coord; |
1530 | cmatrix[13] = (unsigned char)((hue_coord >> 8) & 0x0f); | 1530 | cmatrix[13] = (hue_coord >> 8) & 0x0f; |
1531 | 1531 | ||
1532 | hue_coord = (hsv_blue_x[hue_index] * sd->saturation) >> 8; | 1532 | hue_coord = (hsv_blue_x[hue_index] * sd->saturation) >> 8; |
1533 | cmatrix[14] = (unsigned char)(hue_coord & 0xff); | 1533 | cmatrix[14] = hue_coord; |
1534 | cmatrix[15] = (unsigned char)((hue_coord >> 8) & 0x0f); | 1534 | cmatrix[15] = (hue_coord >> 8) & 0x0f; |
1535 | 1535 | ||
1536 | hue_coord = (hsv_blue_y[hue_index] * sd->saturation) >> 8; | 1536 | hue_coord = (hsv_blue_y[hue_index] * sd->saturation) >> 8; |
1537 | cmatrix[16] = (unsigned char)(hue_coord & 0xff); | 1537 | cmatrix[16] = hue_coord; |
1538 | cmatrix[17] = (unsigned char)((hue_coord >> 8) & 0x0f); | 1538 | cmatrix[17] = (hue_coord >> 8) & 0x0f; |
1539 | 1539 | ||
1540 | return reg_w(gspca_dev, 0x10e1, cmatrix, 21); | 1540 | return reg_w(gspca_dev, 0x10e1, cmatrix, 21); |
1541 | } | 1541 | } |
@@ -2015,6 +2015,7 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
2015 | default: | 2015 | default: |
2016 | cam->cam_mode = vga_mode; | 2016 | cam->cam_mode = vga_mode; |
2017 | cam->nmodes = ARRAY_SIZE(vga_mode); | 2017 | cam->nmodes = ARRAY_SIZE(vga_mode); |
2018 | break; | ||
2018 | } | 2019 | } |
2019 | 2020 | ||
2020 | sd->old_step = 0; | 2021 | sd->old_step = 0; |
@@ -2319,7 +2320,7 @@ static void do_autogain(struct gspca_dev *gspca_dev, u16 avg_lum) | |||
2319 | } | 2320 | } |
2320 | } | 2321 | } |
2321 | if (avg_lum > MAX_AVG_LUM) { | 2322 | if (avg_lum > MAX_AVG_LUM) { |
2322 | if (sd->gain >= 1) { | 2323 | if (sd->gain > 0) { |
2323 | sd->gain--; | 2324 | sd->gain--; |
2324 | set_gain(gspca_dev); | 2325 | set_gain(gspca_dev); |
2325 | } | 2326 | } |
@@ -2347,7 +2348,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
2347 | { | 2348 | { |
2348 | struct sd *sd = (struct sd *) gspca_dev; | 2349 | struct sd *sd = (struct sd *) gspca_dev; |
2349 | int avg_lum; | 2350 | int avg_lum; |
2350 | static unsigned char frame_header[] = | 2351 | static u8 frame_header[] = |
2351 | {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96}; | 2352 | {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96}; |
2352 | if (len == 64 && memcmp(data, frame_header, 6) == 0) { | 2353 | if (len == 64 && memcmp(data, frame_header, 6) == 0) { |
2353 | avg_lum = ((data[35] >> 2) & 3) | | 2354 | avg_lum = ((data[35] >> 2) & 3) | |
diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index ddff2b5ee5c2..785eeb4c2014 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c | |||
@@ -42,6 +42,7 @@ Reg Use | |||
42 | 42 | ||
43 | #define MODULE_NAME "sonixb" | 43 | #define MODULE_NAME "sonixb" |
44 | 44 | ||
45 | #include <linux/input.h> | ||
45 | #include "gspca.h" | 46 | #include "gspca.h" |
46 | 47 | ||
47 | MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); | 48 | MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); |
@@ -53,9 +54,11 @@ struct sd { | |||
53 | struct gspca_dev gspca_dev; /* !! must be the first item */ | 54 | struct gspca_dev gspca_dev; /* !! must be the first item */ |
54 | atomic_t avg_lum; | 55 | atomic_t avg_lum; |
55 | int prev_avg_lum; | 56 | int prev_avg_lum; |
57 | int exp_too_low_cnt; | ||
58 | int exp_too_high_cnt; | ||
56 | 59 | ||
60 | unsigned short exposure; | ||
57 | unsigned char gain; | 61 | unsigned char gain; |
58 | unsigned char exposure; | ||
59 | unsigned char brightness; | 62 | unsigned char brightness; |
60 | unsigned char autogain; | 63 | unsigned char autogain; |
61 | unsigned char autogain_ignore_frames; | 64 | unsigned char autogain_ignore_frames; |
@@ -73,8 +76,9 @@ struct sd { | |||
73 | #define SENSOR_OV7630 2 | 76 | #define SENSOR_OV7630 2 |
74 | #define SENSOR_PAS106 3 | 77 | #define SENSOR_PAS106 3 |
75 | #define SENSOR_PAS202 4 | 78 | #define SENSOR_PAS202 4 |
76 | #define SENSOR_TAS5110 5 | 79 | #define SENSOR_TAS5110C 5 |
77 | #define SENSOR_TAS5130CXX 6 | 80 | #define SENSOR_TAS5110D 6 |
81 | #define SENSOR_TAS5130CXX 7 | ||
78 | __u8 reg11; | 82 | __u8 reg11; |
79 | }; | 83 | }; |
80 | 84 | ||
@@ -95,13 +99,15 @@ struct sensor_data { | |||
95 | /* sensor_data flags */ | 99 | /* sensor_data flags */ |
96 | #define F_GAIN 0x01 /* has gain */ | 100 | #define F_GAIN 0x01 /* has gain */ |
97 | #define F_SIF 0x02 /* sif or vga */ | 101 | #define F_SIF 0x02 /* sif or vga */ |
102 | #define F_COARSE_EXPO 0x04 /* exposure control is coarse */ | ||
98 | 103 | ||
99 | /* priv field of struct v4l2_pix_format flags (do not use low nibble!) */ | 104 | /* priv field of struct v4l2_pix_format flags (do not use low nibble!) */ |
100 | #define MODE_RAW 0x10 /* raw bayer mode */ | 105 | #define MODE_RAW 0x10 /* raw bayer mode */ |
101 | #define MODE_REDUCED_SIF 0x20 /* vga mode (320x240 / 160x120) on sif cam */ | 106 | #define MODE_REDUCED_SIF 0x20 /* vga mode (320x240 / 160x120) on sif cam */ |
102 | 107 | ||
103 | /* ctrl_dis helper macros */ | 108 | /* ctrl_dis helper macros */ |
104 | #define NO_EXPO ((1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX)) | 109 | #define NO_EXPO ((1 << EXPOSURE_IDX) | (1 << COARSE_EXPOSURE_IDX) | \ |
110 | (1 << AUTOGAIN_IDX)) | ||
105 | #define NO_FREQ (1 << FREQ_IDX) | 111 | #define NO_FREQ (1 << FREQ_IDX) |
106 | #define NO_BRIGHTNESS (1 << BRIGHTNESS_IDX) | 112 | #define NO_BRIGHTNESS (1 << BRIGHTNESS_IDX) |
107 | 113 | ||
@@ -127,11 +133,10 @@ struct sensor_data { | |||
127 | } | 133 | } |
128 | 134 | ||
129 | /* We calculate the autogain at the end of the transfer of a frame, at this | 135 | /* We calculate the autogain at the end of the transfer of a frame, at this |
130 | moment a frame with the old settings is being transmitted, and a frame is | 136 | moment a frame with the old settings is being captured and transmitted. So |
131 | being captured with the old settings. So if we adjust the autogain we must | 137 | if we adjust the gain or exposure we must ignore atleast the next frame for |
132 | ignore atleast the 2 next frames for the new settings to come into effect | 138 | the new settings to come into effect before doing any other adjustments. */ |
133 | before doing any other adjustments */ | 139 | #define AUTOGAIN_IGNORE_FRAMES 1 |
134 | #define AUTOGAIN_IGNORE_FRAMES 3 | ||
135 | 140 | ||
136 | /* V4L2 controls supported by the driver */ | 141 | /* V4L2 controls supported by the driver */ |
137 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | 142 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); |
@@ -145,7 +150,7 @@ static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); | |||
145 | static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); | 150 | static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); |
146 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); | 151 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); |
147 | 152 | ||
148 | static struct ctrl sd_ctrls[] = { | 153 | static const struct ctrl sd_ctrls[] = { |
149 | #define BRIGHTNESS_IDX 0 | 154 | #define BRIGHTNESS_IDX 0 |
150 | { | 155 | { |
151 | { | 156 | { |
@@ -171,7 +176,7 @@ static struct ctrl sd_ctrls[] = { | |||
171 | .maximum = 255, | 176 | .maximum = 255, |
172 | .step = 1, | 177 | .step = 1, |
173 | #define GAIN_DEF 127 | 178 | #define GAIN_DEF 127 |
174 | #define GAIN_KNEE 200 | 179 | #define GAIN_KNEE 230 |
175 | .default_value = GAIN_DEF, | 180 | .default_value = GAIN_DEF, |
176 | }, | 181 | }, |
177 | .set = sd_setgain, | 182 | .set = sd_setgain, |
@@ -183,10 +188,10 @@ static struct ctrl sd_ctrls[] = { | |||
183 | .id = V4L2_CID_EXPOSURE, | 188 | .id = V4L2_CID_EXPOSURE, |
184 | .type = V4L2_CTRL_TYPE_INTEGER, | 189 | .type = V4L2_CTRL_TYPE_INTEGER, |
185 | .name = "Exposure", | 190 | .name = "Exposure", |
186 | #define EXPOSURE_DEF 16 /* 32 ms / 30 fps */ | 191 | #define EXPOSURE_DEF 66 /* 33 ms / 30 fps (except on PASXXX) */ |
187 | #define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */ | 192 | #define EXPOSURE_KNEE 200 /* 100 ms / 10 fps (except on PASXXX) */ |
188 | .minimum = 0, | 193 | .minimum = 0, |
189 | .maximum = 255, | 194 | .maximum = 1023, |
190 | .step = 1, | 195 | .step = 1, |
191 | .default_value = EXPOSURE_DEF, | 196 | .default_value = EXPOSURE_DEF, |
192 | .flags = 0, | 197 | .flags = 0, |
@@ -194,7 +199,23 @@ static struct ctrl sd_ctrls[] = { | |||
194 | .set = sd_setexposure, | 199 | .set = sd_setexposure, |
195 | .get = sd_getexposure, | 200 | .get = sd_getexposure, |
196 | }, | 201 | }, |
197 | #define AUTOGAIN_IDX 3 | 202 | #define COARSE_EXPOSURE_IDX 3 |
203 | { | ||
204 | { | ||
205 | .id = V4L2_CID_EXPOSURE, | ||
206 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
207 | .name = "Exposure", | ||
208 | #define COARSE_EXPOSURE_DEF 2 /* 30 fps */ | ||
209 | .minimum = 2, | ||
210 | .maximum = 15, | ||
211 | .step = 1, | ||
212 | .default_value = COARSE_EXPOSURE_DEF, | ||
213 | .flags = 0, | ||
214 | }, | ||
215 | .set = sd_setexposure, | ||
216 | .get = sd_getexposure, | ||
217 | }, | ||
218 | #define AUTOGAIN_IDX 4 | ||
198 | { | 219 | { |
199 | { | 220 | { |
200 | .id = V4L2_CID_AUTOGAIN, | 221 | .id = V4L2_CID_AUTOGAIN, |
@@ -210,7 +231,7 @@ static struct ctrl sd_ctrls[] = { | |||
210 | .set = sd_setautogain, | 231 | .set = sd_setautogain, |
211 | .get = sd_getautogain, | 232 | .get = sd_getautogain, |
212 | }, | 233 | }, |
213 | #define FREQ_IDX 4 | 234 | #define FREQ_IDX 5 |
214 | { | 235 | { |
215 | { | 236 | { |
216 | .id = V4L2_CID_POWER_LINE_FREQUENCY, | 237 | .id = V4L2_CID_POWER_LINE_FREQUENCY, |
@@ -219,7 +240,7 @@ static struct ctrl sd_ctrls[] = { | |||
219 | .minimum = 0, | 240 | .minimum = 0, |
220 | .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */ | 241 | .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */ |
221 | .step = 1, | 242 | .step = 1, |
222 | #define FREQ_DEF 1 | 243 | #define FREQ_DEF 0 |
223 | .default_value = FREQ_DEF, | 244 | .default_value = FREQ_DEF, |
224 | }, | 245 | }, |
225 | .set = sd_setfreq, | 246 | .set = sd_setfreq, |
@@ -345,7 +366,7 @@ static const __u8 initOv7630[] = { | |||
345 | }; | 366 | }; |
346 | static const __u8 initOv7630_3[] = { | 367 | static const __u8 initOv7630_3[] = { |
347 | 0x44, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0x80, /* r01 .. r08 */ | 368 | 0x44, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0x80, /* r01 .. r08 */ |
348 | 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, /* r09 .. r10 */ | 369 | 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */ |
349 | 0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */ | 370 | 0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */ |
350 | 0x28, 0x1e, /* H & V sizes r15 .. r16 */ | 371 | 0x28, 0x1e, /* H & V sizes r15 .. r16 */ |
351 | 0x68, 0x8f, MCK_INIT1, /* r17 .. r19 */ | 372 | 0x68, 0x8f, MCK_INIT1, /* r17 .. r19 */ |
@@ -387,6 +408,30 @@ static const __u8 initPas106[] = { | |||
387 | 0x18, 0x10, 0x02, 0x02, 0x09, 0x07 | 408 | 0x18, 0x10, 0x02, 0x02, 0x09, 0x07 |
388 | }; | 409 | }; |
389 | /* compression 0x86 mckinit1 0x2b */ | 410 | /* compression 0x86 mckinit1 0x2b */ |
411 | |||
412 | /* "Known" PAS106B registers: | ||
413 | 0x02 clock divider | ||
414 | 0x03 Variable framerate bits 4-11 | ||
415 | 0x04 Var framerate bits 0-3, one must leave the 4 msb's at 0 !! | ||
416 | The variable framerate control must never be set lower then 300, | ||
417 | which sets the framerate at 90 / reg02, otherwise vsync is lost. | ||
418 | 0x05 Shutter Time Line Offset, this can be used as an exposure control: | ||
419 | 0 = use full frame time, 255 = no exposure at all | ||
420 | Note this may never be larger then "var-framerate control" / 2 - 2. | ||
421 | When var-framerate control is < 514, no exposure is reached at the max | ||
422 | allowed value for the framerate control value, rather then at 255. | ||
423 | 0x06 Shutter Time Pixel Offset, like reg05 this influences exposure, but | ||
424 | only a very little bit, leave at 0xcd | ||
425 | 0x07 offset sign bit (bit0 1 > negative offset) | ||
426 | 0x08 offset | ||
427 | 0x09 Blue Gain | ||
428 | 0x0a Green1 Gain | ||
429 | 0x0b Green2 Gain | ||
430 | 0x0c Red Gain | ||
431 | 0x0e Global gain | ||
432 | 0x13 Write 1 to commit settings to sensor | ||
433 | */ | ||
434 | |||
390 | static const __u8 pas106_sensor_init[][8] = { | 435 | static const __u8 pas106_sensor_init[][8] = { |
391 | /* Pixel Clock Divider 6 */ | 436 | /* Pixel Clock Divider 6 */ |
392 | { 0xa1, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x14 }, | 437 | { 0xa1, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x14 }, |
@@ -433,37 +478,55 @@ static const __u8 initPas202[] = { | |||
433 | 0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00, | 478 | 0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00, |
434 | 0x00, 0x00, | 479 | 0x00, 0x00, |
435 | 0x00, 0x00, 0x00, 0x06, 0x03, 0x0a, | 480 | 0x00, 0x00, 0x00, 0x06, 0x03, 0x0a, |
436 | 0x28, 0x1e, 0x28, 0x89, 0x20, | 481 | 0x28, 0x1e, 0x20, 0x89, 0x20, |
437 | 0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c | 482 | 0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c |
438 | }; | 483 | }; |
484 | |||
485 | /* "Known" PAS202BCB registers: | ||
486 | 0x02 clock divider | ||
487 | 0x04 Variable framerate bits 6-11 (*) | ||
488 | 0x05 Var framerate bits 0-5, one must leave the 2 msb's at 0 !! | ||
489 | 0x07 Blue Gain | ||
490 | 0x08 Green Gain | ||
491 | 0x09 Red Gain | ||
492 | 0x0b offset sign bit (bit0 1 > negative offset) | ||
493 | 0x0c offset | ||
494 | 0x0e Unknown image is slightly brighter when bit 0 is 0, if reg0f is 0 too, | ||
495 | leave at 1 otherwise we get a jump in our exposure control | ||
496 | 0x0f Exposure 0-255, 0 = use full frame time, 255 = no exposure at all | ||
497 | 0x10 Master gain 0 - 31 | ||
498 | 0x11 write 1 to apply changes | ||
499 | (*) The variable framerate control must never be set lower then 500 | ||
500 | which sets the framerate at 30 / reg02, otherwise vsync is lost. | ||
501 | */ | ||
439 | static const __u8 pas202_sensor_init[][8] = { | 502 | static const __u8 pas202_sensor_init[][8] = { |
440 | {0xa0, 0x40, 0x02, 0x03, 0x00, 0x00, 0x00, 0x10}, | 503 | /* Set the clock divider to 4 -> 30 / 4 = 7.5 fps, we would like |
504 | to set it lower, but for some reason the bridge starts missing | ||
505 | vsync's then */ | ||
506 | {0xa0, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x10}, | ||
441 | {0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10}, | 507 | {0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10}, |
442 | {0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10}, | 508 | {0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10}, |
443 | {0xd0, 0x40, 0x0C, 0x00, 0x0C, 0x00, 0x32, 0x10}, | 509 | {0xd0, 0x40, 0x0C, 0x00, 0x0C, 0x01, 0x32, 0x10}, |
444 | {0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10}, | 510 | {0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10}, |
445 | {0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10}, | 511 | {0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10}, |
446 | {0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10}, | 512 | {0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10}, |
447 | {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10}, | 513 | {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10}, |
448 | {0xa0, 0x40, 0x03, 0x56, 0x01, 0x00, 0x63, 0x10}, | 514 | {0xa0, 0x40, 0x03, 0x56, 0x01, 0x00, 0x63, 0x10}, |
449 | {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10}, | 515 | {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10}, |
450 | {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x10}, | ||
451 | {0xb0, 0x40, 0x0e, 0x00, 0x3d, 0x00, 0x63, 0x10}, | ||
452 | |||
453 | {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16}, | ||
454 | {0xa0, 0x40, 0x10, 0x08, 0x3d, 0x00, 0x63, 0x15}, | ||
455 | {0xa0, 0x40, 0x02, 0x04, 0x3d, 0x00, 0x63, 0x16}, | ||
456 | {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16}, | ||
457 | {0xb0, 0x40, 0x0e, 0x00, 0x31, 0x00, 0x63, 0x16}, | ||
458 | {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16}, | ||
459 | {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15}, | ||
460 | {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16}, | ||
461 | }; | 516 | }; |
462 | 517 | ||
463 | static const __u8 initTas5110[] = { | 518 | static const __u8 initTas5110c[] = { |
464 | 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00, | 519 | 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00, |
465 | 0x00, 0x00, | 520 | 0x00, 0x00, |
466 | 0x00, 0x01, 0x00, 0x45, 0x09, 0x0a, | 521 | 0x00, 0x00, 0x00, 0x45, 0x09, 0x0a, |
522 | 0x16, 0x12, 0x60, 0x86, 0x2b, | ||
523 | 0x14, 0x0a, 0x02, 0x02, 0x09, 0x07 | ||
524 | }; | ||
525 | /* Same as above, except a different hstart */ | ||
526 | static const __u8 initTas5110d[] = { | ||
527 | 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00, | ||
528 | 0x00, 0x00, | ||
529 | 0x00, 0x00, 0x00, 0x41, 0x09, 0x0a, | ||
467 | 0x16, 0x12, 0x60, 0x86, 0x2b, | 530 | 0x16, 0x12, 0x60, 0x86, 0x2b, |
468 | 0x14, 0x0a, 0x02, 0x02, 0x09, 0x07 | 531 | 0x14, 0x0a, 0x02, 0x02, 0x09, 0x07 |
469 | }; | 532 | }; |
@@ -476,7 +539,7 @@ static const __u8 tas5110_sensor_init[][8] = { | |||
476 | static const __u8 initTas5130[] = { | 539 | static const __u8 initTas5130[] = { |
477 | 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00, | 540 | 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00, |
478 | 0x00, 0x00, | 541 | 0x00, 0x00, |
479 | 0x00, 0x01, 0x00, 0x68, 0x0c, 0x0a, | 542 | 0x00, 0x00, 0x00, 0x68, 0x0c, 0x0a, |
480 | 0x28, 0x1e, 0x60, COMP, MCK_INIT, | 543 | 0x28, 0x1e, 0x60, COMP, MCK_INIT, |
481 | 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c | 544 | 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c |
482 | }; | 545 | }; |
@@ -493,12 +556,14 @@ SENS(initHv7131, NULL, hv7131_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, 0), | |||
493 | SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF, 0, 0x60), | 556 | SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF, 0, 0x60), |
494 | SENS(initOv7630, initOv7630_3, ov7630_sensor_init, NULL, ov7630_sensor_init_3, | 557 | SENS(initOv7630, initOv7630_3, ov7630_sensor_init, NULL, ov7630_sensor_init_3, |
495 | F_GAIN, 0, 0x21), | 558 | F_GAIN, 0, 0x21), |
496 | SENS(initPas106, NULL, pas106_sensor_init, NULL, NULL, F_SIF, NO_EXPO|NO_FREQ, | 559 | SENS(initPas106, NULL, pas106_sensor_init, NULL, NULL, F_GAIN|F_SIF, NO_FREQ, |
497 | 0), | 560 | 0), |
498 | SENS(initPas202, initPas202, pas202_sensor_init, NULL, NULL, 0, | 561 | SENS(initPas202, initPas202, pas202_sensor_init, NULL, NULL, F_GAIN, |
499 | NO_EXPO|NO_FREQ, 0), | 562 | NO_FREQ, 0), |
500 | SENS(initTas5110, NULL, tas5110_sensor_init, NULL, NULL, F_GAIN|F_SIF, | 563 | SENS(initTas5110c, NULL, tas5110_sensor_init, NULL, NULL, |
501 | NO_BRIGHTNESS|NO_FREQ, 0), | 564 | F_GAIN|F_SIF|F_COARSE_EXPO, NO_BRIGHTNESS|NO_FREQ, 0), |
565 | SENS(initTas5110d, NULL, tas5110_sensor_init, NULL, NULL, | ||
566 | F_GAIN|F_SIF|F_COARSE_EXPO, NO_BRIGHTNESS|NO_FREQ, 0), | ||
502 | SENS(initTas5130, NULL, tas5130_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, | 567 | SENS(initTas5130, NULL, tas5130_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, |
503 | 0), | 568 | 0), |
504 | }; | 569 | }; |
@@ -587,42 +652,28 @@ static void setbrightness(struct gspca_dev *gspca_dev) | |||
587 | goto err; | 652 | goto err; |
588 | break; | 653 | break; |
589 | } | 654 | } |
590 | case SENSOR_PAS106: { | 655 | case SENSOR_PAS106: |
591 | __u8 i2c1[] = | ||
592 | {0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14}; | ||
593 | |||
594 | i2c1[3] = sd->brightness >> 3; | ||
595 | i2c1[2] = 0x0e; | ||
596 | if (i2c_w(gspca_dev, i2c1) < 0) | ||
597 | goto err; | ||
598 | i2c1[3] = 0x01; | ||
599 | i2c1[2] = 0x13; | ||
600 | if (i2c_w(gspca_dev, i2c1) < 0) | ||
601 | goto err; | ||
602 | break; | ||
603 | } | ||
604 | case SENSOR_PAS202: { | 656 | case SENSOR_PAS202: { |
605 | /* __u8 i2cpexpo1[] = | 657 | __u8 i2cpbright[] = |
606 | {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x16}; */ | 658 | {0xb0, 0x40, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x16}; |
607 | __u8 i2cpexpo[] = | 659 | __u8 i2cpdoit[] = |
608 | {0xb0, 0x40, 0x0e, 0x01, 0xab, 0x00, 0x63, 0x16}; | 660 | {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16}; |
609 | __u8 i2cp202[] = | 661 | |
610 | {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15}; | 662 | /* PAS106 uses reg 7 and 8 instead of b and c */ |
611 | static __u8 i2cpdoit[] = | 663 | if (sd->sensor == SENSOR_PAS106) { |
612 | {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16}; | 664 | i2cpbright[2] = 7; |
613 | 665 | i2cpdoit[2] = 0x13; | |
614 | /* change reg 0x10 */ | 666 | } |
615 | i2cpexpo[4] = 0xff - sd->brightness; | 667 | |
616 | /* if(i2c_w(gspca_dev,i2cpexpo1) < 0) | 668 | if (sd->brightness < 127) { |
617 | goto err; */ | 669 | /* change reg 0x0b, signreg */ |
618 | /* if(i2c_w(gspca_dev,i2cpdoit) < 0) | 670 | i2cpbright[3] = 0x01; |
619 | goto err; */ | 671 | /* set reg 0x0c, offset */ |
620 | if (i2c_w(gspca_dev, i2cpexpo) < 0) | 672 | i2cpbright[4] = 127 - sd->brightness; |
621 | goto err; | 673 | } else |
622 | if (i2c_w(gspca_dev, i2cpdoit) < 0) | 674 | i2cpbright[4] = sd->brightness - 127; |
623 | goto err; | 675 | |
624 | i2cp202[3] = sd->brightness >> 3; | 676 | if (i2c_w(gspca_dev, i2cpbright) < 0) |
625 | if (i2c_w(gspca_dev, i2cp202) < 0) | ||
626 | goto err; | 677 | goto err; |
627 | if (i2c_w(gspca_dev, i2cpdoit) < 0) | 678 | if (i2c_w(gspca_dev, i2cpdoit) < 0) |
628 | goto err; | 679 | goto err; |
@@ -652,7 +703,8 @@ static void setsensorgain(struct gspca_dev *gspca_dev) | |||
652 | 703 | ||
653 | switch (sd->sensor) { | 704 | switch (sd->sensor) { |
654 | 705 | ||
655 | case SENSOR_TAS5110: { | 706 | case SENSOR_TAS5110C: |
707 | case SENSOR_TAS5110D: { | ||
656 | __u8 i2c[] = | 708 | __u8 i2c[] = |
657 | {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10}; | 709 | {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10}; |
658 | 710 | ||
@@ -674,6 +726,37 @@ static void setsensorgain(struct gspca_dev *gspca_dev) | |||
674 | goto err; | 726 | goto err; |
675 | break; | 727 | break; |
676 | } | 728 | } |
729 | case SENSOR_PAS106: | ||
730 | case SENSOR_PAS202: { | ||
731 | __u8 i2cpgain[] = | ||
732 | {0xa0, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x15}; | ||
733 | __u8 i2cpcolorgain[] = | ||
734 | {0xc0, 0x40, 0x07, 0x00, 0x00, 0x00, 0x00, 0x15}; | ||
735 | __u8 i2cpdoit[] = | ||
736 | {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16}; | ||
737 | |||
738 | /* PAS106 uses different regs (and has split green gains) */ | ||
739 | if (sd->sensor == SENSOR_PAS106) { | ||
740 | i2cpgain[2] = 0x0e; | ||
741 | i2cpcolorgain[0] = 0xd0; | ||
742 | i2cpcolorgain[2] = 0x09; | ||
743 | i2cpdoit[2] = 0x13; | ||
744 | } | ||
745 | |||
746 | i2cpgain[3] = sd->gain >> 3; | ||
747 | i2cpcolorgain[3] = sd->gain >> 4; | ||
748 | i2cpcolorgain[4] = sd->gain >> 4; | ||
749 | i2cpcolorgain[5] = sd->gain >> 4; | ||
750 | i2cpcolorgain[6] = sd->gain >> 4; | ||
751 | |||
752 | if (i2c_w(gspca_dev, i2cpgain) < 0) | ||
753 | goto err; | ||
754 | if (i2c_w(gspca_dev, i2cpcolorgain) < 0) | ||
755 | goto err; | ||
756 | if (i2c_w(gspca_dev, i2cpdoit) < 0) | ||
757 | goto err; | ||
758 | break; | ||
759 | } | ||
677 | } | 760 | } |
678 | return; | 761 | return; |
679 | err: | 762 | err: |
@@ -684,19 +767,21 @@ static void setgain(struct gspca_dev *gspca_dev) | |||
684 | { | 767 | { |
685 | struct sd *sd = (struct sd *) gspca_dev; | 768 | struct sd *sd = (struct sd *) gspca_dev; |
686 | __u8 gain; | 769 | __u8 gain; |
687 | __u8 rgb_value; | 770 | __u8 buf[2] = { 0, 0 }; |
771 | |||
772 | if (sensor_data[sd->sensor].flags & F_GAIN) { | ||
773 | /* Use the sensor gain to do the actual gain */ | ||
774 | setsensorgain(gspca_dev); | ||
775 | return; | ||
776 | } | ||
688 | 777 | ||
689 | gain = sd->gain >> 4; | 778 | gain = sd->gain >> 4; |
690 | 779 | ||
691 | /* red and blue gain */ | 780 | /* red and blue gain */ |
692 | rgb_value = gain << 4 | gain; | 781 | buf[0] = gain << 4 | gain; |
693 | reg_w(gspca_dev, 0x10, &rgb_value, 1); | ||
694 | /* green gain */ | 782 | /* green gain */ |
695 | rgb_value = gain; | 783 | buf[1] = gain; |
696 | reg_w(gspca_dev, 0x11, &rgb_value, 1); | 784 | reg_w(gspca_dev, 0x10, buf, 2); |
697 | |||
698 | if (sensor_data[sd->sensor].flags & F_GAIN) | ||
699 | setsensorgain(gspca_dev); | ||
700 | } | 785 | } |
701 | 786 | ||
702 | static void setexposure(struct gspca_dev *gspca_dev) | 787 | static void setexposure(struct gspca_dev *gspca_dev) |
@@ -704,17 +789,12 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
704 | struct sd *sd = (struct sd *) gspca_dev; | 789 | struct sd *sd = (struct sd *) gspca_dev; |
705 | 790 | ||
706 | switch (sd->sensor) { | 791 | switch (sd->sensor) { |
707 | case SENSOR_TAS5110: { | 792 | case SENSOR_TAS5110C: |
708 | __u8 reg; | 793 | case SENSOR_TAS5110D: { |
709 | |||
710 | /* register 19's high nibble contains the sn9c10x clock divider | 794 | /* register 19's high nibble contains the sn9c10x clock divider |
711 | The high nibble configures the no fps according to the | 795 | The high nibble configures the no fps according to the |
712 | formula: 60 / high_nibble. With a maximum of 30 fps */ | 796 | formula: 60 / high_nibble. With a maximum of 30 fps */ |
713 | reg = 120 * sd->exposure / 1000; | 797 | __u8 reg = sd->exposure; |
714 | if (reg < 2) | ||
715 | reg = 2; | ||
716 | else if (reg > 15) | ||
717 | reg = 15; | ||
718 | reg = (reg << 4) | 0x0b; | 798 | reg = (reg << 4) | 0x0b; |
719 | reg_w(gspca_dev, 0x19, ®, 1); | 799 | reg_w(gspca_dev, 0x19, ®, 1); |
720 | break; | 800 | break; |
@@ -750,20 +830,21 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
750 | } else | 830 | } else |
751 | reg10_max = 0x41; | 831 | reg10_max = 0x41; |
752 | 832 | ||
753 | reg11 = (60 * sd->exposure + 999) / 1000; | 833 | reg11 = (15 * sd->exposure + 999) / 1000; |
754 | if (reg11 < 1) | 834 | if (reg11 < 1) |
755 | reg11 = 1; | 835 | reg11 = 1; |
756 | else if (reg11 > 16) | 836 | else if (reg11 > 16) |
757 | reg11 = 16; | 837 | reg11 = 16; |
758 | 838 | ||
759 | /* In 640x480, if the reg11 has less than 3, the image is | 839 | /* In 640x480, if the reg11 has less than 4, the image is |
760 | unstable (not enough bandwidth). */ | 840 | unstable (the bridge goes into a higher compression mode |
761 | if (gspca_dev->width == 640 && reg11 < 3) | 841 | which we have not reverse engineered yet). */ |
762 | reg11 = 3; | 842 | if (gspca_dev->width == 640 && reg11 < 4) |
843 | reg11 = 4; | ||
763 | 844 | ||
764 | /* frame exposure time in ms = 1000 * reg11 / 30 -> | 845 | /* frame exposure time in ms = 1000 * reg11 / 30 -> |
765 | reg10 = sd->exposure * 2 * reg10_max / (1000 * reg11 / 30) */ | 846 | reg10 = (sd->exposure / 2) * reg10_max / (1000 * reg11 / 30) */ |
766 | reg10 = (sd->exposure * 60 * reg10_max) / (1000 * reg11); | 847 | reg10 = (sd->exposure * 15 * reg10_max) / (1000 * reg11); |
767 | 848 | ||
768 | /* Don't allow this to get below 10 when using autogain, the | 849 | /* Don't allow this to get below 10 when using autogain, the |
769 | steps become very large (relatively) when below 10 causing | 850 | steps become very large (relatively) when below 10 causing |
@@ -786,10 +867,85 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
786 | if (i2c_w(gspca_dev, i2c) == 0) | 867 | if (i2c_w(gspca_dev, i2c) == 0) |
787 | sd->reg11 = reg11; | 868 | sd->reg11 = reg11; |
788 | else | 869 | else |
789 | PDEBUG(D_ERR, "i2c error exposure"); | 870 | goto err; |
871 | break; | ||
872 | } | ||
873 | case SENSOR_PAS202: { | ||
874 | __u8 i2cpframerate[] = | ||
875 | {0xb0, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x16}; | ||
876 | __u8 i2cpexpo[] = | ||
877 | {0xa0, 0x40, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x16}; | ||
878 | const __u8 i2cpdoit[] = | ||
879 | {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16}; | ||
880 | int framerate_ctrl; | ||
881 | |||
882 | /* The exposure knee for the autogain algorithm is 200 | ||
883 | (100 ms / 10 fps on other sensors), for values below this | ||
884 | use the control for setting the partial frame expose time, | ||
885 | above that use variable framerate. This way we run at max | ||
886 | framerate (640x480@7.5 fps, 320x240@10fps) until the knee | ||
887 | is reached. Using the variable framerate control above 200 | ||
888 | is better then playing around with both clockdiv + partial | ||
889 | frame exposure times (like we are doing with the ov chips), | ||
890 | as that sometimes leads to jumps in the exposure control, | ||
891 | which are bad for auto exposure. */ | ||
892 | if (sd->exposure < 200) { | ||
893 | i2cpexpo[3] = 255 - (sd->exposure * 255) / 200; | ||
894 | framerate_ctrl = 500; | ||
895 | } else { | ||
896 | /* The PAS202's exposure control goes from 0 - 4095, | ||
897 | but anything below 500 causes vsync issues, so scale | ||
898 | our 200-1023 to 500-4095 */ | ||
899 | framerate_ctrl = (sd->exposure - 200) * 1000 / 229 + | ||
900 | 500; | ||
901 | } | ||
902 | |||
903 | i2cpframerate[3] = framerate_ctrl >> 6; | ||
904 | i2cpframerate[4] = framerate_ctrl & 0x3f; | ||
905 | if (i2c_w(gspca_dev, i2cpframerate) < 0) | ||
906 | goto err; | ||
907 | if (i2c_w(gspca_dev, i2cpexpo) < 0) | ||
908 | goto err; | ||
909 | if (i2c_w(gspca_dev, i2cpdoit) < 0) | ||
910 | goto err; | ||
911 | break; | ||
912 | } | ||
913 | case SENSOR_PAS106: { | ||
914 | __u8 i2cpframerate[] = | ||
915 | {0xb1, 0x40, 0x03, 0x00, 0x00, 0x00, 0x00, 0x14}; | ||
916 | __u8 i2cpexpo[] = | ||
917 | {0xa1, 0x40, 0x05, 0x00, 0x00, 0x00, 0x00, 0x14}; | ||
918 | const __u8 i2cpdoit[] = | ||
919 | {0xa1, 0x40, 0x13, 0x01, 0x00, 0x00, 0x00, 0x14}; | ||
920 | int framerate_ctrl; | ||
921 | |||
922 | /* For values below 150 use partial frame exposure, above | ||
923 | that use framerate ctrl */ | ||
924 | if (sd->exposure < 150) { | ||
925 | i2cpexpo[3] = 150 - sd->exposure; | ||
926 | framerate_ctrl = 300; | ||
927 | } else { | ||
928 | /* The PAS106's exposure control goes from 0 - 4095, | ||
929 | but anything below 300 causes vsync issues, so scale | ||
930 | our 150-1023 to 300-4095 */ | ||
931 | framerate_ctrl = (sd->exposure - 150) * 1000 / 230 + | ||
932 | 300; | ||
933 | } | ||
934 | |||
935 | i2cpframerate[3] = framerate_ctrl >> 4; | ||
936 | i2cpframerate[4] = framerate_ctrl & 0x0f; | ||
937 | if (i2c_w(gspca_dev, i2cpframerate) < 0) | ||
938 | goto err; | ||
939 | if (i2c_w(gspca_dev, i2cpexpo) < 0) | ||
940 | goto err; | ||
941 | if (i2c_w(gspca_dev, i2cpdoit) < 0) | ||
942 | goto err; | ||
790 | break; | 943 | break; |
791 | } | 944 | } |
792 | } | 945 | } |
946 | return; | ||
947 | err: | ||
948 | PDEBUG(D_ERR, "i2c error exposure"); | ||
793 | } | 949 | } |
794 | 950 | ||
795 | static void setfreq(struct gspca_dev *gspca_dev) | 951 | static void setfreq(struct gspca_dev *gspca_dev) |
@@ -823,30 +979,43 @@ static void setfreq(struct gspca_dev *gspca_dev) | |||
823 | } | 979 | } |
824 | } | 980 | } |
825 | 981 | ||
982 | #include "coarse_expo_autogain.h" | ||
983 | |||
826 | static void do_autogain(struct gspca_dev *gspca_dev) | 984 | static void do_autogain(struct gspca_dev *gspca_dev) |
827 | { | 985 | { |
828 | int deadzone, desired_avg_lum; | 986 | int deadzone, desired_avg_lum, result; |
829 | struct sd *sd = (struct sd *) gspca_dev; | 987 | struct sd *sd = (struct sd *) gspca_dev; |
830 | int avg_lum = atomic_read(&sd->avg_lum); | 988 | int avg_lum = atomic_read(&sd->avg_lum); |
831 | 989 | ||
832 | if (avg_lum == -1) | 990 | if (avg_lum == -1 || !sd->autogain) |
833 | return; | 991 | return; |
834 | 992 | ||
993 | if (sd->autogain_ignore_frames > 0) { | ||
994 | sd->autogain_ignore_frames--; | ||
995 | return; | ||
996 | } | ||
997 | |||
835 | /* SIF / VGA sensors have a different autoexposure area and thus | 998 | /* SIF / VGA sensors have a different autoexposure area and thus |
836 | different avg_lum values for the same picture brightness */ | 999 | different avg_lum values for the same picture brightness */ |
837 | if (sensor_data[sd->sensor].flags & F_SIF) { | 1000 | if (sensor_data[sd->sensor].flags & F_SIF) { |
838 | deadzone = 1000; | 1001 | deadzone = 500; |
839 | desired_avg_lum = 7000; | 1002 | /* SIF sensors tend to overexpose, so keep this small */ |
1003 | desired_avg_lum = 5000; | ||
840 | } else { | 1004 | } else { |
841 | deadzone = 3000; | 1005 | deadzone = 1500; |
842 | desired_avg_lum = 23000; | 1006 | desired_avg_lum = 18000; |
843 | } | 1007 | } |
844 | 1008 | ||
845 | if (sd->autogain_ignore_frames > 0) | 1009 | if (sensor_data[sd->sensor].flags & F_COARSE_EXPO) |
846 | sd->autogain_ignore_frames--; | 1010 | result = gspca_coarse_grained_expo_autogain(gspca_dev, avg_lum, |
847 | else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, | 1011 | sd->brightness * desired_avg_lum / 127, |
848 | sd->brightness * desired_avg_lum / 127, | 1012 | deadzone); |
849 | deadzone, GAIN_KNEE, EXPOSURE_KNEE)) { | 1013 | else |
1014 | result = gspca_auto_gain_n_exposure(gspca_dev, avg_lum, | ||
1015 | sd->brightness * desired_avg_lum / 127, | ||
1016 | deadzone, GAIN_KNEE, EXPOSURE_KNEE); | ||
1017 | |||
1018 | if (result) { | ||
850 | PDEBUG(D_FRAM, "autogain: gain changed: gain: %d expo: %d", | 1019 | PDEBUG(D_FRAM, "autogain: gain changed: gain: %d expo: %d", |
851 | (int)sd->gain, (int)sd->exposure); | 1020 | (int)sd->gain, (int)sd->exposure); |
852 | sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES; | 1021 | sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES; |
@@ -881,7 +1050,13 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
881 | 1050 | ||
882 | sd->brightness = BRIGHTNESS_DEF; | 1051 | sd->brightness = BRIGHTNESS_DEF; |
883 | sd->gain = GAIN_DEF; | 1052 | sd->gain = GAIN_DEF; |
884 | sd->exposure = EXPOSURE_DEF; | 1053 | if (sensor_data[sd->sensor].flags & F_COARSE_EXPO) { |
1054 | sd->exposure = COARSE_EXPOSURE_DEF; | ||
1055 | gspca_dev->ctrl_dis |= (1 << EXPOSURE_IDX); | ||
1056 | } else { | ||
1057 | sd->exposure = EXPOSURE_DEF; | ||
1058 | gspca_dev->ctrl_dis |= (1 << COARSE_EXPOSURE_IDX); | ||
1059 | } | ||
885 | if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX)) | 1060 | if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX)) |
886 | sd->autogain = 0; /* Disable do_autogain callback */ | 1061 | sd->autogain = 0; /* Disable do_autogain callback */ |
887 | else | 1062 | else |
@@ -917,9 +1092,6 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
917 | reg12_19[6] = sn9c10x[0x18 - 1] | (mode << 4); | 1092 | reg12_19[6] = sn9c10x[0x18 - 1] | (mode << 4); |
918 | /* Special cases where reg 17 and or 19 value depends on mode */ | 1093 | /* Special cases where reg 17 and or 19 value depends on mode */ |
919 | switch (sd->sensor) { | 1094 | switch (sd->sensor) { |
920 | case SENSOR_PAS202: | ||
921 | reg12_19[5] = mode ? 0x24 : 0x20; | ||
922 | break; | ||
923 | case SENSOR_TAS5130CXX: | 1095 | case SENSOR_TAS5130CXX: |
924 | /* probably not mode specific at all most likely the upper | 1096 | /* probably not mode specific at all most likely the upper |
925 | nibble of 0x19 is exposure (clock divider) just as with | 1097 | nibble of 0x19 is exposure (clock divider) just as with |
@@ -955,6 +1127,16 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
955 | sensor_data[sd->sensor].sensor_bridge_init_size[ | 1127 | sensor_data[sd->sensor].sensor_bridge_init_size[ |
956 | sd->bridge]); | 1128 | sd->bridge]); |
957 | 1129 | ||
1130 | /* Mode specific sensor setup */ | ||
1131 | switch (sd->sensor) { | ||
1132 | case SENSOR_PAS202: { | ||
1133 | const __u8 i2cpclockdiv[] = | ||
1134 | {0xa0, 0x40, 0x02, 0x03, 0x00, 0x00, 0x00, 0x10}; | ||
1135 | /* clockdiv from 4 to 3 (7.5 -> 10 fps) when in low res mode */ | ||
1136 | if (mode) | ||
1137 | i2c_w(gspca_dev, i2cpclockdiv); | ||
1138 | } | ||
1139 | } | ||
958 | /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */ | 1140 | /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */ |
959 | reg_w(gspca_dev, 0x15, ®12_19[3], 2); | 1141 | reg_w(gspca_dev, 0x15, ®12_19[3], 2); |
960 | /* compression register */ | 1142 | /* compression register */ |
@@ -985,6 +1167,8 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
985 | 1167 | ||
986 | sd->frames_to_drop = 0; | 1168 | sd->frames_to_drop = 0; |
987 | sd->autogain_ignore_frames = 0; | 1169 | sd->autogain_ignore_frames = 0; |
1170 | sd->exp_too_high_cnt = 0; | ||
1171 | sd->exp_too_low_cnt = 0; | ||
988 | atomic_set(&sd->avg_lum, -1); | 1172 | atomic_set(&sd->avg_lum, -1); |
989 | return 0; | 1173 | return 0; |
990 | } | 1174 | } |
@@ -1143,11 +1327,14 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) | |||
1143 | struct sd *sd = (struct sd *) gspca_dev; | 1327 | struct sd *sd = (struct sd *) gspca_dev; |
1144 | 1328 | ||
1145 | sd->autogain = val; | 1329 | sd->autogain = val; |
1330 | sd->exp_too_high_cnt = 0; | ||
1331 | sd->exp_too_low_cnt = 0; | ||
1332 | |||
1146 | /* when switching to autogain set defaults to make sure | 1333 | /* when switching to autogain set defaults to make sure |
1147 | we are on a valid point of the autogain gain / | 1334 | we are on a valid point of the autogain gain / |
1148 | exposure knee graph, and give this change time to | 1335 | exposure knee graph, and give this change time to |
1149 | take effect before doing autogain. */ | 1336 | take effect before doing autogain. */ |
1150 | if (sd->autogain) { | 1337 | if (sd->autogain && !(sensor_data[sd->sensor].flags & F_COARSE_EXPO)) { |
1151 | sd->exposure = EXPOSURE_DEF; | 1338 | sd->exposure = EXPOSURE_DEF; |
1152 | sd->gain = GAIN_DEF; | 1339 | sd->gain = GAIN_DEF; |
1153 | if (gspca_dev->streaming) { | 1340 | if (gspca_dev->streaming) { |
@@ -1207,6 +1394,25 @@ static int sd_querymenu(struct gspca_dev *gspca_dev, | |||
1207 | return -EINVAL; | 1394 | return -EINVAL; |
1208 | } | 1395 | } |
1209 | 1396 | ||
1397 | #ifdef CONFIG_INPUT | ||
1398 | static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, | ||
1399 | u8 *data, /* interrupt packet data */ | ||
1400 | int len) /* interrupt packet length */ | ||
1401 | { | ||
1402 | int ret = -EINVAL; | ||
1403 | |||
1404 | if (len == 1 && data[0] == 1) { | ||
1405 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); | ||
1406 | input_sync(gspca_dev->input_dev); | ||
1407 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); | ||
1408 | input_sync(gspca_dev->input_dev); | ||
1409 | ret = 0; | ||
1410 | } | ||
1411 | |||
1412 | return ret; | ||
1413 | } | ||
1414 | #endif | ||
1415 | |||
1210 | /* sub-driver description */ | 1416 | /* sub-driver description */ |
1211 | static const struct sd_desc sd_desc = { | 1417 | static const struct sd_desc sd_desc = { |
1212 | .name = MODULE_NAME, | 1418 | .name = MODULE_NAME, |
@@ -1219,6 +1425,9 @@ static const struct sd_desc sd_desc = { | |||
1219 | .pkt_scan = sd_pkt_scan, | 1425 | .pkt_scan = sd_pkt_scan, |
1220 | .querymenu = sd_querymenu, | 1426 | .querymenu = sd_querymenu, |
1221 | .dq_callback = do_autogain, | 1427 | .dq_callback = do_autogain, |
1428 | #ifdef CONFIG_INPUT | ||
1429 | .int_pkt_scan = sd_int_pkt_scan, | ||
1430 | #endif | ||
1222 | }; | 1431 | }; |
1223 | 1432 | ||
1224 | /* -- module initialisation -- */ | 1433 | /* -- module initialisation -- */ |
@@ -1227,21 +1436,21 @@ static const struct sd_desc sd_desc = { | |||
1227 | 1436 | ||
1228 | 1437 | ||
1229 | static const struct usb_device_id device_table[] __devinitconst = { | 1438 | static const struct usb_device_id device_table[] __devinitconst = { |
1230 | {USB_DEVICE(0x0c45, 0x6001), SB(TAS5110, 102)}, /* TAS5110C1B */ | 1439 | {USB_DEVICE(0x0c45, 0x6001), SB(TAS5110C, 102)}, /* TAS5110C1B */ |
1231 | {USB_DEVICE(0x0c45, 0x6005), SB(TAS5110, 101)}, /* TAS5110C1B */ | 1440 | {USB_DEVICE(0x0c45, 0x6005), SB(TAS5110C, 101)}, /* TAS5110C1B */ |
1232 | #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE | 1441 | #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE |
1233 | {USB_DEVICE(0x0c45, 0x6007), SB(TAS5110, 101)}, /* TAS5110D */ | 1442 | {USB_DEVICE(0x0c45, 0x6007), SB(TAS5110D, 101)}, /* TAS5110D */ |
1443 | #endif | ||
1234 | {USB_DEVICE(0x0c45, 0x6009), SB(PAS106, 101)}, | 1444 | {USB_DEVICE(0x0c45, 0x6009), SB(PAS106, 101)}, |
1235 | {USB_DEVICE(0x0c45, 0x600d), SB(PAS106, 101)}, | 1445 | {USB_DEVICE(0x0c45, 0x600d), SB(PAS106, 101)}, |
1236 | #endif | ||
1237 | {USB_DEVICE(0x0c45, 0x6011), SB(OV6650, 101)}, | 1446 | {USB_DEVICE(0x0c45, 0x6011), SB(OV6650, 101)}, |
1238 | #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE | 1447 | #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE |
1239 | {USB_DEVICE(0x0c45, 0x6019), SB(OV7630, 101)}, | 1448 | {USB_DEVICE(0x0c45, 0x6019), SB(OV7630, 101)}, |
1240 | {USB_DEVICE(0x0c45, 0x6024), SB(TAS5130CXX, 102)}, | 1449 | {USB_DEVICE(0x0c45, 0x6024), SB(TAS5130CXX, 102)}, |
1241 | {USB_DEVICE(0x0c45, 0x6025), SB(TAS5130CXX, 102)}, | 1450 | {USB_DEVICE(0x0c45, 0x6025), SB(TAS5130CXX, 102)}, |
1451 | #endif | ||
1242 | {USB_DEVICE(0x0c45, 0x6028), SB(PAS202, 102)}, | 1452 | {USB_DEVICE(0x0c45, 0x6028), SB(PAS202, 102)}, |
1243 | {USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)}, | 1453 | {USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)}, |
1244 | #endif | ||
1245 | {USB_DEVICE(0x0c45, 0x602c), SB(OV7630, 102)}, | 1454 | {USB_DEVICE(0x0c45, 0x602c), SB(OV7630, 102)}, |
1246 | {USB_DEVICE(0x0c45, 0x602d), SB(HV7131R, 102)}, | 1455 | {USB_DEVICE(0x0c45, 0x602d), SB(HV7131R, 102)}, |
1247 | #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE | 1456 | #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE |
diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 0bd36a00dd2a..83d5773d4629 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c | |||
@@ -21,6 +21,7 @@ | |||
21 | 21 | ||
22 | #define MODULE_NAME "sonixj" | 22 | #define MODULE_NAME "sonixj" |
23 | 23 | ||
24 | #include <linux/input.h> | ||
24 | #include "gspca.h" | 25 | #include "gspca.h" |
25 | #include "jpeg.h" | 26 | #include "jpeg.h" |
26 | 27 | ||
@@ -45,6 +46,7 @@ struct sd { | |||
45 | u8 red; | 46 | u8 red; |
46 | u8 gamma; | 47 | u8 gamma; |
47 | u8 vflip; /* ov7630/ov7648 only */ | 48 | u8 vflip; /* ov7630/ov7648 only */ |
49 | u8 sharpness; | ||
48 | u8 infrared; /* mt9v111 only */ | 50 | u8 infrared; /* mt9v111 only */ |
49 | u8 freq; /* ov76xx only */ | 51 | u8 freq; /* ov76xx only */ |
50 | u8 quality; /* image quality */ | 52 | u8 quality; /* image quality */ |
@@ -64,16 +66,17 @@ struct sd { | |||
64 | #define BRIDGE_SN9C110 2 | 66 | #define BRIDGE_SN9C110 2 |
65 | #define BRIDGE_SN9C120 3 | 67 | #define BRIDGE_SN9C120 3 |
66 | u8 sensor; /* Type of image sensor chip */ | 68 | u8 sensor; /* Type of image sensor chip */ |
67 | #define SENSOR_HV7131R 0 | 69 | #define SENSOR_ADCM1700 0 |
68 | #define SENSOR_MI0360 1 | 70 | #define SENSOR_HV7131R 1 |
69 | #define SENSOR_MO4000 2 | 71 | #define SENSOR_MI0360 2 |
70 | #define SENSOR_MT9V111 3 | 72 | #define SENSOR_MO4000 3 |
71 | #define SENSOR_OM6802 4 | 73 | #define SENSOR_MT9V111 4 |
72 | #define SENSOR_OV7630 5 | 74 | #define SENSOR_OM6802 5 |
73 | #define SENSOR_OV7648 6 | 75 | #define SENSOR_OV7630 6 |
74 | #define SENSOR_OV7660 7 | 76 | #define SENSOR_OV7648 7 |
75 | #define SENSOR_PO1030 8 | 77 | #define SENSOR_OV7660 8 |
76 | #define SENSOR_SP80708 9 | 78 | #define SENSOR_PO1030 9 |
79 | #define SENSOR_SP80708 10 | ||
77 | u8 i2c_addr; | 80 | u8 i2c_addr; |
78 | 81 | ||
79 | u8 *jpeg_hdr; | 82 | u8 *jpeg_hdr; |
@@ -96,12 +99,14 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); | |||
96 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); | 99 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); |
97 | static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); | 100 | static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); |
98 | static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val); | 101 | static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val); |
102 | static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val); | ||
103 | static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); | ||
99 | static int sd_setinfrared(struct gspca_dev *gspca_dev, __s32 val); | 104 | static int sd_setinfrared(struct gspca_dev *gspca_dev, __s32 val); |
100 | static int sd_getinfrared(struct gspca_dev *gspca_dev, __s32 *val); | 105 | static int sd_getinfrared(struct gspca_dev *gspca_dev, __s32 *val); |
101 | static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); | 106 | static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); |
102 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); | 107 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); |
103 | 108 | ||
104 | static struct ctrl sd_ctrls[] = { | 109 | static const struct ctrl sd_ctrls[] = { |
105 | #define BRIGHTNESS_IDX 0 | 110 | #define BRIGHTNESS_IDX 0 |
106 | { | 111 | { |
107 | { | 112 | { |
@@ -225,8 +230,23 @@ static struct ctrl sd_ctrls[] = { | |||
225 | .set = sd_setvflip, | 230 | .set = sd_setvflip, |
226 | .get = sd_getvflip, | 231 | .get = sd_getvflip, |
227 | }, | 232 | }, |
233 | #define SHARPNESS_IDX 8 | ||
234 | { | ||
235 | { | ||
236 | .id = V4L2_CID_SHARPNESS, | ||
237 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
238 | .name = "Sharpness", | ||
239 | .minimum = 0, | ||
240 | .maximum = 255, | ||
241 | .step = 1, | ||
242 | #define SHARPNESS_DEF 90 | ||
243 | .default_value = SHARPNESS_DEF, | ||
244 | }, | ||
245 | .set = sd_setsharpness, | ||
246 | .get = sd_getsharpness, | ||
247 | }, | ||
228 | /* mt9v111 only */ | 248 | /* mt9v111 only */ |
229 | #define INFRARED_IDX 8 | 249 | #define INFRARED_IDX 9 |
230 | { | 250 | { |
231 | { | 251 | { |
232 | .id = V4L2_CID_INFRARED, | 252 | .id = V4L2_CID_INFRARED, |
@@ -242,7 +262,7 @@ static struct ctrl sd_ctrls[] = { | |||
242 | .get = sd_getinfrared, | 262 | .get = sd_getinfrared, |
243 | }, | 263 | }, |
244 | /* ov7630/ov7648/ov7660 only */ | 264 | /* ov7630/ov7648/ov7660 only */ |
245 | #define FREQ_IDX 9 | 265 | #define FREQ_IDX 10 |
246 | { | 266 | { |
247 | { | 267 | { |
248 | .id = V4L2_CID_POWER_LINE_FREQUENCY, | 268 | .id = V4L2_CID_POWER_LINE_FREQUENCY, |
@@ -261,28 +281,37 @@ static struct ctrl sd_ctrls[] = { | |||
261 | 281 | ||
262 | /* table of the disabled controls */ | 282 | /* table of the disabled controls */ |
263 | static __u32 ctrl_dis[] = { | 283 | static __u32 ctrl_dis[] = { |
284 | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX) | | ||
285 | (1 << AUTOGAIN_IDX), /* SENSOR_ADCM1700 0 */ | ||
286 | (1 << INFRARED_IDX) | (1 << FREQ_IDX), | ||
287 | /* SENSOR_HV7131R 1 */ | ||
264 | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX), | 288 | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX), |
265 | /* SENSOR_HV7131R 0 */ | 289 | /* SENSOR_MI0360 2 */ |
266 | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX), | 290 | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX), |
267 | /* SENSOR_MI0360 1 */ | 291 | /* SENSOR_MO4000 3 */ |
268 | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX), | ||
269 | /* SENSOR_MO4000 2 */ | ||
270 | (1 << VFLIP_IDX) | (1 << FREQ_IDX), | 292 | (1 << VFLIP_IDX) | (1 << FREQ_IDX), |
271 | /* SENSOR_MT9V111 3 */ | 293 | /* SENSOR_MT9V111 4 */ |
272 | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX), | 294 | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX), |
273 | /* SENSOR_OM6802 4 */ | 295 | /* SENSOR_OM6802 5 */ |
274 | (1 << INFRARED_IDX), | 296 | (1 << INFRARED_IDX), |
275 | /* SENSOR_OV7630 5 */ | 297 | /* SENSOR_OV7630 6 */ |
276 | (1 << INFRARED_IDX), | 298 | (1 << INFRARED_IDX), |
277 | /* SENSOR_OV7648 6 */ | 299 | /* SENSOR_OV7648 7 */ |
278 | (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX), | 300 | (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX), |
279 | /* SENSOR_OV7660 7 */ | 301 | /* SENSOR_OV7660 8 */ |
280 | (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | | 302 | (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | |
281 | (1 << FREQ_IDX), /* SENSOR_PO1030 8 */ | 303 | (1 << FREQ_IDX), /* SENSOR_PO1030 9 */ |
282 | (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | | 304 | (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | |
283 | (1 << FREQ_IDX), /* SENSOR_SP80708 9 */ | 305 | (1 << FREQ_IDX), /* SENSOR_SP80708 10 */ |
284 | }; | 306 | }; |
285 | 307 | ||
308 | static const struct v4l2_pix_format cif_mode[] = { | ||
309 | {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | ||
310 | .bytesperline = 352, | ||
311 | .sizeimage = 352 * 288 * 4 / 8 + 590, | ||
312 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
313 | .priv = 0}, | ||
314 | }; | ||
286 | static const struct v4l2_pix_format vga_mode[] = { | 315 | static const struct v4l2_pix_format vga_mode[] = { |
287 | {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | 316 | {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, |
288 | .bytesperline = 160, | 317 | .bytesperline = 160, |
@@ -302,6 +331,17 @@ static const struct v4l2_pix_format vga_mode[] = { | |||
302 | .priv = 0}, | 331 | .priv = 0}, |
303 | }; | 332 | }; |
304 | 333 | ||
334 | static const u8 sn_adcm1700[0x1c] = { | ||
335 | /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ | ||
336 | 0x00, 0x43, 0x60, 0x00, 0x1a, 0x00, 0x00, 0x00, | ||
337 | /* reg8 reg9 rega regb regc regd rege regf */ | ||
338 | 0x80, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
339 | /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ | ||
340 | 0x03, 0x00, 0x05, 0x01, 0x05, 0x16, 0x12, 0x42, | ||
341 | /* reg18 reg19 reg1a reg1b */ | ||
342 | 0x06, 0x00, 0x00, 0x00 | ||
343 | }; | ||
344 | |||
305 | /*Data from sn9c102p+hv7131r */ | 345 | /*Data from sn9c102p+hv7131r */ |
306 | static const u8 sn_hv7131[0x1c] = { | 346 | static const u8 sn_hv7131[0x1c] = { |
307 | /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ | 347 | /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ |
@@ -415,6 +455,7 @@ static const u8 sn_sp80708[0x1c] = { | |||
415 | 455 | ||
416 | /* sequence specific to the sensors - !! index = SENSOR_xxx */ | 456 | /* sequence specific to the sensors - !! index = SENSOR_xxx */ |
417 | static const u8 *sn_tb[] = { | 457 | static const u8 *sn_tb[] = { |
458 | sn_adcm1700, | ||
418 | sn_hv7131, | 459 | sn_hv7131, |
419 | sn_mi0360, | 460 | sn_mi0360, |
420 | sn_mo4000, | 461 | sn_mo4000, |
@@ -432,6 +473,11 @@ static const u8 gamma_def[17] = { | |||
432 | 0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99, | 473 | 0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99, |
433 | 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff | 474 | 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff |
434 | }; | 475 | }; |
476 | /* gamma for sensor ADCM1700 */ | ||
477 | static const u8 gamma_spec_0[17] = { | ||
478 | 0x0f, 0x39, 0x5a, 0x74, 0x86, 0x95, 0xa6, 0xb4, | ||
479 | 0xbd, 0xc4, 0xcc, 0xd4, 0xd5, 0xde, 0xe4, 0xed, 0xf5 | ||
480 | }; | ||
435 | /* gamma for sensors HV7131R and MT9V111 */ | 481 | /* gamma for sensors HV7131R and MT9V111 */ |
436 | static const u8 gamma_spec_1[17] = { | 482 | static const u8 gamma_spec_1[17] = { |
437 | 0x08, 0x3a, 0x52, 0x65, 0x75, 0x83, 0x91, 0x9d, | 483 | 0x08, 0x3a, 0x52, 0x65, 0x75, 0x83, 0x91, 0x9d, |
@@ -450,6 +496,42 @@ static const u8 reg84[] = { | |||
450 | 0x3e, 0x00, 0xcd, 0x0f, 0xf7, 0x0f, /* VR VG VB */ | 496 | 0x3e, 0x00, 0xcd, 0x0f, 0xf7, 0x0f, /* VR VG VB */ |
451 | 0x00, 0x00, 0x00 /* YUV offsets */ | 497 | 0x00, 0x00, 0x00 /* YUV offsets */ |
452 | }; | 498 | }; |
499 | static const u8 adcm1700_sensor_init[][8] = { | ||
500 | {0xa0, 0x51, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
501 | {0xb0, 0x51, 0x04, 0x08, 0x00, 0x00, 0x00, 0x10}, /* reset */ | ||
502 | {0xdd, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, | ||
503 | {0xb0, 0x51, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
504 | {0xdd, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, | ||
505 | {0xb0, 0x51, 0x0c, 0xe0, 0x2e, 0x00, 0x00, 0x10}, | ||
506 | {0xb0, 0x51, 0x10, 0x02, 0x02, 0x00, 0x00, 0x10}, | ||
507 | {0xb0, 0x51, 0x14, 0x0e, 0x0e, 0x00, 0x00, 0x10}, | ||
508 | {0xb0, 0x51, 0x1c, 0x00, 0x80, 0x00, 0x00, 0x10}, | ||
509 | {0xb0, 0x51, 0x20, 0x01, 0x00, 0x00, 0x00, 0x10}, | ||
510 | {0xdd, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, | ||
511 | {0xb0, 0x51, 0x04, 0x04, 0x00, 0x00, 0x00, 0x10}, | ||
512 | {0xdd, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, | ||
513 | {0xb0, 0x51, 0x04, 0x01, 0x00, 0x00, 0x00, 0x10}, | ||
514 | {0xa0, 0x51, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x10}, | ||
515 | {0xb0, 0x51, 0x14, 0x01, 0x00, 0x00, 0x00, 0x10}, | ||
516 | {0xb0, 0x51, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
517 | {} | ||
518 | }; | ||
519 | static const u8 adcm1700_sensor_param1[][8] = { | ||
520 | {0xb0, 0x51, 0x26, 0xf9, 0x01, 0x00, 0x00, 0x10}, /* exposure? */ | ||
521 | {0xd0, 0x51, 0x1e, 0x8e, 0x8e, 0x8e, 0x8e, 0x10}, | ||
522 | |||
523 | {0xa0, 0x51, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x10}, | ||
524 | {0xb0, 0x51, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10}, | ||
525 | {0xa0, 0x51, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x10}, | ||
526 | {0xb0, 0x51, 0x32, 0x00, 0x72, 0x00, 0x00, 0x10}, | ||
527 | {0xd0, 0x51, 0x1e, 0xbe, 0xd7, 0xe8, 0xbe, 0x10}, /* exposure? */ | ||
528 | |||
529 | {0xa0, 0x51, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x10}, | ||
530 | {0xb0, 0x51, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10}, | ||
531 | {0xa0, 0x51, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x10}, | ||
532 | {0xb0, 0x51, 0x32, 0x00, 0xa2, 0x00, 0x00, 0x10}, | ||
533 | {} | ||
534 | }; | ||
453 | static const u8 hv7131r_sensor_init[][8] = { | 535 | static const u8 hv7131r_sensor_init[][8] = { |
454 | {0xc1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10}, | 536 | {0xc1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10}, |
455 | {0xb1, 0x11, 0x34, 0x17, 0x7f, 0x00, 0x00, 0x10}, | 537 | {0xb1, 0x11, 0x34, 0x17, 0x7f, 0x00, 0x00, 0x10}, |
@@ -986,17 +1068,18 @@ static const u8 sp80708_sensor_param1[][8] = { | |||
986 | {} | 1068 | {} |
987 | }; | 1069 | }; |
988 | 1070 | ||
989 | static const u8 (*sensor_init[10])[8] = { | 1071 | static const u8 (*sensor_init[11])[8] = { |
990 | hv7131r_sensor_init, /* HV7131R 0 */ | 1072 | adcm1700_sensor_init, /* ADCM1700 0 */ |
991 | mi0360_sensor_init, /* MI0360 1 */ | 1073 | hv7131r_sensor_init, /* HV7131R 1 */ |
992 | mo4000_sensor_init, /* MO4000 2 */ | 1074 | mi0360_sensor_init, /* MI0360 2 */ |
993 | mt9v111_sensor_init, /* MT9V111 3 */ | 1075 | mo4000_sensor_init, /* MO4000 3 */ |
994 | om6802_sensor_init, /* OM6802 4 */ | 1076 | mt9v111_sensor_init, /* MT9V111 4 */ |
995 | ov7630_sensor_init, /* OV7630 5 */ | 1077 | om6802_sensor_init, /* OM6802 5 */ |
996 | ov7648_sensor_init, /* OV7648 6 */ | 1078 | ov7630_sensor_init, /* OV7630 6 */ |
997 | ov7660_sensor_init, /* OV7660 7 */ | 1079 | ov7648_sensor_init, /* OV7648 7 */ |
998 | po1030_sensor_init, /* PO1030 8 */ | 1080 | ov7660_sensor_init, /* OV7660 8 */ |
999 | sp80708_sensor_init, /* SP80708 9 */ | 1081 | po1030_sensor_init, /* PO1030 9 */ |
1082 | sp80708_sensor_init, /* SP80708 10 */ | ||
1000 | }; | 1083 | }; |
1001 | 1084 | ||
1002 | /* read <len> bytes to gspca_dev->usb_buf */ | 1085 | /* read <len> bytes to gspca_dev->usb_buf */ |
@@ -1064,6 +1147,7 @@ static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val) | |||
1064 | 1147 | ||
1065 | PDEBUG(D_USBO, "i2c_w2 [%02x] = %02x", reg, val); | 1148 | PDEBUG(D_USBO, "i2c_w2 [%02x] = %02x", reg, val); |
1066 | switch (sd->sensor) { | 1149 | switch (sd->sensor) { |
1150 | case SENSOR_ADCM1700: | ||
1067 | case SENSOR_OM6802: /* i2c command = a0 (100 kHz) */ | 1151 | case SENSOR_OM6802: /* i2c command = a0 (100 kHz) */ |
1068 | gspca_dev->usb_buf[0] = 0x80 | (2 << 4); | 1152 | gspca_dev->usb_buf[0] = 0x80 | (2 << 4); |
1069 | break; | 1153 | break; |
@@ -1110,6 +1194,7 @@ static void i2c_r(struct gspca_dev *gspca_dev, u8 reg, int len) | |||
1110 | u8 mode[8]; | 1194 | u8 mode[8]; |
1111 | 1195 | ||
1112 | switch (sd->sensor) { | 1196 | switch (sd->sensor) { |
1197 | case SENSOR_ADCM1700: | ||
1113 | case SENSOR_OM6802: /* i2c command = 90 (100 kHz) */ | 1198 | case SENSOR_OM6802: /* i2c command = 90 (100 kHz) */ |
1114 | mode[0] = 0x80 | 0x10; | 1199 | mode[0] = 0x80 | 0x10; |
1115 | break; | 1200 | break; |
@@ -1260,7 +1345,8 @@ static void bridge_init(struct gspca_dev *gspca_dev, | |||
1260 | {0x00, 0x40, 0x38, 0x30, 0x00, 0x20}; | 1345 | {0x00, 0x40, 0x38, 0x30, 0x00, 0x20}; |
1261 | static const u8 regd4[] = {0x60, 0x00, 0x00}; | 1346 | static const u8 regd4[] = {0x60, 0x00, 0x00}; |
1262 | 1347 | ||
1263 | reg_w1(gspca_dev, 0xf1, 0x00); | 1348 | /* sensor clock already enabled in sd_init */ |
1349 | /* reg_w1(gspca_dev, 0xf1, 0x00); */ | ||
1264 | reg_w1(gspca_dev, 0x01, sn9c1xx[1]); | 1350 | reg_w1(gspca_dev, 0x01, sn9c1xx[1]); |
1265 | 1351 | ||
1266 | /* configure gpio */ | 1352 | /* configure gpio */ |
@@ -1284,6 +1370,12 @@ static void bridge_init(struct gspca_dev *gspca_dev, | |||
1284 | reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f); | 1370 | reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f); |
1285 | 1371 | ||
1286 | switch (sd->sensor) { | 1372 | switch (sd->sensor) { |
1373 | case SENSOR_ADCM1700: | ||
1374 | reg_w1(gspca_dev, 0x01, 0x43); | ||
1375 | reg_w1(gspca_dev, 0x17, 0x62); | ||
1376 | reg_w1(gspca_dev, 0x01, 0x42); | ||
1377 | reg_w1(gspca_dev, 0x01, 0x42); | ||
1378 | break; | ||
1287 | case SENSOR_MT9V111: | 1379 | case SENSOR_MT9V111: |
1288 | reg_w1(gspca_dev, 0x01, 0x61); | 1380 | reg_w1(gspca_dev, 0x01, 0x61); |
1289 | reg_w1(gspca_dev, 0x17, 0x61); | 1381 | reg_w1(gspca_dev, 0x17, 0x61); |
@@ -1357,14 +1449,19 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
1357 | struct sd *sd = (struct sd *) gspca_dev; | 1449 | struct sd *sd = (struct sd *) gspca_dev; |
1358 | struct cam *cam; | 1450 | struct cam *cam; |
1359 | 1451 | ||
1360 | cam = &gspca_dev->cam; | ||
1361 | cam->cam_mode = vga_mode; | ||
1362 | cam->nmodes = ARRAY_SIZE(vga_mode); | ||
1363 | cam->npkt = 24; /* 24 packets per ISOC message */ | ||
1364 | |||
1365 | sd->bridge = id->driver_info >> 16; | 1452 | sd->bridge = id->driver_info >> 16; |
1366 | sd->sensor = id->driver_info; | 1453 | sd->sensor = id->driver_info; |
1367 | 1454 | ||
1455 | cam = &gspca_dev->cam; | ||
1456 | if (sd->sensor == SENSOR_ADCM1700) { | ||
1457 | cam->cam_mode = cif_mode; | ||
1458 | cam->nmodes = ARRAY_SIZE(cif_mode); | ||
1459 | } else { | ||
1460 | cam->cam_mode = vga_mode; | ||
1461 | cam->nmodes = ARRAY_SIZE(vga_mode); | ||
1462 | } | ||
1463 | cam->npkt = 24; /* 24 packets per ISOC message */ | ||
1464 | |||
1368 | sd->brightness = BRIGHTNESS_DEF; | 1465 | sd->brightness = BRIGHTNESS_DEF; |
1369 | sd->contrast = CONTRAST_DEF; | 1466 | sd->contrast = CONTRAST_DEF; |
1370 | sd->colors = COLOR_DEF; | 1467 | sd->colors = COLOR_DEF; |
@@ -1374,6 +1471,14 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
1374 | sd->autogain = AUTOGAIN_DEF; | 1471 | sd->autogain = AUTOGAIN_DEF; |
1375 | sd->ag_cnt = -1; | 1472 | sd->ag_cnt = -1; |
1376 | sd->vflip = VFLIP_DEF; | 1473 | sd->vflip = VFLIP_DEF; |
1474 | switch (sd->sensor) { | ||
1475 | case SENSOR_OM6802: | ||
1476 | sd->sharpness = 0x10; | ||
1477 | break; | ||
1478 | default: | ||
1479 | sd->sharpness = SHARPNESS_DEF; | ||
1480 | break; | ||
1481 | } | ||
1377 | sd->infrared = INFRARED_DEF; | 1482 | sd->infrared = INFRARED_DEF; |
1378 | sd->freq = FREQ_DEF; | 1483 | sd->freq = FREQ_DEF; |
1379 | sd->quality = QUALITY_DEF; | 1484 | sd->quality = QUALITY_DEF; |
@@ -1433,7 +1538,9 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
1433 | break; | 1538 | break; |
1434 | } | 1539 | } |
1435 | 1540 | ||
1436 | reg_w1(gspca_dev, 0xf1, 0x01); | 1541 | /* Note we do not disable the sensor clock here (power saving mode), |
1542 | as that also disables the button on the cam. */ | ||
1543 | reg_w1(gspca_dev, 0xf1, 0x00); | ||
1437 | 1544 | ||
1438 | /* set the i2c address */ | 1545 | /* set the i2c address */ |
1439 | sn9c1xx = sn_tb[sd->sensor]; | 1546 | sn9c1xx = sn_tb[sd->sensor]; |
@@ -1543,6 +1650,10 @@ static void setbrightness(struct gspca_dev *gspca_dev) | |||
1543 | 1650 | ||
1544 | k2 = ((int) sd->brightness - 0x8000) >> 10; | 1651 | k2 = ((int) sd->brightness - 0x8000) >> 10; |
1545 | switch (sd->sensor) { | 1652 | switch (sd->sensor) { |
1653 | case SENSOR_ADCM1700: | ||
1654 | if (k2 > 0x1f) | ||
1655 | k2 = 0; /* only positive Y offset */ | ||
1656 | break; | ||
1546 | case SENSOR_HV7131R: | 1657 | case SENSOR_HV7131R: |
1547 | expo = sd->brightness << 4; | 1658 | expo = sd->brightness << 4; |
1548 | if (expo > 0x002dc6c0) | 1659 | if (expo > 0x002dc6c0) |
@@ -1625,6 +1736,9 @@ static void setgamma(struct gspca_dev *gspca_dev) | |||
1625 | }; | 1736 | }; |
1626 | 1737 | ||
1627 | switch (sd->sensor) { | 1738 | switch (sd->sensor) { |
1739 | case SENSOR_ADCM1700: | ||
1740 | gamma_base = gamma_spec_0; | ||
1741 | break; | ||
1628 | case SENSOR_HV7131R: | 1742 | case SENSOR_HV7131R: |
1629 | case SENSOR_MT9V111: | 1743 | case SENSOR_MT9V111: |
1630 | gamma_base = gamma_spec_1; | 1744 | gamma_base = gamma_spec_1; |
@@ -1670,23 +1784,39 @@ static void setautogain(struct gspca_dev *gspca_dev) | |||
1670 | sd->ag_cnt = -1; | 1784 | sd->ag_cnt = -1; |
1671 | } | 1785 | } |
1672 | 1786 | ||
1673 | /* ov7630/ov7648 only */ | 1787 | /* hv7131r/ov7630/ov7648 only */ |
1674 | static void setvflip(struct sd *sd) | 1788 | static void setvflip(struct sd *sd) |
1675 | { | 1789 | { |
1676 | u8 comn; | 1790 | u8 comn; |
1677 | 1791 | ||
1678 | if (sd->gspca_dev.ctrl_dis & (1 << VFLIP_IDX)) | 1792 | if (sd->gspca_dev.ctrl_dis & (1 << VFLIP_IDX)) |
1679 | return; | 1793 | return; |
1680 | if (sd->sensor == SENSOR_OV7630) { | 1794 | switch (sd->sensor) { |
1795 | case SENSOR_HV7131R: | ||
1796 | comn = 0x18; /* clkdiv = 1, ablcen = 1 */ | ||
1797 | if (sd->vflip) | ||
1798 | comn |= 0x01; | ||
1799 | i2c_w1(&sd->gspca_dev, 0x01, comn); /* sctra */ | ||
1800 | break; | ||
1801 | case SENSOR_OV7630: | ||
1681 | comn = 0x02; | 1802 | comn = 0x02; |
1682 | if (!sd->vflip) | 1803 | if (!sd->vflip) |
1683 | comn |= 0x80; | 1804 | comn |= 0x80; |
1684 | } else { | 1805 | i2c_w1(&sd->gspca_dev, 0x75, comn); |
1806 | break; | ||
1807 | default: | ||
1808 | /* case SENSOR_OV7648: */ | ||
1685 | comn = 0x06; | 1809 | comn = 0x06; |
1686 | if (sd->vflip) | 1810 | if (sd->vflip) |
1687 | comn |= 0x80; | 1811 | comn |= 0x80; |
1812 | i2c_w1(&sd->gspca_dev, 0x75, comn); | ||
1813 | break; | ||
1688 | } | 1814 | } |
1689 | i2c_w1(&sd->gspca_dev, 0x75, comn); | 1815 | } |
1816 | |||
1817 | static void setsharpness(struct sd *sd) | ||
1818 | { | ||
1819 | reg_w1(&sd->gspca_dev, 0x99, sd->sharpness); | ||
1690 | } | 1820 | } |
1691 | 1821 | ||
1692 | static void setinfrared(struct sd *sd) | 1822 | static void setinfrared(struct sd *sd) |
@@ -1804,6 +1934,8 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
1804 | int mode; | 1934 | int mode; |
1805 | static const u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f }; | 1935 | static const u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f }; |
1806 | static const u8 CA[] = { 0x28, 0xd8, 0x14, 0xec }; | 1936 | static const u8 CA[] = { 0x28, 0xd8, 0x14, 0xec }; |
1937 | static const u8 CA_adcm1700[] = | ||
1938 | { 0x14, 0xec, 0x0a, 0xf6 }; | ||
1807 | static const u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */ | 1939 | static const u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */ |
1808 | static const u8 CE_ov76xx[] = | 1940 | static const u8 CE_ov76xx[] = |
1809 | { 0x32, 0xdd, 0x32, 0xdd }; | 1941 | { 0x32, 0xdd, 0x32, 0xdd }; |
@@ -1824,6 +1956,9 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
1824 | i2c_w_seq(gspca_dev, sensor_init[sd->sensor]); | 1956 | i2c_w_seq(gspca_dev, sensor_init[sd->sensor]); |
1825 | 1957 | ||
1826 | switch (sd->sensor) { | 1958 | switch (sd->sensor) { |
1959 | case SENSOR_ADCM1700: | ||
1960 | reg2 = 0x60; | ||
1961 | break; | ||
1827 | case SENSOR_OM6802: | 1962 | case SENSOR_OM6802: |
1828 | reg2 = 0x71; | 1963 | reg2 = 0x71; |
1829 | break; | 1964 | break; |
@@ -1842,17 +1977,28 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
1842 | reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]); | 1977 | reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]); |
1843 | reg_w1(gspca_dev, 0x13, sn9c1xx[0x13]); | 1978 | reg_w1(gspca_dev, 0x13, sn9c1xx[0x13]); |
1844 | reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]); | 1979 | reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]); |
1845 | reg_w1(gspca_dev, 0xd2, 0x6a); /* DC29 */ | 1980 | if (sd->sensor == SENSOR_ADCM1700) { |
1846 | reg_w1(gspca_dev, 0xd3, 0x50); | 1981 | reg_w1(gspca_dev, 0xd2, 0x3a); /* AE_H_SIZE = 116 */ |
1982 | reg_w1(gspca_dev, 0xd3, 0x30); /* AE_V_SIZE = 96 */ | ||
1983 | } else { | ||
1984 | reg_w1(gspca_dev, 0xd2, 0x6a); /* AE_H_SIZE = 212 */ | ||
1985 | reg_w1(gspca_dev, 0xd3, 0x50); /* AE_V_SIZE = 160 */ | ||
1986 | } | ||
1847 | reg_w1(gspca_dev, 0xc6, 0x00); | 1987 | reg_w1(gspca_dev, 0xc6, 0x00); |
1848 | reg_w1(gspca_dev, 0xc7, 0x00); | 1988 | reg_w1(gspca_dev, 0xc7, 0x00); |
1849 | reg_w1(gspca_dev, 0xc8, 0x50); | 1989 | if (sd->sensor == SENSOR_ADCM1700) { |
1850 | reg_w1(gspca_dev, 0xc9, 0x3c); | 1990 | reg_w1(gspca_dev, 0xc8, 0x2c); /* AW_H_STOP = 352 */ |
1991 | reg_w1(gspca_dev, 0xc9, 0x24); /* AW_V_STOP = 288 */ | ||
1992 | } else { | ||
1993 | reg_w1(gspca_dev, 0xc8, 0x50); /* AW_H_STOP = 640 */ | ||
1994 | reg_w1(gspca_dev, 0xc9, 0x3c); /* AW_V_STOP = 480 */ | ||
1995 | } | ||
1851 | reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]); | 1996 | reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]); |
1852 | switch (sd->sensor) { | 1997 | switch (sd->sensor) { |
1853 | case SENSOR_MT9V111: | 1998 | case SENSOR_MT9V111: |
1854 | reg17 = 0xe0; | 1999 | reg17 = 0xe0; |
1855 | break; | 2000 | break; |
2001 | case SENSOR_ADCM1700: | ||
1856 | case SENSOR_OV7630: | 2002 | case SENSOR_OV7630: |
1857 | reg17 = 0xe2; | 2003 | reg17 = 0xe2; |
1858 | break; | 2004 | break; |
@@ -1870,44 +2016,39 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
1870 | break; | 2016 | break; |
1871 | } | 2017 | } |
1872 | reg_w1(gspca_dev, 0x17, reg17); | 2018 | reg_w1(gspca_dev, 0x17, reg17); |
1873 | /* set reg1 was here */ | 2019 | |
1874 | reg_w1(gspca_dev, 0x05, sn9c1xx[5]); /* red */ | 2020 | reg_w1(gspca_dev, 0x05, 0x00); /* red */ |
1875 | reg_w1(gspca_dev, 0x07, sn9c1xx[7]); /* green */ | 2021 | reg_w1(gspca_dev, 0x07, 0x00); /* green */ |
1876 | reg_w1(gspca_dev, 0x06, sn9c1xx[6]); /* blue */ | 2022 | reg_w1(gspca_dev, 0x06, 0x00); /* blue */ |
1877 | reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]); | 2023 | reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]); |
1878 | 2024 | ||
1879 | setgamma(gspca_dev); | 2025 | setgamma(gspca_dev); |
1880 | 2026 | ||
2027 | /*fixme: 8 times with all zeroes and 1 or 2 times with normal values */ | ||
1881 | for (i = 0; i < 8; i++) | 2028 | for (i = 0; i < 8; i++) |
1882 | reg_w(gspca_dev, 0x84, reg84, sizeof reg84); | 2029 | reg_w(gspca_dev, 0x84, reg84, sizeof reg84); |
1883 | switch (sd->sensor) { | 2030 | switch (sd->sensor) { |
2031 | case SENSOR_ADCM1700: | ||
2032 | case SENSOR_OV7660: | ||
2033 | case SENSOR_SP80708: | ||
2034 | reg_w1(gspca_dev, 0x9a, 0x05); | ||
2035 | break; | ||
1884 | case SENSOR_MT9V111: | 2036 | case SENSOR_MT9V111: |
1885 | reg_w1(gspca_dev, 0x9a, 0x07); | 2037 | reg_w1(gspca_dev, 0x9a, 0x07); |
1886 | reg_w1(gspca_dev, 0x99, 0x59); | ||
1887 | break; | ||
1888 | case SENSOR_OM6802: | ||
1889 | reg_w1(gspca_dev, 0x9a, 0x08); | ||
1890 | reg_w1(gspca_dev, 0x99, 0x10); | ||
1891 | break; | 2038 | break; |
1892 | case SENSOR_OV7648: | 2039 | case SENSOR_OV7648: |
1893 | reg_w1(gspca_dev, 0x9a, 0x0a); | 2040 | reg_w1(gspca_dev, 0x9a, 0x0a); |
1894 | reg_w1(gspca_dev, 0x99, 0x60); | ||
1895 | break; | ||
1896 | case SENSOR_OV7660: | ||
1897 | case SENSOR_SP80708: | ||
1898 | reg_w1(gspca_dev, 0x9a, 0x05); | ||
1899 | reg_w1(gspca_dev, 0x99, 0x59); | ||
1900 | break; | 2041 | break; |
1901 | default: | 2042 | default: |
1902 | reg_w1(gspca_dev, 0x9a, 0x08); | 2043 | reg_w1(gspca_dev, 0x9a, 0x08); |
1903 | reg_w1(gspca_dev, 0x99, 0x59); | ||
1904 | break; | 2044 | break; |
1905 | } | 2045 | } |
2046 | setsharpness(sd); | ||
1906 | 2047 | ||
1907 | reg_w(gspca_dev, 0x84, reg84, sizeof reg84); | 2048 | reg_w(gspca_dev, 0x84, reg84, sizeof reg84); |
1908 | reg_w1(gspca_dev, 0x05, sn9c1xx[5]); /* red */ | 2049 | reg_w1(gspca_dev, 0x05, 0x20); /* red */ |
1909 | reg_w1(gspca_dev, 0x07, sn9c1xx[7]); /* green */ | 2050 | reg_w1(gspca_dev, 0x07, 0x20); /* green */ |
1910 | reg_w1(gspca_dev, 0x06, sn9c1xx[6]); /* blue */ | 2051 | reg_w1(gspca_dev, 0x06, 0x20); /* blue */ |
1911 | 2052 | ||
1912 | init = NULL; | 2053 | init = NULL; |
1913 | mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; | 2054 | mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; |
@@ -1917,6 +2058,11 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
1917 | reg1 = 0x06; /* 640x480: clk 24Mhz, video trf enable */ | 2058 | reg1 = 0x06; /* 640x480: clk 24Mhz, video trf enable */ |
1918 | reg17 = 0x61; /* 0x:20: enable sensor clock */ | 2059 | reg17 = 0x61; /* 0x:20: enable sensor clock */ |
1919 | switch (sd->sensor) { | 2060 | switch (sd->sensor) { |
2061 | case SENSOR_ADCM1700: | ||
2062 | init = adcm1700_sensor_param1; | ||
2063 | reg1 = 0x46; | ||
2064 | reg17 = 0xe2; | ||
2065 | break; | ||
1920 | case SENSOR_MO4000: | 2066 | case SENSOR_MO4000: |
1921 | if (mode) { | 2067 | if (mode) { |
1922 | /* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */ | 2068 | /* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */ |
@@ -1940,7 +2086,6 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
1940 | reg17 = 0x64; /* 640 MCKSIZE */ | 2086 | reg17 = 0x64; /* 640 MCKSIZE */ |
1941 | break; | 2087 | break; |
1942 | case SENSOR_OV7630: | 2088 | case SENSOR_OV7630: |
1943 | setvflip(sd); | ||
1944 | reg17 = 0xe2; | 2089 | reg17 = 0xe2; |
1945 | reg1 = 0x44; | 2090 | reg1 = 0x44; |
1946 | break; | 2091 | break; |
@@ -1986,8 +2131,12 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
1986 | } | 2131 | } |
1987 | 2132 | ||
1988 | reg_w(gspca_dev, 0xc0, C0, 6); | 2133 | reg_w(gspca_dev, 0xc0, C0, 6); |
1989 | reg_w(gspca_dev, 0xca, CA, 4); | 2134 | if (sd->sensor == SENSOR_ADCM1700) |
2135 | reg_w(gspca_dev, 0xca, CA_adcm1700, 4); | ||
2136 | else | ||
2137 | reg_w(gspca_dev, 0xca, CA, 4); | ||
1990 | switch (sd->sensor) { | 2138 | switch (sd->sensor) { |
2139 | case SENSOR_ADCM1700: | ||
1991 | case SENSOR_OV7630: | 2140 | case SENSOR_OV7630: |
1992 | case SENSOR_OV7648: | 2141 | case SENSOR_OV7648: |
1993 | case SENSOR_OV7660: | 2142 | case SENSOR_OV7660: |
@@ -2008,11 +2157,7 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
2008 | reg_w1(gspca_dev, 0x17, reg17); | 2157 | reg_w1(gspca_dev, 0x17, reg17); |
2009 | reg_w1(gspca_dev, 0x01, reg1); | 2158 | reg_w1(gspca_dev, 0x01, reg1); |
2010 | 2159 | ||
2011 | switch (sd->sensor) { | 2160 | setvflip(sd); |
2012 | case SENSOR_OV7630: | ||
2013 | setvflip(sd); | ||
2014 | break; | ||
2015 | } | ||
2016 | setbrightness(gspca_dev); | 2161 | setbrightness(gspca_dev); |
2017 | setcontrast(gspca_dev); | 2162 | setcontrast(gspca_dev); |
2018 | setautogain(gspca_dev); | 2163 | setautogain(gspca_dev); |
@@ -2056,7 +2201,8 @@ static void sd_stopN(struct gspca_dev *gspca_dev) | |||
2056 | reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]); | 2201 | reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]); |
2057 | reg_w1(gspca_dev, 0x01, sn9c1xx[1]); | 2202 | reg_w1(gspca_dev, 0x01, sn9c1xx[1]); |
2058 | reg_w1(gspca_dev, 0x01, data); | 2203 | reg_w1(gspca_dev, 0x01, data); |
2059 | reg_w1(gspca_dev, 0xf1, 0x00); | 2204 | /* Don't disable sensor clock as that disables the button on the cam */ |
2205 | /* reg_w1(gspca_dev, 0xf1, 0x01); */ | ||
2060 | } | 2206 | } |
2061 | 2207 | ||
2062 | static void sd_stop0(struct gspca_dev *gspca_dev) | 2208 | static void sd_stop0(struct gspca_dev *gspca_dev) |
@@ -2288,6 +2434,24 @@ static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) | |||
2288 | return 0; | 2434 | return 0; |
2289 | } | 2435 | } |
2290 | 2436 | ||
2437 | static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val) | ||
2438 | { | ||
2439 | struct sd *sd = (struct sd *) gspca_dev; | ||
2440 | |||
2441 | sd->sharpness = val; | ||
2442 | if (gspca_dev->streaming) | ||
2443 | setsharpness(sd); | ||
2444 | return 0; | ||
2445 | } | ||
2446 | |||
2447 | static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val) | ||
2448 | { | ||
2449 | struct sd *sd = (struct sd *) gspca_dev; | ||
2450 | |||
2451 | *val = sd->sharpness; | ||
2452 | return 0; | ||
2453 | } | ||
2454 | |||
2291 | static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val) | 2455 | static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val) |
2292 | { | 2456 | { |
2293 | struct sd *sd = (struct sd *) gspca_dev; | 2457 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -2391,6 +2555,25 @@ static int sd_querymenu(struct gspca_dev *gspca_dev, | |||
2391 | return -EINVAL; | 2555 | return -EINVAL; |
2392 | } | 2556 | } |
2393 | 2557 | ||
2558 | #ifdef CONFIG_INPUT | ||
2559 | static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, | ||
2560 | u8 *data, /* interrupt packet data */ | ||
2561 | int len) /* interrupt packet length */ | ||
2562 | { | ||
2563 | int ret = -EINVAL; | ||
2564 | |||
2565 | if (len == 1 && data[0] == 1) { | ||
2566 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); | ||
2567 | input_sync(gspca_dev->input_dev); | ||
2568 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); | ||
2569 | input_sync(gspca_dev->input_dev); | ||
2570 | ret = 0; | ||
2571 | } | ||
2572 | |||
2573 | return ret; | ||
2574 | } | ||
2575 | #endif | ||
2576 | |||
2394 | /* sub-driver description */ | 2577 | /* sub-driver description */ |
2395 | static const struct sd_desc sd_desc = { | 2578 | static const struct sd_desc sd_desc = { |
2396 | .name = MODULE_NAME, | 2579 | .name = MODULE_NAME, |
@@ -2406,6 +2589,9 @@ static const struct sd_desc sd_desc = { | |||
2406 | .get_jcomp = sd_get_jcomp, | 2589 | .get_jcomp = sd_get_jcomp, |
2407 | .set_jcomp = sd_set_jcomp, | 2590 | .set_jcomp = sd_set_jcomp, |
2408 | .querymenu = sd_querymenu, | 2591 | .querymenu = sd_querymenu, |
2592 | #ifdef CONFIG_INPUT | ||
2593 | .int_pkt_scan = sd_int_pkt_scan, | ||
2594 | #endif | ||
2409 | }; | 2595 | }; |
2410 | 2596 | ||
2411 | /* -- module initialisation -- */ | 2597 | /* -- module initialisation -- */ |
@@ -2472,6 +2658,7 @@ static const __devinitdata struct usb_device_id device_table[] = { | |||
2472 | /* {USB_DEVICE(0x0c45, 0x6142), BS(SN9C120, PO2030N)}, *sn9c120b*/ | 2658 | /* {USB_DEVICE(0x0c45, 0x6142), BS(SN9C120, PO2030N)}, *sn9c120b*/ |
2473 | {USB_DEVICE(0x0c45, 0x6143), BS(SN9C120, SP80708)}, /*sn9c120b*/ | 2659 | {USB_DEVICE(0x0c45, 0x6143), BS(SN9C120, SP80708)}, /*sn9c120b*/ |
2474 | {USB_DEVICE(0x0c45, 0x6148), BS(SN9C120, OM6802)}, /*sn9c120b*/ | 2660 | {USB_DEVICE(0x0c45, 0x6148), BS(SN9C120, OM6802)}, /*sn9c120b*/ |
2661 | {USB_DEVICE(0x0c45, 0x614a), BS(SN9C120, ADCM1700)}, /*sn9c120b*/ | ||
2475 | {} | 2662 | {} |
2476 | }; | 2663 | }; |
2477 | MODULE_DEVICE_TABLE(usb, device_table); | 2664 | MODULE_DEVICE_TABLE(usb, device_table); |
diff --git a/drivers/media/video/gspca/spca500.c b/drivers/media/video/gspca/spca500.c index fe46868a87f2..b866c73c97db 100644 --- a/drivers/media/video/gspca/spca500.c +++ b/drivers/media/video/gspca/spca500.c | |||
@@ -68,7 +68,7 @@ static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | |||
68 | static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); | 68 | static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); |
69 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); | 69 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); |
70 | 70 | ||
71 | static struct ctrl sd_ctrls[] = { | 71 | static const struct ctrl sd_ctrls[] = { |
72 | { | 72 | { |
73 | { | 73 | { |
74 | .id = V4L2_CID_BRIGHTNESS, | 74 | .id = V4L2_CID_BRIGHTNESS, |
@@ -1047,7 +1047,7 @@ static int sd_get_jcomp(struct gspca_dev *gspca_dev, | |||
1047 | } | 1047 | } |
1048 | 1048 | ||
1049 | /* sub-driver description */ | 1049 | /* sub-driver description */ |
1050 | static struct sd_desc sd_desc = { | 1050 | static const struct sd_desc sd_desc = { |
1051 | .name = MODULE_NAME, | 1051 | .name = MODULE_NAME, |
1052 | .ctrls = sd_ctrls, | 1052 | .ctrls = sd_ctrls, |
1053 | .nctrls = ARRAY_SIZE(sd_ctrls), | 1053 | .nctrls = ARRAY_SIZE(sd_ctrls), |
diff --git a/drivers/media/video/gspca/spca501.c b/drivers/media/video/gspca/spca501.c index 6761a3048a98..c99333933e32 100644 --- a/drivers/media/video/gspca/spca501.c +++ b/drivers/media/video/gspca/spca501.c | |||
@@ -59,7 +59,7 @@ static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val); | |||
59 | static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val); | 59 | static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val); |
60 | static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val); | 60 | static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val); |
61 | 61 | ||
62 | static struct ctrl sd_ctrls[] = { | 62 | static const struct ctrl sd_ctrls[] = { |
63 | #define MY_BRIGHTNESS 0 | 63 | #define MY_BRIGHTNESS 0 |
64 | { | 64 | { |
65 | { | 65 | { |
diff --git a/drivers/media/video/gspca/spca505.c b/drivers/media/video/gspca/spca505.c index 0f9232ff1281..c576eed73abe 100644 --- a/drivers/media/video/gspca/spca505.c +++ b/drivers/media/video/gspca/spca505.c | |||
@@ -42,7 +42,7 @@ struct sd { | |||
42 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | 42 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); |
43 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | 43 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); |
44 | 44 | ||
45 | static struct ctrl sd_ctrls[] = { | 45 | static const struct ctrl sd_ctrls[] = { |
46 | { | 46 | { |
47 | { | 47 | { |
48 | .id = V4L2_CID_BRIGHTNESS, | 48 | .id = V4L2_CID_BRIGHTNESS, |
diff --git a/drivers/media/video/gspca/spca506.c b/drivers/media/video/gspca/spca506.c index 39257e4e074f..89fec4c500af 100644 --- a/drivers/media/video/gspca/spca506.c +++ b/drivers/media/video/gspca/spca506.c | |||
@@ -51,7 +51,7 @@ static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); | |||
51 | static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val); | 51 | static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val); |
52 | static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val); | 52 | static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val); |
53 | 53 | ||
54 | static struct ctrl sd_ctrls[] = { | 54 | static const struct ctrl sd_ctrls[] = { |
55 | #define SD_BRIGHTNESS 0 | 55 | #define SD_BRIGHTNESS 0 |
56 | { | 56 | { |
57 | { | 57 | { |
@@ -673,7 +673,7 @@ static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val) | |||
673 | } | 673 | } |
674 | 674 | ||
675 | /* sub-driver description */ | 675 | /* sub-driver description */ |
676 | static struct sd_desc sd_desc = { | 676 | static const struct sd_desc sd_desc = { |
677 | .name = MODULE_NAME, | 677 | .name = MODULE_NAME, |
678 | .ctrls = sd_ctrls, | 678 | .ctrls = sd_ctrls, |
679 | .nctrls = ARRAY_SIZE(sd_ctrls), | 679 | .nctrls = ARRAY_SIZE(sd_ctrls), |
diff --git a/drivers/media/video/gspca/spca508.c b/drivers/media/video/gspca/spca508.c index 4d8e6cf75d55..15b2eef8a3f6 100644 --- a/drivers/media/video/gspca/spca508.c +++ b/drivers/media/video/gspca/spca508.c | |||
@@ -45,7 +45,7 @@ struct sd { | |||
45 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | 45 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); |
46 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | 46 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); |
47 | 47 | ||
48 | static struct ctrl sd_ctrls[] = { | 48 | static const struct ctrl sd_ctrls[] = { |
49 | { | 49 | { |
50 | { | 50 | { |
51 | .id = V4L2_CID_BRIGHTNESS, | 51 | .id = V4L2_CID_BRIGHTNESS, |
diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index 58c2f0039af1..dc7f2b0fbc79 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c | |||
@@ -922,7 +922,7 @@ static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) | |||
922 | } | 922 | } |
923 | 923 | ||
924 | /* control tables */ | 924 | /* control tables */ |
925 | static struct ctrl sd_ctrls_12a[] = { | 925 | static const struct ctrl sd_ctrls_12a[] = { |
926 | { | 926 | { |
927 | { | 927 | { |
928 | .id = V4L2_CID_HUE, | 928 | .id = V4L2_CID_HUE, |
@@ -964,7 +964,7 @@ static struct ctrl sd_ctrls_12a[] = { | |||
964 | }, | 964 | }, |
965 | }; | 965 | }; |
966 | 966 | ||
967 | static struct ctrl sd_ctrls_72a[] = { | 967 | static const struct ctrl sd_ctrls_72a[] = { |
968 | { | 968 | { |
969 | { | 969 | { |
970 | .id = V4L2_CID_HUE, | 970 | .id = V4L2_CID_HUE, |
diff --git a/drivers/media/video/gspca/sq905c.c b/drivers/media/video/gspca/sq905c.c index d70b156872d6..e64662052992 100644 --- a/drivers/media/video/gspca/sq905c.c +++ b/drivers/media/video/gspca/sq905c.c | |||
@@ -47,6 +47,7 @@ MODULE_LICENSE("GPL"); | |||
47 | 47 | ||
48 | /* Commands. These go in the "value" slot. */ | 48 | /* Commands. These go in the "value" slot. */ |
49 | #define SQ905C_CLEAR 0xa0 /* clear everything */ | 49 | #define SQ905C_CLEAR 0xa0 /* clear everything */ |
50 | #define SQ905C_GET_ID 0x14f4 /* Read version number */ | ||
50 | #define SQ905C_CAPTURE_LOW 0xa040 /* Starts capture at 160x120 */ | 51 | #define SQ905C_CAPTURE_LOW 0xa040 /* Starts capture at 160x120 */ |
51 | #define SQ905C_CAPTURE_MED 0x1440 /* Starts capture at 320x240 */ | 52 | #define SQ905C_CAPTURE_MED 0x1440 /* Starts capture at 320x240 */ |
52 | #define SQ905C_CAPTURE_HI 0x2840 /* Starts capture at 320x240 */ | 53 | #define SQ905C_CAPTURE_HI 0x2840 /* Starts capture at 320x240 */ |
@@ -101,6 +102,26 @@ static int sq905c_command(struct gspca_dev *gspca_dev, u16 command, u16 index) | |||
101 | return 0; | 102 | return 0; |
102 | } | 103 | } |
103 | 104 | ||
105 | static int sq905c_read(struct gspca_dev *gspca_dev, u16 command, u16 index, | ||
106 | int size) | ||
107 | { | ||
108 | int ret; | ||
109 | |||
110 | ret = usb_control_msg(gspca_dev->dev, | ||
111 | usb_rcvctrlpipe(gspca_dev->dev, 0), | ||
112 | USB_REQ_SYNCH_FRAME, /* request */ | ||
113 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
114 | command, index, gspca_dev->usb_buf, size, | ||
115 | SQ905C_CMD_TIMEOUT); | ||
116 | if (ret < 0) { | ||
117 | PDEBUG(D_ERR, "%s: usb_control_msg failed (%d)", | ||
118 | __func__, ret); | ||
119 | return ret; | ||
120 | } | ||
121 | |||
122 | return 0; | ||
123 | } | ||
124 | |||
104 | /* This function is called as a workqueue function and runs whenever the camera | 125 | /* This function is called as a workqueue function and runs whenever the camera |
105 | * is streaming data. Because it is a workqueue function it is allowed to sleep | 126 | * is streaming data. Because it is a workqueue function it is allowed to sleep |
106 | * so we can use synchronous USB calls. To avoid possible collisions with other | 127 | * so we can use synchronous USB calls. To avoid possible collisions with other |
@@ -183,13 +204,34 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
183 | { | 204 | { |
184 | struct cam *cam = &gspca_dev->cam; | 205 | struct cam *cam = &gspca_dev->cam; |
185 | struct sd *dev = (struct sd *) gspca_dev; | 206 | struct sd *dev = (struct sd *) gspca_dev; |
207 | int ret; | ||
186 | 208 | ||
187 | PDEBUG(D_PROBE, | 209 | PDEBUG(D_PROBE, |
188 | "SQ9050 camera detected" | 210 | "SQ9050 camera detected" |
189 | " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); | 211 | " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); |
212 | |||
213 | ret = sq905c_command(gspca_dev, SQ905C_GET_ID, 0); | ||
214 | if (ret < 0) { | ||
215 | PDEBUG(D_ERR, "Get version command failed"); | ||
216 | return ret; | ||
217 | } | ||
218 | |||
219 | ret = sq905c_read(gspca_dev, 0xf5, 0, 20); | ||
220 | if (ret < 0) { | ||
221 | PDEBUG(D_ERR, "Reading version command failed"); | ||
222 | return ret; | ||
223 | } | ||
224 | /* Note we leave out the usb id and the manufacturing date */ | ||
225 | PDEBUG(D_PROBE, | ||
226 | "SQ9050 ID string: %02x - %02x %02x %02x %02x %02x %02x", | ||
227 | gspca_dev->usb_buf[3], | ||
228 | gspca_dev->usb_buf[14], gspca_dev->usb_buf[15], | ||
229 | gspca_dev->usb_buf[16], gspca_dev->usb_buf[17], | ||
230 | gspca_dev->usb_buf[18], gspca_dev->usb_buf[19]); | ||
231 | |||
190 | cam->cam_mode = sq905c_mode; | 232 | cam->cam_mode = sq905c_mode; |
191 | cam->nmodes = 2; | 233 | cam->nmodes = 2; |
192 | if (id->idProduct == 0x9050) | 234 | if (gspca_dev->usb_buf[15] == 0) |
193 | cam->nmodes = 1; | 235 | cam->nmodes = 1; |
194 | /* We don't use the buffer gspca allocates so make it small. */ | 236 | /* We don't use the buffer gspca allocates so make it small. */ |
195 | cam->bulk_size = 32; | 237 | cam->bulk_size = 32; |
@@ -258,6 +300,7 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
258 | static const __devinitdata struct usb_device_id device_table[] = { | 300 | static const __devinitdata struct usb_device_id device_table[] = { |
259 | {USB_DEVICE(0x2770, 0x905c)}, | 301 | {USB_DEVICE(0x2770, 0x905c)}, |
260 | {USB_DEVICE(0x2770, 0x9050)}, | 302 | {USB_DEVICE(0x2770, 0x9050)}, |
303 | {USB_DEVICE(0x2770, 0x9052)}, | ||
261 | {USB_DEVICE(0x2770, 0x913d)}, | 304 | {USB_DEVICE(0x2770, 0x913d)}, |
262 | {} | 305 | {} |
263 | }; | 306 | }; |
diff --git a/drivers/media/video/gspca/stk014.c b/drivers/media/video/gspca/stk014.c index 2e2935532d99..0fb534210a2c 100644 --- a/drivers/media/video/gspca/stk014.c +++ b/drivers/media/video/gspca/stk014.c | |||
@@ -53,7 +53,7 @@ static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); | |||
53 | static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); | 53 | static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); |
54 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); | 54 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); |
55 | 55 | ||
56 | static struct ctrl sd_ctrls[] = { | 56 | static const struct ctrl sd_ctrls[] = { |
57 | { | 57 | { |
58 | { | 58 | { |
59 | .id = V4L2_CID_BRIGHTNESS, | 59 | .id = V4L2_CID_BRIGHTNESS, |
diff --git a/drivers/media/video/gspca/stv0680.c b/drivers/media/video/gspca/stv0680.c index 2a69d7ccb50d..e50dd7693f74 100644 --- a/drivers/media/video/gspca/stv0680.c +++ b/drivers/media/video/gspca/stv0680.c | |||
@@ -45,7 +45,7 @@ struct sd { | |||
45 | }; | 45 | }; |
46 | 46 | ||
47 | /* V4L2 controls supported by the driver */ | 47 | /* V4L2 controls supported by the driver */ |
48 | static struct ctrl sd_ctrls[] = { | 48 | static const struct ctrl sd_ctrls[] = { |
49 | }; | 49 | }; |
50 | 50 | ||
51 | static int stv_sndctrl(struct gspca_dev *gspca_dev, int set, u8 req, u16 val, | 51 | static int stv_sndctrl(struct gspca_dev *gspca_dev, int set, u8 req, u16 val, |
@@ -53,24 +53,28 @@ static int stv_sndctrl(struct gspca_dev *gspca_dev, int set, u8 req, u16 val, | |||
53 | { | 53 | { |
54 | int ret = -1; | 54 | int ret = -1; |
55 | u8 req_type = 0; | 55 | u8 req_type = 0; |
56 | unsigned int pipe = 0; | ||
56 | 57 | ||
57 | switch (set) { | 58 | switch (set) { |
58 | case 0: /* 0xc1 */ | 59 | case 0: /* 0xc1 */ |
59 | req_type = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT; | 60 | req_type = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT; |
61 | pipe = usb_rcvctrlpipe(gspca_dev->dev, 0); | ||
60 | break; | 62 | break; |
61 | case 1: /* 0x41 */ | 63 | case 1: /* 0x41 */ |
62 | req_type = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT; | 64 | req_type = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT; |
65 | pipe = usb_sndctrlpipe(gspca_dev->dev, 0); | ||
63 | break; | 66 | break; |
64 | case 2: /* 0x80 */ | 67 | case 2: /* 0x80 */ |
65 | req_type = USB_DIR_IN | USB_RECIP_DEVICE; | 68 | req_type = USB_DIR_IN | USB_RECIP_DEVICE; |
69 | pipe = usb_rcvctrlpipe(gspca_dev->dev, 0); | ||
66 | break; | 70 | break; |
67 | case 3: /* 0x40 */ | 71 | case 3: /* 0x40 */ |
68 | req_type = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE; | 72 | req_type = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE; |
73 | pipe = usb_sndctrlpipe(gspca_dev->dev, 0); | ||
69 | break; | 74 | break; |
70 | } | 75 | } |
71 | 76 | ||
72 | ret = usb_control_msg(gspca_dev->dev, | 77 | ret = usb_control_msg(gspca_dev->dev, pipe, |
73 | usb_rcvctrlpipe(gspca_dev->dev, 0), | ||
74 | req, req_type, | 78 | req, req_type, |
75 | val, 0, gspca_dev->usb_buf, size, 500); | 79 | val, 0, gspca_dev->usb_buf, size, 500); |
76 | 80 | ||
@@ -138,6 +142,10 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
138 | struct sd *sd = (struct sd *) gspca_dev; | 142 | struct sd *sd = (struct sd *) gspca_dev; |
139 | struct cam *cam = &gspca_dev->cam; | 143 | struct cam *cam = &gspca_dev->cam; |
140 | 144 | ||
145 | /* Give the camera some time to settle, otherwise initalization will | ||
146 | fail on hotplug, and yes it really needs a full second. */ | ||
147 | msleep(1000); | ||
148 | |||
141 | /* ping camera to be sure STV0680 is present */ | 149 | /* ping camera to be sure STV0680 is present */ |
142 | if (stv_sndctrl(gspca_dev, 0, 0x88, 0x5678, 0x02) != 0x02 || | 150 | if (stv_sndctrl(gspca_dev, 0, 0x88, 0x5678, 0x02) != 0x02 || |
143 | gspca_dev->usb_buf[0] != 0x56 || gspca_dev->usb_buf[1] != 0x78) { | 151 | gspca_dev->usb_buf[0] != 0x56 || gspca_dev->usb_buf[1] != 0x78) { |
@@ -169,6 +177,8 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
169 | PDEBUG(D_PROBE, "Camera supports CIF mode"); | 177 | PDEBUG(D_PROBE, "Camera supports CIF mode"); |
170 | if (gspca_dev->usb_buf[7] & 0x02) | 178 | if (gspca_dev->usb_buf[7] & 0x02) |
171 | PDEBUG(D_PROBE, "Camera supports VGA mode"); | 179 | PDEBUG(D_PROBE, "Camera supports VGA mode"); |
180 | if (gspca_dev->usb_buf[7] & 0x04) | ||
181 | PDEBUG(D_PROBE, "Camera supports QCIF mode"); | ||
172 | if (gspca_dev->usb_buf[7] & 0x08) | 182 | if (gspca_dev->usb_buf[7] & 0x08) |
173 | PDEBUG(D_PROBE, "Camera supports QVGA mode"); | 183 | PDEBUG(D_PROBE, "Camera supports QVGA mode"); |
174 | 184 | ||
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.c b/drivers/media/video/gspca/stv06xx/stv06xx.c index 5d0241bb1611..af73da34c83f 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx.c +++ b/drivers/media/video/gspca/stv06xx/stv06xx.c | |||
@@ -27,6 +27,7 @@ | |||
27 | * P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web | 27 | * P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web |
28 | */ | 28 | */ |
29 | 29 | ||
30 | #include <linux/input.h> | ||
30 | #include "stv06xx_sensor.h" | 31 | #include "stv06xx_sensor.h" |
31 | 32 | ||
32 | MODULE_AUTHOR("Erik Andrén"); | 33 | MODULE_AUTHOR("Erik Andrén"); |
@@ -219,6 +220,7 @@ static void stv06xx_dump_bridge(struct sd *sd) | |||
219 | info("Read 0x%x from address 0x%x", data, i); | 220 | info("Read 0x%x from address 0x%x", data, i); |
220 | } | 221 | } |
221 | 222 | ||
223 | info("Testing stv06xx bridge registers for writability"); | ||
222 | for (i = 0x1400; i < 0x160f; i++) { | 224 | for (i = 0x1400; i < 0x160f; i++) { |
223 | stv06xx_read_bridge(sd, i, &data); | 225 | stv06xx_read_bridge(sd, i, &data); |
224 | buf = data; | 226 | buf = data; |
@@ -229,7 +231,7 @@ static void stv06xx_dump_bridge(struct sd *sd) | |||
229 | info("Register 0x%x is read/write", i); | 231 | info("Register 0x%x is read/write", i); |
230 | else if (data != buf) | 232 | else if (data != buf) |
231 | info("Register 0x%x is read/write," | 233 | info("Register 0x%x is read/write," |
232 | "but only partially", i); | 234 | " but only partially", i); |
233 | else | 235 | else |
234 | info("Register 0x%x is read-only", i); | 236 | info("Register 0x%x is read-only", i); |
235 | 237 | ||
@@ -426,6 +428,29 @@ frame_data: | |||
426 | } | 428 | } |
427 | } | 429 | } |
428 | 430 | ||
431 | #ifdef CONFIG_INPUT | ||
432 | static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, | ||
433 | u8 *data, /* interrupt packet data */ | ||
434 | int len) /* interrupt packet length */ | ||
435 | { | ||
436 | int ret = -EINVAL; | ||
437 | |||
438 | if (len == 1 && data[0] == 0x80) { | ||
439 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); | ||
440 | input_sync(gspca_dev->input_dev); | ||
441 | ret = 0; | ||
442 | } | ||
443 | |||
444 | if (len == 1 && data[0] == 0x88) { | ||
445 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); | ||
446 | input_sync(gspca_dev->input_dev); | ||
447 | ret = 0; | ||
448 | } | ||
449 | |||
450 | return ret; | ||
451 | } | ||
452 | #endif | ||
453 | |||
429 | static int stv06xx_config(struct gspca_dev *gspca_dev, | 454 | static int stv06xx_config(struct gspca_dev *gspca_dev, |
430 | const struct usb_device_id *id); | 455 | const struct usb_device_id *id); |
431 | 456 | ||
@@ -436,7 +461,10 @@ static const struct sd_desc sd_desc = { | |||
436 | .init = stv06xx_init, | 461 | .init = stv06xx_init, |
437 | .start = stv06xx_start, | 462 | .start = stv06xx_start, |
438 | .stopN = stv06xx_stopN, | 463 | .stopN = stv06xx_stopN, |
439 | .pkt_scan = stv06xx_pkt_scan | 464 | .pkt_scan = stv06xx_pkt_scan, |
465 | #ifdef CONFIG_INPUT | ||
466 | .int_pkt_scan = sd_int_pkt_scan, | ||
467 | #endif | ||
440 | }; | 468 | }; |
441 | 469 | ||
442 | /* This function is called at probe time */ | 470 | /* This function is called at probe time */ |
diff --git a/drivers/media/video/gspca/sunplus.c b/drivers/media/video/gspca/sunplus.c index 306b7d75b4aa..0c786e00ebcf 100644 --- a/drivers/media/video/gspca/sunplus.c +++ b/drivers/media/video/gspca/sunplus.c | |||
@@ -67,7 +67,7 @@ static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); | |||
67 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); | 67 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); |
68 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); | 68 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); |
69 | 69 | ||
70 | static struct ctrl sd_ctrls[] = { | 70 | static const struct ctrl sd_ctrls[] = { |
71 | { | 71 | { |
72 | { | 72 | { |
73 | .id = V4L2_CID_BRIGHTNESS, | 73 | .id = V4L2_CID_BRIGHTNESS, |
@@ -267,142 +267,6 @@ static const struct cmd spca504A_clicksmart420_open_data[] = { | |||
267 | {0x06, 0x0000, 0x0000}, | 267 | {0x06, 0x0000, 0x0000}, |
268 | {0x00, 0x0004, 0x2880}, | 268 | {0x00, 0x0004, 0x2880}, |
269 | {0x00, 0x0001, 0x2881}, | 269 | {0x00, 0x0001, 0x2881}, |
270 | /* look like setting a qTable */ | ||
271 | {0x00, 0x0006, 0x2800}, | ||
272 | {0x00, 0x0004, 0x2801}, | ||
273 | {0x00, 0x0004, 0x2802}, | ||
274 | {0x00, 0x0006, 0x2803}, | ||
275 | {0x00, 0x000a, 0x2804}, | ||
276 | {0x00, 0x0010, 0x2805}, | ||
277 | {0x00, 0x0014, 0x2806}, | ||
278 | {0x00, 0x0018, 0x2807}, | ||
279 | {0x00, 0x0005, 0x2808}, | ||
280 | {0x00, 0x0005, 0x2809}, | ||
281 | {0x00, 0x0006, 0x280a}, | ||
282 | {0x00, 0x0008, 0x280b}, | ||
283 | {0x00, 0x000a, 0x280c}, | ||
284 | {0x00, 0x0017, 0x280d}, | ||
285 | {0x00, 0x0018, 0x280e}, | ||
286 | {0x00, 0x0016, 0x280f}, | ||
287 | |||
288 | {0x00, 0x0006, 0x2810}, | ||
289 | {0x00, 0x0005, 0x2811}, | ||
290 | {0x00, 0x0006, 0x2812}, | ||
291 | {0x00, 0x000a, 0x2813}, | ||
292 | {0x00, 0x0010, 0x2814}, | ||
293 | {0x00, 0x0017, 0x2815}, | ||
294 | {0x00, 0x001c, 0x2816}, | ||
295 | {0x00, 0x0016, 0x2817}, | ||
296 | {0x00, 0x0006, 0x2818}, | ||
297 | {0x00, 0x0007, 0x2819}, | ||
298 | {0x00, 0x0009, 0x281a}, | ||
299 | {0x00, 0x000c, 0x281b}, | ||
300 | {0x00, 0x0014, 0x281c}, | ||
301 | {0x00, 0x0023, 0x281d}, | ||
302 | {0x00, 0x0020, 0x281e}, | ||
303 | {0x00, 0x0019, 0x281f}, | ||
304 | |||
305 | {0x00, 0x0007, 0x2820}, | ||
306 | {0x00, 0x0009, 0x2821}, | ||
307 | {0x00, 0x000f, 0x2822}, | ||
308 | {0x00, 0x0016, 0x2823}, | ||
309 | {0x00, 0x001b, 0x2824}, | ||
310 | {0x00, 0x002c, 0x2825}, | ||
311 | {0x00, 0x0029, 0x2826}, | ||
312 | {0x00, 0x001f, 0x2827}, | ||
313 | {0x00, 0x000a, 0x2828}, | ||
314 | {0x00, 0x000e, 0x2829}, | ||
315 | {0x00, 0x0016, 0x282a}, | ||
316 | {0x00, 0x001a, 0x282b}, | ||
317 | {0x00, 0x0020, 0x282c}, | ||
318 | {0x00, 0x002a, 0x282d}, | ||
319 | {0x00, 0x002d, 0x282e}, | ||
320 | {0x00, 0x0025, 0x282f}, | ||
321 | |||
322 | {0x00, 0x0014, 0x2830}, | ||
323 | {0x00, 0x001a, 0x2831}, | ||
324 | {0x00, 0x001f, 0x2832}, | ||
325 | {0x00, 0x0023, 0x2833}, | ||
326 | {0x00, 0x0029, 0x2834}, | ||
327 | {0x00, 0x0030, 0x2835}, | ||
328 | {0x00, 0x0030, 0x2836}, | ||
329 | {0x00, 0x0028, 0x2837}, | ||
330 | {0x00, 0x001d, 0x2838}, | ||
331 | {0x00, 0x0025, 0x2839}, | ||
332 | {0x00, 0x0026, 0x283a}, | ||
333 | {0x00, 0x0027, 0x283b}, | ||
334 | {0x00, 0x002d, 0x283c}, | ||
335 | {0x00, 0x0028, 0x283d}, | ||
336 | {0x00, 0x0029, 0x283e}, | ||
337 | {0x00, 0x0028, 0x283f}, | ||
338 | |||
339 | {0x00, 0x0007, 0x2840}, | ||
340 | {0x00, 0x0007, 0x2841}, | ||
341 | {0x00, 0x000a, 0x2842}, | ||
342 | {0x00, 0x0013, 0x2843}, | ||
343 | {0x00, 0x0028, 0x2844}, | ||
344 | {0x00, 0x0028, 0x2845}, | ||
345 | {0x00, 0x0028, 0x2846}, | ||
346 | {0x00, 0x0028, 0x2847}, | ||
347 | {0x00, 0x0007, 0x2848}, | ||
348 | {0x00, 0x0008, 0x2849}, | ||
349 | {0x00, 0x000a, 0x284a}, | ||
350 | {0x00, 0x001a, 0x284b}, | ||
351 | {0x00, 0x0028, 0x284c}, | ||
352 | {0x00, 0x0028, 0x284d}, | ||
353 | {0x00, 0x0028, 0x284e}, | ||
354 | {0x00, 0x0028, 0x284f}, | ||
355 | |||
356 | {0x00, 0x000a, 0x2850}, | ||
357 | {0x00, 0x000a, 0x2851}, | ||
358 | {0x00, 0x0016, 0x2852}, | ||
359 | {0x00, 0x0028, 0x2853}, | ||
360 | {0x00, 0x0028, 0x2854}, | ||
361 | {0x00, 0x0028, 0x2855}, | ||
362 | {0x00, 0x0028, 0x2856}, | ||
363 | {0x00, 0x0028, 0x2857}, | ||
364 | {0x00, 0x0013, 0x2858}, | ||
365 | {0x00, 0x001a, 0x2859}, | ||
366 | {0x00, 0x0028, 0x285a}, | ||
367 | {0x00, 0x0028, 0x285b}, | ||
368 | {0x00, 0x0028, 0x285c}, | ||
369 | {0x00, 0x0028, 0x285d}, | ||
370 | {0x00, 0x0028, 0x285e}, | ||
371 | {0x00, 0x0028, 0x285f}, | ||
372 | |||
373 | {0x00, 0x0028, 0x2860}, | ||
374 | {0x00, 0x0028, 0x2861}, | ||
375 | {0x00, 0x0028, 0x2862}, | ||
376 | {0x00, 0x0028, 0x2863}, | ||
377 | {0x00, 0x0028, 0x2864}, | ||
378 | {0x00, 0x0028, 0x2865}, | ||
379 | {0x00, 0x0028, 0x2866}, | ||
380 | {0x00, 0x0028, 0x2867}, | ||
381 | {0x00, 0x0028, 0x2868}, | ||
382 | {0x00, 0x0028, 0x2869}, | ||
383 | {0x00, 0x0028, 0x286a}, | ||
384 | {0x00, 0x0028, 0x286b}, | ||
385 | {0x00, 0x0028, 0x286c}, | ||
386 | {0x00, 0x0028, 0x286d}, | ||
387 | {0x00, 0x0028, 0x286e}, | ||
388 | {0x00, 0x0028, 0x286f}, | ||
389 | |||
390 | {0x00, 0x0028, 0x2870}, | ||
391 | {0x00, 0x0028, 0x2871}, | ||
392 | {0x00, 0x0028, 0x2872}, | ||
393 | {0x00, 0x0028, 0x2873}, | ||
394 | {0x00, 0x0028, 0x2874}, | ||
395 | {0x00, 0x0028, 0x2875}, | ||
396 | {0x00, 0x0028, 0x2876}, | ||
397 | {0x00, 0x0028, 0x2877}, | ||
398 | {0x00, 0x0028, 0x2878}, | ||
399 | {0x00, 0x0028, 0x2879}, | ||
400 | {0x00, 0x0028, 0x287a}, | ||
401 | {0x00, 0x0028, 0x287b}, | ||
402 | {0x00, 0x0028, 0x287c}, | ||
403 | {0x00, 0x0028, 0x287d}, | ||
404 | {0x00, 0x0028, 0x287e}, | ||
405 | {0x00, 0x0028, 0x287f}, | ||
406 | 270 | ||
407 | {0xa0, 0x0000, 0x0503}, | 271 | {0xa0, 0x0000, 0x0503}, |
408 | }; | 272 | }; |
@@ -622,6 +486,20 @@ static void spca504_acknowledged_command(struct gspca_dev *gspca_dev, | |||
622 | PDEBUG(D_FRAM, "after wait 0x%04x", notdone); | 486 | PDEBUG(D_FRAM, "after wait 0x%04x", notdone); |
623 | } | 487 | } |
624 | 488 | ||
489 | static void spca504_read_info(struct gspca_dev *gspca_dev) | ||
490 | { | ||
491 | int i; | ||
492 | u8 info[6]; | ||
493 | |||
494 | for (i = 0; i < 6; i++) | ||
495 | info[i] = reg_r_1(gspca_dev, i); | ||
496 | PDEBUG(D_STREAM, | ||
497 | "Read info: %d %d %d %d %d %d." | ||
498 | " Should be 1,0,2,2,0,0", | ||
499 | info[0], info[1], info[2], | ||
500 | info[3], info[4], info[5]); | ||
501 | } | ||
502 | |||
625 | static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev, | 503 | static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev, |
626 | u8 req, | 504 | u8 req, |
627 | u16 idx, u16 val, u16 endcode, u8 count) | 505 | u16 idx, u16 val, u16 endcode, u8 count) |
@@ -881,8 +759,6 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
881 | static int sd_init(struct gspca_dev *gspca_dev) | 759 | static int sd_init(struct gspca_dev *gspca_dev) |
882 | { | 760 | { |
883 | struct sd *sd = (struct sd *) gspca_dev; | 761 | struct sd *sd = (struct sd *) gspca_dev; |
884 | int i; | ||
885 | u8 info[6]; | ||
886 | 762 | ||
887 | switch (sd->bridge) { | 763 | switch (sd->bridge) { |
888 | case BRIDGE_SPCA504B: | 764 | case BRIDGE_SPCA504B: |
@@ -924,15 +800,8 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
924 | /* case BRIDGE_SPCA504: */ | 800 | /* case BRIDGE_SPCA504: */ |
925 | PDEBUG(D_STREAM, "Opening SPCA504"); | 801 | PDEBUG(D_STREAM, "Opening SPCA504"); |
926 | if (sd->subtype == AiptekMiniPenCam13) { | 802 | if (sd->subtype == AiptekMiniPenCam13) { |
927 | /*****************************/ | 803 | spca504_read_info(gspca_dev); |
928 | for (i = 0; i < 6; i++) | 804 | |
929 | info[i] = reg_r_1(gspca_dev, i); | ||
930 | PDEBUG(D_STREAM, | ||
931 | "Read info: %d %d %d %d %d %d." | ||
932 | " Should be 1,0,2,2,0,0", | ||
933 | info[0], info[1], info[2], | ||
934 | info[3], info[4], info[5]); | ||
935 | /* spca504a aiptek */ | ||
936 | /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */ | 805 | /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */ |
937 | spca504A_acknowledged_command(gspca_dev, 0x24, | 806 | spca504A_acknowledged_command(gspca_dev, 0x24, |
938 | 8, 3, 0x9e, 1); | 807 | 8, 3, 0x9e, 1); |
@@ -971,8 +840,6 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
971 | { | 840 | { |
972 | struct sd *sd = (struct sd *) gspca_dev; | 841 | struct sd *sd = (struct sd *) gspca_dev; |
973 | int enable; | 842 | int enable; |
974 | int i; | ||
975 | u8 info[6]; | ||
976 | 843 | ||
977 | /* create the JPEG header */ | 844 | /* create the JPEG header */ |
978 | sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); | 845 | sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); |
@@ -1008,14 +875,8 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
1008 | break; | 875 | break; |
1009 | case BRIDGE_SPCA504: | 876 | case BRIDGE_SPCA504: |
1010 | if (sd->subtype == AiptekMiniPenCam13) { | 877 | if (sd->subtype == AiptekMiniPenCam13) { |
1011 | for (i = 0; i < 6; i++) | 878 | spca504_read_info(gspca_dev); |
1012 | info[i] = reg_r_1(gspca_dev, i); | 879 | |
1013 | PDEBUG(D_STREAM, | ||
1014 | "Read info: %d %d %d %d %d %d." | ||
1015 | " Should be 1,0,2,2,0,0", | ||
1016 | info[0], info[1], info[2], | ||
1017 | info[3], info[4], info[5]); | ||
1018 | /* spca504a aiptek */ | ||
1019 | /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */ | 880 | /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */ |
1020 | spca504A_acknowledged_command(gspca_dev, 0x24, | 881 | spca504A_acknowledged_command(gspca_dev, 0x24, |
1021 | 8, 3, 0x9e, 1); | 882 | 8, 3, 0x9e, 1); |
@@ -1026,13 +887,7 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
1026 | 0, 0, 0x9d, 1); | 887 | 0, 0, 0x9d, 1); |
1027 | } else { | 888 | } else { |
1028 | spca504_acknowledged_command(gspca_dev, 0x24, 8, 3); | 889 | spca504_acknowledged_command(gspca_dev, 0x24, 8, 3); |
1029 | for (i = 0; i < 6; i++) | 890 | spca504_read_info(gspca_dev); |
1030 | info[i] = reg_r_1(gspca_dev, i); | ||
1031 | PDEBUG(D_STREAM, | ||
1032 | "Read info: %d %d %d %d %d %d." | ||
1033 | " Should be 1,0,2,2,0,0", | ||
1034 | info[0], info[1], info[2], | ||
1035 | info[3], info[4], info[5]); | ||
1036 | spca504_acknowledged_command(gspca_dev, 0x24, 8, 3); | 891 | spca504_acknowledged_command(gspca_dev, 0x24, 8, 3); |
1037 | spca504_acknowledged_command(gspca_dev, 0x24, 0, 0); | 892 | spca504_acknowledged_command(gspca_dev, 0x24, 0, 0); |
1038 | } | 893 | } |
@@ -1336,6 +1191,7 @@ static const __devinitdata struct usb_device_id device_table[] = { | |||
1336 | {USB_DEVICE(0x04fc, 0x5330), BS(SPCA533, 0)}, | 1191 | {USB_DEVICE(0x04fc, 0x5330), BS(SPCA533, 0)}, |
1337 | {USB_DEVICE(0x04fc, 0x5360), BS(SPCA536, 0)}, | 1192 | {USB_DEVICE(0x04fc, 0x5360), BS(SPCA536, 0)}, |
1338 | {USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B, 0)}, | 1193 | {USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B, 0)}, |
1194 | {USB_DEVICE(0x052b, 0x1507), BS(SPCA533, MegapixV4)}, | ||
1339 | {USB_DEVICE(0x052b, 0x1513), BS(SPCA533, MegapixV4)}, | 1195 | {USB_DEVICE(0x052b, 0x1513), BS(SPCA533, MegapixV4)}, |
1340 | {USB_DEVICE(0x052b, 0x1803), BS(SPCA533, MegaImageVI)}, | 1196 | {USB_DEVICE(0x052b, 0x1803), BS(SPCA533, MegaImageVI)}, |
1341 | {USB_DEVICE(0x0546, 0x3155), BS(SPCA533, 0)}, | 1197 | {USB_DEVICE(0x0546, 0x3155), BS(SPCA533, 0)}, |
diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c index 55ef6a744427..668a7536af90 100644 --- a/drivers/media/video/gspca/t613.c +++ b/drivers/media/video/gspca/t613.c | |||
@@ -52,6 +52,7 @@ struct sd { | |||
52 | #define SENSOR_OM6802 0 | 52 | #define SENSOR_OM6802 0 |
53 | #define SENSOR_OTHER 1 | 53 | #define SENSOR_OTHER 1 |
54 | #define SENSOR_TAS5130A 2 | 54 | #define SENSOR_TAS5130A 2 |
55 | #define SENSOR_LT168G 3 /* must verify if this is the actual model */ | ||
55 | }; | 56 | }; |
56 | 57 | ||
57 | /* V4L2 controls supported by the driver */ | 58 | /* V4L2 controls supported by the driver */ |
@@ -78,7 +79,7 @@ static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val); | |||
78 | static int sd_querymenu(struct gspca_dev *gspca_dev, | 79 | static int sd_querymenu(struct gspca_dev *gspca_dev, |
79 | struct v4l2_querymenu *menu); | 80 | struct v4l2_querymenu *menu); |
80 | 81 | ||
81 | static struct ctrl sd_ctrls[] = { | 82 | static const struct ctrl sd_ctrls[] = { |
82 | { | 83 | { |
83 | { | 84 | { |
84 | .id = V4L2_CID_BRIGHTNESS, | 85 | .id = V4L2_CID_BRIGHTNESS, |
@@ -306,6 +307,17 @@ static const u8 n4_tas5130a[] = { | |||
306 | 0xbe, 0x36, 0xbf, 0xff, 0xc2, 0x88, 0xc5, 0xc8, | 307 | 0xbe, 0x36, 0xbf, 0xff, 0xc2, 0x88, 0xc5, 0xc8, |
307 | 0xc6, 0xda | 308 | 0xc6, 0xda |
308 | }; | 309 | }; |
310 | static const u8 n4_lt168g[] = { | ||
311 | 0x66, 0x01, 0x7f, 0x00, 0x80, 0x7c, 0x81, 0x28, | ||
312 | 0x83, 0x44, 0x84, 0x20, 0x86, 0x20, 0x8a, 0x70, | ||
313 | 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xa0, 0x8e, 0xb3, | ||
314 | 0x8f, 0x24, 0xa1, 0xb0, 0xa2, 0x38, 0xa5, 0x20, | ||
315 | 0xa6, 0x4a, 0xa8, 0xe8, 0xaf, 0x38, 0xb0, 0x68, | ||
316 | 0xb1, 0x44, 0xb2, 0x88, 0xbb, 0x86, 0xbd, 0x40, | ||
317 | 0xbe, 0x26, 0xc1, 0x05, 0xc2, 0x88, 0xc5, 0xc0, | ||
318 | 0xda, 0x8e, 0xdb, 0xca, 0xdc, 0xa8, 0xdd, 0x8c, | ||
319 | 0xde, 0x44, 0xdf, 0x0c, 0xe9, 0x80 | ||
320 | }; | ||
309 | 321 | ||
310 | static const struct additional_sensor_data sensor_data[] = { | 322 | static const struct additional_sensor_data sensor_data[] = { |
311 | { /* 0: OM6802 */ | 323 | { /* 0: OM6802 */ |
@@ -380,6 +392,23 @@ static const struct additional_sensor_data sensor_data[] = { | |||
380 | .stream = | 392 | .stream = |
381 | {0x0b, 0x04, 0x0a, 0x40}, | 393 | {0x0b, 0x04, 0x0a, 0x40}, |
382 | }, | 394 | }, |
395 | { /* 3: LT168G */ | ||
396 | .n3 = {0x61, 0xc2, 0x65, 0x68, 0x60, 0x00}, | ||
397 | .n4 = n4_lt168g, | ||
398 | .n4sz = sizeof n4_lt168g, | ||
399 | .reg80 = 0x7c, | ||
400 | .reg8e = 0xb3, | ||
401 | .nset8 = {0xa8, 0xf0, 0xc6, 0xba, 0xc0, 0x00}, | ||
402 | .data1 = {0xc0, 0x38, 0x08, 0x10, 0xc0, 0x30, 0x10, 0x40, | ||
403 | 0xb0, 0xf4}, | ||
404 | .data2 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6, | ||
405 | 0xff}, | ||
406 | .data3 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6, | ||
407 | 0xff}, | ||
408 | .data4 = {0x66, 0x41, 0xa8, 0xf0}, | ||
409 | .data5 = {0x0c, 0x03, 0xab, 0x4b, 0x81, 0x2b}, | ||
410 | .stream = {0x0b, 0x04, 0x0a, 0x28}, | ||
411 | }, | ||
383 | }; | 412 | }; |
384 | 413 | ||
385 | #define MAX_EFFECTS 7 | 414 | #define MAX_EFFECTS 7 |
@@ -716,6 +745,10 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
716 | PDEBUG(D_PROBE, "sensor tas5130a"); | 745 | PDEBUG(D_PROBE, "sensor tas5130a"); |
717 | sd->sensor = SENSOR_TAS5130A; | 746 | sd->sensor = SENSOR_TAS5130A; |
718 | break; | 747 | break; |
748 | case 0x0802: | ||
749 | PDEBUG(D_PROBE, "sensor lt168g"); | ||
750 | sd->sensor = SENSOR_LT168G; | ||
751 | break; | ||
719 | case 0x0803: | 752 | case 0x0803: |
720 | PDEBUG(D_PROBE, "sensor 'other'"); | 753 | PDEBUG(D_PROBE, "sensor 'other'"); |
721 | sd->sensor = SENSOR_OTHER; | 754 | sd->sensor = SENSOR_OTHER; |
@@ -758,6 +791,13 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
758 | reg_w_buf(gspca_dev, sensor->n3, sizeof sensor->n3); | 791 | reg_w_buf(gspca_dev, sensor->n3, sizeof sensor->n3); |
759 | reg_w_buf(gspca_dev, sensor->n4, sensor->n4sz); | 792 | reg_w_buf(gspca_dev, sensor->n4, sensor->n4sz); |
760 | 793 | ||
794 | if (sd->sensor == SENSOR_LT168G) { | ||
795 | test_byte = reg_r(gspca_dev, 0x80); | ||
796 | PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80, | ||
797 | test_byte); | ||
798 | reg_w(gspca_dev, 0x6c80); | ||
799 | } | ||
800 | |||
761 | reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1); | 801 | reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1); |
762 | reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2); | 802 | reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2); |
763 | reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3); | 803 | reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3); |
@@ -782,6 +822,13 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
782 | reg_w_buf(gspca_dev, sensor->nset8, sizeof sensor->nset8); | 822 | reg_w_buf(gspca_dev, sensor->nset8, sizeof sensor->nset8); |
783 | reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream); | 823 | reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream); |
784 | 824 | ||
825 | if (sd->sensor == SENSOR_LT168G) { | ||
826 | test_byte = reg_r(gspca_dev, 0x80); | ||
827 | PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80, | ||
828 | test_byte); | ||
829 | reg_w(gspca_dev, 0x6c80); | ||
830 | } | ||
831 | |||
785 | reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1); | 832 | reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1); |
786 | reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2); | 833 | reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2); |
787 | reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3); | 834 | reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3); |
@@ -888,6 +935,8 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
888 | case SENSOR_OM6802: | 935 | case SENSOR_OM6802: |
889 | om6802_sensor_init(gspca_dev); | 936 | om6802_sensor_init(gspca_dev); |
890 | break; | 937 | break; |
938 | case SENSOR_LT168G: | ||
939 | break; | ||
891 | case SENSOR_OTHER: | 940 | case SENSOR_OTHER: |
892 | break; | 941 | break; |
893 | default: | 942 | default: |
diff --git a/drivers/media/video/gspca/tv8532.c b/drivers/media/video/gspca/tv8532.c index b74a3b6489c7..c7b6eb1e04d5 100644 --- a/drivers/media/video/gspca/tv8532.c +++ b/drivers/media/video/gspca/tv8532.c | |||
@@ -39,7 +39,7 @@ struct sd { | |||
39 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | 39 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); |
40 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | 40 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); |
41 | 41 | ||
42 | static struct ctrl sd_ctrls[] = { | 42 | static const struct ctrl sd_ctrls[] = { |
43 | { | 43 | { |
44 | { | 44 | { |
45 | .id = V4L2_CID_BRIGHTNESS, | 45 | .id = V4L2_CID_BRIGHTNESS, |
diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c index 71921c878424..4989f9afb46e 100644 --- a/drivers/media/video/gspca/vc032x.c +++ b/drivers/media/video/gspca/vc032x.c | |||
@@ -32,10 +32,13 @@ MODULE_LICENSE("GPL"); | |||
32 | struct sd { | 32 | struct sd { |
33 | struct gspca_dev gspca_dev; /* !! must be the first item */ | 33 | struct gspca_dev gspca_dev; /* !! must be the first item */ |
34 | 34 | ||
35 | u8 brightness; | ||
36 | u8 contrast; | ||
37 | u8 colors; | ||
35 | u8 hflip; | 38 | u8 hflip; |
36 | u8 vflip; | 39 | u8 vflip; |
37 | u8 lightfreq; | 40 | u8 lightfreq; |
38 | u8 sharpness; | 41 | s8 sharpness; |
39 | 42 | ||
40 | u8 image_offset; | 43 | u8 image_offset; |
41 | 44 | ||
@@ -52,6 +55,7 @@ struct sd { | |||
52 | #define SENSOR_OV7670 6 | 55 | #define SENSOR_OV7670 6 |
53 | #define SENSOR_PO1200 7 | 56 | #define SENSOR_PO1200 7 |
54 | #define SENSOR_PO3130NC 8 | 57 | #define SENSOR_PO3130NC 8 |
58 | #define SENSOR_POxxxx 9 | ||
55 | u8 flags; | 59 | u8 flags; |
56 | #define FL_SAMSUNG 0x01 /* SamsungQ1 (2 sensors) */ | 60 | #define FL_SAMSUNG 0x01 /* SamsungQ1 (2 sensors) */ |
57 | #define FL_HFLIP 0x02 /* mirrored by default */ | 61 | #define FL_HFLIP 0x02 /* mirrored by default */ |
@@ -59,6 +63,12 @@ struct sd { | |||
59 | }; | 63 | }; |
60 | 64 | ||
61 | /* V4L2 controls supported by the driver */ | 65 | /* V4L2 controls supported by the driver */ |
66 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | ||
67 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
68 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | ||
69 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | ||
70 | static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); | ||
71 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); | ||
62 | static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val); | 72 | static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val); |
63 | static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val); | 73 | static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val); |
64 | static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); | 74 | static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); |
@@ -68,9 +78,54 @@ static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); | |||
68 | static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val); | 78 | static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val); |
69 | static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); | 79 | static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); |
70 | 80 | ||
71 | static struct ctrl sd_ctrls[] = { | 81 | static const struct ctrl sd_ctrls[] = { |
82 | #define BRIGHTNESS_IDX 0 | ||
83 | { | ||
84 | { | ||
85 | .id = V4L2_CID_BRIGHTNESS, | ||
86 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
87 | .name = "Brightness", | ||
88 | .minimum = 0, | ||
89 | .maximum = 255, | ||
90 | .step = 1, | ||
91 | #define BRIGHTNESS_DEF 128 | ||
92 | .default_value = BRIGHTNESS_DEF, | ||
93 | }, | ||
94 | .set = sd_setbrightness, | ||
95 | .get = sd_getbrightness, | ||
96 | }, | ||
97 | #define CONTRAST_IDX 1 | ||
98 | { | ||
99 | { | ||
100 | .id = V4L2_CID_CONTRAST, | ||
101 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
102 | .name = "Contrast", | ||
103 | .minimum = 0, | ||
104 | .maximum = 255, | ||
105 | .step = 1, | ||
106 | #define CONTRAST_DEF 127 | ||
107 | .default_value = CONTRAST_DEF, | ||
108 | }, | ||
109 | .set = sd_setcontrast, | ||
110 | .get = sd_getcontrast, | ||
111 | }, | ||
112 | #define COLORS_IDX 2 | ||
113 | { | ||
114 | { | ||
115 | .id = V4L2_CID_SATURATION, | ||
116 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
117 | .name = "Saturation", | ||
118 | .minimum = 1, | ||
119 | .maximum = 127, | ||
120 | .step = 1, | ||
121 | #define COLOR_DEF 63 | ||
122 | .default_value = COLOR_DEF, | ||
123 | }, | ||
124 | .set = sd_setcolors, | ||
125 | .get = sd_getcolors, | ||
126 | }, | ||
72 | /* next 2 controls work with some sensors only */ | 127 | /* next 2 controls work with some sensors only */ |
73 | #define HFLIP_IDX 0 | 128 | #define HFLIP_IDX 3 |
74 | { | 129 | { |
75 | { | 130 | { |
76 | .id = V4L2_CID_HFLIP, | 131 | .id = V4L2_CID_HFLIP, |
@@ -85,7 +140,7 @@ static struct ctrl sd_ctrls[] = { | |||
85 | .set = sd_sethflip, | 140 | .set = sd_sethflip, |
86 | .get = sd_gethflip, | 141 | .get = sd_gethflip, |
87 | }, | 142 | }, |
88 | #define VFLIP_IDX 1 | 143 | #define VFLIP_IDX 4 |
89 | { | 144 | { |
90 | { | 145 | { |
91 | .id = V4L2_CID_VFLIP, | 146 | .id = V4L2_CID_VFLIP, |
@@ -100,7 +155,7 @@ static struct ctrl sd_ctrls[] = { | |||
100 | .set = sd_setvflip, | 155 | .set = sd_setvflip, |
101 | .get = sd_getvflip, | 156 | .get = sd_getvflip, |
102 | }, | 157 | }, |
103 | #define LIGHTFREQ_IDX 2 | 158 | #define LIGHTFREQ_IDX 5 |
104 | { | 159 | { |
105 | { | 160 | { |
106 | .id = V4L2_CID_POWER_LINE_FREQUENCY, | 161 | .id = V4L2_CID_POWER_LINE_FREQUENCY, |
@@ -115,17 +170,16 @@ static struct ctrl sd_ctrls[] = { | |||
115 | .set = sd_setfreq, | 170 | .set = sd_setfreq, |
116 | .get = sd_getfreq, | 171 | .get = sd_getfreq, |
117 | }, | 172 | }, |
118 | /* po1200 only */ | 173 | #define SHARPNESS_IDX 6 |
119 | #define SHARPNESS_IDX 3 | ||
120 | { | 174 | { |
121 | { | 175 | { |
122 | .id = V4L2_CID_SHARPNESS, | 176 | .id = V4L2_CID_SHARPNESS, |
123 | .type = V4L2_CTRL_TYPE_INTEGER, | 177 | .type = V4L2_CTRL_TYPE_INTEGER, |
124 | .name = "Sharpness", | 178 | .name = "Sharpness", |
125 | .minimum = 0, | 179 | .minimum = -1, |
126 | .maximum = 2, | 180 | .maximum = 2, |
127 | .step = 1, | 181 | .step = 1, |
128 | #define SHARPNESS_DEF 1 | 182 | #define SHARPNESS_DEF -1 |
129 | .default_value = SHARPNESS_DEF, | 183 | .default_value = SHARPNESS_DEF, |
130 | }, | 184 | }, |
131 | .set = sd_setsharpness, | 185 | .set = sd_setsharpness, |
@@ -133,6 +187,42 @@ static struct ctrl sd_ctrls[] = { | |||
133 | }, | 187 | }, |
134 | }; | 188 | }; |
135 | 189 | ||
190 | /* table of the disabled controls */ | ||
191 | static u32 ctrl_dis[] = { | ||
192 | /* SENSOR_HV7131R 0 */ | ||
193 | (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | ||
194 | | (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX) | ||
195 | | (1 << SHARPNESS_IDX), | ||
196 | /* SENSOR_MI0360 1 */ | ||
197 | (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | ||
198 | | (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX) | ||
199 | | (1 << SHARPNESS_IDX), | ||
200 | /* SENSOR_MI1310_SOC 2 */ | ||
201 | (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | ||
202 | | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX), | ||
203 | /* SENSOR_MI1320 3 */ | ||
204 | (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | ||
205 | | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX), | ||
206 | /* SENSOR_MI1320_SOC 4 */ | ||
207 | (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | ||
208 | | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX), | ||
209 | /* SENSOR_OV7660 5 */ | ||
210 | (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | ||
211 | | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX), | ||
212 | /* SENSOR_OV7670 6 */ | ||
213 | (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | ||
214 | | (1 << SHARPNESS_IDX), | ||
215 | /* SENSOR_PO1200 7 */ | ||
216 | (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | ||
217 | | (1 << LIGHTFREQ_IDX), | ||
218 | /* SENSOR_PO3130NC 8 */ | ||
219 | (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | ||
220 | | (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX) | ||
221 | | (1 << SHARPNESS_IDX), | ||
222 | /* SENSOR_POxxxx 9 */ | ||
223 | (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX), | ||
224 | }; | ||
225 | |||
136 | static const struct v4l2_pix_format vc0321_mode[] = { | 226 | static const struct v4l2_pix_format vc0321_mode[] = { |
137 | {320, 240, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE, | 227 | {320, 240, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE, |
138 | .bytesperline = 320, | 228 | .bytesperline = 320, |
@@ -215,7 +305,7 @@ static const u8 mi0360_initVGA_JPG[][4] = { | |||
215 | {0xb3, 0x15, 0x00, 0xcc}, | 305 | {0xb3, 0x15, 0x00, 0xcc}, |
216 | {0xb3, 0x16, 0x02, 0xcc}, | 306 | {0xb3, 0x16, 0x02, 0xcc}, |
217 | {0xb3, 0x17, 0x7f, 0xcc}, | 307 | {0xb3, 0x17, 0x7f, 0xcc}, |
218 | {0xb3, 0x35, 0xdd, 0xcc}, | 308 | {0xb3, 0x35, 0xdd, 0xcc}, /* i2c add: 5d */ |
219 | {0xb3, 0x34, 0x02, 0xcc}, | 309 | {0xb3, 0x34, 0x02, 0xcc}, |
220 | {0xb3, 0x00, 0x25, 0xcc}, | 310 | {0xb3, 0x00, 0x25, 0xcc}, |
221 | {0xbc, 0x00, 0x71, 0xcc}, | 311 | {0xbc, 0x00, 0x71, 0xcc}, |
@@ -435,7 +525,7 @@ static const u8 mi1310_socinitVGA_JPG[][4] = { | |||
435 | {0xb3, 0x08, 0x01, 0xcc}, | 525 | {0xb3, 0x08, 0x01, 0xcc}, |
436 | {0xb3, 0x09, 0x0c, 0xcc}, | 526 | {0xb3, 0x09, 0x0c, 0xcc}, |
437 | {0xb3, 0x34, 0x02, 0xcc}, | 527 | {0xb3, 0x34, 0x02, 0xcc}, |
438 | {0xb3, 0x35, 0xdd, 0xcc}, | 528 | {0xb3, 0x35, 0xdd, 0xcc}, /* i2c add: 5d */ |
439 | {0xb3, 0x02, 0x00, 0xcc}, | 529 | {0xb3, 0x02, 0x00, 0xcc}, |
440 | {0xb3, 0x03, 0x0a, 0xcc}, | 530 | {0xb3, 0x03, 0x0a, 0xcc}, |
441 | {0xb3, 0x04, 0x05, 0xcc}, | 531 | {0xb3, 0x04, 0x05, 0xcc}, |
@@ -860,7 +950,8 @@ static const u8 mi1320_initVGA_data[][4] = { | |||
860 | {0xb0, 0x16, 0x03, 0xcc}, {0xb3, 0x05, 0x00, 0xcc}, | 950 | {0xb0, 0x16, 0x03, 0xcc}, {0xb3, 0x05, 0x00, 0xcc}, |
861 | {0xb3, 0x06, 0x00, 0xcc}, {0xb3, 0x08, 0x01, 0xcc}, | 951 | {0xb3, 0x06, 0x00, 0xcc}, {0xb3, 0x08, 0x01, 0xcc}, |
862 | {0xb3, 0x09, 0x0c, 0xcc}, {0xb3, 0x34, 0x02, 0xcc}, | 952 | {0xb3, 0x09, 0x0c, 0xcc}, {0xb3, 0x34, 0x02, 0xcc}, |
863 | {0xb3, 0x35, 0xc8, 0xcc}, {0xb3, 0x02, 0x00, 0xcc}, | 953 | {0xb3, 0x35, 0xc8, 0xcc}, /* i2c add: 48 */ |
954 | {0xb3, 0x02, 0x00, 0xcc}, | ||
864 | {0xb3, 0x03, 0x0a, 0xcc}, {0xb3, 0x04, 0x05, 0xcc}, | 955 | {0xb3, 0x03, 0x0a, 0xcc}, {0xb3, 0x04, 0x05, 0xcc}, |
865 | {0xb3, 0x20, 0x00, 0xcc}, {0xb3, 0x21, 0x00, 0xcc}, | 956 | {0xb3, 0x20, 0x00, 0xcc}, {0xb3, 0x21, 0x00, 0xcc}, |
866 | {0xb3, 0x22, 0x03, 0xcc}, {0xb3, 0x23, 0xc0, 0xcc}, | 957 | {0xb3, 0x22, 0x03, 0xcc}, {0xb3, 0x23, 0xc0, 0xcc}, |
@@ -901,7 +992,8 @@ static const u8 mi1320_initVGA_data[][4] = { | |||
901 | {0xc3, 0x01, 0x03, 0xbb}, {0xc4, 0x00, 0x04, 0xbb}, | 992 | {0xc3, 0x01, 0x03, 0xbb}, {0xc4, 0x00, 0x04, 0xbb}, |
902 | {0xf0, 0x00, 0x00, 0xbb}, {0x05, 0x01, 0x13, 0xbb}, | 993 | {0xf0, 0x00, 0x00, 0xbb}, {0x05, 0x01, 0x13, 0xbb}, |
903 | {0x06, 0x00, 0x11, 0xbb}, {0x07, 0x00, 0x85, 0xbb}, | 994 | {0x06, 0x00, 0x11, 0xbb}, {0x07, 0x00, 0x85, 0xbb}, |
904 | {0x08, 0x00, 0x27, 0xbb}, {0x20, 0x01, 0x03, 0xbb}, | 995 | {0x08, 0x00, 0x27, 0xbb}, |
996 | {0x20, 0x01, 0x00, 0xbb}, /* h/v flips - was 03 */ | ||
905 | {0x21, 0x80, 0x00, 0xbb}, {0x22, 0x0d, 0x0f, 0xbb}, | 997 | {0x21, 0x80, 0x00, 0xbb}, {0x22, 0x0d, 0x0f, 0xbb}, |
906 | {0x24, 0x80, 0x00, 0xbb}, {0x59, 0x00, 0xff, 0xbb}, | 998 | {0x24, 0x80, 0x00, 0xbb}, {0x59, 0x00, 0xff, 0xbb}, |
907 | {0xf0, 0x00, 0x02, 0xbb}, {0x39, 0x03, 0x0d, 0xbb}, | 999 | {0xf0, 0x00, 0x02, 0xbb}, {0x39, 0x03, 0x0d, 0xbb}, |
@@ -1012,7 +1104,7 @@ static const u8 mi1320_soc_InitVGA[][4] = { | |||
1012 | {0xb3, 0x08, 0x01, 0xcc}, | 1104 | {0xb3, 0x08, 0x01, 0xcc}, |
1013 | {0xb3, 0x09, 0x0c, 0xcc}, | 1105 | {0xb3, 0x09, 0x0c, 0xcc}, |
1014 | {0xb3, 0x34, 0x02, 0xcc}, | 1106 | {0xb3, 0x34, 0x02, 0xcc}, |
1015 | {0xb3, 0x35, 0xc8, 0xcc}, | 1107 | {0xb3, 0x35, 0xc8, 0xcc}, /* i2c add: 48 */ |
1016 | {0xb3, 0x02, 0x00, 0xcc}, | 1108 | {0xb3, 0x02, 0x00, 0xcc}, |
1017 | {0xb3, 0x03, 0x0a, 0xcc}, | 1109 | {0xb3, 0x03, 0x0a, 0xcc}, |
1018 | {0xb3, 0x04, 0x05, 0xcc}, | 1110 | {0xb3, 0x04, 0x05, 0xcc}, |
@@ -1359,7 +1451,8 @@ static const u8 po3130_initVGA_data[][4] = { | |||
1359 | {0xb3, 0x23, 0xe8, 0xcc}, {0xb8, 0x08, 0xe8, 0xcc}, | 1451 | {0xb3, 0x23, 0xe8, 0xcc}, {0xb8, 0x08, 0xe8, 0xcc}, |
1360 | {0xb3, 0x14, 0x00, 0xcc}, {0xb3, 0x15, 0x00, 0xcc}, | 1452 | {0xb3, 0x14, 0x00, 0xcc}, {0xb3, 0x15, 0x00, 0xcc}, |
1361 | {0xb3, 0x16, 0x02, 0xcc}, {0xb3, 0x17, 0x7f, 0xcc}, | 1453 | {0xb3, 0x16, 0x02, 0xcc}, {0xb3, 0x17, 0x7f, 0xcc}, |
1362 | {0xb3, 0x34, 0x01, 0xcc}, {0xb3, 0x35, 0xf6, 0xcc}, | 1454 | {0xb3, 0x34, 0x01, 0xcc}, |
1455 | {0xb3, 0x35, 0xf6, 0xcc}, /* i2c add: 76 */ | ||
1363 | {0xb3, 0x00, 0x27, 0xcc}, {0xbc, 0x00, 0x71, 0xcc}, | 1456 | {0xb3, 0x00, 0x27, 0xcc}, {0xbc, 0x00, 0x71, 0xcc}, |
1364 | {0xb8, 0x00, 0x21, 0xcc}, {0xb8, 0x27, 0x20, 0xcc}, | 1457 | {0xb8, 0x00, 0x21, 0xcc}, {0xb8, 0x27, 0x20, 0xcc}, |
1365 | {0xb8, 0x01, 0x79, 0xcc}, {0xb8, 0x81, 0x09, 0xcc}, | 1458 | {0xb8, 0x01, 0x79, 0xcc}, {0xb8, 0x81, 0x09, 0xcc}, |
@@ -1561,7 +1654,7 @@ static const u8 hv7131r_initVGA_data[][4] = { | |||
1561 | {0xb3, 0x16, 0x02, 0xcc}, | 1654 | {0xb3, 0x16, 0x02, 0xcc}, |
1562 | {0xb3, 0x17, 0x7f, 0xcc}, | 1655 | {0xb3, 0x17, 0x7f, 0xcc}, |
1563 | {0xb3, 0x34, 0x01, 0xcc}, | 1656 | {0xb3, 0x34, 0x01, 0xcc}, |
1564 | {0xb3, 0x35, 0x91, 0xcc}, | 1657 | {0xb3, 0x35, 0x91, 0xcc}, /* i2c add: 11 */ |
1565 | {0xb3, 0x00, 0x27, 0xcc}, | 1658 | {0xb3, 0x00, 0x27, 0xcc}, |
1566 | {0xbc, 0x00, 0x73, 0xcc}, | 1659 | {0xbc, 0x00, 0x73, 0xcc}, |
1567 | {0xb8, 0x00, 0x23, 0xcc}, | 1660 | {0xb8, 0x00, 0x23, 0xcc}, |
@@ -1747,7 +1840,8 @@ static const u8 ov7660_initVGA_data[][4] = { | |||
1747 | {0xb3, 0x23, 0xe0, 0xcc}, {0xb3, 0x1d, 0x01, 0xcc}, | 1840 | {0xb3, 0x23, 0xe0, 0xcc}, {0xb3, 0x1d, 0x01, 0xcc}, |
1748 | {0xb3, 0x1f, 0x02, 0xcc}, | 1841 | {0xb3, 0x1f, 0x02, 0xcc}, |
1749 | {0xb3, 0x34, 0x01, 0xcc}, | 1842 | {0xb3, 0x34, 0x01, 0xcc}, |
1750 | {0xb3, 0x35, 0xa1, 0xcc}, {0xb3, 0x00, 0x26, 0xcc}, | 1843 | {0xb3, 0x35, 0xa1, 0xcc}, /* i2c add: 21 */ |
1844 | {0xb3, 0x00, 0x26, 0xcc}, | ||
1751 | {0xb8, 0x00, 0x33, 0xcc}, /* 13 */ | 1845 | {0xb8, 0x00, 0x33, 0xcc}, /* 13 */ |
1752 | {0xb8, 0x01, 0x7d, 0xcc}, | 1846 | {0xb8, 0x01, 0x7d, 0xcc}, |
1753 | {0xbc, 0x00, 0x73, 0xcc}, {0xb8, 0x81, 0x09, 0xcc}, | 1847 | {0xbc, 0x00, 0x73, 0xcc}, {0xb8, 0x81, 0x09, 0xcc}, |
@@ -1883,7 +1977,8 @@ static const u8 ov7670_initVGA_JPG[][4] = { | |||
1883 | {0x00, 0x00, 0x10, 0xdd}, | 1977 | {0x00, 0x00, 0x10, 0xdd}, |
1884 | {0xb0, 0x04, 0x02, 0xcc}, {0x00, 0x00, 0x10, 0xdd}, | 1978 | {0xb0, 0x04, 0x02, 0xcc}, {0x00, 0x00, 0x10, 0xdd}, |
1885 | {0xb3, 0x00, 0x66, 0xcc}, {0xb3, 0x00, 0x67, 0xcc}, | 1979 | {0xb3, 0x00, 0x66, 0xcc}, {0xb3, 0x00, 0x67, 0xcc}, |
1886 | {0xb3, 0x35, 0xa1, 0xcc}, {0xb3, 0x34, 0x01, 0xcc}, | 1980 | {0xb3, 0x35, 0xa1, 0xcc}, /* i2c add: 21 */ |
1981 | {0xb3, 0x34, 0x01, 0xcc}, | ||
1887 | {0xb3, 0x05, 0x01, 0xcc}, {0xb3, 0x06, 0x01, 0xcc}, | 1982 | {0xb3, 0x05, 0x01, 0xcc}, {0xb3, 0x06, 0x01, 0xcc}, |
1888 | {0xb3, 0x08, 0x01, 0xcc}, {0xb3, 0x09, 0x0c, 0xcc}, | 1983 | {0xb3, 0x08, 0x01, 0xcc}, {0xb3, 0x09, 0x0c, 0xcc}, |
1889 | {0xb3, 0x02, 0x02, 0xcc}, {0xb3, 0x03, 0x1f, 0xcc}, | 1984 | {0xb3, 0x02, 0x02, 0xcc}, {0xb3, 0x03, 0x1f, 0xcc}, |
@@ -2181,7 +2276,7 @@ static const u8 po1200_initVGA_data[][4] = { | |||
2181 | {0xb0, 0x54, 0x13, 0xcc}, | 2276 | {0xb0, 0x54, 0x13, 0xcc}, |
2182 | {0xb3, 0x00, 0x67, 0xcc}, | 2277 | {0xb3, 0x00, 0x67, 0xcc}, |
2183 | {0xb3, 0x34, 0x01, 0xcc}, | 2278 | {0xb3, 0x34, 0x01, 0xcc}, |
2184 | {0xb3, 0x35, 0xdc, 0xcc}, | 2279 | {0xb3, 0x35, 0xdc, 0xcc}, /* i2c add: 5c */ |
2185 | {0x00, 0x03, 0x00, 0xaa}, | 2280 | {0x00, 0x03, 0x00, 0xaa}, |
2186 | {0x00, 0x12, 0x05, 0xaa}, | 2281 | {0x00, 0x12, 0x05, 0xaa}, |
2187 | {0x00, 0x13, 0x02, 0xaa}, | 2282 | {0x00, 0x13, 0x02, 0xaa}, |
@@ -2408,6 +2503,251 @@ static const u8 po1200_initVGA_data[][4] = { | |||
2408 | {0x00, 0xb6, 0x39, 0xaa}, | 2503 | {0x00, 0xb6, 0x39, 0xaa}, |
2409 | {0x00, 0xb7, 0x24, 0xaa}, | 2504 | {0x00, 0xb7, 0x24, 0xaa}, |
2410 | /*write 89 0400 1415*/ | 2505 | /*write 89 0400 1415*/ |
2506 | {} | ||
2507 | }; | ||
2508 | |||
2509 | static const u8 poxxxx_init_common[][4] = { | ||
2510 | {0xb3, 0x00, 0x04, 0xcc}, | ||
2511 | {0x00, 0x00, 0x10, 0xdd}, | ||
2512 | {0xb3, 0x00, 0x64, 0xcc}, | ||
2513 | {0x00, 0x00, 0x10, 0xdd}, | ||
2514 | {0xb3, 0x00, 0x65, 0xcc}, | ||
2515 | {0x00, 0x00, 0x10, 0xdd}, | ||
2516 | {0xb3, 0x00, 0x67, 0xcc}, | ||
2517 | {0xb0, 0x03, 0x09, 0xcc}, | ||
2518 | {0xb3, 0x05, 0x00, 0xcc}, | ||
2519 | {0xb3, 0x06, 0x00, 0xcc}, | ||
2520 | {0xb3, 0x5c, 0x01, 0xcc}, | ||
2521 | {0xb3, 0x08, 0x01, 0xcc}, | ||
2522 | {0xb3, 0x09, 0x0c, 0xcc}, | ||
2523 | {0xb3, 0x34, 0x01, 0xcc}, | ||
2524 | {0xb3, 0x35, 0xf6, 0xcc}, /* i2c add: 76 */ | ||
2525 | {0xb3, 0x02, 0xb0, 0xcc}, | ||
2526 | {0xb3, 0x03, 0x18, 0xcc}, | ||
2527 | {0xb3, 0x04, 0x15, 0xcc}, | ||
2528 | {0xb3, 0x20, 0x00, 0xcc}, | ||
2529 | {0xb3, 0x21, 0x00, 0xcc}, | ||
2530 | {0xb3, 0x22, 0x04, 0xcc}, | ||
2531 | {0xb3, 0x23, 0x00, 0xcc}, | ||
2532 | {0xb3, 0x14, 0x00, 0xcc}, | ||
2533 | {0xb3, 0x15, 0x00, 0xcc}, | ||
2534 | {0xb3, 0x16, 0x04, 0xcc}, | ||
2535 | {0xb3, 0x17, 0xff, 0xcc}, | ||
2536 | {0xb3, 0x2c, 0x03, 0xcc}, | ||
2537 | {0xb3, 0x2d, 0x56, 0xcc}, | ||
2538 | {0xb3, 0x2e, 0x02, 0xcc}, | ||
2539 | {0xb3, 0x2f, 0x0a, 0xcc}, | ||
2540 | {0xb3, 0x40, 0x00, 0xcc}, | ||
2541 | {0xb3, 0x41, 0x34, 0xcc}, | ||
2542 | {0xb3, 0x42, 0x01, 0xcc}, | ||
2543 | {0xb3, 0x43, 0xe0, 0xcc}, | ||
2544 | {0xbc, 0x00, 0x71, 0xcc}, | ||
2545 | {0xbc, 0x01, 0x01, 0xcc}, | ||
2546 | {0xb3, 0x01, 0x41, 0xcc}, | ||
2547 | {0xb3, 0x4d, 0x00, 0xcc}, | ||
2548 | {0x00, 0x0b, 0x2a, 0xaa}, | ||
2549 | {0x00, 0x0e, 0x03, 0xaa}, | ||
2550 | {0x00, 0x0f, 0xea, 0xaa}, | ||
2551 | {0x00, 0x12, 0x08, 0xaa}, | ||
2552 | {0x00, 0x1e, 0x06, 0xaa}, | ||
2553 | {0x00, 0x21, 0x00, 0xaa}, | ||
2554 | {0x00, 0x31, 0x1f, 0xaa}, | ||
2555 | {0x00, 0x33, 0x38, 0xaa}, | ||
2556 | {0x00, 0x36, 0xc0, 0xaa}, | ||
2557 | {0x00, 0x37, 0xc8, 0xaa}, | ||
2558 | {0x00, 0x3b, 0x36, 0xaa}, | ||
2559 | {0x00, 0x4b, 0xfe, 0xaa}, | ||
2560 | {0x00, 0x4d, 0x2e, 0xaa}, | ||
2561 | {0x00, 0x51, 0x1c, 0xaa}, | ||
2562 | {0x00, 0x52, 0x01, 0xaa}, | ||
2563 | {0x00, 0x55, 0x0a, 0xaa}, | ||
2564 | {0x00, 0x56, 0x0a, 0xaa}, | ||
2565 | {0x00, 0x57, 0x07, 0xaa}, | ||
2566 | {0x00, 0x58, 0x07, 0xaa}, | ||
2567 | {0x00, 0x59, 0x04, 0xaa}, | ||
2568 | {0x00, 0x70, 0x68, 0xaa}, | ||
2569 | {0x00, 0x71, 0x04, 0xaa}, | ||
2570 | {0x00, 0x72, 0x10, 0xaa}, | ||
2571 | {0x00, 0x80, 0x71, 0xaa}, | ||
2572 | {0x00, 0x81, 0x08, 0xaa}, | ||
2573 | {0x00, 0x82, 0x00, 0xaa}, | ||
2574 | {0x00, 0x83, 0x55, 0xaa}, | ||
2575 | {0x00, 0x84, 0x06, 0xaa}, | ||
2576 | {0x00, 0x85, 0x06, 0xaa}, | ||
2577 | {0x00, 0x8b, 0x25, 0xaa}, | ||
2578 | {0x00, 0x8c, 0x00, 0xaa}, | ||
2579 | {0x00, 0x8d, 0x86, 0xaa}, | ||
2580 | {0x00, 0x8e, 0x82, 0xaa}, | ||
2581 | {0x00, 0x8f, 0x2d, 0xaa}, | ||
2582 | {0x00, 0x90, 0x8b, 0xaa}, | ||
2583 | {0x00, 0x91, 0x81, 0xaa}, | ||
2584 | {0x00, 0x92, 0x81, 0xaa}, | ||
2585 | {0x00, 0x93, 0x23, 0xaa}, | ||
2586 | {0x00, 0xa3, 0x2a, 0xaa}, | ||
2587 | {0x00, 0xa4, 0x03, 0xaa}, | ||
2588 | {0x00, 0xa5, 0xea, 0xaa}, | ||
2589 | {0x00, 0xb0, 0x68, 0xaa}, | ||
2590 | {0x00, 0xbc, 0x04, 0xaa}, | ||
2591 | {0x00, 0xbe, 0x3b, 0xaa}, | ||
2592 | {0x00, 0x4e, 0x40, 0xaa}, | ||
2593 | {0x00, 0x06, 0x04, 0xaa}, | ||
2594 | {0x00, 0x07, 0x03, 0xaa}, | ||
2595 | {0x00, 0xcd, 0x18, 0xaa}, | ||
2596 | {0x00, 0x28, 0x03, 0xaa}, | ||
2597 | {0x00, 0x29, 0xef, 0xaa}, | ||
2598 | /* reinit on alt 2 (qvga) or alt7 (vga) */ | ||
2599 | {0xb3, 0x05, 0x00, 0xcc}, | ||
2600 | {0xb3, 0x06, 0x00, 0xcc}, | ||
2601 | {0xb8, 0x00, 0x01, 0xcc}, | ||
2602 | |||
2603 | {0x00, 0x1d, 0x85, 0xaa}, | ||
2604 | {0x00, 0x1e, 0xc6, 0xaa}, | ||
2605 | {0x00, 0x00, 0x40, 0xdd}, | ||
2606 | {0x00, 0x1d, 0x05, 0xaa}, | ||
2607 | |||
2608 | {0x00, 0xd6, 0x22, 0xaa}, /* gamma 0 */ | ||
2609 | {0x00, 0x73, 0x00, 0xaa}, | ||
2610 | {0x00, 0x74, 0x0a, 0xaa}, | ||
2611 | {0x00, 0x75, 0x16, 0xaa}, | ||
2612 | {0x00, 0x76, 0x25, 0xaa}, | ||
2613 | {0x00, 0x77, 0x34, 0xaa}, | ||
2614 | {0x00, 0x78, 0x49, 0xaa}, | ||
2615 | {0x00, 0x79, 0x5a, 0xaa}, | ||
2616 | {0x00, 0x7a, 0x7f, 0xaa}, | ||
2617 | {0x00, 0x7b, 0x9b, 0xaa}, | ||
2618 | {0x00, 0x7c, 0xba, 0xaa}, | ||
2619 | {0x00, 0x7d, 0xd4, 0xaa}, | ||
2620 | {0x00, 0x7e, 0xea, 0xaa}, | ||
2621 | |||
2622 | {0x00, 0xd6, 0x62, 0xaa}, /* gamma 1 */ | ||
2623 | {0x00, 0x73, 0x00, 0xaa}, | ||
2624 | {0x00, 0x74, 0x0a, 0xaa}, | ||
2625 | {0x00, 0x75, 0x16, 0xaa}, | ||
2626 | {0x00, 0x76, 0x25, 0xaa}, | ||
2627 | {0x00, 0x77, 0x34, 0xaa}, | ||
2628 | {0x00, 0x78, 0x49, 0xaa}, | ||
2629 | {0x00, 0x79, 0x5a, 0xaa}, | ||
2630 | {0x00, 0x7a, 0x7f, 0xaa}, | ||
2631 | {0x00, 0x7b, 0x9b, 0xaa}, | ||
2632 | {0x00, 0x7c, 0xba, 0xaa}, | ||
2633 | {0x00, 0x7d, 0xd4, 0xaa}, | ||
2634 | {0x00, 0x7e, 0xea, 0xaa}, | ||
2635 | |||
2636 | {0x00, 0xd6, 0xa2, 0xaa}, /* gamma 2 */ | ||
2637 | {0x00, 0x73, 0x00, 0xaa}, | ||
2638 | {0x00, 0x74, 0x0a, 0xaa}, | ||
2639 | {0x00, 0x75, 0x16, 0xaa}, | ||
2640 | {0x00, 0x76, 0x25, 0xaa}, | ||
2641 | {0x00, 0x77, 0x34, 0xaa}, | ||
2642 | {0x00, 0x78, 0x49, 0xaa}, | ||
2643 | {0x00, 0x79, 0x5a, 0xaa}, | ||
2644 | {0x00, 0x7a, 0x7f, 0xaa}, | ||
2645 | {0x00, 0x7b, 0x9b, 0xaa}, | ||
2646 | {0x00, 0x7c, 0xba, 0xaa}, | ||
2647 | {0x00, 0x7d, 0xd4, 0xaa}, | ||
2648 | {0x00, 0x7e, 0xea, 0xaa}, | ||
2649 | |||
2650 | {0x00, 0xaa, 0xff, 0xaa}, /* back light comp */ | ||
2651 | {0x00, 0xc4, 0x03, 0xaa}, | ||
2652 | {0x00, 0xc5, 0x19, 0xaa}, | ||
2653 | {0x00, 0xc6, 0x03, 0xaa}, | ||
2654 | {0x00, 0xc7, 0x91, 0xaa}, | ||
2655 | {0x00, 0xc8, 0x01, 0xaa}, | ||
2656 | {0x00, 0xc9, 0xdd, 0xaa}, | ||
2657 | {0x00, 0xca, 0x02, 0xaa}, | ||
2658 | {0x00, 0xcb, 0x37, 0xaa}, | ||
2659 | |||
2660 | /* read d1 */ | ||
2661 | {0x00, 0xd1, 0x3c, 0xaa}, | ||
2662 | {0x00, 0xb8, 0x28, 0xaa}, | ||
2663 | {0x00, 0xb9, 0x1e, 0xaa}, | ||
2664 | {0x00, 0xb6, 0x14, 0xaa}, | ||
2665 | {0x00, 0xb7, 0x0f, 0xaa}, | ||
2666 | {0x00, 0x5c, 0x10, 0xaa}, | ||
2667 | {0x00, 0x5d, 0x18, 0xaa}, | ||
2668 | {0x00, 0x5e, 0x24, 0xaa}, | ||
2669 | {0x00, 0x5f, 0x24, 0xaa}, | ||
2670 | {0x00, 0x86, 0x1a, 0xaa}, | ||
2671 | {0x00, 0x60, 0x00, 0xaa}, | ||
2672 | {0x00, 0x61, 0x1b, 0xaa}, | ||
2673 | {0x00, 0x62, 0x30, 0xaa}, | ||
2674 | {0x00, 0x63, 0x40, 0xaa}, | ||
2675 | {0x00, 0x87, 0x1a, 0xaa}, | ||
2676 | {0x00, 0x64, 0x00, 0xaa}, | ||
2677 | {0x00, 0x65, 0x08, 0xaa}, | ||
2678 | {0x00, 0x66, 0x10, 0xaa}, | ||
2679 | {0x00, 0x67, 0x20, 0xaa}, | ||
2680 | {0x00, 0x88, 0x10, 0xaa}, | ||
2681 | {0x00, 0x68, 0x00, 0xaa}, | ||
2682 | {0x00, 0x69, 0x08, 0xaa}, | ||
2683 | {0x00, 0x6a, 0x0f, 0xaa}, | ||
2684 | {0x00, 0x6b, 0x0f, 0xaa}, | ||
2685 | {0x00, 0x89, 0x07, 0xaa}, | ||
2686 | {0x00, 0xd5, 0x4c, 0xaa}, | ||
2687 | {0x00, 0x0a, 0x00, 0xaa}, | ||
2688 | {0x00, 0x0b, 0x2a, 0xaa}, | ||
2689 | {0x00, 0x0e, 0x03, 0xaa}, | ||
2690 | {0x00, 0x0f, 0xea, 0xaa}, | ||
2691 | {0x00, 0xa2, 0x00, 0xaa}, | ||
2692 | {0x00, 0xa3, 0x2a, 0xaa}, | ||
2693 | {0x00, 0xa4, 0x03, 0xaa}, | ||
2694 | {0x00, 0xa5, 0xea, 0xaa}, | ||
2695 | {} | ||
2696 | }; | ||
2697 | static const u8 poxxxx_initVGA[][4] = { | ||
2698 | {0x00, 0x20, 0x11, 0xaa}, | ||
2699 | {0x00, 0x33, 0x38, 0xaa}, | ||
2700 | {0x00, 0xbb, 0x0d, 0xaa}, | ||
2701 | {0xb3, 0x22, 0x01, 0xcc}, | ||
2702 | {0xb3, 0x23, 0xe0, 0xcc}, | ||
2703 | {0xb3, 0x16, 0x02, 0xcc}, | ||
2704 | {0xb3, 0x17, 0x7f, 0xcc}, | ||
2705 | {0xb3, 0x02, 0xb0, 0xcc}, | ||
2706 | {0xb3, 0x06, 0x00, 0xcc}, | ||
2707 | {0xb3, 0x5c, 0x01, 0xcc}, | ||
2708 | {0x00, 0x04, 0x06, 0xaa}, | ||
2709 | {0x00, 0x05, 0x3f, 0xaa}, | ||
2710 | {0x00, 0x04, 0x00, 0xdd}, /* delay 1s */ | ||
2711 | {} | ||
2712 | }; | ||
2713 | static const u8 poxxxx_initQVGA[][4] = { | ||
2714 | {0x00, 0x20, 0x33, 0xaa}, | ||
2715 | {0x00, 0x33, 0x38, 0xaa}, | ||
2716 | {0x00, 0xbb, 0x0d, 0xaa}, | ||
2717 | {0xb3, 0x22, 0x00, 0xcc}, | ||
2718 | {0xb3, 0x23, 0xf0, 0xcc}, | ||
2719 | {0xb3, 0x16, 0x01, 0xcc}, | ||
2720 | {0xb3, 0x17, 0x3f, 0xcc}, | ||
2721 | {0xb3, 0x02, 0xb0, 0xcc}, | ||
2722 | {0xb3, 0x06, 0x01, 0xcc}, | ||
2723 | {0xb3, 0x5c, 0x00, 0xcc}, | ||
2724 | {0x00, 0x04, 0x06, 0xaa}, | ||
2725 | {0x00, 0x05, 0x3f, 0xaa}, | ||
2726 | {0x00, 0x04, 0x00, 0xdd}, /* delay 1s */ | ||
2727 | {} | ||
2728 | }; | ||
2729 | static const u8 poxxxx_init_end_1[][4] = { | ||
2730 | {0x00, 0x47, 0x25, 0xaa}, | ||
2731 | {0x00, 0x48, 0x80, 0xaa}, | ||
2732 | {0x00, 0x49, 0x1f, 0xaa}, | ||
2733 | {0x00, 0x4a, 0x40, 0xaa}, | ||
2734 | {0x00, 0x44, 0x40, 0xaa}, | ||
2735 | {0x00, 0xab, 0x4a, 0xaa}, | ||
2736 | {0x00, 0xb1, 0x00, 0xaa}, | ||
2737 | {0x00, 0xb2, 0x04, 0xaa}, | ||
2738 | {0x00, 0xb3, 0x08, 0xaa}, | ||
2739 | {0x00, 0xb4, 0x0b, 0xaa}, | ||
2740 | {0x00, 0xb5, 0x0d, 0xaa}, | ||
2741 | {0x00, 0x59, 0x7e, 0xaa}, /* sharpness */ | ||
2742 | {0x00, 0x16, 0x00, 0xaa}, /* white balance */ | ||
2743 | {0x00, 0x18, 0x00, 0xaa}, | ||
2744 | {} | ||
2745 | }; | ||
2746 | static const u8 poxxxx_init_end_2[][4] = { | ||
2747 | {0x00, 0x1d, 0x85, 0xaa}, | ||
2748 | {0x00, 0x1e, 0x06, 0xaa}, | ||
2749 | {0x00, 0x1d, 0x05, 0xaa}, | ||
2750 | {} | ||
2411 | }; | 2751 | }; |
2412 | 2752 | ||
2413 | struct sensor_info { | 2753 | struct sensor_info { |
@@ -2420,33 +2760,89 @@ struct sensor_info { | |||
2420 | u8 op; | 2760 | u8 op; |
2421 | }; | 2761 | }; |
2422 | 2762 | ||
2423 | static const struct sensor_info sensor_info_data[] = { | 2763 | /* probe values */ |
2424 | /* sensorId, I2cAdd, IdAdd, VpId, m1, m2, op */ | 2764 | static const struct sensor_info vc0321_probe_data[] = { |
2765 | /* sensorId, I2cAdd, IdAdd, VpId, m1, m2, op */ | ||
2766 | /* 0 OV9640 */ | ||
2425 | {-1, 0x80 | 0x30, 0x0a, 0x0000, 0x25, 0x24, 0x05}, | 2767 | {-1, 0x80 | 0x30, 0x0a, 0x0000, 0x25, 0x24, 0x05}, |
2768 | /* 1 ICM108T (may respond on IdAdd == 0x83 - tested in vc032x_probe_sensor) */ | ||
2426 | {-1, 0x80 | 0x20, 0x82, 0x0000, 0x24, 0x25, 0x01}, | 2769 | {-1, 0x80 | 0x20, 0x82, 0x0000, 0x24, 0x25, 0x01}, |
2427 | /* (tested in vc032x_probe_sensor) */ | 2770 | /* 2 PO2130 (may detect PO3130NC - tested in vc032x_probe_sensor)*/ |
2428 | /* {-1, 0x80 | 0x20, 0x83, 0x0000, 0x24, 0x25, 0x01}, */ | 2771 | {-1, 0x80 | 0x76, 0x00, 0x0000, 0x24, 0x25, 0x01}, |
2429 | {SENSOR_PO3130NC, 0x80 | 0x76, 0x00, 0x3130, 0x24, 0x25, 0x01}, | 2772 | /* 3 MI1310 */ |
2773 | {-1, 0x80 | 0x5d, 0x00, 0x0000, 0x24, 0x25, 0x01}, | ||
2774 | /* 4 MI360 - tested in vc032x_probe_sensor */ | ||
2775 | /* {SENSOR_MI0360, 0x80 | 0x5d, 0x00, 0x8243, 0x24, 0x25, 0x01}, */ | ||
2776 | /* 5 7131R */ | ||
2777 | {SENSOR_HV7131R, 0x80 | 0x11, 0x00, 0x0209, 0x24, 0x25, 0x01}, | ||
2778 | /* 6 OV7649 */ | ||
2779 | {-1, 0x80 | 0x21, 0x0a, 0x0000, 0x21, 0x20, 0x05}, | ||
2780 | /* 7 PAS302BCW */ | ||
2781 | {-1, 0x80 | 0x40, 0x00, 0x0000, 0x20, 0x22, 0x05}, | ||
2782 | /* 8 OV7660 */ | ||
2783 | {SENSOR_OV7660, 0x80 | 0x21, 0x0a, 0x7660, 0x26, 0x26, 0x05}, | ||
2784 | /* 9 PO3130NC - (tested in vc032x_probe_sensor) */ | ||
2785 | /* {SENSOR_PO3130NC, 0x80 | 0x76, 0x00, 0x3130, 0x24, 0x25, 0x01}, */ | ||
2786 | /* 10 PO1030KC */ | ||
2787 | {-1, 0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01}, | ||
2788 | /* 11 MI1310_SOC */ | ||
2430 | {SENSOR_MI1310_SOC, 0x80 | 0x5d, 0x00, 0x143a, 0x24, 0x25, 0x01}, | 2789 | {SENSOR_MI1310_SOC, 0x80 | 0x5d, 0x00, 0x143a, 0x24, 0x25, 0x01}, |
2431 | /* (tested in vc032x_probe_sensor) */ | 2790 | /* 12 OV9650 */ |
2791 | {-1, 0x80 | 0x30, 0x0a, 0x0000, 0x25, 0x24, 0x05}, | ||
2792 | /* 13 S5K532 */ | ||
2793 | {-1, 0x80 | 0x11, 0x39, 0x0000, 0x24, 0x25, 0x01}, | ||
2794 | /* 14 MI360_SOC - ??? */ | ||
2795 | /* 15 PO1200N */ | ||
2796 | {SENSOR_PO1200, 0x80 | 0x5c, 0x00, 0x1200, 0x67, 0x67, 0x01}, | ||
2797 | /* 16 PO3030K */ | ||
2798 | {-1, 0x80 | 0x18, 0x00, 0x0000, 0x24, 0x25, 0x01}, | ||
2799 | /* 17 PO2030 */ | ||
2800 | {-1, 0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01}, | ||
2801 | /* ?? */ | ||
2802 | {-1, 0x80 | 0x56, 0x01, 0x0000, 0x64, 0x67, 0x01}, | ||
2803 | {SENSOR_MI1320, 0x80 | 0x48, 0x00, 0x148c, 0x64, 0x65, 0x01}, | ||
2804 | }; | ||
2805 | static const struct sensor_info vc0323_probe_data[] = { | ||
2806 | /* sensorId, I2cAdd, IdAdd, VpId, m1, m2, op */ | ||
2807 | /* 0 OV9640 */ | ||
2808 | {-1, 0x80 | 0x30, 0x0a, 0x0000, 0x25, 0x24, 0x05}, | ||
2809 | /* 1 ICM108T (may respond on IdAdd == 0x83 - tested in vc032x_probe_sensor) */ | ||
2810 | {-1, 0x80 | 0x20, 0x82, 0x0000, 0x24, 0x25, 0x01}, | ||
2811 | /* 2 PO2130 (may detect PO3130NC - tested in vc032x_probe_sensor)*/ | ||
2812 | {-1, 0x80 | 0x76, 0x00, 0x0000, 0x24, 0x25, 0x01}, | ||
2813 | /* 3 MI1310 */ | ||
2814 | {-1, 0x80 | 0x5d, 0x00, 0x0000, 0x24, 0x25, 0x01}, | ||
2815 | /* 4 MI360 - tested in vc032x_probe_sensor */ | ||
2432 | /* {SENSOR_MI0360, 0x80 | 0x5d, 0x00, 0x8243, 0x24, 0x25, 0x01}, */ | 2816 | /* {SENSOR_MI0360, 0x80 | 0x5d, 0x00, 0x8243, 0x24, 0x25, 0x01}, */ |
2817 | /* 5 7131R */ | ||
2433 | {SENSOR_HV7131R, 0x80 | 0x11, 0x00, 0x0209, 0x24, 0x25, 0x01}, | 2818 | {SENSOR_HV7131R, 0x80 | 0x11, 0x00, 0x0209, 0x24, 0x25, 0x01}, |
2819 | /* 6 OV7649 */ | ||
2434 | {-1, 0x80 | 0x21, 0x0a, 0x0000, 0x21, 0x20, 0x05}, | 2820 | {-1, 0x80 | 0x21, 0x0a, 0x0000, 0x21, 0x20, 0x05}, |
2821 | /* 7 PAS302BCW */ | ||
2435 | {-1, 0x80 | 0x40, 0x00, 0x0000, 0x20, 0x22, 0x05}, | 2822 | {-1, 0x80 | 0x40, 0x00, 0x0000, 0x20, 0x22, 0x05}, |
2823 | /* 8 OV7660 */ | ||
2436 | {SENSOR_OV7660, 0x80 | 0x21, 0x0a, 0x7660, 0x26, 0x26, 0x05}, | 2824 | {SENSOR_OV7660, 0x80 | 0x21, 0x0a, 0x7660, 0x26, 0x26, 0x05}, |
2437 | /* {SENSOR_PO3130NC, 0x80 | 0x76, 0x00, 0x0000, 0x24, 0x25, 0x01}, */ | 2825 | /* 9 PO3130NC - (tested in vc032x_probe_sensor) */ |
2826 | /* {SENSOR_PO3130NC, 0x80 | 0x76, 0x00, 0x3130, 0x24, 0x25, 0x01}, */ | ||
2827 | /* 10 PO1030KC */ | ||
2438 | {-1, 0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01}, | 2828 | {-1, 0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01}, |
2439 | /* {SENSOR_MI1310_SOC, 0x80 | 0x5d, 0x00, 0x0000, 0x24, 0x25, 0x01}, */ | 2829 | /* 11 MI1310_SOC */ |
2440 | /* {-1, 0x80 | 0x30, 0x0a, 0x0000, 0x25, 0x24, 0x05}, */ | 2830 | {SENSOR_MI1310_SOC, 0x80 | 0x5d, 0x00, 0x143a, 0x24, 0x25, 0x01}, |
2831 | /* 12 OV9650 */ | ||
2832 | {-1, 0x80 | 0x30, 0x0a, 0x0000, 0x25, 0x24, 0x05}, | ||
2833 | /* 13 S5K532 */ | ||
2441 | {-1, 0x80 | 0x11, 0x39, 0x0000, 0x24, 0x25, 0x01}, | 2834 | {-1, 0x80 | 0x11, 0x39, 0x0000, 0x24, 0x25, 0x01}, |
2835 | /* 14 MI360_SOC - ??? */ | ||
2836 | /* 15 PO1200N */ | ||
2442 | {SENSOR_PO1200, 0x80 | 0x5c, 0x00, 0x1200, 0x67, 0x67, 0x01}, | 2837 | {SENSOR_PO1200, 0x80 | 0x5c, 0x00, 0x1200, 0x67, 0x67, 0x01}, |
2838 | /* 16 ?? */ | ||
2443 | {-1, 0x80 | 0x2d, 0x00, 0x0000, 0x65, 0x67, 0x01}, | 2839 | {-1, 0x80 | 0x2d, 0x00, 0x0000, 0x65, 0x67, 0x01}, |
2840 | /* 17 PO2030 */ | ||
2444 | {-1, 0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01}, | 2841 | {-1, 0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01}, |
2842 | /* ?? */ | ||
2445 | {-1, 0x80 | 0x56, 0x01, 0x0000, 0x64, 0x67, 0x01}, | 2843 | {-1, 0x80 | 0x56, 0x01, 0x0000, 0x64, 0x67, 0x01}, |
2446 | {SENSOR_MI1320_SOC, 0x80 | 0x48, 0x00, 0x148c, 0x64, 0x67, 0x01}, | 2844 | {SENSOR_MI1320_SOC, 0x80 | 0x48, 0x00, 0x148c, 0x64, 0x67, 0x01}, |
2447 | /*fixme: previously detected?*/ | 2845 | /*fixme: not in the ms-win probe - may be found before? */ |
2448 | {SENSOR_MI1320, 0x80 | 0x48, 0x00, 0x148c, 0x64, 0x65, 0x01}, | ||
2449 | /*fixme: not in the ms-win probe - may be found before?*/ | ||
2450 | {SENSOR_OV7670, 0x80 | 0x21, 0x0a, 0x7673, 0x66, 0x67, 0x05}, | 2846 | {SENSOR_OV7670, 0x80 | 0x21, 0x0a, 0x7673, 0x66, 0x67, 0x05}, |
2451 | }; | 2847 | }; |
2452 | 2848 | ||
@@ -2520,7 +2916,7 @@ static int vc032x_probe_sensor(struct gspca_dev *gspca_dev) | |||
2520 | { | 2916 | { |
2521 | struct sd *sd = (struct sd *) gspca_dev; | 2917 | struct sd *sd = (struct sd *) gspca_dev; |
2522 | struct usb_device *dev = gspca_dev->dev; | 2918 | struct usb_device *dev = gspca_dev->dev; |
2523 | int i; | 2919 | int i, n; |
2524 | u16 value; | 2920 | u16 value; |
2525 | const struct sensor_info *ptsensor_info; | 2921 | const struct sensor_info *ptsensor_info; |
2526 | 2922 | ||
@@ -2531,9 +2927,16 @@ static int vc032x_probe_sensor(struct gspca_dev *gspca_dev) | |||
2531 | } | 2927 | } |
2532 | 2928 | ||
2533 | reg_r(gspca_dev, 0xa1, 0xbfcf, 1); | 2929 | reg_r(gspca_dev, 0xa1, 0xbfcf, 1); |
2534 | PDEBUG(D_PROBE, "check sensor header %02x", gspca_dev->usb_buf[0]); | 2930 | PDEBUG(D_PROBE, "vc032%d check sensor header %02x", |
2535 | for (i = 0; i < ARRAY_SIZE(sensor_info_data); i++) { | 2931 | sd->bridge == BRIDGE_VC0321 ? 1 : 3, gspca_dev->usb_buf[0]); |
2536 | ptsensor_info = &sensor_info_data[i]; | 2932 | if (sd->bridge == BRIDGE_VC0321) { |
2933 | ptsensor_info = vc0321_probe_data; | ||
2934 | n = ARRAY_SIZE(vc0321_probe_data); | ||
2935 | } else { | ||
2936 | ptsensor_info = vc0323_probe_data; | ||
2937 | n = ARRAY_SIZE(vc0323_probe_data); | ||
2938 | } | ||
2939 | for (i = 0; i < n; i++) { | ||
2537 | reg_w(dev, 0xa0, 0x02, 0xb334); | 2940 | reg_w(dev, 0xa0, 0x02, 0xb334); |
2538 | reg_w(dev, 0xa0, ptsensor_info->m1, 0xb300); | 2941 | reg_w(dev, 0xa0, ptsensor_info->m1, 0xb300); |
2539 | reg_w(dev, 0xa0, ptsensor_info->m2, 0xb300); | 2942 | reg_w(dev, 0xa0, ptsensor_info->m2, 0xb300); |
@@ -2551,13 +2954,15 @@ static int vc032x_probe_sensor(struct gspca_dev *gspca_dev) | |||
2551 | return ptsensor_info->sensorId; | 2954 | return ptsensor_info->sensorId; |
2552 | 2955 | ||
2553 | switch (value) { | 2956 | switch (value) { |
2957 | case 0x3130: | ||
2958 | return SENSOR_PO3130NC; | ||
2554 | case 0x7673: | 2959 | case 0x7673: |
2555 | return SENSOR_OV7670; | 2960 | return SENSOR_OV7670; |
2556 | case 0x8243: | 2961 | case 0x8243: |
2557 | return SENSOR_MI0360; | 2962 | return SENSOR_MI0360; |
2558 | } | 2963 | } |
2559 | /*fixme: should return here*/ | ||
2560 | } | 2964 | } |
2965 | ptsensor_info++; | ||
2561 | } | 2966 | } |
2562 | return -1; | 2967 | return -1; |
2563 | } | 2968 | } |
@@ -2619,7 +3024,7 @@ static void usb_exchange(struct gspca_dev *gspca_dev, | |||
2619 | i2c_write(gspca_dev, data[i][0], &data[i][1], 2); | 3024 | i2c_write(gspca_dev, data[i][0], &data[i][1], 2); |
2620 | break; | 3025 | break; |
2621 | case 0xdd: | 3026 | case 0xdd: |
2622 | msleep(data[i][2] + 10); | 3027 | msleep(data[i][1] * 256 + data[i][2] + 10); |
2623 | break; | 3028 | break; |
2624 | } | 3029 | } |
2625 | i++; | 3030 | i++; |
@@ -2646,12 +3051,17 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
2646 | 64, /* OV7670 6 */ | 3051 | 64, /* OV7670 6 */ |
2647 | 128, /* PO1200 7 */ | 3052 | 128, /* PO1200 7 */ |
2648 | 128, /* PO3130NC 8 */ | 3053 | 128, /* PO3130NC 8 */ |
3054 | 128, /* POxxxx 9 */ | ||
2649 | }; | 3055 | }; |
2650 | 3056 | ||
2651 | cam = &gspca_dev->cam; | 3057 | cam = &gspca_dev->cam; |
2652 | sd->bridge = id->driver_info >> 8; | 3058 | sd->bridge = id->driver_info >> 8; |
2653 | sd->flags = id->driver_info & 0xff; | 3059 | sd->flags = id->driver_info & 0xff; |
2654 | sensor = vc032x_probe_sensor(gspca_dev); | 3060 | if (id->idVendor == 0x046d && |
3061 | (id->idProduct == 0x0892 || id->idProduct == 0x0896)) | ||
3062 | sensor = SENSOR_POxxxx; | ||
3063 | else | ||
3064 | sensor = vc032x_probe_sensor(gspca_dev); | ||
2655 | switch (sensor) { | 3065 | switch (sensor) { |
2656 | case -1: | 3066 | case -1: |
2657 | PDEBUG(D_PROBE, "Unknown sensor..."); | 3067 | PDEBUG(D_PROBE, "Unknown sensor..."); |
@@ -2684,6 +3094,9 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
2684 | case SENSOR_PO3130NC: | 3094 | case SENSOR_PO3130NC: |
2685 | PDEBUG(D_PROBE, "Find Sensor PO3130NC"); | 3095 | PDEBUG(D_PROBE, "Find Sensor PO3130NC"); |
2686 | break; | 3096 | break; |
3097 | case SENSOR_POxxxx: | ||
3098 | PDEBUG(D_PROBE, "Sensor POxxxx"); | ||
3099 | break; | ||
2687 | } | 3100 | } |
2688 | sd->sensor = sensor; | 3101 | sd->sensor = sensor; |
2689 | 3102 | ||
@@ -2712,28 +3125,19 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
2712 | } | 3125 | } |
2713 | cam->npkt = npkt[sd->sensor]; | 3126 | cam->npkt = npkt[sd->sensor]; |
2714 | 3127 | ||
3128 | sd->brightness = BRIGHTNESS_DEF; | ||
3129 | sd->contrast = CONTRAST_DEF; | ||
3130 | sd->colors = COLOR_DEF; | ||
2715 | sd->hflip = HFLIP_DEF; | 3131 | sd->hflip = HFLIP_DEF; |
2716 | sd->vflip = VFLIP_DEF; | 3132 | sd->vflip = VFLIP_DEF; |
2717 | if (sd->sensor == SENSOR_OV7670) | ||
2718 | sd->flags |= FL_HFLIP | FL_VFLIP; | ||
2719 | sd->lightfreq = FREQ_DEF; | 3133 | sd->lightfreq = FREQ_DEF; |
2720 | if (sd->sensor != SENSOR_OV7670) | ||
2721 | gspca_dev->ctrl_dis = (1 << LIGHTFREQ_IDX); | ||
2722 | switch (sd->sensor) { | ||
2723 | case SENSOR_MI1310_SOC: | ||
2724 | case SENSOR_MI1320_SOC: | ||
2725 | case SENSOR_OV7660: | ||
2726 | case SENSOR_OV7670: | ||
2727 | case SENSOR_PO1200: | ||
2728 | break; | ||
2729 | default: | ||
2730 | gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | ||
2731 | | (1 << VFLIP_IDX); | ||
2732 | break; | ||
2733 | } | ||
2734 | |||
2735 | sd->sharpness = SHARPNESS_DEF; | 3134 | sd->sharpness = SHARPNESS_DEF; |
2736 | 3135 | ||
3136 | gspca_dev->ctrl_dis = ctrl_dis[sd->sensor]; | ||
3137 | |||
3138 | if (sd->sensor == SENSOR_OV7670) | ||
3139 | sd->flags |= FL_HFLIP | FL_VFLIP; | ||
3140 | |||
2737 | if (sd->bridge == BRIDGE_VC0321) { | 3141 | if (sd->bridge == BRIDGE_VC0321) { |
2738 | reg_r(gspca_dev, 0x8a, 0, 3); | 3142 | reg_r(gspca_dev, 0x8a, 0, 3); |
2739 | reg_w(dev, 0x87, 0x00, 0x0f0f); | 3143 | reg_w(dev, 0x87, 0x00, 0x0f0f); |
@@ -2747,10 +3151,55 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
2747 | /* this function is called at probe and resume time */ | 3151 | /* this function is called at probe and resume time */ |
2748 | static int sd_init(struct gspca_dev *gspca_dev) | 3152 | static int sd_init(struct gspca_dev *gspca_dev) |
2749 | { | 3153 | { |
3154 | struct sd *sd = (struct sd *) gspca_dev; | ||
3155 | |||
3156 | if (sd->sensor == SENSOR_POxxxx) { | ||
3157 | reg_r(gspca_dev, 0xa1, 0xb300, 1); | ||
3158 | if (gspca_dev->usb_buf[0] != 0) { | ||
3159 | reg_w(gspca_dev->dev, 0xa0, 0x26, 0xb300); | ||
3160 | reg_w(gspca_dev->dev, 0xa0, 0x04, 0xb300); | ||
3161 | reg_w(gspca_dev->dev, 0xa0, 0x00, 0xb300); | ||
3162 | } | ||
3163 | } | ||
2750 | return 0; | 3164 | return 0; |
2751 | } | 3165 | } |
2752 | 3166 | ||
2753 | /* some sensors only */ | 3167 | static void setbrightness(struct gspca_dev *gspca_dev) |
3168 | { | ||
3169 | struct sd *sd = (struct sd *) gspca_dev; | ||
3170 | u8 data; | ||
3171 | |||
3172 | if (gspca_dev->ctrl_dis & (1 << BRIGHTNESS_IDX)) | ||
3173 | return; | ||
3174 | data = sd->brightness; | ||
3175 | if (data >= 0x80) | ||
3176 | data &= 0x7f; | ||
3177 | else | ||
3178 | data = 0xff ^ data; | ||
3179 | i2c_write(gspca_dev, 0x98, &data, 1); | ||
3180 | } | ||
3181 | |||
3182 | static void setcontrast(struct gspca_dev *gspca_dev) | ||
3183 | { | ||
3184 | struct sd *sd = (struct sd *) gspca_dev; | ||
3185 | |||
3186 | if (gspca_dev->ctrl_dis & (1 << CONTRAST_IDX)) | ||
3187 | return; | ||
3188 | i2c_write(gspca_dev, 0x99, &sd->contrast, 1); | ||
3189 | } | ||
3190 | |||
3191 | static void setcolors(struct gspca_dev *gspca_dev) | ||
3192 | { | ||
3193 | struct sd *sd = (struct sd *) gspca_dev; | ||
3194 | u8 data; | ||
3195 | |||
3196 | if (gspca_dev->ctrl_dis & (1 << COLORS_IDX)) | ||
3197 | return; | ||
3198 | data = sd->colors - (sd->colors >> 3) - 1; | ||
3199 | i2c_write(gspca_dev, 0x94, &data, 1); | ||
3200 | i2c_write(gspca_dev, 0x95, &sd->colors, 1); | ||
3201 | } | ||
3202 | |||
2754 | static void sethvflip(struct gspca_dev *gspca_dev) | 3203 | static void sethvflip(struct gspca_dev *gspca_dev) |
2755 | { | 3204 | { |
2756 | struct sd *sd = (struct sd *) gspca_dev; | 3205 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -2764,6 +3213,7 @@ static void sethvflip(struct gspca_dev *gspca_dev) | |||
2764 | vflip = !vflip; | 3213 | vflip = !vflip; |
2765 | switch (sd->sensor) { | 3214 | switch (sd->sensor) { |
2766 | case SENSOR_MI1310_SOC: | 3215 | case SENSOR_MI1310_SOC: |
3216 | case SENSOR_MI1320: | ||
2767 | case SENSOR_MI1320_SOC: | 3217 | case SENSOR_MI1320_SOC: |
2768 | data[0] = data[1] = 0; /* select page 0 */ | 3218 | data[0] = data[1] = 0; /* select page 0 */ |
2769 | i2c_write(gspca_dev, 0xf0, data, 2); | 3219 | i2c_write(gspca_dev, 0xf0, data, 2); |
@@ -2801,18 +3251,29 @@ static void setlightfreq(struct gspca_dev *gspca_dev) | |||
2801 | usb_exchange(gspca_dev, ov7660_freq_tb[sd->lightfreq]); | 3251 | usb_exchange(gspca_dev, ov7660_freq_tb[sd->lightfreq]); |
2802 | } | 3252 | } |
2803 | 3253 | ||
2804 | /* po1200 only */ | ||
2805 | static void setsharpness(struct gspca_dev *gspca_dev) | 3254 | static void setsharpness(struct gspca_dev *gspca_dev) |
2806 | { | 3255 | { |
2807 | struct sd *sd = (struct sd *) gspca_dev; | 3256 | struct sd *sd = (struct sd *) gspca_dev; |
2808 | u8 data; | 3257 | u8 data; |
2809 | 3258 | ||
2810 | if (sd->sensor != SENSOR_PO1200) | 3259 | switch (sd->sensor) { |
2811 | return; | 3260 | case SENSOR_PO1200: |
2812 | data = 0; | 3261 | data = 0; |
2813 | i2c_write(gspca_dev, 0x03, &data, 1); | 3262 | i2c_write(gspca_dev, 0x03, &data, 1); |
2814 | data = 0xb5 + sd->sharpness * 3; | 3263 | if (sd->sharpness < 0) |
2815 | i2c_write(gspca_dev, 0x61, &data, 1); | 3264 | data = 0x6a; |
3265 | else | ||
3266 | data = 0xb5 + sd->sharpness * 3; | ||
3267 | i2c_write(gspca_dev, 0x61, &data, 1); | ||
3268 | break; | ||
3269 | case SENSOR_POxxxx: | ||
3270 | if (sd->sharpness < 0) | ||
3271 | data = 0x7e; /* def = max */ | ||
3272 | else | ||
3273 | data = 0x60 + sd->sharpness * 0x0f; | ||
3274 | i2c_write(gspca_dev, 0x59, &data, 1); | ||
3275 | break; | ||
3276 | } | ||
2816 | } | 3277 | } |
2817 | 3278 | ||
2818 | static int sd_start(struct gspca_dev *gspca_dev) | 3279 | static int sd_start(struct gspca_dev *gspca_dev) |
@@ -2922,12 +3383,27 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
2922 | usb_exchange(gspca_dev, init); | 3383 | usb_exchange(gspca_dev, init); |
2923 | init = po3130_rundata; | 3384 | init = po3130_rundata; |
2924 | break; | 3385 | break; |
2925 | default: | 3386 | case SENSOR_PO1200: |
2926 | /* case SENSOR_PO1200: */ | ||
2927 | GammaT = po1200_gamma; | 3387 | GammaT = po1200_gamma; |
2928 | MatrixT = po1200_matrix; | 3388 | MatrixT = po1200_matrix; |
2929 | init = po1200_initVGA_data; | 3389 | init = po1200_initVGA_data; |
2930 | break; | 3390 | break; |
3391 | default: | ||
3392 | /* case SENSOR_POxxxx: */ | ||
3393 | usb_exchange(gspca_dev, poxxxx_init_common); | ||
3394 | if (mode) | ||
3395 | init = poxxxx_initQVGA; | ||
3396 | else | ||
3397 | init = poxxxx_initVGA; | ||
3398 | usb_exchange(gspca_dev, init); | ||
3399 | reg_r(gspca_dev, 0x8c, 0x0000, 3); | ||
3400 | reg_w(gspca_dev->dev, 0xa0, | ||
3401 | gspca_dev->usb_buf[2] & 1 ? 0 : 1, | ||
3402 | 0xb35c); | ||
3403 | msleep(300); | ||
3404 | /*fixme: i2c read 04 and 05*/ | ||
3405 | init = poxxxx_init_end_1; | ||
3406 | break; | ||
2931 | } | 3407 | } |
2932 | usb_exchange(gspca_dev, init); | 3408 | usb_exchange(gspca_dev, init); |
2933 | if (GammaT && MatrixT) { | 3409 | if (GammaT && MatrixT) { |
@@ -2936,7 +3412,6 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
2936 | put_tab_to_reg(gspca_dev, GammaT, 17, 0xb86c); | 3412 | put_tab_to_reg(gspca_dev, GammaT, 17, 0xb86c); |
2937 | put_tab_to_reg(gspca_dev, MatrixT, 9, 0xb82c); | 3413 | put_tab_to_reg(gspca_dev, MatrixT, 9, 0xb82c); |
2938 | 3414 | ||
2939 | /* set the led on 0x0892 0x0896 */ | ||
2940 | switch (sd->sensor) { | 3415 | switch (sd->sensor) { |
2941 | case SENSOR_PO1200: | 3416 | case SENSOR_PO1200: |
2942 | case SENSOR_HV7131R: | 3417 | case SENSOR_HV7131R: |
@@ -2945,16 +3420,22 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
2945 | case SENSOR_MI1310_SOC: | 3420 | case SENSOR_MI1310_SOC: |
2946 | reg_w(gspca_dev->dev, 0x89, 0x058c, 0x0000); | 3421 | reg_w(gspca_dev->dev, 0x89, 0x058c, 0x0000); |
2947 | break; | 3422 | break; |
2948 | default: | ||
2949 | if (!(sd->flags & FL_SAMSUNG)) | ||
2950 | reg_w(gspca_dev->dev, 0x89, 0xffff, 0xfdff); | ||
2951 | break; | ||
2952 | } | 3423 | } |
2953 | msleep(100); | 3424 | msleep(100); |
2954 | setsharpness(gspca_dev); | 3425 | setsharpness(gspca_dev); |
2955 | sethvflip(gspca_dev); | 3426 | sethvflip(gspca_dev); |
2956 | setlightfreq(gspca_dev); | 3427 | setlightfreq(gspca_dev); |
2957 | } | 3428 | } |
3429 | if (sd->sensor == SENSOR_POxxxx) { | ||
3430 | setcolors(gspca_dev); | ||
3431 | setbrightness(gspca_dev); | ||
3432 | setcontrast(gspca_dev); | ||
3433 | |||
3434 | /* led on */ | ||
3435 | msleep(80); | ||
3436 | reg_w(gspca_dev->dev, 0x89, 0xffff, 0xfdff); | ||
3437 | usb_exchange(gspca_dev, poxxxx_init_end_2); | ||
3438 | } | ||
2958 | return 0; | 3439 | return 0; |
2959 | } | 3440 | } |
2960 | 3441 | ||
@@ -2963,10 +3444,17 @@ static void sd_stopN(struct gspca_dev *gspca_dev) | |||
2963 | struct usb_device *dev = gspca_dev->dev; | 3444 | struct usb_device *dev = gspca_dev->dev; |
2964 | struct sd *sd = (struct sd *) gspca_dev; | 3445 | struct sd *sd = (struct sd *) gspca_dev; |
2965 | 3446 | ||
2966 | if (sd->sensor == SENSOR_MI1310_SOC) | 3447 | switch (sd->sensor) { |
3448 | case SENSOR_MI1310_SOC: | ||
2967 | reg_w(dev, 0x89, 0x058c, 0x00ff); | 3449 | reg_w(dev, 0x89, 0x058c, 0x00ff); |
2968 | else if (!(sd->flags & FL_SAMSUNG)) | 3450 | break; |
2969 | reg_w(dev, 0x89, 0xffff, 0xffff); | 3451 | case SENSOR_POxxxx: |
3452 | return; | ||
3453 | default: | ||
3454 | if (!(sd->flags & FL_SAMSUNG)) | ||
3455 | reg_w(dev, 0x89, 0xffff, 0xffff); | ||
3456 | break; | ||
3457 | } | ||
2970 | reg_w(dev, 0xa0, 0x01, 0xb301); | 3458 | reg_w(dev, 0xa0, 0x01, 0xb301); |
2971 | reg_w(dev, 0xa0, 0x09, 0xb003); | 3459 | reg_w(dev, 0xa0, 0x09, 0xb003); |
2972 | } | 3460 | } |
@@ -2984,6 +3472,12 @@ static void sd_stop0(struct gspca_dev *gspca_dev) | |||
2984 | reg_w(dev, 0x89, 0x058c, 0x00ff); | 3472 | reg_w(dev, 0x89, 0x058c, 0x00ff); |
2985 | else if (!(sd->flags & FL_SAMSUNG)) | 3473 | else if (!(sd->flags & FL_SAMSUNG)) |
2986 | reg_w(dev, 0x89, 0xffff, 0xffff); | 3474 | reg_w(dev, 0x89, 0xffff, 0xffff); |
3475 | |||
3476 | if (sd->sensor == SENSOR_POxxxx) { | ||
3477 | reg_w(dev, 0xa0, 0x26, 0xb300); | ||
3478 | reg_w(dev, 0xa0, 0x04, 0xb300); | ||
3479 | reg_w(dev, 0xa0, 0x00, 0xb300); | ||
3480 | } | ||
2987 | } | 3481 | } |
2988 | 3482 | ||
2989 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 3483 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
@@ -3020,6 +3514,60 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
3020 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); | 3514 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); |
3021 | } | 3515 | } |
3022 | 3516 | ||
3517 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | ||
3518 | { | ||
3519 | struct sd *sd = (struct sd *) gspca_dev; | ||
3520 | |||
3521 | sd->brightness = val; | ||
3522 | if (gspca_dev->streaming) | ||
3523 | setbrightness(gspca_dev); | ||
3524 | return 0; | ||
3525 | } | ||
3526 | |||
3527 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) | ||
3528 | { | ||
3529 | struct sd *sd = (struct sd *) gspca_dev; | ||
3530 | |||
3531 | *val = sd->brightness; | ||
3532 | return 0; | ||
3533 | } | ||
3534 | |||
3535 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) | ||
3536 | { | ||
3537 | struct sd *sd = (struct sd *) gspca_dev; | ||
3538 | |||
3539 | sd->contrast = val; | ||
3540 | if (gspca_dev->streaming) | ||
3541 | setcontrast(gspca_dev); | ||
3542 | return 0; | ||
3543 | } | ||
3544 | |||
3545 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) | ||
3546 | { | ||
3547 | struct sd *sd = (struct sd *) gspca_dev; | ||
3548 | |||
3549 | *val = sd->contrast; | ||
3550 | return 0; | ||
3551 | } | ||
3552 | |||
3553 | static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val) | ||
3554 | { | ||
3555 | struct sd *sd = (struct sd *) gspca_dev; | ||
3556 | |||
3557 | sd->colors = val; | ||
3558 | if (gspca_dev->streaming) | ||
3559 | setcolors(gspca_dev); | ||
3560 | return 0; | ||
3561 | } | ||
3562 | |||
3563 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) | ||
3564 | { | ||
3565 | struct sd *sd = (struct sd *) gspca_dev; | ||
3566 | |||
3567 | *val = sd->colors; | ||
3568 | return 0; | ||
3569 | } | ||
3570 | |||
3023 | static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val) | 3571 | static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val) |
3024 | { | 3572 | { |
3025 | struct sd *sd = (struct sd *) gspca_dev; | 3573 | struct sd *sd = (struct sd *) gspca_dev; |
diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index 1a800fc1c00e..50986da3d912 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c | |||
@@ -1,9 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * Z-Star/Vimicro zc301/zc302p/vc30x library | 2 | * Z-Star/Vimicro zc301/zc302p/vc30x library |
3 | * Copyright (C) 2004 2005 2006 Michel Xhaard | ||
4 | * mxhaard@magic.fr | ||
5 | * | 3 | * |
6 | * V4L2 by Jean-Francois Moine <http://moinejf.free.fr> | 4 | * Copyright (C) 2009-2010 Jean-Francois Moine <http://moinejf.free.fr> |
5 | * Copyright (C) 2004 2005 2006 Michel Xhaard mxhaard@magic.fr | ||
7 | * | 6 | * |
8 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 8 | * it under the terms of the GNU General Public License as published by |
@@ -22,10 +21,11 @@ | |||
22 | 21 | ||
23 | #define MODULE_NAME "zc3xx" | 22 | #define MODULE_NAME "zc3xx" |
24 | 23 | ||
24 | #include <linux/input.h> | ||
25 | #include "gspca.h" | 25 | #include "gspca.h" |
26 | #include "jpeg.h" | 26 | #include "jpeg.h" |
27 | 27 | ||
28 | MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>, " | 28 | MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>, " |
29 | "Serge A. Suchkov <Serge.A.S@tochka.ru>"); | 29 | "Serge A. Suchkov <Serge.A.S@tochka.ru>"); |
30 | MODULE_DESCRIPTION("GSPCA ZC03xx/VC3xx USB Camera Driver"); | 30 | MODULE_DESCRIPTION("GSPCA ZC03xx/VC3xx USB Camera Driver"); |
31 | MODULE_LICENSE("GPL"); | 31 | MODULE_LICENSE("GPL"); |
@@ -39,18 +39,18 @@ static int force_sensor = -1; | |||
39 | struct sd { | 39 | struct sd { |
40 | struct gspca_dev gspca_dev; /* !! must be the first item */ | 40 | struct gspca_dev gspca_dev; /* !! must be the first item */ |
41 | 41 | ||
42 | __u8 brightness; | 42 | u8 brightness; |
43 | __u8 contrast; | 43 | u8 contrast; |
44 | __u8 gamma; | 44 | u8 gamma; |
45 | __u8 autogain; | 45 | u8 autogain; |
46 | __u8 lightfreq; | 46 | u8 lightfreq; |
47 | __u8 sharpness; | 47 | u8 sharpness; |
48 | u8 quality; /* image quality */ | 48 | u8 quality; /* image quality */ |
49 | #define QUALITY_MIN 40 | 49 | #define QUALITY_MIN 40 |
50 | #define QUALITY_MAX 60 | 50 | #define QUALITY_MAX 60 |
51 | #define QUALITY_DEF 50 | 51 | #define QUALITY_DEF 50 |
52 | 52 | ||
53 | signed char sensor; /* Type of image sensor chip */ | 53 | u8 sensor; /* Type of image sensor chip */ |
54 | /* !! values used in different tables */ | 54 | /* !! values used in different tables */ |
55 | #define SENSOR_ADCM2700 0 | 55 | #define SENSOR_ADCM2700 0 |
56 | #define SENSOR_CS2102 1 | 56 | #define SENSOR_CS2102 1 |
@@ -92,9 +92,8 @@ static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); | |||
92 | static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val); | 92 | static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val); |
93 | static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); | 93 | static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); |
94 | 94 | ||
95 | static struct ctrl sd_ctrls[] = { | 95 | static const struct ctrl sd_ctrls[] = { |
96 | #define BRIGHTNESS_IDX 0 | 96 | #define BRIGHTNESS_IDX 0 |
97 | #define SD_BRIGHTNESS 0 | ||
98 | { | 97 | { |
99 | { | 98 | { |
100 | .id = V4L2_CID_BRIGHTNESS, | 99 | .id = V4L2_CID_BRIGHTNESS, |
@@ -103,26 +102,26 @@ static struct ctrl sd_ctrls[] = { | |||
103 | .minimum = 0, | 102 | .minimum = 0, |
104 | .maximum = 255, | 103 | .maximum = 255, |
105 | .step = 1, | 104 | .step = 1, |
106 | .default_value = 128, | 105 | #define BRIGHTNESS_DEF 128 |
106 | .default_value = BRIGHTNESS_DEF, | ||
107 | }, | 107 | }, |
108 | .set = sd_setbrightness, | 108 | .set = sd_setbrightness, |
109 | .get = sd_getbrightness, | 109 | .get = sd_getbrightness, |
110 | }, | 110 | }, |
111 | #define SD_CONTRAST 1 | ||
112 | { | 111 | { |
113 | { | 112 | { |
114 | .id = V4L2_CID_CONTRAST, | 113 | .id = V4L2_CID_CONTRAST, |
115 | .type = V4L2_CTRL_TYPE_INTEGER, | 114 | .type = V4L2_CTRL_TYPE_INTEGER, |
116 | .name = "Contrast", | 115 | .name = "Contrast", |
117 | .minimum = 0, | 116 | .minimum = 0, |
118 | .maximum = 256, | 117 | .maximum = 255, |
119 | .step = 1, | 118 | .step = 1, |
120 | .default_value = 128, | 119 | #define CONTRAST_DEF 128 |
120 | .default_value = CONTRAST_DEF, | ||
121 | }, | 121 | }, |
122 | .set = sd_setcontrast, | 122 | .set = sd_setcontrast, |
123 | .get = sd_getcontrast, | 123 | .get = sd_getcontrast, |
124 | }, | 124 | }, |
125 | #define SD_GAMMA 2 | ||
126 | { | 125 | { |
127 | { | 126 | { |
128 | .id = V4L2_CID_GAMMA, | 127 | .id = V4L2_CID_GAMMA, |
@@ -136,7 +135,6 @@ static struct ctrl sd_ctrls[] = { | |||
136 | .set = sd_setgamma, | 135 | .set = sd_setgamma, |
137 | .get = sd_getgamma, | 136 | .get = sd_getgamma, |
138 | }, | 137 | }, |
139 | #define SD_AUTOGAIN 3 | ||
140 | { | 138 | { |
141 | { | 139 | { |
142 | .id = V4L2_CID_AUTOGAIN, | 140 | .id = V4L2_CID_AUTOGAIN, |
@@ -145,13 +143,13 @@ static struct ctrl sd_ctrls[] = { | |||
145 | .minimum = 0, | 143 | .minimum = 0, |
146 | .maximum = 1, | 144 | .maximum = 1, |
147 | .step = 1, | 145 | .step = 1, |
148 | .default_value = 1, | 146 | #define AUTOGAIN_DEF 1 |
147 | .default_value = AUTOGAIN_DEF, | ||
149 | }, | 148 | }, |
150 | .set = sd_setautogain, | 149 | .set = sd_setautogain, |
151 | .get = sd_getautogain, | 150 | .get = sd_getautogain, |
152 | }, | 151 | }, |
153 | #define LIGHTFREQ_IDX 4 | 152 | #define LIGHTFREQ_IDX 4 |
154 | #define SD_FREQ 4 | ||
155 | { | 153 | { |
156 | { | 154 | { |
157 | .id = V4L2_CID_POWER_LINE_FREQUENCY, | 155 | .id = V4L2_CID_POWER_LINE_FREQUENCY, |
@@ -160,12 +158,12 @@ static struct ctrl sd_ctrls[] = { | |||
160 | .minimum = 0, | 158 | .minimum = 0, |
161 | .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */ | 159 | .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */ |
162 | .step = 1, | 160 | .step = 1, |
163 | .default_value = 1, | 161 | #define FREQ_DEF 0 |
162 | .default_value = FREQ_DEF, | ||
164 | }, | 163 | }, |
165 | .set = sd_setfreq, | 164 | .set = sd_setfreq, |
166 | .get = sd_getfreq, | 165 | .get = sd_getfreq, |
167 | }, | 166 | }, |
168 | #define SD_SHARPNESS 5 | ||
169 | { | 167 | { |
170 | { | 168 | { |
171 | .id = V4L2_CID_SHARPNESS, | 169 | .id = V4L2_CID_SHARPNESS, |
@@ -174,7 +172,8 @@ static struct ctrl sd_ctrls[] = { | |||
174 | .minimum = 0, | 172 | .minimum = 0, |
175 | .maximum = 3, | 173 | .maximum = 3, |
176 | .step = 1, | 174 | .step = 1, |
177 | .default_value = 2, | 175 | #define SHARPNESS_DEF 2 |
176 | .default_value = SHARPNESS_DEF, | ||
178 | }, | 177 | }, |
179 | .set = sd_setsharpness, | 178 | .set = sd_setsharpness, |
180 | .get = sd_getsharpness, | 179 | .get = sd_getsharpness, |
@@ -194,6 +193,19 @@ static const struct v4l2_pix_format vga_mode[] = { | |||
194 | .priv = 0}, | 193 | .priv = 0}, |
195 | }; | 194 | }; |
196 | 195 | ||
196 | static const struct v4l2_pix_format broken_vga_mode[] = { | ||
197 | {320, 232, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | ||
198 | .bytesperline = 320, | ||
199 | .sizeimage = 320 * 232 * 4 / 8 + 590, | ||
200 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
201 | .priv = 1}, | ||
202 | {640, 472, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | ||
203 | .bytesperline = 640, | ||
204 | .sizeimage = 640 * 472 * 3 / 8 + 590, | ||
205 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
206 | .priv = 0}, | ||
207 | }; | ||
208 | |||
197 | static const struct v4l2_pix_format sif_mode[] = { | 209 | static const struct v4l2_pix_format sif_mode[] = { |
198 | {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | 210 | {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, |
199 | .bytesperline = 176, | 211 | .bytesperline = 176, |
@@ -209,9 +221,9 @@ static const struct v4l2_pix_format sif_mode[] = { | |||
209 | 221 | ||
210 | /* usb exchanges */ | 222 | /* usb exchanges */ |
211 | struct usb_action { | 223 | struct usb_action { |
212 | __u8 req; | 224 | u8 req; |
213 | __u8 val; | 225 | u8 val; |
214 | __u16 idx; | 226 | u16 idx; |
215 | }; | 227 | }; |
216 | 228 | ||
217 | static const struct usb_action adcm2700_Initial[] = { | 229 | static const struct usb_action adcm2700_Initial[] = { |
@@ -421,7 +433,7 @@ static const struct usb_action adcm2700_NoFliker[] = { | |||
421 | {0xaa, 0xfe, 0x0010}, /* 00,fe,10,aa */ | 433 | {0xaa, 0xfe, 0x0010}, /* 00,fe,10,aa */ |
422 | {} | 434 | {} |
423 | }; | 435 | }; |
424 | static const struct usb_action cs2102_Initial[] = { /* 320x240 */ | 436 | static const struct usb_action cs2102_InitialScale[] = { /* 320x240 */ |
425 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, | 437 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, |
426 | {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, | 438 | {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, |
427 | {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT}, | 439 | {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT}, |
@@ -473,7 +485,7 @@ static const struct usb_action cs2102_Initial[] = { /* 320x240 */ | |||
473 | {} | 485 | {} |
474 | }; | 486 | }; |
475 | 487 | ||
476 | static const struct usb_action cs2102_InitialScale[] = { /* 640x480 */ | 488 | static const struct usb_action cs2102_Initial[] = { /* 640x480 */ |
477 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, | 489 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, |
478 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, | 490 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, |
479 | {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT}, | 491 | {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT}, |
@@ -524,7 +536,7 @@ static const struct usb_action cs2102_InitialScale[] = { /* 640x480 */ | |||
524 | {0xa0, 0x00, 0x01ad}, | 536 | {0xa0, 0x00, 0x01ad}, |
525 | {} | 537 | {} |
526 | }; | 538 | }; |
527 | static const struct usb_action cs2102_50HZ[] = { | 539 | static const struct usb_action cs2102_50HZScale[] = { |
528 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, | 540 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, |
529 | {0xaa, 0x23, 0x0001}, | 541 | {0xaa, 0x23, 0x0001}, |
530 | {0xaa, 0x24, 0x005f}, | 542 | {0xaa, 0x24, 0x005f}, |
@@ -546,7 +558,7 @@ static const struct usb_action cs2102_50HZ[] = { | |||
546 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, | 558 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, |
547 | {} | 559 | {} |
548 | }; | 560 | }; |
549 | static const struct usb_action cs2102_50HZScale[] = { | 561 | static const struct usb_action cs2102_50HZ[] = { |
550 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, | 562 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, |
551 | {0xaa, 0x23, 0x0000}, | 563 | {0xaa, 0x23, 0x0000}, |
552 | {0xaa, 0x24, 0x00af}, | 564 | {0xaa, 0x24, 0x00af}, |
@@ -568,7 +580,7 @@ static const struct usb_action cs2102_50HZScale[] = { | |||
568 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, | 580 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, |
569 | {} | 581 | {} |
570 | }; | 582 | }; |
571 | static const struct usb_action cs2102_60HZ[] = { | 583 | static const struct usb_action cs2102_60HZScale[] = { |
572 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, | 584 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, |
573 | {0xaa, 0x23, 0x0001}, | 585 | {0xaa, 0x23, 0x0001}, |
574 | {0xaa, 0x24, 0x0055}, | 586 | {0xaa, 0x24, 0x0055}, |
@@ -590,7 +602,7 @@ static const struct usb_action cs2102_60HZ[] = { | |||
590 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, | 602 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, |
591 | {} | 603 | {} |
592 | }; | 604 | }; |
593 | static const struct usb_action cs2102_60HZScale[] = { | 605 | static const struct usb_action cs2102_60HZ[] = { |
594 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, | 606 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, |
595 | {0xaa, 0x23, 0x0000}, | 607 | {0xaa, 0x23, 0x0000}, |
596 | {0xaa, 0x24, 0x00aa}, | 608 | {0xaa, 0x24, 0x00aa}, |
@@ -612,7 +624,7 @@ static const struct usb_action cs2102_60HZScale[] = { | |||
612 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, | 624 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, |
613 | {} | 625 | {} |
614 | }; | 626 | }; |
615 | static const struct usb_action cs2102_NoFliker[] = { | 627 | static const struct usb_action cs2102_NoFlikerScale[] = { |
616 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, | 628 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, |
617 | {0xaa, 0x23, 0x0001}, | 629 | {0xaa, 0x23, 0x0001}, |
618 | {0xaa, 0x24, 0x005f}, | 630 | {0xaa, 0x24, 0x005f}, |
@@ -634,7 +646,7 @@ static const struct usb_action cs2102_NoFliker[] = { | |||
634 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, | 646 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, |
635 | {} | 647 | {} |
636 | }; | 648 | }; |
637 | static const struct usb_action cs2102_NoFlikerScale[] = { | 649 | static const struct usb_action cs2102_NoFliker[] = { |
638 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, | 650 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, |
639 | {0xaa, 0x23, 0x0000}, | 651 | {0xaa, 0x23, 0x0000}, |
640 | {0xaa, 0x24, 0x00af}, | 652 | {0xaa, 0x24, 0x00af}, |
@@ -658,7 +670,7 @@ static const struct usb_action cs2102_NoFlikerScale[] = { | |||
658 | }; | 670 | }; |
659 | 671 | ||
660 | /* CS2102_KOCOM */ | 672 | /* CS2102_KOCOM */ |
661 | static const struct usb_action cs2102K_Initial[] = { | 673 | static const struct usb_action cs2102K_InitialScale[] = { |
662 | {0xa0, 0x11, ZC3XX_R002_CLOCKSELECT}, | 674 | {0xa0, 0x11, ZC3XX_R002_CLOCKSELECT}, |
663 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, | 675 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, |
664 | {0xa0, 0x08, ZC3XX_R010_CMOSSENSORSELECT}, | 676 | {0xa0, 0x08, ZC3XX_R010_CMOSSENSORSELECT}, |
@@ -917,7 +929,7 @@ static const struct usb_action cs2102K_Initial[] = { | |||
917 | {} | 929 | {} |
918 | }; | 930 | }; |
919 | 931 | ||
920 | static const struct usb_action cs2102K_InitialScale[] = { | 932 | static const struct usb_action cs2102K_Initial[] = { |
921 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, | 933 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, |
922 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, | 934 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, |
923 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, | 935 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, |
@@ -1495,7 +1507,7 @@ static const struct usb_action gc0305_NoFliker[] = { | |||
1495 | {} | 1507 | {} |
1496 | }; | 1508 | }; |
1497 | 1509 | ||
1498 | static const struct usb_action hdcs2020xb_Initial[] = { | 1510 | static const struct usb_action hdcs2020b_InitialScale[] = { |
1499 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, | 1511 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, |
1500 | {0xa0, 0x11, ZC3XX_R002_CLOCKSELECT}, | 1512 | {0xa0, 0x11, ZC3XX_R002_CLOCKSELECT}, |
1501 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* qtable 0x05 */ | 1513 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* qtable 0x05 */ |
@@ -1627,7 +1639,7 @@ static const struct usb_action hdcs2020xb_Initial[] = { | |||
1627 | {0xa0, 0x40, ZC3XX_R118_BGAIN}, | 1639 | {0xa0, 0x40, ZC3XX_R118_BGAIN}, |
1628 | {} | 1640 | {} |
1629 | }; | 1641 | }; |
1630 | static const struct usb_action hdcs2020xb_InitialScale[] = { | 1642 | static const struct usb_action hdcs2020b_Initial[] = { |
1631 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, | 1643 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, |
1632 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, | 1644 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, |
1633 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, | 1645 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, |
@@ -1819,7 +1831,7 @@ static const struct usb_action hdcs2020b_NoFliker[] = { | |||
1819 | {} | 1831 | {} |
1820 | }; | 1832 | }; |
1821 | 1833 | ||
1822 | static const struct usb_action hv7131bxx_Initial[] = { /* 320x240 */ | 1834 | static const struct usb_action hv7131b_InitialScale[] = { /* 320x240 */ |
1823 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, | 1835 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, |
1824 | {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, | 1836 | {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, |
1825 | {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT}, | 1837 | {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT}, |
@@ -1866,7 +1878,7 @@ static const struct usb_action hv7131bxx_Initial[] = { /* 320x240 */ | |||
1866 | {} | 1878 | {} |
1867 | }; | 1879 | }; |
1868 | 1880 | ||
1869 | static const struct usb_action hv7131bxx_InitialScale[] = { /* 640x480*/ | 1881 | static const struct usb_action hv7131b_Initial[] = { /* 640x480*/ |
1870 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, | 1882 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, |
1871 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, | 1883 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, |
1872 | {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT}, | 1884 | {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT}, |
@@ -2063,7 +2075,7 @@ static const struct usb_action hv7131b_NoFlikerScale[] = { /* 320x240 */ | |||
2063 | {} | 2075 | {} |
2064 | }; | 2076 | }; |
2065 | 2077 | ||
2066 | static const struct usb_action hv7131cxx_Initial[] = { | 2078 | static const struct usb_action hv7131r_InitialScale[] = { |
2067 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, | 2079 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, |
2068 | {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, | 2080 | {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, |
2069 | {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, | 2081 | {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, |
@@ -2157,7 +2169,7 @@ static const struct usb_action hv7131cxx_Initial[] = { | |||
2157 | {} | 2169 | {} |
2158 | }; | 2170 | }; |
2159 | 2171 | ||
2160 | static const struct usb_action hv7131cxx_InitialScale[] = { | 2172 | static const struct usb_action hv7131r_Initial[] = { |
2161 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, | 2173 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, |
2162 | 2174 | ||
2163 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, /* diff */ | 2175 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, /* diff */ |
@@ -2259,7 +2271,7 @@ static const struct usb_action hv7131cxx_InitialScale[] = { | |||
2259 | {} | 2271 | {} |
2260 | }; | 2272 | }; |
2261 | 2273 | ||
2262 | static const struct usb_action icm105axx_Initial[] = { | 2274 | static const struct usb_action icm105a_InitialScale[] = { |
2263 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, | 2275 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, |
2264 | {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, | 2276 | {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, |
2265 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, | 2277 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, |
@@ -2436,7 +2448,7 @@ static const struct usb_action icm105axx_Initial[] = { | |||
2436 | {} | 2448 | {} |
2437 | }; | 2449 | }; |
2438 | 2450 | ||
2439 | static const struct usb_action icm105axx_InitialScale[] = { | 2451 | static const struct usb_action icm105a_Initial[] = { |
2440 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, | 2452 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, |
2441 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, | 2453 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, |
2442 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, | 2454 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, |
@@ -2615,7 +2627,7 @@ static const struct usb_action icm105axx_InitialScale[] = { | |||
2615 | {0xa0, 0x40, ZC3XX_R118_BGAIN}, | 2627 | {0xa0, 0x40, ZC3XX_R118_BGAIN}, |
2616 | {} | 2628 | {} |
2617 | }; | 2629 | }; |
2618 | static const struct usb_action icm105a_50HZ[] = { | 2630 | static const struct usb_action icm105a_50HZScale[] = { |
2619 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ | 2631 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ |
2620 | {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */ | 2632 | {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */ |
2621 | {0xaa, 0x0c, 0x0020}, /* 00,0c,20,aa */ | 2633 | {0xaa, 0x0c, 0x0020}, /* 00,0c,20,aa */ |
@@ -2646,7 +2658,7 @@ static const struct usb_action icm105a_50HZ[] = { | |||
2646 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ | 2658 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ |
2647 | {} | 2659 | {} |
2648 | }; | 2660 | }; |
2649 | static const struct usb_action icm105a_50HZScale[] = { | 2661 | static const struct usb_action icm105a_50HZ[] = { |
2650 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ | 2662 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ |
2651 | {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */ | 2663 | {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */ |
2652 | {0xaa, 0x0c, 0x008c}, /* 00,0c,8c,aa */ | 2664 | {0xaa, 0x0c, 0x008c}, /* 00,0c,8c,aa */ |
@@ -2679,7 +2691,7 @@ static const struct usb_action icm105a_50HZScale[] = { | |||
2679 | {0xa0, 0xc0, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,c0,cc */ | 2691 | {0xa0, 0xc0, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,c0,cc */ |
2680 | {} | 2692 | {} |
2681 | }; | 2693 | }; |
2682 | static const struct usb_action icm105a_60HZ[] = { | 2694 | static const struct usb_action icm105a_60HZScale[] = { |
2683 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ | 2695 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ |
2684 | {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */ | 2696 | {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */ |
2685 | {0xaa, 0x0c, 0x0004}, /* 00,0c,04,aa */ | 2697 | {0xaa, 0x0c, 0x0004}, /* 00,0c,04,aa */ |
@@ -2710,7 +2722,7 @@ static const struct usb_action icm105a_60HZ[] = { | |||
2710 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ | 2722 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ |
2711 | {} | 2723 | {} |
2712 | }; | 2724 | }; |
2713 | static const struct usb_action icm105a_60HZScale[] = { | 2725 | static const struct usb_action icm105a_60HZ[] = { |
2714 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ | 2726 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ |
2715 | {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */ | 2727 | {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */ |
2716 | {0xaa, 0x0c, 0x0008}, /* 00,0c,08,aa */ | 2728 | {0xaa, 0x0c, 0x0008}, /* 00,0c,08,aa */ |
@@ -2743,7 +2755,7 @@ static const struct usb_action icm105a_60HZScale[] = { | |||
2743 | {0xa0, 0xc0, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,c0,cc */ | 2755 | {0xa0, 0xc0, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,c0,cc */ |
2744 | {} | 2756 | {} |
2745 | }; | 2757 | }; |
2746 | static const struct usb_action icm105a_NoFliker[] = { | 2758 | static const struct usb_action icm105a_NoFlikerScale[] = { |
2747 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ | 2759 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ |
2748 | {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */ | 2760 | {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */ |
2749 | {0xaa, 0x0c, 0x0004}, /* 00,0c,04,aa */ | 2761 | {0xaa, 0x0c, 0x0004}, /* 00,0c,04,aa */ |
@@ -2774,7 +2786,7 @@ static const struct usb_action icm105a_NoFliker[] = { | |||
2774 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ | 2786 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ |
2775 | {} | 2787 | {} |
2776 | }; | 2788 | }; |
2777 | static const struct usb_action icm105a_NoFlikerScale[] = { | 2789 | static const struct usb_action icm105a_NoFliker[] = { |
2778 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ | 2790 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ |
2779 | {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */ | 2791 | {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */ |
2780 | {0xaa, 0x0c, 0x0004}, /* 00,0c,04,aa */ | 2792 | {0xaa, 0x0c, 0x0004}, /* 00,0c,04,aa */ |
@@ -2808,7 +2820,7 @@ static const struct usb_action icm105a_NoFlikerScale[] = { | |||
2808 | {} | 2820 | {} |
2809 | }; | 2821 | }; |
2810 | 2822 | ||
2811 | static const struct usb_action MC501CB_InitialScale[] = { | 2823 | static const struct usb_action mc501cb_Initial[] = { |
2812 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ | 2824 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ |
2813 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, /* 00,02,00,cc */ | 2825 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, /* 00,02,00,cc */ |
2814 | {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ | 2826 | {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ |
@@ -2928,7 +2940,7 @@ static const struct usb_action MC501CB_InitialScale[] = { | |||
2928 | {} | 2940 | {} |
2929 | }; | 2941 | }; |
2930 | 2942 | ||
2931 | static const struct usb_action MC501CB_Initial[] = { /* 320x240 */ | 2943 | static const struct usb_action mc501cb_InitialScale[] = { /* 320x240 */ |
2932 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ | 2944 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ |
2933 | {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc */ | 2945 | {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc */ |
2934 | {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ | 2946 | {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ |
@@ -3047,7 +3059,7 @@ static const struct usb_action MC501CB_Initial[] = { /* 320x240 */ | |||
3047 | {} | 3059 | {} |
3048 | }; | 3060 | }; |
3049 | 3061 | ||
3050 | static const struct usb_action MC501CB_50HZ[] = { | 3062 | static const struct usb_action mc501cb_50HZScale[] = { |
3051 | {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ | 3063 | {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ |
3052 | {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ | 3064 | {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ |
3053 | {0xaa, 0x36, 0x001d}, /* 00,36,1D,aa */ | 3065 | {0xaa, 0x36, 0x001d}, /* 00,36,1D,aa */ |
@@ -3064,7 +3076,7 @@ static const struct usb_action MC501CB_50HZ[] = { | |||
3064 | {} | 3076 | {} |
3065 | }; | 3077 | }; |
3066 | 3078 | ||
3067 | static const struct usb_action MC501CB_50HZScale[] = { | 3079 | static const struct usb_action mc501cb_50HZ[] = { |
3068 | {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ | 3080 | {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ |
3069 | {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ | 3081 | {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ |
3070 | {0xaa, 0x36, 0x003a}, /* 00,36,3A,aa */ | 3082 | {0xaa, 0x36, 0x003a}, /* 00,36,3A,aa */ |
@@ -3081,7 +3093,7 @@ static const struct usb_action MC501CB_50HZScale[] = { | |||
3081 | {} | 3093 | {} |
3082 | }; | 3094 | }; |
3083 | 3095 | ||
3084 | static const struct usb_action MC501CB_60HZ[] = { | 3096 | static const struct usb_action mc501cb_60HZScale[] = { |
3085 | {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ | 3097 | {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ |
3086 | {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ | 3098 | {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ |
3087 | {0xaa, 0x36, 0x0018}, /* 00,36,18,aa */ | 3099 | {0xaa, 0x36, 0x0018}, /* 00,36,18,aa */ |
@@ -3098,7 +3110,7 @@ static const struct usb_action MC501CB_60HZ[] = { | |||
3098 | {} | 3110 | {} |
3099 | }; | 3111 | }; |
3100 | 3112 | ||
3101 | static const struct usb_action MC501CB_60HZScale[] = { | 3113 | static const struct usb_action mc501cb_60HZ[] = { |
3102 | {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ | 3114 | {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ |
3103 | {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ | 3115 | {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ |
3104 | {0xaa, 0x36, 0x0030}, /* 00,36,30,aa */ | 3116 | {0xaa, 0x36, 0x0030}, /* 00,36,30,aa */ |
@@ -3115,7 +3127,7 @@ static const struct usb_action MC501CB_60HZScale[] = { | |||
3115 | {} | 3127 | {} |
3116 | }; | 3128 | }; |
3117 | 3129 | ||
3118 | static const struct usb_action MC501CB_NoFliker[] = { | 3130 | static const struct usb_action mc501cb_NoFlikerScale[] = { |
3119 | {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ | 3131 | {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ |
3120 | {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ | 3132 | {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ |
3121 | {0xaa, 0x36, 0x0018}, /* 00,36,18,aa */ | 3133 | {0xaa, 0x36, 0x0018}, /* 00,36,18,aa */ |
@@ -3132,7 +3144,7 @@ static const struct usb_action MC501CB_NoFliker[] = { | |||
3132 | {} | 3144 | {} |
3133 | }; | 3145 | }; |
3134 | 3146 | ||
3135 | static const struct usb_action MC501CB_NoFlikerScale[] = { | 3147 | static const struct usb_action mc501cb_NoFliker[] = { |
3136 | {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ | 3148 | {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ |
3137 | {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ | 3149 | {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ |
3138 | {0xaa, 0x36, 0x0030}, /* 00,36,30,aa */ | 3150 | {0xaa, 0x36, 0x0030}, /* 00,36,30,aa */ |
@@ -3144,8 +3156,8 @@ static const struct usb_action MC501CB_NoFlikerScale[] = { | |||
3144 | {} | 3156 | {} |
3145 | }; | 3157 | }; |
3146 | 3158 | ||
3147 | /* from zs211.inf - HKR,%OV7620%,Initial - 640x480 */ | 3159 | /* from zs211.inf */ |
3148 | static const struct usb_action OV7620_mode0[] = { | 3160 | static const struct usb_action ov7620_Initial[] = { /* 640x480 */ |
3149 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ | 3161 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ |
3150 | {0xa0, 0x40, ZC3XX_R002_CLOCKSELECT}, /* 00,02,40,cc */ | 3162 | {0xa0, 0x40, ZC3XX_R002_CLOCKSELECT}, /* 00,02,40,cc */ |
3151 | {0xa0, 0x00, ZC3XX_R008_CLOCKSETTING}, /* 00,08,00,cc */ | 3163 | {0xa0, 0x00, ZC3XX_R008_CLOCKSETTING}, /* 00,08,00,cc */ |
@@ -3214,9 +3226,7 @@ static const struct usb_action OV7620_mode0[] = { | |||
3214 | {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,50,cc */ | 3226 | {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,50,cc */ |
3215 | {} | 3227 | {} |
3216 | }; | 3228 | }; |
3217 | 3229 | static const struct usb_action ov7620_InitialScale[] = { /* 320x240 */ | |
3218 | /* from zs211.inf - HKR,%OV7620%,InitialScale - 320x240 */ | ||
3219 | static const struct usb_action OV7620_mode1[] = { | ||
3220 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ | 3230 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ |
3221 | {0xa0, 0x50, ZC3XX_R002_CLOCKSELECT}, /* 00,02,50,cc */ | 3231 | {0xa0, 0x50, ZC3XX_R002_CLOCKSELECT}, /* 00,02,50,cc */ |
3222 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,00,cc */ | 3232 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,00,cc */ |
@@ -3287,9 +3297,7 @@ static const struct usb_action OV7620_mode1[] = { | |||
3287 | {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,50,cc */ | 3297 | {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,50,cc */ |
3288 | {} | 3298 | {} |
3289 | }; | 3299 | }; |
3290 | 3300 | static const struct usb_action ov7620_50HZ[] = { | |
3291 | /* from zs211.inf - HKR,%OV7620%\AE,50HZ */ | ||
3292 | static const struct usb_action OV7620_50HZ[] = { | ||
3293 | {0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */ | 3301 | {0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */ |
3294 | {0xdd, 0x00, 0x0100}, /* 00,01,00,dd */ | 3302 | {0xdd, 0x00, 0x0100}, /* 00,01,00,dd */ |
3295 | {0xaa, 0x2b, 0x0096}, /* 00,2b,96,aa */ | 3303 | {0xaa, 0x2b, 0x0096}, /* 00,2b,96,aa */ |
@@ -3307,9 +3315,7 @@ static const struct usb_action OV7620_50HZ[] = { | |||
3307 | if mode0 (640x480) */ | 3315 | if mode0 (640x480) */ |
3308 | {} | 3316 | {} |
3309 | }; | 3317 | }; |
3310 | 3318 | static const struct usb_action ov7620_60HZ[] = { | |
3311 | /* from zs211.inf - HKR,%OV7620%\AE,60HZ */ | ||
3312 | static const struct usb_action OV7620_60HZ[] = { | ||
3313 | {0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */ | 3319 | {0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */ |
3314 | /* (bug in zs211.inf) */ | 3320 | /* (bug in zs211.inf) */ |
3315 | {0xdd, 0x00, 0x0100}, /* 00,01,00,dd */ | 3321 | {0xdd, 0x00, 0x0100}, /* 00,01,00,dd */ |
@@ -3331,9 +3337,7 @@ static const struct usb_action OV7620_60HZ[] = { | |||
3331 | {0xa1, 0x01, 0x0037}, */ | 3337 | {0xa1, 0x01, 0x0037}, */ |
3332 | {} | 3338 | {} |
3333 | }; | 3339 | }; |
3334 | 3340 | static const struct usb_action ov7620_NoFliker[] = { | |
3335 | /* from zs211.inf - HKR,%OV7620%\AE,NoFliker */ | ||
3336 | static const struct usb_action OV7620_NoFliker[] = { | ||
3337 | {0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */ | 3341 | {0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */ |
3338 | /* (bug in zs211.inf) */ | 3342 | /* (bug in zs211.inf) */ |
3339 | {0xdd, 0x00, 0x0100}, /* 00,01,00,dd */ | 3343 | {0xdd, 0x00, 0x0100}, /* 00,01,00,dd */ |
@@ -3354,7 +3358,7 @@ static const struct usb_action OV7620_NoFliker[] = { | |||
3354 | {} | 3358 | {} |
3355 | }; | 3359 | }; |
3356 | 3360 | ||
3357 | static const struct usb_action ov7630c_Initial[] = { | 3361 | static const struct usb_action ov7630c_InitialScale[] = { |
3358 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, | 3362 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, |
3359 | {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, | 3363 | {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, |
3360 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, | 3364 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, |
@@ -3511,7 +3515,7 @@ static const struct usb_action ov7630c_Initial[] = { | |||
3511 | {} | 3515 | {} |
3512 | }; | 3516 | }; |
3513 | 3517 | ||
3514 | static const struct usb_action ov7630c_InitialScale[] = { | 3518 | static const struct usb_action ov7630c_Initial[] = { |
3515 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, | 3519 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, |
3516 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, | 3520 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, |
3517 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, | 3521 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, |
@@ -3682,7 +3686,7 @@ static const struct usb_action pas106b_Initial_com[] = { | |||
3682 | {} | 3686 | {} |
3683 | }; | 3687 | }; |
3684 | 3688 | ||
3685 | static const struct usb_action pas106b_Initial[] = { /* 176x144 */ | 3689 | static const struct usb_action pas106b_InitialScale[] = { /* 176x144 */ |
3686 | /* JPEG control */ | 3690 | /* JPEG control */ |
3687 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, | 3691 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, |
3688 | /* Sream and Sensor specific */ | 3692 | /* Sream and Sensor specific */ |
@@ -3800,7 +3804,7 @@ static const struct usb_action pas106b_Initial[] = { /* 176x144 */ | |||
3800 | {} | 3804 | {} |
3801 | }; | 3805 | }; |
3802 | 3806 | ||
3803 | static const struct usb_action pas106b_InitialScale[] = { /* 352x288 */ | 3807 | static const struct usb_action pas106b_Initial[] = { /* 352x288 */ |
3804 | /* JPEG control */ | 3808 | /* JPEG control */ |
3805 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, | 3809 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, |
3806 | /* Sream and Sensor specific */ | 3810 | /* Sream and Sensor specific */ |
@@ -3972,10 +3976,10 @@ static const struct usb_action pas106b_NoFliker[] = { | |||
3972 | {} | 3976 | {} |
3973 | }; | 3977 | }; |
3974 | 3978 | ||
3975 | /* from usbvm31b.inf */ | 3979 | /* from lvWIMv.inf 046d:08a2/:08aa 2007/06/03 */ |
3976 | static const struct usb_action pas202b_Initial[] = { /* 640x480 */ | 3980 | static const struct usb_action pas202b_Initial[] = { /* 640x480 */ |
3977 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ | 3981 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ |
3978 | {0xa0, 0x00, ZC3XX_R008_CLOCKSETTING}, /* 00,08,00,cc */ | 3982 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, |
3979 | {0xa0, 0x0e, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0e,cc */ | 3983 | {0xa0, 0x0e, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0e,cc */ |
3980 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, /* 00,02,00,cc */ | 3984 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, /* 00,02,00,cc */ |
3981 | {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */ | 3985 | {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */ |
@@ -4000,7 +4004,7 @@ static const struct usb_action pas202b_Initial[] = { /* 640x480 */ | |||
4000 | {0xaa, 0x09, 0x0006}, /* 00,09,06,aa */ | 4004 | {0xaa, 0x09, 0x0006}, /* 00,09,06,aa */ |
4001 | {0xaa, 0x0a, 0x0001}, /* 00,0a,01,aa */ | 4005 | {0xaa, 0x0a, 0x0001}, /* 00,0a,01,aa */ |
4002 | {0xaa, 0x0b, 0x0001}, /* 00,0b,01,aa */ | 4006 | {0xaa, 0x0b, 0x0001}, /* 00,0b,01,aa */ |
4003 | {0xaa, 0x0c, 0x0008}, /* 00,0c,08,aa */ | 4007 | {0xaa, 0x0c, 0x0006}, |
4004 | {0xaa, 0x0d, 0x0000}, /* 00,0d,00,aa */ | 4008 | {0xaa, 0x0d, 0x0000}, /* 00,0d,00,aa */ |
4005 | {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */ | 4009 | {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */ |
4006 | {0xaa, 0x12, 0x0005}, /* 00,12,05,aa */ | 4010 | {0xaa, 0x12, 0x0005}, /* 00,12,05,aa */ |
@@ -4019,13 +4023,13 @@ static const struct usb_action pas202b_Initial[] = { /* 640x480 */ | |||
4019 | }; | 4023 | }; |
4020 | static const struct usb_action pas202b_InitialScale[] = { /* 320x240 */ | 4024 | static const struct usb_action pas202b_InitialScale[] = { /* 320x240 */ |
4021 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ | 4025 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ |
4022 | {0xa0, 0x00, ZC3XX_R008_CLOCKSETTING}, /* 00,08,00,cc */ | 4026 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, |
4023 | {0xa0, 0x0e, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0e,cc */ | 4027 | {0xa0, 0x0e, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0e,cc */ |
4024 | {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc */ | 4028 | {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc */ |
4025 | {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */ | 4029 | {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */ |
4026 | {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */ | 4030 | {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */ |
4027 | {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */ | 4031 | {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */ |
4028 | {0xa0, 0xd0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,d0,cc */ | 4032 | {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, |
4029 | {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */ | 4033 | {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */ |
4030 | {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */ | 4034 | {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */ |
4031 | {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */ | 4035 | {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */ |
@@ -4035,7 +4039,7 @@ static const struct usb_action pas202b_InitialScale[] = { /* 320x240 */ | |||
4035 | {0xa0, 0x08, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,08,cc */ | 4039 | {0xa0, 0x08, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,08,cc */ |
4036 | {0xa0, 0x02, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,02,cc */ | 4040 | {0xa0, 0x02, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,02,cc */ |
4037 | {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH}, /* 00,9b,01,cc */ | 4041 | {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH}, /* 00,9b,01,cc */ |
4038 | {0xa0, 0xd8, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,d8,cc */ | 4042 | {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW}, |
4039 | {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH}, /* 00,9d,02,cc */ | 4043 | {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH}, /* 00,9d,02,cc */ |
4040 | {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,88,cc */ | 4044 | {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,88,cc */ |
4041 | {0xaa, 0x02, 0x0002}, /* 00,02,02,aa */ | 4045 | {0xaa, 0x02, 0x0002}, /* 00,02,02,aa */ |
@@ -4044,7 +4048,7 @@ static const struct usb_action pas202b_InitialScale[] = { /* 320x240 */ | |||
4044 | {0xaa, 0x09, 0x0006}, /* 00,09,06,aa */ | 4048 | {0xaa, 0x09, 0x0006}, /* 00,09,06,aa */ |
4045 | {0xaa, 0x0a, 0x0001}, /* 00,0a,01,aa */ | 4049 | {0xaa, 0x0a, 0x0001}, /* 00,0a,01,aa */ |
4046 | {0xaa, 0x0b, 0x0001}, /* 00,0b,01,aa */ | 4050 | {0xaa, 0x0b, 0x0001}, /* 00,0b,01,aa */ |
4047 | {0xaa, 0x0c, 0x0008}, /* 00,0c,08,aa */ | 4051 | {0xaa, 0x0c, 0x0006}, |
4048 | {0xaa, 0x0d, 0x0000}, /* 00,0d,00,aa */ | 4052 | {0xaa, 0x0d, 0x0000}, /* 00,0d,00,aa */ |
4049 | {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */ | 4053 | {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */ |
4050 | {0xaa, 0x12, 0x0005}, /* 00,12,05,aa */ | 4054 | {0xaa, 0x12, 0x0005}, /* 00,12,05,aa */ |
@@ -4059,6 +4063,8 @@ static const struct usb_action pas202b_InitialScale[] = { /* 320x240 */ | |||
4059 | {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */ | 4063 | {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */ |
4060 | {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */ | 4064 | {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */ |
4061 | {0xa0, 0x70, ZC3XX_R18D_YTARGET}, /* 01,8d,70,cc */ | 4065 | {0xa0, 0x70, ZC3XX_R18D_YTARGET}, /* 01,8d,70,cc */ |
4066 | {0xa0, 0xff, ZC3XX_R097_WINYSTARTHIGH}, | ||
4067 | {0xa0, 0xfe, ZC3XX_R098_WINYSTARTLOW}, | ||
4062 | {} | 4068 | {} |
4063 | }; | 4069 | }; |
4064 | static const struct usb_action pas202b_50HZ[] = { | 4070 | static const struct usb_action pas202b_50HZ[] = { |
@@ -4066,22 +4072,22 @@ static const struct usb_action pas202b_50HZ[] = { | |||
4066 | {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */ | 4072 | {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */ |
4067 | {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */ | 4073 | {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */ |
4068 | {0xaa, 0x20, 0x0002}, /* 00,20,02,aa */ | 4074 | {0xaa, 0x20, 0x0002}, /* 00,20,02,aa */ |
4069 | {0xaa, 0x21, 0x0068}, /* 00,21,68,aa */ | 4075 | {0xaa, 0x21, 0x001b}, |
4070 | {0xaa, 0x03, 0x0044}, /* 00,03,44,aa */ | 4076 | {0xaa, 0x03, 0x0044}, /* 00,03,44,aa */ |
4071 | {0xaa, 0x04, 0x0009}, /* 00,04,09,aa */ | 4077 | {0xaa, 0x04, 0x0008}, |
4072 | {0xaa, 0x05, 0x0028}, /* 00,05,28,aa */ | 4078 | {0xaa, 0x05, 0x001b}, |
4073 | {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */ | 4079 | {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */ |
4074 | {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */ | 4080 | {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */ |
4075 | {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,14,cc */ | 4081 | {0xa0, 0x1c, ZC3XX_R1A9_DIGITALLIMITDIFF}, |
4076 | {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */ | 4082 | {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */ |
4077 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ | 4083 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ |
4078 | {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,07,cc */ | 4084 | {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID}, |
4079 | {0xa0, 0xd2, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,d2,cc */ | 4085 | {0xa0, 0x1b, ZC3XX_R192_EXPOSURELIMITLOW}, |
4080 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ | 4086 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ |
4081 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ | 4087 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ |
4082 | {0xa0, 0x4d, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,4d,cc */ | 4088 | {0xa0, 0x4d, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,4d,cc */ |
4083 | {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ | 4089 | {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, |
4084 | {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ | 4090 | {0xa0, 0x1b, ZC3XX_R18F_AEUNFREEZE}, |
4085 | {0xa0, 0x44, ZC3XX_R01D_HSYNC_0}, /* 00,1d,44,cc */ | 4091 | {0xa0, 0x44, ZC3XX_R01D_HSYNC_0}, /* 00,1d,44,cc */ |
4086 | {0xa0, 0x6f, ZC3XX_R01E_HSYNC_1}, /* 00,1e,6f,cc */ | 4092 | {0xa0, 0x6f, ZC3XX_R01E_HSYNC_1}, /* 00,1e,6f,cc */ |
4087 | {0xa0, 0xad, ZC3XX_R01F_HSYNC_2}, /* 00,1f,ad,cc */ | 4093 | {0xa0, 0xad, ZC3XX_R01F_HSYNC_2}, /* 00,1f,ad,cc */ |
@@ -4094,23 +4100,23 @@ static const struct usb_action pas202b_50HZScale[] = { | |||
4094 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ | 4100 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ |
4095 | {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */ | 4101 | {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */ |
4096 | {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */ | 4102 | {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */ |
4097 | {0xaa, 0x20, 0x0002}, /* 00,20,02,aa */ | 4103 | {0xaa, 0x20, 0x0004}, |
4098 | {0xaa, 0x21, 0x006c}, /* 00,21,6c,aa */ | 4104 | {0xaa, 0x21, 0x003d}, |
4099 | {0xaa, 0x03, 0x0041}, /* 00,03,41,aa */ | 4105 | {0xaa, 0x03, 0x0041}, /* 00,03,41,aa */ |
4100 | {0xaa, 0x04, 0x0009}, /* 00,04,09,aa */ | 4106 | {0xaa, 0x04, 0x0010}, |
4101 | {0xaa, 0x05, 0x002c}, /* 00,05,2c,aa */ | 4107 | {0xaa, 0x05, 0x003d}, |
4102 | {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */ | 4108 | {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */ |
4103 | {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */ | 4109 | {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */ |
4104 | {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,14,cc */ | 4110 | {0xa0, 0x1c, ZC3XX_R1A9_DIGITALLIMITDIFF}, |
4105 | {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */ | 4111 | {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */ |
4106 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ | 4112 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ |
4107 | {0xa0, 0x0f, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,0f,cc */ | 4113 | {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, |
4108 | {0xa0, 0xbe, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,be,cc */ | 4114 | {0xa0, 0x3d, ZC3XX_R192_EXPOSURELIMITLOW}, |
4109 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ | 4115 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ |
4110 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ | 4116 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ |
4111 | {0xa0, 0x9b, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,9b,cc */ | 4117 | {0xa0, 0x9b, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,9b,cc */ |
4112 | {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ | 4118 | {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, |
4113 | {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ | 4119 | {0xa0, 0x1b, ZC3XX_R18F_AEUNFREEZE}, |
4114 | {0xa0, 0x41, ZC3XX_R01D_HSYNC_0}, /* 00,1d,41,cc */ | 4120 | {0xa0, 0x41, ZC3XX_R01D_HSYNC_0}, /* 00,1d,41,cc */ |
4115 | {0xa0, 0x6f, ZC3XX_R01E_HSYNC_1}, /* 00,1e,6f,cc */ | 4121 | {0xa0, 0x6f, ZC3XX_R01E_HSYNC_1}, /* 00,1e,6f,cc */ |
4116 | {0xa0, 0xad, ZC3XX_R01F_HSYNC_2}, /* 00,1f,ad,cc */ | 4122 | {0xa0, 0xad, ZC3XX_R01F_HSYNC_2}, /* 00,1f,ad,cc */ |
@@ -4130,16 +4136,16 @@ static const struct usb_action pas202b_60HZ[] = { | |||
4130 | {0xaa, 0x05, 0x0000}, /* 00,05,00,aa */ | 4136 | {0xaa, 0x05, 0x0000}, /* 00,05,00,aa */ |
4131 | {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */ | 4137 | {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */ |
4132 | {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */ | 4138 | {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */ |
4133 | {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,14,cc */ | 4139 | {0xa0, 0x1c, ZC3XX_R1A9_DIGITALLIMITDIFF}, |
4134 | {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */ | 4140 | {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */ |
4135 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ | 4141 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ |
4136 | {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,07,cc */ | 4142 | {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID}, |
4137 | {0xa0, 0xc0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,c0,cc */ | 4143 | {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW}, |
4138 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ | 4144 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ |
4139 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ | 4145 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ |
4140 | {0xa0, 0x40, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,40,cc */ | 4146 | {0xa0, 0x40, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,40,cc */ |
4141 | {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ | 4147 | {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, |
4142 | {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ | 4148 | {0xa0, 0x1b, ZC3XX_R18F_AEUNFREEZE}, |
4143 | {0xa0, 0x45, ZC3XX_R01D_HSYNC_0}, /* 00,1d,45,cc */ | 4149 | {0xa0, 0x45, ZC3XX_R01D_HSYNC_0}, /* 00,1d,45,cc */ |
4144 | {0xa0, 0x8e, ZC3XX_R01E_HSYNC_1}, /* 00,1e,8e,cc */ | 4150 | {0xa0, 0x8e, ZC3XX_R01E_HSYNC_1}, /* 00,1e,8e,cc */ |
4145 | {0xa0, 0xc1, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c1,cc */ | 4151 | {0xa0, 0xc1, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c1,cc */ |
@@ -4152,23 +4158,23 @@ static const struct usb_action pas202b_60HZScale[] = { | |||
4152 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ | 4158 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ |
4153 | {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */ | 4159 | {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */ |
4154 | {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */ | 4160 | {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */ |
4155 | {0xaa, 0x20, 0x0002}, /* 00,20,02,aa */ | 4161 | {0xaa, 0x20, 0x0004}, |
4156 | {0xaa, 0x21, 0x0004}, /* 00,21,04,aa */ | 4162 | {0xaa, 0x21, 0x0008}, |
4157 | {0xaa, 0x03, 0x0042}, /* 00,03,42,aa */ | 4163 | {0xaa, 0x03, 0x0042}, /* 00,03,42,aa */ |
4158 | {0xaa, 0x04, 0x0008}, /* 00,04,08,aa */ | 4164 | {0xaa, 0x04, 0x0010}, |
4159 | {0xaa, 0x05, 0x0004}, /* 00,05,04,aa */ | 4165 | {0xaa, 0x05, 0x0008}, |
4160 | {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */ | 4166 | {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */ |
4161 | {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */ | 4167 | {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */ |
4162 | {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,14,cc */ | 4168 | {0xa0, 0x1c, ZC3XX_R1A9_DIGITALLIMITDIFF}, |
4163 | {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */ | 4169 | {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */ |
4164 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ | 4170 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ |
4165 | {0xa0, 0x0f, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,0f,cc */ | 4171 | {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, |
4166 | {0xa0, 0x9f, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,9f,cc */ | 4172 | {0xa0, 0x08, ZC3XX_R192_EXPOSURELIMITLOW}, |
4167 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ | 4173 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ |
4168 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ | 4174 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ |
4169 | {0xa0, 0x81, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,81,cc */ | 4175 | {0xa0, 0x81, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,81,cc */ |
4170 | {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ | 4176 | {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, |
4171 | {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ | 4177 | {0xa0, 0x1b, ZC3XX_R18F_AEUNFREEZE}, |
4172 | {0xa0, 0x42, ZC3XX_R01D_HSYNC_0}, /* 00,1d,42,cc */ | 4178 | {0xa0, 0x42, ZC3XX_R01D_HSYNC_0}, /* 00,1d,42,cc */ |
4173 | {0xa0, 0x6f, ZC3XX_R01E_HSYNC_1}, /* 00,1e,6f,cc */ | 4179 | {0xa0, 0x6f, ZC3XX_R01E_HSYNC_1}, /* 00,1e,6f,cc */ |
4174 | {0xa0, 0xaf, ZC3XX_R01F_HSYNC_2}, /* 00,1f,af,cc */ | 4180 | {0xa0, 0xaf, ZC3XX_R01F_HSYNC_2}, /* 00,1f,af,cc */ |
@@ -4182,22 +4188,22 @@ static const struct usb_action pas202b_NoFliker[] = { | |||
4182 | {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */ | 4188 | {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */ |
4183 | {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */ | 4189 | {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */ |
4184 | {0xaa, 0x20, 0x0002}, /* 00,20,02,aa */ | 4190 | {0xaa, 0x20, 0x0002}, /* 00,20,02,aa */ |
4185 | {0xaa, 0x21, 0x0020}, /* 00,21,20,aa */ | 4191 | {0xaa, 0x21, 0x0006}, |
4186 | {0xaa, 0x03, 0x0040}, /* 00,03,40,aa */ | 4192 | {0xaa, 0x03, 0x0040}, /* 00,03,40,aa */ |
4187 | {0xaa, 0x04, 0x0008}, /* 00,04,08,aa */ | 4193 | {0xaa, 0x04, 0x0008}, /* 00,04,08,aa */ |
4188 | {0xaa, 0x05, 0x0020}, /* 00,05,20,aa */ | 4194 | {0xaa, 0x05, 0x0006}, |
4189 | {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */ | 4195 | {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */ |
4190 | {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */ | 4196 | {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */ |
4191 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ | 4197 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ |
4192 | {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,07,cc */ | 4198 | {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID}, |
4193 | {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,f0,cc */ | 4199 | {0xa0, 0x06, ZC3XX_R192_EXPOSURELIMITLOW}, |
4194 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ | 4200 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ |
4195 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ | 4201 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ |
4196 | {0xa0, 0x02, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,02,cc */ | 4202 | {0xa0, 0x01, ZC3XX_R197_ANTIFLICKERLOW}, |
4197 | {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ | 4203 | {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ |
4198 | {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ | 4204 | {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ |
4199 | {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */ | 4205 | {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */ |
4200 | {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */ | 4206 | {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, |
4201 | {0xa0, 0x40, ZC3XX_R01D_HSYNC_0}, /* 00,1d,40,cc */ | 4207 | {0xa0, 0x40, ZC3XX_R01D_HSYNC_0}, /* 00,1d,40,cc */ |
4202 | {0xa0, 0x60, ZC3XX_R01E_HSYNC_1}, /* 00,1e,60,cc */ | 4208 | {0xa0, 0x60, ZC3XX_R01E_HSYNC_1}, /* 00,1e,60,cc */ |
4203 | {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, /* 00,1f,90,cc */ | 4209 | {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, /* 00,1f,90,cc */ |
@@ -4210,23 +4216,23 @@ static const struct usb_action pas202b_NoFlikerScale[] = { | |||
4210 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ | 4216 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ |
4211 | {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */ | 4217 | {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */ |
4212 | {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */ | 4218 | {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */ |
4213 | {0xaa, 0x20, 0x0002}, /* 00,20,02,aa */ | 4219 | {0xaa, 0x20, 0x0004}, |
4214 | {0xaa, 0x21, 0x0010}, /* 00,21,10,aa */ | 4220 | {0xaa, 0x21, 0x000c}, |
4215 | {0xaa, 0x03, 0x0040}, /* 00,03,40,aa */ | 4221 | {0xaa, 0x03, 0x0040}, /* 00,03,40,aa */ |
4216 | {0xaa, 0x04, 0x0008}, /* 00,04,08,aa */ | 4222 | {0xaa, 0x04, 0x0010}, |
4217 | {0xaa, 0x05, 0x0010}, /* 00,05,10,aa */ | 4223 | {0xaa, 0x05, 0x000c}, |
4218 | {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */ | 4224 | {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */ |
4219 | {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */ | 4225 | {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */ |
4220 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ | 4226 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ |
4221 | {0xa0, 0x0f, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,0f,cc */ | 4227 | {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, |
4222 | {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,f0,cc */ | 4228 | {0xa0, 0x0c, ZC3XX_R192_EXPOSURELIMITLOW}, |
4223 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ | 4229 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ |
4224 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ | 4230 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ |
4225 | {0xa0, 0x02, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,02,cc */ | 4231 | {0xa0, 0x02, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,02,cc */ |
4226 | {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ | 4232 | {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ |
4227 | {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ | 4233 | {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ |
4228 | {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */ | 4234 | {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */ |
4229 | {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */ | 4235 | {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, |
4230 | {0xa0, 0x40, ZC3XX_R01D_HSYNC_0}, /* 00,1d,40,cc */ | 4236 | {0xa0, 0x40, ZC3XX_R01D_HSYNC_0}, /* 00,1d,40,cc */ |
4231 | {0xa0, 0x60, ZC3XX_R01E_HSYNC_1}, /* 00,1e,60,cc */ | 4237 | {0xa0, 0x60, ZC3XX_R01E_HSYNC_1}, /* 00,1e,60,cc */ |
4232 | {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, /* 00,1f,90,cc */ | 4238 | {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, /* 00,1f,90,cc */ |
@@ -4713,8 +4719,8 @@ static const struct usb_action pb0330_NoFlikerScale[] = { | |||
4713 | {} | 4719 | {} |
4714 | }; | 4720 | }; |
4715 | 4721 | ||
4716 | /* from oem9.inf - HKR,%PO2030%,Initial - 640x480 - (close to CS2102) */ | 4722 | /* from oem9.inf */ |
4717 | static const struct usb_action PO2030_mode0[] = { | 4723 | static const struct usb_action po2030_Initial[] = { /* 640x480 */ |
4718 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ | 4724 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ |
4719 | {0xa0, 0x04, ZC3XX_R002_CLOCKSELECT}, /* 00,02,04,cc */ | 4725 | {0xa0, 0x04, ZC3XX_R002_CLOCKSELECT}, /* 00,02,04,cc */ |
4720 | {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ | 4726 | {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ |
@@ -4790,8 +4796,8 @@ static const struct usb_action PO2030_mode0[] = { | |||
4790 | {} | 4796 | {} |
4791 | }; | 4797 | }; |
4792 | 4798 | ||
4793 | /* from oem9.inf - HKR,%PO2030%,InitialScale - 320x240 */ | 4799 | /* from oem9.inf */ |
4794 | static const struct usb_action PO2030_mode1[] = { | 4800 | static const struct usb_action po2030_InitialScale[] = { /* 320x240 */ |
4795 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ | 4801 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ |
4796 | {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc */ | 4802 | {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc */ |
4797 | {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ | 4803 | {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ |
@@ -4867,7 +4873,7 @@ static const struct usb_action PO2030_mode1[] = { | |||
4867 | {} | 4873 | {} |
4868 | }; | 4874 | }; |
4869 | 4875 | ||
4870 | static const struct usb_action PO2030_50HZ[] = { | 4876 | static const struct usb_action po2030_50HZ[] = { |
4871 | {0xaa, 0x8d, 0x0008}, /* 00,8d,08,aa */ | 4877 | {0xaa, 0x8d, 0x0008}, /* 00,8d,08,aa */ |
4872 | {0xaa, 0x1a, 0x0001}, /* 00,1a,01,aa */ | 4878 | {0xaa, 0x1a, 0x0001}, /* 00,1a,01,aa */ |
4873 | {0xaa, 0x1b, 0x000a}, /* 00,1b,0a,aa */ | 4879 | {0xaa, 0x1b, 0x000a}, /* 00,1b,0a,aa */ |
@@ -4889,7 +4895,7 @@ static const struct usb_action PO2030_50HZ[] = { | |||
4889 | {} | 4895 | {} |
4890 | }; | 4896 | }; |
4891 | 4897 | ||
4892 | static const struct usb_action PO2030_60HZ[] = { | 4898 | static const struct usb_action po2030_60HZ[] = { |
4893 | {0xaa, 0x8d, 0x0008}, /* 00,8d,08,aa */ | 4899 | {0xaa, 0x8d, 0x0008}, /* 00,8d,08,aa */ |
4894 | {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa */ | 4900 | {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa */ |
4895 | {0xaa, 0x1b, 0x00de}, /* 00,1b,de,aa */ | 4901 | {0xaa, 0x1b, 0x00de}, /* 00,1b,de,aa */ |
@@ -4912,7 +4918,7 @@ static const struct usb_action PO2030_60HZ[] = { | |||
4912 | {} | 4918 | {} |
4913 | }; | 4919 | }; |
4914 | 4920 | ||
4915 | static const struct usb_action PO2030_NoFliker[] = { | 4921 | static const struct usb_action po2030_NoFliker[] = { |
4916 | {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */ | 4922 | {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */ |
4917 | {0xaa, 0x8d, 0x000d}, /* 00,8d,0d,aa */ | 4923 | {0xaa, 0x8d, 0x000d}, /* 00,8d,0d,aa */ |
4918 | {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa */ | 4924 | {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa */ |
@@ -4924,7 +4930,7 @@ static const struct usb_action PO2030_NoFliker[] = { | |||
4924 | }; | 4930 | }; |
4925 | 4931 | ||
4926 | /* TEST */ | 4932 | /* TEST */ |
4927 | static const struct usb_action tas5130CK_Initial[] = { | 4933 | static const struct usb_action tas5130cK_InitialScale[] = { |
4928 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, | 4934 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, |
4929 | {0xa0, 0x01, 0x003b}, | 4935 | {0xa0, 0x01, 0x003b}, |
4930 | {0xa0, 0x0e, 0x003a}, | 4936 | {0xa0, 0x0e, 0x003a}, |
@@ -5127,7 +5133,7 @@ static const struct usb_action tas5130CK_Initial[] = { | |||
5127 | {} | 5133 | {} |
5128 | }; | 5134 | }; |
5129 | 5135 | ||
5130 | static const struct usb_action tas5130CK_InitialScale[] = { | 5136 | static const struct usb_action tas5130cK_Initial[] = { |
5131 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, | 5137 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, |
5132 | {0xa0, 0x01, 0x003b}, | 5138 | {0xa0, 0x01, 0x003b}, |
5133 | {0xa0, 0x0e, 0x003a}, | 5139 | {0xa0, 0x0e, 0x003a}, |
@@ -5560,7 +5566,7 @@ static const struct usb_action tas5130cxx_NoFlikerScale[] = { | |||
5560 | {} | 5566 | {} |
5561 | }; | 5567 | }; |
5562 | 5568 | ||
5563 | static const struct usb_action tas5130c_vf0250_Initial[] = { | 5569 | static const struct usb_action tas5130c_vf0250_InitialScale[] = { |
5564 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc, */ | 5570 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc, */ |
5565 | {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, /* 00,08,02,cc, */ | 5571 | {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, /* 00,08,02,cc, */ |
5566 | {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc, */ | 5572 | {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc, */ |
@@ -5627,7 +5633,7 @@ static const struct usb_action tas5130c_vf0250_Initial[] = { | |||
5627 | {} | 5633 | {} |
5628 | }; | 5634 | }; |
5629 | 5635 | ||
5630 | static const struct usb_action tas5130c_vf0250_InitialScale[] = { | 5636 | static const struct usb_action tas5130c_vf0250_Initial[] = { |
5631 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc, */ | 5637 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc, */ |
5632 | {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, /* 00,08,02,cc, */ | 5638 | {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, /* 00,08,02,cc, */ |
5633 | {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc, */ | 5639 | {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc, */ |
@@ -5692,8 +5698,7 @@ static const struct usb_action tas5130c_vf0250_InitialScale[] = { | |||
5692 | {0xa0, 0x65, ZC3XX_R118_BGAIN}, /* 01,18,65,cc */ | 5698 | {0xa0, 0x65, ZC3XX_R118_BGAIN}, /* 01,18,65,cc */ |
5693 | {} | 5699 | {} |
5694 | }; | 5700 | }; |
5695 | /* "50HZ" light frequency banding filter */ | 5701 | static const struct usb_action tas5130c_vf0250_50HZScale[] = { |
5696 | static const struct usb_action tas5130c_vf0250_50HZ[] = { | ||
5697 | {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ | 5702 | {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ |
5698 | {0xaa, 0x83, 0x0001}, /* 00,83,01,aa */ | 5703 | {0xaa, 0x83, 0x0001}, /* 00,83,01,aa */ |
5699 | {0xaa, 0x84, 0x00aa}, /* 00,84,aa,aa */ | 5704 | {0xaa, 0x84, 0x00aa}, /* 00,84,aa,aa */ |
@@ -5717,8 +5722,7 @@ static const struct usb_action tas5130c_vf0250_50HZ[] = { | |||
5717 | {} | 5722 | {} |
5718 | }; | 5723 | }; |
5719 | 5724 | ||
5720 | /* "50HZScale" light frequency banding filter */ | 5725 | static const struct usb_action tas5130c_vf0250_50HZ[] = { |
5721 | static const struct usb_action tas5130c_vf0250_50HZScale[] = { | ||
5722 | {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ | 5726 | {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ |
5723 | {0xaa, 0x83, 0x0003}, /* 00,83,03,aa */ | 5727 | {0xaa, 0x83, 0x0003}, /* 00,83,03,aa */ |
5724 | {0xaa, 0x84, 0x0054}, /* 00,84,54,aa */ | 5728 | {0xaa, 0x84, 0x0054}, /* 00,84,54,aa */ |
@@ -5742,8 +5746,7 @@ static const struct usb_action tas5130c_vf0250_50HZScale[] = { | |||
5742 | {} | 5746 | {} |
5743 | }; | 5747 | }; |
5744 | 5748 | ||
5745 | /* "60HZ" light frequency banding filter */ | 5749 | static const struct usb_action tas5130c_vf0250_60HZScale[] = { |
5746 | static const struct usb_action tas5130c_vf0250_60HZ[] = { | ||
5747 | {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ | 5750 | {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ |
5748 | {0xaa, 0x83, 0x0001}, /* 00,83,01,aa */ | 5751 | {0xaa, 0x83, 0x0001}, /* 00,83,01,aa */ |
5749 | {0xaa, 0x84, 0x0062}, /* 00,84,62,aa */ | 5752 | {0xaa, 0x84, 0x0062}, /* 00,84,62,aa */ |
@@ -5767,8 +5770,7 @@ static const struct usb_action tas5130c_vf0250_60HZ[] = { | |||
5767 | {} | 5770 | {} |
5768 | }; | 5771 | }; |
5769 | 5772 | ||
5770 | /* "60HZScale" light frequency banding ilter */ | 5773 | static const struct usb_action tas5130c_vf0250_60HZ[] = { |
5771 | static const struct usb_action tas5130c_vf0250_60HZScale[] = { | ||
5772 | {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ | 5774 | {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ |
5773 | {0xaa, 0x83, 0x0002}, /* 00,83,02,aa */ | 5775 | {0xaa, 0x83, 0x0002}, /* 00,83,02,aa */ |
5774 | {0xaa, 0x84, 0x00c4}, /* 00,84,c4,aa */ | 5776 | {0xaa, 0x84, 0x00c4}, /* 00,84,c4,aa */ |
@@ -5792,8 +5794,7 @@ static const struct usb_action tas5130c_vf0250_60HZScale[] = { | |||
5792 | {} | 5794 | {} |
5793 | }; | 5795 | }; |
5794 | 5796 | ||
5795 | /* "NoFliker" light frequency banding flter */ | 5797 | static const struct usb_action tas5130c_vf0250_NoFlikerScale[] = { |
5796 | static const struct usb_action tas5130c_vf0250_NoFliker[] = { | ||
5797 | {0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc, */ | 5798 | {0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc, */ |
5798 | {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ | 5799 | {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ |
5799 | {0xaa, 0x83, 0x0000}, /* 00,83,00,aa */ | 5800 | {0xaa, 0x83, 0x0000}, /* 00,83,00,aa */ |
@@ -5815,8 +5816,7 @@ static const struct usb_action tas5130c_vf0250_NoFliker[] = { | |||
5815 | {} | 5816 | {} |
5816 | }; | 5817 | }; |
5817 | 5818 | ||
5818 | /* "NoFlikerScale" light frequency banding filter */ | 5819 | static const struct usb_action tas5130c_vf0250_NoFliker[] = { |
5819 | static const struct usb_action tas5130c_vf0250_NoFlikerScale[] = { | ||
5820 | {0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc, */ | 5820 | {0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc, */ |
5821 | {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ | 5821 | {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ |
5822 | {0xaa, 0x83, 0x0000}, /* 00,83,00,aa */ | 5822 | {0xaa, 0x83, 0x0000}, /* 00,83,00,aa */ |
@@ -5839,7 +5839,7 @@ static const struct usb_action tas5130c_vf0250_NoFlikerScale[] = { | |||
5839 | }; | 5839 | }; |
5840 | 5840 | ||
5841 | static u8 reg_r_i(struct gspca_dev *gspca_dev, | 5841 | static u8 reg_r_i(struct gspca_dev *gspca_dev, |
5842 | __u16 index) | 5842 | u16 index) |
5843 | { | 5843 | { |
5844 | usb_control_msg(gspca_dev->dev, | 5844 | usb_control_msg(gspca_dev->dev, |
5845 | usb_rcvctrlpipe(gspca_dev->dev, 0), | 5845 | usb_rcvctrlpipe(gspca_dev->dev, 0), |
@@ -5852,7 +5852,7 @@ static u8 reg_r_i(struct gspca_dev *gspca_dev, | |||
5852 | } | 5852 | } |
5853 | 5853 | ||
5854 | static u8 reg_r(struct gspca_dev *gspca_dev, | 5854 | static u8 reg_r(struct gspca_dev *gspca_dev, |
5855 | __u16 index) | 5855 | u16 index) |
5856 | { | 5856 | { |
5857 | u8 ret; | 5857 | u8 ret; |
5858 | 5858 | ||
@@ -5862,8 +5862,8 @@ static u8 reg_r(struct gspca_dev *gspca_dev, | |||
5862 | } | 5862 | } |
5863 | 5863 | ||
5864 | static void reg_w_i(struct usb_device *dev, | 5864 | static void reg_w_i(struct usb_device *dev, |
5865 | __u8 value, | 5865 | u8 value, |
5866 | __u16 index) | 5866 | u16 index) |
5867 | { | 5867 | { |
5868 | usb_control_msg(dev, | 5868 | usb_control_msg(dev, |
5869 | usb_sndctrlpipe(dev, 0), | 5869 | usb_sndctrlpipe(dev, 0), |
@@ -5874,18 +5874,18 @@ static void reg_w_i(struct usb_device *dev, | |||
5874 | } | 5874 | } |
5875 | 5875 | ||
5876 | static void reg_w(struct usb_device *dev, | 5876 | static void reg_w(struct usb_device *dev, |
5877 | __u8 value, | 5877 | u8 value, |
5878 | __u16 index) | 5878 | u16 index) |
5879 | { | 5879 | { |
5880 | PDEBUG(D_USBO, "reg w [%04x] = %02x", index, value); | 5880 | PDEBUG(D_USBO, "reg w [%04x] = %02x", index, value); |
5881 | reg_w_i(dev, value, index); | 5881 | reg_w_i(dev, value, index); |
5882 | } | 5882 | } |
5883 | 5883 | ||
5884 | static __u16 i2c_read(struct gspca_dev *gspca_dev, | 5884 | static u16 i2c_read(struct gspca_dev *gspca_dev, |
5885 | __u8 reg) | 5885 | u8 reg) |
5886 | { | 5886 | { |
5887 | __u8 retbyte; | 5887 | u8 retbyte; |
5888 | __u16 retval; | 5888 | u16 retval; |
5889 | 5889 | ||
5890 | reg_w_i(gspca_dev->dev, reg, 0x0092); | 5890 | reg_w_i(gspca_dev->dev, reg, 0x0092); |
5891 | reg_w_i(gspca_dev->dev, 0x02, 0x0090); /* <- read command */ | 5891 | reg_w_i(gspca_dev->dev, 0x02, 0x0090); /* <- read command */ |
@@ -5900,12 +5900,12 @@ static __u16 i2c_read(struct gspca_dev *gspca_dev, | |||
5900 | return retval; | 5900 | return retval; |
5901 | } | 5901 | } |
5902 | 5902 | ||
5903 | static __u8 i2c_write(struct gspca_dev *gspca_dev, | 5903 | static u8 i2c_write(struct gspca_dev *gspca_dev, |
5904 | __u8 reg, | 5904 | u8 reg, |
5905 | __u8 valL, | 5905 | u8 valL, |
5906 | __u8 valH) | 5906 | u8 valH) |
5907 | { | 5907 | { |
5908 | __u8 retbyte; | 5908 | u8 retbyte; |
5909 | 5909 | ||
5910 | reg_w_i(gspca_dev->dev, reg, 0x92); | 5910 | reg_w_i(gspca_dev->dev, reg, 0x92); |
5911 | reg_w_i(gspca_dev->dev, valL, 0x93); | 5911 | reg_w_i(gspca_dev->dev, valL, 0x93); |
@@ -5957,24 +5957,24 @@ static void setmatrix(struct gspca_dev *gspca_dev) | |||
5957 | { | 5957 | { |
5958 | struct sd *sd = (struct sd *) gspca_dev; | 5958 | struct sd *sd = (struct sd *) gspca_dev; |
5959 | int i; | 5959 | int i; |
5960 | const __u8 *matrix; | 5960 | const u8 *matrix; |
5961 | static const u8 adcm2700_matrix[9] = | 5961 | static const u8 adcm2700_matrix[9] = |
5962 | /* {0x66, 0xed, 0xed, 0xed, 0x66, 0xed, 0xed, 0xed, 0x66}; */ | 5962 | /* {0x66, 0xed, 0xed, 0xed, 0x66, 0xed, 0xed, 0xed, 0x66}; */ |
5963 | /*ms-win*/ | 5963 | /*ms-win*/ |
5964 | {0x74, 0xed, 0xed, 0xed, 0x74, 0xed, 0xed, 0xed, 0x74}; | 5964 | {0x74, 0xed, 0xed, 0xed, 0x74, 0xed, 0xed, 0xed, 0x74}; |
5965 | static const __u8 gc0305_matrix[9] = | 5965 | static const u8 gc0305_matrix[9] = |
5966 | {0x50, 0xf8, 0xf8, 0xf8, 0x50, 0xf8, 0xf8, 0xf8, 0x50}; | 5966 | {0x50, 0xf8, 0xf8, 0xf8, 0x50, 0xf8, 0xf8, 0xf8, 0x50}; |
5967 | static const __u8 ov7620_matrix[9] = | 5967 | static const u8 ov7620_matrix[9] = |
5968 | {0x58, 0xf4, 0xf4, 0xf4, 0x58, 0xf4, 0xf4, 0xf4, 0x58}; | 5968 | {0x58, 0xf4, 0xf4, 0xf4, 0x58, 0xf4, 0xf4, 0xf4, 0x58}; |
5969 | static const __u8 pas202b_matrix[9] = | 5969 | static const u8 pas202b_matrix[9] = |
5970 | {0x4c, 0xf5, 0xff, 0xf9, 0x51, 0xf5, 0xfb, 0xed, 0x5f}; | 5970 | {0x4c, 0xf5, 0xff, 0xf9, 0x51, 0xf5, 0xfb, 0xed, 0x5f}; |
5971 | static const __u8 po2030_matrix[9] = | 5971 | static const u8 po2030_matrix[9] = |
5972 | {0x60, 0xf0, 0xf0, 0xf0, 0x60, 0xf0, 0xf0, 0xf0, 0x60}; | 5972 | {0x60, 0xf0, 0xf0, 0xf0, 0x60, 0xf0, 0xf0, 0xf0, 0x60}; |
5973 | static const u8 tas5130c_matrix[9] = | 5973 | static const u8 tas5130c_matrix[9] = |
5974 | {0x68, 0xec, 0xec, 0xec, 0x68, 0xec, 0xec, 0xec, 0x68}; | 5974 | {0x68, 0xec, 0xec, 0xec, 0x68, 0xec, 0xec, 0xec, 0x68}; |
5975 | static const __u8 vf0250_matrix[9] = | 5975 | static const u8 vf0250_matrix[9] = |
5976 | {0x7b, 0xea, 0xea, 0xea, 0x7b, 0xea, 0xea, 0xea, 0x7b}; | 5976 | {0x7b, 0xea, 0xea, 0xea, 0x7b, 0xea, 0xea, 0xea, 0x7b}; |
5977 | static const __u8 *matrix_tb[SENSOR_MAX] = { | 5977 | static const u8 *matrix_tb[SENSOR_MAX] = { |
5978 | adcm2700_matrix, /* SENSOR_ADCM2700 0 */ | 5978 | adcm2700_matrix, /* SENSOR_ADCM2700 0 */ |
5979 | ov7620_matrix, /* SENSOR_CS2102 1 */ | 5979 | ov7620_matrix, /* SENSOR_CS2102 1 */ |
5980 | NULL, /* SENSOR_CS2102K 2 */ | 5980 | NULL, /* SENSOR_CS2102K 2 */ |
@@ -6006,11 +6006,12 @@ static void setmatrix(struct gspca_dev *gspca_dev) | |||
6006 | static void setbrightness(struct gspca_dev *gspca_dev) | 6006 | static void setbrightness(struct gspca_dev *gspca_dev) |
6007 | { | 6007 | { |
6008 | struct sd *sd = (struct sd *) gspca_dev; | 6008 | struct sd *sd = (struct sd *) gspca_dev; |
6009 | __u8 brightness; | 6009 | u8 brightness; |
6010 | 6010 | ||
6011 | switch (sd->sensor) { | 6011 | switch (sd->sensor) { |
6012 | case SENSOR_GC0305: | 6012 | case SENSOR_GC0305: |
6013 | case SENSOR_OV7620: | 6013 | case SENSOR_OV7620: |
6014 | case SENSOR_PAS202B: | ||
6014 | case SENSOR_PO2030: | 6015 | case SENSOR_PO2030: |
6015 | return; | 6016 | return; |
6016 | } | 6017 | } |
@@ -6034,7 +6035,7 @@ static void setsharpness(struct gspca_dev *gspca_dev) | |||
6034 | struct sd *sd = (struct sd *) gspca_dev; | 6035 | struct sd *sd = (struct sd *) gspca_dev; |
6035 | struct usb_device *dev = gspca_dev->dev; | 6036 | struct usb_device *dev = gspca_dev->dev; |
6036 | int sharpness; | 6037 | int sharpness; |
6037 | static const __u8 sharpness_tb[][2] = { | 6038 | static const u8 sharpness_tb[][2] = { |
6038 | {0x02, 0x03}, | 6039 | {0x02, 0x03}, |
6039 | {0x04, 0x07}, | 6040 | {0x04, 0x07}, |
6040 | {0x08, 0x0f}, | 6041 | {0x08, 0x0f}, |
@@ -6053,118 +6054,69 @@ static void setcontrast(struct gspca_dev *gspca_dev) | |||
6053 | { | 6054 | { |
6054 | struct sd *sd = (struct sd *) gspca_dev; | 6055 | struct sd *sd = (struct sd *) gspca_dev; |
6055 | struct usb_device *dev = gspca_dev->dev; | 6056 | struct usb_device *dev = gspca_dev->dev; |
6056 | const __u8 *Tgamma, *Tgradient; | 6057 | const u8 *Tgamma; |
6057 | int g, i, k; | 6058 | int g, i, k, adj, gp; |
6058 | static const __u8 kgamma_tb[16] = /* delta for contrast */ | 6059 | u8 gr[16]; |
6060 | static const u8 delta_tb[16] = /* delta for contrast */ | ||
6059 | {0x15, 0x0d, 0x0a, 0x09, 0x08, 0x08, 0x08, 0x08, | 6061 | {0x15, 0x0d, 0x0a, 0x09, 0x08, 0x08, 0x08, 0x08, |
6060 | 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08}; | 6062 | 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08}; |
6061 | static const __u8 kgrad_tb[16] = | 6063 | static const u8 gamma_tb[6][16] = { |
6062 | {0x1b, 0x06, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, | ||
6063 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x04}; | ||
6064 | static const __u8 Tgamma_1[16] = | ||
6065 | {0x00, 0x00, 0x03, 0x0d, 0x1b, 0x2e, 0x45, 0x5f, | 6064 | {0x00, 0x00, 0x03, 0x0d, 0x1b, 0x2e, 0x45, 0x5f, |
6066 | 0x79, 0x93, 0xab, 0xc1, 0xd4, 0xe5, 0xf3, 0xff}; | 6065 | 0x79, 0x93, 0xab, 0xc1, 0xd4, 0xe5, 0xf3, 0xff}, |
6067 | static const __u8 Tgradient_1[16] = | ||
6068 | {0x00, 0x01, 0x05, 0x0b, 0x10, 0x15, 0x18, 0x1a, | ||
6069 | 0x1a, 0x18, 0x16, 0x14, 0x12, 0x0f, 0x0d, 0x06}; | ||
6070 | static const __u8 Tgamma_2[16] = | ||
6071 | {0x01, 0x0c, 0x1f, 0x3a, 0x53, 0x6d, 0x85, 0x9c, | 6066 | {0x01, 0x0c, 0x1f, 0x3a, 0x53, 0x6d, 0x85, 0x9c, |
6072 | 0xb0, 0xc2, 0xd1, 0xde, 0xe9, 0xf2, 0xf9, 0xff}; | 6067 | 0xb0, 0xc2, 0xd1, 0xde, 0xe9, 0xf2, 0xf9, 0xff}, |
6073 | static const __u8 Tgradient_2[16] = | ||
6074 | {0x05, 0x0f, 0x16, 0x1a, 0x19, 0x19, 0x17, 0x15, | ||
6075 | 0x12, 0x10, 0x0e, 0x0b, 0x09, 0x08, 0x06, 0x03}; | ||
6076 | static const __u8 Tgamma_3[16] = | ||
6077 | {0x04, 0x16, 0x30, 0x4e, 0x68, 0x81, 0x98, 0xac, | 6068 | {0x04, 0x16, 0x30, 0x4e, 0x68, 0x81, 0x98, 0xac, |
6078 | 0xbe, 0xcd, 0xda, 0xe4, 0xed, 0xf5, 0xfb, 0xff}; | 6069 | 0xbe, 0xcd, 0xda, 0xe4, 0xed, 0xf5, 0xfb, 0xff}, |
6079 | static const __u8 Tgradient_3[16] = | ||
6080 | {0x0c, 0x16, 0x1b, 0x1c, 0x19, 0x18, 0x15, 0x12, | ||
6081 | 0x10, 0x0d, 0x0b, 0x09, 0x08, 0x06, 0x05, 0x03}; | ||
6082 | static const __u8 Tgamma_4[16] = | ||
6083 | {0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8, | 6070 | {0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8, |
6084 | 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff}; | 6071 | 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff}, |
6085 | static const __u8 Tgradient_4[16] = | ||
6086 | {0x26, 0x22, 0x20, 0x1c, 0x16, 0x13, 0x10, 0x0d, | ||
6087 | 0x0b, 0x09, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02}; | ||
6088 | static const __u8 Tgamma_5[16] = | ||
6089 | {0x20, 0x4b, 0x6e, 0x8d, 0xa3, 0xb5, 0xc5, 0xd2, | 6072 | {0x20, 0x4b, 0x6e, 0x8d, 0xa3, 0xb5, 0xc5, 0xd2, |
6090 | 0xdc, 0xe5, 0xec, 0xf2, 0xf6, 0xfa, 0xfd, 0xff}; | 6073 | 0xdc, 0xe5, 0xec, 0xf2, 0xf6, 0xfa, 0xfd, 0xff}, |
6091 | static const __u8 Tgradient_5[16] = | ||
6092 | {0x37, 0x26, 0x20, 0x1a, 0x14, 0x10, 0x0e, 0x0b, | ||
6093 | 0x09, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x02}; | ||
6094 | static const __u8 Tgamma_6[16] = /* ?? was gamma 5 */ | ||
6095 | {0x24, 0x44, 0x64, 0x84, 0x9d, 0xb2, 0xc4, 0xd3, | 6074 | {0x24, 0x44, 0x64, 0x84, 0x9d, 0xb2, 0xc4, 0xd3, |
6096 | 0xe0, 0xeb, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff}; | 6075 | 0xe0, 0xeb, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff}, |
6097 | static const __u8 Tgradient_6[16] = | ||
6098 | {0x18, 0x20, 0x20, 0x1c, 0x16, 0x13, 0x10, 0x0e, | ||
6099 | 0x0b, 0x09, 0x07, 0x00, 0x00, 0x00, 0x00, 0x01}; | ||
6100 | static const __u8 *gamma_tb[] = { | ||
6101 | NULL, Tgamma_1, Tgamma_2, | ||
6102 | Tgamma_3, Tgamma_4, Tgamma_5, Tgamma_6 | ||
6103 | }; | 6076 | }; |
6104 | static const __u8 *gradient_tb[] = { | ||
6105 | NULL, Tgradient_1, Tgradient_2, | ||
6106 | Tgradient_3, Tgradient_4, Tgradient_5, Tgradient_6 | ||
6107 | }; | ||
6108 | #ifdef GSPCA_DEBUG | ||
6109 | __u8 v[16]; | ||
6110 | #endif | ||
6111 | 6077 | ||
6112 | Tgamma = gamma_tb[sd->gamma]; | 6078 | Tgamma = gamma_tb[sd->gamma - 1]; |
6113 | Tgradient = gradient_tb[sd->gamma]; | ||
6114 | 6079 | ||
6115 | k = (sd->contrast - 128) /* -128 / 128 */ | 6080 | k = ((int) sd->contrast - 128); /* -128 / 128 */ |
6116 | * Tgamma[0]; | 6081 | adj = 0; |
6117 | PDEBUG(D_CONF, "gamma:%d contrast:%d gamma coeff: %d/128", | 6082 | gp = 0; |
6118 | sd->gamma, sd->contrast, k); | ||
6119 | for (i = 0; i < 16; i++) { | 6083 | for (i = 0; i < 16; i++) { |
6120 | g = Tgamma[i] + kgamma_tb[i] * k / 128; | 6084 | g = Tgamma[i] - delta_tb[i] * k / 128 - adj / 2; |
6121 | if (g > 0xff) | 6085 | if (g > 0xff) |
6122 | g = 0xff; | 6086 | g = 0xff; |
6123 | else if (g <= 0) | 6087 | else if (g <= 0) |
6124 | g = 1; | 6088 | g = 1; |
6125 | reg_w(dev, g, 0x0120 + i); /* gamma */ | 6089 | reg_w(dev, g, 0x0120 + i); /* gamma */ |
6126 | #ifdef GSPCA_DEBUG | 6090 | if (k > 0) |
6127 | if (gspca_debug & D_CONF) | 6091 | adj--; |
6128 | v[i] = g; | 6092 | else |
6129 | #endif | 6093 | adj++; |
6130 | } | 6094 | |
6131 | PDEBUG(D_CONF, "tb: %02x %02x %02x %02x %02x %02x %02x %02x", | 6095 | if (i != 0) { |
6132 | v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]); | 6096 | if (gp == 0) |
6133 | PDEBUG(D_CONF, " %02x %02x %02x %02x %02x %02x %02x %02x", | 6097 | gr[i - 1] = 0; |
6134 | v[8], v[9], v[10], v[11], v[12], v[13], v[14], v[15]); | ||
6135 | for (i = 0; i < 16; i++) { | ||
6136 | g = Tgradient[i] - kgrad_tb[i] * k / 128; | ||
6137 | if (g > 0xff) | ||
6138 | g = 0xff; | ||
6139 | else if (g <= 0) { | ||
6140 | if (i != 15) | ||
6141 | g = 0; | ||
6142 | else | 6098 | else |
6143 | g = 1; | 6099 | gr[i - 1] = g - gp; |
6144 | } | 6100 | } |
6145 | reg_w(dev, g, 0x0130 + i); /* gradient */ | 6101 | gp = g; |
6146 | #ifdef GSPCA_DEBUG | ||
6147 | if (gspca_debug & D_CONF) | ||
6148 | v[i] = g; | ||
6149 | #endif | ||
6150 | } | 6102 | } |
6151 | PDEBUG(D_CONF, " %02x %02x %02x %02x %02x %02x %02x %02x", | 6103 | gr[15] = gr[14] / 2; |
6152 | v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]); | 6104 | for (i = 0; i < 16; i++) |
6153 | PDEBUG(D_CONF, " %02x %02x %02x %02x %02x %02x %02x %02x", | 6105 | reg_w(dev, gr[i], 0x0130 + i); /* gradient */ |
6154 | v[8], v[9], v[10], v[11], v[12], v[13], v[14], v[15]); | ||
6155 | } | 6106 | } |
6156 | 6107 | ||
6157 | static void setquality(struct gspca_dev *gspca_dev) | 6108 | static void setquality(struct gspca_dev *gspca_dev) |
6158 | { | 6109 | { |
6159 | struct sd *sd = (struct sd *) gspca_dev; | 6110 | struct sd *sd = (struct sd *) gspca_dev; |
6160 | struct usb_device *dev = gspca_dev->dev; | 6111 | struct usb_device *dev = gspca_dev->dev; |
6161 | __u8 frxt; | 6112 | u8 frxt; |
6162 | 6113 | ||
6163 | switch (sd->sensor) { | 6114 | switch (sd->sensor) { |
6164 | case SENSOR_ADCM2700: | 6115 | case SENSOR_ADCM2700: |
6165 | case SENSOR_GC0305: | 6116 | case SENSOR_GC0305: |
6166 | case SENSOR_HV7131B: | 6117 | case SENSOR_HV7131B: |
6167 | case SENSOR_OV7620: | 6118 | case SENSOR_OV7620: |
6119 | case SENSOR_PAS202B: | ||
6168 | case SENSOR_PO2030: | 6120 | case SENSOR_PO2030: |
6169 | return; | 6121 | return; |
6170 | } | 6122 | } |
@@ -6218,9 +6170,9 @@ static int setlightfreq(struct gspca_dev *gspca_dev) | |||
6218 | hdcs2020b_50HZ, hdcs2020b_50HZ, | 6170 | hdcs2020b_50HZ, hdcs2020b_50HZ, |
6219 | hdcs2020b_60HZ, hdcs2020b_60HZ}, | 6171 | hdcs2020b_60HZ, hdcs2020b_60HZ}, |
6220 | /* SENSOR_HV7131B 5 */ | 6172 | /* SENSOR_HV7131B 5 */ |
6221 | {hv7131b_NoFlikerScale, hv7131b_NoFliker, | 6173 | {hv7131b_NoFliker, hv7131b_NoFlikerScale, |
6222 | hv7131b_50HZScale, hv7131b_50HZ, | 6174 | hv7131b_50HZ, hv7131b_50HZScale, |
6223 | hv7131b_60HZScale, hv7131b_60HZ}, | 6175 | hv7131b_60HZ, hv7131b_60HZScale}, |
6224 | /* SENSOR_HV7131C 6 */ | 6176 | /* SENSOR_HV7131C 6 */ |
6225 | {NULL, NULL, | 6177 | {NULL, NULL, |
6226 | NULL, NULL, | 6178 | NULL, NULL, |
@@ -6230,17 +6182,17 @@ static int setlightfreq(struct gspca_dev *gspca_dev) | |||
6230 | icm105a_50HZ, icm105a_50HZScale, | 6182 | icm105a_50HZ, icm105a_50HZScale, |
6231 | icm105a_60HZ, icm105a_60HZScale}, | 6183 | icm105a_60HZ, icm105a_60HZScale}, |
6232 | /* SENSOR_MC501CB 8 */ | 6184 | /* SENSOR_MC501CB 8 */ |
6233 | {MC501CB_NoFliker, MC501CB_NoFlikerScale, | 6185 | {mc501cb_NoFliker, mc501cb_NoFlikerScale, |
6234 | MC501CB_50HZ, MC501CB_50HZScale, | 6186 | mc501cb_50HZ, mc501cb_50HZScale, |
6235 | MC501CB_60HZ, MC501CB_60HZScale}, | 6187 | mc501cb_60HZ, mc501cb_60HZScale}, |
6236 | /* SENSOR_MI0360SOC 9 */ | 6188 | /* SENSOR_MI0360SOC 9 */ |
6237 | {mi360soc_AENoFlikerScale, mi360soc_AENoFliker, | 6189 | {mi360soc_AENoFliker, mi360soc_AENoFlikerScale, |
6238 | mi360soc_AE50HZScale, mi360soc_AE50HZ, | 6190 | mi360soc_AE50HZ, mi360soc_AE50HZScale, |
6239 | mi360soc_AE60HZScale, mi360soc_AE60HZ}, | 6191 | mi360soc_AE60HZ, mi360soc_AE60HZScale}, |
6240 | /* SENSOR_OV7620 10 */ | 6192 | /* SENSOR_OV7620 10 */ |
6241 | {OV7620_NoFliker, OV7620_NoFliker, | 6193 | {ov7620_NoFliker, ov7620_NoFliker, |
6242 | OV7620_50HZ, OV7620_50HZ, | 6194 | ov7620_50HZ, ov7620_50HZ, |
6243 | OV7620_60HZ, OV7620_60HZ}, | 6195 | ov7620_60HZ, ov7620_60HZ}, |
6244 | /* SENSOR_OV7630C 11 */ | 6196 | /* SENSOR_OV7630C 11 */ |
6245 | {NULL, NULL, | 6197 | {NULL, NULL, |
6246 | NULL, NULL, | 6198 | NULL, NULL, |
@@ -6258,17 +6210,17 @@ static int setlightfreq(struct gspca_dev *gspca_dev) | |||
6258 | pb0330_50HZScale, pb0330_50HZ, | 6210 | pb0330_50HZScale, pb0330_50HZ, |
6259 | pb0330_60HZScale, pb0330_60HZ}, | 6211 | pb0330_60HZScale, pb0330_60HZ}, |
6260 | /* SENSOR_PO2030 15 */ | 6212 | /* SENSOR_PO2030 15 */ |
6261 | {PO2030_NoFliker, PO2030_NoFliker, | 6213 | {po2030_NoFliker, po2030_NoFliker, |
6262 | PO2030_50HZ, PO2030_50HZ, | 6214 | po2030_50HZ, po2030_50HZ, |
6263 | PO2030_60HZ, PO2030_60HZ}, | 6215 | po2030_60HZ, po2030_60HZ}, |
6264 | /* SENSOR_TAS5130CK 16 */ | 6216 | /* SENSOR_TAS5130CK 16 */ |
6265 | {tas5130cxx_NoFlikerScale, tas5130cxx_NoFliker, | 6217 | {tas5130cxx_NoFliker, tas5130cxx_NoFlikerScale, |
6266 | tas5130cxx_50HZScale, tas5130cxx_50HZ, | 6218 | tas5130cxx_50HZ, tas5130cxx_50HZScale, |
6267 | tas5130cxx_60HZScale, tas5130cxx_60HZ}, | 6219 | tas5130cxx_60HZ, tas5130cxx_60HZScale}, |
6268 | /* SENSOR_TAS5130CXX 17 */ | 6220 | /* SENSOR_TAS5130CXX 17 */ |
6269 | {tas5130cxx_NoFlikerScale, tas5130cxx_NoFliker, | 6221 | {tas5130cxx_NoFliker, tas5130cxx_NoFlikerScale, |
6270 | tas5130cxx_50HZScale, tas5130cxx_50HZ, | 6222 | tas5130cxx_50HZ, tas5130cxx_50HZScale, |
6271 | tas5130cxx_60HZScale, tas5130cxx_60HZ}, | 6223 | tas5130cxx_60HZ, tas5130cxx_60HZScale}, |
6272 | /* SENSOR_TAS5130C_VF0250 18 */ | 6224 | /* SENSOR_TAS5130C_VF0250 18 */ |
6273 | {tas5130c_vf0250_NoFliker, tas5130c_vf0250_NoFlikerScale, | 6225 | {tas5130c_vf0250_NoFliker, tas5130c_vf0250_NoFlikerScale, |
6274 | tas5130c_vf0250_50HZ, tas5130c_vf0250_50HZScale, | 6226 | tas5130c_vf0250_50HZ, tas5130c_vf0250_50HZScale, |
@@ -6277,9 +6229,9 @@ static int setlightfreq(struct gspca_dev *gspca_dev) | |||
6277 | 6229 | ||
6278 | i = sd->lightfreq * 2; | 6230 | i = sd->lightfreq * 2; |
6279 | mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; | 6231 | mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; |
6280 | if (!mode) | 6232 | if (mode) |
6281 | i++; /* 640x480 */ | 6233 | i++; /* 320x240 */ |
6282 | zc3_freq = freq_tb[(int) sd->sensor][i]; | 6234 | zc3_freq = freq_tb[sd->sensor][i]; |
6283 | if (zc3_freq != NULL) { | 6235 | if (zc3_freq != NULL) { |
6284 | usb_exchange(gspca_dev, zc3_freq); | 6236 | usb_exchange(gspca_dev, zc3_freq); |
6285 | switch (sd->sensor) { | 6237 | switch (sd->sensor) { |
@@ -6297,6 +6249,9 @@ static int setlightfreq(struct gspca_dev *gspca_dev) | |||
6297 | reg_w(gspca_dev->dev, 0x44, 0x0002); | 6249 | reg_w(gspca_dev->dev, 0x44, 0x0002); |
6298 | } | 6250 | } |
6299 | break; | 6251 | break; |
6252 | case SENSOR_PAS202B: | ||
6253 | reg_w(gspca_dev->dev, 0x00, 0x01a7); | ||
6254 | break; | ||
6300 | } | 6255 | } |
6301 | } | 6256 | } |
6302 | return 0; | 6257 | return 0; |
@@ -6305,7 +6260,7 @@ static int setlightfreq(struct gspca_dev *gspca_dev) | |||
6305 | static void setautogain(struct gspca_dev *gspca_dev) | 6260 | static void setautogain(struct gspca_dev *gspca_dev) |
6306 | { | 6261 | { |
6307 | struct sd *sd = (struct sd *) gspca_dev; | 6262 | struct sd *sd = (struct sd *) gspca_dev; |
6308 | __u8 autoval; | 6263 | u8 autoval; |
6309 | 6264 | ||
6310 | if (sd->autogain) | 6265 | if (sd->autogain) |
6311 | autoval = 0x42; | 6266 | autoval = 0x42; |
@@ -6333,6 +6288,12 @@ static void send_unknown(struct usb_device *dev, int sensor) | |||
6333 | reg_w(dev, 0x02, 0x003b); | 6288 | reg_w(dev, 0x02, 0x003b); |
6334 | reg_w(dev, 0x00, 0x0038); | 6289 | reg_w(dev, 0x00, 0x0038); |
6335 | break; | 6290 | break; |
6291 | case SENSOR_PAS202B: | ||
6292 | reg_w(dev, 0x03, 0x003b); | ||
6293 | reg_w(dev, 0x0c, 0x003a); | ||
6294 | reg_w(dev, 0x0b, 0x0039); | ||
6295 | reg_w(dev, 0x0b, 0x0038); | ||
6296 | break; | ||
6336 | } | 6297 | } |
6337 | } | 6298 | } |
6338 | 6299 | ||
@@ -6349,7 +6310,7 @@ static void start_2wr_probe(struct usb_device *dev, int sensor) | |||
6349 | 6310 | ||
6350 | static int sif_probe(struct gspca_dev *gspca_dev) | 6311 | static int sif_probe(struct gspca_dev *gspca_dev) |
6351 | { | 6312 | { |
6352 | __u16 checkword; | 6313 | u16 checkword; |
6353 | 6314 | ||
6354 | start_2wr_probe(gspca_dev->dev, 0x0f); /* PAS106 */ | 6315 | start_2wr_probe(gspca_dev->dev, 0x0f); /* PAS106 */ |
6355 | reg_w(gspca_dev->dev, 0x08, 0x008d); | 6316 | reg_w(gspca_dev->dev, 0x08, 0x008d); |
@@ -6392,6 +6353,7 @@ static int vga_2wr_probe(struct gspca_dev *gspca_dev) | |||
6392 | } | 6353 | } |
6393 | 6354 | ||
6394 | start_2wr_probe(dev, 0x08); /* HDCS2020 */ | 6355 | start_2wr_probe(dev, 0x08); /* HDCS2020 */ |
6356 | i2c_write(gspca_dev, 0x1c, 0x00, 0x00); | ||
6395 | i2c_write(gspca_dev, 0x15, 0xaa, 0x00); | 6357 | i2c_write(gspca_dev, 0x15, 0xaa, 0x00); |
6396 | retword = i2c_read(gspca_dev, 0x15); | 6358 | retword = i2c_read(gspca_dev, 0x15); |
6397 | if (retword != 0) | 6359 | if (retword != 0) |
@@ -6420,8 +6382,10 @@ static int vga_2wr_probe(struct gspca_dev *gspca_dev) | |||
6420 | i2c_write(gspca_dev, 0x03, 0xaa, 0x00); | 6382 | i2c_write(gspca_dev, 0x03, 0xaa, 0x00); |
6421 | msleep(50); | 6383 | msleep(50); |
6422 | retword = i2c_read(gspca_dev, 0x03); | 6384 | retword = i2c_read(gspca_dev, 0x03); |
6423 | if (retword != 0) | 6385 | if (retword != 0) { |
6386 | send_unknown(dev, SENSOR_PAS202B); | ||
6424 | return 0x0e; /* PAS202BCB */ | 6387 | return 0x0e; /* PAS202BCB */ |
6388 | } | ||
6425 | 6389 | ||
6426 | start_2wr_probe(dev, 0x02); /* TAS5130C */ | 6390 | start_2wr_probe(dev, 0x02); /* TAS5130C */ |
6427 | i2c_write(gspca_dev, 0x01, 0xaa, 0x00); | 6391 | i2c_write(gspca_dev, 0x01, 0xaa, 0x00); |
@@ -6457,8 +6421,8 @@ ov_check: | |||
6457 | } | 6421 | } |
6458 | 6422 | ||
6459 | struct sensor_by_chipset_revision { | 6423 | struct sensor_by_chipset_revision { |
6460 | __u16 revision; | 6424 | u16 revision; |
6461 | __u8 internal_sensor_id; | 6425 | u8 internal_sensor_id; |
6462 | }; | 6426 | }; |
6463 | static const struct sensor_by_chipset_revision chipset_revision_sensor[] = { | 6427 | static const struct sensor_by_chipset_revision chipset_revision_sensor[] = { |
6464 | {0xc000, 0x12}, /* TAS5130C */ | 6428 | {0xc000, 0x12}, /* TAS5130C */ |
@@ -6467,6 +6431,7 @@ static const struct sensor_by_chipset_revision chipset_revision_sensor[] = { | |||
6467 | {0x8001, 0x13}, | 6431 | {0x8001, 0x13}, |
6468 | {0x8000, 0x14}, /* CS2102K */ | 6432 | {0x8000, 0x14}, /* CS2102K */ |
6469 | {0x8400, 0x15}, /* TAS5130K */ | 6433 | {0x8400, 0x15}, /* TAS5130K */ |
6434 | {0xe400, 0x15}, | ||
6470 | }; | 6435 | }; |
6471 | 6436 | ||
6472 | static int vga_3wr_probe(struct gspca_dev *gspca_dev) | 6437 | static int vga_3wr_probe(struct gspca_dev *gspca_dev) |
@@ -6474,7 +6439,7 @@ static int vga_3wr_probe(struct gspca_dev *gspca_dev) | |||
6474 | struct sd *sd = (struct sd *) gspca_dev; | 6439 | struct sd *sd = (struct sd *) gspca_dev; |
6475 | struct usb_device *dev = gspca_dev->dev; | 6440 | struct usb_device *dev = gspca_dev->dev; |
6476 | int i; | 6441 | int i; |
6477 | __u8 retbyte; | 6442 | u8 retbyte; |
6478 | u16 retword; | 6443 | u16 retword; |
6479 | 6444 | ||
6480 | /*fixme: lack of 8b=b3 (11,12)-> 10, 8b=e0 (14,15,16)-> 12 found in gspcav1*/ | 6445 | /*fixme: lack of 8b=b3 (11,12)-> 10, 8b=e0 (14,15,16)-> 12 found in gspcav1*/ |
@@ -6622,8 +6587,7 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
6622 | struct sd *sd = (struct sd *) gspca_dev; | 6587 | struct sd *sd = (struct sd *) gspca_dev; |
6623 | struct cam *cam; | 6588 | struct cam *cam; |
6624 | int sensor; | 6589 | int sensor; |
6625 | int vga = 1; /* 1: vga, 0: sif */ | 6590 | static const u8 gamma[SENSOR_MAX] = { |
6626 | static const __u8 gamma[SENSOR_MAX] = { | ||
6627 | 4, /* SENSOR_ADCM2700 0 */ | 6591 | 4, /* SENSOR_ADCM2700 0 */ |
6628 | 4, /* SENSOR_CS2102 1 */ | 6592 | 4, /* SENSOR_CS2102 1 */ |
6629 | 5, /* SENSOR_CS2102K 2 */ | 6593 | 5, /* SENSOR_CS2102K 2 */ |
@@ -6644,9 +6608,30 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
6644 | 3, /* SENSOR_TAS5130CXX 17 */ | 6608 | 3, /* SENSOR_TAS5130CXX 17 */ |
6645 | 3, /* SENSOR_TAS5130C_VF0250 18 */ | 6609 | 3, /* SENSOR_TAS5130C_VF0250 18 */ |
6646 | }; | 6610 | }; |
6611 | static const u8 mode_tb[SENSOR_MAX] = { | ||
6612 | 2, /* SENSOR_ADCM2700 0 */ | ||
6613 | 1, /* SENSOR_CS2102 1 */ | ||
6614 | 1, /* SENSOR_CS2102K 2 */ | ||
6615 | 1, /* SENSOR_GC0305 3 */ | ||
6616 | 1, /* SENSOR_HDCS2020b 4 */ | ||
6617 | 1, /* SENSOR_HV7131B 5 */ | ||
6618 | 1, /* SENSOR_HV7131C 6 */ | ||
6619 | 1, /* SENSOR_ICM105A 7 */ | ||
6620 | 2, /* SENSOR_MC501CB 8 */ | ||
6621 | 1, /* SENSOR_MI0360SOC 9 */ | ||
6622 | 2, /* SENSOR_OV7620 10 */ | ||
6623 | 1, /* SENSOR_OV7630C 11 */ | ||
6624 | 0, /* SENSOR_PAS106 12 */ | ||
6625 | 1, /* SENSOR_PAS202B 13 */ | ||
6626 | 1, /* SENSOR_PB0330 14 */ | ||
6627 | 1, /* SENSOR_PO2030 15 */ | ||
6628 | 1, /* SENSOR_TAS5130CK 16 */ | ||
6629 | 1, /* SENSOR_TAS5130CXX 17 */ | ||
6630 | 1, /* SENSOR_TAS5130C_VF0250 18 */ | ||
6631 | }; | ||
6647 | 6632 | ||
6648 | /* define some sensors from the vendor/product */ | 6633 | /* define some sensors from the vendor/product */ |
6649 | sd->sharpness = 2; | 6634 | sd->sharpness = SHARPNESS_DEF; |
6650 | sd->sensor = id->driver_info; | 6635 | sd->sensor = id->driver_info; |
6651 | sensor = zcxx_probeSensor(gspca_dev); | 6636 | sensor = zcxx_probeSensor(gspca_dev); |
6652 | if (sensor >= 0) | 6637 | if (sensor >= 0) |
@@ -6671,8 +6656,21 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
6671 | } | 6656 | } |
6672 | break; | 6657 | break; |
6673 | case 0: | 6658 | case 0: |
6674 | PDEBUG(D_PROBE, "Find Sensor HV7131B"); | 6659 | /* check the sensor type */ |
6675 | sd->sensor = SENSOR_HV7131B; | 6660 | sensor = i2c_read(gspca_dev, 0x00); |
6661 | PDEBUG(D_PROBE, "Sensor hv7131 type %d", sensor); | ||
6662 | switch (sensor) { | ||
6663 | case 0: /* hv7131b */ | ||
6664 | case 1: /* hv7131e */ | ||
6665 | PDEBUG(D_PROBE, "Find Sensor HV7131B"); | ||
6666 | sd->sensor = SENSOR_HV7131B; | ||
6667 | break; | ||
6668 | default: | ||
6669 | /* case 2: * hv7131r */ | ||
6670 | PDEBUG(D_PROBE, "Find Sensor HV7131R(c)"); | ||
6671 | sd->sensor = SENSOR_HV7131C; | ||
6672 | break; | ||
6673 | } | ||
6676 | break; | 6674 | break; |
6677 | case 0x02: | 6675 | case 0x02: |
6678 | PDEBUG(D_PROBE, "Sensor TAS5130C"); | 6676 | PDEBUG(D_PROBE, "Sensor TAS5130C"); |
@@ -6699,12 +6697,11 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
6699 | case 0x0e: | 6697 | case 0x0e: |
6700 | PDEBUG(D_PROBE, "Find Sensor PAS202B"); | 6698 | PDEBUG(D_PROBE, "Find Sensor PAS202B"); |
6701 | sd->sensor = SENSOR_PAS202B; | 6699 | sd->sensor = SENSOR_PAS202B; |
6702 | sd->sharpness = 1; | 6700 | /* sd->sharpness = 1; */ |
6703 | break; | 6701 | break; |
6704 | case 0x0f: | 6702 | case 0x0f: |
6705 | PDEBUG(D_PROBE, "Find Sensor PAS106"); | 6703 | PDEBUG(D_PROBE, "Find Sensor PAS106"); |
6706 | sd->sensor = SENSOR_PAS106; | 6704 | sd->sensor = SENSOR_PAS106; |
6707 | vga = 0; /* SIF */ | ||
6708 | break; | 6705 | break; |
6709 | case 0x10: | 6706 | case 0x10: |
6710 | case 0x12: | 6707 | case 0x12: |
@@ -6770,31 +6767,38 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
6770 | if (sensor < 0x20) { | 6767 | if (sensor < 0x20) { |
6771 | if (sensor == -1 || sensor == 0x10 || sensor == 0x12) | 6768 | if (sensor == -1 || sensor == 0x10 || sensor == 0x12) |
6772 | reg_w(gspca_dev->dev, 0x02, 0x0010); | 6769 | reg_w(gspca_dev->dev, 0x02, 0x0010); |
6773 | else | ||
6774 | reg_w(gspca_dev->dev, sensor & 0x0f, 0x0010); | ||
6775 | reg_r(gspca_dev, 0x0010); | 6770 | reg_r(gspca_dev, 0x0010); |
6776 | } | 6771 | } |
6777 | 6772 | ||
6778 | cam = &gspca_dev->cam; | 6773 | cam = &gspca_dev->cam; |
6779 | /*fixme:test*/ | 6774 | /*fixme:test*/ |
6780 | gspca_dev->nbalt--; | 6775 | gspca_dev->nbalt--; |
6781 | if (vga) { | 6776 | switch (mode_tb[sd->sensor]) { |
6782 | cam->cam_mode = vga_mode; | 6777 | case 0: |
6783 | cam->nmodes = ARRAY_SIZE(vga_mode); | ||
6784 | } else { | ||
6785 | cam->cam_mode = sif_mode; | 6778 | cam->cam_mode = sif_mode; |
6786 | cam->nmodes = ARRAY_SIZE(sif_mode); | 6779 | cam->nmodes = ARRAY_SIZE(sif_mode); |
6780 | break; | ||
6781 | case 1: | ||
6782 | cam->cam_mode = vga_mode; | ||
6783 | cam->nmodes = ARRAY_SIZE(vga_mode); | ||
6784 | break; | ||
6785 | default: | ||
6786 | /* case 2: */ | ||
6787 | cam->cam_mode = broken_vga_mode; | ||
6788 | cam->nmodes = ARRAY_SIZE(broken_vga_mode); | ||
6789 | break; | ||
6787 | } | 6790 | } |
6788 | sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value; | 6791 | sd->brightness = BRIGHTNESS_DEF; |
6789 | sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value; | 6792 | sd->contrast = CONTRAST_DEF; |
6790 | sd->gamma = gamma[(int) sd->sensor]; | 6793 | sd->gamma = gamma[sd->sensor]; |
6791 | sd->autogain = sd_ctrls[SD_AUTOGAIN].qctrl.default_value; | 6794 | sd->autogain = AUTOGAIN_DEF; |
6792 | sd->lightfreq = sd_ctrls[SD_FREQ].qctrl.default_value; | 6795 | sd->lightfreq = FREQ_DEF; |
6793 | sd->quality = QUALITY_DEF; | 6796 | sd->quality = QUALITY_DEF; |
6794 | 6797 | ||
6795 | switch (sd->sensor) { | 6798 | switch (sd->sensor) { |
6796 | case SENSOR_GC0305: | 6799 | case SENSOR_GC0305: |
6797 | case SENSOR_OV7620: | 6800 | case SENSOR_OV7620: |
6801 | case SENSOR_PAS202B: | ||
6798 | case SENSOR_PO2030: | 6802 | case SENSOR_PO2030: |
6799 | gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX); | 6803 | gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX); |
6800 | break; | 6804 | break; |
@@ -6805,14 +6809,13 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
6805 | break; | 6809 | break; |
6806 | } | 6810 | } |
6807 | 6811 | ||
6808 | /* switch the led off */ | ||
6809 | reg_w(gspca_dev->dev, 0x01, 0x0000); | ||
6810 | return 0; | 6812 | return 0; |
6811 | } | 6813 | } |
6812 | 6814 | ||
6813 | /* this function is called at probe and resume time */ | 6815 | /* this function is called at probe and resume time */ |
6814 | static int sd_init(struct gspca_dev *gspca_dev) | 6816 | static int sd_init(struct gspca_dev *gspca_dev) |
6815 | { | 6817 | { |
6818 | /* switch off the led */ | ||
6816 | reg_w(gspca_dev->dev, 0x01, 0x0000); | 6819 | reg_w(gspca_dev->dev, 0x01, 0x0000); |
6817 | return 0; | 6820 | return 0; |
6818 | } | 6821 | } |
@@ -6821,28 +6824,27 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
6821 | { | 6824 | { |
6822 | struct sd *sd = (struct sd *) gspca_dev; | 6825 | struct sd *sd = (struct sd *) gspca_dev; |
6823 | struct usb_device *dev = gspca_dev->dev; | 6826 | struct usb_device *dev = gspca_dev->dev; |
6824 | const struct usb_action *zc3_init; | ||
6825 | int mode; | 6827 | int mode; |
6826 | static const struct usb_action *init_tb[SENSOR_MAX][2] = { | 6828 | static const struct usb_action *init_tb[SENSOR_MAX][2] = { |
6827 | {adcm2700_Initial, adcm2700_InitialScale}, /* 0 */ | 6829 | {adcm2700_Initial, adcm2700_InitialScale}, /* 0 */ |
6828 | {cs2102_InitialScale, cs2102_Initial}, /* 1 */ | 6830 | {cs2102_Initial, cs2102_InitialScale}, /* 1 */ |
6829 | {cs2102K_InitialScale, cs2102K_Initial}, /* 2 */ | 6831 | {cs2102K_Initial, cs2102K_InitialScale}, /* 2 */ |
6830 | {gc0305_Initial, gc0305_InitialScale}, /* 3 */ | 6832 | {gc0305_Initial, gc0305_InitialScale}, /* 3 */ |
6831 | {hdcs2020xb_InitialScale, hdcs2020xb_Initial}, /* 4 */ | 6833 | {hdcs2020b_Initial, hdcs2020b_InitialScale}, /* 4 */ |
6832 | {hv7131bxx_InitialScale, hv7131bxx_Initial}, /* 5 */ | 6834 | {hv7131b_Initial, hv7131b_InitialScale}, /* 5 */ |
6833 | {hv7131cxx_InitialScale, hv7131cxx_Initial}, /* 6 */ | 6835 | {hv7131r_Initial, hv7131r_InitialScale}, /* 6 */ |
6834 | {icm105axx_InitialScale, icm105axx_Initial}, /* 7 */ | 6836 | {icm105a_Initial, icm105a_InitialScale}, /* 7 */ |
6835 | {MC501CB_InitialScale, MC501CB_Initial}, /* 8 */ | 6837 | {mc501cb_Initial, mc501cb_InitialScale}, /* 8 */ |
6836 | {mi0360soc_Initial, mi0360soc_InitialScale}, /* 9 */ | 6838 | {mi0360soc_Initial, mi0360soc_InitialScale}, /* 9 */ |
6837 | {OV7620_mode0, OV7620_mode1}, /* 10 */ | 6839 | {ov7620_Initial, ov7620_InitialScale}, /* 10 */ |
6838 | {ov7630c_InitialScale, ov7630c_Initial}, /* 11 */ | 6840 | {ov7630c_Initial, ov7630c_InitialScale}, /* 11 */ |
6839 | {pas106b_InitialScale, pas106b_Initial}, /* 12 */ | 6841 | {pas106b_Initial, pas106b_InitialScale}, /* 12 */ |
6840 | {pas202b_Initial, pas202b_InitialScale}, /* 13 */ | 6842 | {pas202b_Initial, pas202b_InitialScale}, /* 13 */ |
6841 | {pb0330_Initial, pb0330_InitialScale}, /* 14 */ | 6843 | {pb0330_Initial, pb0330_InitialScale}, /* 14 */ |
6842 | {PO2030_mode0, PO2030_mode1}, /* 15 */ | 6844 | {po2030_Initial, po2030_InitialScale}, /* 15 */ |
6843 | {tas5130CK_InitialScale, tas5130CK_Initial}, /* 16 */ | 6845 | {tas5130cK_Initial, tas5130cK_InitialScale}, /* 16 */ |
6844 | {tas5130cxx_Initial, tas5130cxx_InitialScale}, /* 17 */ | 6846 | {tas5130cxx_Initial, tas5130cxx_InitialScale}, /* 17 */ |
6845 | {tas5130c_vf0250_InitialScale, tas5130c_vf0250_Initial}, | 6847 | {tas5130c_vf0250_Initial, tas5130c_vf0250_InitialScale}, |
6846 | /* 18 */ | 6848 | /* 18 */ |
6847 | }; | 6849 | }; |
6848 | 6850 | ||
@@ -6854,8 +6856,7 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
6854 | 0x21); /* JPEG 422 */ | 6856 | 0x21); /* JPEG 422 */ |
6855 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); | 6857 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); |
6856 | 6858 | ||
6857 | mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; | 6859 | mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; |
6858 | zc3_init = init_tb[(int) sd->sensor][mode]; | ||
6859 | switch (sd->sensor) { | 6860 | switch (sd->sensor) { |
6860 | case SENSOR_HV7131C: | 6861 | case SENSOR_HV7131C: |
6861 | zcxx_probeSensor(gspca_dev); | 6862 | zcxx_probeSensor(gspca_dev); |
@@ -6864,7 +6865,7 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
6864 | usb_exchange(gspca_dev, pas106b_Initial_com); | 6865 | usb_exchange(gspca_dev, pas106b_Initial_com); |
6865 | break; | 6866 | break; |
6866 | } | 6867 | } |
6867 | usb_exchange(gspca_dev, zc3_init); | 6868 | usb_exchange(gspca_dev, init_tb[sd->sensor][mode]); |
6868 | 6869 | ||
6869 | switch (sd->sensor) { | 6870 | switch (sd->sensor) { |
6870 | case SENSOR_ADCM2700: | 6871 | case SENSOR_ADCM2700: |
@@ -6883,6 +6884,11 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
6883 | reg_w(dev, 0x02, 0x003b); | 6884 | reg_w(dev, 0x02, 0x003b); |
6884 | reg_w(dev, 0x00, 0x0038); | 6885 | reg_w(dev, 0x00, 0x0038); |
6885 | break; | 6886 | break; |
6887 | case SENSOR_PAS202B: | ||
6888 | reg_w(dev, 0x03, 0x003b); | ||
6889 | reg_w(dev, 0x0c, 0x003a); | ||
6890 | reg_w(dev, 0x0b, 0x0039); | ||
6891 | break; | ||
6886 | } | 6892 | } |
6887 | 6893 | ||
6888 | setmatrix(gspca_dev); | 6894 | setmatrix(gspca_dev); |
@@ -6961,13 +6967,13 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
6961 | switch (sd->sensor) { | 6967 | switch (sd->sensor) { |
6962 | case SENSOR_PO2030: | 6968 | case SENSOR_PO2030: |
6963 | msleep(50); | 6969 | msleep(50); |
6964 | reg_r(gspca_dev, 0x0008); | ||
6965 | reg_r(gspca_dev, 0x0007); | ||
6966 | /*fall thru*/ | ||
6967 | case SENSOR_PAS202B: | ||
6968 | reg_w(dev, 0x00, 0x0007); /* (from win traces) */ | 6970 | reg_w(dev, 0x00, 0x0007); /* (from win traces) */ |
6969 | reg_w(dev, 0x02, ZC3XX_R008_CLOCKSETTING); | 6971 | reg_w(dev, 0x02, ZC3XX_R008_CLOCKSETTING); |
6970 | break; | 6972 | break; |
6973 | case SENSOR_PAS202B: | ||
6974 | reg_w(dev, 0x32, 0x0007); /* (from win traces) */ | ||
6975 | reg_w(dev, 0x02, ZC3XX_R008_CLOCKSETTING); | ||
6976 | break; | ||
6971 | } | 6977 | } |
6972 | return 0; | 6978 | return 0; |
6973 | } | 6979 | } |
@@ -7165,6 +7171,22 @@ static int sd_get_jcomp(struct gspca_dev *gspca_dev, | |||
7165 | return 0; | 7171 | return 0; |
7166 | } | 7172 | } |
7167 | 7173 | ||
7174 | #ifdef CONFIG_INPUT | ||
7175 | static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, | ||
7176 | u8 *data, /* interrupt packet data */ | ||
7177 | int len) /* interrput packet length */ | ||
7178 | { | ||
7179 | if (len == 8 && data[4] == 1) { | ||
7180 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); | ||
7181 | input_sync(gspca_dev->input_dev); | ||
7182 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); | ||
7183 | input_sync(gspca_dev->input_dev); | ||
7184 | } | ||
7185 | |||
7186 | return 0; | ||
7187 | } | ||
7188 | #endif | ||
7189 | |||
7168 | static const struct sd_desc sd_desc = { | 7190 | static const struct sd_desc sd_desc = { |
7169 | .name = MODULE_NAME, | 7191 | .name = MODULE_NAME, |
7170 | .ctrls = sd_ctrls, | 7192 | .ctrls = sd_ctrls, |
@@ -7177,6 +7199,9 @@ static const struct sd_desc sd_desc = { | |||
7177 | .querymenu = sd_querymenu, | 7199 | .querymenu = sd_querymenu, |
7178 | .get_jcomp = sd_get_jcomp, | 7200 | .get_jcomp = sd_get_jcomp, |
7179 | .set_jcomp = sd_set_jcomp, | 7201 | .set_jcomp = sd_set_jcomp, |
7202 | #ifdef CONFIG_INPUT | ||
7203 | .int_pkt_scan = sd_int_pkt_scan, | ||
7204 | #endif | ||
7180 | }; | 7205 | }; |
7181 | 7206 | ||
7182 | static const __devinitdata struct usb_device_id device_table[] = { | 7207 | static const __devinitdata struct usb_device_id device_table[] = { |
diff --git a/drivers/media/video/hdpvr/hdpvr-core.c b/drivers/media/video/hdpvr/hdpvr-core.c index 51f393d03a46..2fc9865fd486 100644 --- a/drivers/media/video/hdpvr/hdpvr-core.c +++ b/drivers/media/video/hdpvr/hdpvr-core.c | |||
@@ -39,12 +39,12 @@ int hdpvr_debug; | |||
39 | module_param(hdpvr_debug, int, S_IRUGO|S_IWUSR); | 39 | module_param(hdpvr_debug, int, S_IRUGO|S_IWUSR); |
40 | MODULE_PARM_DESC(hdpvr_debug, "enable debugging output"); | 40 | MODULE_PARM_DESC(hdpvr_debug, "enable debugging output"); |
41 | 41 | ||
42 | uint default_video_input = HDPVR_VIDEO_INPUTS; | 42 | static uint default_video_input = HDPVR_VIDEO_INPUTS; |
43 | module_param(default_video_input, uint, S_IRUGO|S_IWUSR); | 43 | module_param(default_video_input, uint, S_IRUGO|S_IWUSR); |
44 | MODULE_PARM_DESC(default_video_input, "default video input: 0=Component / " | 44 | MODULE_PARM_DESC(default_video_input, "default video input: 0=Component / " |
45 | "1=S-Video / 2=Composite"); | 45 | "1=S-Video / 2=Composite"); |
46 | 46 | ||
47 | uint default_audio_input = HDPVR_AUDIO_INPUTS; | 47 | static uint default_audio_input = HDPVR_AUDIO_INPUTS; |
48 | module_param(default_audio_input, uint, S_IRUGO|S_IWUSR); | 48 | module_param(default_audio_input, uint, S_IRUGO|S_IWUSR); |
49 | MODULE_PARM_DESC(default_audio_input, "default audio input: 0=RCA back / " | 49 | MODULE_PARM_DESC(default_audio_input, "default audio input: 0=RCA back / " |
50 | "1=RCA front / 2=S/PDIF"); | 50 | "1=RCA front / 2=S/PDIF"); |
@@ -59,6 +59,7 @@ static struct usb_device_id hdpvr_table[] = { | |||
59 | { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID) }, | 59 | { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID) }, |
60 | { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID1) }, | 60 | { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID1) }, |
61 | { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID2) }, | 61 | { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID2) }, |
62 | { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID3) }, | ||
62 | { } /* Terminating entry */ | 63 | { } /* Terminating entry */ |
63 | }; | 64 | }; |
64 | MODULE_DEVICE_TABLE(usb, hdpvr_table); | 65 | MODULE_DEVICE_TABLE(usb, hdpvr_table); |
diff --git a/drivers/media/video/hdpvr/hdpvr-video.c b/drivers/media/video/hdpvr/hdpvr-video.c index fdd782039e9d..196f82de48f0 100644 --- a/drivers/media/video/hdpvr/hdpvr-video.c +++ b/drivers/media/video/hdpvr/hdpvr-video.c | |||
@@ -302,7 +302,8 @@ static int hdpvr_start_streaming(struct hdpvr_device *dev) | |||
302 | /* function expects dev->io_mutex to be hold by caller */ | 302 | /* function expects dev->io_mutex to be hold by caller */ |
303 | static int hdpvr_stop_streaming(struct hdpvr_device *dev) | 303 | static int hdpvr_stop_streaming(struct hdpvr_device *dev) |
304 | { | 304 | { |
305 | uint actual_length, c = 0; | 305 | int actual_length; |
306 | uint c = 0; | ||
306 | u8 *buf; | 307 | u8 *buf; |
307 | 308 | ||
308 | if (dev->status == STATUS_IDLE) | 309 | if (dev->status == STATUS_IDLE) |
@@ -572,7 +573,7 @@ static int vidioc_querycap(struct file *file, void *priv, | |||
572 | struct hdpvr_device *dev = video_drvdata(file); | 573 | struct hdpvr_device *dev = video_drvdata(file); |
573 | 574 | ||
574 | strcpy(cap->driver, "hdpvr"); | 575 | strcpy(cap->driver, "hdpvr"); |
575 | strcpy(cap->card, "Haupauge HD PVR"); | 576 | strcpy(cap->card, "Hauppauge HD PVR"); |
576 | usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)); | 577 | usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)); |
577 | cap->version = HDPVR_VERSION; | 578 | cap->version = HDPVR_VERSION; |
578 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | | 579 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | |
diff --git a/drivers/media/video/hdpvr/hdpvr.h b/drivers/media/video/hdpvr/hdpvr.h index 1edd8759121e..49ae25d83d10 100644 --- a/drivers/media/video/hdpvr/hdpvr.h +++ b/drivers/media/video/hdpvr/hdpvr.h | |||
@@ -30,6 +30,7 @@ | |||
30 | #define HD_PVR_PRODUCT_ID 0x4900 | 30 | #define HD_PVR_PRODUCT_ID 0x4900 |
31 | #define HD_PVR_PRODUCT_ID1 0x4901 | 31 | #define HD_PVR_PRODUCT_ID1 0x4901 |
32 | #define HD_PVR_PRODUCT_ID2 0x4902 | 32 | #define HD_PVR_PRODUCT_ID2 0x4902 |
33 | #define HD_PVR_PRODUCT_ID3 0x4982 | ||
33 | 34 | ||
34 | #define UNSET (-1U) | 35 | #define UNSET (-1U) |
35 | 36 | ||
diff --git a/drivers/media/video/hexium_gemini.c b/drivers/media/video/hexium_gemini.c index 60d992ee2589..e620a3a92f25 100644 --- a/drivers/media/video/hexium_gemini.c +++ b/drivers/media/video/hexium_gemini.c | |||
@@ -352,9 +352,13 @@ static struct saa7146_ext_vv vv_data; | |||
352 | static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info) | 352 | static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info) |
353 | { | 353 | { |
354 | struct hexium *hexium = (struct hexium *) dev->ext_priv; | 354 | struct hexium *hexium = (struct hexium *) dev->ext_priv; |
355 | int ret; | ||
355 | 356 | ||
356 | DEB_EE((".\n")); | 357 | DEB_EE((".\n")); |
357 | 358 | ||
359 | ret = saa7146_vv_devinit(dev); | ||
360 | if (ret) | ||
361 | return ret; | ||
358 | hexium = kzalloc(sizeof(struct hexium), GFP_KERNEL); | 362 | hexium = kzalloc(sizeof(struct hexium), GFP_KERNEL); |
359 | if (NULL == hexium) { | 363 | if (NULL == hexium) { |
360 | printk("hexium_gemini: not enough kernel memory in hexium_attach().\n"); | 364 | printk("hexium_gemini: not enough kernel memory in hexium_attach().\n"); |
@@ -400,9 +404,10 @@ static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_d | |||
400 | vv_data.ops.vidioc_enum_input = vidioc_enum_input; | 404 | vv_data.ops.vidioc_enum_input = vidioc_enum_input; |
401 | vv_data.ops.vidioc_g_input = vidioc_g_input; | 405 | vv_data.ops.vidioc_g_input = vidioc_g_input; |
402 | vv_data.ops.vidioc_s_input = vidioc_s_input; | 406 | vv_data.ops.vidioc_s_input = vidioc_s_input; |
403 | if (0 != saa7146_register_device(&hexium->video_dev, dev, "hexium gemini", VFL_TYPE_GRABBER)) { | 407 | ret = saa7146_register_device(&hexium->video_dev, dev, "hexium gemini", VFL_TYPE_GRABBER); |
408 | if (ret < 0) { | ||
404 | printk("hexium_gemini: cannot register capture v4l2 device. skipping.\n"); | 409 | printk("hexium_gemini: cannot register capture v4l2 device. skipping.\n"); |
405 | return -1; | 410 | return ret; |
406 | } | 411 | } |
407 | 412 | ||
408 | printk("hexium_gemini: found 'hexium gemini' frame grabber-%d.\n", hexium_num); | 413 | printk("hexium_gemini: found 'hexium gemini' frame grabber-%d.\n", hexium_num); |
diff --git a/drivers/media/video/hexium_orion.c b/drivers/media/video/hexium_orion.c index 938a1f8f880a..fe596a1c12a8 100644 --- a/drivers/media/video/hexium_orion.c +++ b/drivers/media/video/hexium_orion.c | |||
@@ -216,6 +216,10 @@ static int hexium_probe(struct saa7146_dev *dev) | |||
216 | return -EFAULT; | 216 | return -EFAULT; |
217 | } | 217 | } |
218 | 218 | ||
219 | err = saa7146_vv_devinit(dev); | ||
220 | if (err) | ||
221 | return err; | ||
222 | |||
219 | hexium = kzalloc(sizeof(struct hexium), GFP_KERNEL); | 223 | hexium = kzalloc(sizeof(struct hexium), GFP_KERNEL); |
220 | if (NULL == hexium) { | 224 | if (NULL == hexium) { |
221 | printk("hexium_orion: hexium_probe: not enough kernel memory.\n"); | 225 | printk("hexium_orion: hexium_probe: not enough kernel memory.\n"); |
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index b86e35386cee..da18d698e7f2 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c | |||
@@ -299,7 +299,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
299 | { | 299 | { |
300 | struct ir_scancode_table *ir_codes = NULL; | 300 | struct ir_scancode_table *ir_codes = NULL; |
301 | const char *name = NULL; | 301 | const char *name = NULL; |
302 | int ir_type = 0; | 302 | u64 ir_type = 0; |
303 | struct IR_i2c *ir; | 303 | struct IR_i2c *ir; |
304 | struct input_dev *input_dev; | 304 | struct input_dev *input_dev; |
305 | struct i2c_adapter *adap = client->adapter; | 305 | struct i2c_adapter *adap = client->adapter; |
@@ -331,6 +331,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
331 | ir_codes = &ir_codes_pv951_table; | 331 | ir_codes = &ir_codes_pv951_table; |
332 | break; | 332 | break; |
333 | case 0x18: | 333 | case 0x18: |
334 | case 0x1f: | ||
334 | case 0x1a: | 335 | case 0x1a: |
335 | name = "Hauppauge"; | 336 | name = "Hauppauge"; |
336 | ir->get_key = get_key_haup; | 337 | ir->get_key = get_key_haup; |
@@ -446,7 +447,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
446 | input_dev->name = ir->name; | 447 | input_dev->name = ir->name; |
447 | input_dev->phys = ir->phys; | 448 | input_dev->phys = ir->phys; |
448 | 449 | ||
449 | err = ir_input_register(ir->input, ir->ir_codes); | 450 | err = ir_input_register(ir->input, ir->ir_codes, NULL); |
450 | if (err) | 451 | if (err) |
451 | goto err_out_free; | 452 | goto err_out_free; |
452 | 453 | ||
diff --git a/drivers/media/video/ivtv/ivtv-cards.c b/drivers/media/video/ivtv/ivtv-cards.c index 79d0fe4990d6..ca1fd3227a93 100644 --- a/drivers/media/video/ivtv/ivtv-cards.c +++ b/drivers/media/video/ivtv/ivtv-cards.c | |||
@@ -1210,6 +1210,53 @@ static const struct ivtv_card ivtv_card_buffalo = { | |||
1210 | .i2c = &ivtv_i2c_std, | 1210 | .i2c = &ivtv_i2c_std, |
1211 | }; | 1211 | }; |
1212 | 1212 | ||
1213 | /* ------------------------------------------------------------------------- */ | ||
1214 | /* Sony Kikyou */ | ||
1215 | |||
1216 | static const struct ivtv_card_pci_info ivtv_pci_kikyou[] = { | ||
1217 | { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_SONY, 0x813d }, | ||
1218 | { 0, 0, 0 } | ||
1219 | }; | ||
1220 | |||
1221 | static const struct ivtv_card ivtv_card_kikyou = { | ||
1222 | .type = IVTV_CARD_KIKYOU, | ||
1223 | .name = "Sony VAIO Giga Pocket (ENX Kikyou)", | ||
1224 | .v4l2_capabilities = IVTV_CAP_ENCODER, | ||
1225 | .hw_video = IVTV_HW_SAA7115, | ||
1226 | .hw_audio = IVTV_HW_GPIO, | ||
1227 | .hw_audio_ctrl = IVTV_HW_GPIO, | ||
1228 | .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7115 | IVTV_HW_TUNER, | ||
1229 | .video_inputs = { | ||
1230 | { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_COMPOSITE1 }, | ||
1231 | { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE1 }, | ||
1232 | { IVTV_CARD_INPUT_SVIDEO1, 1, IVTV_SAA71XX_SVIDEO1 }, | ||
1233 | }, | ||
1234 | .audio_inputs = { | ||
1235 | { IVTV_CARD_INPUT_AUD_TUNER, IVTV_GPIO_TUNER }, | ||
1236 | { IVTV_CARD_INPUT_LINE_IN1, IVTV_GPIO_LINE_IN }, | ||
1237 | { IVTV_CARD_INPUT_LINE_IN2, IVTV_GPIO_LINE_IN }, | ||
1238 | }, | ||
1239 | .gpio_init = { .direction = 0x03e1, .initial_value = 0x0320 }, | ||
1240 | .gpio_audio_input = { .mask = 0x0060, | ||
1241 | .tuner = 0x0020, | ||
1242 | .linein = 0x0000, | ||
1243 | .radio = 0x0060 }, | ||
1244 | .gpio_audio_mute = { .mask = 0x0000, | ||
1245 | .mute = 0x0000 }, /* 0x200? Disable for now. */ | ||
1246 | .gpio_audio_mode = { .mask = 0x0080, | ||
1247 | .mono = 0x0000, | ||
1248 | .stereo = 0x0000, /* SAP */ | ||
1249 | .lang1 = 0x0080, | ||
1250 | .lang2 = 0x0000, | ||
1251 | .both = 0x0080 }, | ||
1252 | .tuners = { | ||
1253 | { .std = V4L2_STD_ALL, .tuner = TUNER_SONY_BTF_PXN01Z }, | ||
1254 | }, | ||
1255 | .pci_list = ivtv_pci_kikyou, | ||
1256 | .i2c = &ivtv_i2c_std, | ||
1257 | }; | ||
1258 | |||
1259 | |||
1213 | static const struct ivtv_card *ivtv_card_list[] = { | 1260 | static const struct ivtv_card *ivtv_card_list[] = { |
1214 | &ivtv_card_pvr250, | 1261 | &ivtv_card_pvr250, |
1215 | &ivtv_card_pvr350, | 1262 | &ivtv_card_pvr350, |
@@ -1238,6 +1285,7 @@ static const struct ivtv_card *ivtv_card_list[] = { | |||
1238 | &ivtv_card_aver_m104, | 1285 | &ivtv_card_aver_m104, |
1239 | &ivtv_card_buffalo, | 1286 | &ivtv_card_buffalo, |
1240 | &ivtv_card_aver_ultra1500mce, | 1287 | &ivtv_card_aver_ultra1500mce, |
1288 | &ivtv_card_kikyou, | ||
1241 | 1289 | ||
1242 | /* Variations of standard cards but with the same PCI IDs. | 1290 | /* Variations of standard cards but with the same PCI IDs. |
1243 | These cards must come last in this list. */ | 1291 | These cards must come last in this list. */ |
diff --git a/drivers/media/video/ivtv/ivtv-cards.h b/drivers/media/video/ivtv/ivtv-cards.h index 6148827ec885..78eca992e1fd 100644 --- a/drivers/media/video/ivtv/ivtv-cards.h +++ b/drivers/media/video/ivtv/ivtv-cards.h | |||
@@ -51,7 +51,8 @@ | |||
51 | #define IVTV_CARD_AVER_M104 24 /* AverMedia M104 miniPCI card */ | 51 | #define IVTV_CARD_AVER_M104 24 /* AverMedia M104 miniPCI card */ |
52 | #define IVTV_CARD_BUFFALO_MV5L 25 /* Buffalo PC-MV5L/PCI card */ | 52 | #define IVTV_CARD_BUFFALO_MV5L 25 /* Buffalo PC-MV5L/PCI card */ |
53 | #define IVTV_CARD_AVER_ULTRA1500MCE 26 /* AVerMedia UltraTV 1500 MCE */ | 53 | #define IVTV_CARD_AVER_ULTRA1500MCE 26 /* AVerMedia UltraTV 1500 MCE */ |
54 | #define IVTV_CARD_LAST 26 | 54 | #define IVTV_CARD_KIKYOU 27 /* Sony VAIO Giga Pocket (ENX Kikyou) */ |
55 | #define IVTV_CARD_LAST 27 | ||
55 | 56 | ||
56 | /* Variants of existing cards but with the same PCI IDs. The driver | 57 | /* Variants of existing cards but with the same PCI IDs. The driver |
57 | detects these based on other device information. | 58 | detects these based on other device information. |
@@ -86,6 +87,7 @@ | |||
86 | #define IVTV_PCI_ID_MELCO 0x1154 | 87 | #define IVTV_PCI_ID_MELCO 0x1154 |
87 | #define IVTV_PCI_ID_GOTVIEW1 0xffac | 88 | #define IVTV_PCI_ID_GOTVIEW1 0xffac |
88 | #define IVTV_PCI_ID_GOTVIEW2 0xffad | 89 | #define IVTV_PCI_ID_GOTVIEW2 0xffad |
90 | #define IVTV_PCI_ID_SONY 0x104d | ||
89 | 91 | ||
90 | /* hardware flags, no gaps allowed */ | 92 | /* hardware flags, no gaps allowed */ |
91 | #define IVTV_HW_CX25840 (1 << 0) | 93 | #define IVTV_HW_CX25840 (1 << 0) |
diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index 347c3344f56d..9a250548be4d 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c | |||
@@ -193,6 +193,7 @@ MODULE_PARM_DESC(cardtype, | |||
193 | "\t\t\t25 = AverMedia M104 (not yet working)\n" | 193 | "\t\t\t25 = AverMedia M104 (not yet working)\n" |
194 | "\t\t\t26 = Buffalo PC-MV5L/PCI\n" | 194 | "\t\t\t26 = Buffalo PC-MV5L/PCI\n" |
195 | "\t\t\t27 = AVerMedia UltraTV 1500 MCE\n" | 195 | "\t\t\t27 = AVerMedia UltraTV 1500 MCE\n" |
196 | "\t\t\t28 = Sony VAIO Giga Pocket (ENX Kikyou)\n" | ||
196 | "\t\t\t 0 = Autodetect (default)\n" | 197 | "\t\t\t 0 = Autodetect (default)\n" |
197 | "\t\t\t-1 = Ignore this card\n\t\t"); | 198 | "\t\t\t-1 = Ignore this card\n\t\t"); |
198 | MODULE_PARM_DESC(pal, "Set PAL standard: BGH, DK, I, M, N, Nc, 60"); | 199 | MODULE_PARM_DESC(pal, "Set PAL standard: BGH, DK, I, M, N, Nc, 60"); |
diff --git a/drivers/media/video/ivtv/ivtv-firmware.c b/drivers/media/video/ivtv/ivtv-firmware.c index c1b7ec475c27..a71e8ba306b0 100644 --- a/drivers/media/video/ivtv/ivtv-firmware.c +++ b/drivers/media/video/ivtv/ivtv-firmware.c | |||
@@ -258,7 +258,7 @@ void ivtv_init_mpeg_decoder(struct ivtv *itv) | |||
258 | IVTV_ERR("ivtv_init_mpeg_decoder failed to start playback\n"); | 258 | IVTV_ERR("ivtv_init_mpeg_decoder failed to start playback\n"); |
259 | return; | 259 | return; |
260 | } | 260 | } |
261 | ivtv_api_get_data(&itv->dec_mbox, IVTV_MBOX_DMA, data); | 261 | ivtv_api_get_data(&itv->dec_mbox, IVTV_MBOX_DMA, 2, data); |
262 | mem_offset = itv->dec_mem + data[1]; | 262 | mem_offset = itv->dec_mem + data[1]; |
263 | 263 | ||
264 | if ((readbytes = load_fw_direct(IVTV_DECODE_INIT_MPEG_FILENAME, | 264 | if ((readbytes = load_fw_direct(IVTV_DECODE_INIT_MPEG_FILENAME, |
diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c index cd9db0bf33bf..12d36ca91d53 100644 --- a/drivers/media/video/ivtv/ivtv-irq.c +++ b/drivers/media/video/ivtv/ivtv-irq.c | |||
@@ -562,7 +562,7 @@ static void ivtv_irq_enc_dma_complete(struct ivtv *itv) | |||
562 | u32 data[CX2341X_MBOX_MAX_DATA]; | 562 | u32 data[CX2341X_MBOX_MAX_DATA]; |
563 | struct ivtv_stream *s; | 563 | struct ivtv_stream *s; |
564 | 564 | ||
565 | ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA_END, data); | 565 | ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA_END, 2, data); |
566 | IVTV_DEBUG_HI_IRQ("ENC DMA COMPLETE %x %d (%d)\n", data[0], data[1], itv->cur_dma_stream); | 566 | IVTV_DEBUG_HI_IRQ("ENC DMA COMPLETE %x %d (%d)\n", data[0], data[1], itv->cur_dma_stream); |
567 | 567 | ||
568 | del_timer(&itv->dma_timer); | 568 | del_timer(&itv->dma_timer); |
@@ -638,7 +638,7 @@ static void ivtv_irq_dma_err(struct ivtv *itv) | |||
638 | u32 data[CX2341X_MBOX_MAX_DATA]; | 638 | u32 data[CX2341X_MBOX_MAX_DATA]; |
639 | 639 | ||
640 | del_timer(&itv->dma_timer); | 640 | del_timer(&itv->dma_timer); |
641 | ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA_END, data); | 641 | ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA_END, 2, data); |
642 | IVTV_DEBUG_WARN("DMA ERROR %08x %08x %08x %d\n", data[0], data[1], | 642 | IVTV_DEBUG_WARN("DMA ERROR %08x %08x %08x %d\n", data[0], data[1], |
643 | read_reg(IVTV_REG_DMASTATUS), itv->cur_dma_stream); | 643 | read_reg(IVTV_REG_DMASTATUS), itv->cur_dma_stream); |
644 | write_reg(read_reg(IVTV_REG_DMASTATUS) & 3, IVTV_REG_DMASTATUS); | 644 | write_reg(read_reg(IVTV_REG_DMASTATUS) & 3, IVTV_REG_DMASTATUS); |
@@ -669,7 +669,7 @@ static void ivtv_irq_enc_start_cap(struct ivtv *itv) | |||
669 | struct ivtv_stream *s; | 669 | struct ivtv_stream *s; |
670 | 670 | ||
671 | /* Get DMA destination and size arguments from card */ | 671 | /* Get DMA destination and size arguments from card */ |
672 | ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA, data); | 672 | ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA, 7, data); |
673 | IVTV_DEBUG_HI_IRQ("ENC START CAP %d: %08x %08x\n", data[0], data[1], data[2]); | 673 | IVTV_DEBUG_HI_IRQ("ENC START CAP %d: %08x %08x\n", data[0], data[1], data[2]); |
674 | 674 | ||
675 | if (data[0] > 2 || data[1] == 0 || data[2] == 0) { | 675 | if (data[0] > 2 || data[1] == 0 || data[2] == 0) { |
@@ -713,9 +713,9 @@ static void ivtv_irq_dec_data_req(struct ivtv *itv) | |||
713 | struct ivtv_stream *s; | 713 | struct ivtv_stream *s; |
714 | 714 | ||
715 | /* YUV or MPG */ | 715 | /* YUV or MPG */ |
716 | ivtv_api_get_data(&itv->dec_mbox, IVTV_MBOX_DMA, data); | ||
717 | 716 | ||
718 | if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags)) { | 717 | if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags)) { |
718 | ivtv_api_get_data(&itv->dec_mbox, IVTV_MBOX_DMA, 2, data); | ||
719 | itv->dma_data_req_size = | 719 | itv->dma_data_req_size = |
720 | 1080 * ((itv->yuv_info.v4l2_src_h + 31) & ~31); | 720 | 1080 * ((itv->yuv_info.v4l2_src_h + 31) & ~31); |
721 | itv->dma_data_req_offset = data[1]; | 721 | itv->dma_data_req_offset = data[1]; |
@@ -724,6 +724,7 @@ static void ivtv_irq_dec_data_req(struct ivtv *itv) | |||
724 | s = &itv->streams[IVTV_DEC_STREAM_TYPE_YUV]; | 724 | s = &itv->streams[IVTV_DEC_STREAM_TYPE_YUV]; |
725 | } | 725 | } |
726 | else { | 726 | else { |
727 | ivtv_api_get_data(&itv->dec_mbox, IVTV_MBOX_DMA, 3, data); | ||
727 | itv->dma_data_req_size = min_t(u32, data[2], 0x10000); | 728 | itv->dma_data_req_size = min_t(u32, data[2], 0x10000); |
728 | itv->dma_data_req_offset = data[1]; | 729 | itv->dma_data_req_offset = data[1]; |
729 | s = &itv->streams[IVTV_DEC_STREAM_TYPE_MPG]; | 730 | s = &itv->streams[IVTV_DEC_STREAM_TYPE_MPG]; |
@@ -940,9 +941,10 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id) | |||
940 | ivtv_dma_enc_start(s); | 941 | ivtv_dma_enc_start(s); |
941 | break; | 942 | break; |
942 | } | 943 | } |
943 | if (i == IVTV_MAX_STREAMS && test_and_clear_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags)) { | 944 | |
945 | if (i == IVTV_MAX_STREAMS && | ||
946 | test_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags)) | ||
944 | ivtv_udma_start(itv); | 947 | ivtv_udma_start(itv); |
945 | } | ||
946 | } | 948 | } |
947 | 949 | ||
948 | if ((combo & IVTV_IRQ_DMA) && !test_bit(IVTV_F_I_PIO, &itv->i_flags)) { | 950 | if ((combo & IVTV_IRQ_DMA) && !test_bit(IVTV_F_I_PIO, &itv->i_flags)) { |
diff --git a/drivers/media/video/ivtv/ivtv-mailbox.c b/drivers/media/video/ivtv/ivtv-mailbox.c index 1b5c0ac09a85..84577f6f41a2 100644 --- a/drivers/media/video/ivtv/ivtv-mailbox.c +++ b/drivers/media/video/ivtv/ivtv-mailbox.c | |||
@@ -369,10 +369,11 @@ int ivtv_vapi(struct ivtv *itv, int cmd, int args, ...) | |||
369 | } | 369 | } |
370 | 370 | ||
371 | /* This one is for stuff that can't sleep.. irq handlers, etc.. */ | 371 | /* This one is for stuff that can't sleep.. irq handlers, etc.. */ |
372 | void ivtv_api_get_data(struct ivtv_mailbox_data *mbdata, int mb, u32 data[]) | 372 | void ivtv_api_get_data(struct ivtv_mailbox_data *mbdata, int mb, |
373 | int argc, u32 data[]) | ||
373 | { | 374 | { |
375 | volatile u32 __iomem *p = mbdata->mbox[mb].data; | ||
374 | int i; | 376 | int i; |
375 | 377 | for (i = 0; i < argc; i++, p++) | |
376 | for (i = 0; i < CX2341X_MBOX_MAX_DATA; i++) | 378 | data[i] = readl(p); |
377 | data[i] = readl(&mbdata->mbox[mb].data[i]); | ||
378 | } | 379 | } |
diff --git a/drivers/media/video/ivtv/ivtv-mailbox.h b/drivers/media/video/ivtv/ivtv-mailbox.h index 6ef12091e3f3..8247662c928e 100644 --- a/drivers/media/video/ivtv/ivtv-mailbox.h +++ b/drivers/media/video/ivtv/ivtv-mailbox.h | |||
@@ -24,7 +24,8 @@ | |||
24 | #define IVTV_MBOX_DMA_END 8 | 24 | #define IVTV_MBOX_DMA_END 8 |
25 | #define IVTV_MBOX_DMA 9 | 25 | #define IVTV_MBOX_DMA 9 |
26 | 26 | ||
27 | void ivtv_api_get_data(struct ivtv_mailbox_data *mbox, int mb, u32 data[]); | 27 | void ivtv_api_get_data(struct ivtv_mailbox_data *mbdata, int mb, |
28 | int argc, u32 data[]); | ||
28 | int ivtv_api(struct ivtv *itv, int cmd, int args, u32 data[]); | 29 | int ivtv_api(struct ivtv *itv, int cmd, int args, u32 data[]); |
29 | int ivtv_vapi_result(struct ivtv *itv, u32 data[CX2341X_MBOX_MAX_DATA], int cmd, int args, ...); | 30 | int ivtv_vapi_result(struct ivtv *itv, u32 data[CX2341X_MBOX_MAX_DATA], int cmd, int args, ...); |
30 | int ivtv_vapi(struct ivtv *itv, int cmd, int args, ...); | 31 | int ivtv_vapi(struct ivtv *itv, int cmd, int args, ...); |
diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c index e12c6022373e..1f9387f6ca24 100644 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ b/drivers/media/video/ivtv/ivtv-streams.c | |||
@@ -577,10 +577,14 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s) | |||
577 | clear_bit(IVTV_F_I_EOS, &itv->i_flags); | 577 | clear_bit(IVTV_F_I_EOS, &itv->i_flags); |
578 | 578 | ||
579 | /* Initialize Digitizer for Capture */ | 579 | /* Initialize Digitizer for Capture */ |
580 | /* Avoid tinny audio problem - ensure audio clocks are going */ | ||
581 | v4l2_subdev_call(itv->sd_audio, audio, s_stream, 1); | ||
582 | /* Avoid unpredictable PCI bus hang - disable video clocks */ | ||
580 | v4l2_subdev_call(itv->sd_video, video, s_stream, 0); | 583 | v4l2_subdev_call(itv->sd_video, video, s_stream, 0); |
581 | ivtv_msleep_timeout(300, 1); | 584 | ivtv_msleep_timeout(150, 1); |
582 | ivtv_vapi(itv, CX2341X_ENC_INITIALIZE_INPUT, 0); | 585 | ivtv_vapi(itv, CX2341X_ENC_INITIALIZE_INPUT, 0); |
583 | v4l2_subdev_call(itv->sd_video, video, s_stream, 1); | 586 | v4l2_subdev_call(itv->sd_video, video, s_stream, 1); |
587 | ivtv_msleep_timeout(150, 1); | ||
584 | } | 588 | } |
585 | 589 | ||
586 | /* begin_capture */ | 590 | /* begin_capture */ |
diff --git a/drivers/media/video/ivtv/ivtv-udma.c b/drivers/media/video/ivtv/ivtv-udma.c index d07ad6c39024..1daf1dd65bf7 100644 --- a/drivers/media/video/ivtv/ivtv-udma.c +++ b/drivers/media/video/ivtv/ivtv-udma.c | |||
@@ -213,6 +213,7 @@ void ivtv_udma_start(struct ivtv *itv) | |||
213 | write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x01, IVTV_REG_DMAXFER); | 213 | write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x01, IVTV_REG_DMAXFER); |
214 | set_bit(IVTV_F_I_DMA, &itv->i_flags); | 214 | set_bit(IVTV_F_I_DMA, &itv->i_flags); |
215 | set_bit(IVTV_F_I_UDMA, &itv->i_flags); | 215 | set_bit(IVTV_F_I_UDMA, &itv->i_flags); |
216 | clear_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags); | ||
216 | } | 217 | } |
217 | 218 | ||
218 | void ivtv_udma_prepare(struct ivtv *itv) | 219 | void ivtv_udma_prepare(struct ivtv *itv) |
diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c index 91df7ec91fb6..1a34d2993e94 100644 --- a/drivers/media/video/mt9v022.c +++ b/drivers/media/video/mt9v022.c | |||
@@ -257,19 +257,18 @@ static int mt9v022_set_bus_param(struct soc_camera_device *icd, | |||
257 | static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd) | 257 | static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd) |
258 | { | 258 | { |
259 | struct soc_camera_link *icl = to_soc_camera_link(icd); | 259 | struct soc_camera_link *icl = to_soc_camera_link(icd); |
260 | unsigned int width_flag; | 260 | unsigned int flags = SOCAM_MASTER | SOCAM_SLAVE | |
261 | SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING | | ||
262 | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW | | ||
263 | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW | | ||
264 | SOCAM_DATA_ACTIVE_HIGH; | ||
261 | 265 | ||
262 | if (icl->query_bus_param) | 266 | if (icl->query_bus_param) |
263 | width_flag = icl->query_bus_param(icl) & | 267 | flags |= icl->query_bus_param(icl) & SOCAM_DATAWIDTH_MASK; |
264 | SOCAM_DATAWIDTH_MASK; | ||
265 | else | 268 | else |
266 | width_flag = SOCAM_DATAWIDTH_10; | 269 | flags |= SOCAM_DATAWIDTH_10; |
267 | 270 | ||
268 | return SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING | | 271 | return soc_camera_apply_sensor_flags(icl, flags); |
269 | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW | | ||
270 | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW | | ||
271 | SOCAM_DATA_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_SLAVE | | ||
272 | width_flag; | ||
273 | } | 272 | } |
274 | 273 | ||
275 | static int mt9v022_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) | 274 | static int mt9v022_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) |
diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c index c1fc6dc776f5..9f01f14e4aa2 100644 --- a/drivers/media/video/mxb.c +++ b/drivers/media/video/mxb.c | |||
@@ -169,7 +169,11 @@ static struct saa7146_extension extension; | |||
169 | static int mxb_probe(struct saa7146_dev *dev) | 169 | static int mxb_probe(struct saa7146_dev *dev) |
170 | { | 170 | { |
171 | struct mxb *mxb = NULL; | 171 | struct mxb *mxb = NULL; |
172 | int err; | ||
172 | 173 | ||
174 | err = saa7146_vv_devinit(dev); | ||
175 | if (err) | ||
176 | return err; | ||
173 | mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL); | 177 | mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL); |
174 | if (mxb == NULL) { | 178 | if (mxb == NULL) { |
175 | DEB_D(("not enough kernel memory.\n")); | 179 | DEB_D(("not enough kernel memory.\n")); |
@@ -294,7 +298,7 @@ static int mxb_init_done(struct saa7146_dev* dev) | |||
294 | /* select tuner-output on saa7111a */ | 298 | /* select tuner-output on saa7111a */ |
295 | i = 0; | 299 | i = 0; |
296 | saa7111a_call(mxb, video, s_routing, SAA7115_COMPOSITE0, | 300 | saa7111a_call(mxb, video, s_routing, SAA7115_COMPOSITE0, |
297 | SAA7111_FMT_CCIR | SAA7111_VBI_BYPASS, 0); | 301 | SAA7111_FMT_CCIR, 0); |
298 | 302 | ||
299 | /* select a tuner type */ | 303 | /* select a tuner type */ |
300 | tun_setup.mode_mask = T_ANALOG_TV; | 304 | tun_setup.mode_mask = T_ANALOG_TV; |
@@ -518,8 +522,8 @@ static int vidioc_s_input(struct file *file, void *fh, unsigned int input) | |||
518 | return err; | 522 | return err; |
519 | 523 | ||
520 | /* switch video in saa7111a */ | 524 | /* switch video in saa7111a */ |
521 | if (saa7111a_call(mxb, video, s_routing, i, 0, 0)) | 525 | if (saa7111a_call(mxb, video, s_routing, i, SAA7111_FMT_CCIR, 0)) |
522 | printk(KERN_ERR "VIDIOC_S_INPUT: could not address saa7111a #1.\n"); | 526 | printk(KERN_ERR "VIDIOC_S_INPUT: could not address saa7111a.\n"); |
523 | 527 | ||
524 | /* switch the audio-source only if necessary */ | 528 | /* switch the audio-source only if necessary */ |
525 | if (0 == mxb->cur_mute) | 529 | if (0 == mxb->cur_mute) |
diff --git a/drivers/media/video/ov772x.c b/drivers/media/video/ov772x.c index 3a45e945a528..7f8ece30c77b 100644 --- a/drivers/media/video/ov772x.c +++ b/drivers/media/video/ov772x.c | |||
@@ -547,7 +547,6 @@ static const struct v4l2_queryctrl ov772x_controls[] = { | |||
547 | }, | 547 | }, |
548 | }; | 548 | }; |
549 | 549 | ||
550 | |||
551 | /* | 550 | /* |
552 | * general function | 551 | * general function |
553 | */ | 552 | */ |
@@ -634,7 +633,12 @@ static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd) | |||
634 | struct soc_camera_link *icl = to_soc_camera_link(icd); | 633 | struct soc_camera_link *icl = to_soc_camera_link(icd); |
635 | unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER | | 634 | unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER | |
636 | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH | | 635 | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH | |
637 | SOCAM_DATA_ACTIVE_HIGH | priv->info->buswidth; | 636 | SOCAM_DATA_ACTIVE_HIGH; |
637 | |||
638 | if (priv->info->flags & OV772X_FLAG_8BIT) | ||
639 | flags |= SOCAM_DATAWIDTH_8; | ||
640 | else | ||
641 | flags |= SOCAM_DATAWIDTH_10; | ||
638 | 642 | ||
639 | return soc_camera_apply_sensor_flags(icl, flags); | 643 | return soc_camera_apply_sensor_flags(icl, flags); |
640 | } | 644 | } |
@@ -1040,15 +1044,6 @@ static int ov772x_video_probe(struct soc_camera_device *icd, | |||
1040 | return -ENODEV; | 1044 | return -ENODEV; |
1041 | 1045 | ||
1042 | /* | 1046 | /* |
1043 | * ov772x only use 8 or 10 bit bus width | ||
1044 | */ | ||
1045 | if (SOCAM_DATAWIDTH_10 != priv->info->buswidth && | ||
1046 | SOCAM_DATAWIDTH_8 != priv->info->buswidth) { | ||
1047 | dev_err(&client->dev, "bus width error\n"); | ||
1048 | return -ENODEV; | ||
1049 | } | ||
1050 | |||
1051 | /* | ||
1052 | * check and show product ID and manufacturer ID | 1047 | * check and show product ID and manufacturer ID |
1053 | */ | 1048 | */ |
1054 | pid = i2c_smbus_read_byte_data(client, PID); | 1049 | pid = i2c_smbus_read_byte_data(client, PID); |
@@ -1130,7 +1125,6 @@ static int ov772x_probe(struct i2c_client *client, | |||
1130 | const struct i2c_device_id *did) | 1125 | const struct i2c_device_id *did) |
1131 | { | 1126 | { |
1132 | struct ov772x_priv *priv; | 1127 | struct ov772x_priv *priv; |
1133 | struct ov772x_camera_info *info; | ||
1134 | struct soc_camera_device *icd = client->dev.platform_data; | 1128 | struct soc_camera_device *icd = client->dev.platform_data; |
1135 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); | 1129 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); |
1136 | struct soc_camera_link *icl; | 1130 | struct soc_camera_link *icl; |
@@ -1145,8 +1139,6 @@ static int ov772x_probe(struct i2c_client *client, | |||
1145 | if (!icl || !icl->priv) | 1139 | if (!icl || !icl->priv) |
1146 | return -EINVAL; | 1140 | return -EINVAL; |
1147 | 1141 | ||
1148 | info = icl->priv; | ||
1149 | |||
1150 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { | 1142 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { |
1151 | dev_err(&adapter->dev, | 1143 | dev_err(&adapter->dev, |
1152 | "I2C-Adapter doesn't support " | 1144 | "I2C-Adapter doesn't support " |
@@ -1158,7 +1150,7 @@ static int ov772x_probe(struct i2c_client *client, | |||
1158 | if (!priv) | 1150 | if (!priv) |
1159 | return -ENOMEM; | 1151 | return -ENOMEM; |
1160 | 1152 | ||
1161 | priv->info = info; | 1153 | priv->info = icl->priv; |
1162 | 1154 | ||
1163 | v4l2_i2c_subdev_init(&priv->subdev, client, &ov772x_subdev_ops); | 1155 | v4l2_i2c_subdev_init(&priv->subdev, client, &ov772x_subdev_ops); |
1164 | 1156 | ||
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index de5485f506b1..cb4057bb07a0 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h | |||
@@ -233,8 +233,9 @@ struct pvr2_hdw { | |||
233 | int state_encoder_waitok; /* Encoder pre-wait done */ | 233 | int state_encoder_waitok; /* Encoder pre-wait done */ |
234 | int state_encoder_runok; /* Encoder has run for >= .25 sec */ | 234 | int state_encoder_runok; /* Encoder has run for >= .25 sec */ |
235 | int state_decoder_run; /* Decoder is running */ | 235 | int state_decoder_run; /* Decoder is running */ |
236 | int state_decoder_ready; /* Decoder is stabilized & streamable */ | ||
236 | int state_usbstream_run; /* FX2 is streaming */ | 237 | int state_usbstream_run; /* FX2 is streaming */ |
237 | int state_decoder_quiescent; /* Decoder idle for > 50msec */ | 238 | int state_decoder_quiescent; /* Decoder idle for minimal interval */ |
238 | int state_pipeline_config; /* Pipeline is configured */ | 239 | int state_pipeline_config; /* Pipeline is configured */ |
239 | int state_pipeline_req; /* Somebody wants to stream */ | 240 | int state_pipeline_req; /* Somebody wants to stream */ |
240 | int state_pipeline_pause; /* Pipeline must be paused */ | 241 | int state_pipeline_pause; /* Pipeline must be paused */ |
@@ -255,9 +256,16 @@ struct pvr2_hdw { | |||
255 | void (*state_func)(void *); | 256 | void (*state_func)(void *); |
256 | void *state_data; | 257 | void *state_data; |
257 | 258 | ||
258 | /* Timer for measuring decoder settling time */ | 259 | /* Timer for measuring required decoder settling time before we're |
260 | allowed to fire it up again. */ | ||
259 | struct timer_list quiescent_timer; | 261 | struct timer_list quiescent_timer; |
260 | 262 | ||
263 | /* Timer for measuring decoder stabilization time, which is the | ||
264 | amount of time we need to let the decoder run before we can | ||
265 | trust its output (otherwise the encoder might see garbage and | ||
266 | then fail to start correctly). */ | ||
267 | struct timer_list decoder_stabilization_timer; | ||
268 | |||
261 | /* Timer for measuring encoder pre-wait time */ | 269 | /* Timer for measuring encoder pre-wait time */ |
262 | struct timer_list encoder_wait_timer; | 270 | struct timer_list encoder_wait_timer; |
263 | 271 | ||
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 1bbdab08fe0e..712b300f723f 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c | |||
@@ -48,11 +48,13 @@ | |||
48 | before we are allowed to start it running. */ | 48 | before we are allowed to start it running. */ |
49 | #define TIME_MSEC_DECODER_WAIT 50 | 49 | #define TIME_MSEC_DECODER_WAIT 50 |
50 | 50 | ||
51 | /* This defines a minimum interval that the decoder must be allowed to run | ||
52 | before we can safely begin using its streaming output. */ | ||
53 | #define TIME_MSEC_DECODER_STABILIZATION_WAIT 300 | ||
54 | |||
51 | /* This defines a minimum interval that the encoder must remain quiet | 55 | /* This defines a minimum interval that the encoder must remain quiet |
52 | before we are allowed to configure it. I had this originally set to | 56 | before we are allowed to configure it. */ |
53 | 50msec, but Martin Dauskardt <martin.dauskardt@gmx.de> reports that | 57 | #define TIME_MSEC_ENCODER_WAIT 50 |
54 | things work better when it's set to 100msec. */ | ||
55 | #define TIME_MSEC_ENCODER_WAIT 100 | ||
56 | 58 | ||
57 | /* This defines the minimum interval that the encoder must successfully run | 59 | /* This defines the minimum interval that the encoder must successfully run |
58 | before we consider that the encoder has run at least once since its | 60 | before we consider that the encoder has run at least once since its |
@@ -334,6 +336,7 @@ static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw); | |||
334 | static void pvr2_hdw_internal_find_stdenum(struct pvr2_hdw *hdw); | 336 | static void pvr2_hdw_internal_find_stdenum(struct pvr2_hdw *hdw); |
335 | static void pvr2_hdw_internal_set_std_avail(struct pvr2_hdw *hdw); | 337 | static void pvr2_hdw_internal_set_std_avail(struct pvr2_hdw *hdw); |
336 | static void pvr2_hdw_quiescent_timeout(unsigned long); | 338 | static void pvr2_hdw_quiescent_timeout(unsigned long); |
339 | static void pvr2_hdw_decoder_stabilization_timeout(unsigned long); | ||
337 | static void pvr2_hdw_encoder_wait_timeout(unsigned long); | 340 | static void pvr2_hdw_encoder_wait_timeout(unsigned long); |
338 | static void pvr2_hdw_encoder_run_timeout(unsigned long); | 341 | static void pvr2_hdw_encoder_run_timeout(unsigned long); |
339 | static int pvr2_issue_simple_cmd(struct pvr2_hdw *,u32); | 342 | static int pvr2_issue_simple_cmd(struct pvr2_hdw *,u32); |
@@ -1705,6 +1708,7 @@ static int pvr2_decoder_enable(struct pvr2_hdw *hdw,int enablefl) | |||
1705 | pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 stream=%s", | 1708 | pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 stream=%s", |
1706 | (enablefl ? "on" : "off")); | 1709 | (enablefl ? "on" : "off")); |
1707 | v4l2_device_call_all(&hdw->v4l2_dev, 0, video, s_stream, enablefl); | 1710 | v4l2_device_call_all(&hdw->v4l2_dev, 0, video, s_stream, enablefl); |
1711 | v4l2_device_call_all(&hdw->v4l2_dev, 0, audio, s_stream, enablefl); | ||
1708 | if (hdw->decoder_client_id) { | 1712 | if (hdw->decoder_client_id) { |
1709 | /* We get here if the encoder has been noticed. Otherwise | 1713 | /* We get here if the encoder has been noticed. Otherwise |
1710 | we'll issue a warning to the user (which should | 1714 | we'll issue a warning to the user (which should |
@@ -2461,6 +2465,11 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, | |||
2461 | hdw->quiescent_timer.data = (unsigned long)hdw; | 2465 | hdw->quiescent_timer.data = (unsigned long)hdw; |
2462 | hdw->quiescent_timer.function = pvr2_hdw_quiescent_timeout; | 2466 | hdw->quiescent_timer.function = pvr2_hdw_quiescent_timeout; |
2463 | 2467 | ||
2468 | init_timer(&hdw->decoder_stabilization_timer); | ||
2469 | hdw->decoder_stabilization_timer.data = (unsigned long)hdw; | ||
2470 | hdw->decoder_stabilization_timer.function = | ||
2471 | pvr2_hdw_decoder_stabilization_timeout; | ||
2472 | |||
2464 | init_timer(&hdw->encoder_wait_timer); | 2473 | init_timer(&hdw->encoder_wait_timer); |
2465 | hdw->encoder_wait_timer.data = (unsigned long)hdw; | 2474 | hdw->encoder_wait_timer.data = (unsigned long)hdw; |
2466 | hdw->encoder_wait_timer.function = pvr2_hdw_encoder_wait_timeout; | 2475 | hdw->encoder_wait_timer.function = pvr2_hdw_encoder_wait_timeout; |
@@ -2674,6 +2683,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, | |||
2674 | fail: | 2683 | fail: |
2675 | if (hdw) { | 2684 | if (hdw) { |
2676 | del_timer_sync(&hdw->quiescent_timer); | 2685 | del_timer_sync(&hdw->quiescent_timer); |
2686 | del_timer_sync(&hdw->decoder_stabilization_timer); | ||
2677 | del_timer_sync(&hdw->encoder_run_timer); | 2687 | del_timer_sync(&hdw->encoder_run_timer); |
2678 | del_timer_sync(&hdw->encoder_wait_timer); | 2688 | del_timer_sync(&hdw->encoder_wait_timer); |
2679 | if (hdw->workqueue) { | 2689 | if (hdw->workqueue) { |
@@ -2741,6 +2751,7 @@ void pvr2_hdw_destroy(struct pvr2_hdw *hdw) | |||
2741 | hdw->workqueue = NULL; | 2751 | hdw->workqueue = NULL; |
2742 | } | 2752 | } |
2743 | del_timer_sync(&hdw->quiescent_timer); | 2753 | del_timer_sync(&hdw->quiescent_timer); |
2754 | del_timer_sync(&hdw->decoder_stabilization_timer); | ||
2744 | del_timer_sync(&hdw->encoder_run_timer); | 2755 | del_timer_sync(&hdw->encoder_run_timer); |
2745 | del_timer_sync(&hdw->encoder_wait_timer); | 2756 | del_timer_sync(&hdw->encoder_wait_timer); |
2746 | if (hdw->fw_buffer) { | 2757 | if (hdw->fw_buffer) { |
@@ -4452,7 +4463,7 @@ static int state_check_enable_encoder_run(struct pvr2_hdw *hdw) | |||
4452 | 4463 | ||
4453 | switch (hdw->pathway_state) { | 4464 | switch (hdw->pathway_state) { |
4454 | case PVR2_PATHWAY_ANALOG: | 4465 | case PVR2_PATHWAY_ANALOG: |
4455 | if (hdw->state_decoder_run) { | 4466 | if (hdw->state_decoder_run && hdw->state_decoder_ready) { |
4456 | /* In analog mode, if the decoder is running, then | 4467 | /* In analog mode, if the decoder is running, then |
4457 | run the encoder. */ | 4468 | run the encoder. */ |
4458 | return !0; | 4469 | return !0; |
@@ -4519,6 +4530,17 @@ static void pvr2_hdw_quiescent_timeout(unsigned long data) | |||
4519 | } | 4530 | } |
4520 | 4531 | ||
4521 | 4532 | ||
4533 | /* Timeout function for decoder stabilization timer. */ | ||
4534 | static void pvr2_hdw_decoder_stabilization_timeout(unsigned long data) | ||
4535 | { | ||
4536 | struct pvr2_hdw *hdw = (struct pvr2_hdw *)data; | ||
4537 | hdw->state_decoder_ready = !0; | ||
4538 | trace_stbit("state_decoder_ready", hdw->state_decoder_ready); | ||
4539 | hdw->state_stale = !0; | ||
4540 | queue_work(hdw->workqueue, &hdw->workpoll); | ||
4541 | } | ||
4542 | |||
4543 | |||
4522 | /* Timeout function for encoder wait timer. */ | 4544 | /* Timeout function for encoder wait timer. */ |
4523 | static void pvr2_hdw_encoder_wait_timeout(unsigned long data) | 4545 | static void pvr2_hdw_encoder_wait_timeout(unsigned long data) |
4524 | { | 4546 | { |
@@ -4557,8 +4579,13 @@ static int state_eval_decoder_run(struct pvr2_hdw *hdw) | |||
4557 | } | 4579 | } |
4558 | hdw->state_decoder_quiescent = 0; | 4580 | hdw->state_decoder_quiescent = 0; |
4559 | hdw->state_decoder_run = 0; | 4581 | hdw->state_decoder_run = 0; |
4560 | /* paranoia - solve race if timer just completed */ | 4582 | /* paranoia - solve race if timer(s) just completed */ |
4561 | del_timer_sync(&hdw->quiescent_timer); | 4583 | del_timer_sync(&hdw->quiescent_timer); |
4584 | /* Kill the stabilization timer, in case we're killing the | ||
4585 | encoder before the previous stabilization interval has | ||
4586 | been properly timed. */ | ||
4587 | del_timer_sync(&hdw->decoder_stabilization_timer); | ||
4588 | hdw->state_decoder_ready = 0; | ||
4562 | } else { | 4589 | } else { |
4563 | if (!hdw->state_decoder_quiescent) { | 4590 | if (!hdw->state_decoder_quiescent) { |
4564 | if (!timer_pending(&hdw->quiescent_timer)) { | 4591 | if (!timer_pending(&hdw->quiescent_timer)) { |
@@ -4596,10 +4623,21 @@ static int state_eval_decoder_run(struct pvr2_hdw *hdw) | |||
4596 | if (hdw->flag_decoder_missed) return 0; | 4623 | if (hdw->flag_decoder_missed) return 0; |
4597 | if (pvr2_decoder_enable(hdw,!0) < 0) return 0; | 4624 | if (pvr2_decoder_enable(hdw,!0) < 0) return 0; |
4598 | hdw->state_decoder_quiescent = 0; | 4625 | hdw->state_decoder_quiescent = 0; |
4626 | hdw->state_decoder_ready = 0; | ||
4599 | hdw->state_decoder_run = !0; | 4627 | hdw->state_decoder_run = !0; |
4628 | if (hdw->decoder_client_id == PVR2_CLIENT_ID_SAA7115) { | ||
4629 | hdw->decoder_stabilization_timer.expires = | ||
4630 | jiffies + | ||
4631 | (HZ * TIME_MSEC_DECODER_STABILIZATION_WAIT / | ||
4632 | 1000); | ||
4633 | add_timer(&hdw->decoder_stabilization_timer); | ||
4634 | } else { | ||
4635 | hdw->state_decoder_ready = !0; | ||
4636 | } | ||
4600 | } | 4637 | } |
4601 | trace_stbit("state_decoder_quiescent",hdw->state_decoder_quiescent); | 4638 | trace_stbit("state_decoder_quiescent",hdw->state_decoder_quiescent); |
4602 | trace_stbit("state_decoder_run",hdw->state_decoder_run); | 4639 | trace_stbit("state_decoder_run",hdw->state_decoder_run); |
4640 | trace_stbit("state_decoder_ready", hdw->state_decoder_ready); | ||
4603 | return !0; | 4641 | return !0; |
4604 | } | 4642 | } |
4605 | 4643 | ||
@@ -4797,7 +4835,8 @@ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which, | |||
4797 | buf,acnt, | 4835 | buf,acnt, |
4798 | "worker:%s%s%s%s%s%s%s", | 4836 | "worker:%s%s%s%s%s%s%s", |
4799 | (hdw->state_decoder_run ? | 4837 | (hdw->state_decoder_run ? |
4800 | " <decode:run>" : | 4838 | (hdw->state_decoder_ready ? |
4839 | "<decode:run>" : " <decode:start>") : | ||
4801 | (hdw->state_decoder_quiescent ? | 4840 | (hdw->state_decoder_quiescent ? |
4802 | "" : " <decode:stop>")), | 4841 | "" : " <decode:stop>")), |
4803 | (hdw->state_decoder_quiescent ? | 4842 | (hdw->state_decoder_quiescent ? |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h index 56e70eae20c1..51d3009ab57f 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h | |||
@@ -306,6 +306,7 @@ struct pvr2_hdw_debug_info { | |||
306 | int state_encoder_ok; | 306 | int state_encoder_ok; |
307 | int state_encoder_run; | 307 | int state_encoder_run; |
308 | int state_decoder_run; | 308 | int state_decoder_run; |
309 | int state_decoder_ready; | ||
309 | int state_usbstream_run; | 310 | int state_usbstream_run; |
310 | int state_decoder_quiescent; | 311 | int state_decoder_quiescent; |
311 | int state_pipeline_config; | 312 | int state_pipeline_config; |
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index 294f860ce2b0..322ac4eecf0a 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c | |||
@@ -898,18 +898,8 @@ static void recalculate_fifo_timeout(struct pxa_camera_dev *pcdev, | |||
898 | 898 | ||
899 | static void pxa_camera_activate(struct pxa_camera_dev *pcdev) | 899 | static void pxa_camera_activate(struct pxa_camera_dev *pcdev) |
900 | { | 900 | { |
901 | struct pxacamera_platform_data *pdata = pcdev->pdata; | ||
902 | struct device *dev = pcdev->soc_host.v4l2_dev.dev; | ||
903 | u32 cicr4 = 0; | 901 | u32 cicr4 = 0; |
904 | 902 | ||
905 | dev_dbg(dev, "Registered platform device at %p data %p\n", | ||
906 | pcdev, pdata); | ||
907 | |||
908 | if (pdata && pdata->init) { | ||
909 | dev_dbg(dev, "%s: Init gpios\n", __func__); | ||
910 | pdata->init(dev); | ||
911 | } | ||
912 | |||
913 | /* disable all interrupts */ | 903 | /* disable all interrupts */ |
914 | __raw_writel(0x3ff, pcdev->base + CICR0); | 904 | __raw_writel(0x3ff, pcdev->base + CICR0); |
915 | 905 | ||
diff --git a/drivers/media/video/rj54n1cb0c.c b/drivers/media/video/rj54n1cb0c.c index 805226e0d9c1..9277194cd821 100644 --- a/drivers/media/video/rj54n1cb0c.c +++ b/drivers/media/video/rj54n1cb0c.c | |||
@@ -165,7 +165,7 @@ struct rj54n1_reg_val { | |||
165 | u8 val; | 165 | u8 val; |
166 | }; | 166 | }; |
167 | 167 | ||
168 | const static struct rj54n1_reg_val bank_4[] = { | 168 | static const struct rj54n1_reg_val bank_4[] = { |
169 | {0x417, 0}, | 169 | {0x417, 0}, |
170 | {0x42c, 0}, | 170 | {0x42c, 0}, |
171 | {0x42d, 0xf0}, | 171 | {0x42d, 0xf0}, |
@@ -186,7 +186,7 @@ const static struct rj54n1_reg_val bank_4[] = { | |||
186 | {0x4fe, 2}, | 186 | {0x4fe, 2}, |
187 | }; | 187 | }; |
188 | 188 | ||
189 | const static struct rj54n1_reg_val bank_5[] = { | 189 | static const struct rj54n1_reg_val bank_5[] = { |
190 | {0x514, 0}, | 190 | {0x514, 0}, |
191 | {0x516, 0}, | 191 | {0x516, 0}, |
192 | {0x518, 0}, | 192 | {0x518, 0}, |
@@ -207,7 +207,7 @@ const static struct rj54n1_reg_val bank_5[] = { | |||
207 | {0x5fe, 2}, | 207 | {0x5fe, 2}, |
208 | }; | 208 | }; |
209 | 209 | ||
210 | const static struct rj54n1_reg_val bank_7[] = { | 210 | static const struct rj54n1_reg_val bank_7[] = { |
211 | {0x70a, 0}, | 211 | {0x70a, 0}, |
212 | {0x714, 0xff}, | 212 | {0x714, 0xff}, |
213 | {0x715, 0xff}, | 213 | {0x715, 0xff}, |
@@ -215,7 +215,7 @@ const static struct rj54n1_reg_val bank_7[] = { | |||
215 | {0x7FE, 2}, | 215 | {0x7FE, 2}, |
216 | }; | 216 | }; |
217 | 217 | ||
218 | const static struct rj54n1_reg_val bank_8[] = { | 218 | static const struct rj54n1_reg_val bank_8[] = { |
219 | {0x800, 0x00}, | 219 | {0x800, 0x00}, |
220 | {0x801, 0x01}, | 220 | {0x801, 0x01}, |
221 | {0x802, 0x61}, | 221 | {0x802, 0x61}, |
@@ -403,12 +403,12 @@ const static struct rj54n1_reg_val bank_8[] = { | |||
403 | {0x8FE, 2}, | 403 | {0x8FE, 2}, |
404 | }; | 404 | }; |
405 | 405 | ||
406 | const static struct rj54n1_reg_val bank_10[] = { | 406 | static const struct rj54n1_reg_val bank_10[] = { |
407 | {0x10bf, 0x69} | 407 | {0x10bf, 0x69} |
408 | }; | 408 | }; |
409 | 409 | ||
410 | /* Clock dividers - these are default register values, divider = register + 1 */ | 410 | /* Clock dividers - these are default register values, divider = register + 1 */ |
411 | const static struct rj54n1_clock_div clk_div = { | 411 | static const struct rj54n1_clock_div clk_div = { |
412 | .ratio_tg = 3 /* default: 5 */, | 412 | .ratio_tg = 3 /* default: 5 */, |
413 | .ratio_t = 4 /* default: 1 */, | 413 | .ratio_t = 4 /* default: 1 */, |
414 | .ratio_r = 4 /* default: 0 */, | 414 | .ratio_r = 4 /* default: 0 */, |
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index 44873a016c2c..c0a7f8a369f4 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c | |||
@@ -104,6 +104,10 @@ static int saa711x_has_reg(const int id, const u8 reg) | |||
104 | if (id == V4L2_IDENT_SAA7111) | 104 | if (id == V4L2_IDENT_SAA7111) |
105 | return reg < 0x20 && reg != 0x01 && reg != 0x0f && | 105 | return reg < 0x20 && reg != 0x01 && reg != 0x0f && |
106 | (reg < 0x13 || reg > 0x19) && reg != 0x1d && reg != 0x1e; | 106 | (reg < 0x13 || reg > 0x19) && reg != 0x1d && reg != 0x1e; |
107 | if (id == V4L2_IDENT_SAA7111A) | ||
108 | return reg < 0x20 && reg != 0x01 && reg != 0x0f && | ||
109 | reg != 0x14 && reg != 0x18 && reg != 0x19 && | ||
110 | reg != 0x1d && reg != 0x1e; | ||
107 | 111 | ||
108 | /* common for saa7113/4/5/8 */ | 112 | /* common for saa7113/4/5/8 */ |
109 | if (unlikely((reg >= 0x3b && reg <= 0x3f) || reg == 0x5c || reg == 0x5f || | 113 | if (unlikely((reg >= 0x3b && reg <= 0x3f) || reg == 0x5c || reg == 0x5f || |
@@ -954,8 +958,7 @@ static void saa711x_set_v4lstd(struct v4l2_subdev *sd, v4l2_std_id std) | |||
954 | 011 NTSC N (3.58MHz) PAL M (3.58MHz) | 958 | 011 NTSC N (3.58MHz) PAL M (3.58MHz) |
955 | 100 reserved NTSC-Japan (3.58MHz) | 959 | 100 reserved NTSC-Japan (3.58MHz) |
956 | */ | 960 | */ |
957 | if (state->ident == V4L2_IDENT_SAA7111 || | 961 | if (state->ident <= V4L2_IDENT_SAA7113) { |
958 | state->ident == V4L2_IDENT_SAA7113) { | ||
959 | u8 reg = saa711x_read(sd, R_0E_CHROMA_CNTL_1) & 0x8f; | 962 | u8 reg = saa711x_read(sd, R_0E_CHROMA_CNTL_1) & 0x8f; |
960 | 963 | ||
961 | if (std == V4L2_STD_PAL_M) { | 964 | if (std == V4L2_STD_PAL_M) { |
@@ -1232,22 +1235,19 @@ static int saa711x_s_routing(struct v4l2_subdev *sd, | |||
1232 | u32 input, u32 output, u32 config) | 1235 | u32 input, u32 output, u32 config) |
1233 | { | 1236 | { |
1234 | struct saa711x_state *state = to_state(sd); | 1237 | struct saa711x_state *state = to_state(sd); |
1235 | u8 mask = (state->ident == V4L2_IDENT_SAA7111) ? 0xf8 : 0xf0; | 1238 | u8 mask = (state->ident <= V4L2_IDENT_SAA7111A) ? 0xf8 : 0xf0; |
1236 | 1239 | ||
1237 | v4l2_dbg(1, debug, sd, "decoder set input %d output %d\n", | 1240 | v4l2_dbg(1, debug, sd, "decoder set input %d output %d\n", |
1238 | input, output); | 1241 | input, output); |
1239 | 1242 | ||
1240 | /* saa7111/3 does not have these inputs */ | 1243 | /* saa7111/3 does not have these inputs */ |
1241 | if ((state->ident == V4L2_IDENT_SAA7113 || | 1244 | if (state->ident <= V4L2_IDENT_SAA7113 && |
1242 | state->ident == V4L2_IDENT_SAA7111) && | ||
1243 | (input == SAA7115_COMPOSITE4 || | 1245 | (input == SAA7115_COMPOSITE4 || |
1244 | input == SAA7115_COMPOSITE5)) { | 1246 | input == SAA7115_COMPOSITE5)) { |
1245 | return -EINVAL; | 1247 | return -EINVAL; |
1246 | } | 1248 | } |
1247 | if (input > SAA7115_SVIDEO3) | 1249 | if (input > SAA7115_SVIDEO3) |
1248 | return -EINVAL; | 1250 | return -EINVAL; |
1249 | if (output > SAA7115_IPORT_ON) | ||
1250 | return -EINVAL; | ||
1251 | if (state->input == input && state->output == output) | 1251 | if (state->input == input && state->output == output) |
1252 | return 0; | 1252 | return 0; |
1253 | v4l2_dbg(1, debug, sd, "now setting %s input %s output\n", | 1253 | v4l2_dbg(1, debug, sd, "now setting %s input %s output\n", |
@@ -1256,7 +1256,7 @@ static int saa711x_s_routing(struct v4l2_subdev *sd, | |||
1256 | state->input = input; | 1256 | state->input = input; |
1257 | 1257 | ||
1258 | /* saa7111 has slightly different input numbering */ | 1258 | /* saa7111 has slightly different input numbering */ |
1259 | if (state->ident == V4L2_IDENT_SAA7111) { | 1259 | if (state->ident <= V4L2_IDENT_SAA7111A) { |
1260 | if (input >= SAA7115_COMPOSITE4) | 1260 | if (input >= SAA7115_COMPOSITE4) |
1261 | input -= 2; | 1261 | input -= 2; |
1262 | /* saa7111 specific */ | 1262 | /* saa7111 specific */ |
@@ -1292,7 +1292,7 @@ static int saa711x_s_gpio(struct v4l2_subdev *sd, u32 val) | |||
1292 | { | 1292 | { |
1293 | struct saa711x_state *state = to_state(sd); | 1293 | struct saa711x_state *state = to_state(sd); |
1294 | 1294 | ||
1295 | if (state->ident != V4L2_IDENT_SAA7111) | 1295 | if (state->ident > V4L2_IDENT_SAA7111A) |
1296 | return -EINVAL; | 1296 | return -EINVAL; |
1297 | saa711x_write(sd, 0x11, (saa711x_read(sd, 0x11) & 0x7f) | | 1297 | saa711x_write(sd, 0x11, (saa711x_read(sd, 0x11) & 0x7f) | |
1298 | (val ? 0x80 : 0)); | 1298 | (val ? 0x80 : 0)); |
@@ -1596,6 +1596,10 @@ static int saa711x_probe(struct i2c_client *client, | |||
1596 | switch (chip_id) { | 1596 | switch (chip_id) { |
1597 | case '1': | 1597 | case '1': |
1598 | state->ident = V4L2_IDENT_SAA7111; | 1598 | state->ident = V4L2_IDENT_SAA7111; |
1599 | if (saa711x_read(sd, R_00_CHIP_VERSION) & 0xf0) { | ||
1600 | v4l_info(client, "saa7111a variant found\n"); | ||
1601 | state->ident = V4L2_IDENT_SAA7111A; | ||
1602 | } | ||
1599 | break; | 1603 | break; |
1600 | case '3': | 1604 | case '3': |
1601 | state->ident = V4L2_IDENT_SAA7113; | 1605 | state->ident = V4L2_IDENT_SAA7113; |
@@ -1612,7 +1616,7 @@ static int saa711x_probe(struct i2c_client *client, | |||
1612 | default: | 1616 | default: |
1613 | state->ident = V4L2_IDENT_SAA7111; | 1617 | state->ident = V4L2_IDENT_SAA7111; |
1614 | v4l2_info(sd, "WARNING: Chip is not known - Falling back to saa7111\n"); | 1618 | v4l2_info(sd, "WARNING: Chip is not known - Falling back to saa7111\n"); |
1615 | 1619 | break; | |
1616 | } | 1620 | } |
1617 | 1621 | ||
1618 | state->audclk_freq = 48000; | 1622 | state->audclk_freq = 48000; |
@@ -1623,6 +1627,7 @@ static int saa711x_probe(struct i2c_client *client, | |||
1623 | state->crystal_freq = SAA7115_FREQ_24_576_MHZ; | 1627 | state->crystal_freq = SAA7115_FREQ_24_576_MHZ; |
1624 | switch (state->ident) { | 1628 | switch (state->ident) { |
1625 | case V4L2_IDENT_SAA7111: | 1629 | case V4L2_IDENT_SAA7111: |
1630 | case V4L2_IDENT_SAA7111A: | ||
1626 | saa711x_writeregs(sd, saa7111_init); | 1631 | saa711x_writeregs(sd, saa7111_init); |
1627 | break; | 1632 | break; |
1628 | case V4L2_IDENT_SAA7113: | 1633 | case V4L2_IDENT_SAA7113: |
@@ -1632,7 +1637,7 @@ static int saa711x_probe(struct i2c_client *client, | |||
1632 | state->crystal_freq = SAA7115_FREQ_32_11_MHZ; | 1637 | state->crystal_freq = SAA7115_FREQ_32_11_MHZ; |
1633 | saa711x_writeregs(sd, saa7115_init_auto_input); | 1638 | saa711x_writeregs(sd, saa7115_init_auto_input); |
1634 | } | 1639 | } |
1635 | if (state->ident != V4L2_IDENT_SAA7111) | 1640 | if (state->ident > V4L2_IDENT_SAA7111A) |
1636 | saa711x_writeregs(sd, saa7115_init_misc); | 1641 | saa711x_writeregs(sd, saa7115_init_misc); |
1637 | saa711x_set_v4lstd(sd, V4L2_STD_NTSC); | 1642 | saa711x_set_v4lstd(sd, V4L2_STD_NTSC); |
1638 | 1643 | ||
diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c index 2fe7a701b954..250ef84cf5ca 100644 --- a/drivers/media/video/saa7127.c +++ b/drivers/media/video/saa7127.c | |||
@@ -181,7 +181,7 @@ static const struct i2c_reg_value saa7127_init_config_common[] = { | |||
181 | #define SAA7127_60HZ_DAC_CONTROL 0x15 | 181 | #define SAA7127_60HZ_DAC_CONTROL 0x15 |
182 | static const struct i2c_reg_value saa7127_init_config_60hz[] = { | 182 | static const struct i2c_reg_value saa7127_init_config_60hz[] = { |
183 | { SAA7127_REG_BURST_START, 0x19 }, | 183 | { SAA7127_REG_BURST_START, 0x19 }, |
184 | /* BURST_END is also used as a chip ID in saa7127_detect_client */ | 184 | /* BURST_END is also used as a chip ID in saa7127_probe */ |
185 | { SAA7127_REG_BURST_END, 0x1d }, | 185 | { SAA7127_REG_BURST_END, 0x1d }, |
186 | { SAA7127_REG_CHROMA_PHASE, 0xa3 }, | 186 | { SAA7127_REG_CHROMA_PHASE, 0xa3 }, |
187 | { SAA7127_REG_GAINU, 0x98 }, | 187 | { SAA7127_REG_GAINU, 0x98 }, |
@@ -200,10 +200,10 @@ static const struct i2c_reg_value saa7127_init_config_60hz[] = { | |||
200 | { 0, 0 } | 200 | { 0, 0 } |
201 | }; | 201 | }; |
202 | 202 | ||
203 | #define SAA7127_50HZ_DAC_CONTROL 0x02 | 203 | #define SAA7127_50HZ_PAL_DAC_CONTROL 0x02 |
204 | static struct i2c_reg_value saa7127_init_config_50hz[] = { | 204 | static struct i2c_reg_value saa7127_init_config_50hz_pal[] = { |
205 | { SAA7127_REG_BURST_START, 0x21 }, | 205 | { SAA7127_REG_BURST_START, 0x21 }, |
206 | /* BURST_END is also used as a chip ID in saa7127_detect_client */ | 206 | /* BURST_END is also used as a chip ID in saa7127_probe */ |
207 | { SAA7127_REG_BURST_END, 0x1d }, | 207 | { SAA7127_REG_BURST_END, 0x1d }, |
208 | { SAA7127_REG_CHROMA_PHASE, 0x3f }, | 208 | { SAA7127_REG_CHROMA_PHASE, 0x3f }, |
209 | { SAA7127_REG_GAINU, 0x7d }, | 209 | { SAA7127_REG_GAINU, 0x7d }, |
@@ -222,6 +222,28 @@ static struct i2c_reg_value saa7127_init_config_50hz[] = { | |||
222 | { 0, 0 } | 222 | { 0, 0 } |
223 | }; | 223 | }; |
224 | 224 | ||
225 | #define SAA7127_50HZ_SECAM_DAC_CONTROL 0x08 | ||
226 | static struct i2c_reg_value saa7127_init_config_50hz_secam[] = { | ||
227 | { SAA7127_REG_BURST_START, 0x21 }, | ||
228 | /* BURST_END is also used as a chip ID in saa7127_probe */ | ||
229 | { SAA7127_REG_BURST_END, 0x1d }, | ||
230 | { SAA7127_REG_CHROMA_PHASE, 0x3f }, | ||
231 | { SAA7127_REG_GAINU, 0x6a }, | ||
232 | { SAA7127_REG_GAINV, 0x81 }, | ||
233 | { SAA7127_REG_BLACK_LEVEL, 0x33 }, | ||
234 | { SAA7127_REG_BLANKING_LEVEL, 0x35 }, | ||
235 | { SAA7127_REG_VBI_BLANKING, 0x35 }, | ||
236 | { SAA7127_REG_DAC_CONTROL, 0x08 }, | ||
237 | { SAA7127_REG_BURST_AMP, 0x2f }, | ||
238 | { SAA7127_REG_SUBC3, 0xb2 }, | ||
239 | { SAA7127_REG_SUBC2, 0x3b }, | ||
240 | { SAA7127_REG_SUBC1, 0xa3 }, | ||
241 | { SAA7127_REG_SUBC0, 0x28 }, | ||
242 | { SAA7127_REG_MULTI, 0x90 }, | ||
243 | { SAA7127_REG_CLOSED_CAPTION, 0x00 }, | ||
244 | { 0, 0 } | ||
245 | }; | ||
246 | |||
225 | /* | 247 | /* |
226 | ********************************************************************** | 248 | ********************************************************************** |
227 | * | 249 | * |
@@ -463,10 +485,21 @@ static int saa7127_set_std(struct v4l2_subdev *sd, v4l2_std_id std) | |||
463 | v4l2_dbg(1, debug, sd, "Selecting 60 Hz video Standard\n"); | 485 | v4l2_dbg(1, debug, sd, "Selecting 60 Hz video Standard\n"); |
464 | inittab = saa7127_init_config_60hz; | 486 | inittab = saa7127_init_config_60hz; |
465 | state->reg_61 = SAA7127_60HZ_DAC_CONTROL; | 487 | state->reg_61 = SAA7127_60HZ_DAC_CONTROL; |
488 | |||
489 | } else if (state->ident == V4L2_IDENT_SAA7129 && | ||
490 | (std & V4L2_STD_SECAM) && | ||
491 | !(std & (V4L2_STD_625_50 & ~V4L2_STD_SECAM))) { | ||
492 | |||
493 | /* If and only if SECAM, with a SAA712[89] */ | ||
494 | v4l2_dbg(1, debug, sd, | ||
495 | "Selecting 50 Hz SECAM video Standard\n"); | ||
496 | inittab = saa7127_init_config_50hz_secam; | ||
497 | state->reg_61 = SAA7127_50HZ_SECAM_DAC_CONTROL; | ||
498 | |||
466 | } else { | 499 | } else { |
467 | v4l2_dbg(1, debug, sd, "Selecting 50 Hz video Standard\n"); | 500 | v4l2_dbg(1, debug, sd, "Selecting 50 Hz PAL video Standard\n"); |
468 | inittab = saa7127_init_config_50hz; | 501 | inittab = saa7127_init_config_50hz_pal; |
469 | state->reg_61 = SAA7127_50HZ_DAC_CONTROL; | 502 | state->reg_61 = SAA7127_50HZ_PAL_DAC_CONTROL; |
470 | } | 503 | } |
471 | 504 | ||
472 | /* Write Table */ | 505 | /* Write Table */ |
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 03f572708b85..297833fb3b4a 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c | |||
@@ -4160,7 +4160,7 @@ struct saa7134_board saa7134_boards[] = { | |||
4160 | .amux = LINE2, | 4160 | .amux = LINE2, |
4161 | }, | 4161 | }, |
4162 | }, | 4162 | }, |
4163 | [SAA7134_BOARD_BEHOLD_505RDS] = { | 4163 | [SAA7134_BOARD_BEHOLD_505RDS_MK5] = { |
4164 | /* Beholder Intl. Ltd. 2008 */ | 4164 | /* Beholder Intl. Ltd. 2008 */ |
4165 | /*Dmitry Belimov <d.belimov@gmail.com> */ | 4165 | /*Dmitry Belimov <d.belimov@gmail.com> */ |
4166 | .name = "Beholder BeholdTV 505 RDS", | 4166 | .name = "Beholder BeholdTV 505 RDS", |
@@ -5320,6 +5320,41 @@ struct saa7134_board saa7134_boards[] = { | |||
5320 | .vmux = 8, | 5320 | .vmux = 8, |
5321 | } }, | 5321 | } }, |
5322 | }, | 5322 | }, |
5323 | [SAA7134_BOARD_BEHOLD_505RDS_MK3] = { | ||
5324 | /* Beholder Intl. Ltd. 2008 */ | ||
5325 | /*Dmitry Belimov <d.belimov@gmail.com> */ | ||
5326 | .name = "Beholder BeholdTV 505 RDS", | ||
5327 | .audio_clock = 0x00200000, | ||
5328 | .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, | ||
5329 | .radio_type = UNSET, | ||
5330 | .tuner_addr = ADDR_UNSET, | ||
5331 | .radio_addr = ADDR_UNSET, | ||
5332 | .rds_addr = 0x10, | ||
5333 | .tda9887_conf = TDA9887_PRESENT, | ||
5334 | .gpiomask = 0x00008000, | ||
5335 | .inputs = {{ | ||
5336 | .name = name_tv, | ||
5337 | .vmux = 3, | ||
5338 | .amux = LINE2, | ||
5339 | .tv = 1, | ||
5340 | }, { | ||
5341 | .name = name_comp1, | ||
5342 | .vmux = 1, | ||
5343 | .amux = LINE1, | ||
5344 | }, { | ||
5345 | .name = name_svideo, | ||
5346 | .vmux = 8, | ||
5347 | .amux = LINE1, | ||
5348 | } }, | ||
5349 | .mute = { | ||
5350 | .name = name_mute, | ||
5351 | .amux = LINE1, | ||
5352 | }, | ||
5353 | .radio = { | ||
5354 | .name = name_radio, | ||
5355 | .amux = LINE2, | ||
5356 | }, | ||
5357 | }, | ||
5323 | 5358 | ||
5324 | }; | 5359 | }; |
5325 | 5360 | ||
@@ -6235,7 +6270,13 @@ struct pci_device_id saa7134_pci_tbl[] = { | |||
6235 | .device = PCI_DEVICE_ID_PHILIPS_SAA7130, | 6270 | .device = PCI_DEVICE_ID_PHILIPS_SAA7130, |
6236 | .subvendor = 0x0000, | 6271 | .subvendor = 0x0000, |
6237 | .subdevice = 0x505B, | 6272 | .subdevice = 0x505B, |
6238 | .driver_data = SAA7134_BOARD_BEHOLD_505RDS, | 6273 | .driver_data = SAA7134_BOARD_BEHOLD_505RDS_MK5, |
6274 | }, { | ||
6275 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
6276 | .device = PCI_DEVICE_ID_PHILIPS_SAA7130, | ||
6277 | .subvendor = 0x0000, | ||
6278 | .subdevice = 0x5051, | ||
6279 | .driver_data = SAA7134_BOARD_BEHOLD_505RDS_MK3, | ||
6239 | },{ | 6280 | },{ |
6240 | .vendor = PCI_VENDOR_ID_PHILIPS, | 6281 | .vendor = PCI_VENDOR_ID_PHILIPS, |
6241 | .device = PCI_DEVICE_ID_PHILIPS_SAA7130, | 6282 | .device = PCI_DEVICE_ID_PHILIPS_SAA7130, |
@@ -6792,7 +6833,8 @@ int saa7134_board_init1(struct saa7134_dev *dev) | |||
6792 | case SAA7134_BOARD_BEHOLD_407FM: | 6833 | case SAA7134_BOARD_BEHOLD_407FM: |
6793 | case SAA7134_BOARD_BEHOLD_409: | 6834 | case SAA7134_BOARD_BEHOLD_409: |
6794 | case SAA7134_BOARD_BEHOLD_505FM: | 6835 | case SAA7134_BOARD_BEHOLD_505FM: |
6795 | case SAA7134_BOARD_BEHOLD_505RDS: | 6836 | case SAA7134_BOARD_BEHOLD_505RDS_MK5: |
6837 | case SAA7134_BOARD_BEHOLD_505RDS_MK3: | ||
6796 | case SAA7134_BOARD_BEHOLD_507_9FM: | 6838 | case SAA7134_BOARD_BEHOLD_507_9FM: |
6797 | case SAA7134_BOARD_BEHOLD_507RDS_MK3: | 6839 | case SAA7134_BOARD_BEHOLD_507RDS_MK3: |
6798 | case SAA7134_BOARD_BEHOLD_507RDS_MK5: | 6840 | case SAA7134_BOARD_BEHOLD_507RDS_MK5: |
@@ -6953,8 +6995,8 @@ int saa7134_board_init1(struct saa7134_dev *dev) | |||
6953 | break; | 6995 | break; |
6954 | case SAA7134_BOARD_VIDEOMATE_S350: | 6996 | case SAA7134_BOARD_VIDEOMATE_S350: |
6955 | dev->has_remote = SAA7134_REMOTE_GPIO; | 6997 | dev->has_remote = SAA7134_REMOTE_GPIO; |
6956 | saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x00008000, 0x00008000); | 6998 | saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x0000C000, 0x0000C000); |
6957 | saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00008000, 0x00008000); | 6999 | saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x0000C000, 0x0000C000); |
6958 | break; | 7000 | break; |
6959 | } | 7001 | } |
6960 | return 0; | 7002 | return 0; |
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index f8e985989ca0..9499000f66b6 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c | |||
@@ -460,7 +460,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
460 | int polling = 0; | 460 | int polling = 0; |
461 | int rc5_gpio = 0; | 461 | int rc5_gpio = 0; |
462 | int nec_gpio = 0; | 462 | int nec_gpio = 0; |
463 | int ir_type = IR_TYPE_OTHER; | 463 | u64 ir_type = IR_TYPE_OTHER; |
464 | int err; | 464 | int err; |
465 | 465 | ||
466 | if (dev->has_remote != SAA7134_REMOTE_GPIO) | 466 | if (dev->has_remote != SAA7134_REMOTE_GPIO) |
@@ -568,7 +568,8 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
568 | case SAA7134_BOARD_BEHOLD_407FM: | 568 | case SAA7134_BOARD_BEHOLD_407FM: |
569 | case SAA7134_BOARD_BEHOLD_409: | 569 | case SAA7134_BOARD_BEHOLD_409: |
570 | case SAA7134_BOARD_BEHOLD_505FM: | 570 | case SAA7134_BOARD_BEHOLD_505FM: |
571 | case SAA7134_BOARD_BEHOLD_505RDS: | 571 | case SAA7134_BOARD_BEHOLD_505RDS_MK5: |
572 | case SAA7134_BOARD_BEHOLD_505RDS_MK3: | ||
572 | case SAA7134_BOARD_BEHOLD_507_9FM: | 573 | case SAA7134_BOARD_BEHOLD_507_9FM: |
573 | case SAA7134_BOARD_BEHOLD_507RDS_MK3: | 574 | case SAA7134_BOARD_BEHOLD_507RDS_MK3: |
574 | case SAA7134_BOARD_BEHOLD_507RDS_MK5: | 575 | case SAA7134_BOARD_BEHOLD_507RDS_MK5: |
@@ -728,7 +729,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
728 | dev->remote = ir; | 729 | dev->remote = ir; |
729 | saa7134_ir_start(dev, ir); | 730 | saa7134_ir_start(dev, ir); |
730 | 731 | ||
731 | err = ir_input_register(ir->dev, ir_codes); | 732 | err = ir_input_register(ir->dev, ir_codes, NULL); |
732 | if (err) | 733 | if (err) |
733 | goto err_out_stop; | 734 | goto err_out_stop; |
734 | 735 | ||
diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index cb732640ac4a..31138d3e51bb 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c | |||
@@ -205,7 +205,7 @@ static struct saa7134_format formats[] = { | |||
205 | 205 | ||
206 | #define NORM_525_60 \ | 206 | #define NORM_525_60 \ |
207 | .h_start = 0, \ | 207 | .h_start = 0, \ |
208 | .h_stop = 703, \ | 208 | .h_stop = 719, \ |
209 | .video_v_start = 23, \ | 209 | .video_v_start = 23, \ |
210 | .video_v_stop = 262, \ | 210 | .video_v_stop = 262, \ |
211 | .vbi_v_start_0 = 10, \ | 211 | .vbi_v_start_0 = 10, \ |
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 53b7e0b8a2fb..bf130967ed17 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h | |||
@@ -282,7 +282,7 @@ struct saa7134_format { | |||
282 | #define SAA7134_BOARD_HAUPPAUGE_HVR1120 156 | 282 | #define SAA7134_BOARD_HAUPPAUGE_HVR1120 156 |
283 | #define SAA7134_BOARD_AVERMEDIA_STUDIO_507UA 157 | 283 | #define SAA7134_BOARD_AVERMEDIA_STUDIO_507UA 157 |
284 | #define SAA7134_BOARD_AVERMEDIA_CARDBUS_501 158 | 284 | #define SAA7134_BOARD_AVERMEDIA_CARDBUS_501 158 |
285 | #define SAA7134_BOARD_BEHOLD_505RDS 159 | 285 | #define SAA7134_BOARD_BEHOLD_505RDS_MK5 159 |
286 | #define SAA7134_BOARD_BEHOLD_507RDS_MK3 160 | 286 | #define SAA7134_BOARD_BEHOLD_507RDS_MK3 160 |
287 | #define SAA7134_BOARD_BEHOLD_507RDS_MK5 161 | 287 | #define SAA7134_BOARD_BEHOLD_507RDS_MK5 161 |
288 | #define SAA7134_BOARD_BEHOLD_607FM_MK5 162 | 288 | #define SAA7134_BOARD_BEHOLD_607FM_MK5 162 |
@@ -299,6 +299,7 @@ struct saa7134_format { | |||
299 | #define SAA7134_BOARD_ZOLID_HYBRID_PCI 173 | 299 | #define SAA7134_BOARD_ZOLID_HYBRID_PCI 173 |
300 | #define SAA7134_BOARD_ASUS_EUROPA_HYBRID 174 | 300 | #define SAA7134_BOARD_ASUS_EUROPA_HYBRID 174 |
301 | #define SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S 175 | 301 | #define SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S 175 |
302 | #define SAA7134_BOARD_BEHOLD_505RDS_MK3 176 | ||
302 | 303 | ||
303 | #define SAA7134_MAXBOARDS 32 | 304 | #define SAA7134_MAXBOARDS 32 |
304 | #define SAA7134_INPUT_MAX 8 | 305 | #define SAA7134_INPUT_MAX 8 |
diff --git a/drivers/media/video/saa7164/saa7164-api.c b/drivers/media/video/saa7164/saa7164-api.c index 6f094a96ac81..1d487c150340 100644 --- a/drivers/media/video/saa7164/saa7164-api.c +++ b/drivers/media/video/saa7164/saa7164-api.c | |||
@@ -523,7 +523,7 @@ int saa7164_api_i2c_write(struct saa7164_i2c *bus, u8 addr, u32 datalen, | |||
523 | } | 523 | } |
524 | 524 | ||
525 | reglen = saa7164_i2caddr_to_reglen(bus, addr); | 525 | reglen = saa7164_i2caddr_to_reglen(bus, addr); |
526 | if (unitid < 0) { | 526 | if (reglen < 0) { |
527 | printk(KERN_ERR | 527 | printk(KERN_ERR |
528 | "%s() error, cannot translate regaddr to reglen\n", | 528 | "%s() error, cannot translate regaddr to reglen\n", |
529 | __func__); | 529 | __func__); |
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index f09c7140d6b2..fb88c63188f3 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c | |||
@@ -1748,6 +1748,22 @@ static void sh_mobile_ceu_init_videobuf(struct videobuf_queue *q, | |||
1748 | icd); | 1748 | icd); |
1749 | } | 1749 | } |
1750 | 1750 | ||
1751 | static int sh_mobile_ceu_get_parm(struct soc_camera_device *icd, | ||
1752 | struct v4l2_streamparm *parm) | ||
1753 | { | ||
1754 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | ||
1755 | |||
1756 | return v4l2_subdev_call(sd, video, g_parm, parm); | ||
1757 | } | ||
1758 | |||
1759 | static int sh_mobile_ceu_set_parm(struct soc_camera_device *icd, | ||
1760 | struct v4l2_streamparm *parm) | ||
1761 | { | ||
1762 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | ||
1763 | |||
1764 | return v4l2_subdev_call(sd, video, s_parm, parm); | ||
1765 | } | ||
1766 | |||
1751 | static int sh_mobile_ceu_get_ctrl(struct soc_camera_device *icd, | 1767 | static int sh_mobile_ceu_get_ctrl(struct soc_camera_device *icd, |
1752 | struct v4l2_control *ctrl) | 1768 | struct v4l2_control *ctrl) |
1753 | { | 1769 | { |
@@ -1808,6 +1824,8 @@ static struct soc_camera_host_ops sh_mobile_ceu_host_ops = { | |||
1808 | .try_fmt = sh_mobile_ceu_try_fmt, | 1824 | .try_fmt = sh_mobile_ceu_try_fmt, |
1809 | .set_ctrl = sh_mobile_ceu_set_ctrl, | 1825 | .set_ctrl = sh_mobile_ceu_set_ctrl, |
1810 | .get_ctrl = sh_mobile_ceu_get_ctrl, | 1826 | .get_ctrl = sh_mobile_ceu_get_ctrl, |
1827 | .set_parm = sh_mobile_ceu_set_parm, | ||
1828 | .get_parm = sh_mobile_ceu_get_parm, | ||
1811 | .reqbufs = sh_mobile_ceu_reqbufs, | 1829 | .reqbufs = sh_mobile_ceu_reqbufs, |
1812 | .poll = sh_mobile_ceu_poll, | 1830 | .poll = sh_mobile_ceu_poll, |
1813 | .querycap = sh_mobile_ceu_querycap, | 1831 | .querycap = sh_mobile_ceu_querycap, |
diff --git a/drivers/media/video/sn9c102/Kconfig b/drivers/media/video/sn9c102/Kconfig index f71f272776de..6ebaf2940d06 100644 --- a/drivers/media/video/sn9c102/Kconfig +++ b/drivers/media/video/sn9c102/Kconfig | |||
@@ -1,7 +1,10 @@ | |||
1 | config USB_SN9C102 | 1 | config USB_SN9C102 |
2 | tristate "USB SN9C1xx PC Camera Controller support" | 2 | tristate "USB SN9C1xx PC Camera Controller support (DEPRECATED)" |
3 | depends on VIDEO_V4L2 | 3 | depends on VIDEO_V4L2 |
4 | ---help--- | 4 | ---help--- |
5 | This driver is DEPRECATED please use the gspca sonixb and | ||
6 | sonixj modules instead. | ||
7 | |||
5 | Say Y here if you want support for cameras based on SONiX SN9C101, | 8 | Say Y here if you want support for cameras based on SONiX SN9C101, |
6 | SN9C102, SN9C103, SN9C105 and SN9C120 PC Camera Controllers. | 9 | SN9C102, SN9C103, SN9C105 and SN9C120 PC Camera Controllers. |
7 | 10 | ||
diff --git a/drivers/media/video/sn9c102/sn9c102_devtable.h b/drivers/media/video/sn9c102/sn9c102_devtable.h index 36ee43a9ee95..cc40d6ba9f22 100644 --- a/drivers/media/video/sn9c102/sn9c102_devtable.h +++ b/drivers/media/video/sn9c102/sn9c102_devtable.h | |||
@@ -45,20 +45,24 @@ static const struct usb_device_id sn9c102_id_table[] = { | |||
45 | { SN9C102_USB_DEVICE(0x0c45, 0x6005, BRIDGE_SN9C102), }, | 45 | { SN9C102_USB_DEVICE(0x0c45, 0x6005, BRIDGE_SN9C102), }, |
46 | #endif | 46 | #endif |
47 | { SN9C102_USB_DEVICE(0x0c45, 0x6007, BRIDGE_SN9C102), }, | 47 | { SN9C102_USB_DEVICE(0x0c45, 0x6007, BRIDGE_SN9C102), }, |
48 | #if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE | ||
48 | { SN9C102_USB_DEVICE(0x0c45, 0x6009, BRIDGE_SN9C102), }, | 49 | { SN9C102_USB_DEVICE(0x0c45, 0x6009, BRIDGE_SN9C102), }, |
49 | { SN9C102_USB_DEVICE(0x0c45, 0x600d, BRIDGE_SN9C102), }, | 50 | { SN9C102_USB_DEVICE(0x0c45, 0x600d, BRIDGE_SN9C102), }, |
50 | /* { SN9C102_USB_DEVICE(0x0c45, 0x6011, BRIDGE_SN9C102), }, OV6650 */ | 51 | /* { SN9C102_USB_DEVICE(0x0c45, 0x6011, BRIDGE_SN9C102), }, OV6650 */ |
52 | #endif | ||
51 | { SN9C102_USB_DEVICE(0x0c45, 0x6019, BRIDGE_SN9C102), }, | 53 | { SN9C102_USB_DEVICE(0x0c45, 0x6019, BRIDGE_SN9C102), }, |
52 | { SN9C102_USB_DEVICE(0x0c45, 0x6024, BRIDGE_SN9C102), }, | 54 | { SN9C102_USB_DEVICE(0x0c45, 0x6024, BRIDGE_SN9C102), }, |
53 | { SN9C102_USB_DEVICE(0x0c45, 0x6025, BRIDGE_SN9C102), }, | 55 | { SN9C102_USB_DEVICE(0x0c45, 0x6025, BRIDGE_SN9C102), }, |
56 | #if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE | ||
54 | { SN9C102_USB_DEVICE(0x0c45, 0x6028, BRIDGE_SN9C102), }, | 57 | { SN9C102_USB_DEVICE(0x0c45, 0x6028, BRIDGE_SN9C102), }, |
55 | { SN9C102_USB_DEVICE(0x0c45, 0x6029, BRIDGE_SN9C102), }, | 58 | { SN9C102_USB_DEVICE(0x0c45, 0x6029, BRIDGE_SN9C102), }, |
59 | #endif | ||
56 | { SN9C102_USB_DEVICE(0x0c45, 0x602a, BRIDGE_SN9C102), }, | 60 | { SN9C102_USB_DEVICE(0x0c45, 0x602a, BRIDGE_SN9C102), }, |
57 | { SN9C102_USB_DEVICE(0x0c45, 0x602b, BRIDGE_SN9C102), }, | 61 | { SN9C102_USB_DEVICE(0x0c45, 0x602b, BRIDGE_SN9C102), }, |
58 | #if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE | 62 | #if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE |
59 | { SN9C102_USB_DEVICE(0x0c45, 0x602c, BRIDGE_SN9C102), }, | 63 | { SN9C102_USB_DEVICE(0x0c45, 0x602c, BRIDGE_SN9C102), }, |
60 | #endif | ||
61 | /* { SN9C102_USB_DEVICE(0x0c45, 0x602d, BRIDGE_SN9C102), }, HV7131R */ | 64 | /* { SN9C102_USB_DEVICE(0x0c45, 0x602d, BRIDGE_SN9C102), }, HV7131R */ |
65 | #endif | ||
62 | { SN9C102_USB_DEVICE(0x0c45, 0x602e, BRIDGE_SN9C102), }, | 66 | { SN9C102_USB_DEVICE(0x0c45, 0x602e, BRIDGE_SN9C102), }, |
63 | { SN9C102_USB_DEVICE(0x0c45, 0x6030, BRIDGE_SN9C102), }, | 67 | { SN9C102_USB_DEVICE(0x0c45, 0x6030, BRIDGE_SN9C102), }, |
64 | /* SN9C103 */ | 68 | /* SN9C103 */ |
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 6b3fbcca7747..80f6bfa2632b 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c | |||
@@ -781,6 +781,32 @@ static int soc_camera_s_crop(struct file *file, void *fh, | |||
781 | return ret; | 781 | return ret; |
782 | } | 782 | } |
783 | 783 | ||
784 | static int soc_camera_g_parm(struct file *file, void *fh, | ||
785 | struct v4l2_streamparm *a) | ||
786 | { | ||
787 | struct soc_camera_file *icf = file->private_data; | ||
788 | struct soc_camera_device *icd = icf->icd; | ||
789 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | ||
790 | |||
791 | if (ici->ops->get_parm) | ||
792 | return ici->ops->get_parm(icd, a); | ||
793 | |||
794 | return -ENOIOCTLCMD; | ||
795 | } | ||
796 | |||
797 | static int soc_camera_s_parm(struct file *file, void *fh, | ||
798 | struct v4l2_streamparm *a) | ||
799 | { | ||
800 | struct soc_camera_file *icf = file->private_data; | ||
801 | struct soc_camera_device *icd = icf->icd; | ||
802 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | ||
803 | |||
804 | if (ici->ops->set_parm) | ||
805 | return ici->ops->set_parm(icd, a); | ||
806 | |||
807 | return -ENOIOCTLCMD; | ||
808 | } | ||
809 | |||
784 | static int soc_camera_g_chip_ident(struct file *file, void *fh, | 810 | static int soc_camera_g_chip_ident(struct file *file, void *fh, |
785 | struct v4l2_dbg_chip_ident *id) | 811 | struct v4l2_dbg_chip_ident *id) |
786 | { | 812 | { |
@@ -846,10 +872,8 @@ static int soc_camera_init_i2c(struct soc_camera_device *icd, | |||
846 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | 872 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); |
847 | struct i2c_adapter *adap = i2c_get_adapter(icl->i2c_adapter_id); | 873 | struct i2c_adapter *adap = i2c_get_adapter(icl->i2c_adapter_id); |
848 | struct v4l2_subdev *subdev; | 874 | struct v4l2_subdev *subdev; |
849 | int ret; | ||
850 | 875 | ||
851 | if (!adap) { | 876 | if (!adap) { |
852 | ret = -ENODEV; | ||
853 | dev_err(&icd->dev, "Cannot get I2C adapter #%d. No driver?\n", | 877 | dev_err(&icd->dev, "Cannot get I2C adapter #%d. No driver?\n", |
854 | icl->i2c_adapter_id); | 878 | icl->i2c_adapter_id); |
855 | goto ei2cga; | 879 | goto ei2cga; |
@@ -859,10 +883,8 @@ static int soc_camera_init_i2c(struct soc_camera_device *icd, | |||
859 | 883 | ||
860 | subdev = v4l2_i2c_new_subdev_board(&ici->v4l2_dev, adap, | 884 | subdev = v4l2_i2c_new_subdev_board(&ici->v4l2_dev, adap, |
861 | icl->module_name, icl->board_info, NULL); | 885 | icl->module_name, icl->board_info, NULL); |
862 | if (!subdev) { | 886 | if (!subdev) |
863 | ret = -ENOMEM; | ||
864 | goto ei2cnd; | 887 | goto ei2cnd; |
865 | } | ||
866 | 888 | ||
867 | client = subdev->priv; | 889 | client = subdev->priv; |
868 | 890 | ||
@@ -873,7 +895,7 @@ static int soc_camera_init_i2c(struct soc_camera_device *icd, | |||
873 | ei2cnd: | 895 | ei2cnd: |
874 | i2c_put_adapter(adap); | 896 | i2c_put_adapter(adap); |
875 | ei2cga: | 897 | ei2cga: |
876 | return ret; | 898 | return -ENODEV; |
877 | } | 899 | } |
878 | 900 | ||
879 | static void soc_camera_free_i2c(struct soc_camera_device *icd) | 901 | static void soc_camera_free_i2c(struct soc_camera_device *icd) |
@@ -1260,6 +1282,8 @@ static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = { | |||
1260 | .vidioc_cropcap = soc_camera_cropcap, | 1282 | .vidioc_cropcap = soc_camera_cropcap, |
1261 | .vidioc_g_crop = soc_camera_g_crop, | 1283 | .vidioc_g_crop = soc_camera_g_crop, |
1262 | .vidioc_s_crop = soc_camera_s_crop, | 1284 | .vidioc_s_crop = soc_camera_s_crop, |
1285 | .vidioc_g_parm = soc_camera_g_parm, | ||
1286 | .vidioc_s_parm = soc_camera_s_parm, | ||
1263 | .vidioc_g_chip_ident = soc_camera_g_chip_ident, | 1287 | .vidioc_g_chip_ident = soc_camera_g_chip_ident, |
1264 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 1288 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
1265 | .vidioc_g_register = soc_camera_g_register, | 1289 | .vidioc_g_register = soc_camera_g_register, |
diff --git a/drivers/media/video/soc_mediabus.c b/drivers/media/video/soc_mediabus.c index f8d5c87dc2aa..8b63b6545e76 100644 --- a/drivers/media/video/soc_mediabus.c +++ b/drivers/media/video/soc_mediabus.c | |||
@@ -24,91 +24,106 @@ static const struct soc_mbus_pixelfmt mbus_fmt[] = { | |||
24 | .bits_per_sample = 8, | 24 | .bits_per_sample = 8, |
25 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | 25 | .packing = SOC_MBUS_PACKING_2X8_PADHI, |
26 | .order = SOC_MBUS_ORDER_LE, | 26 | .order = SOC_MBUS_ORDER_LE, |
27 | }, [MBUS_IDX(YVYU8_2X8_LE)] = { | 27 | }, |
28 | [MBUS_IDX(YVYU8_2X8_LE)] = { | ||
28 | .fourcc = V4L2_PIX_FMT_YVYU, | 29 | .fourcc = V4L2_PIX_FMT_YVYU, |
29 | .name = "YVYU", | 30 | .name = "YVYU", |
30 | .bits_per_sample = 8, | 31 | .bits_per_sample = 8, |
31 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | 32 | .packing = SOC_MBUS_PACKING_2X8_PADHI, |
32 | .order = SOC_MBUS_ORDER_LE, | 33 | .order = SOC_MBUS_ORDER_LE, |
33 | }, [MBUS_IDX(YUYV8_2X8_BE)] = { | 34 | }, |
35 | [MBUS_IDX(YUYV8_2X8_BE)] = { | ||
34 | .fourcc = V4L2_PIX_FMT_UYVY, | 36 | .fourcc = V4L2_PIX_FMT_UYVY, |
35 | .name = "UYVY", | 37 | .name = "UYVY", |
36 | .bits_per_sample = 8, | 38 | .bits_per_sample = 8, |
37 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | 39 | .packing = SOC_MBUS_PACKING_2X8_PADHI, |
38 | .order = SOC_MBUS_ORDER_LE, | 40 | .order = SOC_MBUS_ORDER_LE, |
39 | }, [MBUS_IDX(YVYU8_2X8_BE)] = { | 41 | }, |
42 | [MBUS_IDX(YVYU8_2X8_BE)] = { | ||
40 | .fourcc = V4L2_PIX_FMT_VYUY, | 43 | .fourcc = V4L2_PIX_FMT_VYUY, |
41 | .name = "VYUY", | 44 | .name = "VYUY", |
42 | .bits_per_sample = 8, | 45 | .bits_per_sample = 8, |
43 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | 46 | .packing = SOC_MBUS_PACKING_2X8_PADHI, |
44 | .order = SOC_MBUS_ORDER_LE, | 47 | .order = SOC_MBUS_ORDER_LE, |
45 | }, [MBUS_IDX(RGB555_2X8_PADHI_LE)] = { | 48 | }, |
49 | [MBUS_IDX(RGB555_2X8_PADHI_LE)] = { | ||
46 | .fourcc = V4L2_PIX_FMT_RGB555, | 50 | .fourcc = V4L2_PIX_FMT_RGB555, |
47 | .name = "RGB555", | 51 | .name = "RGB555", |
48 | .bits_per_sample = 8, | 52 | .bits_per_sample = 8, |
49 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | 53 | .packing = SOC_MBUS_PACKING_2X8_PADHI, |
50 | .order = SOC_MBUS_ORDER_LE, | 54 | .order = SOC_MBUS_ORDER_LE, |
51 | }, [MBUS_IDX(RGB555_2X8_PADHI_BE)] = { | 55 | }, |
56 | [MBUS_IDX(RGB555_2X8_PADHI_BE)] = { | ||
52 | .fourcc = V4L2_PIX_FMT_RGB555X, | 57 | .fourcc = V4L2_PIX_FMT_RGB555X, |
53 | .name = "RGB555X", | 58 | .name = "RGB555X", |
54 | .bits_per_sample = 8, | 59 | .bits_per_sample = 8, |
55 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | 60 | .packing = SOC_MBUS_PACKING_2X8_PADHI, |
56 | .order = SOC_MBUS_ORDER_LE, | 61 | .order = SOC_MBUS_ORDER_LE, |
57 | }, [MBUS_IDX(RGB565_2X8_LE)] = { | 62 | }, |
63 | [MBUS_IDX(RGB565_2X8_LE)] = { | ||
58 | .fourcc = V4L2_PIX_FMT_RGB565, | 64 | .fourcc = V4L2_PIX_FMT_RGB565, |
59 | .name = "RGB565", | 65 | .name = "RGB565", |
60 | .bits_per_sample = 8, | 66 | .bits_per_sample = 8, |
61 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | 67 | .packing = SOC_MBUS_PACKING_2X8_PADHI, |
62 | .order = SOC_MBUS_ORDER_LE, | 68 | .order = SOC_MBUS_ORDER_LE, |
63 | }, [MBUS_IDX(RGB565_2X8_BE)] = { | 69 | }, |
70 | [MBUS_IDX(RGB565_2X8_BE)] = { | ||
64 | .fourcc = V4L2_PIX_FMT_RGB565X, | 71 | .fourcc = V4L2_PIX_FMT_RGB565X, |
65 | .name = "RGB565X", | 72 | .name = "RGB565X", |
66 | .bits_per_sample = 8, | 73 | .bits_per_sample = 8, |
67 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | 74 | .packing = SOC_MBUS_PACKING_2X8_PADHI, |
68 | .order = SOC_MBUS_ORDER_LE, | 75 | .order = SOC_MBUS_ORDER_LE, |
69 | }, [MBUS_IDX(SBGGR8_1X8)] = { | 76 | }, |
77 | [MBUS_IDX(SBGGR8_1X8)] = { | ||
70 | .fourcc = V4L2_PIX_FMT_SBGGR8, | 78 | .fourcc = V4L2_PIX_FMT_SBGGR8, |
71 | .name = "Bayer 8 BGGR", | 79 | .name = "Bayer 8 BGGR", |
72 | .bits_per_sample = 8, | 80 | .bits_per_sample = 8, |
73 | .packing = SOC_MBUS_PACKING_NONE, | 81 | .packing = SOC_MBUS_PACKING_NONE, |
74 | .order = SOC_MBUS_ORDER_LE, | 82 | .order = SOC_MBUS_ORDER_LE, |
75 | }, [MBUS_IDX(SBGGR10_1X10)] = { | 83 | }, |
84 | [MBUS_IDX(SBGGR10_1X10)] = { | ||
76 | .fourcc = V4L2_PIX_FMT_SBGGR10, | 85 | .fourcc = V4L2_PIX_FMT_SBGGR10, |
77 | .name = "Bayer 10 BGGR", | 86 | .name = "Bayer 10 BGGR", |
78 | .bits_per_sample = 10, | 87 | .bits_per_sample = 10, |
79 | .packing = SOC_MBUS_PACKING_EXTEND16, | 88 | .packing = SOC_MBUS_PACKING_EXTEND16, |
80 | .order = SOC_MBUS_ORDER_LE, | 89 | .order = SOC_MBUS_ORDER_LE, |
81 | }, [MBUS_IDX(GREY8_1X8)] = { | 90 | }, |
91 | [MBUS_IDX(GREY8_1X8)] = { | ||
82 | .fourcc = V4L2_PIX_FMT_GREY, | 92 | .fourcc = V4L2_PIX_FMT_GREY, |
83 | .name = "Grey", | 93 | .name = "Grey", |
84 | .bits_per_sample = 8, | 94 | .bits_per_sample = 8, |
85 | .packing = SOC_MBUS_PACKING_NONE, | 95 | .packing = SOC_MBUS_PACKING_NONE, |
86 | .order = SOC_MBUS_ORDER_LE, | 96 | .order = SOC_MBUS_ORDER_LE, |
87 | }, [MBUS_IDX(Y10_1X10)] = { | 97 | }, |
98 | [MBUS_IDX(Y10_1X10)] = { | ||
88 | .fourcc = V4L2_PIX_FMT_Y10, | 99 | .fourcc = V4L2_PIX_FMT_Y10, |
89 | .name = "Grey 10bit", | 100 | .name = "Grey 10bit", |
90 | .bits_per_sample = 10, | 101 | .bits_per_sample = 10, |
91 | .packing = SOC_MBUS_PACKING_EXTEND16, | 102 | .packing = SOC_MBUS_PACKING_EXTEND16, |
92 | .order = SOC_MBUS_ORDER_LE, | 103 | .order = SOC_MBUS_ORDER_LE, |
93 | }, [MBUS_IDX(SBGGR10_2X8_PADHI_LE)] = { | 104 | }, |
105 | [MBUS_IDX(SBGGR10_2X8_PADHI_LE)] = { | ||
94 | .fourcc = V4L2_PIX_FMT_SBGGR10, | 106 | .fourcc = V4L2_PIX_FMT_SBGGR10, |
95 | .name = "Bayer 10 BGGR", | 107 | .name = "Bayer 10 BGGR", |
96 | .bits_per_sample = 8, | 108 | .bits_per_sample = 8, |
97 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | 109 | .packing = SOC_MBUS_PACKING_2X8_PADHI, |
98 | .order = SOC_MBUS_ORDER_LE, | 110 | .order = SOC_MBUS_ORDER_LE, |
99 | }, [MBUS_IDX(SBGGR10_2X8_PADLO_LE)] = { | 111 | }, |
112 | [MBUS_IDX(SBGGR10_2X8_PADLO_LE)] = { | ||
100 | .fourcc = V4L2_PIX_FMT_SBGGR10, | 113 | .fourcc = V4L2_PIX_FMT_SBGGR10, |
101 | .name = "Bayer 10 BGGR", | 114 | .name = "Bayer 10 BGGR", |
102 | .bits_per_sample = 8, | 115 | .bits_per_sample = 8, |
103 | .packing = SOC_MBUS_PACKING_2X8_PADLO, | 116 | .packing = SOC_MBUS_PACKING_2X8_PADLO, |
104 | .order = SOC_MBUS_ORDER_LE, | 117 | .order = SOC_MBUS_ORDER_LE, |
105 | }, [MBUS_IDX(SBGGR10_2X8_PADHI_BE)] = { | 118 | }, |
119 | [MBUS_IDX(SBGGR10_2X8_PADHI_BE)] = { | ||
106 | .fourcc = V4L2_PIX_FMT_SBGGR10, | 120 | .fourcc = V4L2_PIX_FMT_SBGGR10, |
107 | .name = "Bayer 10 BGGR", | 121 | .name = "Bayer 10 BGGR", |
108 | .bits_per_sample = 8, | 122 | .bits_per_sample = 8, |
109 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | 123 | .packing = SOC_MBUS_PACKING_2X8_PADHI, |
110 | .order = SOC_MBUS_ORDER_BE, | 124 | .order = SOC_MBUS_ORDER_BE, |
111 | }, [MBUS_IDX(SBGGR10_2X8_PADLO_BE)] = { | 125 | }, |
126 | [MBUS_IDX(SBGGR10_2X8_PADLO_BE)] = { | ||
112 | .fourcc = V4L2_PIX_FMT_SBGGR10, | 127 | .fourcc = V4L2_PIX_FMT_SBGGR10, |
113 | .name = "Bayer 10 BGGR", | 128 | .name = "Bayer 10 BGGR", |
114 | .bits_per_sample = 8, | 129 | .bits_per_sample = 8, |
@@ -134,7 +149,8 @@ EXPORT_SYMBOL(soc_mbus_bytes_per_line); | |||
134 | const struct soc_mbus_pixelfmt *soc_mbus_get_fmtdesc( | 149 | const struct soc_mbus_pixelfmt *soc_mbus_get_fmtdesc( |
135 | enum v4l2_mbus_pixelcode code) | 150 | enum v4l2_mbus_pixelcode code) |
136 | { | 151 | { |
137 | if ((unsigned int)(code - V4L2_MBUS_FMT_FIXED) > ARRAY_SIZE(mbus_fmt)) | 152 | if (code - V4L2_MBUS_FMT_FIXED > ARRAY_SIZE(mbus_fmt) || |
153 | code <= V4L2_MBUS_FMT_FIXED) | ||
138 | return NULL; | 154 | return NULL; |
139 | return mbus_fmt + code - V4L2_MBUS_FMT_FIXED - 1; | 155 | return mbus_fmt + code - V4L2_MBUS_FMT_FIXED - 1; |
140 | } | 156 | } |
diff --git a/drivers/media/video/tlg2300/Kconfig b/drivers/media/video/tlg2300/Kconfig new file mode 100644 index 000000000000..2c29ec659b4e --- /dev/null +++ b/drivers/media/video/tlg2300/Kconfig | |||
@@ -0,0 +1,16 @@ | |||
1 | config VIDEO_TLG2300 | ||
2 | tristate "Telegent TLG2300 USB video capture support" | ||
3 | depends on VIDEO_DEV && I2C && INPUT && SND && DVB_CORE | ||
4 | select VIDEO_TUNER | ||
5 | select VIDEO_TVEEPROM | ||
6 | select VIDEO_IR | ||
7 | select VIDEOBUF_VMALLOC | ||
8 | select SND_PCM | ||
9 | select VIDEOBUF_DVB | ||
10 | |||
11 | ---help--- | ||
12 | This is a video4linux driver for Telegent tlg2300 based TV cards. | ||
13 | The driver supports V4L2, DVB-T and radio. | ||
14 | |||
15 | To compile this driver as a module, choose M here: the | ||
16 | module will be called poseidon | ||
diff --git a/drivers/media/video/tlg2300/Makefile b/drivers/media/video/tlg2300/Makefile new file mode 100644 index 000000000000..81bb7fdd1e3d --- /dev/null +++ b/drivers/media/video/tlg2300/Makefile | |||
@@ -0,0 +1,9 @@ | |||
1 | poseidon-objs := pd-video.o pd-alsa.o pd-dvb.o pd-radio.o pd-main.o | ||
2 | |||
3 | obj-$(CONFIG_VIDEO_TLG2300) += poseidon.o | ||
4 | |||
5 | EXTRA_CFLAGS += -Idrivers/media/video | ||
6 | EXTRA_CFLAGS += -Idrivers/media/common/tuners | ||
7 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core | ||
8 | EXTRA_CFLAGS += -Idrivers/media/dvb/frontends | ||
9 | |||
diff --git a/drivers/media/video/tlg2300/pd-alsa.c b/drivers/media/video/tlg2300/pd-alsa.c new file mode 100644 index 000000000000..6f42621ad478 --- /dev/null +++ b/drivers/media/video/tlg2300/pd-alsa.c | |||
@@ -0,0 +1,332 @@ | |||
1 | #include <linux/kernel.h> | ||
2 | #include <linux/usb.h> | ||
3 | #include <linux/init.h> | ||
4 | #include <linux/sound.h> | ||
5 | #include <linux/spinlock.h> | ||
6 | #include <linux/soundcard.h> | ||
7 | #include <linux/slab.h> | ||
8 | #include <linux/vmalloc.h> | ||
9 | #include <linux/proc_fs.h> | ||
10 | #include <linux/module.h> | ||
11 | #include <sound/core.h> | ||
12 | #include <sound/pcm.h> | ||
13 | #include <sound/pcm_params.h> | ||
14 | #include <sound/info.h> | ||
15 | #include <sound/initval.h> | ||
16 | #include <sound/control.h> | ||
17 | #include <media/v4l2-common.h> | ||
18 | #include "pd-common.h" | ||
19 | #include "vendorcmds.h" | ||
20 | |||
21 | static void complete_handler_audio(struct urb *urb); | ||
22 | #define AUDIO_EP (0x83) | ||
23 | #define AUDIO_BUF_SIZE (512) | ||
24 | #define PERIOD_SIZE (1024 * 8) | ||
25 | #define PERIOD_MIN (4) | ||
26 | #define PERIOD_MAX PERIOD_MIN | ||
27 | |||
28 | static struct snd_pcm_hardware snd_pd_hw_capture = { | ||
29 | .info = SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
30 | SNDRV_PCM_INFO_MMAP | | ||
31 | SNDRV_PCM_INFO_INTERLEAVED | | ||
32 | SNDRV_PCM_INFO_MMAP_VALID, | ||
33 | |||
34 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
35 | .rates = SNDRV_PCM_RATE_48000, | ||
36 | |||
37 | .rate_min = 48000, | ||
38 | .rate_max = 48000, | ||
39 | .channels_min = 2, | ||
40 | .channels_max = 2, | ||
41 | .buffer_bytes_max = PERIOD_SIZE * PERIOD_MIN, | ||
42 | .period_bytes_min = PERIOD_SIZE, | ||
43 | .period_bytes_max = PERIOD_SIZE, | ||
44 | .periods_min = PERIOD_MIN, | ||
45 | .periods_max = PERIOD_MAX, | ||
46 | /* | ||
47 | .buffer_bytes_max = 62720 * 8, | ||
48 | .period_bytes_min = 64, | ||
49 | .period_bytes_max = 12544, | ||
50 | .periods_min = 2, | ||
51 | .periods_max = 98 | ||
52 | */ | ||
53 | }; | ||
54 | |||
55 | static int snd_pd_capture_open(struct snd_pcm_substream *substream) | ||
56 | { | ||
57 | struct poseidon *p = snd_pcm_substream_chip(substream); | ||
58 | struct poseidon_audio *pa = &p->audio; | ||
59 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
60 | |||
61 | if (!p) | ||
62 | return -ENODEV; | ||
63 | pa->users++; | ||
64 | pa->card_close = 0; | ||
65 | pa->capture_pcm_substream = substream; | ||
66 | runtime->private_data = p; | ||
67 | |||
68 | runtime->hw = snd_pd_hw_capture; | ||
69 | snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); | ||
70 | usb_autopm_get_interface(p->interface); | ||
71 | kref_get(&p->kref); | ||
72 | return 0; | ||
73 | } | ||
74 | |||
75 | static int snd_pd_pcm_close(struct snd_pcm_substream *substream) | ||
76 | { | ||
77 | struct poseidon *p = snd_pcm_substream_chip(substream); | ||
78 | struct poseidon_audio *pa = &p->audio; | ||
79 | |||
80 | pa->users--; | ||
81 | pa->card_close = 1; | ||
82 | usb_autopm_put_interface(p->interface); | ||
83 | kref_put(&p->kref, poseidon_delete); | ||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | static int snd_pd_hw_capture_params(struct snd_pcm_substream *substream, | ||
88 | struct snd_pcm_hw_params *hw_params) | ||
89 | { | ||
90 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
91 | unsigned int size; | ||
92 | |||
93 | size = params_buffer_bytes(hw_params); | ||
94 | if (runtime->dma_area) { | ||
95 | if (runtime->dma_bytes > size) | ||
96 | return 0; | ||
97 | vfree(runtime->dma_area); | ||
98 | } | ||
99 | runtime->dma_area = vmalloc(size); | ||
100 | if (!runtime->dma_area) | ||
101 | return -ENOMEM; | ||
102 | else | ||
103 | runtime->dma_bytes = size; | ||
104 | return 0; | ||
105 | } | ||
106 | |||
107 | static int audio_buf_free(struct poseidon *p) | ||
108 | { | ||
109 | struct poseidon_audio *pa = &p->audio; | ||
110 | int i; | ||
111 | |||
112 | for (i = 0; i < AUDIO_BUFS; i++) | ||
113 | if (pa->urb_array[i]) | ||
114 | usb_kill_urb(pa->urb_array[i]); | ||
115 | free_all_urb_generic(pa->urb_array, AUDIO_BUFS); | ||
116 | logpm(); | ||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | static int snd_pd_hw_capture_free(struct snd_pcm_substream *substream) | ||
121 | { | ||
122 | struct poseidon *p = snd_pcm_substream_chip(substream); | ||
123 | |||
124 | logpm(); | ||
125 | audio_buf_free(p); | ||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | static int snd_pd_prepare(struct snd_pcm_substream *substream) | ||
130 | { | ||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | #define AUDIO_TRAILER_SIZE (16) | ||
135 | static inline void handle_audio_data(struct urb *urb, int *period_elapsed) | ||
136 | { | ||
137 | struct poseidon_audio *pa = urb->context; | ||
138 | struct snd_pcm_runtime *runtime = pa->capture_pcm_substream->runtime; | ||
139 | |||
140 | int stride = runtime->frame_bits >> 3; | ||
141 | int len = urb->actual_length / stride; | ||
142 | unsigned char *cp = urb->transfer_buffer; | ||
143 | unsigned int oldptr = pa->rcv_position; | ||
144 | |||
145 | if (urb->actual_length == AUDIO_BUF_SIZE - 4) | ||
146 | len -= (AUDIO_TRAILER_SIZE / stride); | ||
147 | |||
148 | /* do the copy */ | ||
149 | if (oldptr + len >= runtime->buffer_size) { | ||
150 | unsigned int cnt = runtime->buffer_size - oldptr; | ||
151 | |||
152 | memcpy(runtime->dma_area + oldptr * stride, cp, cnt * stride); | ||
153 | memcpy(runtime->dma_area, (cp + cnt * stride), | ||
154 | (len * stride - cnt * stride)); | ||
155 | } else | ||
156 | memcpy(runtime->dma_area + oldptr * stride, cp, len * stride); | ||
157 | |||
158 | /* update the statas */ | ||
159 | snd_pcm_stream_lock(pa->capture_pcm_substream); | ||
160 | pa->rcv_position += len; | ||
161 | if (pa->rcv_position >= runtime->buffer_size) | ||
162 | pa->rcv_position -= runtime->buffer_size; | ||
163 | |||
164 | pa->copied_position += (len); | ||
165 | if (pa->copied_position >= runtime->period_size) { | ||
166 | pa->copied_position -= runtime->period_size; | ||
167 | *period_elapsed = 1; | ||
168 | } | ||
169 | snd_pcm_stream_unlock(pa->capture_pcm_substream); | ||
170 | } | ||
171 | |||
172 | static void complete_handler_audio(struct urb *urb) | ||
173 | { | ||
174 | struct poseidon_audio *pa = urb->context; | ||
175 | struct snd_pcm_substream *substream = pa->capture_pcm_substream; | ||
176 | int period_elapsed = 0; | ||
177 | int ret; | ||
178 | |||
179 | if (1 == pa->card_close || pa->capture_stream != STREAM_ON) | ||
180 | return; | ||
181 | |||
182 | if (urb->status != 0) { | ||
183 | /*if (urb->status == -ESHUTDOWN)*/ | ||
184 | return; | ||
185 | } | ||
186 | |||
187 | if (substream) { | ||
188 | if (urb->actual_length) { | ||
189 | handle_audio_data(urb, &period_elapsed); | ||
190 | if (period_elapsed) | ||
191 | snd_pcm_period_elapsed(substream); | ||
192 | } | ||
193 | } | ||
194 | |||
195 | ret = usb_submit_urb(urb, GFP_ATOMIC); | ||
196 | if (ret < 0) | ||
197 | log("audio urb failed (errcod = %i)", ret); | ||
198 | return; | ||
199 | } | ||
200 | |||
201 | static int fire_audio_urb(struct poseidon *p) | ||
202 | { | ||
203 | int i, ret = 0; | ||
204 | struct poseidon_audio *pa = &p->audio; | ||
205 | |||
206 | alloc_bulk_urbs_generic(pa->urb_array, AUDIO_BUFS, | ||
207 | p->udev, AUDIO_EP, | ||
208 | AUDIO_BUF_SIZE, GFP_ATOMIC, | ||
209 | complete_handler_audio, pa); | ||
210 | |||
211 | for (i = 0; i < AUDIO_BUFS; i++) { | ||
212 | ret = usb_submit_urb(pa->urb_array[i], GFP_KERNEL); | ||
213 | if (ret) | ||
214 | log("urb err : %d", ret); | ||
215 | } | ||
216 | log(); | ||
217 | return ret; | ||
218 | } | ||
219 | |||
220 | static int snd_pd_capture_trigger(struct snd_pcm_substream *substream, int cmd) | ||
221 | { | ||
222 | struct poseidon *p = snd_pcm_substream_chip(substream); | ||
223 | struct poseidon_audio *pa = &p->audio; | ||
224 | |||
225 | if (debug_mode) | ||
226 | log("cmd %d, audio stat : %d\n", cmd, pa->capture_stream); | ||
227 | |||
228 | switch (cmd) { | ||
229 | case SNDRV_PCM_TRIGGER_RESUME: | ||
230 | case SNDRV_PCM_TRIGGER_START: | ||
231 | if (pa->capture_stream == STREAM_ON) | ||
232 | return 0; | ||
233 | |||
234 | pa->rcv_position = pa->copied_position = 0; | ||
235 | pa->capture_stream = STREAM_ON; | ||
236 | |||
237 | if (in_hibernation(p)) | ||
238 | return 0; | ||
239 | fire_audio_urb(p); | ||
240 | return 0; | ||
241 | |||
242 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
243 | pa->capture_stream = STREAM_SUSPEND; | ||
244 | return 0; | ||
245 | case SNDRV_PCM_TRIGGER_STOP: | ||
246 | pa->capture_stream = STREAM_OFF; | ||
247 | return 0; | ||
248 | default: | ||
249 | return -EINVAL; | ||
250 | } | ||
251 | } | ||
252 | |||
253 | static snd_pcm_uframes_t | ||
254 | snd_pd_capture_pointer(struct snd_pcm_substream *substream) | ||
255 | { | ||
256 | struct poseidon *p = snd_pcm_substream_chip(substream); | ||
257 | struct poseidon_audio *pa = &p->audio; | ||
258 | return pa->rcv_position; | ||
259 | } | ||
260 | |||
261 | static struct page *snd_pcm_pd_get_page(struct snd_pcm_substream *subs, | ||
262 | unsigned long offset) | ||
263 | { | ||
264 | void *pageptr = subs->runtime->dma_area + offset; | ||
265 | return vmalloc_to_page(pageptr); | ||
266 | } | ||
267 | |||
268 | static struct snd_pcm_ops pcm_capture_ops = { | ||
269 | .open = snd_pd_capture_open, | ||
270 | .close = snd_pd_pcm_close, | ||
271 | .ioctl = snd_pcm_lib_ioctl, | ||
272 | .hw_params = snd_pd_hw_capture_params, | ||
273 | .hw_free = snd_pd_hw_capture_free, | ||
274 | .prepare = snd_pd_prepare, | ||
275 | .trigger = snd_pd_capture_trigger, | ||
276 | .pointer = snd_pd_capture_pointer, | ||
277 | .page = snd_pcm_pd_get_page, | ||
278 | }; | ||
279 | |||
280 | #ifdef CONFIG_PM | ||
281 | int pm_alsa_suspend(struct poseidon *p) | ||
282 | { | ||
283 | logpm(p); | ||
284 | audio_buf_free(p); | ||
285 | return 0; | ||
286 | } | ||
287 | |||
288 | int pm_alsa_resume(struct poseidon *p) | ||
289 | { | ||
290 | logpm(p); | ||
291 | fire_audio_urb(p); | ||
292 | return 0; | ||
293 | } | ||
294 | #endif | ||
295 | |||
296 | int poseidon_audio_init(struct poseidon *p) | ||
297 | { | ||
298 | struct poseidon_audio *pa = &p->audio; | ||
299 | struct snd_card *card; | ||
300 | struct snd_pcm *pcm; | ||
301 | int ret; | ||
302 | |||
303 | ret = snd_card_create(-1, "Telegent", THIS_MODULE, 0, &card); | ||
304 | if (ret != 0) | ||
305 | return ret; | ||
306 | |||
307 | ret = snd_pcm_new(card, "poseidon audio", 0, 0, 1, &pcm); | ||
308 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcm_capture_ops); | ||
309 | pcm->info_flags = 0; | ||
310 | pcm->private_data = p; | ||
311 | strcpy(pcm->name, "poseidon audio capture"); | ||
312 | |||
313 | strcpy(card->driver, "ALSA driver"); | ||
314 | strcpy(card->shortname, "poseidon Audio"); | ||
315 | strcpy(card->longname, "poseidon ALSA Audio"); | ||
316 | |||
317 | if (snd_card_register(card)) { | ||
318 | snd_card_free(card); | ||
319 | return -ENOMEM; | ||
320 | } | ||
321 | pa->card = card; | ||
322 | return 0; | ||
323 | } | ||
324 | |||
325 | int poseidon_audio_free(struct poseidon *p) | ||
326 | { | ||
327 | struct poseidon_audio *pa = &p->audio; | ||
328 | |||
329 | if (pa->card) | ||
330 | snd_card_free(pa->card); | ||
331 | return 0; | ||
332 | } | ||
diff --git a/drivers/media/video/tlg2300/pd-common.h b/drivers/media/video/tlg2300/pd-common.h new file mode 100644 index 000000000000..46066bdc73f9 --- /dev/null +++ b/drivers/media/video/tlg2300/pd-common.h | |||
@@ -0,0 +1,282 @@ | |||
1 | #ifndef PD_COMMON_H | ||
2 | #define PD_COMMON_H | ||
3 | |||
4 | #include <linux/version.h> | ||
5 | #include <linux/fs.h> | ||
6 | #include <linux/wait.h> | ||
7 | #include <linux/list.h> | ||
8 | #include <linux/videodev2.h> | ||
9 | #include <linux/semaphore.h> | ||
10 | #include <linux/usb.h> | ||
11 | #include <linux/poll.h> | ||
12 | #include <media/videobuf-vmalloc.h> | ||
13 | #include <media/v4l2-device.h> | ||
14 | |||
15 | #include "dvb_frontend.h" | ||
16 | #include "dvbdev.h" | ||
17 | #include "dvb_demux.h" | ||
18 | #include "dmxdev.h" | ||
19 | |||
20 | #define SBUF_NUM 8 | ||
21 | #define MAX_BUFFER_NUM 6 | ||
22 | #define PK_PER_URB 32 | ||
23 | #define ISO_PKT_SIZE 3072 | ||
24 | |||
25 | #define POSEIDON_STATE_NONE (0x0000) | ||
26 | #define POSEIDON_STATE_ANALOG (0x0001) | ||
27 | #define POSEIDON_STATE_FM (0x0002) | ||
28 | #define POSEIDON_STATE_DVBT (0x0004) | ||
29 | #define POSEIDON_STATE_VBI (0x0008) | ||
30 | #define POSEIDON_STATE_DISCONNECT (0x0080) | ||
31 | |||
32 | #define PM_SUSPEND_DELAY 3 | ||
33 | |||
34 | #define V4L_PAL_VBI_LINES 18 | ||
35 | #define V4L_NTSC_VBI_LINES 12 | ||
36 | #define V4L_PAL_VBI_FRAMESIZE (V4L_PAL_VBI_LINES * 1440 * 2) | ||
37 | #define V4L_NTSC_VBI_FRAMESIZE (V4L_NTSC_VBI_LINES * 1440 * 2) | ||
38 | |||
39 | #define TUNER_FREQ_MIN (45000000) | ||
40 | #define TUNER_FREQ_MAX (862000000) | ||
41 | |||
42 | struct vbi_data { | ||
43 | struct video_device *v_dev; | ||
44 | struct video_data *video; | ||
45 | struct front_face *front; | ||
46 | |||
47 | unsigned int copied; | ||
48 | unsigned int vbi_size; /* the whole size of two fields */ | ||
49 | int users; | ||
50 | }; | ||
51 | |||
52 | /* | ||
53 | * This is the running context of the video, it is useful for | ||
54 | * resume() | ||
55 | */ | ||
56 | struct running_context { | ||
57 | u32 freq; /* VIDIOC_S_FREQUENCY */ | ||
58 | int audio_idx; /* VIDIOC_S_TUNER */ | ||
59 | v4l2_std_id tvnormid; /* VIDIOC_S_STD */ | ||
60 | int sig_index; /* VIDIOC_S_INPUT */ | ||
61 | struct v4l2_pix_format pix; /* VIDIOC_S_FMT */ | ||
62 | }; | ||
63 | |||
64 | struct video_data { | ||
65 | /* v4l2 video device */ | ||
66 | struct video_device *v_dev; | ||
67 | |||
68 | /* the working context */ | ||
69 | struct running_context context; | ||
70 | |||
71 | /* for data copy */ | ||
72 | int field_count; | ||
73 | |||
74 | char *dst; | ||
75 | int lines_copied; | ||
76 | int prev_left; | ||
77 | |||
78 | int lines_per_field; | ||
79 | int lines_size; | ||
80 | |||
81 | /* for communication */ | ||
82 | u8 endpoint_addr; | ||
83 | struct urb *urb_array[SBUF_NUM]; | ||
84 | struct vbi_data *vbi; | ||
85 | struct poseidon *pd; | ||
86 | struct front_face *front; | ||
87 | |||
88 | int is_streaming; | ||
89 | int users; | ||
90 | |||
91 | /* for bubble handler */ | ||
92 | struct work_struct bubble_work; | ||
93 | }; | ||
94 | |||
95 | enum pcm_stream_state { | ||
96 | STREAM_OFF, | ||
97 | STREAM_ON, | ||
98 | STREAM_SUSPEND, | ||
99 | }; | ||
100 | |||
101 | #define AUDIO_BUFS (3) | ||
102 | #define CAPTURE_STREAM_EN 1 | ||
103 | struct poseidon_audio { | ||
104 | struct urb *urb_array[AUDIO_BUFS]; | ||
105 | unsigned int copied_position; | ||
106 | struct snd_pcm_substream *capture_pcm_substream; | ||
107 | |||
108 | unsigned int rcv_position; | ||
109 | struct snd_card *card; | ||
110 | int card_close; | ||
111 | |||
112 | int users; | ||
113 | int pm_state; | ||
114 | enum pcm_stream_state capture_stream; | ||
115 | }; | ||
116 | |||
117 | struct radio_data { | ||
118 | __u32 fm_freq; | ||
119 | int users; | ||
120 | unsigned int is_radio_streaming; | ||
121 | int pre_emphasis; | ||
122 | struct video_device *fm_dev; | ||
123 | }; | ||
124 | |||
125 | #define DVB_SBUF_NUM 4 | ||
126 | #define DVB_URB_BUF_SIZE 0x2000 | ||
127 | struct pd_dvb_adapter { | ||
128 | struct dvb_adapter dvb_adap; | ||
129 | struct dvb_frontend dvb_fe; | ||
130 | struct dmxdev dmxdev; | ||
131 | struct dvb_demux demux; | ||
132 | |||
133 | atomic_t users; | ||
134 | atomic_t active_feed; | ||
135 | |||
136 | /* data transfer */ | ||
137 | s32 is_streaming; | ||
138 | struct urb *urb_array[DVB_SBUF_NUM]; | ||
139 | struct poseidon *pd_device; | ||
140 | u8 ep_addr; | ||
141 | u8 reserved[3]; | ||
142 | |||
143 | /* data for power resume*/ | ||
144 | struct dvb_frontend_parameters fe_param; | ||
145 | |||
146 | /* for channel scanning */ | ||
147 | int prev_freq; | ||
148 | int bandwidth; | ||
149 | unsigned long last_jiffies; | ||
150 | }; | ||
151 | |||
152 | struct front_face { | ||
153 | /* use this field to distinguish VIDEO and VBI */ | ||
154 | enum v4l2_buf_type type; | ||
155 | |||
156 | /* for host */ | ||
157 | struct videobuf_queue q; | ||
158 | |||
159 | /* the bridge for host and device */ | ||
160 | struct videobuf_buffer *curr_frame; | ||
161 | |||
162 | /* for device */ | ||
163 | spinlock_t queue_lock; | ||
164 | struct list_head active; | ||
165 | struct poseidon *pd; | ||
166 | }; | ||
167 | |||
168 | struct poseidon { | ||
169 | struct list_head device_list; | ||
170 | |||
171 | struct mutex lock; | ||
172 | struct kref kref; | ||
173 | |||
174 | /* for V4L2 */ | ||
175 | struct v4l2_device v4l2_dev; | ||
176 | |||
177 | /* hardware info */ | ||
178 | struct usb_device *udev; | ||
179 | struct usb_interface *interface; | ||
180 | int cur_transfer_mode; | ||
181 | |||
182 | struct video_data video_data; /* video */ | ||
183 | struct vbi_data vbi_data; /* vbi */ | ||
184 | struct poseidon_audio audio; /* audio (alsa) */ | ||
185 | struct radio_data radio_data; /* FM */ | ||
186 | struct pd_dvb_adapter dvb_data; /* DVB */ | ||
187 | |||
188 | u32 state; | ||
189 | struct file *file_for_stream; /* the active stream*/ | ||
190 | |||
191 | #ifdef CONFIG_PM | ||
192 | int (*pm_suspend)(struct poseidon *); | ||
193 | int (*pm_resume)(struct poseidon *); | ||
194 | pm_message_t msg; | ||
195 | |||
196 | struct work_struct pm_work; | ||
197 | u8 portnum; | ||
198 | #endif | ||
199 | }; | ||
200 | |||
201 | struct poseidon_format { | ||
202 | char *name; | ||
203 | int fourcc; /* video4linux 2 */ | ||
204 | int depth; /* bit/pixel */ | ||
205 | int flags; | ||
206 | }; | ||
207 | |||
208 | struct poseidon_tvnorm { | ||
209 | v4l2_std_id v4l2_id; | ||
210 | char name[12]; | ||
211 | u32 tlg_tvnorm; | ||
212 | }; | ||
213 | |||
214 | /* video */ | ||
215 | int pd_video_init(struct poseidon *); | ||
216 | void pd_video_exit(struct poseidon *); | ||
217 | int stop_all_video_stream(struct poseidon *); | ||
218 | |||
219 | /* alsa audio */ | ||
220 | int poseidon_audio_init(struct poseidon *); | ||
221 | int poseidon_audio_free(struct poseidon *); | ||
222 | #ifdef CONFIG_PM | ||
223 | int pm_alsa_suspend(struct poseidon *); | ||
224 | int pm_alsa_resume(struct poseidon *); | ||
225 | #endif | ||
226 | |||
227 | /* dvb */ | ||
228 | int pd_dvb_usb_device_init(struct poseidon *); | ||
229 | void pd_dvb_usb_device_exit(struct poseidon *); | ||
230 | void pd_dvb_usb_device_cleanup(struct poseidon *); | ||
231 | int pd_dvb_get_adapter_num(struct pd_dvb_adapter *); | ||
232 | void dvb_stop_streaming(struct pd_dvb_adapter *); | ||
233 | |||
234 | /* FM */ | ||
235 | int poseidon_fm_init(struct poseidon *); | ||
236 | int poseidon_fm_exit(struct poseidon *); | ||
237 | struct video_device *vdev_init(struct poseidon *, struct video_device *); | ||
238 | |||
239 | /* vendor command ops */ | ||
240 | int send_set_req(struct poseidon*, u8, s32, s32*); | ||
241 | int send_get_req(struct poseidon*, u8, s32, void*, s32*, s32); | ||
242 | s32 set_tuner_mode(struct poseidon*, unsigned char); | ||
243 | |||
244 | /* bulk urb alloc/free */ | ||
245 | int alloc_bulk_urbs_generic(struct urb **urb_array, int num, | ||
246 | struct usb_device *udev, u8 ep_addr, | ||
247 | int buf_size, gfp_t gfp_flags, | ||
248 | usb_complete_t complete_fn, void *context); | ||
249 | void free_all_urb_generic(struct urb **urb_array, int num); | ||
250 | |||
251 | /* misc */ | ||
252 | void poseidon_delete(struct kref *kref); | ||
253 | void destroy_video_device(struct video_device **v_dev); | ||
254 | extern int debug_mode; | ||
255 | void set_debug_mode(struct video_device *vfd, int debug_mode); | ||
256 | |||
257 | #ifdef CONFIG_PM | ||
258 | #define in_hibernation(pd) (pd->msg.event == PM_EVENT_FREEZE) | ||
259 | #else | ||
260 | #define in_hibernation(pd) (0) | ||
261 | #endif | ||
262 | #define get_pm_count(p) (atomic_read(&(p)->interface->pm_usage_cnt)) | ||
263 | |||
264 | #define log(a, ...) printk(KERN_DEBUG "\t[ %s : %.3d ] "a"\n", \ | ||
265 | __func__, __LINE__, ## __VA_ARGS__) | ||
266 | |||
267 | /* for power management */ | ||
268 | #define logpm(pd) do {\ | ||
269 | if (debug_mode & 0x10)\ | ||
270 | log();\ | ||
271 | } while (0) | ||
272 | |||
273 | #define logs(f) do { \ | ||
274 | if ((debug_mode & 0x4) && \ | ||
275 | (f)->type == V4L2_BUF_TYPE_VBI_CAPTURE) \ | ||
276 | log("type : VBI");\ | ||
277 | \ | ||
278 | if ((debug_mode & 0x8) && \ | ||
279 | (f)->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) \ | ||
280 | log("type : VIDEO");\ | ||
281 | } while (0) | ||
282 | #endif | ||
diff --git a/drivers/media/video/tlg2300/pd-dvb.c b/drivers/media/video/tlg2300/pd-dvb.c new file mode 100644 index 000000000000..4133aee568bf --- /dev/null +++ b/drivers/media/video/tlg2300/pd-dvb.c | |||
@@ -0,0 +1,593 @@ | |||
1 | #include "pd-common.h" | ||
2 | #include <linux/kernel.h> | ||
3 | #include <linux/usb.h> | ||
4 | #include <linux/dvb/dmx.h> | ||
5 | #include <linux/delay.h> | ||
6 | |||
7 | #include "vendorcmds.h" | ||
8 | #include <linux/sched.h> | ||
9 | #include <asm/atomic.h> | ||
10 | |||
11 | static void dvb_urb_cleanup(struct pd_dvb_adapter *pd_dvb); | ||
12 | |||
13 | static int dvb_bandwidth[][2] = { | ||
14 | { TLG_BW_8, BANDWIDTH_8_MHZ }, | ||
15 | { TLG_BW_7, BANDWIDTH_7_MHZ }, | ||
16 | { TLG_BW_6, BANDWIDTH_6_MHZ } | ||
17 | }; | ||
18 | static int dvb_bandwidth_length = ARRAY_SIZE(dvb_bandwidth); | ||
19 | |||
20 | static s32 dvb_start_streaming(struct pd_dvb_adapter *pd_dvb); | ||
21 | static int poseidon_check_mode_dvbt(struct poseidon *pd) | ||
22 | { | ||
23 | s32 ret = 0, cmd_status = 0; | ||
24 | |||
25 | set_current_state(TASK_INTERRUPTIBLE); | ||
26 | schedule_timeout(HZ/4); | ||
27 | |||
28 | ret = usb_set_interface(pd->udev, 0, BULK_ALTERNATE_IFACE); | ||
29 | if (ret != 0) | ||
30 | return ret; | ||
31 | |||
32 | ret = set_tuner_mode(pd, TLG_MODE_CAPS_DVB_T); | ||
33 | if (ret) | ||
34 | return ret; | ||
35 | |||
36 | /* signal source */ | ||
37 | ret = send_set_req(pd, SGNL_SRC_SEL, TLG_SIG_SRC_ANTENNA, &cmd_status); | ||
38 | if (ret|cmd_status) | ||
39 | return ret; | ||
40 | |||
41 | return 0; | ||
42 | } | ||
43 | |||
44 | /* acquire : | ||
45 | * 1 == open | ||
46 | * 0 == release | ||
47 | */ | ||
48 | static int poseidon_ts_bus_ctrl(struct dvb_frontend *fe, int acquire) | ||
49 | { | ||
50 | struct poseidon *pd = fe->demodulator_priv; | ||
51 | struct pd_dvb_adapter *pd_dvb; | ||
52 | int ret = 0; | ||
53 | |||
54 | if (!pd) | ||
55 | return -ENODEV; | ||
56 | |||
57 | pd_dvb = container_of(fe, struct pd_dvb_adapter, dvb_fe); | ||
58 | if (acquire) { | ||
59 | mutex_lock(&pd->lock); | ||
60 | if (pd->state & POSEIDON_STATE_DISCONNECT) { | ||
61 | ret = -ENODEV; | ||
62 | goto open_out; | ||
63 | } | ||
64 | |||
65 | if (pd->state && !(pd->state & POSEIDON_STATE_DVBT)) { | ||
66 | ret = -EBUSY; | ||
67 | goto open_out; | ||
68 | } | ||
69 | |||
70 | usb_autopm_get_interface(pd->interface); | ||
71 | if (0 == pd->state) { | ||
72 | ret = poseidon_check_mode_dvbt(pd); | ||
73 | if (ret < 0) { | ||
74 | usb_autopm_put_interface(pd->interface); | ||
75 | goto open_out; | ||
76 | } | ||
77 | pd->state |= POSEIDON_STATE_DVBT; | ||
78 | pd_dvb->bandwidth = 0; | ||
79 | pd_dvb->prev_freq = 0; | ||
80 | } | ||
81 | atomic_inc(&pd_dvb->users); | ||
82 | kref_get(&pd->kref); | ||
83 | open_out: | ||
84 | mutex_unlock(&pd->lock); | ||
85 | } else { | ||
86 | dvb_stop_streaming(pd_dvb); | ||
87 | |||
88 | if (atomic_dec_and_test(&pd_dvb->users)) { | ||
89 | mutex_lock(&pd->lock); | ||
90 | pd->state &= ~POSEIDON_STATE_DVBT; | ||
91 | mutex_unlock(&pd->lock); | ||
92 | } | ||
93 | kref_put(&pd->kref, poseidon_delete); | ||
94 | usb_autopm_put_interface(pd->interface); | ||
95 | } | ||
96 | return ret; | ||
97 | } | ||
98 | |||
99 | static void poseidon_fe_release(struct dvb_frontend *fe) | ||
100 | { | ||
101 | struct poseidon *pd = fe->demodulator_priv; | ||
102 | |||
103 | #ifdef CONFIG_PM | ||
104 | pd->pm_suspend = NULL; | ||
105 | pd->pm_resume = NULL; | ||
106 | #endif | ||
107 | } | ||
108 | |||
109 | static s32 poseidon_fe_sleep(struct dvb_frontend *fe) | ||
110 | { | ||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | /* | ||
115 | * return true if we can satisfy the conditions, else return false. | ||
116 | */ | ||
117 | static bool check_scan_ok(__u32 freq, int bandwidth, | ||
118 | struct pd_dvb_adapter *adapter) | ||
119 | { | ||
120 | if (bandwidth < 0) | ||
121 | return false; | ||
122 | |||
123 | if (adapter->prev_freq == freq | ||
124 | && adapter->bandwidth == bandwidth) { | ||
125 | long nl = jiffies - adapter->last_jiffies; | ||
126 | unsigned int msec ; | ||
127 | |||
128 | msec = jiffies_to_msecs(abs(nl)); | ||
129 | return msec > 15000 ? true : false; | ||
130 | } | ||
131 | return true; | ||
132 | } | ||
133 | |||
134 | /* | ||
135 | * Check if the firmware delays too long for an invalid frequency. | ||
136 | */ | ||
137 | static int fw_delay_overflow(struct pd_dvb_adapter *adapter) | ||
138 | { | ||
139 | long nl = jiffies - adapter->last_jiffies; | ||
140 | unsigned int msec ; | ||
141 | |||
142 | msec = jiffies_to_msecs(abs(nl)); | ||
143 | return msec > 800 ? true : false; | ||
144 | } | ||
145 | |||
146 | static int poseidon_set_fe(struct dvb_frontend *fe, | ||
147 | struct dvb_frontend_parameters *fep) | ||
148 | { | ||
149 | s32 ret = 0, cmd_status = 0; | ||
150 | s32 i, bandwidth = -1; | ||
151 | struct poseidon *pd = fe->demodulator_priv; | ||
152 | struct pd_dvb_adapter *pd_dvb = &pd->dvb_data; | ||
153 | |||
154 | if (in_hibernation(pd)) | ||
155 | return -EBUSY; | ||
156 | |||
157 | mutex_lock(&pd->lock); | ||
158 | for (i = 0; i < dvb_bandwidth_length; i++) | ||
159 | if (fep->u.ofdm.bandwidth == dvb_bandwidth[i][1]) | ||
160 | bandwidth = dvb_bandwidth[i][0]; | ||
161 | |||
162 | if (check_scan_ok(fep->frequency, bandwidth, pd_dvb)) { | ||
163 | ret = send_set_req(pd, TUNE_FREQ_SELECT, | ||
164 | fep->frequency / 1000, &cmd_status); | ||
165 | if (ret | cmd_status) { | ||
166 | log("error line"); | ||
167 | goto front_out; | ||
168 | } | ||
169 | |||
170 | ret = send_set_req(pd, DVBT_BANDW_SEL, | ||
171 | bandwidth, &cmd_status); | ||
172 | if (ret | cmd_status) { | ||
173 | log("error line"); | ||
174 | goto front_out; | ||
175 | } | ||
176 | |||
177 | ret = send_set_req(pd, TAKE_REQUEST, 0, &cmd_status); | ||
178 | if (ret | cmd_status) { | ||
179 | log("error line"); | ||
180 | goto front_out; | ||
181 | } | ||
182 | |||
183 | /* save the context for future */ | ||
184 | memcpy(&pd_dvb->fe_param, fep, sizeof(*fep)); | ||
185 | pd_dvb->bandwidth = bandwidth; | ||
186 | pd_dvb->prev_freq = fep->frequency; | ||
187 | pd_dvb->last_jiffies = jiffies; | ||
188 | } | ||
189 | front_out: | ||
190 | mutex_unlock(&pd->lock); | ||
191 | return ret; | ||
192 | } | ||
193 | |||
194 | #ifdef CONFIG_PM | ||
195 | static int pm_dvb_suspend(struct poseidon *pd) | ||
196 | { | ||
197 | struct pd_dvb_adapter *pd_dvb = &pd->dvb_data; | ||
198 | dvb_stop_streaming(pd_dvb); | ||
199 | dvb_urb_cleanup(pd_dvb); | ||
200 | msleep(500); | ||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | static int pm_dvb_resume(struct poseidon *pd) | ||
205 | { | ||
206 | struct pd_dvb_adapter *pd_dvb = &pd->dvb_data; | ||
207 | |||
208 | poseidon_check_mode_dvbt(pd); | ||
209 | msleep(300); | ||
210 | poseidon_set_fe(&pd_dvb->dvb_fe, &pd_dvb->fe_param); | ||
211 | |||
212 | dvb_start_streaming(pd_dvb); | ||
213 | return 0; | ||
214 | } | ||
215 | #endif | ||
216 | |||
217 | static s32 poseidon_fe_init(struct dvb_frontend *fe) | ||
218 | { | ||
219 | struct poseidon *pd = fe->demodulator_priv; | ||
220 | struct pd_dvb_adapter *pd_dvb = &pd->dvb_data; | ||
221 | |||
222 | #ifdef CONFIG_PM | ||
223 | pd->pm_suspend = pm_dvb_suspend; | ||
224 | pd->pm_resume = pm_dvb_resume; | ||
225 | #endif | ||
226 | memset(&pd_dvb->fe_param, 0, | ||
227 | sizeof(struct dvb_frontend_parameters)); | ||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | static int poseidon_get_fe(struct dvb_frontend *fe, | ||
232 | struct dvb_frontend_parameters *fep) | ||
233 | { | ||
234 | struct poseidon *pd = fe->demodulator_priv; | ||
235 | struct pd_dvb_adapter *pd_dvb = &pd->dvb_data; | ||
236 | |||
237 | memcpy(fep, &pd_dvb->fe_param, sizeof(*fep)); | ||
238 | return 0; | ||
239 | } | ||
240 | |||
241 | static int poseidon_fe_get_tune_settings(struct dvb_frontend *fe, | ||
242 | struct dvb_frontend_tune_settings *tune) | ||
243 | { | ||
244 | tune->min_delay_ms = 1000; | ||
245 | return 0; | ||
246 | } | ||
247 | |||
248 | static int poseidon_read_status(struct dvb_frontend *fe, fe_status_t *stat) | ||
249 | { | ||
250 | struct poseidon *pd = fe->demodulator_priv; | ||
251 | s32 ret = -1, cmd_status; | ||
252 | struct tuner_dtv_sig_stat_s status = {}; | ||
253 | |||
254 | if (in_hibernation(pd)) | ||
255 | return -EBUSY; | ||
256 | mutex_lock(&pd->lock); | ||
257 | |||
258 | ret = send_get_req(pd, TUNER_STATUS, TLG_MODE_DVB_T, | ||
259 | &status, &cmd_status, sizeof(status)); | ||
260 | if (ret | cmd_status) { | ||
261 | log("get tuner status error"); | ||
262 | goto out; | ||
263 | } | ||
264 | |||
265 | if (debug_mode) | ||
266 | log("P : %d, L %d, LB :%d", status.sig_present, | ||
267 | status.sig_locked, status.sig_lock_busy); | ||
268 | |||
269 | if (status.sig_lock_busy) { | ||
270 | goto out; | ||
271 | } else if (status.sig_present || status.sig_locked) { | ||
272 | *stat |= FE_HAS_LOCK | FE_HAS_SIGNAL | FE_HAS_CARRIER | ||
273 | | FE_HAS_SYNC | FE_HAS_VITERBI; | ||
274 | } else { | ||
275 | if (fw_delay_overflow(&pd->dvb_data)) | ||
276 | *stat |= FE_TIMEDOUT; | ||
277 | } | ||
278 | out: | ||
279 | mutex_unlock(&pd->lock); | ||
280 | return ret; | ||
281 | } | ||
282 | |||
283 | static int poseidon_read_ber(struct dvb_frontend *fe, u32 *ber) | ||
284 | { | ||
285 | struct poseidon *pd = fe->demodulator_priv; | ||
286 | struct tuner_ber_rate_s tlg_ber = {}; | ||
287 | s32 ret = -1, cmd_status; | ||
288 | |||
289 | mutex_lock(&pd->lock); | ||
290 | ret = send_get_req(pd, TUNER_BER_RATE, 0, | ||
291 | &tlg_ber, &cmd_status, sizeof(tlg_ber)); | ||
292 | if (ret | cmd_status) | ||
293 | goto out; | ||
294 | *ber = tlg_ber.ber_rate; | ||
295 | out: | ||
296 | mutex_unlock(&pd->lock); | ||
297 | return ret; | ||
298 | } | ||
299 | |||
300 | static s32 poseidon_read_signal_strength(struct dvb_frontend *fe, u16 *strength) | ||
301 | { | ||
302 | struct poseidon *pd = fe->demodulator_priv; | ||
303 | struct tuner_dtv_sig_stat_s status = {}; | ||
304 | s32 ret = 0, cmd_status; | ||
305 | |||
306 | mutex_lock(&pd->lock); | ||
307 | ret = send_get_req(pd, TUNER_STATUS, TLG_MODE_DVB_T, | ||
308 | &status, &cmd_status, sizeof(status)); | ||
309 | if (ret | cmd_status) | ||
310 | goto out; | ||
311 | if ((status.sig_present || status.sig_locked) && !status.sig_strength) | ||
312 | *strength = 0xFFFF; | ||
313 | else | ||
314 | *strength = status.sig_strength; | ||
315 | out: | ||
316 | mutex_unlock(&pd->lock); | ||
317 | return ret; | ||
318 | } | ||
319 | |||
320 | static int poseidon_read_snr(struct dvb_frontend *fe, u16 *snr) | ||
321 | { | ||
322 | return 0; | ||
323 | } | ||
324 | |||
325 | static int poseidon_read_unc_blocks(struct dvb_frontend *fe, u32 *unc) | ||
326 | { | ||
327 | *unc = 0; | ||
328 | return 0; | ||
329 | } | ||
330 | |||
331 | static struct dvb_frontend_ops poseidon_frontend_ops = { | ||
332 | .info = { | ||
333 | .name = "Poseidon DVB-T", | ||
334 | .type = FE_OFDM, | ||
335 | .frequency_min = 174000000, | ||
336 | .frequency_max = 862000000, | ||
337 | .frequency_stepsize = 62500,/* FIXME */ | ||
338 | .caps = FE_CAN_INVERSION_AUTO | | ||
339 | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | ||
340 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | | ||
341 | FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | | ||
342 | FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO | | ||
343 | FE_CAN_GUARD_INTERVAL_AUTO | | ||
344 | FE_CAN_RECOVER | | ||
345 | FE_CAN_HIERARCHY_AUTO, | ||
346 | }, | ||
347 | |||
348 | .release = poseidon_fe_release, | ||
349 | |||
350 | .init = poseidon_fe_init, | ||
351 | .sleep = poseidon_fe_sleep, | ||
352 | |||
353 | .set_frontend = poseidon_set_fe, | ||
354 | .get_frontend = poseidon_get_fe, | ||
355 | .get_tune_settings = poseidon_fe_get_tune_settings, | ||
356 | |||
357 | .read_status = poseidon_read_status, | ||
358 | .read_ber = poseidon_read_ber, | ||
359 | .read_signal_strength = poseidon_read_signal_strength, | ||
360 | .read_snr = poseidon_read_snr, | ||
361 | .read_ucblocks = poseidon_read_unc_blocks, | ||
362 | |||
363 | .ts_bus_ctrl = poseidon_ts_bus_ctrl, | ||
364 | }; | ||
365 | |||
366 | static void dvb_urb_irq(struct urb *urb) | ||
367 | { | ||
368 | struct pd_dvb_adapter *pd_dvb = urb->context; | ||
369 | int len = urb->transfer_buffer_length; | ||
370 | struct dvb_demux *demux = &pd_dvb->demux; | ||
371 | s32 ret; | ||
372 | |||
373 | if (!pd_dvb->is_streaming || urb->status) { | ||
374 | if (urb->status == -EPROTO) | ||
375 | goto resend; | ||
376 | return; | ||
377 | } | ||
378 | |||
379 | if (urb->actual_length == len) | ||
380 | dvb_dmx_swfilter(demux, urb->transfer_buffer, len); | ||
381 | else if (urb->actual_length == len - 4) { | ||
382 | int offset; | ||
383 | u8 *buf = urb->transfer_buffer; | ||
384 | |||
385 | /* | ||
386 | * The packet size is 512, | ||
387 | * last packet contains 456 bytes tsp data | ||
388 | */ | ||
389 | for (offset = 456; offset < len; offset += 512) { | ||
390 | if (!strncmp(buf + offset, "DVHS", 4)) { | ||
391 | dvb_dmx_swfilter(demux, buf, offset); | ||
392 | if (len > offset + 52 + 4) { | ||
393 | /*16 bytes trailer + 36 bytes padding */ | ||
394 | buf += offset + 52; | ||
395 | len -= offset + 52 + 4; | ||
396 | dvb_dmx_swfilter(demux, buf, len); | ||
397 | } | ||
398 | break; | ||
399 | } | ||
400 | } | ||
401 | } | ||
402 | |||
403 | resend: | ||
404 | ret = usb_submit_urb(urb, GFP_ATOMIC); | ||
405 | if (ret) | ||
406 | log(" usb_submit_urb failed: error %d", ret); | ||
407 | } | ||
408 | |||
409 | static int dvb_urb_init(struct pd_dvb_adapter *pd_dvb) | ||
410 | { | ||
411 | if (pd_dvb->urb_array[0]) | ||
412 | return 0; | ||
413 | |||
414 | alloc_bulk_urbs_generic(pd_dvb->urb_array, DVB_SBUF_NUM, | ||
415 | pd_dvb->pd_device->udev, pd_dvb->ep_addr, | ||
416 | DVB_URB_BUF_SIZE, GFP_KERNEL, | ||
417 | dvb_urb_irq, pd_dvb); | ||
418 | return 0; | ||
419 | } | ||
420 | |||
421 | static void dvb_urb_cleanup(struct pd_dvb_adapter *pd_dvb) | ||
422 | { | ||
423 | free_all_urb_generic(pd_dvb->urb_array, DVB_SBUF_NUM); | ||
424 | } | ||
425 | |||
426 | static s32 dvb_start_streaming(struct pd_dvb_adapter *pd_dvb) | ||
427 | { | ||
428 | struct poseidon *pd = pd_dvb->pd_device; | ||
429 | int ret = 0; | ||
430 | |||
431 | if (pd->state & POSEIDON_STATE_DISCONNECT) | ||
432 | return -ENODEV; | ||
433 | |||
434 | mutex_lock(&pd->lock); | ||
435 | if (!pd_dvb->is_streaming) { | ||
436 | s32 i, cmd_status = 0; | ||
437 | /* | ||
438 | * Once upon a time, there was a difficult bug lying here. | ||
439 | * ret = send_set_req(pd, TAKE_REQUEST, 0, &cmd_status); | ||
440 | */ | ||
441 | |||
442 | ret = send_set_req(pd, PLAY_SERVICE, 1, &cmd_status); | ||
443 | if (ret | cmd_status) | ||
444 | goto out; | ||
445 | |||
446 | ret = dvb_urb_init(pd_dvb); | ||
447 | if (ret < 0) | ||
448 | goto out; | ||
449 | |||
450 | pd_dvb->is_streaming = 1; | ||
451 | for (i = 0; i < DVB_SBUF_NUM; i++) { | ||
452 | ret = usb_submit_urb(pd_dvb->urb_array[i], | ||
453 | GFP_KERNEL); | ||
454 | if (ret) { | ||
455 | log(" submit urb error %d", ret); | ||
456 | goto out; | ||
457 | } | ||
458 | } | ||
459 | } | ||
460 | out: | ||
461 | mutex_unlock(&pd->lock); | ||
462 | return ret; | ||
463 | } | ||
464 | |||
465 | void dvb_stop_streaming(struct pd_dvb_adapter *pd_dvb) | ||
466 | { | ||
467 | struct poseidon *pd = pd_dvb->pd_device; | ||
468 | |||
469 | mutex_lock(&pd->lock); | ||
470 | if (pd_dvb->is_streaming) { | ||
471 | s32 i, ret, cmd_status = 0; | ||
472 | |||
473 | pd_dvb->is_streaming = 0; | ||
474 | |||
475 | for (i = 0; i < DVB_SBUF_NUM; i++) | ||
476 | if (pd_dvb->urb_array[i]) | ||
477 | usb_kill_urb(pd_dvb->urb_array[i]); | ||
478 | |||
479 | ret = send_set_req(pd, PLAY_SERVICE, TLG_TUNE_PLAY_SVC_STOP, | ||
480 | &cmd_status); | ||
481 | if (ret | cmd_status) | ||
482 | log("error"); | ||
483 | } | ||
484 | mutex_unlock(&pd->lock); | ||
485 | } | ||
486 | |||
487 | static int pd_start_feed(struct dvb_demux_feed *feed) | ||
488 | { | ||
489 | struct pd_dvb_adapter *pd_dvb = feed->demux->priv; | ||
490 | int ret = 0; | ||
491 | |||
492 | if (!pd_dvb) | ||
493 | return -1; | ||
494 | if (atomic_inc_return(&pd_dvb->active_feed) == 1) | ||
495 | ret = dvb_start_streaming(pd_dvb); | ||
496 | return ret; | ||
497 | } | ||
498 | |||
499 | static int pd_stop_feed(struct dvb_demux_feed *feed) | ||
500 | { | ||
501 | struct pd_dvb_adapter *pd_dvb = feed->demux->priv; | ||
502 | |||
503 | if (!pd_dvb) | ||
504 | return -1; | ||
505 | if (atomic_dec_and_test(&pd_dvb->active_feed)) | ||
506 | dvb_stop_streaming(pd_dvb); | ||
507 | return 0; | ||
508 | } | ||
509 | |||
510 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
511 | int pd_dvb_usb_device_init(struct poseidon *pd) | ||
512 | { | ||
513 | struct pd_dvb_adapter *pd_dvb = &pd->dvb_data; | ||
514 | struct dvb_demux *dvbdemux; | ||
515 | int ret = 0; | ||
516 | |||
517 | pd_dvb->ep_addr = 0x82; | ||
518 | atomic_set(&pd_dvb->users, 0); | ||
519 | atomic_set(&pd_dvb->active_feed, 0); | ||
520 | pd_dvb->pd_device = pd; | ||
521 | |||
522 | ret = dvb_register_adapter(&pd_dvb->dvb_adap, | ||
523 | "Poseidon dvbt adapter", | ||
524 | THIS_MODULE, | ||
525 | NULL /* for hibernation correctly*/, | ||
526 | adapter_nr); | ||
527 | if (ret < 0) | ||
528 | goto error1; | ||
529 | |||
530 | /* register frontend */ | ||
531 | pd_dvb->dvb_fe.demodulator_priv = pd; | ||
532 | memcpy(&pd_dvb->dvb_fe.ops, &poseidon_frontend_ops, | ||
533 | sizeof(struct dvb_frontend_ops)); | ||
534 | ret = dvb_register_frontend(&pd_dvb->dvb_adap, &pd_dvb->dvb_fe); | ||
535 | if (ret < 0) | ||
536 | goto error2; | ||
537 | |||
538 | /* register demux device */ | ||
539 | dvbdemux = &pd_dvb->demux; | ||
540 | dvbdemux->dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING; | ||
541 | dvbdemux->priv = pd_dvb; | ||
542 | dvbdemux->feednum = dvbdemux->filternum = 64; | ||
543 | dvbdemux->start_feed = pd_start_feed; | ||
544 | dvbdemux->stop_feed = pd_stop_feed; | ||
545 | dvbdemux->write_to_decoder = NULL; | ||
546 | |||
547 | ret = dvb_dmx_init(dvbdemux); | ||
548 | if (ret < 0) | ||
549 | goto error3; | ||
550 | |||
551 | pd_dvb->dmxdev.filternum = pd_dvb->demux.filternum; | ||
552 | pd_dvb->dmxdev.demux = &pd_dvb->demux.dmx; | ||
553 | pd_dvb->dmxdev.capabilities = 0; | ||
554 | |||
555 | ret = dvb_dmxdev_init(&pd_dvb->dmxdev, &pd_dvb->dvb_adap); | ||
556 | if (ret < 0) | ||
557 | goto error3; | ||
558 | return 0; | ||
559 | |||
560 | error3: | ||
561 | dvb_unregister_frontend(&pd_dvb->dvb_fe); | ||
562 | error2: | ||
563 | dvb_unregister_adapter(&pd_dvb->dvb_adap); | ||
564 | error1: | ||
565 | return ret; | ||
566 | } | ||
567 | |||
568 | void pd_dvb_usb_device_exit(struct poseidon *pd) | ||
569 | { | ||
570 | struct pd_dvb_adapter *pd_dvb = &pd->dvb_data; | ||
571 | |||
572 | while (atomic_read(&pd_dvb->users) != 0 | ||
573 | || atomic_read(&pd_dvb->active_feed) != 0) { | ||
574 | set_current_state(TASK_INTERRUPTIBLE); | ||
575 | schedule_timeout(HZ); | ||
576 | } | ||
577 | dvb_dmxdev_release(&pd_dvb->dmxdev); | ||
578 | dvb_unregister_frontend(&pd_dvb->dvb_fe); | ||
579 | dvb_unregister_adapter(&pd_dvb->dvb_adap); | ||
580 | pd_dvb_usb_device_cleanup(pd); | ||
581 | } | ||
582 | |||
583 | void pd_dvb_usb_device_cleanup(struct poseidon *pd) | ||
584 | { | ||
585 | struct pd_dvb_adapter *pd_dvb = &pd->dvb_data; | ||
586 | |||
587 | dvb_urb_cleanup(pd_dvb); | ||
588 | } | ||
589 | |||
590 | int pd_dvb_get_adapter_num(struct pd_dvb_adapter *pd_dvb) | ||
591 | { | ||
592 | return pd_dvb->dvb_adap.num; | ||
593 | } | ||
diff --git a/drivers/media/video/tlg2300/pd-main.c b/drivers/media/video/tlg2300/pd-main.c new file mode 100644 index 000000000000..2cf0ebf9f28b --- /dev/null +++ b/drivers/media/video/tlg2300/pd-main.c | |||
@@ -0,0 +1,539 @@ | |||
1 | /* | ||
2 | * device driver for Telegent tlg2300 based TV cards | ||
3 | * | ||
4 | * Author : | ||
5 | * Kang Yong <kangyong@telegent.com> | ||
6 | * Zhang Xiaobing <xbzhang@telegent.com> | ||
7 | * Huang Shijie <zyziii@telegent.com> or <shijie8@gmail.com> | ||
8 | * | ||
9 | * (c) 2009 Telegent Systems | ||
10 | * (c) 2010 Telegent Systems | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #include <linux/version.h> | ||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/errno.h> | ||
30 | #include <linux/init.h> | ||
31 | #include <linux/slab.h> | ||
32 | #include <linux/module.h> | ||
33 | #include <linux/kref.h> | ||
34 | #include <linux/suspend.h> | ||
35 | #include <linux/usb/quirks.h> | ||
36 | #include <linux/ctype.h> | ||
37 | #include <linux/string.h> | ||
38 | #include <linux/types.h> | ||
39 | #include <linux/firmware.h> | ||
40 | #include <linux/smp_lock.h> | ||
41 | |||
42 | #include "vendorcmds.h" | ||
43 | #include "pd-common.h" | ||
44 | |||
45 | #define VENDOR_ID 0x1B24 | ||
46 | #define PRODUCT_ID 0x4001 | ||
47 | static struct usb_device_id id_table[] = { | ||
48 | { USB_DEVICE_AND_INTERFACE_INFO(VENDOR_ID, PRODUCT_ID, 255, 1, 0) }, | ||
49 | { USB_DEVICE_AND_INTERFACE_INFO(VENDOR_ID, PRODUCT_ID, 255, 1, 1) }, | ||
50 | { }, | ||
51 | }; | ||
52 | MODULE_DEVICE_TABLE(usb, id_table); | ||
53 | |||
54 | int debug_mode; | ||
55 | module_param(debug_mode, int, 0644); | ||
56 | MODULE_PARM_DESC(debug_mode, "0 = disable, 1 = enable, 2 = verbose"); | ||
57 | |||
58 | const char *firmware_name = "tlg2300_firmware.bin"; | ||
59 | struct usb_driver poseidon_driver; | ||
60 | static LIST_HEAD(pd_device_list); | ||
61 | |||
62 | /* | ||
63 | * send set request to USB firmware. | ||
64 | */ | ||
65 | s32 send_set_req(struct poseidon *pd, u8 cmdid, s32 param, s32 *cmd_status) | ||
66 | { | ||
67 | s32 ret; | ||
68 | s8 data[32] = {}; | ||
69 | u16 lower_16, upper_16; | ||
70 | |||
71 | if (pd->state & POSEIDON_STATE_DISCONNECT) | ||
72 | return -ENODEV; | ||
73 | |||
74 | mdelay(30); | ||
75 | |||
76 | if (param == 0) { | ||
77 | upper_16 = lower_16 = 0; | ||
78 | } else { | ||
79 | /* send 32 bit param as two 16 bit param,little endian */ | ||
80 | lower_16 = (unsigned short)(param & 0xffff); | ||
81 | upper_16 = (unsigned short)((param >> 16) & 0xffff); | ||
82 | } | ||
83 | ret = usb_control_msg(pd->udev, | ||
84 | usb_rcvctrlpipe(pd->udev, 0), | ||
85 | REQ_SET_CMD | cmdid, | ||
86 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
87 | lower_16, | ||
88 | upper_16, | ||
89 | &data, | ||
90 | sizeof(*cmd_status), | ||
91 | USB_CTRL_GET_TIMEOUT); | ||
92 | |||
93 | if (!ret) { | ||
94 | return -ENXIO; | ||
95 | } else { | ||
96 | /* 1st 4 bytes into cmd_status */ | ||
97 | memcpy((char *)cmd_status, &(data[0]), sizeof(*cmd_status)); | ||
98 | } | ||
99 | return 0; | ||
100 | } | ||
101 | |||
102 | /* | ||
103 | * send get request to Poseidon firmware. | ||
104 | */ | ||
105 | s32 send_get_req(struct poseidon *pd, u8 cmdid, s32 param, | ||
106 | void *buf, s32 *cmd_status, s32 datalen) | ||
107 | { | ||
108 | s32 ret; | ||
109 | s8 data[128] = {}; | ||
110 | u16 lower_16, upper_16; | ||
111 | |||
112 | if (pd->state & POSEIDON_STATE_DISCONNECT) | ||
113 | return -ENODEV; | ||
114 | |||
115 | mdelay(30); | ||
116 | if (param == 0) { | ||
117 | upper_16 = lower_16 = 0; | ||
118 | } else { | ||
119 | /*send 32 bit param as two 16 bit param, little endian */ | ||
120 | lower_16 = (unsigned short)(param & 0xffff); | ||
121 | upper_16 = (unsigned short)((param >> 16) & 0xffff); | ||
122 | } | ||
123 | ret = usb_control_msg(pd->udev, | ||
124 | usb_rcvctrlpipe(pd->udev, 0), | ||
125 | REQ_GET_CMD | cmdid, | ||
126 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
127 | lower_16, | ||
128 | upper_16, | ||
129 | &data, | ||
130 | (datalen + sizeof(*cmd_status)), | ||
131 | USB_CTRL_GET_TIMEOUT); | ||
132 | |||
133 | if (ret < 0) { | ||
134 | return -ENXIO; | ||
135 | } else { | ||
136 | /* 1st 4 bytes into cmd_status, remaining data into cmd_data */ | ||
137 | memcpy((char *)cmd_status, &data[0], sizeof(*cmd_status)); | ||
138 | memcpy((char *)buf, &data[sizeof(*cmd_status)], datalen); | ||
139 | } | ||
140 | return 0; | ||
141 | } | ||
142 | |||
143 | static int pm_notifier_block(struct notifier_block *nb, | ||
144 | unsigned long event, void *dummy) | ||
145 | { | ||
146 | struct poseidon *pd = NULL; | ||
147 | struct list_head *node, *next; | ||
148 | |||
149 | switch (event) { | ||
150 | case PM_POST_HIBERNATION: | ||
151 | list_for_each_safe(node, next, &pd_device_list) { | ||
152 | struct usb_device *udev; | ||
153 | struct usb_interface *iface; | ||
154 | int rc = 0; | ||
155 | |||
156 | pd = container_of(node, struct poseidon, device_list); | ||
157 | udev = pd->udev; | ||
158 | iface = pd->interface; | ||
159 | |||
160 | /* It will cause the system to reload the firmware */ | ||
161 | rc = usb_lock_device_for_reset(udev, iface); | ||
162 | if (rc >= 0) { | ||
163 | usb_reset_device(udev); | ||
164 | usb_unlock_device(udev); | ||
165 | } | ||
166 | } | ||
167 | break; | ||
168 | default: | ||
169 | break; | ||
170 | } | ||
171 | log("event :%ld\n", event); | ||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | static struct notifier_block pm_notifer = { | ||
176 | .notifier_call = pm_notifier_block, | ||
177 | }; | ||
178 | |||
179 | int set_tuner_mode(struct poseidon *pd, unsigned char mode) | ||
180 | { | ||
181 | s32 ret, cmd_status; | ||
182 | |||
183 | if (pd->state & POSEIDON_STATE_DISCONNECT) | ||
184 | return -ENODEV; | ||
185 | |||
186 | ret = send_set_req(pd, TUNE_MODE_SELECT, mode, &cmd_status); | ||
187 | if (ret || cmd_status) | ||
188 | return -ENXIO; | ||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | void poseidon_delete(struct kref *kref) | ||
193 | { | ||
194 | struct poseidon *pd = container_of(kref, struct poseidon, kref); | ||
195 | |||
196 | if (!pd) | ||
197 | return; | ||
198 | list_del_init(&pd->device_list); | ||
199 | |||
200 | pd_dvb_usb_device_cleanup(pd); | ||
201 | /* clean_audio_data(&pd->audio_data);*/ | ||
202 | |||
203 | if (pd->udev) { | ||
204 | usb_put_dev(pd->udev); | ||
205 | pd->udev = NULL; | ||
206 | } | ||
207 | if (pd->interface) { | ||
208 | usb_put_intf(pd->interface); | ||
209 | pd->interface = NULL; | ||
210 | } | ||
211 | kfree(pd); | ||
212 | log(); | ||
213 | } | ||
214 | |||
215 | static int firmware_download(struct usb_device *udev) | ||
216 | { | ||
217 | int ret = 0, actual_length; | ||
218 | const struct firmware *fw = NULL; | ||
219 | void *fwbuf = NULL; | ||
220 | size_t fwlength = 0, offset; | ||
221 | size_t max_packet_size; | ||
222 | |||
223 | ret = request_firmware(&fw, firmware_name, &udev->dev); | ||
224 | if (ret) { | ||
225 | log("download err : %d", ret); | ||
226 | return ret; | ||
227 | } | ||
228 | |||
229 | fwlength = fw->size; | ||
230 | |||
231 | fwbuf = kzalloc(fwlength, GFP_KERNEL); | ||
232 | if (!fwbuf) { | ||
233 | ret = -ENOMEM; | ||
234 | goto out; | ||
235 | } | ||
236 | memcpy(fwbuf, fw->data, fwlength); | ||
237 | |||
238 | max_packet_size = udev->ep_out[0x1]->desc.wMaxPacketSize; | ||
239 | log("\t\t download size : %d", (int)max_packet_size); | ||
240 | |||
241 | for (offset = 0; offset < fwlength; offset += max_packet_size) { | ||
242 | actual_length = 0; | ||
243 | ret = usb_bulk_msg(udev, | ||
244 | usb_sndbulkpipe(udev, 0x01), /* ep 1 */ | ||
245 | fwbuf + offset, | ||
246 | min(max_packet_size, fwlength - offset), | ||
247 | &actual_length, | ||
248 | HZ * 10); | ||
249 | if (ret) | ||
250 | break; | ||
251 | } | ||
252 | kfree(fwbuf); | ||
253 | out: | ||
254 | release_firmware(fw); | ||
255 | return ret; | ||
256 | } | ||
257 | |||
258 | static inline struct poseidon *get_pd(struct usb_interface *intf) | ||
259 | { | ||
260 | return usb_get_intfdata(intf); | ||
261 | } | ||
262 | |||
263 | #ifdef CONFIG_PM | ||
264 | /* one-to-one map : poseidon{} <----> usb_device{}'s port */ | ||
265 | static inline void set_map_flags(struct poseidon *pd, struct usb_device *udev) | ||
266 | { | ||
267 | pd->portnum = udev->portnum; | ||
268 | } | ||
269 | |||
270 | static inline int get_autopm_ref(struct poseidon *pd) | ||
271 | { | ||
272 | return pd->video_data.users + pd->vbi_data.users + pd->audio.users | ||
273 | + atomic_read(&pd->dvb_data.users) + pd->radio_data.users; | ||
274 | } | ||
275 | |||
276 | /* fixup something for poseidon */ | ||
277 | static inline struct poseidon *fixup(struct poseidon *pd) | ||
278 | { | ||
279 | int count; | ||
280 | |||
281 | /* old udev and interface have gone, so put back reference . */ | ||
282 | count = get_autopm_ref(pd); | ||
283 | log("count : %d, ref count : %d", count, get_pm_count(pd)); | ||
284 | while (count--) | ||
285 | usb_autopm_put_interface(pd->interface); | ||
286 | /*usb_autopm_set_interface(pd->interface); */ | ||
287 | |||
288 | usb_put_dev(pd->udev); | ||
289 | usb_put_intf(pd->interface); | ||
290 | log("event : %d\n", pd->msg.event); | ||
291 | return pd; | ||
292 | } | ||
293 | |||
294 | static struct poseidon *find_old_poseidon(struct usb_device *udev) | ||
295 | { | ||
296 | struct poseidon *pd; | ||
297 | |||
298 | list_for_each_entry(pd, &pd_device_list, device_list) { | ||
299 | if (pd->portnum == udev->portnum && in_hibernation(pd)) | ||
300 | return fixup(pd); | ||
301 | } | ||
302 | return NULL; | ||
303 | } | ||
304 | |||
305 | /* Is the card working now ? */ | ||
306 | static inline int is_working(struct poseidon *pd) | ||
307 | { | ||
308 | return get_pm_count(pd) > 0; | ||
309 | } | ||
310 | |||
311 | static int poseidon_suspend(struct usb_interface *intf, pm_message_t msg) | ||
312 | { | ||
313 | struct poseidon *pd = get_pd(intf); | ||
314 | |||
315 | if (!pd) | ||
316 | return 0; | ||
317 | if (!is_working(pd)) { | ||
318 | if (get_pm_count(pd) <= 0 && !in_hibernation(pd)) { | ||
319 | pd->msg.event = PM_EVENT_AUTO_SUSPEND; | ||
320 | pd->pm_resume = NULL; /* a good guard */ | ||
321 | printk(KERN_DEBUG "\n\t+ TLG2300 auto suspend +\n\n"); | ||
322 | } | ||
323 | return 0; | ||
324 | } | ||
325 | pd->msg = msg; /* save it here */ | ||
326 | logpm(pd); | ||
327 | return pd->pm_suspend ? pd->pm_suspend(pd) : 0; | ||
328 | } | ||
329 | |||
330 | static int poseidon_resume(struct usb_interface *intf) | ||
331 | { | ||
332 | struct poseidon *pd = get_pd(intf); | ||
333 | |||
334 | if (!pd) | ||
335 | return 0; | ||
336 | printk(KERN_DEBUG "\n\t ++ TLG2300 resume ++\n\n"); | ||
337 | |||
338 | if (!is_working(pd)) { | ||
339 | if (PM_EVENT_AUTO_SUSPEND == pd->msg.event) | ||
340 | pd->msg = PMSG_ON; | ||
341 | return 0; | ||
342 | } | ||
343 | if (in_hibernation(pd)) { | ||
344 | logpm(pd); | ||
345 | return 0; | ||
346 | } | ||
347 | logpm(pd); | ||
348 | return pd->pm_resume ? pd->pm_resume(pd) : 0; | ||
349 | } | ||
350 | |||
351 | static void hibernation_resume(struct work_struct *w) | ||
352 | { | ||
353 | struct poseidon *pd = container_of(w, struct poseidon, pm_work); | ||
354 | int count; | ||
355 | |||
356 | pd->msg.event = 0; /* clear it here */ | ||
357 | pd->state &= ~POSEIDON_STATE_DISCONNECT; | ||
358 | |||
359 | /* set the new interface's reference */ | ||
360 | count = get_autopm_ref(pd); | ||
361 | while (count--) | ||
362 | usb_autopm_get_interface(pd->interface); | ||
363 | |||
364 | /* resume the context */ | ||
365 | logpm(pd); | ||
366 | if (pd->pm_resume) | ||
367 | pd->pm_resume(pd); | ||
368 | } | ||
369 | #else /* CONFIG_PM is not enabled: */ | ||
370 | static inline struct poseidon *find_old_poseidon(struct usb_device *udev) | ||
371 | { | ||
372 | return NULL; | ||
373 | } | ||
374 | |||
375 | static inline void set_map_flags(struct poseidon *pd, struct usb_device *udev) | ||
376 | { | ||
377 | } | ||
378 | #endif | ||
379 | |||
380 | static bool check_firmware(struct usb_device *udev, int *down_firmware) | ||
381 | { | ||
382 | void *buf; | ||
383 | int ret; | ||
384 | struct cmd_firmware_vers_s *cmd_firm; | ||
385 | |||
386 | buf = kzalloc(sizeof(*cmd_firm) + sizeof(u32), GFP_KERNEL); | ||
387 | if (!buf) | ||
388 | return -ENOMEM; | ||
389 | ret = usb_control_msg(udev, | ||
390 | usb_rcvctrlpipe(udev, 0), | ||
391 | REQ_GET_CMD | GET_FW_ID, | ||
392 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
393 | 0, | ||
394 | 0, | ||
395 | buf, | ||
396 | sizeof(*cmd_firm) + sizeof(u32), | ||
397 | USB_CTRL_GET_TIMEOUT); | ||
398 | kfree(buf); | ||
399 | |||
400 | if (ret < 0) { | ||
401 | *down_firmware = 1; | ||
402 | return firmware_download(udev); | ||
403 | } | ||
404 | return ret; | ||
405 | } | ||
406 | |||
407 | static int poseidon_probe(struct usb_interface *interface, | ||
408 | const struct usb_device_id *id) | ||
409 | { | ||
410 | struct usb_device *udev = interface_to_usbdev(interface); | ||
411 | struct poseidon *pd = NULL; | ||
412 | int ret = 0; | ||
413 | int new_one = 0; | ||
414 | |||
415 | /* download firmware */ | ||
416 | check_firmware(udev, &ret); | ||
417 | if (ret) | ||
418 | return 0; | ||
419 | |||
420 | /* Do I recovery from the hibernate ? */ | ||
421 | pd = find_old_poseidon(udev); | ||
422 | if (!pd) { | ||
423 | pd = kzalloc(sizeof(*pd), GFP_KERNEL); | ||
424 | if (!pd) | ||
425 | return -ENOMEM; | ||
426 | kref_init(&pd->kref); | ||
427 | set_map_flags(pd, udev); | ||
428 | new_one = 1; | ||
429 | } | ||
430 | |||
431 | pd->udev = usb_get_dev(udev); | ||
432 | pd->interface = usb_get_intf(interface); | ||
433 | usb_set_intfdata(interface, pd); | ||
434 | |||
435 | if (new_one) { | ||
436 | struct device *dev = &interface->dev; | ||
437 | |||
438 | logpm(pd); | ||
439 | mutex_init(&pd->lock); | ||
440 | |||
441 | /* register v4l2 device */ | ||
442 | snprintf(pd->v4l2_dev.name, sizeof(pd->v4l2_dev.name), "%s %s", | ||
443 | dev->driver->name, dev_name(dev)); | ||
444 | ret = v4l2_device_register(NULL, &pd->v4l2_dev); | ||
445 | |||
446 | /* register devices in directory /dev */ | ||
447 | ret = pd_video_init(pd); | ||
448 | poseidon_audio_init(pd); | ||
449 | poseidon_fm_init(pd); | ||
450 | pd_dvb_usb_device_init(pd); | ||
451 | |||
452 | INIT_LIST_HEAD(&pd->device_list); | ||
453 | list_add_tail(&pd->device_list, &pd_device_list); | ||
454 | } | ||
455 | |||
456 | device_init_wakeup(&udev->dev, 1); | ||
457 | #ifdef CONFIG_PM | ||
458 | pd->udev->autosuspend_disabled = 0; | ||
459 | pd->udev->autosuspend_delay = HZ * PM_SUSPEND_DELAY; | ||
460 | |||
461 | if (in_hibernation(pd)) { | ||
462 | INIT_WORK(&pd->pm_work, hibernation_resume); | ||
463 | schedule_work(&pd->pm_work); | ||
464 | } | ||
465 | #endif | ||
466 | return 0; | ||
467 | } | ||
468 | |||
469 | static void poseidon_disconnect(struct usb_interface *interface) | ||
470 | { | ||
471 | struct poseidon *pd = get_pd(interface); | ||
472 | |||
473 | if (!pd) | ||
474 | return; | ||
475 | logpm(pd); | ||
476 | if (in_hibernation(pd)) | ||
477 | return; | ||
478 | |||
479 | mutex_lock(&pd->lock); | ||
480 | pd->state |= POSEIDON_STATE_DISCONNECT; | ||
481 | mutex_unlock(&pd->lock); | ||
482 | |||
483 | /* stop urb transferring */ | ||
484 | stop_all_video_stream(pd); | ||
485 | dvb_stop_streaming(&pd->dvb_data); | ||
486 | |||
487 | /*unregister v4l2 device */ | ||
488 | v4l2_device_unregister(&pd->v4l2_dev); | ||
489 | |||
490 | lock_kernel(); | ||
491 | { | ||
492 | pd_dvb_usb_device_exit(pd); | ||
493 | poseidon_fm_exit(pd); | ||
494 | |||
495 | poseidon_audio_free(pd); | ||
496 | pd_video_exit(pd); | ||
497 | } | ||
498 | unlock_kernel(); | ||
499 | |||
500 | usb_set_intfdata(interface, NULL); | ||
501 | kref_put(&pd->kref, poseidon_delete); | ||
502 | } | ||
503 | |||
504 | struct usb_driver poseidon_driver = { | ||
505 | .name = "poseidon", | ||
506 | .probe = poseidon_probe, | ||
507 | .disconnect = poseidon_disconnect, | ||
508 | .id_table = id_table, | ||
509 | #ifdef CONFIG_PM | ||
510 | .suspend = poseidon_suspend, | ||
511 | .resume = poseidon_resume, | ||
512 | #endif | ||
513 | .supports_autosuspend = 1, | ||
514 | }; | ||
515 | |||
516 | static int __init poseidon_init(void) | ||
517 | { | ||
518 | int ret; | ||
519 | |||
520 | ret = usb_register(&poseidon_driver); | ||
521 | if (ret) | ||
522 | return ret; | ||
523 | register_pm_notifier(&pm_notifer); | ||
524 | return ret; | ||
525 | } | ||
526 | |||
527 | static void __exit poseidon_exit(void) | ||
528 | { | ||
529 | log(); | ||
530 | unregister_pm_notifier(&pm_notifer); | ||
531 | usb_deregister(&poseidon_driver); | ||
532 | } | ||
533 | |||
534 | module_init(poseidon_init); | ||
535 | module_exit(poseidon_exit); | ||
536 | |||
537 | MODULE_AUTHOR("Telegent Systems"); | ||
538 | MODULE_DESCRIPTION("For tlg2300-based USB device "); | ||
539 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/video/tlg2300/pd-radio.c b/drivers/media/video/tlg2300/pd-radio.c new file mode 100644 index 000000000000..755766b15157 --- /dev/null +++ b/drivers/media/video/tlg2300/pd-radio.c | |||
@@ -0,0 +1,420 @@ | |||
1 | #include <linux/init.h> | ||
2 | #include <linux/list.h> | ||
3 | #include <linux/module.h> | ||
4 | #include <linux/kernel.h> | ||
5 | #include <linux/bitmap.h> | ||
6 | #include <linux/usb.h> | ||
7 | #include <linux/i2c.h> | ||
8 | #include <media/v4l2-dev.h> | ||
9 | #include <linux/version.h> | ||
10 | #include <linux/mm.h> | ||
11 | #include <linux/mutex.h> | ||
12 | #include <media/v4l2-ioctl.h> | ||
13 | #include <linux/sched.h> | ||
14 | |||
15 | #include "pd-common.h" | ||
16 | #include "vendorcmds.h" | ||
17 | |||
18 | static int set_frequency(struct poseidon *p, __u32 frequency); | ||
19 | static int poseidon_fm_close(struct file *filp); | ||
20 | static int poseidon_fm_open(struct file *filp); | ||
21 | |||
22 | #define TUNER_FREQ_MIN_FM 76000000 | ||
23 | #define TUNER_FREQ_MAX_FM 108000000 | ||
24 | |||
25 | #define MAX_PREEMPHASIS (V4L2_PREEMPHASIS_75_uS + 1) | ||
26 | static int preemphasis[MAX_PREEMPHASIS] = { | ||
27 | TLG_TUNE_ASTD_NONE, /* V4L2_PREEMPHASIS_DISABLED */ | ||
28 | TLG_TUNE_ASTD_FM_EUR, /* V4L2_PREEMPHASIS_50_uS */ | ||
29 | TLG_TUNE_ASTD_FM_US, /* V4L2_PREEMPHASIS_75_uS */ | ||
30 | }; | ||
31 | |||
32 | static int poseidon_check_mode_radio(struct poseidon *p) | ||
33 | { | ||
34 | int ret; | ||
35 | u32 status; | ||
36 | |||
37 | set_current_state(TASK_INTERRUPTIBLE); | ||
38 | schedule_timeout(HZ/2); | ||
39 | ret = usb_set_interface(p->udev, 0, BULK_ALTERNATE_IFACE); | ||
40 | if (ret < 0) | ||
41 | goto out; | ||
42 | |||
43 | ret = set_tuner_mode(p, TLG_MODE_FM_RADIO); | ||
44 | if (ret != 0) | ||
45 | goto out; | ||
46 | |||
47 | ret = send_set_req(p, SGNL_SRC_SEL, TLG_SIG_SRC_ANTENNA, &status); | ||
48 | ret = send_set_req(p, TUNER_AUD_ANA_STD, | ||
49 | p->radio_data.pre_emphasis, &status); | ||
50 | ret |= send_set_req(p, TUNER_AUD_MODE, | ||
51 | TLG_TUNE_TVAUDIO_MODE_STEREO, &status); | ||
52 | ret |= send_set_req(p, AUDIO_SAMPLE_RATE_SEL, | ||
53 | ATV_AUDIO_RATE_48K, &status); | ||
54 | ret |= send_set_req(p, TUNE_FREQ_SELECT, TUNER_FREQ_MIN_FM, &status); | ||
55 | out: | ||
56 | return ret; | ||
57 | } | ||
58 | |||
59 | #ifdef CONFIG_PM | ||
60 | static int pm_fm_suspend(struct poseidon *p) | ||
61 | { | ||
62 | logpm(p); | ||
63 | pm_alsa_suspend(p); | ||
64 | usb_set_interface(p->udev, 0, 0); | ||
65 | msleep(300); | ||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | static int pm_fm_resume(struct poseidon *p) | ||
70 | { | ||
71 | logpm(p); | ||
72 | poseidon_check_mode_radio(p); | ||
73 | set_frequency(p, p->radio_data.fm_freq); | ||
74 | pm_alsa_resume(p); | ||
75 | return 0; | ||
76 | } | ||
77 | #endif | ||
78 | |||
79 | static int poseidon_fm_open(struct file *filp) | ||
80 | { | ||
81 | struct video_device *vfd = video_devdata(filp); | ||
82 | struct poseidon *p = video_get_drvdata(vfd); | ||
83 | int ret = 0; | ||
84 | |||
85 | if (!p) | ||
86 | return -1; | ||
87 | |||
88 | mutex_lock(&p->lock); | ||
89 | if (p->state & POSEIDON_STATE_DISCONNECT) { | ||
90 | ret = -ENODEV; | ||
91 | goto out; | ||
92 | } | ||
93 | |||
94 | if (p->state && !(p->state & POSEIDON_STATE_FM)) { | ||
95 | ret = -EBUSY; | ||
96 | goto out; | ||
97 | } | ||
98 | |||
99 | usb_autopm_get_interface(p->interface); | ||
100 | if (0 == p->state) { | ||
101 | /* default pre-emphasis */ | ||
102 | if (p->radio_data.pre_emphasis == 0) | ||
103 | p->radio_data.pre_emphasis = TLG_TUNE_ASTD_FM_EUR; | ||
104 | set_debug_mode(vfd, debug_mode); | ||
105 | |||
106 | ret = poseidon_check_mode_radio(p); | ||
107 | if (ret < 0) { | ||
108 | usb_autopm_put_interface(p->interface); | ||
109 | goto out; | ||
110 | } | ||
111 | p->state |= POSEIDON_STATE_FM; | ||
112 | } | ||
113 | p->radio_data.users++; | ||
114 | kref_get(&p->kref); | ||
115 | filp->private_data = p; | ||
116 | out: | ||
117 | mutex_unlock(&p->lock); | ||
118 | return ret; | ||
119 | } | ||
120 | |||
121 | static int poseidon_fm_close(struct file *filp) | ||
122 | { | ||
123 | struct poseidon *p = filp->private_data; | ||
124 | struct radio_data *fm = &p->radio_data; | ||
125 | uint32_t status; | ||
126 | |||
127 | mutex_lock(&p->lock); | ||
128 | fm->users--; | ||
129 | if (0 == fm->users) | ||
130 | p->state &= ~POSEIDON_STATE_FM; | ||
131 | |||
132 | if (fm->is_radio_streaming && filp == p->file_for_stream) { | ||
133 | fm->is_radio_streaming = 0; | ||
134 | send_set_req(p, PLAY_SERVICE, TLG_TUNE_PLAY_SVC_STOP, &status); | ||
135 | } | ||
136 | usb_autopm_put_interface(p->interface); | ||
137 | mutex_unlock(&p->lock); | ||
138 | |||
139 | kref_put(&p->kref, poseidon_delete); | ||
140 | filp->private_data = NULL; | ||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | static int vidioc_querycap(struct file *file, void *priv, | ||
145 | struct v4l2_capability *v) | ||
146 | { | ||
147 | struct poseidon *p = file->private_data; | ||
148 | |||
149 | strlcpy(v->driver, "tele-radio", sizeof(v->driver)); | ||
150 | strlcpy(v->card, "Telegent Poseidon", sizeof(v->card)); | ||
151 | usb_make_path(p->udev, v->bus_info, sizeof(v->bus_info)); | ||
152 | v->version = KERNEL_VERSION(0, 0, 1); | ||
153 | v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; | ||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | static const struct v4l2_file_operations poseidon_fm_fops = { | ||
158 | .owner = THIS_MODULE, | ||
159 | .open = poseidon_fm_open, | ||
160 | .release = poseidon_fm_close, | ||
161 | .ioctl = video_ioctl2, | ||
162 | }; | ||
163 | |||
164 | int tlg_fm_vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *vt) | ||
165 | { | ||
166 | struct tuner_fm_sig_stat_s fm_stat = {}; | ||
167 | int ret, status, count = 5; | ||
168 | struct poseidon *p = file->private_data; | ||
169 | |||
170 | if (vt->index != 0) | ||
171 | return -EINVAL; | ||
172 | |||
173 | vt->type = V4L2_TUNER_RADIO; | ||
174 | vt->capability = V4L2_TUNER_CAP_STEREO; | ||
175 | vt->rangelow = TUNER_FREQ_MIN_FM / 62500; | ||
176 | vt->rangehigh = TUNER_FREQ_MAX_FM / 62500; | ||
177 | vt->rxsubchans = V4L2_TUNER_SUB_STEREO; | ||
178 | vt->audmode = V4L2_TUNER_MODE_STEREO; | ||
179 | vt->signal = 0; | ||
180 | vt->afc = 0; | ||
181 | |||
182 | mutex_lock(&p->lock); | ||
183 | ret = send_get_req(p, TUNER_STATUS, TLG_MODE_FM_RADIO, | ||
184 | &fm_stat, &status, sizeof(fm_stat)); | ||
185 | |||
186 | while (fm_stat.sig_lock_busy && count-- && !ret) { | ||
187 | set_current_state(TASK_INTERRUPTIBLE); | ||
188 | schedule_timeout(HZ); | ||
189 | |||
190 | ret = send_get_req(p, TUNER_STATUS, TLG_MODE_FM_RADIO, | ||
191 | &fm_stat, &status, sizeof(fm_stat)); | ||
192 | } | ||
193 | mutex_unlock(&p->lock); | ||
194 | |||
195 | if (ret || status) { | ||
196 | vt->signal = 0; | ||
197 | } else if ((fm_stat.sig_present || fm_stat.sig_locked) | ||
198 | && fm_stat.sig_strength == 0) { | ||
199 | vt->signal = 0xffff; | ||
200 | } else | ||
201 | vt->signal = (fm_stat.sig_strength * 255 / 10) << 8; | ||
202 | |||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | int fm_get_freq(struct file *file, void *priv, struct v4l2_frequency *argp) | ||
207 | { | ||
208 | struct poseidon *p = file->private_data; | ||
209 | |||
210 | argp->frequency = p->radio_data.fm_freq; | ||
211 | return 0; | ||
212 | } | ||
213 | |||
214 | static int set_frequency(struct poseidon *p, __u32 frequency) | ||
215 | { | ||
216 | __u32 freq ; | ||
217 | int ret, status; | ||
218 | |||
219 | mutex_lock(&p->lock); | ||
220 | |||
221 | ret = send_set_req(p, TUNER_AUD_ANA_STD, | ||
222 | p->radio_data.pre_emphasis, &status); | ||
223 | |||
224 | freq = (frequency * 125) * 500 / 1000;/* kHZ */ | ||
225 | if (freq < TUNER_FREQ_MIN_FM/1000 || freq > TUNER_FREQ_MAX_FM/1000) { | ||
226 | ret = -EINVAL; | ||
227 | goto error; | ||
228 | } | ||
229 | |||
230 | ret = send_set_req(p, TUNE_FREQ_SELECT, freq, &status); | ||
231 | if (ret < 0) | ||
232 | goto error ; | ||
233 | ret = send_set_req(p, TAKE_REQUEST, 0, &status); | ||
234 | |||
235 | set_current_state(TASK_INTERRUPTIBLE); | ||
236 | schedule_timeout(HZ/4); | ||
237 | if (!p->radio_data.is_radio_streaming) { | ||
238 | ret = send_set_req(p, TAKE_REQUEST, 0, &status); | ||
239 | ret = send_set_req(p, PLAY_SERVICE, | ||
240 | TLG_TUNE_PLAY_SVC_START, &status); | ||
241 | p->radio_data.is_radio_streaming = 1; | ||
242 | } | ||
243 | p->radio_data.fm_freq = frequency; | ||
244 | error: | ||
245 | mutex_unlock(&p->lock); | ||
246 | return ret; | ||
247 | } | ||
248 | |||
249 | int fm_set_freq(struct file *file, void *priv, struct v4l2_frequency *argp) | ||
250 | { | ||
251 | struct poseidon *p = file->private_data; | ||
252 | |||
253 | p->file_for_stream = file; | ||
254 | #ifdef CONFIG_PM | ||
255 | p->pm_suspend = pm_fm_suspend; | ||
256 | p->pm_resume = pm_fm_resume; | ||
257 | #endif | ||
258 | return set_frequency(p, argp->frequency); | ||
259 | } | ||
260 | |||
261 | int tlg_fm_vidioc_g_ctrl(struct file *file, void *priv, | ||
262 | struct v4l2_control *arg) | ||
263 | { | ||
264 | return 0; | ||
265 | } | ||
266 | |||
267 | int tlg_fm_vidioc_g_exts_ctrl(struct file *file, void *fh, | ||
268 | struct v4l2_ext_controls *ctrls) | ||
269 | { | ||
270 | struct poseidon *p = file->private_data; | ||
271 | int i; | ||
272 | |||
273 | if (ctrls->ctrl_class != V4L2_CTRL_CLASS_FM_TX) | ||
274 | return -EINVAL; | ||
275 | |||
276 | for (i = 0; i < ctrls->count; i++) { | ||
277 | struct v4l2_ext_control *ctrl = ctrls->controls + i; | ||
278 | |||
279 | if (ctrl->id != V4L2_CID_TUNE_PREEMPHASIS) | ||
280 | continue; | ||
281 | |||
282 | if (i < MAX_PREEMPHASIS) | ||
283 | ctrl->value = p->radio_data.pre_emphasis; | ||
284 | } | ||
285 | return 0; | ||
286 | } | ||
287 | |||
288 | int tlg_fm_vidioc_s_exts_ctrl(struct file *file, void *fh, | ||
289 | struct v4l2_ext_controls *ctrls) | ||
290 | { | ||
291 | int i; | ||
292 | |||
293 | if (ctrls->ctrl_class != V4L2_CTRL_CLASS_FM_TX) | ||
294 | return -EINVAL; | ||
295 | |||
296 | for (i = 0; i < ctrls->count; i++) { | ||
297 | struct v4l2_ext_control *ctrl = ctrls->controls + i; | ||
298 | |||
299 | if (ctrl->id != V4L2_CID_TUNE_PREEMPHASIS) | ||
300 | continue; | ||
301 | |||
302 | if (ctrl->value >= 0 && ctrl->value < MAX_PREEMPHASIS) { | ||
303 | struct poseidon *p = file->private_data; | ||
304 | int pre_emphasis = preemphasis[ctrl->value]; | ||
305 | u32 status; | ||
306 | |||
307 | send_set_req(p, TUNER_AUD_ANA_STD, | ||
308 | pre_emphasis, &status); | ||
309 | p->radio_data.pre_emphasis = pre_emphasis; | ||
310 | } | ||
311 | } | ||
312 | return 0; | ||
313 | } | ||
314 | |||
315 | int tlg_fm_vidioc_s_ctrl(struct file *file, void *priv, | ||
316 | struct v4l2_control *ctrl) | ||
317 | { | ||
318 | return 0; | ||
319 | } | ||
320 | |||
321 | int tlg_fm_vidioc_queryctrl(struct file *file, void *priv, | ||
322 | struct v4l2_queryctrl *ctrl) | ||
323 | { | ||
324 | if (!(ctrl->id & V4L2_CTRL_FLAG_NEXT_CTRL)) | ||
325 | return -EINVAL; | ||
326 | |||
327 | ctrl->id &= ~V4L2_CTRL_FLAG_NEXT_CTRL; | ||
328 | if (ctrl->id != V4L2_CID_TUNE_PREEMPHASIS) { | ||
329 | /* return the next supported control */ | ||
330 | ctrl->id = V4L2_CID_TUNE_PREEMPHASIS; | ||
331 | v4l2_ctrl_query_fill(ctrl, V4L2_PREEMPHASIS_DISABLED, | ||
332 | V4L2_PREEMPHASIS_75_uS, 1, | ||
333 | V4L2_PREEMPHASIS_50_uS); | ||
334 | ctrl->flags = V4L2_CTRL_FLAG_UPDATE; | ||
335 | return 0; | ||
336 | } | ||
337 | return -EINVAL; | ||
338 | } | ||
339 | |||
340 | int tlg_fm_vidioc_querymenu(struct file *file, void *fh, | ||
341 | struct v4l2_querymenu *qmenu) | ||
342 | { | ||
343 | return v4l2_ctrl_query_menu(qmenu, NULL, NULL); | ||
344 | } | ||
345 | |||
346 | static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *vt) | ||
347 | { | ||
348 | return vt->index > 0 ? -EINVAL : 0; | ||
349 | } | ||
350 | static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *va) | ||
351 | { | ||
352 | return (va->index != 0) ? -EINVAL : 0; | ||
353 | } | ||
354 | |||
355 | static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) | ||
356 | { | ||
357 | a->index = 0; | ||
358 | a->mode = 0; | ||
359 | a->capability = V4L2_AUDCAP_STEREO; | ||
360 | strcpy(a->name, "Radio"); | ||
361 | return 0; | ||
362 | } | ||
363 | |||
364 | static int vidioc_s_input(struct file *filp, void *priv, u32 i) | ||
365 | { | ||
366 | return (i != 0) ? -EINVAL : 0; | ||
367 | } | ||
368 | |||
369 | static int vidioc_g_input(struct file *filp, void *priv, u32 *i) | ||
370 | { | ||
371 | return (*i != 0) ? -EINVAL : 0; | ||
372 | } | ||
373 | |||
374 | static const struct v4l2_ioctl_ops poseidon_fm_ioctl_ops = { | ||
375 | .vidioc_querycap = vidioc_querycap, | ||
376 | .vidioc_g_audio = vidioc_g_audio, | ||
377 | .vidioc_s_audio = vidioc_s_audio, | ||
378 | .vidioc_g_input = vidioc_g_input, | ||
379 | .vidioc_s_input = vidioc_s_input, | ||
380 | .vidioc_queryctrl = tlg_fm_vidioc_queryctrl, | ||
381 | .vidioc_querymenu = tlg_fm_vidioc_querymenu, | ||
382 | .vidioc_g_ctrl = tlg_fm_vidioc_g_ctrl, | ||
383 | .vidioc_s_ctrl = tlg_fm_vidioc_s_ctrl, | ||
384 | .vidioc_s_ext_ctrls = tlg_fm_vidioc_s_exts_ctrl, | ||
385 | .vidioc_g_ext_ctrls = tlg_fm_vidioc_g_exts_ctrl, | ||
386 | .vidioc_s_tuner = vidioc_s_tuner, | ||
387 | .vidioc_g_tuner = tlg_fm_vidioc_g_tuner, | ||
388 | .vidioc_g_frequency = fm_get_freq, | ||
389 | .vidioc_s_frequency = fm_set_freq, | ||
390 | }; | ||
391 | |||
392 | static struct video_device poseidon_fm_template = { | ||
393 | .name = "Telegent-Radio", | ||
394 | .fops = &poseidon_fm_fops, | ||
395 | .minor = -1, | ||
396 | .release = video_device_release, | ||
397 | .ioctl_ops = &poseidon_fm_ioctl_ops, | ||
398 | }; | ||
399 | |||
400 | int poseidon_fm_init(struct poseidon *p) | ||
401 | { | ||
402 | struct video_device *fm_dev; | ||
403 | |||
404 | fm_dev = vdev_init(p, &poseidon_fm_template); | ||
405 | if (fm_dev == NULL) | ||
406 | return -1; | ||
407 | |||
408 | if (video_register_device(fm_dev, VFL_TYPE_RADIO, -1) < 0) { | ||
409 | video_device_release(fm_dev); | ||
410 | return -1; | ||
411 | } | ||
412 | p->radio_data.fm_dev = fm_dev; | ||
413 | return 0; | ||
414 | } | ||
415 | |||
416 | int poseidon_fm_exit(struct poseidon *p) | ||
417 | { | ||
418 | destroy_video_device(&p->radio_data.fm_dev); | ||
419 | return 0; | ||
420 | } | ||
diff --git a/drivers/media/video/tlg2300/pd-video.c b/drivers/media/video/tlg2300/pd-video.c new file mode 100644 index 000000000000..becfba6a3041 --- /dev/null +++ b/drivers/media/video/tlg2300/pd-video.c | |||
@@ -0,0 +1,1667 @@ | |||
1 | #include <linux/fs.h> | ||
2 | #include <linux/vmalloc.h> | ||
3 | #include <linux/videodev2.h> | ||
4 | #include <linux/usb.h> | ||
5 | #include <linux/mm.h> | ||
6 | #include <linux/sched.h> | ||
7 | |||
8 | #include <media/v4l2-ioctl.h> | ||
9 | #include <media/v4l2-dev.h> | ||
10 | |||
11 | #include "pd-common.h" | ||
12 | #include "vendorcmds.h" | ||
13 | |||
14 | static int pm_video_suspend(struct poseidon *pd); | ||
15 | static int pm_video_resume(struct poseidon *pd); | ||
16 | static void iso_bubble_handler(struct work_struct *w); | ||
17 | |||
18 | int usb_transfer_mode; | ||
19 | module_param(usb_transfer_mode, int, 0644); | ||
20 | MODULE_PARM_DESC(usb_transfer_mode, "0 = Bulk, 1 = Isochronous"); | ||
21 | |||
22 | static const struct poseidon_format poseidon_formats[] = { | ||
23 | { "YUV 422", V4L2_PIX_FMT_YUYV, 16, 0}, | ||
24 | { "RGB565", V4L2_PIX_FMT_RGB565, 16, 0}, | ||
25 | }; | ||
26 | |||
27 | static const struct poseidon_tvnorm poseidon_tvnorms[] = { | ||
28 | { V4L2_STD_PAL_D, "PAL-D", TLG_TUNE_VSTD_PAL_D }, | ||
29 | { V4L2_STD_PAL_B, "PAL-B", TLG_TUNE_VSTD_PAL_B }, | ||
30 | { V4L2_STD_PAL_G, "PAL-G", TLG_TUNE_VSTD_PAL_G }, | ||
31 | { V4L2_STD_PAL_H, "PAL-H", TLG_TUNE_VSTD_PAL_H }, | ||
32 | { V4L2_STD_PAL_I, "PAL-I", TLG_TUNE_VSTD_PAL_I }, | ||
33 | { V4L2_STD_PAL_M, "PAL-M", TLG_TUNE_VSTD_PAL_M }, | ||
34 | { V4L2_STD_PAL_N, "PAL-N", TLG_TUNE_VSTD_PAL_N_COMBO }, | ||
35 | { V4L2_STD_PAL_Nc, "PAL-Nc", TLG_TUNE_VSTD_PAL_N_COMBO }, | ||
36 | { V4L2_STD_NTSC_M, "NTSC-M", TLG_TUNE_VSTD_NTSC_M }, | ||
37 | { V4L2_STD_NTSC_M_JP, "NTSC-JP", TLG_TUNE_VSTD_NTSC_M_J }, | ||
38 | { V4L2_STD_SECAM_B, "SECAM-B", TLG_TUNE_VSTD_SECAM_B }, | ||
39 | { V4L2_STD_SECAM_D, "SECAM-D", TLG_TUNE_VSTD_SECAM_D }, | ||
40 | { V4L2_STD_SECAM_G, "SECAM-G", TLG_TUNE_VSTD_SECAM_G }, | ||
41 | { V4L2_STD_SECAM_H, "SECAM-H", TLG_TUNE_VSTD_SECAM_H }, | ||
42 | { V4L2_STD_SECAM_K, "SECAM-K", TLG_TUNE_VSTD_SECAM_K }, | ||
43 | { V4L2_STD_SECAM_K1, "SECAM-K1", TLG_TUNE_VSTD_SECAM_K1 }, | ||
44 | { V4L2_STD_SECAM_L, "SECAM-L", TLG_TUNE_VSTD_SECAM_L }, | ||
45 | { V4L2_STD_SECAM_LC, "SECAM-LC", TLG_TUNE_VSTD_SECAM_L1 }, | ||
46 | }; | ||
47 | static const unsigned int POSEIDON_TVNORMS = ARRAY_SIZE(poseidon_tvnorms); | ||
48 | |||
49 | struct pd_audio_mode { | ||
50 | u32 tlg_audio_mode; | ||
51 | u32 v4l2_audio_sub; | ||
52 | u32 v4l2_audio_mode; | ||
53 | }; | ||
54 | |||
55 | static const struct pd_audio_mode pd_audio_modes[] = { | ||
56 | { TLG_TUNE_TVAUDIO_MODE_MONO, V4L2_TUNER_SUB_MONO, | ||
57 | V4L2_TUNER_MODE_MONO }, | ||
58 | { TLG_TUNE_TVAUDIO_MODE_STEREO, V4L2_TUNER_SUB_STEREO, | ||
59 | V4L2_TUNER_MODE_STEREO }, | ||
60 | { TLG_TUNE_TVAUDIO_MODE_LANG_A, V4L2_TUNER_SUB_LANG1, | ||
61 | V4L2_TUNER_MODE_LANG1 }, | ||
62 | { TLG_TUNE_TVAUDIO_MODE_LANG_B, V4L2_TUNER_SUB_LANG2, | ||
63 | V4L2_TUNER_MODE_LANG2 }, | ||
64 | { TLG_TUNE_TVAUDIO_MODE_LANG_C, V4L2_TUNER_SUB_LANG1, | ||
65 | V4L2_TUNER_MODE_LANG1_LANG2 } | ||
66 | }; | ||
67 | static const unsigned int POSEIDON_AUDIOMODS = ARRAY_SIZE(pd_audio_modes); | ||
68 | |||
69 | struct pd_input { | ||
70 | char *name; | ||
71 | uint32_t tlg_src; | ||
72 | }; | ||
73 | |||
74 | static const struct pd_input pd_inputs[] = { | ||
75 | { "TV Antenna", TLG_SIG_SRC_ANTENNA }, | ||
76 | { "TV Cable", TLG_SIG_SRC_CABLE }, | ||
77 | { "TV SVideo", TLG_SIG_SRC_SVIDEO }, | ||
78 | { "TV Composite", TLG_SIG_SRC_COMPOSITE } | ||
79 | }; | ||
80 | static const unsigned int POSEIDON_INPUTS = ARRAY_SIZE(pd_inputs); | ||
81 | |||
82 | struct poseidon_control { | ||
83 | struct v4l2_queryctrl v4l2_ctrl; | ||
84 | enum cmd_custom_param_id vc_id; | ||
85 | }; | ||
86 | |||
87 | static struct poseidon_control controls[] = { | ||
88 | { | ||
89 | { V4L2_CID_BRIGHTNESS, V4L2_CTRL_TYPE_INTEGER, | ||
90 | "brightness", 0, 10000, 1, 100, 0, }, | ||
91 | CUST_PARM_ID_BRIGHTNESS_CTRL | ||
92 | }, { | ||
93 | { V4L2_CID_CONTRAST, V4L2_CTRL_TYPE_INTEGER, | ||
94 | "contrast", 0, 10000, 1, 100, 0, }, | ||
95 | CUST_PARM_ID_CONTRAST_CTRL, | ||
96 | }, { | ||
97 | { V4L2_CID_HUE, V4L2_CTRL_TYPE_INTEGER, | ||
98 | "hue", 0, 10000, 1, 100, 0, }, | ||
99 | CUST_PARM_ID_HUE_CTRL, | ||
100 | }, { | ||
101 | { V4L2_CID_SATURATION, V4L2_CTRL_TYPE_INTEGER, | ||
102 | "saturation", 0, 10000, 1, 100, 0, }, | ||
103 | CUST_PARM_ID_SATURATION_CTRL, | ||
104 | }, | ||
105 | }; | ||
106 | |||
107 | struct video_std_to_audio_std { | ||
108 | v4l2_std_id video_std; | ||
109 | int audio_std; | ||
110 | }; | ||
111 | |||
112 | static const struct video_std_to_audio_std video_to_audio_map[] = { | ||
113 | /* country : { 27, 32, 33, 34, 36, 44, 45, 46, 47, 48, 64, | ||
114 | 65, 86, 351, 352, 353, 354, 358, 372, 852, 972 } */ | ||
115 | { (V4L2_STD_PAL_I | V4L2_STD_PAL_B | V4L2_STD_PAL_D | | ||
116 | V4L2_STD_SECAM_L | V4L2_STD_SECAM_D), TLG_TUNE_ASTD_NICAM }, | ||
117 | |||
118 | /* country : { 1, 52, 54, 55, 886 } */ | ||
119 | {V4L2_STD_NTSC_M | V4L2_STD_PAL_N | V4L2_STD_PAL_M, TLG_TUNE_ASTD_BTSC}, | ||
120 | |||
121 | /* country : { 81 } */ | ||
122 | { V4L2_STD_NTSC_M_JP, TLG_TUNE_ASTD_EIAJ }, | ||
123 | |||
124 | /* other country : TLG_TUNE_ASTD_A2 */ | ||
125 | }; | ||
126 | static const unsigned int map_size = ARRAY_SIZE(video_to_audio_map); | ||
127 | |||
128 | static int get_audio_std(v4l2_std_id v4l2_std) | ||
129 | { | ||
130 | int i = 0; | ||
131 | |||
132 | for (; i < map_size; i++) { | ||
133 | if (v4l2_std & video_to_audio_map[i].video_std) | ||
134 | return video_to_audio_map[i].audio_std; | ||
135 | } | ||
136 | return TLG_TUNE_ASTD_A2; | ||
137 | } | ||
138 | |||
139 | static int vidioc_querycap(struct file *file, void *fh, | ||
140 | struct v4l2_capability *cap) | ||
141 | { | ||
142 | struct front_face *front = fh; | ||
143 | struct poseidon *p = front->pd; | ||
144 | |||
145 | logs(front); | ||
146 | |||
147 | strcpy(cap->driver, "tele-video"); | ||
148 | strcpy(cap->card, "Telegent Poseidon"); | ||
149 | usb_make_path(p->udev, cap->bus_info, sizeof(cap->bus_info)); | ||
150 | cap->version = KERNEL_VERSION(0, 0, 1); | ||
151 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | | ||
152 | V4L2_CAP_AUDIO | V4L2_CAP_STREAMING | | ||
153 | V4L2_CAP_READWRITE | V4L2_CAP_VBI_CAPTURE; | ||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | /*====================================================================*/ | ||
158 | static void init_copy(struct video_data *video, bool index) | ||
159 | { | ||
160 | struct front_face *front = video->front; | ||
161 | |||
162 | video->field_count = index; | ||
163 | video->lines_copied = 0; | ||
164 | video->prev_left = 0 ; | ||
165 | video->dst = (char *)videobuf_to_vmalloc(front->curr_frame) | ||
166 | + index * video->lines_size; | ||
167 | video->vbi->copied = 0; /* set it here */ | ||
168 | } | ||
169 | |||
170 | static bool get_frame(struct front_face *front, int *need_init) | ||
171 | { | ||
172 | struct videobuf_buffer *vb = front->curr_frame; | ||
173 | |||
174 | if (vb) | ||
175 | return true; | ||
176 | |||
177 | spin_lock(&front->queue_lock); | ||
178 | if (!list_empty(&front->active)) { | ||
179 | vb = list_entry(front->active.next, | ||
180 | struct videobuf_buffer, queue); | ||
181 | if (need_init) | ||
182 | *need_init = 1; | ||
183 | front->curr_frame = vb; | ||
184 | list_del_init(&vb->queue); | ||
185 | } | ||
186 | spin_unlock(&front->queue_lock); | ||
187 | |||
188 | return !!vb; | ||
189 | } | ||
190 | |||
191 | /* check if the video's buffer is ready */ | ||
192 | static bool get_video_frame(struct front_face *front, struct video_data *video) | ||
193 | { | ||
194 | int need_init = 0; | ||
195 | bool ret = true; | ||
196 | |||
197 | ret = get_frame(front, &need_init); | ||
198 | if (ret && need_init) | ||
199 | init_copy(video, 0); | ||
200 | return ret; | ||
201 | } | ||
202 | |||
203 | static void submit_frame(struct front_face *front) | ||
204 | { | ||
205 | struct videobuf_buffer *vb = front->curr_frame; | ||
206 | |||
207 | if (vb == NULL) | ||
208 | return; | ||
209 | |||
210 | front->curr_frame = NULL; | ||
211 | vb->state = VIDEOBUF_DONE; | ||
212 | vb->field_count++; | ||
213 | do_gettimeofday(&vb->ts); | ||
214 | |||
215 | wake_up(&vb->done); | ||
216 | } | ||
217 | |||
218 | /* | ||
219 | * A frame is composed of two fields. If we receive all the two fields, | ||
220 | * call the submit_frame() to submit the whole frame to applications. | ||
221 | */ | ||
222 | static void end_field(struct video_data *video) | ||
223 | { | ||
224 | /* logs(video->front); */ | ||
225 | if (1 == video->field_count) | ||
226 | submit_frame(video->front); | ||
227 | else | ||
228 | init_copy(video, 1); | ||
229 | } | ||
230 | |||
231 | static void copy_video_data(struct video_data *video, char *src, | ||
232 | unsigned int count) | ||
233 | { | ||
234 | #define copy_data(len) \ | ||
235 | do { \ | ||
236 | if (++video->lines_copied > video->lines_per_field) \ | ||
237 | goto overflow; \ | ||
238 | memcpy(video->dst, src, len);\ | ||
239 | video->dst += len + video->lines_size; \ | ||
240 | src += len; \ | ||
241 | count -= len; \ | ||
242 | } while (0) | ||
243 | |||
244 | while (count && count >= video->lines_size) { | ||
245 | if (video->prev_left) { | ||
246 | copy_data(video->prev_left); | ||
247 | video->prev_left = 0; | ||
248 | continue; | ||
249 | } | ||
250 | copy_data(video->lines_size); | ||
251 | } | ||
252 | if (count && count < video->lines_size) { | ||
253 | memcpy(video->dst, src, count); | ||
254 | |||
255 | video->prev_left = video->lines_size - count; | ||
256 | video->dst += count; | ||
257 | } | ||
258 | return; | ||
259 | |||
260 | overflow: | ||
261 | end_field(video); | ||
262 | } | ||
263 | |||
264 | static void check_trailer(struct video_data *video, char *src, int count) | ||
265 | { | ||
266 | struct vbi_data *vbi = video->vbi; | ||
267 | int offset; /* trailer's offset */ | ||
268 | char *buf; | ||
269 | |||
270 | offset = (video->context.pix.sizeimage / 2 + vbi->vbi_size / 2) | ||
271 | - (vbi->copied + video->lines_size * video->lines_copied); | ||
272 | if (video->prev_left) | ||
273 | offset -= (video->lines_size - video->prev_left); | ||
274 | |||
275 | if (offset > count || offset <= 0) | ||
276 | goto short_package; | ||
277 | |||
278 | buf = src + offset; | ||
279 | |||
280 | /* trailer : (VFHS) + U32 + U32 + field_num */ | ||
281 | if (!strncmp(buf, "VFHS", 4)) { | ||
282 | int field_num = *((u32 *)(buf + 12)); | ||
283 | |||
284 | if ((field_num & 1) ^ video->field_count) { | ||
285 | init_copy(video, video->field_count); | ||
286 | return; | ||
287 | } | ||
288 | copy_video_data(video, src, offset); | ||
289 | } | ||
290 | short_package: | ||
291 | end_field(video); | ||
292 | } | ||
293 | |||
294 | /* ========== Check this more carefully! =========== */ | ||
295 | static inline void copy_vbi_data(struct vbi_data *vbi, | ||
296 | char *src, unsigned int count) | ||
297 | { | ||
298 | struct front_face *front = vbi->front; | ||
299 | |||
300 | if (front && get_frame(front, NULL)) { | ||
301 | char *buf = videobuf_to_vmalloc(front->curr_frame); | ||
302 | |||
303 | if (vbi->video->field_count) | ||
304 | buf += (vbi->vbi_size / 2); | ||
305 | memcpy(buf + vbi->copied, src, count); | ||
306 | } | ||
307 | vbi->copied += count; | ||
308 | } | ||
309 | |||
310 | /* | ||
311 | * Copy the normal data (VBI or VIDEO) without the trailer. | ||
312 | * VBI is not interlaced, while VIDEO is interlaced. | ||
313 | */ | ||
314 | static inline void copy_vbi_video_data(struct video_data *video, | ||
315 | char *src, unsigned int count) | ||
316 | { | ||
317 | struct vbi_data *vbi = video->vbi; | ||
318 | unsigned int vbi_delta = (vbi->vbi_size / 2) - vbi->copied; | ||
319 | |||
320 | if (vbi_delta >= count) { | ||
321 | copy_vbi_data(vbi, src, count); | ||
322 | } else { | ||
323 | if (vbi_delta) { | ||
324 | copy_vbi_data(vbi, src, vbi_delta); | ||
325 | |||
326 | /* we receive the two fields of the VBI*/ | ||
327 | if (vbi->front && video->field_count) | ||
328 | submit_frame(vbi->front); | ||
329 | } | ||
330 | copy_video_data(video, src + vbi_delta, count - vbi_delta); | ||
331 | } | ||
332 | } | ||
333 | |||
334 | static void urb_complete_bulk(struct urb *urb) | ||
335 | { | ||
336 | struct front_face *front = urb->context; | ||
337 | struct video_data *video = &front->pd->video_data; | ||
338 | char *src = (char *)urb->transfer_buffer; | ||
339 | int count = urb->actual_length; | ||
340 | int ret = 0; | ||
341 | |||
342 | if (!video->is_streaming || urb->status) { | ||
343 | if (urb->status == -EPROTO) | ||
344 | goto resend_it; | ||
345 | return; | ||
346 | } | ||
347 | if (!get_video_frame(front, video)) | ||
348 | goto resend_it; | ||
349 | |||
350 | if (count == urb->transfer_buffer_length) | ||
351 | copy_vbi_video_data(video, src, count); | ||
352 | else | ||
353 | check_trailer(video, src, count); | ||
354 | |||
355 | resend_it: | ||
356 | ret = usb_submit_urb(urb, GFP_ATOMIC); | ||
357 | if (ret) | ||
358 | log(" submit failed: error %d", ret); | ||
359 | } | ||
360 | |||
361 | /************************* for ISO *********************/ | ||
362 | #define GET_SUCCESS (0) | ||
363 | #define GET_TRAILER (1) | ||
364 | #define GET_TOO_MUCH_BUBBLE (2) | ||
365 | #define GET_NONE (3) | ||
366 | static int get_chunk(int start, struct urb *urb, | ||
367 | int *head, int *tail, int *bubble_err) | ||
368 | { | ||
369 | struct usb_iso_packet_descriptor *pkt = NULL; | ||
370 | int ret = GET_SUCCESS; | ||
371 | |||
372 | for (*head = *tail = -1; start < urb->number_of_packets; start++) { | ||
373 | pkt = &urb->iso_frame_desc[start]; | ||
374 | |||
375 | /* handle the bubble of the Hub */ | ||
376 | if (-EOVERFLOW == pkt->status) { | ||
377 | if (++*bubble_err > urb->number_of_packets / 3) | ||
378 | return GET_TOO_MUCH_BUBBLE; | ||
379 | continue; | ||
380 | } | ||
381 | |||
382 | /* This is the gap */ | ||
383 | if (pkt->status || pkt->actual_length <= 0 | ||
384 | || pkt->actual_length > ISO_PKT_SIZE) { | ||
385 | if (*head != -1) | ||
386 | break; | ||
387 | continue; | ||
388 | } | ||
389 | |||
390 | /* a good isochronous packet */ | ||
391 | if (pkt->actual_length == ISO_PKT_SIZE) { | ||
392 | if (*head == -1) | ||
393 | *head = start; | ||
394 | *tail = start; | ||
395 | continue; | ||
396 | } | ||
397 | |||
398 | /* trailer is here */ | ||
399 | if (pkt->actual_length < ISO_PKT_SIZE) { | ||
400 | if (*head == -1) { | ||
401 | *head = start; | ||
402 | *tail = start; | ||
403 | return GET_TRAILER; | ||
404 | } | ||
405 | break; | ||
406 | } | ||
407 | } | ||
408 | |||
409 | if (*head == -1 && *tail == -1) | ||
410 | ret = GET_NONE; | ||
411 | return ret; | ||
412 | } | ||
413 | |||
414 | /* | ||
415 | * |__|------|___|-----|_______| | ||
416 | * ^ ^ | ||
417 | * | | | ||
418 | * gap gap | ||
419 | */ | ||
420 | static void urb_complete_iso(struct urb *urb) | ||
421 | { | ||
422 | struct front_face *front = urb->context; | ||
423 | struct video_data *video = &front->pd->video_data; | ||
424 | int bubble_err = 0, head = 0, tail = 0; | ||
425 | char *src = (char *)urb->transfer_buffer; | ||
426 | int ret = 0; | ||
427 | |||
428 | if (!video->is_streaming) | ||
429 | return; | ||
430 | |||
431 | do { | ||
432 | if (!get_video_frame(front, video)) | ||
433 | goto out; | ||
434 | |||
435 | switch (get_chunk(head, urb, &head, &tail, &bubble_err)) { | ||
436 | case GET_SUCCESS: | ||
437 | copy_vbi_video_data(video, src + (head * ISO_PKT_SIZE), | ||
438 | (tail - head + 1) * ISO_PKT_SIZE); | ||
439 | break; | ||
440 | case GET_TRAILER: | ||
441 | check_trailer(video, src + (head * ISO_PKT_SIZE), | ||
442 | ISO_PKT_SIZE); | ||
443 | break; | ||
444 | case GET_NONE: | ||
445 | goto out; | ||
446 | case GET_TOO_MUCH_BUBBLE: | ||
447 | log("\t We got too much bubble"); | ||
448 | schedule_work(&video->bubble_work); | ||
449 | return; | ||
450 | } | ||
451 | } while (head = tail + 1, head < urb->number_of_packets); | ||
452 | |||
453 | out: | ||
454 | ret = usb_submit_urb(urb, GFP_ATOMIC); | ||
455 | if (ret) | ||
456 | log("usb_submit_urb err : %d", ret); | ||
457 | } | ||
458 | /*============================= [ end ] =====================*/ | ||
459 | |||
460 | static int prepare_iso_urb(struct video_data *video) | ||
461 | { | ||
462 | struct usb_device *udev = video->pd->udev; | ||
463 | int i; | ||
464 | |||
465 | if (video->urb_array[0]) | ||
466 | return 0; | ||
467 | |||
468 | for (i = 0; i < SBUF_NUM; i++) { | ||
469 | struct urb *urb; | ||
470 | void *mem; | ||
471 | int j; | ||
472 | |||
473 | urb = usb_alloc_urb(PK_PER_URB, GFP_KERNEL); | ||
474 | if (urb == NULL) | ||
475 | goto out; | ||
476 | |||
477 | video->urb_array[i] = urb; | ||
478 | mem = usb_buffer_alloc(udev, | ||
479 | ISO_PKT_SIZE * PK_PER_URB, | ||
480 | GFP_KERNEL, | ||
481 | &urb->transfer_dma); | ||
482 | |||
483 | urb->complete = urb_complete_iso; /* handler */ | ||
484 | urb->dev = udev; | ||
485 | urb->context = video->front; | ||
486 | urb->pipe = usb_rcvisocpipe(udev, | ||
487 | video->endpoint_addr); | ||
488 | urb->interval = 1; | ||
489 | urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; | ||
490 | urb->number_of_packets = PK_PER_URB; | ||
491 | urb->transfer_buffer = mem; | ||
492 | urb->transfer_buffer_length = PK_PER_URB * ISO_PKT_SIZE; | ||
493 | |||
494 | for (j = 0; j < PK_PER_URB; j++) { | ||
495 | urb->iso_frame_desc[j].offset = ISO_PKT_SIZE * j; | ||
496 | urb->iso_frame_desc[j].length = ISO_PKT_SIZE; | ||
497 | } | ||
498 | } | ||
499 | return 0; | ||
500 | out: | ||
501 | for (; i > 0; i--) | ||
502 | ; | ||
503 | return -ENOMEM; | ||
504 | } | ||
505 | |||
506 | /* return the succeeded number of the allocation */ | ||
507 | int alloc_bulk_urbs_generic(struct urb **urb_array, int num, | ||
508 | struct usb_device *udev, u8 ep_addr, | ||
509 | int buf_size, gfp_t gfp_flags, | ||
510 | usb_complete_t complete_fn, void *context) | ||
511 | { | ||
512 | struct urb *urb; | ||
513 | void *mem; | ||
514 | int i; | ||
515 | |||
516 | for (i = 0; i < num; i++) { | ||
517 | urb = usb_alloc_urb(0, gfp_flags); | ||
518 | if (urb == NULL) | ||
519 | return i; | ||
520 | |||
521 | mem = usb_buffer_alloc(udev, buf_size, gfp_flags, | ||
522 | &urb->transfer_dma); | ||
523 | if (mem == NULL) | ||
524 | return i; | ||
525 | |||
526 | usb_fill_bulk_urb(urb, udev, usb_rcvbulkpipe(udev, ep_addr), | ||
527 | mem, buf_size, complete_fn, context); | ||
528 | urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
529 | urb_array[i] = urb; | ||
530 | } | ||
531 | return i; | ||
532 | } | ||
533 | |||
534 | void free_all_urb_generic(struct urb **urb_array, int num) | ||
535 | { | ||
536 | int i; | ||
537 | struct urb *urb; | ||
538 | |||
539 | for (i = 0; i < num; i++) { | ||
540 | urb = urb_array[i]; | ||
541 | if (urb) { | ||
542 | usb_buffer_free(urb->dev, | ||
543 | urb->transfer_buffer_length, | ||
544 | urb->transfer_buffer, | ||
545 | urb->transfer_dma); | ||
546 | usb_free_urb(urb); | ||
547 | urb_array[i] = NULL; | ||
548 | } | ||
549 | } | ||
550 | } | ||
551 | |||
552 | static int prepare_bulk_urb(struct video_data *video) | ||
553 | { | ||
554 | if (video->urb_array[0]) | ||
555 | return 0; | ||
556 | |||
557 | alloc_bulk_urbs_generic(video->urb_array, SBUF_NUM, | ||
558 | video->pd->udev, video->endpoint_addr, | ||
559 | 0x2000, GFP_KERNEL, | ||
560 | urb_complete_bulk, video->front); | ||
561 | return 0; | ||
562 | } | ||
563 | |||
564 | /* free the URBs */ | ||
565 | static void free_all_urb(struct video_data *video) | ||
566 | { | ||
567 | free_all_urb_generic(video->urb_array, SBUF_NUM); | ||
568 | } | ||
569 | |||
570 | static void pd_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb) | ||
571 | { | ||
572 | videobuf_vmalloc_free(vb); | ||
573 | vb->state = VIDEOBUF_NEEDS_INIT; | ||
574 | } | ||
575 | |||
576 | static void pd_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) | ||
577 | { | ||
578 | struct front_face *front = q->priv_data; | ||
579 | vb->state = VIDEOBUF_QUEUED; | ||
580 | list_add_tail(&vb->queue, &front->active); | ||
581 | } | ||
582 | |||
583 | static int pd_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, | ||
584 | enum v4l2_field field) | ||
585 | { | ||
586 | struct front_face *front = q->priv_data; | ||
587 | int rc; | ||
588 | |||
589 | switch (front->type) { | ||
590 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
591 | if (VIDEOBUF_NEEDS_INIT == vb->state) { | ||
592 | struct v4l2_pix_format *pix; | ||
593 | |||
594 | pix = &front->pd->video_data.context.pix; | ||
595 | vb->size = pix->sizeimage; /* real frame size */ | ||
596 | vb->width = pix->width; | ||
597 | vb->height = pix->height; | ||
598 | rc = videobuf_iolock(q, vb, NULL); | ||
599 | if (rc < 0) | ||
600 | return rc; | ||
601 | } | ||
602 | break; | ||
603 | case V4L2_BUF_TYPE_VBI_CAPTURE: | ||
604 | if (VIDEOBUF_NEEDS_INIT == vb->state) { | ||
605 | vb->size = front->pd->vbi_data.vbi_size; | ||
606 | rc = videobuf_iolock(q, vb, NULL); | ||
607 | if (rc < 0) | ||
608 | return rc; | ||
609 | } | ||
610 | break; | ||
611 | default: | ||
612 | return -EINVAL; | ||
613 | } | ||
614 | vb->field = field; | ||
615 | vb->state = VIDEOBUF_PREPARED; | ||
616 | return 0; | ||
617 | } | ||
618 | |||
619 | int fire_all_urb(struct video_data *video) | ||
620 | { | ||
621 | int i, ret; | ||
622 | |||
623 | video->is_streaming = 1; | ||
624 | |||
625 | for (i = 0; i < SBUF_NUM; i++) { | ||
626 | ret = usb_submit_urb(video->urb_array[i], GFP_KERNEL); | ||
627 | if (ret) | ||
628 | log("(%d) failed: error %d", i, ret); | ||
629 | } | ||
630 | return ret; | ||
631 | } | ||
632 | |||
633 | static int start_video_stream(struct poseidon *pd) | ||
634 | { | ||
635 | struct video_data *video = &pd->video_data; | ||
636 | s32 cmd_status; | ||
637 | |||
638 | send_set_req(pd, TAKE_REQUEST, 0, &cmd_status); | ||
639 | send_set_req(pd, PLAY_SERVICE, TLG_TUNE_PLAY_SVC_START, &cmd_status); | ||
640 | |||
641 | if (pd->cur_transfer_mode) { | ||
642 | prepare_iso_urb(video); | ||
643 | INIT_WORK(&video->bubble_work, iso_bubble_handler); | ||
644 | } else { | ||
645 | /* The bulk mode does not need a bubble handler */ | ||
646 | prepare_bulk_urb(video); | ||
647 | } | ||
648 | fire_all_urb(video); | ||
649 | return 0; | ||
650 | } | ||
651 | |||
652 | static int pd_buf_setup(struct videobuf_queue *q, unsigned int *count, | ||
653 | unsigned int *size) | ||
654 | { | ||
655 | struct front_face *front = q->priv_data; | ||
656 | struct poseidon *pd = front->pd; | ||
657 | |||
658 | switch (front->type) { | ||
659 | default: | ||
660 | return -EINVAL; | ||
661 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: { | ||
662 | struct video_data *video = &pd->video_data; | ||
663 | struct v4l2_pix_format *pix = &video->context.pix; | ||
664 | |||
665 | *size = PAGE_ALIGN(pix->sizeimage);/* page aligned frame size */ | ||
666 | if (*count < 4) | ||
667 | *count = 4; | ||
668 | if (1) { | ||
669 | /* same in different altersetting */ | ||
670 | video->endpoint_addr = 0x82; | ||
671 | video->vbi = &pd->vbi_data; | ||
672 | video->vbi->video = video; | ||
673 | video->pd = pd; | ||
674 | video->lines_per_field = pix->height / 2; | ||
675 | video->lines_size = pix->width * 2; | ||
676 | video->front = front; | ||
677 | } | ||
678 | return start_video_stream(pd); | ||
679 | } | ||
680 | |||
681 | case V4L2_BUF_TYPE_VBI_CAPTURE: { | ||
682 | struct vbi_data *vbi = &pd->vbi_data; | ||
683 | |||
684 | *size = PAGE_ALIGN(vbi->vbi_size); | ||
685 | log("size : %d", *size); | ||
686 | if (*count == 0) | ||
687 | *count = 4; | ||
688 | } | ||
689 | break; | ||
690 | } | ||
691 | return 0; | ||
692 | } | ||
693 | |||
694 | static struct videobuf_queue_ops pd_video_qops = { | ||
695 | .buf_setup = pd_buf_setup, | ||
696 | .buf_prepare = pd_buf_prepare, | ||
697 | .buf_queue = pd_buf_queue, | ||
698 | .buf_release = pd_buf_release, | ||
699 | }; | ||
700 | |||
701 | static int vidioc_enum_fmt(struct file *file, void *fh, | ||
702 | struct v4l2_fmtdesc *f) | ||
703 | { | ||
704 | if (ARRAY_SIZE(poseidon_formats) <= f->index) | ||
705 | return -EINVAL; | ||
706 | f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
707 | f->flags = 0; | ||
708 | f->pixelformat = poseidon_formats[f->index].fourcc; | ||
709 | strcpy(f->description, poseidon_formats[f->index].name); | ||
710 | return 0; | ||
711 | } | ||
712 | |||
713 | static int vidioc_g_fmt(struct file *file, void *fh, struct v4l2_format *f) | ||
714 | { | ||
715 | struct front_face *front = fh; | ||
716 | struct poseidon *pd = front->pd; | ||
717 | |||
718 | logs(front); | ||
719 | f->fmt.pix = pd->video_data.context.pix; | ||
720 | return 0; | ||
721 | } | ||
722 | |||
723 | static int vidioc_try_fmt(struct file *file, void *fh, | ||
724 | struct v4l2_format *f) | ||
725 | { | ||
726 | return 0; | ||
727 | } | ||
728 | |||
729 | /* | ||
730 | * VLC calls VIDIOC_S_STD before VIDIOC_S_FMT, while | ||
731 | * Mplayer calls them in the reverse order. | ||
732 | */ | ||
733 | static int pd_vidioc_s_fmt(struct poseidon *pd, struct v4l2_pix_format *pix) | ||
734 | { | ||
735 | struct video_data *video = &pd->video_data; | ||
736 | struct running_context *context = &video->context; | ||
737 | struct v4l2_pix_format *pix_def = &context->pix; | ||
738 | s32 ret = 0, cmd_status = 0, vid_resol; | ||
739 | |||
740 | /* set the pixel format to firmware */ | ||
741 | if (pix->pixelformat == V4L2_PIX_FMT_RGB565) { | ||
742 | vid_resol = TLG_TUNER_VID_FORMAT_RGB_565; | ||
743 | } else { | ||
744 | pix->pixelformat = V4L2_PIX_FMT_YUYV; | ||
745 | vid_resol = TLG_TUNER_VID_FORMAT_YUV; | ||
746 | } | ||
747 | ret = send_set_req(pd, VIDEO_STREAM_FMT_SEL, | ||
748 | vid_resol, &cmd_status); | ||
749 | |||
750 | /* set the resolution to firmware */ | ||
751 | vid_resol = TLG_TUNE_VID_RES_720; | ||
752 | switch (pix->width) { | ||
753 | case 704: | ||
754 | vid_resol = TLG_TUNE_VID_RES_704; | ||
755 | break; | ||
756 | default: | ||
757 | pix->width = 720; | ||
758 | case 720: | ||
759 | break; | ||
760 | } | ||
761 | ret |= send_set_req(pd, VIDEO_ROSOLU_SEL, | ||
762 | vid_resol, &cmd_status); | ||
763 | if (ret || cmd_status) { | ||
764 | mutex_unlock(&pd->lock); | ||
765 | return -EBUSY; | ||
766 | } | ||
767 | |||
768 | pix_def->pixelformat = pix->pixelformat; /* save it */ | ||
769 | pix->height = (context->tvnormid & V4L2_STD_525_60) ? 480 : 576; | ||
770 | |||
771 | /* Compare with the default setting */ | ||
772 | if ((pix_def->width != pix->width) | ||
773 | || (pix_def->height != pix->height)) { | ||
774 | pix_def->width = pix->width; | ||
775 | pix_def->height = pix->height; | ||
776 | pix_def->bytesperline = pix->width * 2; | ||
777 | pix_def->sizeimage = pix->width * pix->height * 2; | ||
778 | } | ||
779 | *pix = *pix_def; | ||
780 | |||
781 | return 0; | ||
782 | } | ||
783 | |||
784 | static int vidioc_s_fmt(struct file *file, void *fh, struct v4l2_format *f) | ||
785 | { | ||
786 | struct front_face *front = fh; | ||
787 | struct poseidon *pd = front->pd; | ||
788 | |||
789 | logs(front); | ||
790 | /* stop VBI here */ | ||
791 | if (V4L2_BUF_TYPE_VIDEO_CAPTURE != f->type) | ||
792 | return -EINVAL; | ||
793 | |||
794 | mutex_lock(&pd->lock); | ||
795 | if (pd->file_for_stream == NULL) | ||
796 | pd->file_for_stream = file; | ||
797 | else if (file != pd->file_for_stream) { | ||
798 | mutex_unlock(&pd->lock); | ||
799 | return -EINVAL; | ||
800 | } | ||
801 | |||
802 | pd_vidioc_s_fmt(pd, &f->fmt.pix); | ||
803 | mutex_unlock(&pd->lock); | ||
804 | return 0; | ||
805 | } | ||
806 | |||
807 | static int vidioc_g_fmt_vbi(struct file *file, void *fh, | ||
808 | struct v4l2_format *v4l2_f) | ||
809 | { | ||
810 | struct front_face *front = fh; | ||
811 | struct poseidon *pd = front->pd; | ||
812 | struct v4l2_vbi_format *vbi_fmt = &v4l2_f->fmt.vbi; | ||
813 | |||
814 | vbi_fmt->samples_per_line = 720 * 2; | ||
815 | vbi_fmt->sampling_rate = 6750000 * 4; | ||
816 | vbi_fmt->sample_format = V4L2_PIX_FMT_GREY; | ||
817 | vbi_fmt->offset = 64 * 4; /*FIXME: why offset */ | ||
818 | if (pd->video_data.context.tvnormid & V4L2_STD_525_60) { | ||
819 | vbi_fmt->start[0] = 10; | ||
820 | vbi_fmt->start[1] = 264; | ||
821 | vbi_fmt->count[0] = V4L_NTSC_VBI_LINES; | ||
822 | vbi_fmt->count[1] = V4L_NTSC_VBI_LINES; | ||
823 | } else { | ||
824 | vbi_fmt->start[0] = 6; | ||
825 | vbi_fmt->start[1] = 314; | ||
826 | vbi_fmt->count[0] = V4L_PAL_VBI_LINES; | ||
827 | vbi_fmt->count[1] = V4L_PAL_VBI_LINES; | ||
828 | } | ||
829 | vbi_fmt->flags = V4L2_VBI_UNSYNC; | ||
830 | logs(front); | ||
831 | return 0; | ||
832 | } | ||
833 | |||
834 | static int set_std(struct poseidon *pd, v4l2_std_id *norm) | ||
835 | { | ||
836 | struct video_data *video = &pd->video_data; | ||
837 | struct vbi_data *vbi = &pd->vbi_data; | ||
838 | struct running_context *context; | ||
839 | struct v4l2_pix_format *pix; | ||
840 | s32 i, ret = 0, cmd_status, param; | ||
841 | int height; | ||
842 | |||
843 | for (i = 0; i < POSEIDON_TVNORMS; i++) { | ||
844 | if (*norm & poseidon_tvnorms[i].v4l2_id) { | ||
845 | param = poseidon_tvnorms[i].tlg_tvnorm; | ||
846 | log("name : %s", poseidon_tvnorms[i].name); | ||
847 | goto found; | ||
848 | } | ||
849 | } | ||
850 | return -EINVAL; | ||
851 | found: | ||
852 | mutex_lock(&pd->lock); | ||
853 | ret = send_set_req(pd, VIDEO_STD_SEL, param, &cmd_status); | ||
854 | if (ret || cmd_status) | ||
855 | goto out; | ||
856 | |||
857 | /* Set vbi size and check the height of the frame */ | ||
858 | context = &video->context; | ||
859 | context->tvnormid = poseidon_tvnorms[i].v4l2_id; | ||
860 | if (context->tvnormid & V4L2_STD_525_60) { | ||
861 | vbi->vbi_size = V4L_NTSC_VBI_FRAMESIZE; | ||
862 | height = 480; | ||
863 | } else { | ||
864 | vbi->vbi_size = V4L_PAL_VBI_FRAMESIZE; | ||
865 | height = 576; | ||
866 | } | ||
867 | |||
868 | pix = &context->pix; | ||
869 | if (pix->height != height) { | ||
870 | pix->height = height; | ||
871 | pix->sizeimage = pix->width * pix->height * 2; | ||
872 | } | ||
873 | |||
874 | out: | ||
875 | mutex_unlock(&pd->lock); | ||
876 | return ret; | ||
877 | } | ||
878 | |||
879 | int vidioc_s_std(struct file *file, void *fh, v4l2_std_id *norm) | ||
880 | { | ||
881 | struct front_face *front = fh; | ||
882 | logs(front); | ||
883 | return set_std(front->pd, norm); | ||
884 | } | ||
885 | |||
886 | static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *in) | ||
887 | { | ||
888 | struct front_face *front = fh; | ||
889 | |||
890 | if (in->index < 0 || in->index >= POSEIDON_INPUTS) | ||
891 | return -EINVAL; | ||
892 | strcpy(in->name, pd_inputs[in->index].name); | ||
893 | in->type = V4L2_INPUT_TYPE_TUNER; | ||
894 | |||
895 | /* | ||
896 | * the audio input index mixed with this video input, | ||
897 | * Poseidon only have one audio/video, set to "0" | ||
898 | */ | ||
899 | in->audioset = 0; | ||
900 | in->tuner = 0; | ||
901 | in->std = V4L2_STD_ALL; | ||
902 | in->status = 0; | ||
903 | logs(front); | ||
904 | return 0; | ||
905 | } | ||
906 | |||
907 | static int vidioc_g_input(struct file *file, void *fh, unsigned int *i) | ||
908 | { | ||
909 | struct front_face *front = fh; | ||
910 | struct poseidon *pd = front->pd; | ||
911 | struct running_context *context = &pd->video_data.context; | ||
912 | |||
913 | logs(front); | ||
914 | *i = context->sig_index; | ||
915 | return 0; | ||
916 | } | ||
917 | |||
918 | /* We can support several inputs */ | ||
919 | static int vidioc_s_input(struct file *file, void *fh, unsigned int i) | ||
920 | { | ||
921 | struct front_face *front = fh; | ||
922 | struct poseidon *pd = front->pd; | ||
923 | s32 ret, cmd_status; | ||
924 | |||
925 | if (i < 0 || i >= POSEIDON_INPUTS) | ||
926 | return -EINVAL; | ||
927 | ret = send_set_req(pd, SGNL_SRC_SEL, | ||
928 | pd_inputs[i].tlg_src, &cmd_status); | ||
929 | if (ret) | ||
930 | return ret; | ||
931 | |||
932 | pd->video_data.context.sig_index = i; | ||
933 | return 0; | ||
934 | } | ||
935 | |||
936 | static struct poseidon_control *check_control_id(__u32 id) | ||
937 | { | ||
938 | struct poseidon_control *control = &controls[0]; | ||
939 | int array_size = ARRAY_SIZE(controls); | ||
940 | |||
941 | for (; control < &controls[array_size]; control++) | ||
942 | if (control->v4l2_ctrl.id == id) | ||
943 | return control; | ||
944 | return NULL; | ||
945 | } | ||
946 | |||
947 | static int vidioc_queryctrl(struct file *file, void *fh, | ||
948 | struct v4l2_queryctrl *a) | ||
949 | { | ||
950 | struct poseidon_control *control = NULL; | ||
951 | |||
952 | control = check_control_id(a->id); | ||
953 | if (!control) | ||
954 | return -EINVAL; | ||
955 | |||
956 | *a = control->v4l2_ctrl; | ||
957 | return 0; | ||
958 | } | ||
959 | |||
960 | static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *ctrl) | ||
961 | { | ||
962 | struct front_face *front = fh; | ||
963 | struct poseidon *pd = front->pd; | ||
964 | struct poseidon_control *control = NULL; | ||
965 | struct tuner_custom_parameter_s tuner_param; | ||
966 | s32 ret = 0, cmd_status; | ||
967 | |||
968 | control = check_control_id(ctrl->id); | ||
969 | if (!control) | ||
970 | return -EINVAL; | ||
971 | |||
972 | mutex_lock(&pd->lock); | ||
973 | ret = send_get_req(pd, TUNER_CUSTOM_PARAMETER, control->vc_id, | ||
974 | &tuner_param, &cmd_status, sizeof(tuner_param)); | ||
975 | mutex_unlock(&pd->lock); | ||
976 | |||
977 | if (ret || cmd_status) | ||
978 | return -1; | ||
979 | |||
980 | ctrl->value = tuner_param.param_value; | ||
981 | return 0; | ||
982 | } | ||
983 | |||
984 | static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *a) | ||
985 | { | ||
986 | struct tuner_custom_parameter_s param = {0}; | ||
987 | struct poseidon_control *control = NULL; | ||
988 | struct front_face *front = fh; | ||
989 | struct poseidon *pd = front->pd; | ||
990 | s32 ret = 0, cmd_status, params; | ||
991 | |||
992 | control = check_control_id(a->id); | ||
993 | if (!control) | ||
994 | return -EINVAL; | ||
995 | |||
996 | param.param_value = a->value; | ||
997 | param.param_id = control->vc_id; | ||
998 | params = *(s32 *)¶m; /* temp code */ | ||
999 | |||
1000 | mutex_lock(&pd->lock); | ||
1001 | ret = send_set_req(pd, TUNER_CUSTOM_PARAMETER, params, &cmd_status); | ||
1002 | ret = send_set_req(pd, TAKE_REQUEST, 0, &cmd_status); | ||
1003 | mutex_unlock(&pd->lock); | ||
1004 | |||
1005 | set_current_state(TASK_INTERRUPTIBLE); | ||
1006 | schedule_timeout(HZ/4); | ||
1007 | return ret; | ||
1008 | } | ||
1009 | |||
1010 | /* Audio ioctls */ | ||
1011 | static int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *a) | ||
1012 | { | ||
1013 | if (0 != a->index) | ||
1014 | return -EINVAL; | ||
1015 | a->capability = V4L2_AUDCAP_STEREO; | ||
1016 | strcpy(a->name, "USB audio in"); | ||
1017 | /*Poseidon have no AVL function.*/ | ||
1018 | a->mode = 0; | ||
1019 | return 0; | ||
1020 | } | ||
1021 | |||
1022 | int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a) | ||
1023 | { | ||
1024 | a->index = 0; | ||
1025 | a->capability = V4L2_AUDCAP_STEREO; | ||
1026 | strcpy(a->name, "USB audio in"); | ||
1027 | a->mode = 0; | ||
1028 | return 0; | ||
1029 | } | ||
1030 | |||
1031 | int vidioc_s_audio(struct file *file, void *fh, struct v4l2_audio *a) | ||
1032 | { | ||
1033 | return (0 == a->index) ? 0 : -EINVAL; | ||
1034 | } | ||
1035 | |||
1036 | /* Tuner ioctls */ | ||
1037 | static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *tuner) | ||
1038 | { | ||
1039 | struct front_face *front = fh; | ||
1040 | struct poseidon *pd = front->pd; | ||
1041 | struct tuner_atv_sig_stat_s atv_stat; | ||
1042 | s32 count = 5, ret, cmd_status; | ||
1043 | int index; | ||
1044 | |||
1045 | if (0 != tuner->index) | ||
1046 | return -EINVAL; | ||
1047 | |||
1048 | mutex_lock(&pd->lock); | ||
1049 | ret = send_get_req(pd, TUNER_STATUS, TLG_MODE_ANALOG_TV, | ||
1050 | &atv_stat, &cmd_status, sizeof(atv_stat)); | ||
1051 | |||
1052 | while (atv_stat.sig_lock_busy && count-- && !ret) { | ||
1053 | set_current_state(TASK_INTERRUPTIBLE); | ||
1054 | schedule_timeout(HZ); | ||
1055 | |||
1056 | ret = send_get_req(pd, TUNER_STATUS, TLG_MODE_ANALOG_TV, | ||
1057 | &atv_stat, &cmd_status, sizeof(atv_stat)); | ||
1058 | } | ||
1059 | mutex_unlock(&pd->lock); | ||
1060 | |||
1061 | if (debug_mode) | ||
1062 | log("P:%d,S:%d", atv_stat.sig_present, atv_stat.sig_strength); | ||
1063 | |||
1064 | if (ret || cmd_status) | ||
1065 | tuner->signal = 0; | ||
1066 | else if (atv_stat.sig_present && !atv_stat.sig_strength) | ||
1067 | tuner->signal = 0xFFFF; | ||
1068 | else | ||
1069 | tuner->signal = (atv_stat.sig_strength * 255 / 10) << 8; | ||
1070 | |||
1071 | strcpy(tuner->name, "Telegent Systems"); | ||
1072 | tuner->type = V4L2_TUNER_ANALOG_TV; | ||
1073 | tuner->rangelow = TUNER_FREQ_MIN / 62500; | ||
1074 | tuner->rangehigh = TUNER_FREQ_MAX / 62500; | ||
1075 | tuner->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO | | ||
1076 | V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2; | ||
1077 | index = pd->video_data.context.audio_idx; | ||
1078 | tuner->rxsubchans = pd_audio_modes[index].v4l2_audio_sub; | ||
1079 | tuner->audmode = pd_audio_modes[index].v4l2_audio_mode; | ||
1080 | tuner->afc = 0; | ||
1081 | logs(front); | ||
1082 | return 0; | ||
1083 | } | ||
1084 | |||
1085 | static int pd_vidioc_s_tuner(struct poseidon *pd, int index) | ||
1086 | { | ||
1087 | s32 ret = 0, cmd_status, param, audiomode; | ||
1088 | |||
1089 | mutex_lock(&pd->lock); | ||
1090 | param = pd_audio_modes[index].tlg_audio_mode; | ||
1091 | ret = send_set_req(pd, TUNER_AUD_MODE, param, &cmd_status); | ||
1092 | audiomode = get_audio_std(pd->video_data.context.tvnormid); | ||
1093 | ret |= send_set_req(pd, TUNER_AUD_ANA_STD, audiomode, | ||
1094 | &cmd_status); | ||
1095 | if (!ret) | ||
1096 | pd->video_data.context.audio_idx = index; | ||
1097 | mutex_unlock(&pd->lock); | ||
1098 | return ret; | ||
1099 | } | ||
1100 | |||
1101 | static int vidioc_s_tuner(struct file *file, void *fh, struct v4l2_tuner *a) | ||
1102 | { | ||
1103 | struct front_face *front = fh; | ||
1104 | struct poseidon *pd = front->pd; | ||
1105 | int index; | ||
1106 | |||
1107 | if (0 != a->index) | ||
1108 | return -EINVAL; | ||
1109 | logs(front); | ||
1110 | for (index = 0; index < POSEIDON_AUDIOMODS; index++) | ||
1111 | if (a->audmode == pd_audio_modes[index].v4l2_audio_mode) | ||
1112 | return pd_vidioc_s_tuner(pd, index); | ||
1113 | return -EINVAL; | ||
1114 | } | ||
1115 | |||
1116 | static int vidioc_g_frequency(struct file *file, void *fh, | ||
1117 | struct v4l2_frequency *freq) | ||
1118 | { | ||
1119 | struct front_face *front = fh; | ||
1120 | struct poseidon *pd = front->pd; | ||
1121 | struct running_context *context = &pd->video_data.context; | ||
1122 | |||
1123 | if (0 != freq->tuner) | ||
1124 | return -EINVAL; | ||
1125 | freq->frequency = context->freq; | ||
1126 | freq->type = V4L2_TUNER_ANALOG_TV; | ||
1127 | return 0; | ||
1128 | } | ||
1129 | |||
1130 | static int set_frequency(struct poseidon *pd, __u32 frequency) | ||
1131 | { | ||
1132 | s32 ret = 0, param, cmd_status; | ||
1133 | struct running_context *context = &pd->video_data.context; | ||
1134 | |||
1135 | param = frequency * 62500 / 1000; | ||
1136 | if (param < TUNER_FREQ_MIN/1000 || param > TUNER_FREQ_MAX / 1000) | ||
1137 | return -EINVAL; | ||
1138 | |||
1139 | mutex_lock(&pd->lock); | ||
1140 | ret = send_set_req(pd, TUNE_FREQ_SELECT, param, &cmd_status); | ||
1141 | ret = send_set_req(pd, TAKE_REQUEST, 0, &cmd_status); | ||
1142 | |||
1143 | msleep(250); /* wait for a while until the hardware is ready. */ | ||
1144 | context->freq = frequency; | ||
1145 | mutex_unlock(&pd->lock); | ||
1146 | return ret; | ||
1147 | } | ||
1148 | |||
1149 | static int vidioc_s_frequency(struct file *file, void *fh, | ||
1150 | struct v4l2_frequency *freq) | ||
1151 | { | ||
1152 | struct front_face *front = fh; | ||
1153 | struct poseidon *pd = front->pd; | ||
1154 | |||
1155 | logs(front); | ||
1156 | #ifdef CONFIG_PM | ||
1157 | pd->pm_suspend = pm_video_suspend; | ||
1158 | pd->pm_resume = pm_video_resume; | ||
1159 | #endif | ||
1160 | return set_frequency(pd, freq->frequency); | ||
1161 | } | ||
1162 | |||
1163 | static int vidioc_reqbufs(struct file *file, void *fh, | ||
1164 | struct v4l2_requestbuffers *b) | ||
1165 | { | ||
1166 | struct front_face *front = file->private_data; | ||
1167 | logs(front); | ||
1168 | return videobuf_reqbufs(&front->q, b); | ||
1169 | } | ||
1170 | |||
1171 | static int vidioc_querybuf(struct file *file, void *fh, struct v4l2_buffer *b) | ||
1172 | { | ||
1173 | struct front_face *front = file->private_data; | ||
1174 | logs(front); | ||
1175 | return videobuf_querybuf(&front->q, b); | ||
1176 | } | ||
1177 | |||
1178 | static int vidioc_qbuf(struct file *file, void *fh, struct v4l2_buffer *b) | ||
1179 | { | ||
1180 | struct front_face *front = file->private_data; | ||
1181 | return videobuf_qbuf(&front->q, b); | ||
1182 | } | ||
1183 | |||
1184 | static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b) | ||
1185 | { | ||
1186 | struct front_face *front = file->private_data; | ||
1187 | return videobuf_dqbuf(&front->q, b, file->f_flags & O_NONBLOCK); | ||
1188 | } | ||
1189 | |||
1190 | /* Just stop the URBs, do not free the URBs */ | ||
1191 | int usb_transfer_stop(struct video_data *video) | ||
1192 | { | ||
1193 | if (video->is_streaming) { | ||
1194 | int i; | ||
1195 | s32 cmd_status; | ||
1196 | struct poseidon *pd = video->pd; | ||
1197 | |||
1198 | video->is_streaming = 0; | ||
1199 | for (i = 0; i < SBUF_NUM; ++i) { | ||
1200 | if (video->urb_array[i]) | ||
1201 | usb_kill_urb(video->urb_array[i]); | ||
1202 | } | ||
1203 | |||
1204 | send_set_req(pd, PLAY_SERVICE, TLG_TUNE_PLAY_SVC_STOP, | ||
1205 | &cmd_status); | ||
1206 | } | ||
1207 | return 0; | ||
1208 | } | ||
1209 | |||
1210 | int stop_all_video_stream(struct poseidon *pd) | ||
1211 | { | ||
1212 | struct video_data *video = &pd->video_data; | ||
1213 | struct vbi_data *vbi = &pd->vbi_data; | ||
1214 | |||
1215 | mutex_lock(&pd->lock); | ||
1216 | if (video->is_streaming) { | ||
1217 | struct front_face *front = video->front; | ||
1218 | |||
1219 | /* stop the URBs */ | ||
1220 | usb_transfer_stop(video); | ||
1221 | free_all_urb(video); | ||
1222 | |||
1223 | /* stop the host side of VIDEO */ | ||
1224 | videobuf_stop(&front->q); | ||
1225 | videobuf_mmap_free(&front->q); | ||
1226 | |||
1227 | /* stop the host side of VBI */ | ||
1228 | front = vbi->front; | ||
1229 | if (front) { | ||
1230 | videobuf_stop(&front->q); | ||
1231 | videobuf_mmap_free(&front->q); | ||
1232 | } | ||
1233 | } | ||
1234 | mutex_unlock(&pd->lock); | ||
1235 | return 0; | ||
1236 | } | ||
1237 | |||
1238 | /* | ||
1239 | * The bubbles can seriously damage the video's quality, | ||
1240 | * though it occurs in very rare situation. | ||
1241 | */ | ||
1242 | static void iso_bubble_handler(struct work_struct *w) | ||
1243 | { | ||
1244 | struct video_data *video; | ||
1245 | struct poseidon *pd; | ||
1246 | |||
1247 | video = container_of(w, struct video_data, bubble_work); | ||
1248 | pd = video->pd; | ||
1249 | |||
1250 | mutex_lock(&pd->lock); | ||
1251 | usb_transfer_stop(video); | ||
1252 | msleep(500); | ||
1253 | start_video_stream(pd); | ||
1254 | mutex_unlock(&pd->lock); | ||
1255 | } | ||
1256 | |||
1257 | |||
1258 | static int vidioc_streamon(struct file *file, void *fh, | ||
1259 | enum v4l2_buf_type type) | ||
1260 | { | ||
1261 | struct front_face *front = fh; | ||
1262 | |||
1263 | logs(front); | ||
1264 | if (unlikely(type != front->type)) | ||
1265 | return -EINVAL; | ||
1266 | return videobuf_streamon(&front->q); | ||
1267 | } | ||
1268 | |||
1269 | static int vidioc_streamoff(struct file *file, void *fh, | ||
1270 | enum v4l2_buf_type type) | ||
1271 | { | ||
1272 | struct front_face *front = file->private_data; | ||
1273 | |||
1274 | logs(front); | ||
1275 | if (unlikely(type != front->type)) | ||
1276 | return -EINVAL; | ||
1277 | return videobuf_streamoff(&front->q); | ||
1278 | } | ||
1279 | |||
1280 | /* Set the firmware's default values : need altersetting */ | ||
1281 | static int pd_video_checkmode(struct poseidon *pd) | ||
1282 | { | ||
1283 | s32 ret = 0, cmd_status, audiomode; | ||
1284 | |||
1285 | set_current_state(TASK_INTERRUPTIBLE); | ||
1286 | schedule_timeout(HZ/2); | ||
1287 | |||
1288 | /* choose the altersetting */ | ||
1289 | ret = usb_set_interface(pd->udev, 0, | ||
1290 | (pd->cur_transfer_mode ? | ||
1291 | ISO_3K_BULK_ALTERNATE_IFACE : | ||
1292 | BULK_ALTERNATE_IFACE)); | ||
1293 | if (ret < 0) | ||
1294 | goto error; | ||
1295 | |||
1296 | /* set default parameters for PAL-D , with the VBI enabled*/ | ||
1297 | ret = set_tuner_mode(pd, TLG_MODE_ANALOG_TV); | ||
1298 | ret |= send_set_req(pd, SGNL_SRC_SEL, | ||
1299 | TLG_SIG_SRC_ANTENNA, &cmd_status); | ||
1300 | ret |= send_set_req(pd, VIDEO_STD_SEL, | ||
1301 | TLG_TUNE_VSTD_PAL_D, &cmd_status); | ||
1302 | ret |= send_set_req(pd, VIDEO_STREAM_FMT_SEL, | ||
1303 | TLG_TUNER_VID_FORMAT_YUV, &cmd_status); | ||
1304 | ret |= send_set_req(pd, VIDEO_ROSOLU_SEL, | ||
1305 | TLG_TUNE_VID_RES_720, &cmd_status); | ||
1306 | ret |= send_set_req(pd, TUNE_FREQ_SELECT, TUNER_FREQ_MIN, &cmd_status); | ||
1307 | ret |= send_set_req(pd, VBI_DATA_SEL, 1, &cmd_status);/* enable vbi */ | ||
1308 | |||
1309 | /* set the audio */ | ||
1310 | audiomode = get_audio_std(pd->video_data.context.tvnormid); | ||
1311 | ret |= send_set_req(pd, TUNER_AUD_ANA_STD, audiomode, &cmd_status); | ||
1312 | ret |= send_set_req(pd, TUNER_AUD_MODE, | ||
1313 | TLG_TUNE_TVAUDIO_MODE_STEREO, &cmd_status); | ||
1314 | ret |= send_set_req(pd, AUDIO_SAMPLE_RATE_SEL, | ||
1315 | ATV_AUDIO_RATE_48K, &cmd_status); | ||
1316 | error: | ||
1317 | return ret; | ||
1318 | } | ||
1319 | |||
1320 | #ifdef CONFIG_PM | ||
1321 | static int pm_video_suspend(struct poseidon *pd) | ||
1322 | { | ||
1323 | /* stop audio */ | ||
1324 | pm_alsa_suspend(pd); | ||
1325 | |||
1326 | /* stop and free all the URBs */ | ||
1327 | usb_transfer_stop(&pd->video_data); | ||
1328 | free_all_urb(&pd->video_data); | ||
1329 | |||
1330 | /* reset the interface */ | ||
1331 | usb_set_interface(pd->udev, 0, 0); | ||
1332 | msleep(300); | ||
1333 | return 0; | ||
1334 | } | ||
1335 | |||
1336 | static int restore_v4l2_context(struct poseidon *pd, | ||
1337 | struct running_context *context) | ||
1338 | { | ||
1339 | struct front_face *front = pd->video_data.front; | ||
1340 | |||
1341 | pd_video_checkmode(pd); | ||
1342 | |||
1343 | set_std(pd, &context->tvnormid); | ||
1344 | vidioc_s_input(NULL, front, context->sig_index); | ||
1345 | pd_vidioc_s_tuner(pd, context->audio_idx); | ||
1346 | pd_vidioc_s_fmt(pd, &context->pix); | ||
1347 | set_frequency(pd, context->freq); | ||
1348 | return 0; | ||
1349 | } | ||
1350 | |||
1351 | static int pm_video_resume(struct poseidon *pd) | ||
1352 | { | ||
1353 | struct video_data *video = &pd->video_data; | ||
1354 | |||
1355 | /* resume the video */ | ||
1356 | /* [1] restore the origin V4L2 parameters */ | ||
1357 | restore_v4l2_context(pd, &video->context); | ||
1358 | |||
1359 | /* [2] initiate video copy variables */ | ||
1360 | if (video->front->curr_frame) | ||
1361 | init_copy(video, 0); | ||
1362 | |||
1363 | /* [3] fire urbs */ | ||
1364 | start_video_stream(pd); | ||
1365 | |||
1366 | /* resume the audio */ | ||
1367 | pm_alsa_resume(pd); | ||
1368 | return 0; | ||
1369 | } | ||
1370 | #endif | ||
1371 | |||
1372 | void set_debug_mode(struct video_device *vfd, int debug_mode) | ||
1373 | { | ||
1374 | vfd->debug = 0; | ||
1375 | if (debug_mode & 0x1) | ||
1376 | vfd->debug = V4L2_DEBUG_IOCTL; | ||
1377 | if (debug_mode & 0x2) | ||
1378 | vfd->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG; | ||
1379 | } | ||
1380 | |||
1381 | static void init_video_context(struct running_context *context) | ||
1382 | { | ||
1383 | context->sig_index = 0; | ||
1384 | context->audio_idx = 1; /* stereo */ | ||
1385 | context->tvnormid = V4L2_STD_PAL_D; | ||
1386 | context->pix = (struct v4l2_pix_format) { | ||
1387 | .width = 720, | ||
1388 | .height = 576, | ||
1389 | .pixelformat = V4L2_PIX_FMT_YUYV, | ||
1390 | .field = V4L2_FIELD_INTERLACED, | ||
1391 | .bytesperline = 720 * 2, | ||
1392 | .sizeimage = 720 * 576 * 2, | ||
1393 | .colorspace = V4L2_COLORSPACE_SMPTE170M, | ||
1394 | .priv = 0 | ||
1395 | }; | ||
1396 | } | ||
1397 | |||
1398 | static int pd_video_open(struct file *file) | ||
1399 | { | ||
1400 | struct video_device *vfd = video_devdata(file); | ||
1401 | struct poseidon *pd = video_get_drvdata(vfd); | ||
1402 | struct front_face *front = NULL; | ||
1403 | int ret = -ENOMEM; | ||
1404 | |||
1405 | mutex_lock(&pd->lock); | ||
1406 | usb_autopm_get_interface(pd->interface); | ||
1407 | |||
1408 | if (vfd->vfl_type == VFL_TYPE_GRABBER | ||
1409 | && !(pd->state & POSEIDON_STATE_ANALOG)) { | ||
1410 | front = kzalloc(sizeof(struct front_face), GFP_KERNEL); | ||
1411 | if (!front) | ||
1412 | goto out; | ||
1413 | |||
1414 | pd->cur_transfer_mode = usb_transfer_mode;/* bulk or iso */ | ||
1415 | init_video_context(&pd->video_data.context); | ||
1416 | |||
1417 | ret = pd_video_checkmode(pd); | ||
1418 | if (ret < 0) { | ||
1419 | kfree(front); | ||
1420 | ret = -1; | ||
1421 | goto out; | ||
1422 | } | ||
1423 | |||
1424 | pd->state |= POSEIDON_STATE_ANALOG; | ||
1425 | front->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
1426 | pd->video_data.users++; | ||
1427 | set_debug_mode(vfd, debug_mode); | ||
1428 | |||
1429 | videobuf_queue_vmalloc_init(&front->q, &pd_video_qops, | ||
1430 | NULL, &front->queue_lock, | ||
1431 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
1432 | V4L2_FIELD_INTERLACED,/* video is interlacd */ | ||
1433 | sizeof(struct videobuf_buffer),/*it's enough*/ | ||
1434 | front); | ||
1435 | } else if (vfd->vfl_type == VFL_TYPE_VBI | ||
1436 | && !(pd->state & POSEIDON_STATE_VBI)) { | ||
1437 | front = kzalloc(sizeof(struct front_face), GFP_KERNEL); | ||
1438 | if (!front) | ||
1439 | goto out; | ||
1440 | |||
1441 | pd->state |= POSEIDON_STATE_VBI; | ||
1442 | front->type = V4L2_BUF_TYPE_VBI_CAPTURE; | ||
1443 | pd->vbi_data.front = front; | ||
1444 | pd->vbi_data.users++; | ||
1445 | |||
1446 | videobuf_queue_vmalloc_init(&front->q, &pd_video_qops, | ||
1447 | NULL, &front->queue_lock, | ||
1448 | V4L2_BUF_TYPE_VBI_CAPTURE, | ||
1449 | V4L2_FIELD_NONE, /* vbi is NONE mode */ | ||
1450 | sizeof(struct videobuf_buffer), | ||
1451 | front); | ||
1452 | } else { | ||
1453 | /* maybe add FM support here */ | ||
1454 | log("other "); | ||
1455 | ret = -EINVAL; | ||
1456 | goto out; | ||
1457 | } | ||
1458 | |||
1459 | front->pd = pd; | ||
1460 | front->curr_frame = NULL; | ||
1461 | INIT_LIST_HEAD(&front->active); | ||
1462 | spin_lock_init(&front->queue_lock); | ||
1463 | |||
1464 | file->private_data = front; | ||
1465 | kref_get(&pd->kref); | ||
1466 | |||
1467 | mutex_unlock(&pd->lock); | ||
1468 | return 0; | ||
1469 | out: | ||
1470 | usb_autopm_put_interface(pd->interface); | ||
1471 | mutex_unlock(&pd->lock); | ||
1472 | return ret; | ||
1473 | } | ||
1474 | |||
1475 | static int pd_video_release(struct file *file) | ||
1476 | { | ||
1477 | struct front_face *front = file->private_data; | ||
1478 | struct poseidon *pd = front->pd; | ||
1479 | s32 cmd_status = 0; | ||
1480 | |||
1481 | logs(front); | ||
1482 | mutex_lock(&pd->lock); | ||
1483 | |||
1484 | if (front->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { | ||
1485 | pd->state &= ~POSEIDON_STATE_ANALOG; | ||
1486 | |||
1487 | /* stop the device, and free the URBs */ | ||
1488 | usb_transfer_stop(&pd->video_data); | ||
1489 | free_all_urb(&pd->video_data); | ||
1490 | |||
1491 | /* stop the firmware */ | ||
1492 | send_set_req(pd, PLAY_SERVICE, TLG_TUNE_PLAY_SVC_STOP, | ||
1493 | &cmd_status); | ||
1494 | |||
1495 | pd->file_for_stream = NULL; | ||
1496 | pd->video_data.users--; | ||
1497 | } else if (front->type == V4L2_BUF_TYPE_VBI_CAPTURE) { | ||
1498 | pd->state &= ~POSEIDON_STATE_VBI; | ||
1499 | pd->vbi_data.front = NULL; | ||
1500 | pd->vbi_data.users--; | ||
1501 | } | ||
1502 | videobuf_stop(&front->q); | ||
1503 | videobuf_mmap_free(&front->q); | ||
1504 | |||
1505 | usb_autopm_put_interface(pd->interface); | ||
1506 | mutex_unlock(&pd->lock); | ||
1507 | |||
1508 | kfree(front); | ||
1509 | file->private_data = NULL; | ||
1510 | kref_put(&pd->kref, poseidon_delete); | ||
1511 | return 0; | ||
1512 | } | ||
1513 | |||
1514 | static int pd_video_mmap(struct file *file, struct vm_area_struct *vma) | ||
1515 | { | ||
1516 | struct front_face *front = file->private_data; | ||
1517 | return videobuf_mmap_mapper(&front->q, vma); | ||
1518 | } | ||
1519 | |||
1520 | unsigned int pd_video_poll(struct file *file, poll_table *table) | ||
1521 | { | ||
1522 | struct front_face *front = file->private_data; | ||
1523 | return videobuf_poll_stream(file, &front->q, table); | ||
1524 | } | ||
1525 | |||
1526 | ssize_t pd_video_read(struct file *file, char __user *buffer, | ||
1527 | size_t count, loff_t *ppos) | ||
1528 | { | ||
1529 | struct front_face *front = file->private_data; | ||
1530 | return videobuf_read_stream(&front->q, buffer, count, ppos, | ||
1531 | 0, file->f_flags & O_NONBLOCK); | ||
1532 | } | ||
1533 | |||
1534 | /* This struct works for both VIDEO and VBI */ | ||
1535 | static const struct v4l2_file_operations pd_video_fops = { | ||
1536 | .owner = THIS_MODULE, | ||
1537 | .open = pd_video_open, | ||
1538 | .release = pd_video_release, | ||
1539 | .read = pd_video_read, | ||
1540 | .poll = pd_video_poll, | ||
1541 | .mmap = pd_video_mmap, | ||
1542 | .ioctl = video_ioctl2, /* maybe changed in future */ | ||
1543 | }; | ||
1544 | |||
1545 | static const struct v4l2_ioctl_ops pd_video_ioctl_ops = { | ||
1546 | .vidioc_querycap = vidioc_querycap, | ||
1547 | |||
1548 | /* Video format */ | ||
1549 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt, | ||
1550 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt, | ||
1551 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt, | ||
1552 | .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi, /* VBI */ | ||
1553 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt, | ||
1554 | |||
1555 | /* Input */ | ||
1556 | .vidioc_g_input = vidioc_g_input, | ||
1557 | .vidioc_s_input = vidioc_s_input, | ||
1558 | .vidioc_enum_input = vidioc_enum_input, | ||
1559 | |||
1560 | /* Audio ioctls */ | ||
1561 | .vidioc_enumaudio = vidioc_enumaudio, | ||
1562 | .vidioc_g_audio = vidioc_g_audio, | ||
1563 | .vidioc_s_audio = vidioc_s_audio, | ||
1564 | |||
1565 | /* Tuner ioctls */ | ||
1566 | .vidioc_g_tuner = vidioc_g_tuner, | ||
1567 | .vidioc_s_tuner = vidioc_s_tuner, | ||
1568 | .vidioc_s_std = vidioc_s_std, | ||
1569 | .vidioc_g_frequency = vidioc_g_frequency, | ||
1570 | .vidioc_s_frequency = vidioc_s_frequency, | ||
1571 | |||
1572 | /* Buffer handlers */ | ||
1573 | .vidioc_reqbufs = vidioc_reqbufs, | ||
1574 | .vidioc_querybuf = vidioc_querybuf, | ||
1575 | .vidioc_qbuf = vidioc_qbuf, | ||
1576 | .vidioc_dqbuf = vidioc_dqbuf, | ||
1577 | |||
1578 | /* Stream on/off */ | ||
1579 | .vidioc_streamon = vidioc_streamon, | ||
1580 | .vidioc_streamoff = vidioc_streamoff, | ||
1581 | |||
1582 | /* Control handling */ | ||
1583 | .vidioc_queryctrl = vidioc_queryctrl, | ||
1584 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
1585 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
1586 | }; | ||
1587 | |||
1588 | static struct video_device pd_video_template = { | ||
1589 | .name = "Telegent-Video", | ||
1590 | .fops = &pd_video_fops, | ||
1591 | .minor = -1, | ||
1592 | .release = video_device_release, | ||
1593 | .tvnorms = V4L2_STD_ALL, | ||
1594 | .ioctl_ops = &pd_video_ioctl_ops, | ||
1595 | }; | ||
1596 | |||
1597 | struct video_device *vdev_init(struct poseidon *pd, struct video_device *tmp) | ||
1598 | { | ||
1599 | struct video_device *vfd; | ||
1600 | |||
1601 | vfd = video_device_alloc(); | ||
1602 | if (vfd == NULL) | ||
1603 | return NULL; | ||
1604 | *vfd = *tmp; | ||
1605 | vfd->minor = -1; | ||
1606 | vfd->v4l2_dev = &pd->v4l2_dev; | ||
1607 | /*vfd->parent = &(pd->udev->dev); */ | ||
1608 | vfd->release = video_device_release; | ||
1609 | video_set_drvdata(vfd, pd); | ||
1610 | return vfd; | ||
1611 | } | ||
1612 | |||
1613 | void destroy_video_device(struct video_device **v_dev) | ||
1614 | { | ||
1615 | struct video_device *dev = *v_dev; | ||
1616 | |||
1617 | if (dev == NULL) | ||
1618 | return; | ||
1619 | |||
1620 | if (video_is_registered(dev)) | ||
1621 | video_unregister_device(dev); | ||
1622 | else | ||
1623 | video_device_release(dev); | ||
1624 | *v_dev = NULL; | ||
1625 | } | ||
1626 | |||
1627 | void pd_video_exit(struct poseidon *pd) | ||
1628 | { | ||
1629 | struct video_data *video = &pd->video_data; | ||
1630 | struct vbi_data *vbi = &pd->vbi_data; | ||
1631 | |||
1632 | destroy_video_device(&video->v_dev); | ||
1633 | destroy_video_device(&vbi->v_dev); | ||
1634 | log(); | ||
1635 | } | ||
1636 | |||
1637 | int pd_video_init(struct poseidon *pd) | ||
1638 | { | ||
1639 | struct video_data *video = &pd->video_data; | ||
1640 | struct vbi_data *vbi = &pd->vbi_data; | ||
1641 | int ret = -ENOMEM; | ||
1642 | |||
1643 | video->v_dev = vdev_init(pd, &pd_video_template); | ||
1644 | if (video->v_dev == NULL) | ||
1645 | goto out; | ||
1646 | |||
1647 | ret = video_register_device(video->v_dev, VFL_TYPE_GRABBER, -1); | ||
1648 | if (ret != 0) | ||
1649 | goto out; | ||
1650 | |||
1651 | /* VBI uses the same template as video */ | ||
1652 | vbi->v_dev = vdev_init(pd, &pd_video_template); | ||
1653 | if (vbi->v_dev == NULL) { | ||
1654 | ret = -ENOMEM; | ||
1655 | goto out; | ||
1656 | } | ||
1657 | ret = video_register_device(vbi->v_dev, VFL_TYPE_VBI, -1); | ||
1658 | if (ret != 0) | ||
1659 | goto out; | ||
1660 | log("register VIDEO/VBI devices"); | ||
1661 | return 0; | ||
1662 | out: | ||
1663 | log("VIDEO/VBI devices register failed, : %d", ret); | ||
1664 | pd_video_exit(pd); | ||
1665 | return ret; | ||
1666 | } | ||
1667 | |||
diff --git a/drivers/media/video/tlg2300/vendorcmds.h b/drivers/media/video/tlg2300/vendorcmds.h new file mode 100644 index 000000000000..ba6f4ae3b2c2 --- /dev/null +++ b/drivers/media/video/tlg2300/vendorcmds.h | |||
@@ -0,0 +1,243 @@ | |||
1 | #ifndef VENDOR_CMD_H_ | ||
2 | #define VENDOR_CMD_H_ | ||
3 | |||
4 | #define BULK_ALTERNATE_IFACE (2) | ||
5 | #define ISO_3K_BULK_ALTERNATE_IFACE (1) | ||
6 | #define REQ_SET_CMD (0X00) | ||
7 | #define REQ_GET_CMD (0X80) | ||
8 | |||
9 | enum tlg__analog_audio_standard { | ||
10 | TLG_TUNE_ASTD_NONE = 0x00000000, | ||
11 | TLG_TUNE_ASTD_A2 = 0x00000001, | ||
12 | TLG_TUNE_ASTD_NICAM = 0x00000002, | ||
13 | TLG_TUNE_ASTD_EIAJ = 0x00000004, | ||
14 | TLG_TUNE_ASTD_BTSC = 0x00000008, | ||
15 | TLG_TUNE_ASTD_FM_US = 0x00000010, | ||
16 | TLG_TUNE_ASTD_FM_EUR = 0x00000020, | ||
17 | TLG_TUNE_ASTD_ALL = 0x0000003f | ||
18 | }; | ||
19 | |||
20 | /* | ||
21 | * identifiers for Custom Parameter messages. | ||
22 | * @typedef cmd_custom_param_id_t | ||
23 | */ | ||
24 | enum cmd_custom_param_id { | ||
25 | CUST_PARM_ID_NONE = 0x00, | ||
26 | CUST_PARM_ID_BRIGHTNESS_CTRL = 0x01, | ||
27 | CUST_PARM_ID_CONTRAST_CTRL = 0x02, | ||
28 | CUST_PARM_ID_HUE_CTRL = 0x03, | ||
29 | CUST_PARM_ID_SATURATION_CTRL = 0x04, | ||
30 | CUST_PARM_ID_AUDIO_SNR_THRESHOLD = 0x10, | ||
31 | CUST_PARM_ID_AUDIO_AGC_THRESHOLD = 0x11, | ||
32 | CUST_PARM_ID_MAX | ||
33 | }; | ||
34 | |||
35 | struct tuner_custom_parameter_s { | ||
36 | uint16_t param_id; /* Parameter identifier */ | ||
37 | uint16_t param_value; /* Parameter value */ | ||
38 | }; | ||
39 | |||
40 | struct tuner_ber_rate_s { | ||
41 | uint32_t ber_rate; /* BER sample rate in seconds */ | ||
42 | }; | ||
43 | |||
44 | struct tuner_atv_sig_stat_s { | ||
45 | uint32_t sig_present; | ||
46 | uint32_t sig_locked; | ||
47 | uint32_t sig_lock_busy; | ||
48 | uint32_t sig_strength; /* milliDb */ | ||
49 | uint32_t tv_audio_chan; /* mono/stereo/sap*/ | ||
50 | uint32_t mvision_stat; /* macrovision status */ | ||
51 | }; | ||
52 | |||
53 | struct tuner_dtv_sig_stat_s { | ||
54 | uint32_t sig_present; /* Boolean*/ | ||
55 | uint32_t sig_locked; /* Boolean */ | ||
56 | uint32_t sig_lock_busy; /* Boolean (Can this time-out?) */ | ||
57 | uint32_t sig_strength; /* milliDb*/ | ||
58 | }; | ||
59 | |||
60 | struct tuner_fm_sig_stat_s { | ||
61 | uint32_t sig_present; /* Boolean*/ | ||
62 | uint32_t sig_locked; /* Boolean */ | ||
63 | uint32_t sig_lock_busy; /* Boolean */ | ||
64 | uint32_t sig_stereo_mono;/* TBD*/ | ||
65 | uint32_t sig_strength; /* milliDb*/ | ||
66 | }; | ||
67 | |||
68 | enum _tag_tlg_tune_srv_cmd { | ||
69 | TLG_TUNE_PLAY_SVC_START = 1, | ||
70 | TLG_TUNE_PLAY_SVC_STOP | ||
71 | }; | ||
72 | |||
73 | enum _tag_tune_atv_audio_mode_caps { | ||
74 | TLG_TUNE_TVAUDIO_MODE_MONO = 0x00000001, | ||
75 | TLG_TUNE_TVAUDIO_MODE_STEREO = 0x00000002, | ||
76 | TLG_TUNE_TVAUDIO_MODE_LANG_A = 0x00000010,/* Primary language*/ | ||
77 | TLG_TUNE_TVAUDIO_MODE_LANG_B = 0x00000020,/* 2nd avail language*/ | ||
78 | TLG_TUNE_TVAUDIO_MODE_LANG_C = 0x00000040 | ||
79 | }; | ||
80 | |||
81 | |||
82 | enum _tag_tuner_atv_audio_rates { | ||
83 | ATV_AUDIO_RATE_NONE = 0x00,/* Audio not supported*/ | ||
84 | ATV_AUDIO_RATE_32K = 0x01,/* Audio rate = 32 KHz*/ | ||
85 | ATV_AUDIO_RATE_48K = 0x02, /* Audio rate = 48 KHz*/ | ||
86 | ATV_AUDIO_RATE_31_25K = 0x04 /* Audio rate = 31.25KHz */ | ||
87 | }; | ||
88 | |||
89 | enum _tag_tune_atv_vid_res_caps { | ||
90 | TLG_TUNE_VID_RES_NONE = 0x00000000, | ||
91 | TLG_TUNE_VID_RES_720 = 0x00000001, | ||
92 | TLG_TUNE_VID_RES_704 = 0x00000002, | ||
93 | TLG_TUNE_VID_RES_360 = 0x00000004 | ||
94 | }; | ||
95 | |||
96 | enum _tag_tuner_analog_video_format { | ||
97 | TLG_TUNER_VID_FORMAT_YUV = 0x00000001, | ||
98 | TLG_TUNER_VID_FORMAT_YCRCB = 0x00000002, | ||
99 | TLG_TUNER_VID_FORMAT_RGB_565 = 0x00000004, | ||
100 | }; | ||
101 | |||
102 | enum tlg_ext_audio_support { | ||
103 | TLG_EXT_AUDIO_NONE = 0x00,/* No external audio input supported */ | ||
104 | TLG_EXT_AUDIO_LR = 0x01/* LR external audio inputs supported*/ | ||
105 | }; | ||
106 | |||
107 | enum { | ||
108 | TLG_MODE_NONE = 0x00, /* No Mode specified*/ | ||
109 | TLG_MODE_ANALOG_TV = 0x01, /* Analog Television mode*/ | ||
110 | TLG_MODE_ANALOG_TV_UNCOMP = 0x01, /* Analog Television mode*/ | ||
111 | TLG_MODE_ANALOG_TV_COMP = 0x02, /* Analog TV mode (compressed)*/ | ||
112 | TLG_MODE_FM_RADIO = 0x04, /* FM Radio mode*/ | ||
113 | TLG_MODE_DVB_T = 0x08, /* Digital TV (DVB-T)*/ | ||
114 | }; | ||
115 | |||
116 | enum tlg_signal_sources_t { | ||
117 | TLG_SIG_SRC_NONE = 0x00,/* Signal source not specified */ | ||
118 | TLG_SIG_SRC_ANTENNA = 0x01,/* Signal src is: Antenna */ | ||
119 | TLG_SIG_SRC_CABLE = 0x02,/* Signal src is: Coax Cable*/ | ||
120 | TLG_SIG_SRC_SVIDEO = 0x04,/* Signal src is: S_VIDEO */ | ||
121 | TLG_SIG_SRC_COMPOSITE = 0x08 /* Signal src is: Composite Video */ | ||
122 | }; | ||
123 | |||
124 | enum tuner_analog_video_standard { | ||
125 | TLG_TUNE_VSTD_NONE = 0x00000000, | ||
126 | TLG_TUNE_VSTD_NTSC_M = 0x00000001, | ||
127 | TLG_TUNE_VSTD_NTSC_M_J = 0x00000002,/* Japan */ | ||
128 | TLG_TUNE_VSTD_PAL_B = 0x00000010, | ||
129 | TLG_TUNE_VSTD_PAL_D = 0x00000020, | ||
130 | TLG_TUNE_VSTD_PAL_G = 0x00000040, | ||
131 | TLG_TUNE_VSTD_PAL_H = 0x00000080, | ||
132 | TLG_TUNE_VSTD_PAL_I = 0x00000100, | ||
133 | TLG_TUNE_VSTD_PAL_M = 0x00000200, | ||
134 | TLG_TUNE_VSTD_PAL_N = 0x00000400, | ||
135 | TLG_TUNE_VSTD_SECAM_B = 0x00001000, | ||
136 | TLG_TUNE_VSTD_SECAM_D = 0x00002000, | ||
137 | TLG_TUNE_VSTD_SECAM_G = 0x00004000, | ||
138 | TLG_TUNE_VSTD_SECAM_H = 0x00008000, | ||
139 | TLG_TUNE_VSTD_SECAM_K = 0x00010000, | ||
140 | TLG_TUNE_VSTD_SECAM_K1 = 0x00020000, | ||
141 | TLG_TUNE_VSTD_SECAM_L = 0x00040000, | ||
142 | TLG_TUNE_VSTD_SECAM_L1 = 0x00080000, | ||
143 | TLG_TUNE_VSTD_PAL_N_COMBO = 0x00100000 | ||
144 | }; | ||
145 | |||
146 | enum tlg_mode_caps { | ||
147 | TLG_MODE_CAPS_NONE = 0x00, /* No Mode specified */ | ||
148 | TLG_MODE_CAPS_ANALOG_TV_UNCOMP = 0x01, /* Analog TV mode */ | ||
149 | TLG_MODE_CAPS_ANALOG_TV_COMP = 0x02, /* Analog TV (compressed)*/ | ||
150 | TLG_MODE_CAPS_FM_RADIO = 0x04, /* FM Radio mode */ | ||
151 | TLG_MODE_CAPS_DVB_T = 0x08, /* Digital TV (DVB-T) */ | ||
152 | }; | ||
153 | |||
154 | enum poseidon_vendor_cmds { | ||
155 | LAST_CMD_STAT = 0x00, | ||
156 | GET_CHIP_ID = 0x01, | ||
157 | GET_FW_ID = 0x02, | ||
158 | PRODUCT_CAPS = 0x03, | ||
159 | |||
160 | TUNE_MODE_CAP_ATV = 0x10, | ||
161 | TUNE_MODE_CAP_ATVCOMP = 0X10, | ||
162 | TUNE_MODE_CAP_DVBT = 0x10, | ||
163 | TUNE_MODE_CAP_FM = 0x10, | ||
164 | TUNE_MODE_SELECT = 0x11, | ||
165 | TUNE_FREQ_SELECT = 0x12, | ||
166 | SGNL_SRC_SEL = 0x13, | ||
167 | |||
168 | VIDEO_STD_SEL = 0x14, | ||
169 | VIDEO_STREAM_FMT_SEL = 0x15, | ||
170 | VIDEO_ROSOLU_AVAIL = 0x16, | ||
171 | VIDEO_ROSOLU_SEL = 0x17, | ||
172 | VIDEO_CONT_PROTECT = 0x20, | ||
173 | |||
174 | VCR_TIMING_MODSEL = 0x21, | ||
175 | EXT_AUDIO_CAP = 0x22, | ||
176 | EXT_AUDIO_SEL = 0x23, | ||
177 | TEST_PATTERN_SEL = 0x24, | ||
178 | VBI_DATA_SEL = 0x25, | ||
179 | AUDIO_SAMPLE_RATE_CAP = 0x28, | ||
180 | AUDIO_SAMPLE_RATE_SEL = 0x29, | ||
181 | TUNER_AUD_MODE = 0x2a, | ||
182 | TUNER_AUD_MODE_AVAIL = 0x2b, | ||
183 | TUNER_AUD_ANA_STD = 0x2c, | ||
184 | TUNER_CUSTOM_PARAMETER = 0x2f, | ||
185 | |||
186 | DVBT_TUNE_MODE_SEL = 0x30, | ||
187 | DVBT_BANDW_CAP = 0x31, | ||
188 | DVBT_BANDW_SEL = 0x32, | ||
189 | DVBT_GUARD_INTERV_CAP = 0x33, | ||
190 | DVBT_GUARD_INTERV_SEL = 0x34, | ||
191 | DVBT_MODULATION_CAP = 0x35, | ||
192 | DVBT_MODULATION_SEL = 0x36, | ||
193 | DVBT_INNER_FEC_RATE_CAP = 0x37, | ||
194 | DVBT_INNER_FEC_RATE_SEL = 0x38, | ||
195 | DVBT_TRANS_MODE_CAP = 0x39, | ||
196 | DVBT_TRANS_MODE_SEL = 0x3a, | ||
197 | DVBT_SEARCH_RANG = 0x3c, | ||
198 | |||
199 | TUNER_SETUP_ANALOG = 0x40, | ||
200 | TUNER_SETUP_DIGITAL = 0x41, | ||
201 | TUNER_SETUP_FM_RADIO = 0x42, | ||
202 | TAKE_REQUEST = 0x43, /* Take effect of the command */ | ||
203 | PLAY_SERVICE = 0x44, /* Play start or Play stop */ | ||
204 | TUNER_STATUS = 0x45, | ||
205 | TUNE_PROP_DVBT = 0x46, | ||
206 | ERR_RATE_STATS = 0x47, | ||
207 | TUNER_BER_RATE = 0x48, | ||
208 | |||
209 | SCAN_CAPS = 0x50, | ||
210 | SCAN_SETUP = 0x51, | ||
211 | SCAN_SERVICE = 0x52, | ||
212 | SCAN_STATS = 0x53, | ||
213 | |||
214 | PID_SET = 0x58, | ||
215 | PID_UNSET = 0x59, | ||
216 | PID_LIST = 0x5a, | ||
217 | |||
218 | IRD_CAP = 0x60, | ||
219 | IRD_MODE_SEL = 0x61, | ||
220 | IRD_SETUP = 0x62, | ||
221 | |||
222 | PTM_MODE_CAP = 0x70, | ||
223 | PTM_MODE_SEL = 0x71, | ||
224 | PTM_SERVICE = 0x72, | ||
225 | TUNER_REG_SCRIPT = 0x73, | ||
226 | CMD_CHIP_RST = 0x74, | ||
227 | }; | ||
228 | |||
229 | enum tlg_bw { | ||
230 | TLG_BW_5 = 5, | ||
231 | TLG_BW_6 = 6, | ||
232 | TLG_BW_7 = 7, | ||
233 | TLG_BW_8 = 8, | ||
234 | TLG_BW_12 = 12, | ||
235 | TLG_BW_15 = 15 | ||
236 | }; | ||
237 | |||
238 | struct cmd_firmware_vers_s { | ||
239 | uint8_t fw_rev_major; | ||
240 | uint8_t fw_rev_minor; | ||
241 | uint16_t fw_patch; | ||
242 | }; | ||
243 | #endif /* VENDOR_CMD_H_ */ | ||
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 5b3eaa16afd2..c4dab6cfd948 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c | |||
@@ -1078,6 +1078,7 @@ static int tuner_probe(struct i2c_client *client, | |||
1078 | 1078 | ||
1079 | goto register_client; | 1079 | goto register_client; |
1080 | } | 1080 | } |
1081 | kfree(t); | ||
1081 | return -ENODEV; | 1082 | return -ENODEV; |
1082 | case 0x42: | 1083 | case 0x42: |
1083 | case 0x43: | 1084 | case 0x43: |
diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index d533ea57e7b1..0a877497b93f 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c | |||
@@ -680,10 +680,7 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, | |||
680 | tveeprom_info("Hauppauge model %d, rev %s, serial# %d\n", | 680 | tveeprom_info("Hauppauge model %d, rev %s, serial# %d\n", |
681 | tvee->model, tvee->rev_str, tvee->serial_number); | 681 | tvee->model, tvee->rev_str, tvee->serial_number); |
682 | if (tvee->has_MAC_address == 1) | 682 | if (tvee->has_MAC_address == 1) |
683 | tveeprom_info("MAC address is %02X-%02X-%02X-%02X-%02X-%02X\n", | 683 | tveeprom_info("MAC address is %pM\n", tvee->MAC_address); |
684 | tvee->MAC_address[0], tvee->MAC_address[1], | ||
685 | tvee->MAC_address[2], tvee->MAC_address[3], | ||
686 | tvee->MAC_address[4], tvee->MAC_address[5]); | ||
687 | tveeprom_info("tuner model is %s (idx %d, type %d)\n", | 684 | tveeprom_info("tuner model is %s (idx %d, type %d)\n", |
688 | t_name1, tuner1, tvee->tuner_type); | 685 | t_name1, tuner1, tvee->tuner_type); |
689 | tveeprom_info("TV standards%s%s%s%s%s%s%s%s (eeprom 0x%02x)\n", | 686 | tveeprom_info("TV standards%s%s%s%s%s%s%s%s (eeprom 0x%02x)\n", |
diff --git a/drivers/media/video/tvp7002.c b/drivers/media/video/tvp7002.c new file mode 100644 index 000000000000..5a878bca02d4 --- /dev/null +++ b/drivers/media/video/tvp7002.c | |||
@@ -0,0 +1,1187 @@ | |||
1 | /* Texas Instruments Triple 8-/10-BIT 165-/110-MSPS Video and Graphics | ||
2 | * Digitizer with Horizontal PLL registers | ||
3 | * | ||
4 | * Copyright (C) 2009 Texas Instruments Inc | ||
5 | * Author: Santiago Nunez-Corrales <santiago.nunez@ridgerun.com> | ||
6 | * | ||
7 | * This code is partially based upon the TVP5150 driver | ||
8 | * written by Mauro Carvalho Chehab (mchehab@infradead.org), | ||
9 | * the TVP514x driver written by Vaibhav Hiremath <hvaibhav@ti.com> | ||
10 | * and the TVP7002 driver in the TI LSP 2.10.00.14. Revisions by | ||
11 | * Muralidharan Karicheri and Snehaprabha Narnakaje (TI). | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | #include <linux/delay.h> | ||
28 | #include <linux/i2c.h> | ||
29 | #include <linux/videodev2.h> | ||
30 | #include <media/tvp7002.h> | ||
31 | #include <media/v4l2-device.h> | ||
32 | #include <media/v4l2-chip-ident.h> | ||
33 | #include <media/v4l2-common.h> | ||
34 | #include "tvp7002_reg.h" | ||
35 | |||
36 | MODULE_DESCRIPTION("TI TVP7002 Video and Graphics Digitizer driver"); | ||
37 | MODULE_AUTHOR("Santiago Nunez-Corrales <santiago.nunez@ridgerun.com>"); | ||
38 | MODULE_LICENSE("GPL"); | ||
39 | |||
40 | /* Module Name */ | ||
41 | #define TVP7002_MODULE_NAME "tvp7002" | ||
42 | |||
43 | /* I2C retry attempts */ | ||
44 | #define I2C_RETRY_COUNT (5) | ||
45 | |||
46 | /* End of registers */ | ||
47 | #define TVP7002_EOR 0x5c | ||
48 | |||
49 | /* Read write definition for registers */ | ||
50 | #define TVP7002_READ 0 | ||
51 | #define TVP7002_WRITE 1 | ||
52 | #define TVP7002_RESERVED 2 | ||
53 | |||
54 | /* Interlaced vs progressive mask and shift */ | ||
55 | #define TVP7002_IP_SHIFT 5 | ||
56 | #define TVP7002_INPR_MASK (0x01 << TVP7002_IP_SHIFT) | ||
57 | |||
58 | /* Shift for CPL and LPF registers */ | ||
59 | #define TVP7002_CL_SHIFT 8 | ||
60 | #define TVP7002_CL_MASK 0x0f | ||
61 | |||
62 | /* Debug functions */ | ||
63 | static int debug; | ||
64 | module_param(debug, bool, 0644); | ||
65 | MODULE_PARM_DESC(debug, "Debug level (0-2)"); | ||
66 | |||
67 | /* Structure for register values */ | ||
68 | struct i2c_reg_value { | ||
69 | u8 reg; | ||
70 | u8 value; | ||
71 | u8 type; | ||
72 | }; | ||
73 | |||
74 | /* | ||
75 | * Register default values (according to tvp7002 datasheet) | ||
76 | * In the case of read-only registers, the value (0xff) is | ||
77 | * never written. R/W functionality is controlled by the | ||
78 | * writable bit in the register struct definition. | ||
79 | */ | ||
80 | static const struct i2c_reg_value tvp7002_init_default[] = { | ||
81 | { TVP7002_CHIP_REV, 0xff, TVP7002_READ }, | ||
82 | { TVP7002_HPLL_FDBK_DIV_MSBS, 0x67, TVP7002_WRITE }, | ||
83 | { TVP7002_HPLL_FDBK_DIV_LSBS, 0x20, TVP7002_WRITE }, | ||
84 | { TVP7002_HPLL_CRTL, 0xa0, TVP7002_WRITE }, | ||
85 | { TVP7002_HPLL_PHASE_SEL, 0x80, TVP7002_WRITE }, | ||
86 | { TVP7002_CLAMP_START, 0x32, TVP7002_WRITE }, | ||
87 | { TVP7002_CLAMP_W, 0x20, TVP7002_WRITE }, | ||
88 | { TVP7002_HSYNC_OUT_W, 0x60, TVP7002_WRITE }, | ||
89 | { TVP7002_B_FINE_GAIN, 0x00, TVP7002_WRITE }, | ||
90 | { TVP7002_G_FINE_GAIN, 0x00, TVP7002_WRITE }, | ||
91 | { TVP7002_R_FINE_GAIN, 0x00, TVP7002_WRITE }, | ||
92 | { TVP7002_B_FINE_OFF_MSBS, 0x80, TVP7002_WRITE }, | ||
93 | { TVP7002_G_FINE_OFF_MSBS, 0x80, TVP7002_WRITE }, | ||
94 | { TVP7002_R_FINE_OFF_MSBS, 0x80, TVP7002_WRITE }, | ||
95 | { TVP7002_SYNC_CTL_1, 0x20, TVP7002_WRITE }, | ||
96 | { TVP7002_HPLL_AND_CLAMP_CTL, 0x2e, TVP7002_WRITE }, | ||
97 | { TVP7002_SYNC_ON_G_THRS, 0x5d, TVP7002_WRITE }, | ||
98 | { TVP7002_SYNC_SEPARATOR_THRS, 0x47, TVP7002_WRITE }, | ||
99 | { TVP7002_HPLL_PRE_COAST, 0x00, TVP7002_WRITE }, | ||
100 | { TVP7002_HPLL_POST_COAST, 0x00, TVP7002_WRITE }, | ||
101 | { TVP7002_SYNC_DETECT_STAT, 0xff, TVP7002_READ }, | ||
102 | { TVP7002_OUT_FORMATTER, 0x47, TVP7002_WRITE }, | ||
103 | { TVP7002_MISC_CTL_1, 0x01, TVP7002_WRITE }, | ||
104 | { TVP7002_MISC_CTL_2, 0x00, TVP7002_WRITE }, | ||
105 | { TVP7002_MISC_CTL_3, 0x01, TVP7002_WRITE }, | ||
106 | { TVP7002_IN_MUX_SEL_1, 0x00, TVP7002_WRITE }, | ||
107 | { TVP7002_IN_MUX_SEL_2, 0x67, TVP7002_WRITE }, | ||
108 | { TVP7002_B_AND_G_COARSE_GAIN, 0x77, TVP7002_WRITE }, | ||
109 | { TVP7002_R_COARSE_GAIN, 0x07, TVP7002_WRITE }, | ||
110 | { TVP7002_FINE_OFF_LSBS, 0x00, TVP7002_WRITE }, | ||
111 | { TVP7002_B_COARSE_OFF, 0x10, TVP7002_WRITE }, | ||
112 | { TVP7002_G_COARSE_OFF, 0x10, TVP7002_WRITE }, | ||
113 | { TVP7002_R_COARSE_OFF, 0x10, TVP7002_WRITE }, | ||
114 | { TVP7002_HSOUT_OUT_START, 0x08, TVP7002_WRITE }, | ||
115 | { TVP7002_MISC_CTL_4, 0x00, TVP7002_WRITE }, | ||
116 | { TVP7002_B_DGTL_ALC_OUT_LSBS, 0xff, TVP7002_READ }, | ||
117 | { TVP7002_G_DGTL_ALC_OUT_LSBS, 0xff, TVP7002_READ }, | ||
118 | { TVP7002_R_DGTL_ALC_OUT_LSBS, 0xff, TVP7002_READ }, | ||
119 | { TVP7002_AUTO_LVL_CTL_ENABLE, 0x80, TVP7002_WRITE }, | ||
120 | { TVP7002_DGTL_ALC_OUT_MSBS, 0xff, TVP7002_READ }, | ||
121 | { TVP7002_AUTO_LVL_CTL_FILTER, 0x53, TVP7002_WRITE }, | ||
122 | { 0x29, 0x08, TVP7002_RESERVED }, | ||
123 | { TVP7002_FINE_CLAMP_CTL, 0x07, TVP7002_WRITE }, | ||
124 | /* PWR_CTL is controlled only by the probe and reset functions */ | ||
125 | { TVP7002_PWR_CTL, 0x00, TVP7002_RESERVED }, | ||
126 | { TVP7002_ADC_SETUP, 0x50, TVP7002_WRITE }, | ||
127 | { TVP7002_COARSE_CLAMP_CTL, 0x00, TVP7002_WRITE }, | ||
128 | { TVP7002_SOG_CLAMP, 0x80, TVP7002_WRITE }, | ||
129 | { TVP7002_RGB_COARSE_CLAMP_CTL, 0x00, TVP7002_WRITE }, | ||
130 | { TVP7002_SOG_COARSE_CLAMP_CTL, 0x04, TVP7002_WRITE }, | ||
131 | { TVP7002_ALC_PLACEMENT, 0x5a, TVP7002_WRITE }, | ||
132 | { 0x32, 0x18, TVP7002_RESERVED }, | ||
133 | { 0x33, 0x60, TVP7002_RESERVED }, | ||
134 | { TVP7002_MVIS_STRIPPER_W, 0xff, TVP7002_RESERVED }, | ||
135 | { TVP7002_VSYNC_ALGN, 0x10, TVP7002_WRITE }, | ||
136 | { TVP7002_SYNC_BYPASS, 0x00, TVP7002_WRITE }, | ||
137 | { TVP7002_L_FRAME_STAT_LSBS, 0xff, TVP7002_READ }, | ||
138 | { TVP7002_L_FRAME_STAT_MSBS, 0xff, TVP7002_READ }, | ||
139 | { TVP7002_CLK_L_STAT_LSBS, 0xff, TVP7002_READ }, | ||
140 | { TVP7002_CLK_L_STAT_MSBS, 0xff, TVP7002_READ }, | ||
141 | { TVP7002_HSYNC_W, 0xff, TVP7002_READ }, | ||
142 | { TVP7002_VSYNC_W, 0xff, TVP7002_READ }, | ||
143 | { TVP7002_L_LENGTH_TOL, 0x03, TVP7002_WRITE }, | ||
144 | { 0x3e, 0x60, TVP7002_RESERVED }, | ||
145 | { TVP7002_VIDEO_BWTH_CTL, 0x01, TVP7002_WRITE }, | ||
146 | { TVP7002_AVID_START_PIXEL_LSBS, 0x01, TVP7002_WRITE }, | ||
147 | { TVP7002_AVID_START_PIXEL_MSBS, 0x2c, TVP7002_WRITE }, | ||
148 | { TVP7002_AVID_STOP_PIXEL_LSBS, 0x06, TVP7002_WRITE }, | ||
149 | { TVP7002_AVID_STOP_PIXEL_MSBS, 0x2c, TVP7002_WRITE }, | ||
150 | { TVP7002_VBLK_F_0_START_L_OFF, 0x05, TVP7002_WRITE }, | ||
151 | { TVP7002_VBLK_F_1_START_L_OFF, 0x00, TVP7002_WRITE }, | ||
152 | { TVP7002_VBLK_F_0_DURATION, 0x1e, TVP7002_WRITE }, | ||
153 | { TVP7002_VBLK_F_1_DURATION, 0x00, TVP7002_WRITE }, | ||
154 | { TVP7002_FBIT_F_0_START_L_OFF, 0x00, TVP7002_WRITE }, | ||
155 | { TVP7002_FBIT_F_1_START_L_OFF, 0x00, TVP7002_WRITE }, | ||
156 | { TVP7002_YUV_Y_G_COEF_LSBS, 0xe3, TVP7002_WRITE }, | ||
157 | { TVP7002_YUV_Y_G_COEF_MSBS, 0x16, TVP7002_WRITE }, | ||
158 | { TVP7002_YUV_Y_B_COEF_LSBS, 0x4f, TVP7002_WRITE }, | ||
159 | { TVP7002_YUV_Y_B_COEF_MSBS, 0x02, TVP7002_WRITE }, | ||
160 | { TVP7002_YUV_Y_R_COEF_LSBS, 0xce, TVP7002_WRITE }, | ||
161 | { TVP7002_YUV_Y_R_COEF_MSBS, 0x06, TVP7002_WRITE }, | ||
162 | { TVP7002_YUV_U_G_COEF_LSBS, 0xab, TVP7002_WRITE }, | ||
163 | { TVP7002_YUV_U_G_COEF_MSBS, 0xf3, TVP7002_WRITE }, | ||
164 | { TVP7002_YUV_U_B_COEF_LSBS, 0x00, TVP7002_WRITE }, | ||
165 | { TVP7002_YUV_U_B_COEF_MSBS, 0x10, TVP7002_WRITE }, | ||
166 | { TVP7002_YUV_U_R_COEF_LSBS, 0x55, TVP7002_WRITE }, | ||
167 | { TVP7002_YUV_U_R_COEF_MSBS, 0xfc, TVP7002_WRITE }, | ||
168 | { TVP7002_YUV_V_G_COEF_LSBS, 0x78, TVP7002_WRITE }, | ||
169 | { TVP7002_YUV_V_G_COEF_MSBS, 0xf1, TVP7002_WRITE }, | ||
170 | { TVP7002_YUV_V_B_COEF_LSBS, 0x88, TVP7002_WRITE }, | ||
171 | { TVP7002_YUV_V_B_COEF_MSBS, 0xfe, TVP7002_WRITE }, | ||
172 | { TVP7002_YUV_V_R_COEF_LSBS, 0x00, TVP7002_WRITE }, | ||
173 | { TVP7002_YUV_V_R_COEF_MSBS, 0x10, TVP7002_WRITE }, | ||
174 | /* This signals end of register values */ | ||
175 | { TVP7002_EOR, 0xff, TVP7002_RESERVED } | ||
176 | }; | ||
177 | |||
178 | /* Register parameters for 480P */ | ||
179 | static const struct i2c_reg_value tvp7002_parms_480P[] = { | ||
180 | { TVP7002_HPLL_FDBK_DIV_MSBS, 0x35, TVP7002_WRITE }, | ||
181 | { TVP7002_HPLL_FDBK_DIV_LSBS, 0x0a, TVP7002_WRITE }, | ||
182 | { TVP7002_HPLL_CRTL, 0x02, TVP7002_WRITE }, | ||
183 | { TVP7002_HPLL_PHASE_SEL, 0x14, TVP7002_WRITE }, | ||
184 | { TVP7002_AVID_START_PIXEL_LSBS, 0x91, TVP7002_WRITE }, | ||
185 | { TVP7002_AVID_START_PIXEL_MSBS, 0x00, TVP7002_WRITE }, | ||
186 | { TVP7002_AVID_STOP_PIXEL_LSBS, 0x0B, TVP7002_WRITE }, | ||
187 | { TVP7002_AVID_STOP_PIXEL_MSBS, 0x00, TVP7002_WRITE }, | ||
188 | { TVP7002_VBLK_F_0_START_L_OFF, 0x03, TVP7002_WRITE }, | ||
189 | { TVP7002_VBLK_F_1_START_L_OFF, 0x01, TVP7002_WRITE }, | ||
190 | { TVP7002_VBLK_F_0_DURATION, 0x13, TVP7002_WRITE }, | ||
191 | { TVP7002_VBLK_F_1_DURATION, 0x13, TVP7002_WRITE }, | ||
192 | { TVP7002_ALC_PLACEMENT, 0x18, TVP7002_WRITE }, | ||
193 | { TVP7002_CLAMP_START, 0x06, TVP7002_WRITE }, | ||
194 | { TVP7002_CLAMP_W, 0x10, TVP7002_WRITE }, | ||
195 | { TVP7002_HPLL_PRE_COAST, 0x03, TVP7002_WRITE }, | ||
196 | { TVP7002_HPLL_POST_COAST, 0x03, TVP7002_WRITE }, | ||
197 | { TVP7002_EOR, 0xff, TVP7002_RESERVED } | ||
198 | }; | ||
199 | |||
200 | /* Register parameters for 576P */ | ||
201 | static const struct i2c_reg_value tvp7002_parms_576P[] = { | ||
202 | { TVP7002_HPLL_FDBK_DIV_MSBS, 0x36, TVP7002_WRITE }, | ||
203 | { TVP7002_HPLL_FDBK_DIV_LSBS, 0x00, TVP7002_WRITE }, | ||
204 | { TVP7002_HPLL_CRTL, 0x18, TVP7002_WRITE }, | ||
205 | { TVP7002_HPLL_PHASE_SEL, 0x14, TVP7002_WRITE }, | ||
206 | { TVP7002_AVID_START_PIXEL_LSBS, 0x9B, TVP7002_WRITE }, | ||
207 | { TVP7002_AVID_START_PIXEL_MSBS, 0x00, TVP7002_WRITE }, | ||
208 | { TVP7002_AVID_STOP_PIXEL_LSBS, 0x0F, TVP7002_WRITE }, | ||
209 | { TVP7002_AVID_STOP_PIXEL_MSBS, 0x00, TVP7002_WRITE }, | ||
210 | { TVP7002_VBLK_F_0_START_L_OFF, 0x00, TVP7002_WRITE }, | ||
211 | { TVP7002_VBLK_F_1_START_L_OFF, 0x00, TVP7002_WRITE }, | ||
212 | { TVP7002_VBLK_F_0_DURATION, 0x2D, TVP7002_WRITE }, | ||
213 | { TVP7002_VBLK_F_1_DURATION, 0x00, TVP7002_WRITE }, | ||
214 | { TVP7002_ALC_PLACEMENT, 0x18, TVP7002_WRITE }, | ||
215 | { TVP7002_CLAMP_START, 0x06, TVP7002_WRITE }, | ||
216 | { TVP7002_CLAMP_W, 0x10, TVP7002_WRITE }, | ||
217 | { TVP7002_HPLL_PRE_COAST, 0x03, TVP7002_WRITE }, | ||
218 | { TVP7002_HPLL_POST_COAST, 0x03, TVP7002_WRITE }, | ||
219 | { TVP7002_EOR, 0xff, TVP7002_RESERVED } | ||
220 | }; | ||
221 | |||
222 | /* Register parameters for 1080I60 */ | ||
223 | static const struct i2c_reg_value tvp7002_parms_1080I60[] = { | ||
224 | { TVP7002_HPLL_FDBK_DIV_MSBS, 0x89, TVP7002_WRITE }, | ||
225 | { TVP7002_HPLL_FDBK_DIV_LSBS, 0x08, TVP7002_WRITE }, | ||
226 | { TVP7002_HPLL_CRTL, 0x98, TVP7002_WRITE }, | ||
227 | { TVP7002_HPLL_PHASE_SEL, 0x14, TVP7002_WRITE }, | ||
228 | { TVP7002_AVID_START_PIXEL_LSBS, 0x06, TVP7002_WRITE }, | ||
229 | { TVP7002_AVID_START_PIXEL_MSBS, 0x01, TVP7002_WRITE }, | ||
230 | { TVP7002_AVID_STOP_PIXEL_LSBS, 0x8a, TVP7002_WRITE }, | ||
231 | { TVP7002_AVID_STOP_PIXEL_MSBS, 0x08, TVP7002_WRITE }, | ||
232 | { TVP7002_VBLK_F_0_START_L_OFF, 0x02, TVP7002_WRITE }, | ||
233 | { TVP7002_VBLK_F_1_START_L_OFF, 0x02, TVP7002_WRITE }, | ||
234 | { TVP7002_VBLK_F_0_DURATION, 0x16, TVP7002_WRITE }, | ||
235 | { TVP7002_VBLK_F_1_DURATION, 0x17, TVP7002_WRITE }, | ||
236 | { TVP7002_ALC_PLACEMENT, 0x5a, TVP7002_WRITE }, | ||
237 | { TVP7002_CLAMP_START, 0x32, TVP7002_WRITE }, | ||
238 | { TVP7002_CLAMP_W, 0x20, TVP7002_WRITE }, | ||
239 | { TVP7002_HPLL_PRE_COAST, 0x01, TVP7002_WRITE }, | ||
240 | { TVP7002_HPLL_POST_COAST, 0x00, TVP7002_WRITE }, | ||
241 | { TVP7002_EOR, 0xff, TVP7002_RESERVED } | ||
242 | }; | ||
243 | |||
244 | /* Register parameters for 1080P60 */ | ||
245 | static const struct i2c_reg_value tvp7002_parms_1080P60[] = { | ||
246 | { TVP7002_HPLL_FDBK_DIV_MSBS, 0x89, TVP7002_WRITE }, | ||
247 | { TVP7002_HPLL_FDBK_DIV_LSBS, 0x08, TVP7002_WRITE }, | ||
248 | { TVP7002_HPLL_CRTL, 0xE0, TVP7002_WRITE }, | ||
249 | { TVP7002_HPLL_PHASE_SEL, 0x14, TVP7002_WRITE }, | ||
250 | { TVP7002_AVID_START_PIXEL_LSBS, 0x06, TVP7002_WRITE }, | ||
251 | { TVP7002_AVID_START_PIXEL_MSBS, 0x01, TVP7002_WRITE }, | ||
252 | { TVP7002_AVID_STOP_PIXEL_LSBS, 0x8a, TVP7002_WRITE }, | ||
253 | { TVP7002_AVID_STOP_PIXEL_MSBS, 0x08, TVP7002_WRITE }, | ||
254 | { TVP7002_VBLK_F_0_START_L_OFF, 0x02, TVP7002_WRITE }, | ||
255 | { TVP7002_VBLK_F_1_START_L_OFF, 0x02, TVP7002_WRITE }, | ||
256 | { TVP7002_VBLK_F_0_DURATION, 0x16, TVP7002_WRITE }, | ||
257 | { TVP7002_VBLK_F_1_DURATION, 0x17, TVP7002_WRITE }, | ||
258 | { TVP7002_ALC_PLACEMENT, 0x5a, TVP7002_WRITE }, | ||
259 | { TVP7002_CLAMP_START, 0x32, TVP7002_WRITE }, | ||
260 | { TVP7002_CLAMP_W, 0x20, TVP7002_WRITE }, | ||
261 | { TVP7002_HPLL_PRE_COAST, 0x01, TVP7002_WRITE }, | ||
262 | { TVP7002_HPLL_POST_COAST, 0x00, TVP7002_WRITE }, | ||
263 | { TVP7002_EOR, 0xff, TVP7002_RESERVED } | ||
264 | }; | ||
265 | |||
266 | /* Register parameters for 1080I50 */ | ||
267 | static const struct i2c_reg_value tvp7002_parms_1080I50[] = { | ||
268 | { TVP7002_HPLL_FDBK_DIV_MSBS, 0xa5, TVP7002_WRITE }, | ||
269 | { TVP7002_HPLL_FDBK_DIV_LSBS, 0x00, TVP7002_WRITE }, | ||
270 | { TVP7002_HPLL_CRTL, 0x98, TVP7002_WRITE }, | ||
271 | { TVP7002_HPLL_PHASE_SEL, 0x14, TVP7002_WRITE }, | ||
272 | { TVP7002_AVID_START_PIXEL_LSBS, 0x06, TVP7002_WRITE }, | ||
273 | { TVP7002_AVID_START_PIXEL_MSBS, 0x01, TVP7002_WRITE }, | ||
274 | { TVP7002_AVID_STOP_PIXEL_LSBS, 0x8a, TVP7002_WRITE }, | ||
275 | { TVP7002_AVID_STOP_PIXEL_MSBS, 0x08, TVP7002_WRITE }, | ||
276 | { TVP7002_VBLK_F_0_START_L_OFF, 0x02, TVP7002_WRITE }, | ||
277 | { TVP7002_VBLK_F_1_START_L_OFF, 0x02, TVP7002_WRITE }, | ||
278 | { TVP7002_VBLK_F_0_DURATION, 0x16, TVP7002_WRITE }, | ||
279 | { TVP7002_VBLK_F_1_DURATION, 0x17, TVP7002_WRITE }, | ||
280 | { TVP7002_ALC_PLACEMENT, 0x5a, TVP7002_WRITE }, | ||
281 | { TVP7002_CLAMP_START, 0x32, TVP7002_WRITE }, | ||
282 | { TVP7002_CLAMP_W, 0x20, TVP7002_WRITE }, | ||
283 | { TVP7002_HPLL_PRE_COAST, 0x01, TVP7002_WRITE }, | ||
284 | { TVP7002_HPLL_POST_COAST, 0x00, TVP7002_WRITE }, | ||
285 | { TVP7002_EOR, 0xff, TVP7002_RESERVED } | ||
286 | }; | ||
287 | |||
288 | /* Register parameters for 720P60 */ | ||
289 | static const struct i2c_reg_value tvp7002_parms_720P60[] = { | ||
290 | { TVP7002_HPLL_FDBK_DIV_MSBS, 0x67, TVP7002_WRITE }, | ||
291 | { TVP7002_HPLL_FDBK_DIV_LSBS, 0x02, TVP7002_WRITE }, | ||
292 | { TVP7002_HPLL_CRTL, 0xa0, TVP7002_WRITE }, | ||
293 | { TVP7002_HPLL_PHASE_SEL, 0x16, TVP7002_WRITE }, | ||
294 | { TVP7002_AVID_START_PIXEL_LSBS, 0x47, TVP7002_WRITE }, | ||
295 | { TVP7002_AVID_START_PIXEL_MSBS, 0x01, TVP7002_WRITE }, | ||
296 | { TVP7002_AVID_STOP_PIXEL_LSBS, 0x4B, TVP7002_WRITE }, | ||
297 | { TVP7002_AVID_STOP_PIXEL_MSBS, 0x06, TVP7002_WRITE }, | ||
298 | { TVP7002_VBLK_F_0_START_L_OFF, 0x05, TVP7002_WRITE }, | ||
299 | { TVP7002_VBLK_F_1_START_L_OFF, 0x00, TVP7002_WRITE }, | ||
300 | { TVP7002_VBLK_F_0_DURATION, 0x2D, TVP7002_WRITE }, | ||
301 | { TVP7002_VBLK_F_1_DURATION, 0x00, TVP7002_WRITE }, | ||
302 | { TVP7002_ALC_PLACEMENT, 0x5a, TVP7002_WRITE }, | ||
303 | { TVP7002_CLAMP_START, 0x32, TVP7002_WRITE }, | ||
304 | { TVP7002_CLAMP_W, 0x20, TVP7002_WRITE }, | ||
305 | { TVP7002_HPLL_PRE_COAST, 0x00, TVP7002_WRITE }, | ||
306 | { TVP7002_HPLL_POST_COAST, 0x00, TVP7002_WRITE }, | ||
307 | { TVP7002_EOR, 0xff, TVP7002_RESERVED } | ||
308 | }; | ||
309 | |||
310 | /* Register parameters for 720P50 */ | ||
311 | static const struct i2c_reg_value tvp7002_parms_720P50[] = { | ||
312 | { TVP7002_HPLL_FDBK_DIV_MSBS, 0x7b, TVP7002_WRITE }, | ||
313 | { TVP7002_HPLL_FDBK_DIV_LSBS, 0x0c, TVP7002_WRITE }, | ||
314 | { TVP7002_HPLL_CRTL, 0x98, TVP7002_WRITE }, | ||
315 | { TVP7002_HPLL_PHASE_SEL, 0x16, TVP7002_WRITE }, | ||
316 | { TVP7002_AVID_START_PIXEL_LSBS, 0x47, TVP7002_WRITE }, | ||
317 | { TVP7002_AVID_START_PIXEL_MSBS, 0x01, TVP7002_WRITE }, | ||
318 | { TVP7002_AVID_STOP_PIXEL_LSBS, 0x4B, TVP7002_WRITE }, | ||
319 | { TVP7002_AVID_STOP_PIXEL_MSBS, 0x06, TVP7002_WRITE }, | ||
320 | { TVP7002_VBLK_F_0_START_L_OFF, 0x05, TVP7002_WRITE }, | ||
321 | { TVP7002_VBLK_F_1_START_L_OFF, 0x00, TVP7002_WRITE }, | ||
322 | { TVP7002_VBLK_F_0_DURATION, 0x2D, TVP7002_WRITE }, | ||
323 | { TVP7002_VBLK_F_1_DURATION, 0x00, TVP7002_WRITE }, | ||
324 | { TVP7002_ALC_PLACEMENT, 0x5a, TVP7002_WRITE }, | ||
325 | { TVP7002_CLAMP_START, 0x32, TVP7002_WRITE }, | ||
326 | { TVP7002_CLAMP_W, 0x20, TVP7002_WRITE }, | ||
327 | { TVP7002_HPLL_PRE_COAST, 0x01, TVP7002_WRITE }, | ||
328 | { TVP7002_HPLL_POST_COAST, 0x00, TVP7002_WRITE }, | ||
329 | { TVP7002_EOR, 0xff, TVP7002_RESERVED } | ||
330 | }; | ||
331 | |||
332 | /* Struct list for available formats */ | ||
333 | static const struct v4l2_fmtdesc tvp7002_fmt_list[] = { | ||
334 | { | ||
335 | .index = 0, | ||
336 | .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
337 | .flags = 0, | ||
338 | .description = "8-bit UYVY 4:2:2 Format", | ||
339 | .pixelformat = V4L2_PIX_FMT_UYVY, | ||
340 | }, | ||
341 | }; | ||
342 | |||
343 | #define NUM_FORMATS ARRAY_SIZE(tvp7002_fmt_list) | ||
344 | |||
345 | /* Preset definition for handling device operation */ | ||
346 | struct tvp7002_preset_definition { | ||
347 | u32 preset; | ||
348 | const struct i2c_reg_value *p_settings; | ||
349 | enum v4l2_colorspace color_space; | ||
350 | enum v4l2_field scanmode; | ||
351 | u16 progressive; | ||
352 | u16 lines_per_frame; | ||
353 | u16 cpl_min; | ||
354 | u16 cpl_max; | ||
355 | }; | ||
356 | |||
357 | /* Struct list for digital video presets */ | ||
358 | static const struct tvp7002_preset_definition tvp7002_presets[] = { | ||
359 | { | ||
360 | V4L2_DV_720P60, | ||
361 | tvp7002_parms_720P60, | ||
362 | V4L2_COLORSPACE_REC709, | ||
363 | V4L2_FIELD_NONE, | ||
364 | 1, | ||
365 | 0x2EE, | ||
366 | 135, | ||
367 | 153 | ||
368 | }, | ||
369 | { | ||
370 | V4L2_DV_1080I60, | ||
371 | tvp7002_parms_1080I60, | ||
372 | V4L2_COLORSPACE_REC709, | ||
373 | V4L2_FIELD_INTERLACED, | ||
374 | 0, | ||
375 | 0x465, | ||
376 | 181, | ||
377 | 205 | ||
378 | }, | ||
379 | { | ||
380 | V4L2_DV_1080I50, | ||
381 | tvp7002_parms_1080I50, | ||
382 | V4L2_COLORSPACE_REC709, | ||
383 | V4L2_FIELD_INTERLACED, | ||
384 | 0, | ||
385 | 0x465, | ||
386 | 217, | ||
387 | 245 | ||
388 | }, | ||
389 | { | ||
390 | V4L2_DV_720P50, | ||
391 | tvp7002_parms_720P50, | ||
392 | V4L2_COLORSPACE_REC709, | ||
393 | V4L2_FIELD_NONE, | ||
394 | 1, | ||
395 | 0x2EE, | ||
396 | 163, | ||
397 | 183 | ||
398 | }, | ||
399 | { | ||
400 | V4L2_DV_1080P60, | ||
401 | tvp7002_parms_1080P60, | ||
402 | V4L2_COLORSPACE_REC709, | ||
403 | V4L2_FIELD_NONE, | ||
404 | 1, | ||
405 | 0x465, | ||
406 | 90, | ||
407 | 102 | ||
408 | }, | ||
409 | { | ||
410 | V4L2_DV_480P59_94, | ||
411 | tvp7002_parms_480P, | ||
412 | V4L2_COLORSPACE_SMPTE170M, | ||
413 | V4L2_FIELD_NONE, | ||
414 | 1, | ||
415 | 0x20D, | ||
416 | 0xffff, | ||
417 | 0xffff | ||
418 | }, | ||
419 | { | ||
420 | V4L2_DV_576P50, | ||
421 | tvp7002_parms_576P, | ||
422 | V4L2_COLORSPACE_SMPTE170M, | ||
423 | V4L2_FIELD_NONE, | ||
424 | 1, | ||
425 | 0x271, | ||
426 | 0xffff, | ||
427 | 0xffff | ||
428 | } | ||
429 | }; | ||
430 | |||
431 | #define NUM_PRESETS ARRAY_SIZE(tvp7002_presets) | ||
432 | |||
433 | /* Device definition */ | ||
434 | struct tvp7002 { | ||
435 | struct v4l2_subdev sd; | ||
436 | const struct tvp7002_config *pdata; | ||
437 | |||
438 | int ver; | ||
439 | int streaming; | ||
440 | |||
441 | struct v4l2_pix_format pix; | ||
442 | const struct tvp7002_preset_definition *current_preset; | ||
443 | u8 gain; | ||
444 | }; | ||
445 | |||
446 | /* | ||
447 | * to_tvp7002 - Obtain device handler TVP7002 | ||
448 | * @sd: ptr to v4l2_subdev struct | ||
449 | * | ||
450 | * Returns device handler tvp7002. | ||
451 | */ | ||
452 | static inline struct tvp7002 *to_tvp7002(struct v4l2_subdev *sd) | ||
453 | { | ||
454 | return container_of(sd, struct tvp7002, sd); | ||
455 | } | ||
456 | |||
457 | /* | ||
458 | * tvp7002_read - Read a value from a register in an TVP7002 | ||
459 | * @sd: ptr to v4l2_subdev struct | ||
460 | * @reg: TVP7002 register address | ||
461 | * @dst: pointer to 8-bit destination | ||
462 | * | ||
463 | * Returns value read if successful, or non-zero (-1) otherwise. | ||
464 | */ | ||
465 | static int tvp7002_read(struct v4l2_subdev *sd, u8 addr, u8 *dst) | ||
466 | { | ||
467 | struct i2c_client *c = v4l2_get_subdevdata(sd); | ||
468 | int retry; | ||
469 | int error; | ||
470 | |||
471 | for (retry = 0; retry < I2C_RETRY_COUNT; retry++) { | ||
472 | error = i2c_smbus_read_byte_data(c, addr); | ||
473 | |||
474 | if (error >= 0) { | ||
475 | *dst = (u8)error; | ||
476 | return 0; | ||
477 | } | ||
478 | |||
479 | msleep_interruptible(10); | ||
480 | } | ||
481 | v4l2_err(sd, "TVP7002 read error %d\n", error); | ||
482 | return error; | ||
483 | } | ||
484 | |||
485 | /* | ||
486 | * tvp7002_read_err() - Read a register value with error code | ||
487 | * @sd: pointer to standard V4L2 sub-device structure | ||
488 | * @reg: destination register | ||
489 | * @val: value to be read | ||
490 | * @error: pointer to error value | ||
491 | * | ||
492 | * Read a value in a register and save error value in pointer. | ||
493 | * Also update the register table if successful | ||
494 | */ | ||
495 | static inline void tvp7002_read_err(struct v4l2_subdev *sd, u8 reg, | ||
496 | u8 *dst, int *err) | ||
497 | { | ||
498 | if (!*err) | ||
499 | *err = tvp7002_read(sd, reg, dst); | ||
500 | } | ||
501 | |||
502 | /* | ||
503 | * tvp7002_write() - Write a value to a register in TVP7002 | ||
504 | * @sd: ptr to v4l2_subdev struct | ||
505 | * @addr: TVP7002 register address | ||
506 | * @value: value to be written to the register | ||
507 | * | ||
508 | * Write a value to a register in an TVP7002 decoder device. | ||
509 | * Returns zero if successful, or non-zero otherwise. | ||
510 | */ | ||
511 | static int tvp7002_write(struct v4l2_subdev *sd, u8 addr, u8 value) | ||
512 | { | ||
513 | struct i2c_client *c; | ||
514 | int retry; | ||
515 | int error; | ||
516 | |||
517 | c = v4l2_get_subdevdata(sd); | ||
518 | |||
519 | for (retry = 0; retry < I2C_RETRY_COUNT; retry++) { | ||
520 | error = i2c_smbus_write_byte_data(c, addr, value); | ||
521 | |||
522 | if (error >= 0) | ||
523 | return 0; | ||
524 | |||
525 | v4l2_warn(sd, "Write: retry ... %d\n", retry); | ||
526 | msleep_interruptible(10); | ||
527 | } | ||
528 | v4l2_err(sd, "TVP7002 write error %d\n", error); | ||
529 | return error; | ||
530 | } | ||
531 | |||
532 | /* | ||
533 | * tvp7002_write_err() - Write a register value with error code | ||
534 | * @sd: pointer to standard V4L2 sub-device structure | ||
535 | * @reg: destination register | ||
536 | * @val: value to be written | ||
537 | * @error: pointer to error value | ||
538 | * | ||
539 | * Write a value in a register and save error value in pointer. | ||
540 | * Also update the register table if successful | ||
541 | */ | ||
542 | static inline void tvp7002_write_err(struct v4l2_subdev *sd, u8 reg, | ||
543 | u8 val, int *err) | ||
544 | { | ||
545 | if (!*err) | ||
546 | *err = tvp7002_write(sd, reg, val); | ||
547 | } | ||
548 | |||
549 | /* | ||
550 | * tvp7002_g_chip_ident() - Get chip identification number | ||
551 | * @sd: ptr to v4l2_subdev struct | ||
552 | * @chip: ptr to v4l2_dbg_chip_ident struct | ||
553 | * | ||
554 | * Obtains the chip's identification number. | ||
555 | * Returns zero or -EINVAL if read operation fails. | ||
556 | */ | ||
557 | static int tvp7002_g_chip_ident(struct v4l2_subdev *sd, | ||
558 | struct v4l2_dbg_chip_ident *chip) | ||
559 | { | ||
560 | u8 rev; | ||
561 | int error; | ||
562 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
563 | |||
564 | error = tvp7002_read(sd, TVP7002_CHIP_REV, &rev); | ||
565 | |||
566 | if (error < 0) | ||
567 | return error; | ||
568 | |||
569 | return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_TVP7002, rev); | ||
570 | } | ||
571 | |||
572 | /* | ||
573 | * tvp7002_write_inittab() - Write initialization values | ||
574 | * @sd: ptr to v4l2_subdev struct | ||
575 | * @regs: ptr to i2c_reg_value struct | ||
576 | * | ||
577 | * Write initialization values. | ||
578 | * Returns zero or -EINVAL if read operation fails. | ||
579 | */ | ||
580 | static int tvp7002_write_inittab(struct v4l2_subdev *sd, | ||
581 | const struct i2c_reg_value *regs) | ||
582 | { | ||
583 | int error = 0; | ||
584 | |||
585 | /* Initialize the first (defined) registers */ | ||
586 | while (TVP7002_EOR != regs->reg) { | ||
587 | if (TVP7002_WRITE == regs->type) | ||
588 | tvp7002_write_err(sd, regs->reg, regs->value, &error); | ||
589 | regs++; | ||
590 | } | ||
591 | |||
592 | return error; | ||
593 | } | ||
594 | |||
595 | /* | ||
596 | * tvp7002_s_dv_preset() - Set digital video preset | ||
597 | * @sd: ptr to v4l2_subdev struct | ||
598 | * @std: ptr to v4l2_dv_preset struct | ||
599 | * | ||
600 | * Set the digital video preset for a TVP7002 decoder device. | ||
601 | * Returns zero when successful or -EINVAL if register access fails. | ||
602 | */ | ||
603 | static int tvp7002_s_dv_preset(struct v4l2_subdev *sd, | ||
604 | struct v4l2_dv_preset *dv_preset) | ||
605 | { | ||
606 | struct tvp7002 *device = to_tvp7002(sd); | ||
607 | u32 preset; | ||
608 | int i; | ||
609 | |||
610 | for (i = 0; i < NUM_PRESETS; i++) { | ||
611 | preset = tvp7002_presets[i].preset; | ||
612 | if (preset == dv_preset->preset) { | ||
613 | device->current_preset = &tvp7002_presets[i]; | ||
614 | return tvp7002_write_inittab(sd, tvp7002_presets[i].p_settings); | ||
615 | } | ||
616 | } | ||
617 | |||
618 | return -EINVAL; | ||
619 | } | ||
620 | |||
621 | /* | ||
622 | * tvp7002_g_ctrl() - Get a control | ||
623 | * @sd: ptr to v4l2_subdev struct | ||
624 | * @ctrl: ptr to v4l2_control struct | ||
625 | * | ||
626 | * Get a control for a TVP7002 decoder device. | ||
627 | * Returns zero when successful or -EINVAL if register access fails. | ||
628 | */ | ||
629 | static int tvp7002_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | ||
630 | { | ||
631 | struct tvp7002 *device = to_tvp7002(sd); | ||
632 | |||
633 | switch (ctrl->id) { | ||
634 | case V4L2_CID_GAIN: | ||
635 | ctrl->value = device->gain; | ||
636 | return 0; | ||
637 | default: | ||
638 | return -EINVAL; | ||
639 | } | ||
640 | } | ||
641 | |||
642 | /* | ||
643 | * tvp7002_s_ctrl() - Set a control | ||
644 | * @sd: ptr to v4l2_subdev struct | ||
645 | * @ctrl: ptr to v4l2_control struct | ||
646 | * | ||
647 | * Set a control in TVP7002 decoder device. | ||
648 | * Returns zero when successful or -EINVAL if register access fails. | ||
649 | */ | ||
650 | static int tvp7002_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | ||
651 | { | ||
652 | struct tvp7002 *device = to_tvp7002(sd); | ||
653 | int error = 0; | ||
654 | |||
655 | switch (ctrl->id) { | ||
656 | case V4L2_CID_GAIN: | ||
657 | tvp7002_write_err(sd, TVP7002_R_FINE_GAIN, | ||
658 | ctrl->value & 0xff, &error); | ||
659 | tvp7002_write_err(sd, TVP7002_G_FINE_GAIN, | ||
660 | ctrl->value & 0xff, &error); | ||
661 | tvp7002_write_err(sd, TVP7002_B_FINE_GAIN, | ||
662 | ctrl->value & 0xff, &error); | ||
663 | |||
664 | if (error < 0) | ||
665 | return error; | ||
666 | |||
667 | /* Set only after knowing there is no error */ | ||
668 | device->gain = ctrl->value & 0xff; | ||
669 | return 0; | ||
670 | default: | ||
671 | return -EINVAL; | ||
672 | } | ||
673 | } | ||
674 | |||
675 | /* | ||
676 | * tvp7002_queryctrl() - Query a control | ||
677 | * @sd: ptr to v4l2_subdev struct | ||
678 | * @ctrl: ptr to v4l2_queryctrl struct | ||
679 | * | ||
680 | * Query a control of a TVP7002 decoder device. | ||
681 | * Returns zero when successful or -EINVAL if register read fails. | ||
682 | */ | ||
683 | static int tvp7002_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) | ||
684 | { | ||
685 | switch (qc->id) { | ||
686 | case V4L2_CID_GAIN: | ||
687 | /* | ||
688 | * Gain is supported [0-255, default=0, step=1] | ||
689 | */ | ||
690 | return v4l2_ctrl_query_fill(qc, 0, 255, 1, 0); | ||
691 | default: | ||
692 | return -EINVAL; | ||
693 | } | ||
694 | } | ||
695 | |||
696 | /* | ||
697 | * tvp7002_try_fmt_cap() - V4L2 decoder interface handler for try_fmt | ||
698 | * @sd: pointer to standard V4L2 sub-device structure | ||
699 | * @f: pointer to standard V4L2 VIDIOC_TRY_FMT ioctl structure | ||
700 | * | ||
701 | * Implement the VIDIOC_TRY_FMT ioctl for the CAPTURE buffer type. This | ||
702 | * ioctl is used to negotiate the image capture size and pixel format | ||
703 | * without actually making it take effect. | ||
704 | */ | ||
705 | static int tvp7002_try_fmt_cap(struct v4l2_subdev *sd, struct v4l2_format *f) | ||
706 | { | ||
707 | struct tvp7002 *device = to_tvp7002(sd); | ||
708 | struct v4l2_dv_enum_preset e_preset; | ||
709 | struct v4l2_pix_format *pix; | ||
710 | int error = 0; | ||
711 | |||
712 | pix = &f->fmt.pix; | ||
713 | |||
714 | /* Calculate height and width based on current standard */ | ||
715 | error = v4l_fill_dv_preset_info(device->current_preset->preset, &e_preset); | ||
716 | if (error) | ||
717 | return -EINVAL; | ||
718 | |||
719 | pix->width = e_preset.width; | ||
720 | pix->height = e_preset.height; | ||
721 | pix->pixelformat = V4L2_PIX_FMT_UYVY; | ||
722 | pix->field = device->current_preset->scanmode; | ||
723 | pix->bytesperline = pix->width * 2; | ||
724 | pix->sizeimage = pix->bytesperline * pix->height; | ||
725 | pix->colorspace = device->current_preset->color_space; | ||
726 | pix->priv = 0; | ||
727 | |||
728 | v4l2_dbg(1, debug, sd, "Try FMT: pixelformat - %s, bytesperline - %d" | ||
729 | "Width - %d, Height - %d", "8-bit UYVY 4:2:2 Format", | ||
730 | pix->bytesperline, pix->width, pix->height); | ||
731 | return error; | ||
732 | } | ||
733 | |||
734 | /* | ||
735 | * tvp7002_s_fmt() - V4L2 decoder interface handler for s_fmt | ||
736 | * @sd: pointer to standard V4L2 sub-device structure | ||
737 | * @f: pointer to standard V4L2 VIDIOC_S_FMT ioctl structure | ||
738 | * | ||
739 | * If the requested format is supported, configures the HW to use that | ||
740 | * format, returns error code if format not supported or HW can't be | ||
741 | * correctly configured. | ||
742 | */ | ||
743 | static int tvp7002_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | ||
744 | { | ||
745 | struct tvp7002 *decoder = to_tvp7002(sd); | ||
746 | int rval; | ||
747 | |||
748 | rval = tvp7002_try_fmt_cap(sd, f); | ||
749 | if (!rval) | ||
750 | decoder->pix = f->fmt.pix; | ||
751 | return rval; | ||
752 | } | ||
753 | |||
754 | /* | ||
755 | * tvp7002_g_fmt() - V4L2 decoder interface handler for tvp7002_g_fmt | ||
756 | * @sd: pointer to standard V4L2 sub-device structure | ||
757 | * @f: pointer to standard V4L2 v4l2_format structure | ||
758 | * | ||
759 | * Returns the decoder's current pixel format in the v4l2_format | ||
760 | * parameter. | ||
761 | */ | ||
762 | static int tvp7002_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | ||
763 | { | ||
764 | struct tvp7002 *decoder = to_tvp7002(sd); | ||
765 | |||
766 | f->fmt.pix = decoder->pix; | ||
767 | |||
768 | v4l2_dbg(1, debug, sd, "Current FMT: bytesperline - %d" | ||
769 | "Width - %d, Height - %d", | ||
770 | decoder->pix.bytesperline, | ||
771 | decoder->pix.width, decoder->pix.height); | ||
772 | return 0; | ||
773 | } | ||
774 | |||
775 | /* | ||
776 | * tvp7002_query_dv_preset() - query DV preset | ||
777 | * @sd: pointer to standard V4L2 sub-device structure | ||
778 | * @std_id: standard V4L2 v4l2_dv_preset | ||
779 | * | ||
780 | * Returns the current DV preset by TVP7002. If no active input is | ||
781 | * detected, returns -EINVAL | ||
782 | */ | ||
783 | static int tvp7002_query_dv_preset(struct v4l2_subdev *sd, | ||
784 | struct v4l2_dv_preset *qpreset) | ||
785 | { | ||
786 | const struct tvp7002_preset_definition *presets = tvp7002_presets; | ||
787 | struct v4l2_dv_enum_preset e_preset; | ||
788 | struct tvp7002 *device; | ||
789 | u8 progressive; | ||
790 | u32 lpfr; | ||
791 | u32 cpln; | ||
792 | int error = 0; | ||
793 | u8 lpf_lsb; | ||
794 | u8 lpf_msb; | ||
795 | u8 cpl_lsb; | ||
796 | u8 cpl_msb; | ||
797 | int index; | ||
798 | |||
799 | device = to_tvp7002(sd); | ||
800 | |||
801 | /* Read standards from device registers */ | ||
802 | tvp7002_read_err(sd, TVP7002_L_FRAME_STAT_LSBS, &lpf_lsb, &error); | ||
803 | tvp7002_read_err(sd, TVP7002_L_FRAME_STAT_MSBS, &lpf_msb, &error); | ||
804 | |||
805 | if (error < 0) | ||
806 | return error; | ||
807 | |||
808 | tvp7002_read_err(sd, TVP7002_CLK_L_STAT_LSBS, &cpl_lsb, &error); | ||
809 | tvp7002_read_err(sd, TVP7002_CLK_L_STAT_MSBS, &cpl_msb, &error); | ||
810 | |||
811 | if (error < 0) | ||
812 | return error; | ||
813 | |||
814 | /* Get lines per frame, clocks per line and interlaced/progresive */ | ||
815 | lpfr = lpf_lsb | ((TVP7002_CL_MASK & lpf_msb) << TVP7002_CL_SHIFT); | ||
816 | cpln = cpl_lsb | ((TVP7002_CL_MASK & cpl_msb) << TVP7002_CL_SHIFT); | ||
817 | progressive = (lpf_msb & TVP7002_INPR_MASK) >> TVP7002_IP_SHIFT; | ||
818 | |||
819 | /* Do checking of video modes */ | ||
820 | for (index = 0; index < NUM_PRESETS; index++, presets++) | ||
821 | if (lpfr == presets->lines_per_frame && | ||
822 | progressive == presets->progressive) { | ||
823 | if (presets->cpl_min == 0xffff) | ||
824 | break; | ||
825 | if (cpln >= presets->cpl_min && cpln <= presets->cpl_max) | ||
826 | break; | ||
827 | } | ||
828 | |||
829 | if (index == NUM_PRESETS) { | ||
830 | v4l2_err(sd, "querystd error, lpf = %x, cpl = %x\n", | ||
831 | lpfr, cpln); | ||
832 | return -EINVAL; | ||
833 | } | ||
834 | |||
835 | if (v4l_fill_dv_preset_info(presets->preset, &e_preset)) | ||
836 | return -EINVAL; | ||
837 | |||
838 | /* Set values in found preset */ | ||
839 | qpreset->preset = presets->preset; | ||
840 | |||
841 | /* Update lines per frame and clocks per line info */ | ||
842 | v4l2_dbg(1, debug, sd, "Current preset: %d %d", | ||
843 | e_preset.width, e_preset.height); | ||
844 | return 0; | ||
845 | } | ||
846 | |||
847 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
848 | /* | ||
849 | * tvp7002_g_register() - Get the value of a register | ||
850 | * @sd: ptr to v4l2_subdev struct | ||
851 | * @vreg: ptr to v4l2_dbg_register struct | ||
852 | * | ||
853 | * Get the value of a TVP7002 decoder device register. | ||
854 | * Returns zero when successful, -EINVAL if register read fails or | ||
855 | * access to I2C client fails, -EPERM if the call is not allowed | ||
856 | * by diabled CAP_SYS_ADMIN. | ||
857 | */ | ||
858 | static int tvp7002_g_register(struct v4l2_subdev *sd, | ||
859 | struct v4l2_dbg_register *reg) | ||
860 | { | ||
861 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
862 | u8 val; | ||
863 | int ret; | ||
864 | |||
865 | if (!v4l2_chip_match_i2c_client(client, ®->match)) | ||
866 | return -EINVAL; | ||
867 | if (!capable(CAP_SYS_ADMIN)) | ||
868 | return -EPERM; | ||
869 | |||
870 | ret = tvp7002_read(sd, reg->reg & 0xff, &val); | ||
871 | reg->val = val; | ||
872 | return ret; | ||
873 | } | ||
874 | |||
875 | /* | ||
876 | * tvp7002_s_register() - set a control | ||
877 | * @sd: ptr to v4l2_subdev struct | ||
878 | * @ctrl: ptr to v4l2_control struct | ||
879 | * | ||
880 | * Get the value of a TVP7002 decoder device register. | ||
881 | * Returns zero when successful, -EINVAL if register read fails or | ||
882 | * -EPERM if call not allowed. | ||
883 | */ | ||
884 | static int tvp7002_s_register(struct v4l2_subdev *sd, | ||
885 | struct v4l2_dbg_register *reg) | ||
886 | { | ||
887 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
888 | |||
889 | if (!v4l2_chip_match_i2c_client(client, ®->match)) | ||
890 | return -EINVAL; | ||
891 | if (!capable(CAP_SYS_ADMIN)) | ||
892 | return -EPERM; | ||
893 | |||
894 | return tvp7002_write(sd, reg->reg & 0xff, reg->val & 0xff); | ||
895 | } | ||
896 | #endif | ||
897 | |||
898 | /* | ||
899 | * tvp7002_enum_fmt() - Enum supported formats | ||
900 | * @sd: pointer to standard V4L2 sub-device structure | ||
901 | * @enable: pointer to format struct | ||
902 | * | ||
903 | * Enumerate supported formats. | ||
904 | */ | ||
905 | |||
906 | static int tvp7002_enum_fmt(struct v4l2_subdev *sd, | ||
907 | struct v4l2_fmtdesc *fmtdesc) | ||
908 | { | ||
909 | /* Check requested format index is within range */ | ||
910 | if (fmtdesc->index < 0 || fmtdesc->index >= NUM_FORMATS) | ||
911 | return -EINVAL; | ||
912 | *fmtdesc = tvp7002_fmt_list[fmtdesc->index]; | ||
913 | |||
914 | return 0; | ||
915 | } | ||
916 | |||
917 | /* | ||
918 | * tvp7002_s_stream() - V4L2 decoder i/f handler for s_stream | ||
919 | * @sd: pointer to standard V4L2 sub-device structure | ||
920 | * @enable: streaming enable or disable | ||
921 | * | ||
922 | * Sets streaming to enable or disable, if possible. | ||
923 | */ | ||
924 | static int tvp7002_s_stream(struct v4l2_subdev *sd, int enable) | ||
925 | { | ||
926 | struct tvp7002 *device = to_tvp7002(sd); | ||
927 | int error = 0; | ||
928 | |||
929 | if (device->streaming == enable) | ||
930 | return 0; | ||
931 | |||
932 | if (enable) { | ||
933 | /* Set output state on (low impedance means stream on) */ | ||
934 | error = tvp7002_write(sd, TVP7002_MISC_CTL_2, 0x00); | ||
935 | device->streaming = enable; | ||
936 | } else { | ||
937 | /* Set output state off (high impedance means stream off) */ | ||
938 | error = tvp7002_write(sd, TVP7002_MISC_CTL_2, 0x03); | ||
939 | if (error) | ||
940 | v4l2_dbg(1, debug, sd, "Unable to stop streaming\n"); | ||
941 | |||
942 | device->streaming = enable; | ||
943 | } | ||
944 | |||
945 | return error; | ||
946 | } | ||
947 | |||
948 | /* | ||
949 | * tvp7002_log_status() - Print information about register settings | ||
950 | * @sd: ptr to v4l2_subdev struct | ||
951 | * | ||
952 | * Log register values of a TVP7002 decoder device. | ||
953 | * Returns zero or -EINVAL if read operation fails. | ||
954 | */ | ||
955 | static int tvp7002_log_status(struct v4l2_subdev *sd) | ||
956 | { | ||
957 | const struct tvp7002_preset_definition *presets = tvp7002_presets; | ||
958 | struct tvp7002 *device = to_tvp7002(sd); | ||
959 | struct v4l2_dv_enum_preset e_preset; | ||
960 | struct v4l2_dv_preset detected; | ||
961 | int i; | ||
962 | |||
963 | detected.preset = V4L2_DV_INVALID; | ||
964 | /* Find my current standard*/ | ||
965 | tvp7002_query_dv_preset(sd, &detected); | ||
966 | |||
967 | /* Print standard related code values */ | ||
968 | for (i = 0; i < NUM_PRESETS; i++, presets++) | ||
969 | if (presets->preset == detected.preset) | ||
970 | break; | ||
971 | |||
972 | if (v4l_fill_dv_preset_info(device->current_preset->preset, &e_preset)) | ||
973 | return -EINVAL; | ||
974 | |||
975 | v4l2_info(sd, "Selected DV Preset: %s\n", e_preset.name); | ||
976 | v4l2_info(sd, " Pixels per line: %u\n", e_preset.width); | ||
977 | v4l2_info(sd, " Lines per frame: %u\n\n", e_preset.height); | ||
978 | if (i == NUM_PRESETS) { | ||
979 | v4l2_info(sd, "Detected DV Preset: None\n"); | ||
980 | } else { | ||
981 | if (v4l_fill_dv_preset_info(presets->preset, &e_preset)) | ||
982 | return -EINVAL; | ||
983 | v4l2_info(sd, "Detected DV Preset: %s\n", e_preset.name); | ||
984 | v4l2_info(sd, " Pixels per line: %u\n", e_preset.width); | ||
985 | v4l2_info(sd, " Lines per frame: %u\n\n", e_preset.height); | ||
986 | } | ||
987 | v4l2_info(sd, "Streaming enabled: %s\n", | ||
988 | device->streaming ? "yes" : "no"); | ||
989 | |||
990 | /* Print the current value of the gain control */ | ||
991 | v4l2_info(sd, "Gain: %u\n", device->gain); | ||
992 | |||
993 | return 0; | ||
994 | } | ||
995 | |||
996 | /* V4L2 core operation handlers */ | ||
997 | static const struct v4l2_subdev_core_ops tvp7002_core_ops = { | ||
998 | .g_chip_ident = tvp7002_g_chip_ident, | ||
999 | .log_status = tvp7002_log_status, | ||
1000 | .g_ctrl = tvp7002_g_ctrl, | ||
1001 | .s_ctrl = tvp7002_s_ctrl, | ||
1002 | .queryctrl = tvp7002_queryctrl, | ||
1003 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
1004 | .g_register = tvp7002_g_register, | ||
1005 | .s_register = tvp7002_s_register, | ||
1006 | #endif | ||
1007 | }; | ||
1008 | |||
1009 | /* Specific video subsystem operation handlers */ | ||
1010 | static const struct v4l2_subdev_video_ops tvp7002_video_ops = { | ||
1011 | .s_dv_preset = tvp7002_s_dv_preset, | ||
1012 | .query_dv_preset = tvp7002_query_dv_preset, | ||
1013 | .s_stream = tvp7002_s_stream, | ||
1014 | .g_fmt = tvp7002_g_fmt, | ||
1015 | .s_fmt = tvp7002_s_fmt, | ||
1016 | .enum_fmt = tvp7002_enum_fmt, | ||
1017 | }; | ||
1018 | |||
1019 | /* V4L2 top level operation handlers */ | ||
1020 | static const struct v4l2_subdev_ops tvp7002_ops = { | ||
1021 | .core = &tvp7002_core_ops, | ||
1022 | .video = &tvp7002_video_ops, | ||
1023 | }; | ||
1024 | |||
1025 | static struct tvp7002 tvp7002_dev = { | ||
1026 | .streaming = 0, | ||
1027 | |||
1028 | .pix = { | ||
1029 | .width = 1280, | ||
1030 | .height = 720, | ||
1031 | .pixelformat = V4L2_PIX_FMT_UYVY, | ||
1032 | .field = V4L2_FIELD_NONE, | ||
1033 | .bytesperline = 1280 * 2, | ||
1034 | .sizeimage = 1280 * 2 * 720, | ||
1035 | .colorspace = V4L2_COLORSPACE_REC709, | ||
1036 | }, | ||
1037 | |||
1038 | .current_preset = tvp7002_presets, | ||
1039 | .gain = 0, | ||
1040 | }; | ||
1041 | |||
1042 | /* | ||
1043 | * tvp7002_probe - Probe a TVP7002 device | ||
1044 | * @sd: ptr to v4l2_subdev struct | ||
1045 | * @ctrl: ptr to i2c_device_id struct | ||
1046 | * | ||
1047 | * Initialize the TVP7002 device | ||
1048 | * Returns zero when successful, -EINVAL if register read fails or | ||
1049 | * -EIO if i2c access is not available. | ||
1050 | */ | ||
1051 | static int tvp7002_probe(struct i2c_client *c, const struct i2c_device_id *id) | ||
1052 | { | ||
1053 | struct v4l2_subdev *sd; | ||
1054 | struct tvp7002 *device; | ||
1055 | struct v4l2_dv_preset preset; | ||
1056 | int polarity_a; | ||
1057 | int polarity_b; | ||
1058 | u8 revision; | ||
1059 | |||
1060 | int error; | ||
1061 | |||
1062 | /* Check if the adapter supports the needed features */ | ||
1063 | if (!i2c_check_functionality(c->adapter, | ||
1064 | I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) | ||
1065 | return -EIO; | ||
1066 | |||
1067 | if (!c->dev.platform_data) { | ||
1068 | v4l_err(c, "No platform data!!\n"); | ||
1069 | return -ENODEV; | ||
1070 | } | ||
1071 | |||
1072 | device = kmalloc(sizeof(struct tvp7002), GFP_KERNEL); | ||
1073 | |||
1074 | if (!device) | ||
1075 | return -ENOMEM; | ||
1076 | |||
1077 | *device = tvp7002_dev; | ||
1078 | sd = &device->sd; | ||
1079 | device->pdata = c->dev.platform_data; | ||
1080 | |||
1081 | /* Tell v4l2 the device is ready */ | ||
1082 | v4l2_i2c_subdev_init(sd, c, &tvp7002_ops); | ||
1083 | v4l_info(c, "tvp7002 found @ 0x%02x (%s)\n", | ||
1084 | c->addr, c->adapter->name); | ||
1085 | |||
1086 | error = tvp7002_read(sd, TVP7002_CHIP_REV, &revision); | ||
1087 | if (error < 0) | ||
1088 | goto found_error; | ||
1089 | |||
1090 | /* Get revision number */ | ||
1091 | v4l2_info(sd, "Rev. %02x detected.\n", revision); | ||
1092 | if (revision != 0x02) | ||
1093 | v4l2_info(sd, "Unknown revision detected.\n"); | ||
1094 | |||
1095 | /* Initializes TVP7002 to its default values */ | ||
1096 | error = tvp7002_write_inittab(sd, tvp7002_init_default); | ||
1097 | |||
1098 | if (error < 0) | ||
1099 | goto found_error; | ||
1100 | |||
1101 | /* Set polarity information after registers have been set */ | ||
1102 | polarity_a = 0x20 | device->pdata->hs_polarity << 5 | ||
1103 | | device->pdata->vs_polarity << 2; | ||
1104 | error = tvp7002_write(sd, TVP7002_SYNC_CTL_1, polarity_a); | ||
1105 | if (error < 0) | ||
1106 | goto found_error; | ||
1107 | |||
1108 | polarity_b = 0x01 | device->pdata->fid_polarity << 2 | ||
1109 | | device->pdata->sog_polarity << 1 | ||
1110 | | device->pdata->clk_polarity; | ||
1111 | error = tvp7002_write(sd, TVP7002_MISC_CTL_3, polarity_b); | ||
1112 | if (error < 0) | ||
1113 | goto found_error; | ||
1114 | |||
1115 | /* Set registers according to default video mode */ | ||
1116 | preset.preset = device->current_preset->preset; | ||
1117 | error = tvp7002_s_dv_preset(sd, &preset); | ||
1118 | |||
1119 | found_error: | ||
1120 | if (error < 0) | ||
1121 | kfree(device); | ||
1122 | |||
1123 | return error; | ||
1124 | } | ||
1125 | |||
1126 | /* | ||
1127 | * tvp7002_remove - Remove TVP7002 device support | ||
1128 | * @c: ptr to i2c_client struct | ||
1129 | * | ||
1130 | * Reset the TVP7002 device | ||
1131 | * Returns zero. | ||
1132 | */ | ||
1133 | static int tvp7002_remove(struct i2c_client *c) | ||
1134 | { | ||
1135 | struct v4l2_subdev *sd = i2c_get_clientdata(c); | ||
1136 | struct tvp7002 *device = to_tvp7002(sd); | ||
1137 | |||
1138 | v4l2_dbg(1, debug, sd, "Removing tvp7002 adapter" | ||
1139 | "on address 0x%x\n", c->addr); | ||
1140 | |||
1141 | v4l2_device_unregister_subdev(sd); | ||
1142 | kfree(device); | ||
1143 | return 0; | ||
1144 | } | ||
1145 | |||
1146 | /* I2C Device ID table */ | ||
1147 | static const struct i2c_device_id tvp7002_id[] = { | ||
1148 | { "tvp7002", 0 }, | ||
1149 | { } | ||
1150 | }; | ||
1151 | MODULE_DEVICE_TABLE(i2c, tvp7002_id); | ||
1152 | |||
1153 | /* I2C driver data */ | ||
1154 | static struct i2c_driver tvp7002_driver = { | ||
1155 | .driver = { | ||
1156 | .owner = THIS_MODULE, | ||
1157 | .name = TVP7002_MODULE_NAME, | ||
1158 | }, | ||
1159 | .probe = tvp7002_probe, | ||
1160 | .remove = tvp7002_remove, | ||
1161 | .id_table = tvp7002_id, | ||
1162 | }; | ||
1163 | |||
1164 | /* | ||
1165 | * tvp7002_init - Initialize driver via I2C interface | ||
1166 | * | ||
1167 | * Register the TVP7002 driver. | ||
1168 | * Return 0 on success or error code on failure. | ||
1169 | */ | ||
1170 | static int __init tvp7002_init(void) | ||
1171 | { | ||
1172 | return i2c_add_driver(&tvp7002_driver); | ||
1173 | } | ||
1174 | |||
1175 | /* | ||
1176 | * tvp7002_exit - Remove driver via I2C interface | ||
1177 | * | ||
1178 | * Unregister the TVP7002 driver. | ||
1179 | * Returns nothing. | ||
1180 | */ | ||
1181 | static void __exit tvp7002_exit(void) | ||
1182 | { | ||
1183 | i2c_del_driver(&tvp7002_driver); | ||
1184 | } | ||
1185 | |||
1186 | module_init(tvp7002_init); | ||
1187 | module_exit(tvp7002_exit); | ||
diff --git a/drivers/media/video/tvp7002_reg.h b/drivers/media/video/tvp7002_reg.h new file mode 100644 index 000000000000..0e34ca9bccf3 --- /dev/null +++ b/drivers/media/video/tvp7002_reg.h | |||
@@ -0,0 +1,150 @@ | |||
1 | /* Texas Instruments Triple 8-/10-BIT 165-/110-MSPS Video and Graphics | ||
2 | * Digitizer with Horizontal PLL registers | ||
3 | * | ||
4 | * Copyright (C) 2009 Texas Instruments Inc | ||
5 | * Author: Santiago Nunez-Corrales <santiago.nunez@ridgerun.com> | ||
6 | * | ||
7 | * This code is partially based upon the TVP5150 driver | ||
8 | * written by Mauro Carvalho Chehab (mchehab@infradead.org), | ||
9 | * the TVP514x driver written by Vaibhav Hiremath <hvaibhav@ti.com> | ||
10 | * and the TVP7002 driver in the TI LSP 2.10.00.14 | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | /* Naming conventions | ||
28 | * ------------------ | ||
29 | * | ||
30 | * FDBK: Feedback | ||
31 | * DIV: Divider | ||
32 | * CTL: Control | ||
33 | * SEL: Select | ||
34 | * IN: Input | ||
35 | * OUT: Output | ||
36 | * R: Red | ||
37 | * G: Green | ||
38 | * B: Blue | ||
39 | * OFF: Offset | ||
40 | * THRS: Threshold | ||
41 | * DGTL: Digital | ||
42 | * LVL: Level | ||
43 | * PWR: Power | ||
44 | * MVIS: Macrovision | ||
45 | * W: Width | ||
46 | * H: Height | ||
47 | * ALGN: Alignment | ||
48 | * CLK: Clocks | ||
49 | * TOL: Tolerance | ||
50 | * BWTH: Bandwidth | ||
51 | * COEF: Coefficient | ||
52 | * STAT: Status | ||
53 | * AUTO: Automatic | ||
54 | * FLD: Field | ||
55 | * L: Line | ||
56 | */ | ||
57 | |||
58 | #define TVP7002_CHIP_REV 0x00 | ||
59 | #define TVP7002_HPLL_FDBK_DIV_MSBS 0x01 | ||
60 | #define TVP7002_HPLL_FDBK_DIV_LSBS 0x02 | ||
61 | #define TVP7002_HPLL_CRTL 0x03 | ||
62 | #define TVP7002_HPLL_PHASE_SEL 0x04 | ||
63 | #define TVP7002_CLAMP_START 0x05 | ||
64 | #define TVP7002_CLAMP_W 0x06 | ||
65 | #define TVP7002_HSYNC_OUT_W 0x07 | ||
66 | #define TVP7002_B_FINE_GAIN 0x08 | ||
67 | #define TVP7002_G_FINE_GAIN 0x09 | ||
68 | #define TVP7002_R_FINE_GAIN 0x0a | ||
69 | #define TVP7002_B_FINE_OFF_MSBS 0x0b | ||
70 | #define TVP7002_G_FINE_OFF_MSBS 0x0c | ||
71 | #define TVP7002_R_FINE_OFF_MSBS 0x0d | ||
72 | #define TVP7002_SYNC_CTL_1 0x0e | ||
73 | #define TVP7002_HPLL_AND_CLAMP_CTL 0x0f | ||
74 | #define TVP7002_SYNC_ON_G_THRS 0x10 | ||
75 | #define TVP7002_SYNC_SEPARATOR_THRS 0x11 | ||
76 | #define TVP7002_HPLL_PRE_COAST 0x12 | ||
77 | #define TVP7002_HPLL_POST_COAST 0x13 | ||
78 | #define TVP7002_SYNC_DETECT_STAT 0x14 | ||
79 | #define TVP7002_OUT_FORMATTER 0x15 | ||
80 | #define TVP7002_MISC_CTL_1 0x16 | ||
81 | #define TVP7002_MISC_CTL_2 0x17 | ||
82 | #define TVP7002_MISC_CTL_3 0x18 | ||
83 | #define TVP7002_IN_MUX_SEL_1 0x19 | ||
84 | #define TVP7002_IN_MUX_SEL_2 0x1a | ||
85 | #define TVP7002_B_AND_G_COARSE_GAIN 0x1b | ||
86 | #define TVP7002_R_COARSE_GAIN 0x1c | ||
87 | #define TVP7002_FINE_OFF_LSBS 0x1d | ||
88 | #define TVP7002_B_COARSE_OFF 0x1e | ||
89 | #define TVP7002_G_COARSE_OFF 0x1f | ||
90 | #define TVP7002_R_COARSE_OFF 0x20 | ||
91 | #define TVP7002_HSOUT_OUT_START 0x21 | ||
92 | #define TVP7002_MISC_CTL_4 0x22 | ||
93 | #define TVP7002_B_DGTL_ALC_OUT_LSBS 0x23 | ||
94 | #define TVP7002_G_DGTL_ALC_OUT_LSBS 0x24 | ||
95 | #define TVP7002_R_DGTL_ALC_OUT_LSBS 0x25 | ||
96 | #define TVP7002_AUTO_LVL_CTL_ENABLE 0x26 | ||
97 | #define TVP7002_DGTL_ALC_OUT_MSBS 0x27 | ||
98 | #define TVP7002_AUTO_LVL_CTL_FILTER 0x28 | ||
99 | /* Reserved 0x29*/ | ||
100 | #define TVP7002_FINE_CLAMP_CTL 0x2a | ||
101 | #define TVP7002_PWR_CTL 0x2b | ||
102 | #define TVP7002_ADC_SETUP 0x2c | ||
103 | #define TVP7002_COARSE_CLAMP_CTL 0x2d | ||
104 | #define TVP7002_SOG_CLAMP 0x2e | ||
105 | #define TVP7002_RGB_COARSE_CLAMP_CTL 0x2f | ||
106 | #define TVP7002_SOG_COARSE_CLAMP_CTL 0x30 | ||
107 | #define TVP7002_ALC_PLACEMENT 0x31 | ||
108 | /* Reserved 0x32 */ | ||
109 | /* Reserved 0x33 */ | ||
110 | #define TVP7002_MVIS_STRIPPER_W 0x34 | ||
111 | #define TVP7002_VSYNC_ALGN 0x35 | ||
112 | #define TVP7002_SYNC_BYPASS 0x36 | ||
113 | #define TVP7002_L_FRAME_STAT_LSBS 0x37 | ||
114 | #define TVP7002_L_FRAME_STAT_MSBS 0x38 | ||
115 | #define TVP7002_CLK_L_STAT_LSBS 0x39 | ||
116 | #define TVP7002_CLK_L_STAT_MSBS 0x3a | ||
117 | #define TVP7002_HSYNC_W 0x3b | ||
118 | #define TVP7002_VSYNC_W 0x3c | ||
119 | #define TVP7002_L_LENGTH_TOL 0x3d | ||
120 | /* Reserved 0x3e */ | ||
121 | #define TVP7002_VIDEO_BWTH_CTL 0x3f | ||
122 | #define TVP7002_AVID_START_PIXEL_LSBS 0x40 | ||
123 | #define TVP7002_AVID_START_PIXEL_MSBS 0x41 | ||
124 | #define TVP7002_AVID_STOP_PIXEL_LSBS 0x42 | ||
125 | #define TVP7002_AVID_STOP_PIXEL_MSBS 0x43 | ||
126 | #define TVP7002_VBLK_F_0_START_L_OFF 0x44 | ||
127 | #define TVP7002_VBLK_F_1_START_L_OFF 0x45 | ||
128 | #define TVP7002_VBLK_F_0_DURATION 0x46 | ||
129 | #define TVP7002_VBLK_F_1_DURATION 0x47 | ||
130 | #define TVP7002_FBIT_F_0_START_L_OFF 0x48 | ||
131 | #define TVP7002_FBIT_F_1_START_L_OFF 0x49 | ||
132 | #define TVP7002_YUV_Y_G_COEF_LSBS 0x4a | ||
133 | #define TVP7002_YUV_Y_G_COEF_MSBS 0x4b | ||
134 | #define TVP7002_YUV_Y_B_COEF_LSBS 0x4c | ||
135 | #define TVP7002_YUV_Y_B_COEF_MSBS 0x4d | ||
136 | #define TVP7002_YUV_Y_R_COEF_LSBS 0x4e | ||
137 | #define TVP7002_YUV_Y_R_COEF_MSBS 0x4f | ||
138 | #define TVP7002_YUV_U_G_COEF_LSBS 0x50 | ||
139 | #define TVP7002_YUV_U_G_COEF_MSBS 0x51 | ||
140 | #define TVP7002_YUV_U_B_COEF_LSBS 0x52 | ||
141 | #define TVP7002_YUV_U_B_COEF_MSBS 0x53 | ||
142 | #define TVP7002_YUV_U_R_COEF_LSBS 0x54 | ||
143 | #define TVP7002_YUV_U_R_COEF_MSBS 0x55 | ||
144 | #define TVP7002_YUV_V_G_COEF_LSBS 0x56 | ||
145 | #define TVP7002_YUV_V_G_COEF_MSBS 0x57 | ||
146 | #define TVP7002_YUV_V_B_COEF_LSBS 0x58 | ||
147 | #define TVP7002_YUV_V_B_COEF_MSBS 0x59 | ||
148 | #define TVP7002_YUV_V_R_COEF_LSBS 0x5a | ||
149 | #define TVP7002_YUV_V_R_COEF_MSBS 0x5b | ||
150 | |||
diff --git a/drivers/media/video/tw9910.c b/drivers/media/video/tw9910.c index 5b801a6e1eea..76be733eabfd 100644 --- a/drivers/media/video/tw9910.c +++ b/drivers/media/video/tw9910.c | |||
@@ -233,10 +233,10 @@ struct tw9910_hsync_ctrl { | |||
233 | }; | 233 | }; |
234 | 234 | ||
235 | struct tw9910_priv { | 235 | struct tw9910_priv { |
236 | struct v4l2_subdev subdev; | 236 | struct v4l2_subdev subdev; |
237 | struct tw9910_video_info *info; | 237 | struct tw9910_video_info *info; |
238 | const struct tw9910_scale_ctrl *scale; | 238 | const struct tw9910_scale_ctrl *scale; |
239 | u32 revision; | 239 | u32 revision; |
240 | }; | 240 | }; |
241 | 241 | ||
242 | static const struct tw9910_scale_ctrl tw9910_ntsc_scales[] = { | 242 | static const struct tw9910_scale_ctrl tw9910_ntsc_scales[] = { |
diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index 1054546db908..7c17ec63c5da 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c | |||
@@ -1487,7 +1487,7 @@ static int __devinit usbvision_register_video(struct usb_usbvision *usbvision) | |||
1487 | usbvision->vbi = usbvision_vdev_init(usbvision, | 1487 | usbvision->vbi = usbvision_vdev_init(usbvision, |
1488 | &usbvision_vbi_template, | 1488 | &usbvision_vbi_template, |
1489 | "USBVision VBI"); | 1489 | "USBVision VBI"); |
1490 | if (usbvision->vdev == NULL) { | 1490 | if (usbvision->vbi == NULL) { |
1491 | goto err_exit; | 1491 | goto err_exit; |
1492 | } | 1492 | } |
1493 | if (video_register_device(usbvision->vbi, | 1493 | if (video_register_device(usbvision->vbi, |
diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c index ec8ef8c5560a..3b2e7800d56f 100644 --- a/drivers/media/video/uvc/uvc_ctrl.c +++ b/drivers/media/video/uvc/uvc_ctrl.c | |||
@@ -23,9 +23,13 @@ | |||
23 | 23 | ||
24 | #include "uvcvideo.h" | 24 | #include "uvcvideo.h" |
25 | 25 | ||
26 | #define UVC_CTRL_NDATA 2 | ||
27 | #define UVC_CTRL_DATA_CURRENT 0 | 26 | #define UVC_CTRL_DATA_CURRENT 0 |
28 | #define UVC_CTRL_DATA_BACKUP 1 | 27 | #define UVC_CTRL_DATA_BACKUP 1 |
28 | #define UVC_CTRL_DATA_MIN 2 | ||
29 | #define UVC_CTRL_DATA_MAX 3 | ||
30 | #define UVC_CTRL_DATA_RES 4 | ||
31 | #define UVC_CTRL_DATA_DEF 5 | ||
32 | #define UVC_CTRL_DATA_LAST 6 | ||
29 | 33 | ||
30 | /* ------------------------------------------------------------------------ | 34 | /* ------------------------------------------------------------------------ |
31 | * Controls | 35 | * Controls |
@@ -755,6 +759,49 @@ struct uvc_control *uvc_find_control(struct uvc_video_chain *chain, | |||
755 | return ctrl; | 759 | return ctrl; |
756 | } | 760 | } |
757 | 761 | ||
762 | static int uvc_ctrl_populate_cache(struct uvc_video_chain *chain, | ||
763 | struct uvc_control *ctrl) | ||
764 | { | ||
765 | int ret; | ||
766 | |||
767 | if (ctrl->info->flags & UVC_CONTROL_GET_DEF) { | ||
768 | ret = uvc_query_ctrl(chain->dev, UVC_GET_DEF, ctrl->entity->id, | ||
769 | chain->dev->intfnum, ctrl->info->selector, | ||
770 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_DEF), | ||
771 | ctrl->info->size); | ||
772 | if (ret < 0) | ||
773 | return ret; | ||
774 | } | ||
775 | |||
776 | if (ctrl->info->flags & UVC_CONTROL_GET_MIN) { | ||
777 | ret = uvc_query_ctrl(chain->dev, UVC_GET_MIN, ctrl->entity->id, | ||
778 | chain->dev->intfnum, ctrl->info->selector, | ||
779 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MIN), | ||
780 | ctrl->info->size); | ||
781 | if (ret < 0) | ||
782 | return ret; | ||
783 | } | ||
784 | if (ctrl->info->flags & UVC_CONTROL_GET_MAX) { | ||
785 | ret = uvc_query_ctrl(chain->dev, UVC_GET_MAX, ctrl->entity->id, | ||
786 | chain->dev->intfnum, ctrl->info->selector, | ||
787 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MAX), | ||
788 | ctrl->info->size); | ||
789 | if (ret < 0) | ||
790 | return ret; | ||
791 | } | ||
792 | if (ctrl->info->flags & UVC_CONTROL_GET_RES) { | ||
793 | ret = uvc_query_ctrl(chain->dev, UVC_GET_RES, ctrl->entity->id, | ||
794 | chain->dev->intfnum, ctrl->info->selector, | ||
795 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES), | ||
796 | ctrl->info->size); | ||
797 | if (ret < 0) | ||
798 | return ret; | ||
799 | } | ||
800 | |||
801 | ctrl->cached = 1; | ||
802 | return 0; | ||
803 | } | ||
804 | |||
758 | int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, | 805 | int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, |
759 | struct v4l2_queryctrl *v4l2_ctrl) | 806 | struct v4l2_queryctrl *v4l2_ctrl) |
760 | { | 807 | { |
@@ -762,17 +809,12 @@ int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, | |||
762 | struct uvc_control_mapping *mapping; | 809 | struct uvc_control_mapping *mapping; |
763 | struct uvc_menu_info *menu; | 810 | struct uvc_menu_info *menu; |
764 | unsigned int i; | 811 | unsigned int i; |
765 | __u8 *data; | ||
766 | int ret; | 812 | int ret; |
767 | 813 | ||
768 | ctrl = uvc_find_control(chain, v4l2_ctrl->id, &mapping); | 814 | ctrl = uvc_find_control(chain, v4l2_ctrl->id, &mapping); |
769 | if (ctrl == NULL) | 815 | if (ctrl == NULL) |
770 | return -EINVAL; | 816 | return -EINVAL; |
771 | 817 | ||
772 | data = kmalloc(ctrl->info->size, GFP_KERNEL); | ||
773 | if (data == NULL) | ||
774 | return -ENOMEM; | ||
775 | |||
776 | memset(v4l2_ctrl, 0, sizeof *v4l2_ctrl); | 818 | memset(v4l2_ctrl, 0, sizeof *v4l2_ctrl); |
777 | v4l2_ctrl->id = mapping->id; | 819 | v4l2_ctrl->id = mapping->id; |
778 | v4l2_ctrl->type = mapping->v4l2_type; | 820 | v4l2_ctrl->type = mapping->v4l2_type; |
@@ -782,14 +824,15 @@ int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, | |||
782 | if (!(ctrl->info->flags & UVC_CONTROL_SET_CUR)) | 824 | if (!(ctrl->info->flags & UVC_CONTROL_SET_CUR)) |
783 | v4l2_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; | 825 | v4l2_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; |
784 | 826 | ||
785 | if (ctrl->info->flags & UVC_CONTROL_GET_DEF) { | 827 | if (!ctrl->cached) { |
786 | ret = uvc_query_ctrl(chain->dev, UVC_GET_DEF, ctrl->entity->id, | 828 | ret = uvc_ctrl_populate_cache(chain, ctrl); |
787 | chain->dev->intfnum, ctrl->info->selector, | ||
788 | data, ctrl->info->size); | ||
789 | if (ret < 0) | 829 | if (ret < 0) |
790 | goto out; | 830 | return ret; |
791 | v4l2_ctrl->default_value = | 831 | } |
792 | mapping->get(mapping, UVC_GET_DEF, data); | 832 | |
833 | if (ctrl->info->flags & UVC_CONTROL_GET_DEF) { | ||
834 | v4l2_ctrl->default_value = mapping->get(mapping, UVC_GET_DEF, | ||
835 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_DEF)); | ||
793 | } | 836 | } |
794 | 837 | ||
795 | switch (mapping->v4l2_type) { | 838 | switch (mapping->v4l2_type) { |
@@ -806,56 +849,37 @@ int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, | |||
806 | } | 849 | } |
807 | } | 850 | } |
808 | 851 | ||
809 | ret = 0; | 852 | return 0; |
810 | goto out; | ||
811 | 853 | ||
812 | case V4L2_CTRL_TYPE_BOOLEAN: | 854 | case V4L2_CTRL_TYPE_BOOLEAN: |
813 | v4l2_ctrl->minimum = 0; | 855 | v4l2_ctrl->minimum = 0; |
814 | v4l2_ctrl->maximum = 1; | 856 | v4l2_ctrl->maximum = 1; |
815 | v4l2_ctrl->step = 1; | 857 | v4l2_ctrl->step = 1; |
816 | ret = 0; | 858 | return 0; |
817 | goto out; | ||
818 | 859 | ||
819 | case V4L2_CTRL_TYPE_BUTTON: | 860 | case V4L2_CTRL_TYPE_BUTTON: |
820 | v4l2_ctrl->minimum = 0; | 861 | v4l2_ctrl->minimum = 0; |
821 | v4l2_ctrl->maximum = 0; | 862 | v4l2_ctrl->maximum = 0; |
822 | v4l2_ctrl->step = 0; | 863 | v4l2_ctrl->step = 0; |
823 | ret = 0; | 864 | return 0; |
824 | goto out; | ||
825 | 865 | ||
826 | default: | 866 | default: |
827 | break; | 867 | break; |
828 | } | 868 | } |
829 | 869 | ||
830 | if (ctrl->info->flags & UVC_CONTROL_GET_MIN) { | 870 | if (ctrl->info->flags & UVC_CONTROL_GET_MIN) |
831 | ret = uvc_query_ctrl(chain->dev, UVC_GET_MIN, ctrl->entity->id, | 871 | v4l2_ctrl->minimum = mapping->get(mapping, UVC_GET_MIN, |
832 | chain->dev->intfnum, ctrl->info->selector, | 872 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MIN)); |
833 | data, ctrl->info->size); | ||
834 | if (ret < 0) | ||
835 | goto out; | ||
836 | v4l2_ctrl->minimum = mapping->get(mapping, UVC_GET_MIN, data); | ||
837 | } | ||
838 | if (ctrl->info->flags & UVC_CONTROL_GET_MAX) { | ||
839 | ret = uvc_query_ctrl(chain->dev, UVC_GET_MAX, ctrl->entity->id, | ||
840 | chain->dev->intfnum, ctrl->info->selector, | ||
841 | data, ctrl->info->size); | ||
842 | if (ret < 0) | ||
843 | goto out; | ||
844 | v4l2_ctrl->maximum = mapping->get(mapping, UVC_GET_MAX, data); | ||
845 | } | ||
846 | if (ctrl->info->flags & UVC_CONTROL_GET_RES) { | ||
847 | ret = uvc_query_ctrl(chain->dev, UVC_GET_RES, ctrl->entity->id, | ||
848 | chain->dev->intfnum, ctrl->info->selector, | ||
849 | data, ctrl->info->size); | ||
850 | if (ret < 0) | ||
851 | goto out; | ||
852 | v4l2_ctrl->step = mapping->get(mapping, UVC_GET_RES, data); | ||
853 | } | ||
854 | 873 | ||
855 | ret = 0; | 874 | if (ctrl->info->flags & UVC_CONTROL_GET_MAX) |
856 | out: | 875 | v4l2_ctrl->maximum = mapping->get(mapping, UVC_GET_MAX, |
857 | kfree(data); | 876 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MAX)); |
858 | return ret; | 877 | |
878 | if (ctrl->info->flags & UVC_CONTROL_GET_RES) | ||
879 | v4l2_ctrl->step = mapping->get(mapping, UVC_GET_RES, | ||
880 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES)); | ||
881 | |||
882 | return 0; | ||
859 | } | 883 | } |
860 | 884 | ||
861 | 885 | ||
@@ -997,19 +1021,57 @@ int uvc_ctrl_set(struct uvc_video_chain *chain, | |||
997 | { | 1021 | { |
998 | struct uvc_control *ctrl; | 1022 | struct uvc_control *ctrl; |
999 | struct uvc_control_mapping *mapping; | 1023 | struct uvc_control_mapping *mapping; |
1000 | s32 value = xctrl->value; | 1024 | s32 value; |
1025 | u32 step; | ||
1026 | s32 min; | ||
1027 | s32 max; | ||
1001 | int ret; | 1028 | int ret; |
1002 | 1029 | ||
1003 | ctrl = uvc_find_control(chain, xctrl->id, &mapping); | 1030 | ctrl = uvc_find_control(chain, xctrl->id, &mapping); |
1004 | if (ctrl == NULL || (ctrl->info->flags & UVC_CONTROL_SET_CUR) == 0) | 1031 | if (ctrl == NULL || (ctrl->info->flags & UVC_CONTROL_SET_CUR) == 0) |
1005 | return -EINVAL; | 1032 | return -EINVAL; |
1006 | 1033 | ||
1007 | if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) { | 1034 | /* Clamp out of range values. */ |
1008 | if (value < 0 || value >= mapping->menu_count) | 1035 | switch (mapping->v4l2_type) { |
1009 | return -EINVAL; | 1036 | case V4L2_CTRL_TYPE_INTEGER: |
1010 | value = mapping->menu_info[value].value; | 1037 | if (!ctrl->cached) { |
1038 | ret = uvc_ctrl_populate_cache(chain, ctrl); | ||
1039 | if (ret < 0) | ||
1040 | return ret; | ||
1041 | } | ||
1042 | |||
1043 | min = mapping->get(mapping, UVC_GET_MIN, | ||
1044 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MIN)); | ||
1045 | max = mapping->get(mapping, UVC_GET_MAX, | ||
1046 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MAX)); | ||
1047 | step = mapping->get(mapping, UVC_GET_RES, | ||
1048 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES)); | ||
1049 | |||
1050 | xctrl->value = min + (xctrl->value - min + step/2) / step * step; | ||
1051 | xctrl->value = clamp(xctrl->value, min, max); | ||
1052 | value = xctrl->value; | ||
1053 | break; | ||
1054 | |||
1055 | case V4L2_CTRL_TYPE_BOOLEAN: | ||
1056 | xctrl->value = clamp(xctrl->value, 0, 1); | ||
1057 | value = xctrl->value; | ||
1058 | break; | ||
1059 | |||
1060 | case V4L2_CTRL_TYPE_MENU: | ||
1061 | if (xctrl->value < 0 || xctrl->value >= mapping->menu_count) | ||
1062 | return -ERANGE; | ||
1063 | value = mapping->menu_info[xctrl->value].value; | ||
1064 | break; | ||
1065 | |||
1066 | default: | ||
1067 | value = xctrl->value; | ||
1068 | break; | ||
1011 | } | 1069 | } |
1012 | 1070 | ||
1071 | /* If the mapping doesn't span the whole UVC control, the current value | ||
1072 | * needs to be loaded from the device to perform the read-modify-write | ||
1073 | * operation. | ||
1074 | */ | ||
1013 | if (!ctrl->loaded && (ctrl->info->size * 8) != mapping->size) { | 1075 | if (!ctrl->loaded && (ctrl->info->size * 8) != mapping->size) { |
1014 | if ((ctrl->info->flags & UVC_CONTROL_GET_CUR) == 0) { | 1076 | if ((ctrl->info->flags & UVC_CONTROL_GET_CUR) == 0) { |
1015 | memset(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), | 1077 | memset(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), |
@@ -1027,6 +1089,7 @@ int uvc_ctrl_set(struct uvc_video_chain *chain, | |||
1027 | ctrl->loaded = 1; | 1089 | ctrl->loaded = 1; |
1028 | } | 1090 | } |
1029 | 1091 | ||
1092 | /* Backup the current value in case we need to rollback later. */ | ||
1030 | if (!ctrl->dirty) { | 1093 | if (!ctrl->dirty) { |
1031 | memcpy(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP), | 1094 | memcpy(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP), |
1032 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), | 1095 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), |
@@ -1080,10 +1143,8 @@ int uvc_xu_ctrl_query(struct uvc_video_chain *chain, | |||
1080 | } | 1143 | } |
1081 | 1144 | ||
1082 | if (!found) { | 1145 | if (!found) { |
1083 | uvc_trace(UVC_TRACE_CONTROL, | 1146 | uvc_trace(UVC_TRACE_CONTROL, "Control %pUl/%u not found.\n", |
1084 | "Control " UVC_GUID_FORMAT "/%u not found.\n", | 1147 | entity->extension.guidExtensionCode, xctrl->selector); |
1085 | UVC_GUID_ARGS(entity->extension.guidExtensionCode), | ||
1086 | xctrl->selector); | ||
1087 | return -EINVAL; | 1148 | return -EINVAL; |
1088 | } | 1149 | } |
1089 | 1150 | ||
@@ -1159,9 +1220,9 @@ int uvc_ctrl_resume_device(struct uvc_device *dev) | |||
1159 | (ctrl->info->flags & UVC_CONTROL_RESTORE) == 0) | 1220 | (ctrl->info->flags & UVC_CONTROL_RESTORE) == 0) |
1160 | continue; | 1221 | continue; |
1161 | 1222 | ||
1162 | printk(KERN_INFO "restoring control " UVC_GUID_FORMAT | 1223 | printk(KERN_INFO "restoring control %pUl/%u/%u\n", |
1163 | "/%u/%u\n", UVC_GUID_ARGS(ctrl->info->entity), | 1224 | ctrl->info->entity, ctrl->info->index, |
1164 | ctrl->info->index, ctrl->info->selector); | 1225 | ctrl->info->selector); |
1165 | ctrl->dirty = 1; | 1226 | ctrl->dirty = 1; |
1166 | } | 1227 | } |
1167 | 1228 | ||
@@ -1215,47 +1276,43 @@ static void uvc_ctrl_add_ctrl(struct uvc_device *dev, | |||
1215 | ret = uvc_query_ctrl(dev, UVC_GET_LEN, ctrl->entity->id, | 1276 | ret = uvc_query_ctrl(dev, UVC_GET_LEN, ctrl->entity->id, |
1216 | dev->intfnum, info->selector, (__u8 *)&size, 2); | 1277 | dev->intfnum, info->selector, (__u8 *)&size, 2); |
1217 | if (ret < 0) { | 1278 | if (ret < 0) { |
1218 | uvc_trace(UVC_TRACE_CONTROL, "GET_LEN failed on " | 1279 | uvc_trace(UVC_TRACE_CONTROL, |
1219 | "control " UVC_GUID_FORMAT "/%u (%d).\n", | 1280 | "GET_LEN failed on control %pUl/%u (%d).\n", |
1220 | UVC_GUID_ARGS(info->entity), info->selector, | 1281 | info->entity, info->selector, ret); |
1221 | ret); | ||
1222 | return; | 1282 | return; |
1223 | } | 1283 | } |
1224 | 1284 | ||
1225 | if (info->size != le16_to_cpu(size)) { | 1285 | if (info->size != le16_to_cpu(size)) { |
1226 | uvc_trace(UVC_TRACE_CONTROL, "Control " UVC_GUID_FORMAT | 1286 | uvc_trace(UVC_TRACE_CONTROL, "Control %pUl/%u size " |
1227 | "/%u size doesn't match user supplied " | 1287 | "doesn't match user supplied value.\n", |
1228 | "value.\n", UVC_GUID_ARGS(info->entity), | 1288 | info->entity, info->selector); |
1229 | info->selector); | ||
1230 | return; | 1289 | return; |
1231 | } | 1290 | } |
1232 | 1291 | ||
1233 | ret = uvc_query_ctrl(dev, UVC_GET_INFO, ctrl->entity->id, | 1292 | ret = uvc_query_ctrl(dev, UVC_GET_INFO, ctrl->entity->id, |
1234 | dev->intfnum, info->selector, &inf, 1); | 1293 | dev->intfnum, info->selector, &inf, 1); |
1235 | if (ret < 0) { | 1294 | if (ret < 0) { |
1236 | uvc_trace(UVC_TRACE_CONTROL, "GET_INFO failed on " | 1295 | uvc_trace(UVC_TRACE_CONTROL, |
1237 | "control " UVC_GUID_FORMAT "/%u (%d).\n", | 1296 | "GET_INFO failed on control %pUl/%u (%d).\n", |
1238 | UVC_GUID_ARGS(info->entity), info->selector, | 1297 | info->entity, info->selector, ret); |
1239 | ret); | ||
1240 | return; | 1298 | return; |
1241 | } | 1299 | } |
1242 | 1300 | ||
1243 | flags = info->flags; | 1301 | flags = info->flags; |
1244 | if (((flags & UVC_CONTROL_GET_CUR) && !(inf & (1 << 0))) || | 1302 | if (((flags & UVC_CONTROL_GET_CUR) && !(inf & (1 << 0))) || |
1245 | ((flags & UVC_CONTROL_SET_CUR) && !(inf & (1 << 1)))) { | 1303 | ((flags & UVC_CONTROL_SET_CUR) && !(inf & (1 << 1)))) { |
1246 | uvc_trace(UVC_TRACE_CONTROL, "Control " | 1304 | uvc_trace(UVC_TRACE_CONTROL, "Control %pUl/%u flags " |
1247 | UVC_GUID_FORMAT "/%u flags don't match " | 1305 | "don't match supported operations.\n", |
1248 | "supported operations.\n", | 1306 | info->entity, info->selector); |
1249 | UVC_GUID_ARGS(info->entity), info->selector); | ||
1250 | return; | 1307 | return; |
1251 | } | 1308 | } |
1252 | } | 1309 | } |
1253 | 1310 | ||
1254 | ctrl->info = info; | 1311 | ctrl->info = info; |
1255 | ctrl->data = kmalloc(ctrl->info->size * UVC_CTRL_NDATA, GFP_KERNEL); | 1312 | ctrl->data = kmalloc(ctrl->info->size * UVC_CTRL_DATA_LAST, GFP_KERNEL); |
1256 | uvc_trace(UVC_TRACE_CONTROL, "Added control " UVC_GUID_FORMAT "/%u " | 1313 | uvc_trace(UVC_TRACE_CONTROL, "Added control %pUl/%u to device %s " |
1257 | "to device %s entity %u\n", UVC_GUID_ARGS(ctrl->info->entity), | 1314 | "entity %u\n", ctrl->info->entity, ctrl->info->selector, |
1258 | ctrl->info->selector, dev->udev->devpath, entity->id); | 1315 | dev->udev->devpath, entity->id); |
1259 | } | 1316 | } |
1260 | 1317 | ||
1261 | /* | 1318 | /* |
@@ -1281,17 +1338,16 @@ int uvc_ctrl_add_info(struct uvc_control_info *info) | |||
1281 | continue; | 1338 | continue; |
1282 | 1339 | ||
1283 | if (ctrl->selector == info->selector) { | 1340 | if (ctrl->selector == info->selector) { |
1284 | uvc_trace(UVC_TRACE_CONTROL, "Control " | 1341 | uvc_trace(UVC_TRACE_CONTROL, |
1285 | UVC_GUID_FORMAT "/%u is already defined.\n", | 1342 | "Control %pUl/%u is already defined.\n", |
1286 | UVC_GUID_ARGS(info->entity), info->selector); | 1343 | info->entity, info->selector); |
1287 | ret = -EEXIST; | 1344 | ret = -EEXIST; |
1288 | goto end; | 1345 | goto end; |
1289 | } | 1346 | } |
1290 | if (ctrl->index == info->index) { | 1347 | if (ctrl->index == info->index) { |
1291 | uvc_trace(UVC_TRACE_CONTROL, "Control " | 1348 | uvc_trace(UVC_TRACE_CONTROL, |
1292 | UVC_GUID_FORMAT "/%u would overwrite index " | 1349 | "Control %pUl/%u would overwrite index %d.\n", |
1293 | "%d.\n", UVC_GUID_ARGS(info->entity), | 1350 | info->entity, info->selector, info->index); |
1294 | info->selector, info->index); | ||
1295 | ret = -EEXIST; | 1351 | ret = -EEXIST; |
1296 | goto end; | 1352 | goto end; |
1297 | } | 1353 | } |
@@ -1332,10 +1388,9 @@ int uvc_ctrl_add_mapping(struct uvc_control_mapping *mapping) | |||
1332 | continue; | 1388 | continue; |
1333 | 1389 | ||
1334 | if (info->size * 8 < mapping->size + mapping->offset) { | 1390 | if (info->size * 8 < mapping->size + mapping->offset) { |
1335 | uvc_trace(UVC_TRACE_CONTROL, "Mapping '%s' would " | 1391 | uvc_trace(UVC_TRACE_CONTROL, |
1336 | "overflow control " UVC_GUID_FORMAT "/%u\n", | 1392 | "Mapping '%s' would overflow control %pUl/%u\n", |
1337 | mapping->name, UVC_GUID_ARGS(info->entity), | 1393 | mapping->name, info->entity, info->selector); |
1338 | info->selector); | ||
1339 | ret = -EOVERFLOW; | 1394 | ret = -EOVERFLOW; |
1340 | goto end; | 1395 | goto end; |
1341 | } | 1396 | } |
@@ -1354,9 +1409,9 @@ int uvc_ctrl_add_mapping(struct uvc_control_mapping *mapping) | |||
1354 | 1409 | ||
1355 | mapping->ctrl = info; | 1410 | mapping->ctrl = info; |
1356 | list_add_tail(&mapping->list, &info->mappings); | 1411 | list_add_tail(&mapping->list, &info->mappings); |
1357 | uvc_trace(UVC_TRACE_CONTROL, "Adding mapping %s to control " | 1412 | uvc_trace(UVC_TRACE_CONTROL, |
1358 | UVC_GUID_FORMAT "/%u.\n", mapping->name, | 1413 | "Adding mapping %s to control %pUl/%u.\n", |
1359 | UVC_GUID_ARGS(info->entity), info->selector); | 1414 | mapping->name, info->entity, info->selector); |
1360 | 1415 | ||
1361 | ret = 0; | 1416 | ret = 0; |
1362 | break; | 1417 | break; |
@@ -1378,6 +1433,7 @@ uvc_ctrl_prune_entity(struct uvc_device *dev, struct uvc_entity *entity) | |||
1378 | struct usb_device_id id; | 1433 | struct usb_device_id id; |
1379 | u8 index; | 1434 | u8 index; |
1380 | } blacklist[] = { | 1435 | } blacklist[] = { |
1436 | { { USB_DEVICE(0x13d3, 0x509b) }, 9 }, /* Gain */ | ||
1381 | { { USB_DEVICE(0x1c4f, 0x3000) }, 6 }, /* WB Temperature */ | 1437 | { { USB_DEVICE(0x1c4f, 0x3000) }, 6 }, /* WB Temperature */ |
1382 | { { USB_DEVICE(0x5986, 0x0241) }, 2 }, /* Hue */ | 1438 | { { USB_DEVICE(0x5986, 0x0241) }, 2 }, /* Hue */ |
1383 | }; | 1439 | }; |
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index 391cccca7ffc..a814820a3f6e 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c | |||
@@ -43,8 +43,9 @@ | |||
43 | #define DRIVER_VERSION "v0.1.0" | 43 | #define DRIVER_VERSION "v0.1.0" |
44 | #endif | 44 | #endif |
45 | 45 | ||
46 | unsigned int uvc_clock_param = CLOCK_MONOTONIC; | ||
46 | unsigned int uvc_no_drop_param; | 47 | unsigned int uvc_no_drop_param; |
47 | static unsigned int uvc_quirks_param; | 48 | static unsigned int uvc_quirks_param = -1; |
48 | unsigned int uvc_trace_param; | 49 | unsigned int uvc_trace_param; |
49 | unsigned int uvc_timeout_param = UVC_CTRL_STREAMING_TIMEOUT; | 50 | unsigned int uvc_timeout_param = UVC_CTRL_STREAMING_TIMEOUT; |
50 | 51 | ||
@@ -59,6 +60,11 @@ static struct uvc_format_desc uvc_fmts[] = { | |||
59 | .fcc = V4L2_PIX_FMT_YUYV, | 60 | .fcc = V4L2_PIX_FMT_YUYV, |
60 | }, | 61 | }, |
61 | { | 62 | { |
63 | .name = "YUV 4:2:2 (YUYV)", | ||
64 | .guid = UVC_GUID_FORMAT_YUY2_ISIGHT, | ||
65 | .fcc = V4L2_PIX_FMT_YUYV, | ||
66 | }, | ||
67 | { | ||
62 | .name = "YUV 4:2:0 (NV12)", | 68 | .name = "YUV 4:2:0 (NV12)", |
63 | .guid = UVC_GUID_FORMAT_NV12, | 69 | .guid = UVC_GUID_FORMAT_NV12, |
64 | .fcc = V4L2_PIX_FMT_NV12, | 70 | .fcc = V4L2_PIX_FMT_NV12, |
@@ -309,11 +315,10 @@ static int uvc_parse_format(struct uvc_device *dev, | |||
309 | sizeof format->name); | 315 | sizeof format->name); |
310 | format->fcc = fmtdesc->fcc; | 316 | format->fcc = fmtdesc->fcc; |
311 | } else { | 317 | } else { |
312 | uvc_printk(KERN_INFO, "Unknown video format " | 318 | uvc_printk(KERN_INFO, "Unknown video format %pUl\n", |
313 | UVC_GUID_FORMAT "\n", | 319 | &buffer[5]); |
314 | UVC_GUID_ARGS(&buffer[5])); | 320 | snprintf(format->name, sizeof(format->name), "%pUl\n", |
315 | snprintf(format->name, sizeof format->name, | 321 | &buffer[5]); |
316 | UVC_GUID_FORMAT, UVC_GUID_ARGS(&buffer[5])); | ||
317 | format->fcc = 0; | 322 | format->fcc = 0; |
318 | } | 323 | } |
319 | 324 | ||
@@ -1750,7 +1755,8 @@ static int uvc_probe(struct usb_interface *intf, | |||
1750 | dev->udev = usb_get_dev(udev); | 1755 | dev->udev = usb_get_dev(udev); |
1751 | dev->intf = usb_get_intf(intf); | 1756 | dev->intf = usb_get_intf(intf); |
1752 | dev->intfnum = intf->cur_altsetting->desc.bInterfaceNumber; | 1757 | dev->intfnum = intf->cur_altsetting->desc.bInterfaceNumber; |
1753 | dev->quirks = id->driver_info | uvc_quirks_param; | 1758 | dev->quirks = (uvc_quirks_param == -1) |
1759 | ? id->driver_info : uvc_quirks_param; | ||
1754 | 1760 | ||
1755 | if (udev->product != NULL) | 1761 | if (udev->product != NULL) |
1756 | strlcpy(dev->name, udev->product, sizeof dev->name); | 1762 | strlcpy(dev->name, udev->product, sizeof dev->name); |
@@ -1773,9 +1779,9 @@ static int uvc_probe(struct usb_interface *intf, | |||
1773 | le16_to_cpu(udev->descriptor.idVendor), | 1779 | le16_to_cpu(udev->descriptor.idVendor), |
1774 | le16_to_cpu(udev->descriptor.idProduct)); | 1780 | le16_to_cpu(udev->descriptor.idProduct)); |
1775 | 1781 | ||
1776 | if (uvc_quirks_param != 0) { | 1782 | if (dev->quirks != id->driver_info) { |
1777 | uvc_printk(KERN_INFO, "Forcing device quirks 0x%x by module " | 1783 | uvc_printk(KERN_INFO, "Forcing device quirks to 0x%x by module " |
1778 | "parameter for testing purpose.\n", uvc_quirks_param); | 1784 | "parameter for testing purpose.\n", dev->quirks); |
1779 | uvc_printk(KERN_INFO, "Please report required quirks to the " | 1785 | uvc_printk(KERN_INFO, "Please report required quirks to the " |
1780 | "linux-uvc-devel mailing list.\n"); | 1786 | "linux-uvc-devel mailing list.\n"); |
1781 | } | 1787 | } |
@@ -1892,6 +1898,45 @@ static int uvc_reset_resume(struct usb_interface *intf) | |||
1892 | } | 1898 | } |
1893 | 1899 | ||
1894 | /* ------------------------------------------------------------------------ | 1900 | /* ------------------------------------------------------------------------ |
1901 | * Module parameters | ||
1902 | */ | ||
1903 | |||
1904 | static int uvc_clock_param_get(char *buffer, struct kernel_param *kp) | ||
1905 | { | ||
1906 | if (uvc_clock_param == CLOCK_MONOTONIC) | ||
1907 | return sprintf(buffer, "CLOCK_MONOTONIC"); | ||
1908 | else | ||
1909 | return sprintf(buffer, "CLOCK_REALTIME"); | ||
1910 | } | ||
1911 | |||
1912 | static int uvc_clock_param_set(const char *val, struct kernel_param *kp) | ||
1913 | { | ||
1914 | if (strncasecmp(val, "clock_", strlen("clock_")) == 0) | ||
1915 | val += strlen("clock_"); | ||
1916 | |||
1917 | if (strcasecmp(val, "monotonic") == 0) | ||
1918 | uvc_clock_param = CLOCK_MONOTONIC; | ||
1919 | else if (strcasecmp(val, "realtime") == 0) | ||
1920 | uvc_clock_param = CLOCK_REALTIME; | ||
1921 | else | ||
1922 | return -EINVAL; | ||
1923 | |||
1924 | return 0; | ||
1925 | } | ||
1926 | |||
1927 | module_param_call(clock, uvc_clock_param_set, uvc_clock_param_get, | ||
1928 | &uvc_clock_param, S_IRUGO|S_IWUSR); | ||
1929 | MODULE_PARM_DESC(clock, "Video buffers timestamp clock"); | ||
1930 | module_param_named(nodrop, uvc_no_drop_param, uint, S_IRUGO|S_IWUSR); | ||
1931 | MODULE_PARM_DESC(nodrop, "Don't drop incomplete frames"); | ||
1932 | module_param_named(quirks, uvc_quirks_param, uint, S_IRUGO|S_IWUSR); | ||
1933 | MODULE_PARM_DESC(quirks, "Forced device quirks"); | ||
1934 | module_param_named(trace, uvc_trace_param, uint, S_IRUGO|S_IWUSR); | ||
1935 | MODULE_PARM_DESC(trace, "Trace level bitmask"); | ||
1936 | module_param_named(timeout, uvc_timeout_param, uint, S_IRUGO|S_IWUSR); | ||
1937 | MODULE_PARM_DESC(timeout, "Streaming control requests timeout"); | ||
1938 | |||
1939 | /* ------------------------------------------------------------------------ | ||
1895 | * Driver initialization and cleanup | 1940 | * Driver initialization and cleanup |
1896 | */ | 1941 | */ |
1897 | 1942 | ||
@@ -2197,15 +2242,6 @@ static void __exit uvc_cleanup(void) | |||
2197 | module_init(uvc_init); | 2242 | module_init(uvc_init); |
2198 | module_exit(uvc_cleanup); | 2243 | module_exit(uvc_cleanup); |
2199 | 2244 | ||
2200 | module_param_named(nodrop, uvc_no_drop_param, uint, S_IRUGO|S_IWUSR); | ||
2201 | MODULE_PARM_DESC(nodrop, "Don't drop incomplete frames"); | ||
2202 | module_param_named(quirks, uvc_quirks_param, uint, S_IRUGO|S_IWUSR); | ||
2203 | MODULE_PARM_DESC(quirks, "Forced device quirks"); | ||
2204 | module_param_named(trace, uvc_trace_param, uint, S_IRUGO|S_IWUSR); | ||
2205 | MODULE_PARM_DESC(trace, "Trace level bitmask"); | ||
2206 | module_param_named(timeout, uvc_timeout_param, uint, S_IRUGO|S_IWUSR); | ||
2207 | MODULE_PARM_DESC(timeout, "Streaming control requests timeout"); | ||
2208 | |||
2209 | MODULE_AUTHOR(DRIVER_AUTHOR); | 2245 | MODULE_AUTHOR(DRIVER_AUTHOR); |
2210 | MODULE_DESCRIPTION(DRIVER_DESC); | 2246 | MODULE_DESCRIPTION(DRIVER_DESC); |
2211 | MODULE_LICENSE("GPL"); | 2247 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c index ea11839cba4a..4a925a31b0e0 100644 --- a/drivers/media/video/uvc/uvc_queue.c +++ b/drivers/media/video/uvc/uvc_queue.c | |||
@@ -502,7 +502,6 @@ struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, | |||
502 | spin_unlock_irqrestore(&queue->irqlock, flags); | 502 | spin_unlock_irqrestore(&queue->irqlock, flags); |
503 | 503 | ||
504 | buf->buf.sequence = queue->sequence++; | 504 | buf->buf.sequence = queue->sequence++; |
505 | do_gettimeofday(&buf->buf.timestamp); | ||
506 | 505 | ||
507 | wake_up(&buf->wait); | 506 | wake_up(&buf->wait); |
508 | return nextbuf; | 507 | return nextbuf; |
diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c index 23239a4adefe..43152aa52227 100644 --- a/drivers/media/video/uvc/uvc_v4l2.c +++ b/drivers/media/video/uvc/uvc_v4l2.c | |||
@@ -539,7 +539,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) | |||
539 | xctrl.id = ctrl->id; | 539 | xctrl.id = ctrl->id; |
540 | xctrl.value = ctrl->value; | 540 | xctrl.value = ctrl->value; |
541 | 541 | ||
542 | uvc_ctrl_begin(chain); | 542 | ret = uvc_ctrl_begin(chain); |
543 | if (ret < 0) | 543 | if (ret < 0) |
544 | return ret; | 544 | return ret; |
545 | 545 | ||
@@ -549,6 +549,8 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) | |||
549 | return ret; | 549 | return ret; |
550 | } | 550 | } |
551 | ret = uvc_ctrl_commit(chain); | 551 | ret = uvc_ctrl_commit(chain); |
552 | if (ret == 0) | ||
553 | ctrl->value = xctrl.value; | ||
552 | break; | 554 | break; |
553 | } | 555 | } |
554 | 556 | ||
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index 7dcf534a0cf3..6b0666be370f 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c | |||
@@ -410,6 +410,8 @@ static int uvc_video_decode_start(struct uvc_streaming *stream, | |||
410 | * when the EOF bit is set to force synchronisation on the next packet. | 410 | * when the EOF bit is set to force synchronisation on the next packet. |
411 | */ | 411 | */ |
412 | if (buf->state != UVC_BUF_STATE_ACTIVE) { | 412 | if (buf->state != UVC_BUF_STATE_ACTIVE) { |
413 | struct timespec ts; | ||
414 | |||
413 | if (fid == stream->last_fid) { | 415 | if (fid == stream->last_fid) { |
414 | uvc_trace(UVC_TRACE_FRAME, "Dropping payload (out of " | 416 | uvc_trace(UVC_TRACE_FRAME, "Dropping payload (out of " |
415 | "sync).\n"); | 417 | "sync).\n"); |
@@ -419,6 +421,14 @@ static int uvc_video_decode_start(struct uvc_streaming *stream, | |||
419 | return -ENODATA; | 421 | return -ENODATA; |
420 | } | 422 | } |
421 | 423 | ||
424 | if (uvc_clock_param == CLOCK_MONOTONIC) | ||
425 | ktime_get_ts(&ts); | ||
426 | else | ||
427 | ktime_get_real_ts(&ts); | ||
428 | |||
429 | buf->buf.timestamp.tv_sec = ts.tv_sec; | ||
430 | buf->buf.timestamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC; | ||
431 | |||
422 | /* TODO: Handle PTS and SCR. */ | 432 | /* TODO: Handle PTS and SCR. */ |
423 | buf->state = UVC_BUF_STATE_ACTIVE; | 433 | buf->state = UVC_BUF_STATE_ACTIVE; |
424 | } | 434 | } |
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h index 2337585001ea..2bba059259e6 100644 --- a/drivers/media/video/uvc/uvcvideo.h +++ b/drivers/media/video/uvc/uvcvideo.h | |||
@@ -113,6 +113,9 @@ struct uvc_xu_control { | |||
113 | #define UVC_GUID_FORMAT_YUY2 \ | 113 | #define UVC_GUID_FORMAT_YUY2 \ |
114 | { 'Y', 'U', 'Y', '2', 0x00, 0x00, 0x10, 0x00, \ | 114 | { 'Y', 'U', 'Y', '2', 0x00, 0x00, 0x10, 0x00, \ |
115 | 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} | 115 | 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} |
116 | #define UVC_GUID_FORMAT_YUY2_ISIGHT \ | ||
117 | { 'Y', 'U', 'Y', '2', 0x00, 0x00, 0x10, 0x00, \ | ||
118 | 0x80, 0x00, 0x00, 0x00, 0x00, 0x38, 0x9b, 0x71} | ||
116 | #define UVC_GUID_FORMAT_NV12 \ | 119 | #define UVC_GUID_FORMAT_NV12 \ |
117 | { 'N', 'V', '1', '2', 0x00, 0x00, 0x10, 0x00, \ | 120 | { 'N', 'V', '1', '2', 0x00, 0x00, 0x10, 0x00, \ |
118 | 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} | 121 | 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} |
@@ -149,7 +152,7 @@ struct uvc_xu_control { | |||
149 | #define UVC_MAX_STATUS_SIZE 16 | 152 | #define UVC_MAX_STATUS_SIZE 16 |
150 | 153 | ||
151 | #define UVC_CTRL_CONTROL_TIMEOUT 300 | 154 | #define UVC_CTRL_CONTROL_TIMEOUT 300 |
152 | #define UVC_CTRL_STREAMING_TIMEOUT 3000 | 155 | #define UVC_CTRL_STREAMING_TIMEOUT 5000 |
153 | 156 | ||
154 | /* Devices quirks */ | 157 | /* Devices quirks */ |
155 | #define UVC_QUIRK_STATUS_INTERVAL 0x00000001 | 158 | #define UVC_QUIRK_STATUS_INTERVAL 0x00000001 |
@@ -242,7 +245,8 @@ struct uvc_control { | |||
242 | uvc_control_info. */ | 245 | uvc_control_info. */ |
243 | __u8 dirty : 1, | 246 | __u8 dirty : 1, |
244 | loaded : 1, | 247 | loaded : 1, |
245 | modified : 1; | 248 | modified : 1, |
249 | cached : 1; | ||
246 | 250 | ||
247 | __u8 *data; | 251 | __u8 *data; |
248 | }; | 252 | }; |
@@ -533,6 +537,7 @@ struct uvc_driver { | |||
533 | #define UVC_WARN_MINMAX 0 | 537 | #define UVC_WARN_MINMAX 0 |
534 | #define UVC_WARN_PROBE_DEF 1 | 538 | #define UVC_WARN_PROBE_DEF 1 |
535 | 539 | ||
540 | extern unsigned int uvc_clock_param; | ||
536 | extern unsigned int uvc_no_drop_param; | 541 | extern unsigned int uvc_no_drop_param; |
537 | extern unsigned int uvc_trace_param; | 542 | extern unsigned int uvc_trace_param; |
538 | extern unsigned int uvc_timeout_param; | 543 | extern unsigned int uvc_timeout_param; |
@@ -552,16 +557,6 @@ extern unsigned int uvc_timeout_param; | |||
552 | #define uvc_printk(level, msg...) \ | 557 | #define uvc_printk(level, msg...) \ |
553 | printk(level "uvcvideo: " msg) | 558 | printk(level "uvcvideo: " msg) |
554 | 559 | ||
555 | #define UVC_GUID_FORMAT "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-" \ | ||
556 | "%02x%02x%02x%02x%02x%02x" | ||
557 | #define UVC_GUID_ARGS(guid) \ | ||
558 | (guid)[3], (guid)[2], (guid)[1], (guid)[0], \ | ||
559 | (guid)[5], (guid)[4], \ | ||
560 | (guid)[7], (guid)[6], \ | ||
561 | (guid)[8], (guid)[9], \ | ||
562 | (guid)[10], (guid)[11], (guid)[12], \ | ||
563 | (guid)[13], (guid)[14], (guid)[15] | ||
564 | |||
565 | /* -------------------------------------------------------------------------- | 560 | /* -------------------------------------------------------------------------- |
566 | * Internal functions. | 561 | * Internal functions. |
567 | */ | 562 | */ |
diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c index c4150bd26337..f77f84bfe714 100644 --- a/drivers/media/video/v4l2-compat-ioctl32.c +++ b/drivers/media/video/v4l2-compat-ioctl32.c | |||
@@ -288,7 +288,7 @@ static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user | |||
288 | 288 | ||
289 | static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up) | 289 | static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up) |
290 | { | 290 | { |
291 | if (copy_to_user(&up->w, &kp->w, sizeof(up->w)) || | 291 | if (copy_to_user(&up->w, &kp->w, sizeof(kp->w)) || |
292 | put_user(kp->field, &up->field) || | 292 | put_user(kp->field, &up->field) || |
293 | put_user(kp->chromakey, &up->chromakey) || | 293 | put_user(kp->chromakey, &up->chromakey) || |
294 | put_user(kp->clipcount, &up->clipcount)) | 294 | put_user(kp->clipcount, &up->clipcount)) |
@@ -475,6 +475,9 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user | |||
475 | return -EFAULT; | 475 | return -EFAULT; |
476 | switch (kp->memory) { | 476 | switch (kp->memory) { |
477 | case V4L2_MEMORY_MMAP: | 477 | case V4L2_MEMORY_MMAP: |
478 | if (get_user(kp->length, &up->length) || | ||
479 | get_user(kp->m.offset, &up->m.offset)) | ||
480 | return -EFAULT; | ||
478 | break; | 481 | break; |
479 | case V4L2_MEMORY_USERPTR: | 482 | case V4L2_MEMORY_USERPTR: |
480 | { | 483 | { |
diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c index fa78555b118b..fcd045e7a1c1 100644 --- a/drivers/media/video/videobuf-dma-sg.c +++ b/drivers/media/video/videobuf-dma-sg.c | |||
@@ -418,6 +418,8 @@ static void *__videobuf_alloc(size_t size) | |||
418 | struct videobuf_buffer *vb; | 418 | struct videobuf_buffer *vb; |
419 | 419 | ||
420 | vb = kzalloc(size+sizeof(*mem),GFP_KERNEL); | 420 | vb = kzalloc(size+sizeof(*mem),GFP_KERNEL); |
421 | if (!vb) | ||
422 | return vb; | ||
421 | 423 | ||
422 | mem = vb->priv = ((char *)vb)+size; | 424 | mem = vb->priv = ((char *)vb)+size; |
423 | mem->magic=MAGIC_SG_MEM; | 425 | mem->magic=MAGIC_SG_MEM; |
diff --git a/drivers/media/video/videobuf-vmalloc.c b/drivers/media/video/videobuf-vmalloc.c index d6e6a28fb6b8..136e09383c06 100644 --- a/drivers/media/video/videobuf-vmalloc.c +++ b/drivers/media/video/videobuf-vmalloc.c | |||
@@ -138,6 +138,8 @@ static void *__videobuf_alloc(size_t size) | |||
138 | struct videobuf_buffer *vb; | 138 | struct videobuf_buffer *vb; |
139 | 139 | ||
140 | vb = kzalloc(size+sizeof(*mem),GFP_KERNEL); | 140 | vb = kzalloc(size+sizeof(*mem),GFP_KERNEL); |
141 | if (!vb) | ||
142 | return vb; | ||
141 | 143 | ||
142 | mem = vb->priv = ((char *)vb)+size; | 144 | mem = vb->priv = ((char *)vb)+size; |
143 | mem->magic=MAGIC_VMAL_MEM; | 145 | mem->magic=MAGIC_VMAL_MEM; |
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 37632a064966..cdbe70385c12 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c | |||
@@ -1371,7 +1371,7 @@ static int __init vivi_create_instance(int inst) | |||
1371 | /* Now that everything is fine, let's add it to device list */ | 1371 | /* Now that everything is fine, let's add it to device list */ |
1372 | list_add_tail(&dev->vivi_devlist, &vivi_devlist); | 1372 | list_add_tail(&dev->vivi_devlist, &vivi_devlist); |
1373 | 1373 | ||
1374 | if (video_nr >= 0) | 1374 | if (video_nr != -1) |
1375 | video_nr++; | 1375 | video_nr++; |
1376 | 1376 | ||
1377 | dev->vfd = vfd; | 1377 | dev->vfd = vfd; |
diff --git a/drivers/media/video/zc0301/Kconfig b/drivers/media/video/zc0301/Kconfig index edb00293cd59..a7e610e0be9e 100644 --- a/drivers/media/video/zc0301/Kconfig +++ b/drivers/media/video/zc0301/Kconfig | |||
@@ -1,7 +1,11 @@ | |||
1 | config USB_ZC0301 | 1 | config USB_ZC0301 |
2 | tristate "USB ZC0301[P] Image Processor and Control Chip support" | 2 | tristate "USB ZC0301[P] webcam support (DEPRECATED)" |
3 | depends on VIDEO_V4L2 | 3 | depends on VIDEO_V4L2 |
4 | default n | ||
4 | ---help--- | 5 | ---help--- |
6 | This driver is DEPRECATED please use the gspca zc3xx module | ||
7 | instead. | ||
8 | |||
5 | Say Y here if you want support for cameras based on the ZC0301 or | 9 | Say Y here if you want support for cameras based on the ZC0301 or |
6 | ZC0301P Image Processors and Control Chips. | 10 | ZC0301P Image Processors and Control Chips. |
7 | 11 | ||
diff --git a/drivers/media/video/zoran/zoran_device.c b/drivers/media/video/zoran/zoran_device.c index f6c2fb4fc3b4..e6ad4b205611 100644 --- a/drivers/media/video/zoran/zoran_device.c +++ b/drivers/media/video/zoran/zoran_device.c | |||
@@ -1196,7 +1196,8 @@ zoran_reap_stat_com (struct zoran *zr) | |||
1196 | static void zoran_restart(struct zoran *zr) | 1196 | static void zoran_restart(struct zoran *zr) |
1197 | { | 1197 | { |
1198 | /* Now the stat_comm buffer is ready for restart */ | 1198 | /* Now the stat_comm buffer is ready for restart */ |
1199 | int status = 0, mode; | 1199 | unsigned int status = 0; |
1200 | int mode; | ||
1200 | 1201 | ||
1201 | if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) { | 1202 | if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) { |
1202 | decoder_call(zr, video, g_input_status, &status); | 1203 | decoder_call(zr, video, g_input_status, &status); |
@@ -1228,7 +1229,7 @@ error_handler (struct zoran *zr, | |||
1228 | u32 astat, | 1229 | u32 astat, |
1229 | u32 stat) | 1230 | u32 stat) |
1230 | { | 1231 | { |
1231 | int i, j; | 1232 | int i; |
1232 | 1233 | ||
1233 | /* This is JPEG error handling part */ | 1234 | /* This is JPEG error handling part */ |
1234 | if (zr->codec_mode != BUZ_MODE_MOTION_COMPRESS && | 1235 | if (zr->codec_mode != BUZ_MODE_MOTION_COMPRESS && |
@@ -1279,6 +1280,7 @@ error_handler (struct zoran *zr, | |||
1279 | /* Report error */ | 1280 | /* Report error */ |
1280 | if (zr36067_debug > 1 && zr->num_errors <= 8) { | 1281 | if (zr36067_debug > 1 && zr->num_errors <= 8) { |
1281 | long frame; | 1282 | long frame; |
1283 | int j; | ||
1282 | 1284 | ||
1283 | frame = zr->jpg_pend[zr->jpg_dma_tail & BUZ_MASK_FRAME]; | 1285 | frame = zr->jpg_pend[zr->jpg_dma_tail & BUZ_MASK_FRAME]; |
1284 | printk(KERN_ERR | 1286 | printk(KERN_ERR |
diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index 2ddffed019ee..ec41303544e5 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c | |||
@@ -324,7 +324,7 @@ static int jpg_fbuffer_alloc(struct zoran_fh *fh) | |||
324 | /* Allocate fragment table for this buffer */ | 324 | /* Allocate fragment table for this buffer */ |
325 | 325 | ||
326 | mem = (void *)get_zeroed_page(GFP_KERNEL); | 326 | mem = (void *)get_zeroed_page(GFP_KERNEL); |
327 | if (mem == 0) { | 327 | if (!mem) { |
328 | dprintk(1, | 328 | dprintk(1, |
329 | KERN_ERR | 329 | KERN_ERR |
330 | "%s: %s - get_zeroed_page (frag_tab) failed for buffer %d\n", | 330 | "%s: %s - get_zeroed_page (frag_tab) failed for buffer %d\n", |
@@ -1444,7 +1444,7 @@ zoran_set_norm (struct zoran *zr, | |||
1444 | } | 1444 | } |
1445 | 1445 | ||
1446 | if (norm == V4L2_STD_ALL) { | 1446 | if (norm == V4L2_STD_ALL) { |
1447 | int status = 0; | 1447 | unsigned int status = 0; |
1448 | v4l2_std_id std = 0; | 1448 | v4l2_std_id std = 0; |
1449 | 1449 | ||
1450 | decoder_call(zr, video, querystd, &std); | 1450 | decoder_call(zr, video, querystd, &std); |
diff --git a/drivers/media/video/zr364xx.c b/drivers/media/video/zr364xx.c index f0eae83e3d89..3d4bac252902 100644 --- a/drivers/media/video/zr364xx.c +++ b/drivers/media/video/zr364xx.c | |||
@@ -78,6 +78,7 @@ | |||
78 | #define METHOD0 0 | 78 | #define METHOD0 0 |
79 | #define METHOD1 1 | 79 | #define METHOD1 1 |
80 | #define METHOD2 2 | 80 | #define METHOD2 2 |
81 | #define METHOD3 3 | ||
81 | 82 | ||
82 | 83 | ||
83 | /* Module parameters */ | 84 | /* Module parameters */ |
@@ -114,7 +115,7 @@ static struct usb_device_id device_table[] = { | |||
114 | {USB_DEVICE(0x06d6, 0x003b), .driver_info = METHOD0 }, | 115 | {USB_DEVICE(0x06d6, 0x003b), .driver_info = METHOD0 }, |
115 | {USB_DEVICE(0x0a17, 0x004e), .driver_info = METHOD2 }, | 116 | {USB_DEVICE(0x0a17, 0x004e), .driver_info = METHOD2 }, |
116 | {USB_DEVICE(0x041e, 0x405d), .driver_info = METHOD2 }, | 117 | {USB_DEVICE(0x041e, 0x405d), .driver_info = METHOD2 }, |
117 | {USB_DEVICE(0x08ca, 0x2102), .driver_info = METHOD2 }, | 118 | {USB_DEVICE(0x08ca, 0x2102), .driver_info = METHOD3 }, |
118 | {USB_DEVICE(0x06d6, 0x003d), .driver_info = METHOD0 }, | 119 | {USB_DEVICE(0x06d6, 0x003d), .driver_info = METHOD0 }, |
119 | {} /* Terminating entry */ | 120 | {} /* Terminating entry */ |
120 | }; | 121 | }; |
@@ -302,7 +303,7 @@ static message m2[] = { | |||
302 | }; | 303 | }; |
303 | 304 | ||
304 | /* init table */ | 305 | /* init table */ |
305 | static message *init[3] = { m0, m1, m2 }; | 306 | static message *init[4] = { m0, m1, m2, m2 }; |
306 | 307 | ||
307 | 308 | ||
308 | /* JPEG static data in header (Huffman table, etc) */ | 309 | /* JPEG static data in header (Huffman table, etc) */ |
@@ -967,6 +968,22 @@ static int zr364xx_vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
967 | m0d1[0] = mode; | 968 | m0d1[0] = mode; |
968 | m1[2].value = 0xf000 + mode; | 969 | m1[2].value = 0xf000 + mode; |
969 | m2[1].value = 0xf000 + mode; | 970 | m2[1].value = 0xf000 + mode; |
971 | |||
972 | /* special case for METHOD3, the modes are different */ | ||
973 | if (cam->method == METHOD3) { | ||
974 | switch (mode) { | ||
975 | case 1: | ||
976 | m2[1].value = 0xf000 + 4; | ||
977 | break; | ||
978 | case 2: | ||
979 | m2[1].value = 0xf000 + 0; | ||
980 | break; | ||
981 | default: | ||
982 | m2[1].value = 0xf000 + 1; | ||
983 | break; | ||
984 | } | ||
985 | } | ||
986 | |||
970 | header2[437] = cam->height / 256; | 987 | header2[437] = cam->height / 256; |
971 | header2[438] = cam->height % 256; | 988 | header2[438] = cam->height % 256; |
972 | header2[439] = cam->width / 256; | 989 | header2[439] = cam->width / 256; |
@@ -1582,6 +1599,22 @@ static int zr364xx_probe(struct usb_interface *intf, | |||
1582 | m0d1[0] = mode; | 1599 | m0d1[0] = mode; |
1583 | m1[2].value = 0xf000 + mode; | 1600 | m1[2].value = 0xf000 + mode; |
1584 | m2[1].value = 0xf000 + mode; | 1601 | m2[1].value = 0xf000 + mode; |
1602 | |||
1603 | /* special case for METHOD3, the modes are different */ | ||
1604 | if (cam->method == METHOD3) { | ||
1605 | switch (mode) { | ||
1606 | case 1: | ||
1607 | m2[1].value = 0xf000 + 4; | ||
1608 | break; | ||
1609 | case 2: | ||
1610 | m2[1].value = 0xf000 + 0; | ||
1611 | break; | ||
1612 | default: | ||
1613 | m2[1].value = 0xf000 + 1; | ||
1614 | break; | ||
1615 | } | ||
1616 | } | ||
1617 | |||
1585 | header2[437] = cam->height / 256; | 1618 | header2[437] = cam->height / 256; |
1586 | header2[438] = cam->height % 256; | 1619 | header2[438] = cam->height % 256; |
1587 | header2[439] = cam->width / 256; | 1620 | header2[439] = cam->width / 256; |
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 87829789243e..413576a2f313 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig | |||
@@ -348,6 +348,16 @@ config AB4500_CORE | |||
348 | read/write functions for the devices to get access to this chip. | 348 | read/write functions for the devices to get access to this chip. |
349 | This chip embeds various other multimedia funtionalities as well. | 349 | This chip embeds various other multimedia funtionalities as well. |
350 | 350 | ||
351 | config MFD_TIMBERDALE | ||
352 | tristate "Support for the Timberdale FPGA" | ||
353 | select MFD_CORE | ||
354 | depends on PCI && GPIOLIB | ||
355 | ---help--- | ||
356 | This is the core driver for the timberdale FPGA. This device is a | ||
357 | multifunction device which exposes numerous platform devices. | ||
358 | |||
359 | The timberdale FPGA can be found on the Intel Atom development board | ||
360 | for in-vehicle infontainment, called Russellville. | ||
351 | endmenu | 361 | endmenu |
352 | 362 | ||
353 | menu "Multimedia Capabilities Port drivers" | 363 | menu "Multimedia Capabilities Port drivers" |
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index e09eb4870db6..78295d6a75f7 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile | |||
@@ -54,5 +54,6 @@ obj-$(CONFIG_PCF50633_GPIO) += pcf50633-gpio.o | |||
54 | obj-$(CONFIG_AB3100_CORE) += ab3100-core.o | 54 | obj-$(CONFIG_AB3100_CORE) += ab3100-core.o |
55 | obj-$(CONFIG_AB3100_OTP) += ab3100-otp.o | 55 | obj-$(CONFIG_AB3100_OTP) += ab3100-otp.o |
56 | obj-$(CONFIG_AB4500_CORE) += ab4500-core.o | 56 | obj-$(CONFIG_AB4500_CORE) += ab4500-core.o |
57 | obj-$(CONFIG_MFD_TIMBERDALE) += timberdale.o | ||
57 | obj-$(CONFIG_MFD_88PM8607) += 88pm8607.o | 58 | obj-$(CONFIG_MFD_88PM8607) += 88pm8607.o |
58 | obj-$(CONFIG_PMIC_ADP5520) += adp5520.o \ No newline at end of file | 59 | obj-$(CONFIG_PMIC_ADP5520) += adp5520.o |
diff --git a/drivers/mfd/timberdale.c b/drivers/mfd/timberdale.c new file mode 100644 index 000000000000..1ed44d283803 --- /dev/null +++ b/drivers/mfd/timberdale.c | |||
@@ -0,0 +1,727 @@ | |||
1 | /* | ||
2 | * timberdale.c timberdale FPGA MFD driver | ||
3 | * Copyright (c) 2009 Intel Corporation | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | */ | ||
18 | |||
19 | /* Supports: | ||
20 | * Timberdale FPGA | ||
21 | */ | ||
22 | |||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/pci.h> | ||
26 | #include <linux/msi.h> | ||
27 | #include <linux/mfd/core.h> | ||
28 | |||
29 | #include <linux/timb_gpio.h> | ||
30 | |||
31 | #include <linux/i2c.h> | ||
32 | #include <linux/i2c-ocores.h> | ||
33 | #include <linux/i2c/tsc2007.h> | ||
34 | |||
35 | #include <linux/spi/spi.h> | ||
36 | #include <linux/spi/xilinx_spi.h> | ||
37 | #include <linux/spi/max7301.h> | ||
38 | #include <linux/spi/mc33880.h> | ||
39 | |||
40 | #include <media/timb_radio.h> | ||
41 | |||
42 | #include "timberdale.h" | ||
43 | |||
44 | #define DRIVER_NAME "timberdale" | ||
45 | |||
46 | struct timberdale_device { | ||
47 | resource_size_t ctl_mapbase; | ||
48 | unsigned char __iomem *ctl_membase; | ||
49 | struct { | ||
50 | u32 major; | ||
51 | u32 minor; | ||
52 | u32 config; | ||
53 | } fw; | ||
54 | }; | ||
55 | |||
56 | /*--------------------------------------------------------------------------*/ | ||
57 | |||
58 | static struct tsc2007_platform_data timberdale_tsc2007_platform_data = { | ||
59 | .model = 2003, | ||
60 | .x_plate_ohms = 100 | ||
61 | }; | ||
62 | |||
63 | static struct i2c_board_info timberdale_i2c_board_info[] = { | ||
64 | { | ||
65 | I2C_BOARD_INFO("tsc2007", 0x48), | ||
66 | .platform_data = &timberdale_tsc2007_platform_data, | ||
67 | .irq = IRQ_TIMBERDALE_TSC_INT | ||
68 | }, | ||
69 | }; | ||
70 | |||
71 | static __devinitdata struct ocores_i2c_platform_data | ||
72 | timberdale_ocores_platform_data = { | ||
73 | .regstep = 4, | ||
74 | .clock_khz = 62500, | ||
75 | .devices = timberdale_i2c_board_info, | ||
76 | .num_devices = ARRAY_SIZE(timberdale_i2c_board_info) | ||
77 | }; | ||
78 | |||
79 | const static __devinitconst struct resource timberdale_ocores_resources[] = { | ||
80 | { | ||
81 | .start = OCORESOFFSET, | ||
82 | .end = OCORESEND, | ||
83 | .flags = IORESOURCE_MEM, | ||
84 | }, | ||
85 | { | ||
86 | .start = IRQ_TIMBERDALE_I2C, | ||
87 | .end = IRQ_TIMBERDALE_I2C, | ||
88 | .flags = IORESOURCE_IRQ, | ||
89 | }, | ||
90 | }; | ||
91 | |||
92 | const struct max7301_platform_data timberdale_max7301_platform_data = { | ||
93 | .base = 200 | ||
94 | }; | ||
95 | |||
96 | const struct mc33880_platform_data timberdale_mc33880_platform_data = { | ||
97 | .base = 100 | ||
98 | }; | ||
99 | |||
100 | static struct spi_board_info timberdale_spi_16bit_board_info[] = { | ||
101 | { | ||
102 | .modalias = "max7301", | ||
103 | .max_speed_hz = 26000, | ||
104 | .chip_select = 2, | ||
105 | .mode = SPI_MODE_0, | ||
106 | .platform_data = &timberdale_max7301_platform_data | ||
107 | }, | ||
108 | }; | ||
109 | |||
110 | static struct spi_board_info timberdale_spi_8bit_board_info[] = { | ||
111 | { | ||
112 | .modalias = "mc33880", | ||
113 | .max_speed_hz = 4000, | ||
114 | .chip_select = 1, | ||
115 | .mode = SPI_MODE_1, | ||
116 | .platform_data = &timberdale_mc33880_platform_data | ||
117 | }, | ||
118 | }; | ||
119 | |||
120 | static __devinitdata struct xspi_platform_data timberdale_xspi_platform_data = { | ||
121 | .num_chipselect = 3, | ||
122 | .little_endian = true, | ||
123 | /* bits per word and devices will be filled in runtime depending | ||
124 | * on the HW config | ||
125 | */ | ||
126 | }; | ||
127 | |||
128 | const static __devinitconst struct resource timberdale_spi_resources[] = { | ||
129 | { | ||
130 | .start = SPIOFFSET, | ||
131 | .end = SPIEND, | ||
132 | .flags = IORESOURCE_MEM, | ||
133 | }, | ||
134 | { | ||
135 | .start = IRQ_TIMBERDALE_SPI, | ||
136 | .end = IRQ_TIMBERDALE_SPI, | ||
137 | .flags = IORESOURCE_IRQ, | ||
138 | }, | ||
139 | }; | ||
140 | |||
141 | const static __devinitconst struct resource timberdale_eth_resources[] = { | ||
142 | { | ||
143 | .start = ETHOFFSET, | ||
144 | .end = ETHEND, | ||
145 | .flags = IORESOURCE_MEM, | ||
146 | }, | ||
147 | { | ||
148 | .start = IRQ_TIMBERDALE_ETHSW_IF, | ||
149 | .end = IRQ_TIMBERDALE_ETHSW_IF, | ||
150 | .flags = IORESOURCE_IRQ, | ||
151 | }, | ||
152 | }; | ||
153 | |||
154 | static __devinitdata struct timbgpio_platform_data | ||
155 | timberdale_gpio_platform_data = { | ||
156 | .gpio_base = 0, | ||
157 | .nr_pins = GPIO_NR_PINS, | ||
158 | .irq_base = 200, | ||
159 | }; | ||
160 | |||
161 | const static __devinitconst struct resource timberdale_gpio_resources[] = { | ||
162 | { | ||
163 | .start = GPIOOFFSET, | ||
164 | .end = GPIOEND, | ||
165 | .flags = IORESOURCE_MEM, | ||
166 | }, | ||
167 | { | ||
168 | .start = IRQ_TIMBERDALE_GPIO, | ||
169 | .end = IRQ_TIMBERDALE_GPIO, | ||
170 | .flags = IORESOURCE_IRQ, | ||
171 | }, | ||
172 | }; | ||
173 | |||
174 | const static __devinitconst struct resource timberdale_mlogicore_resources[] = { | ||
175 | { | ||
176 | .start = MLCOREOFFSET, | ||
177 | .end = MLCOREEND, | ||
178 | .flags = IORESOURCE_MEM, | ||
179 | }, | ||
180 | { | ||
181 | .start = IRQ_TIMBERDALE_MLCORE, | ||
182 | .end = IRQ_TIMBERDALE_MLCORE, | ||
183 | .flags = IORESOURCE_IRQ, | ||
184 | }, | ||
185 | { | ||
186 | .start = IRQ_TIMBERDALE_MLCORE_BUF, | ||
187 | .end = IRQ_TIMBERDALE_MLCORE_BUF, | ||
188 | .flags = IORESOURCE_IRQ, | ||
189 | }, | ||
190 | }; | ||
191 | |||
192 | const static __devinitconst struct resource timberdale_uart_resources[] = { | ||
193 | { | ||
194 | .start = UARTOFFSET, | ||
195 | .end = UARTEND, | ||
196 | .flags = IORESOURCE_MEM, | ||
197 | }, | ||
198 | { | ||
199 | .start = IRQ_TIMBERDALE_UART, | ||
200 | .end = IRQ_TIMBERDALE_UART, | ||
201 | .flags = IORESOURCE_IRQ, | ||
202 | }, | ||
203 | }; | ||
204 | |||
205 | const static __devinitconst struct resource timberdale_uartlite_resources[] = { | ||
206 | { | ||
207 | .start = UARTLITEOFFSET, | ||
208 | .end = UARTLITEEND, | ||
209 | .flags = IORESOURCE_MEM, | ||
210 | }, | ||
211 | { | ||
212 | .start = IRQ_TIMBERDALE_UARTLITE, | ||
213 | .end = IRQ_TIMBERDALE_UARTLITE, | ||
214 | .flags = IORESOURCE_IRQ, | ||
215 | }, | ||
216 | }; | ||
217 | |||
218 | const static __devinitconst struct resource timberdale_radio_resources[] = { | ||
219 | { | ||
220 | .start = RDSOFFSET, | ||
221 | .end = RDSEND, | ||
222 | .flags = IORESOURCE_MEM, | ||
223 | }, | ||
224 | { | ||
225 | .start = IRQ_TIMBERDALE_RDS, | ||
226 | .end = IRQ_TIMBERDALE_RDS, | ||
227 | .flags = IORESOURCE_IRQ, | ||
228 | }, | ||
229 | }; | ||
230 | |||
231 | static __devinitdata struct i2c_board_info timberdale_tef6868_i2c_board_info = { | ||
232 | I2C_BOARD_INFO("tef6862", 0x60) | ||
233 | }; | ||
234 | |||
235 | static __devinitdata struct i2c_board_info timberdale_saa7706_i2c_board_info = { | ||
236 | I2C_BOARD_INFO("saa7706h", 0x1C) | ||
237 | }; | ||
238 | |||
239 | static __devinitdata struct timb_radio_platform_data | ||
240 | timberdale_radio_platform_data = { | ||
241 | .i2c_adapter = 0, | ||
242 | .tuner = { | ||
243 | .module_name = "tef6862", | ||
244 | .info = &timberdale_tef6868_i2c_board_info | ||
245 | }, | ||
246 | .dsp = { | ||
247 | .module_name = "saa7706h", | ||
248 | .info = &timberdale_saa7706_i2c_board_info | ||
249 | } | ||
250 | }; | ||
251 | |||
252 | const static __devinitconst struct resource timberdale_dma_resources[] = { | ||
253 | { | ||
254 | .start = DMAOFFSET, | ||
255 | .end = DMAEND, | ||
256 | .flags = IORESOURCE_MEM, | ||
257 | }, | ||
258 | { | ||
259 | .start = IRQ_TIMBERDALE_DMA, | ||
260 | .end = IRQ_TIMBERDALE_DMA, | ||
261 | .flags = IORESOURCE_IRQ, | ||
262 | }, | ||
263 | }; | ||
264 | |||
265 | static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg0[] = { | ||
266 | { | ||
267 | .name = "timb-uart", | ||
268 | .num_resources = ARRAY_SIZE(timberdale_uart_resources), | ||
269 | .resources = timberdale_uart_resources, | ||
270 | }, | ||
271 | { | ||
272 | .name = "timb-gpio", | ||
273 | .num_resources = ARRAY_SIZE(timberdale_gpio_resources), | ||
274 | .resources = timberdale_gpio_resources, | ||
275 | .platform_data = &timberdale_gpio_platform_data, | ||
276 | .data_size = sizeof(timberdale_gpio_platform_data), | ||
277 | }, | ||
278 | { | ||
279 | .name = "timb-radio", | ||
280 | .num_resources = ARRAY_SIZE(timberdale_radio_resources), | ||
281 | .resources = timberdale_radio_resources, | ||
282 | .platform_data = &timberdale_radio_platform_data, | ||
283 | .data_size = sizeof(timberdale_radio_platform_data), | ||
284 | }, | ||
285 | { | ||
286 | .name = "xilinx_spi", | ||
287 | .num_resources = ARRAY_SIZE(timberdale_spi_resources), | ||
288 | .resources = timberdale_spi_resources, | ||
289 | .platform_data = &timberdale_xspi_platform_data, | ||
290 | .data_size = sizeof(timberdale_xspi_platform_data), | ||
291 | }, | ||
292 | { | ||
293 | .name = "ks8842", | ||
294 | .num_resources = ARRAY_SIZE(timberdale_eth_resources), | ||
295 | .resources = timberdale_eth_resources, | ||
296 | }, | ||
297 | { | ||
298 | .name = "timb-dma", | ||
299 | .num_resources = ARRAY_SIZE(timberdale_dma_resources), | ||
300 | .resources = timberdale_dma_resources, | ||
301 | }, | ||
302 | }; | ||
303 | |||
304 | static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg1[] = { | ||
305 | { | ||
306 | .name = "timb-uart", | ||
307 | .num_resources = ARRAY_SIZE(timberdale_uart_resources), | ||
308 | .resources = timberdale_uart_resources, | ||
309 | }, | ||
310 | { | ||
311 | .name = "uartlite", | ||
312 | .num_resources = ARRAY_SIZE(timberdale_uartlite_resources), | ||
313 | .resources = timberdale_uartlite_resources, | ||
314 | }, | ||
315 | { | ||
316 | .name = "timb-gpio", | ||
317 | .num_resources = ARRAY_SIZE(timberdale_gpio_resources), | ||
318 | .resources = timberdale_gpio_resources, | ||
319 | .platform_data = &timberdale_gpio_platform_data, | ||
320 | .data_size = sizeof(timberdale_gpio_platform_data), | ||
321 | }, | ||
322 | { | ||
323 | .name = "timb-mlogicore", | ||
324 | .num_resources = ARRAY_SIZE(timberdale_mlogicore_resources), | ||
325 | .resources = timberdale_mlogicore_resources, | ||
326 | }, | ||
327 | { | ||
328 | .name = "timb-radio", | ||
329 | .num_resources = ARRAY_SIZE(timberdale_radio_resources), | ||
330 | .resources = timberdale_radio_resources, | ||
331 | .platform_data = &timberdale_radio_platform_data, | ||
332 | .data_size = sizeof(timberdale_radio_platform_data), | ||
333 | }, | ||
334 | { | ||
335 | .name = "xilinx_spi", | ||
336 | .num_resources = ARRAY_SIZE(timberdale_spi_resources), | ||
337 | .resources = timberdale_spi_resources, | ||
338 | .platform_data = &timberdale_xspi_platform_data, | ||
339 | .data_size = sizeof(timberdale_xspi_platform_data), | ||
340 | }, | ||
341 | { | ||
342 | .name = "ks8842", | ||
343 | .num_resources = ARRAY_SIZE(timberdale_eth_resources), | ||
344 | .resources = timberdale_eth_resources, | ||
345 | }, | ||
346 | { | ||
347 | .name = "timb-dma", | ||
348 | .num_resources = ARRAY_SIZE(timberdale_dma_resources), | ||
349 | .resources = timberdale_dma_resources, | ||
350 | }, | ||
351 | }; | ||
352 | |||
353 | static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg2[] = { | ||
354 | { | ||
355 | .name = "timb-uart", | ||
356 | .num_resources = ARRAY_SIZE(timberdale_uart_resources), | ||
357 | .resources = timberdale_uart_resources, | ||
358 | }, | ||
359 | { | ||
360 | .name = "timb-gpio", | ||
361 | .num_resources = ARRAY_SIZE(timberdale_gpio_resources), | ||
362 | .resources = timberdale_gpio_resources, | ||
363 | .platform_data = &timberdale_gpio_platform_data, | ||
364 | .data_size = sizeof(timberdale_gpio_platform_data), | ||
365 | }, | ||
366 | { | ||
367 | .name = "timb-radio", | ||
368 | .num_resources = ARRAY_SIZE(timberdale_radio_resources), | ||
369 | .resources = timberdale_radio_resources, | ||
370 | .platform_data = &timberdale_radio_platform_data, | ||
371 | .data_size = sizeof(timberdale_radio_platform_data), | ||
372 | }, | ||
373 | { | ||
374 | .name = "xilinx_spi", | ||
375 | .num_resources = ARRAY_SIZE(timberdale_spi_resources), | ||
376 | .resources = timberdale_spi_resources, | ||
377 | .platform_data = &timberdale_xspi_platform_data, | ||
378 | .data_size = sizeof(timberdale_xspi_platform_data), | ||
379 | }, | ||
380 | { | ||
381 | .name = "timb-dma", | ||
382 | .num_resources = ARRAY_SIZE(timberdale_dma_resources), | ||
383 | .resources = timberdale_dma_resources, | ||
384 | }, | ||
385 | }; | ||
386 | |||
387 | static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg3[] = { | ||
388 | { | ||
389 | .name = "timb-uart", | ||
390 | .num_resources = ARRAY_SIZE(timberdale_uart_resources), | ||
391 | .resources = timberdale_uart_resources, | ||
392 | }, | ||
393 | { | ||
394 | .name = "ocores-i2c", | ||
395 | .num_resources = ARRAY_SIZE(timberdale_ocores_resources), | ||
396 | .resources = timberdale_ocores_resources, | ||
397 | .platform_data = &timberdale_ocores_platform_data, | ||
398 | .data_size = sizeof(timberdale_ocores_platform_data), | ||
399 | }, | ||
400 | { | ||
401 | .name = "timb-gpio", | ||
402 | .num_resources = ARRAY_SIZE(timberdale_gpio_resources), | ||
403 | .resources = timberdale_gpio_resources, | ||
404 | .platform_data = &timberdale_gpio_platform_data, | ||
405 | .data_size = sizeof(timberdale_gpio_platform_data), | ||
406 | }, | ||
407 | { | ||
408 | .name = "timb-radio", | ||
409 | .num_resources = ARRAY_SIZE(timberdale_radio_resources), | ||
410 | .resources = timberdale_radio_resources, | ||
411 | .platform_data = &timberdale_radio_platform_data, | ||
412 | .data_size = sizeof(timberdale_radio_platform_data), | ||
413 | }, | ||
414 | { | ||
415 | .name = "xilinx_spi", | ||
416 | .num_resources = ARRAY_SIZE(timberdale_spi_resources), | ||
417 | .resources = timberdale_spi_resources, | ||
418 | .platform_data = &timberdale_xspi_platform_data, | ||
419 | .data_size = sizeof(timberdale_xspi_platform_data), | ||
420 | }, | ||
421 | { | ||
422 | .name = "ks8842", | ||
423 | .num_resources = ARRAY_SIZE(timberdale_eth_resources), | ||
424 | .resources = timberdale_eth_resources, | ||
425 | }, | ||
426 | { | ||
427 | .name = "timb-dma", | ||
428 | .num_resources = ARRAY_SIZE(timberdale_dma_resources), | ||
429 | .resources = timberdale_dma_resources, | ||
430 | }, | ||
431 | }; | ||
432 | |||
433 | static const __devinitconst struct resource timberdale_sdhc_resources[] = { | ||
434 | /* located in bar 1 and bar 2 */ | ||
435 | { | ||
436 | .start = SDHC0OFFSET, | ||
437 | .end = SDHC0END, | ||
438 | .flags = IORESOURCE_MEM, | ||
439 | }, | ||
440 | { | ||
441 | .start = IRQ_TIMBERDALE_SDHC, | ||
442 | .end = IRQ_TIMBERDALE_SDHC, | ||
443 | .flags = IORESOURCE_IRQ, | ||
444 | }, | ||
445 | }; | ||
446 | |||
447 | static __devinitdata struct mfd_cell timberdale_cells_bar1[] = { | ||
448 | { | ||
449 | .name = "sdhci", | ||
450 | .num_resources = ARRAY_SIZE(timberdale_sdhc_resources), | ||
451 | .resources = timberdale_sdhc_resources, | ||
452 | }, | ||
453 | }; | ||
454 | |||
455 | static __devinitdata struct mfd_cell timberdale_cells_bar2[] = { | ||
456 | { | ||
457 | .name = "sdhci", | ||
458 | .num_resources = ARRAY_SIZE(timberdale_sdhc_resources), | ||
459 | .resources = timberdale_sdhc_resources, | ||
460 | }, | ||
461 | }; | ||
462 | |||
463 | static ssize_t show_fw_ver(struct device *dev, struct device_attribute *attr, | ||
464 | char *buf) | ||
465 | { | ||
466 | struct pci_dev *pdev = to_pci_dev(dev); | ||
467 | struct timberdale_device *priv = pci_get_drvdata(pdev); | ||
468 | |||
469 | return sprintf(buf, "%d.%d.%d\n", priv->fw.major, priv->fw.minor, | ||
470 | priv->fw.config); | ||
471 | } | ||
472 | |||
473 | static DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL); | ||
474 | |||
475 | /*--------------------------------------------------------------------------*/ | ||
476 | |||
477 | static int __devinit timb_probe(struct pci_dev *dev, | ||
478 | const struct pci_device_id *id) | ||
479 | { | ||
480 | struct timberdale_device *priv; | ||
481 | int err, i; | ||
482 | resource_size_t mapbase; | ||
483 | struct msix_entry *msix_entries = NULL; | ||
484 | u8 ip_setup; | ||
485 | |||
486 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
487 | if (!priv) | ||
488 | return -ENOMEM; | ||
489 | |||
490 | pci_set_drvdata(dev, priv); | ||
491 | |||
492 | err = pci_enable_device(dev); | ||
493 | if (err) | ||
494 | goto err_enable; | ||
495 | |||
496 | mapbase = pci_resource_start(dev, 0); | ||
497 | if (!mapbase) { | ||
498 | dev_err(&dev->dev, "No resource\n"); | ||
499 | goto err_start; | ||
500 | } | ||
501 | |||
502 | /* create a resource for the PCI master register */ | ||
503 | priv->ctl_mapbase = mapbase + CHIPCTLOFFSET; | ||
504 | if (!request_mem_region(priv->ctl_mapbase, CHIPCTLSIZE, "timb-ctl")) { | ||
505 | dev_err(&dev->dev, "Failed to request ctl mem\n"); | ||
506 | goto err_request; | ||
507 | } | ||
508 | |||
509 | priv->ctl_membase = ioremap(priv->ctl_mapbase, CHIPCTLSIZE); | ||
510 | if (!priv->ctl_membase) { | ||
511 | dev_err(&dev->dev, "ioremap failed for ctl mem\n"); | ||
512 | goto err_ioremap; | ||
513 | } | ||
514 | |||
515 | /* read the HW config */ | ||
516 | priv->fw.major = ioread32(priv->ctl_membase + TIMB_REV_MAJOR); | ||
517 | priv->fw.minor = ioread32(priv->ctl_membase + TIMB_REV_MINOR); | ||
518 | priv->fw.config = ioread32(priv->ctl_membase + TIMB_HW_CONFIG); | ||
519 | |||
520 | if (priv->fw.major > TIMB_SUPPORTED_MAJOR) { | ||
521 | dev_err(&dev->dev, "The driver supports an older " | ||
522 | "version of the FPGA, please update the driver to " | ||
523 | "support %d.%d\n", priv->fw.major, priv->fw.minor); | ||
524 | goto err_ioremap; | ||
525 | } | ||
526 | if (priv->fw.major < TIMB_SUPPORTED_MAJOR || | ||
527 | priv->fw.minor < TIMB_REQUIRED_MINOR) { | ||
528 | dev_err(&dev->dev, "The FPGA image is too old (%d.%d), " | ||
529 | "please upgrade the FPGA to at least: %d.%d\n", | ||
530 | priv->fw.major, priv->fw.minor, | ||
531 | TIMB_SUPPORTED_MAJOR, TIMB_REQUIRED_MINOR); | ||
532 | goto err_ioremap; | ||
533 | } | ||
534 | |||
535 | msix_entries = kzalloc(TIMBERDALE_NR_IRQS * sizeof(*msix_entries), | ||
536 | GFP_KERNEL); | ||
537 | if (!msix_entries) | ||
538 | goto err_ioremap; | ||
539 | |||
540 | for (i = 0; i < TIMBERDALE_NR_IRQS; i++) | ||
541 | msix_entries[i].entry = i; | ||
542 | |||
543 | err = pci_enable_msix(dev, msix_entries, TIMBERDALE_NR_IRQS); | ||
544 | if (err) { | ||
545 | dev_err(&dev->dev, | ||
546 | "MSI-X init failed: %d, expected entries: %d\n", | ||
547 | err, TIMBERDALE_NR_IRQS); | ||
548 | goto err_msix; | ||
549 | } | ||
550 | |||
551 | err = device_create_file(&dev->dev, &dev_attr_fw_ver); | ||
552 | if (err) | ||
553 | goto err_create_file; | ||
554 | |||
555 | /* Reset all FPGA PLB peripherals */ | ||
556 | iowrite32(0x1, priv->ctl_membase + TIMB_SW_RST); | ||
557 | |||
558 | /* update IRQ offsets in I2C board info */ | ||
559 | for (i = 0; i < ARRAY_SIZE(timberdale_i2c_board_info); i++) | ||
560 | timberdale_i2c_board_info[i].irq = | ||
561 | msix_entries[timberdale_i2c_board_info[i].irq].vector; | ||
562 | |||
563 | /* Update the SPI configuration depending on the HW (8 or 16 bit) */ | ||
564 | if (priv->fw.config & TIMB_HW_CONFIG_SPI_8BIT) { | ||
565 | timberdale_xspi_platform_data.bits_per_word = 8; | ||
566 | timberdale_xspi_platform_data.devices = | ||
567 | timberdale_spi_8bit_board_info; | ||
568 | timberdale_xspi_platform_data.num_devices = | ||
569 | ARRAY_SIZE(timberdale_spi_8bit_board_info); | ||
570 | } else { | ||
571 | timberdale_xspi_platform_data.bits_per_word = 16; | ||
572 | timberdale_xspi_platform_data.devices = | ||
573 | timberdale_spi_16bit_board_info; | ||
574 | timberdale_xspi_platform_data.num_devices = | ||
575 | ARRAY_SIZE(timberdale_spi_16bit_board_info); | ||
576 | } | ||
577 | |||
578 | ip_setup = priv->fw.config & TIMB_HW_VER_MASK; | ||
579 | switch (ip_setup) { | ||
580 | case TIMB_HW_VER0: | ||
581 | err = mfd_add_devices(&dev->dev, -1, | ||
582 | timberdale_cells_bar0_cfg0, | ||
583 | ARRAY_SIZE(timberdale_cells_bar0_cfg0), | ||
584 | &dev->resource[0], msix_entries[0].vector); | ||
585 | break; | ||
586 | case TIMB_HW_VER1: | ||
587 | err = mfd_add_devices(&dev->dev, -1, | ||
588 | timberdale_cells_bar0_cfg1, | ||
589 | ARRAY_SIZE(timberdale_cells_bar0_cfg1), | ||
590 | &dev->resource[0], msix_entries[0].vector); | ||
591 | break; | ||
592 | case TIMB_HW_VER2: | ||
593 | err = mfd_add_devices(&dev->dev, -1, | ||
594 | timberdale_cells_bar0_cfg2, | ||
595 | ARRAY_SIZE(timberdale_cells_bar0_cfg2), | ||
596 | &dev->resource[0], msix_entries[0].vector); | ||
597 | break; | ||
598 | case TIMB_HW_VER3: | ||
599 | err = mfd_add_devices(&dev->dev, -1, | ||
600 | timberdale_cells_bar0_cfg3, | ||
601 | ARRAY_SIZE(timberdale_cells_bar0_cfg3), | ||
602 | &dev->resource[0], msix_entries[0].vector); | ||
603 | break; | ||
604 | default: | ||
605 | dev_err(&dev->dev, "Uknown IP setup: %d.%d.%d\n", | ||
606 | priv->fw.major, priv->fw.minor, ip_setup); | ||
607 | err = -ENODEV; | ||
608 | goto err_mfd; | ||
609 | break; | ||
610 | } | ||
611 | |||
612 | if (err) { | ||
613 | dev_err(&dev->dev, "mfd_add_devices failed: %d\n", err); | ||
614 | goto err_mfd; | ||
615 | } | ||
616 | |||
617 | err = mfd_add_devices(&dev->dev, 0, | ||
618 | timberdale_cells_bar1, ARRAY_SIZE(timberdale_cells_bar1), | ||
619 | &dev->resource[1], msix_entries[0].vector); | ||
620 | if (err) { | ||
621 | dev_err(&dev->dev, "mfd_add_devices failed: %d\n", err); | ||
622 | goto err_mfd2; | ||
623 | } | ||
624 | |||
625 | /* only version 0 and 3 have the iNand routed to SDHCI */ | ||
626 | if (((priv->fw.config & TIMB_HW_VER_MASK) == TIMB_HW_VER0) || | ||
627 | ((priv->fw.config & TIMB_HW_VER_MASK) == TIMB_HW_VER3)) { | ||
628 | err = mfd_add_devices(&dev->dev, 1, timberdale_cells_bar2, | ||
629 | ARRAY_SIZE(timberdale_cells_bar2), | ||
630 | &dev->resource[2], msix_entries[0].vector); | ||
631 | if (err) { | ||
632 | dev_err(&dev->dev, "mfd_add_devices failed: %d\n", err); | ||
633 | goto err_mfd2; | ||
634 | } | ||
635 | } | ||
636 | |||
637 | kfree(msix_entries); | ||
638 | |||
639 | dev_info(&dev->dev, | ||
640 | "Found Timberdale Card. Rev: %d.%d, HW config: 0x%02x\n", | ||
641 | priv->fw.major, priv->fw.minor, priv->fw.config); | ||
642 | |||
643 | return 0; | ||
644 | |||
645 | err_mfd2: | ||
646 | mfd_remove_devices(&dev->dev); | ||
647 | err_mfd: | ||
648 | device_remove_file(&dev->dev, &dev_attr_fw_ver); | ||
649 | err_create_file: | ||
650 | pci_disable_msix(dev); | ||
651 | err_msix: | ||
652 | iounmap(priv->ctl_membase); | ||
653 | err_ioremap: | ||
654 | release_mem_region(priv->ctl_mapbase, CHIPCTLSIZE); | ||
655 | err_request: | ||
656 | pci_set_drvdata(dev, NULL); | ||
657 | err_start: | ||
658 | pci_disable_device(dev); | ||
659 | err_enable: | ||
660 | kfree(msix_entries); | ||
661 | kfree(priv); | ||
662 | pci_set_drvdata(dev, NULL); | ||
663 | return -ENODEV; | ||
664 | } | ||
665 | |||
666 | static void __devexit timb_remove(struct pci_dev *dev) | ||
667 | { | ||
668 | struct timberdale_device *priv = pci_get_drvdata(dev); | ||
669 | |||
670 | mfd_remove_devices(&dev->dev); | ||
671 | |||
672 | device_remove_file(&dev->dev, &dev_attr_fw_ver); | ||
673 | |||
674 | iounmap(priv->ctl_membase); | ||
675 | release_mem_region(priv->ctl_mapbase, CHIPCTLSIZE); | ||
676 | |||
677 | pci_disable_msix(dev); | ||
678 | pci_disable_device(dev); | ||
679 | pci_set_drvdata(dev, NULL); | ||
680 | kfree(priv); | ||
681 | } | ||
682 | |||
683 | static struct pci_device_id timberdale_pci_tbl[] = { | ||
684 | { PCI_DEVICE(PCI_VENDOR_ID_TIMB, PCI_DEVICE_ID_TIMB) }, | ||
685 | { 0 } | ||
686 | }; | ||
687 | MODULE_DEVICE_TABLE(pci, timberdale_pci_tbl); | ||
688 | |||
689 | static struct pci_driver timberdale_pci_driver = { | ||
690 | .name = DRIVER_NAME, | ||
691 | .id_table = timberdale_pci_tbl, | ||
692 | .probe = timb_probe, | ||
693 | .remove = __devexit_p(timb_remove), | ||
694 | }; | ||
695 | |||
696 | static int __init timberdale_init(void) | ||
697 | { | ||
698 | int err; | ||
699 | |||
700 | err = pci_register_driver(&timberdale_pci_driver); | ||
701 | if (err < 0) { | ||
702 | printk(KERN_ERR | ||
703 | "Failed to register PCI driver for %s device.\n", | ||
704 | timberdale_pci_driver.name); | ||
705 | return -ENODEV; | ||
706 | } | ||
707 | |||
708 | printk(KERN_INFO "Driver for %s has been successfully registered.\n", | ||
709 | timberdale_pci_driver.name); | ||
710 | |||
711 | return 0; | ||
712 | } | ||
713 | |||
714 | static void __exit timberdale_exit(void) | ||
715 | { | ||
716 | pci_unregister_driver(&timberdale_pci_driver); | ||
717 | |||
718 | printk(KERN_INFO "Driver for %s has been successfully unregistered.\n", | ||
719 | timberdale_pci_driver.name); | ||
720 | } | ||
721 | |||
722 | module_init(timberdale_init); | ||
723 | module_exit(timberdale_exit); | ||
724 | |||
725 | MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>"); | ||
726 | MODULE_VERSION(DRV_VERSION); | ||
727 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/mfd/timberdale.h b/drivers/mfd/timberdale.h new file mode 100644 index 000000000000..8d27ffabc25d --- /dev/null +++ b/drivers/mfd/timberdale.h | |||
@@ -0,0 +1,130 @@ | |||
1 | /* | ||
2 | * timberdale.h timberdale FPGA MFD driver defines | ||
3 | * Copyright (c) 2009 Intel Corporation | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | */ | ||
18 | |||
19 | /* Supports: | ||
20 | * Timberdale FPGA | ||
21 | */ | ||
22 | |||
23 | #ifndef MFD_TIMBERDALE_H | ||
24 | #define MFD_TIMBERDALE_H | ||
25 | |||
26 | #define DRV_VERSION "0.1" | ||
27 | |||
28 | /* This driver only support versions >= 3.8 and < 4.0 */ | ||
29 | #define TIMB_SUPPORTED_MAJOR 3 | ||
30 | |||
31 | /* This driver only support minor >= 8 */ | ||
32 | #define TIMB_REQUIRED_MINOR 8 | ||
33 | |||
34 | /* Registers of the control area */ | ||
35 | #define TIMB_REV_MAJOR 0x00 | ||
36 | #define TIMB_REV_MINOR 0x04 | ||
37 | #define TIMB_HW_CONFIG 0x08 | ||
38 | #define TIMB_SW_RST 0x40 | ||
39 | |||
40 | /* bits in the TIMB_HW_CONFIG register */ | ||
41 | #define TIMB_HW_CONFIG_SPI_8BIT 0x80 | ||
42 | |||
43 | #define TIMB_HW_VER_MASK 0x0f | ||
44 | #define TIMB_HW_VER0 0x00 | ||
45 | #define TIMB_HW_VER1 0x01 | ||
46 | #define TIMB_HW_VER2 0x02 | ||
47 | #define TIMB_HW_VER3 0x03 | ||
48 | |||
49 | #define OCORESOFFSET 0x0 | ||
50 | #define OCORESEND 0x1f | ||
51 | |||
52 | #define SPIOFFSET 0x80 | ||
53 | #define SPIEND 0xff | ||
54 | |||
55 | #define UARTLITEOFFSET 0x100 | ||
56 | #define UARTLITEEND 0x10f | ||
57 | |||
58 | #define RDSOFFSET 0x180 | ||
59 | #define RDSEND 0x183 | ||
60 | |||
61 | #define ETHOFFSET 0x300 | ||
62 | #define ETHEND 0x3ff | ||
63 | |||
64 | #define GPIOOFFSET 0x400 | ||
65 | #define GPIOEND 0x7ff | ||
66 | |||
67 | #define CHIPCTLOFFSET 0x800 | ||
68 | #define CHIPCTLEND 0x8ff | ||
69 | #define CHIPCTLSIZE (CHIPCTLEND - CHIPCTLOFFSET) | ||
70 | |||
71 | #define INTCOFFSET 0xc00 | ||
72 | #define INTCEND 0xfff | ||
73 | #define INTCSIZE (INTCEND - INTCOFFSET) | ||
74 | |||
75 | #define MOSTOFFSET 0x1000 | ||
76 | #define MOSTEND 0x13ff | ||
77 | |||
78 | #define UARTOFFSET 0x1400 | ||
79 | #define UARTEND 0x17ff | ||
80 | |||
81 | #define XIICOFFSET 0x1800 | ||
82 | #define XIICEND 0x19ff | ||
83 | |||
84 | #define I2SOFFSET 0x1C00 | ||
85 | #define I2SEND 0x1fff | ||
86 | |||
87 | #define LOGIWOFFSET 0x30000 | ||
88 | #define LOGIWEND 0x37fff | ||
89 | |||
90 | #define MLCOREOFFSET 0x40000 | ||
91 | #define MLCOREEND 0x43fff | ||
92 | |||
93 | #define DMAOFFSET 0x01000000 | ||
94 | #define DMAEND 0x013fffff | ||
95 | |||
96 | /* SDHC0 is placed in PCI bar 1 */ | ||
97 | #define SDHC0OFFSET 0x00 | ||
98 | #define SDHC0END 0xff | ||
99 | |||
100 | /* SDHC1 is placed in PCI bar 2 */ | ||
101 | #define SDHC1OFFSET 0x00 | ||
102 | #define SDHC1END 0xff | ||
103 | |||
104 | #define PCI_VENDOR_ID_TIMB 0x10ee | ||
105 | #define PCI_DEVICE_ID_TIMB 0xa123 | ||
106 | |||
107 | #define IRQ_TIMBERDALE_INIC 0 | ||
108 | #define IRQ_TIMBERDALE_MLB 1 | ||
109 | #define IRQ_TIMBERDALE_GPIO 2 | ||
110 | #define IRQ_TIMBERDALE_I2C 3 | ||
111 | #define IRQ_TIMBERDALE_UART 4 | ||
112 | #define IRQ_TIMBERDALE_DMA 5 | ||
113 | #define IRQ_TIMBERDALE_I2S 6 | ||
114 | #define IRQ_TIMBERDALE_TSC_INT 7 | ||
115 | #define IRQ_TIMBERDALE_SDHC 8 | ||
116 | #define IRQ_TIMBERDALE_ADV7180 9 | ||
117 | #define IRQ_TIMBERDALE_ETHSW_IF 10 | ||
118 | #define IRQ_TIMBERDALE_SPI 11 | ||
119 | #define IRQ_TIMBERDALE_UARTLITE 12 | ||
120 | #define IRQ_TIMBERDALE_MLCORE 13 | ||
121 | #define IRQ_TIMBERDALE_MLCORE_BUF 14 | ||
122 | #define IRQ_TIMBERDALE_RDS 15 | ||
123 | #define TIMBERDALE_NR_IRQS 16 | ||
124 | |||
125 | #define GPIO_PIN_ASCB 8 | ||
126 | #define GPIO_PIN_INIC_RST 14 | ||
127 | #define GPIO_PIN_BT_RST 15 | ||
128 | #define GPIO_NR_PINS 16 | ||
129 | |||
130 | #endif | ||
diff --git a/drivers/staging/go7007/s2250-board.c b/drivers/staging/go7007/s2250-board.c index 8cf7f2750b3f..c324f6ea002b 100644 --- a/drivers/staging/go7007/s2250-board.c +++ b/drivers/staging/go7007/s2250-board.c | |||
@@ -159,7 +159,7 @@ static int write_reg(struct i2c_client *client, u8 reg, u8 value) | |||
159 | struct go7007 *go = i2c_get_adapdata(client->adapter); | 159 | struct go7007 *go = i2c_get_adapdata(client->adapter); |
160 | struct go7007_usb *usb; | 160 | struct go7007_usb *usb; |
161 | int rc; | 161 | int rc; |
162 | int dev_addr = client->addr; | 162 | int dev_addr = client->addr << 1; /* firmware wants 8-bit address */ |
163 | u8 *buf; | 163 | u8 *buf; |
164 | 164 | ||
165 | if (go == NULL) | 165 | if (go == NULL) |