diff options
author | David S. Miller <davem@davemloft.net> | 2010-01-23 01:45:46 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-01-23 01:45:46 -0500 |
commit | 6be325719b3e54624397e413efd4b33a997e55a3 (patch) | |
tree | 57f321a56794cab2222e179b16731e0d76a4a68a /drivers/media | |
parent | 26d92f9276a56d55511a427fb70bd70886af647a (diff) | |
parent | 92dcffb916d309aa01778bf8963a6932e4014d07 (diff) |
Merge branch 'master' of /home/davem/src/GIT/linux-2.6/
Diffstat (limited to 'drivers/media')
239 files changed, 16597 insertions, 3741 deletions
diff --git a/drivers/media/IR/Kconfig b/drivers/media/IR/Kconfig new file mode 100644 index 000000000000..4dde7d180a32 --- /dev/null +++ b/drivers/media/IR/Kconfig | |||
@@ -0,0 +1,9 @@ | |||
1 | config IR_CORE | ||
2 | tristate | ||
3 | depends on INPUT | ||
4 | default INPUT | ||
5 | |||
6 | config VIDEO_IR | ||
7 | tristate | ||
8 | depends on IR_CORE | ||
9 | default IR_CORE | ||
diff --git a/drivers/media/IR/Makefile b/drivers/media/IR/Makefile new file mode 100644 index 000000000000..df5ddb4bbbf7 --- /dev/null +++ b/drivers/media/IR/Makefile | |||
@@ -0,0 +1,5 @@ | |||
1 | ir-common-objs := ir-functions.o ir-keymaps.o | ||
2 | ir-core-objs := ir-keytable.o | ||
3 | |||
4 | obj-$(CONFIG_IR_CORE) += ir-core.o | ||
5 | obj-$(CONFIG_VIDEO_IR) += ir-common.o | ||
diff --git a/drivers/media/common/ir-functions.c b/drivers/media/IR/ir-functions.c index e616f624ceaa..776a136616d6 100644 --- a/drivers/media/common/ir-functions.c +++ b/drivers/media/IR/ir-functions.c | |||
@@ -34,9 +34,6 @@ static int repeat = 1; | |||
34 | module_param(repeat, int, 0444); | 34 | module_param(repeat, int, 0444); |
35 | MODULE_PARM_DESC(repeat,"auto-repeat for IR keys (default: on)"); | 35 | MODULE_PARM_DESC(repeat,"auto-repeat for IR keys (default: on)"); |
36 | 36 | ||
37 | int media_ir_debug; /* media_ir_debug level (0,1,2) */ | ||
38 | module_param_named(debug, media_ir_debug, int, 0644); | ||
39 | |||
40 | /* -------------------------------------------------------------------------- */ | 37 | /* -------------------------------------------------------------------------- */ |
41 | 38 | ||
42 | static void ir_input_key_event(struct input_dev *dev, struct ir_input_state *ir) | 39 | static void ir_input_key_event(struct input_dev *dev, struct ir_input_state *ir) |
@@ -55,25 +52,10 @@ static void ir_input_key_event(struct input_dev *dev, struct ir_input_state *ir) | |||
55 | /* -------------------------------------------------------------------------- */ | 52 | /* -------------------------------------------------------------------------- */ |
56 | 53 | ||
57 | 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, |
58 | int ir_type, struct ir_scancode_table *ir_codes) | 55 | int ir_type) |
59 | { | 56 | { |
60 | ir->ir_type = ir_type; | 57 | ir->ir_type = ir_type; |
61 | 58 | ||
62 | ir->keytable.size = ir_roundup_tablesize(ir_codes->size); | ||
63 | ir->keytable.scan = kzalloc(ir->keytable.size * | ||
64 | sizeof(struct ir_scancode), GFP_KERNEL); | ||
65 | if (!ir->keytable.scan) | ||
66 | return -ENOMEM; | ||
67 | |||
68 | IR_dprintk(1, "Allocated space for %d keycode entries (%zd bytes)\n", | ||
69 | ir->keytable.size, | ||
70 | ir->keytable.size * sizeof(ir->keytable.scan)); | ||
71 | |||
72 | ir_copy_table(&ir->keytable, ir_codes); | ||
73 | ir_set_keycode_table(dev, &ir->keytable); | ||
74 | |||
75 | clear_bit(0, dev->keybit); | ||
76 | set_bit(EV_KEY, dev->evbit); | ||
77 | if (repeat) | 59 | if (repeat) |
78 | set_bit(EV_REP, dev->evbit); | 60 | set_bit(EV_REP, dev->evbit); |
79 | 61 | ||
diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/IR/ir-keymaps.c index 328c973a0838..9bbe6b1e9871 100644 --- a/drivers/media/common/ir-keymaps.c +++ b/drivers/media/IR/ir-keymaps.c | |||
@@ -1847,76 +1847,6 @@ struct ir_scancode_table ir_codes_hauppauge_new_table = { | |||
1847 | }; | 1847 | }; |
1848 | EXPORT_SYMBOL_GPL(ir_codes_hauppauge_new_table); | 1848 | EXPORT_SYMBOL_GPL(ir_codes_hauppauge_new_table); |
1849 | 1849 | ||
1850 | /* | ||
1851 | * Hauppauge:the newer, gray remotes (seems there are multiple | ||
1852 | * slightly different versions), shipped with cx88+ivtv cards. | ||
1853 | * | ||
1854 | * This table contains the complete RC5 code, instead of just the data part | ||
1855 | */ | ||
1856 | static struct ir_scancode ir_codes_rc5_hauppauge_new[] = { | ||
1857 | /* Keys 0 to 9 */ | ||
1858 | { 0x1e00, KEY_0 }, | ||
1859 | { 0x1e01, KEY_1 }, | ||
1860 | { 0x1e02, KEY_2 }, | ||
1861 | { 0x1e03, KEY_3 }, | ||
1862 | { 0x1e04, KEY_4 }, | ||
1863 | { 0x1e05, KEY_5 }, | ||
1864 | { 0x1e06, KEY_6 }, | ||
1865 | { 0x1e07, KEY_7 }, | ||
1866 | { 0x1e08, KEY_8 }, | ||
1867 | { 0x1e09, KEY_9 }, | ||
1868 | |||
1869 | { 0x1e0a, KEY_TEXT }, /* keypad asterisk as well */ | ||
1870 | { 0x1e0b, KEY_RED }, /* red button */ | ||
1871 | { 0x1e0c, KEY_RADIO }, | ||
1872 | { 0x1e0d, KEY_MENU }, | ||
1873 | { 0x1e0e, KEY_SUBTITLE }, /* also the # key */ | ||
1874 | { 0x1e0f, KEY_MUTE }, | ||
1875 | { 0x1e10, KEY_VOLUMEUP }, | ||
1876 | { 0x1e11, KEY_VOLUMEDOWN }, | ||
1877 | { 0x1e12, KEY_PREVIOUS }, /* previous channel */ | ||
1878 | { 0x1e14, KEY_UP }, | ||
1879 | { 0x1e15, KEY_DOWN }, | ||
1880 | { 0x1e16, KEY_LEFT }, | ||
1881 | { 0x1e17, KEY_RIGHT }, | ||
1882 | { 0x1e18, KEY_VIDEO }, /* Videos */ | ||
1883 | { 0x1e19, KEY_AUDIO }, /* Music */ | ||
1884 | /* 0x1e1a: Pictures - presume this means | ||
1885 | "Multimedia Home Platform" - | ||
1886 | no "PICTURES" key in input.h | ||
1887 | */ | ||
1888 | { 0x1e1a, KEY_MHP }, | ||
1889 | |||
1890 | { 0x1e1b, KEY_EPG }, /* Guide */ | ||
1891 | { 0x1e1c, KEY_TV }, | ||
1892 | { 0x1e1e, KEY_NEXTSONG }, /* skip >| */ | ||
1893 | { 0x1e1f, KEY_EXIT }, /* back/exit */ | ||
1894 | { 0x1e20, KEY_CHANNELUP }, /* channel / program + */ | ||
1895 | { 0x1e21, KEY_CHANNELDOWN }, /* channel / program - */ | ||
1896 | { 0x1e22, KEY_CHANNEL }, /* source (old black remote) */ | ||
1897 | { 0x1e24, KEY_PREVIOUSSONG }, /* replay |< */ | ||
1898 | { 0x1e25, KEY_ENTER }, /* OK */ | ||
1899 | { 0x1e26, KEY_SLEEP }, /* minimize (old black remote) */ | ||
1900 | { 0x1e29, KEY_BLUE }, /* blue key */ | ||
1901 | { 0x1e2e, KEY_GREEN }, /* green button */ | ||
1902 | { 0x1e30, KEY_PAUSE }, /* pause */ | ||
1903 | { 0x1e32, KEY_REWIND }, /* backward << */ | ||
1904 | { 0x1e34, KEY_FASTFORWARD }, /* forward >> */ | ||
1905 | { 0x1e35, KEY_PLAY }, | ||
1906 | { 0x1e36, KEY_STOP }, | ||
1907 | { 0x1e37, KEY_RECORD }, /* recording */ | ||
1908 | { 0x1e38, KEY_YELLOW }, /* yellow key */ | ||
1909 | { 0x1e3b, KEY_SELECT }, /* top right button */ | ||
1910 | { 0x1e3c, KEY_ZOOM }, /* full */ | ||
1911 | { 0x1e3d, KEY_POWER }, /* system power (green button) */ | ||
1912 | }; | ||
1913 | |||
1914 | struct ir_scancode_table ir_codes_rc5_hauppauge_new_table = { | ||
1915 | .scan = ir_codes_rc5_hauppauge_new, | ||
1916 | .size = ARRAY_SIZE(ir_codes_rc5_hauppauge_new), | ||
1917 | }; | ||
1918 | EXPORT_SYMBOL_GPL(ir_codes_rc5_hauppauge_new_table); | ||
1919 | |||
1920 | static struct ir_scancode ir_codes_npgtech[] = { | 1850 | static struct ir_scancode ir_codes_npgtech[] = { |
1921 | { 0x1d, KEY_SWITCHVIDEOMODE }, /* switch inputs */ | 1851 | { 0x1d, KEY_SWITCHVIDEOMODE }, /* switch inputs */ |
1922 | { 0x2a, KEY_FRONT }, | 1852 | { 0x2a, KEY_FRONT }, |
@@ -3314,3 +3244,152 @@ struct ir_scancode_table ir_codes_gadmei_rm008z_table = { | |||
3314 | }; | 3244 | }; |
3315 | EXPORT_SYMBOL_GPL(ir_codes_gadmei_rm008z_table); | 3245 | EXPORT_SYMBOL_GPL(ir_codes_gadmei_rm008z_table); |
3316 | 3246 | ||
3247 | /************************************************************* | ||
3248 | * COMPLETE SCANCODE TABLES | ||
3249 | * Instead of just a partial scancode, the tables bellow | ||
3250 | * contains the complete scancode and the receiver protocol | ||
3251 | *************************************************************/ | ||
3252 | |||
3253 | /* | ||
3254 | * Hauppauge:the newer, gray remotes (seems there are multiple | ||
3255 | * slightly different versions), shipped with cx88+ivtv cards. | ||
3256 | * | ||
3257 | * This table contains the complete RC5 code, instead of just the data part | ||
3258 | */ | ||
3259 | static struct ir_scancode ir_codes_rc5_hauppauge_new[] = { | ||
3260 | /* Keys 0 to 9 */ | ||
3261 | { 0x1e00, KEY_0 }, | ||
3262 | { 0x1e01, KEY_1 }, | ||
3263 | { 0x1e02, KEY_2 }, | ||
3264 | { 0x1e03, KEY_3 }, | ||
3265 | { 0x1e04, KEY_4 }, | ||
3266 | { 0x1e05, KEY_5 }, | ||
3267 | { 0x1e06, KEY_6 }, | ||
3268 | { 0x1e07, KEY_7 }, | ||
3269 | { 0x1e08, KEY_8 }, | ||
3270 | { 0x1e09, KEY_9 }, | ||
3271 | |||
3272 | { 0x1e0a, KEY_TEXT }, /* keypad asterisk as well */ | ||
3273 | { 0x1e0b, KEY_RED }, /* red button */ | ||
3274 | { 0x1e0c, KEY_RADIO }, | ||
3275 | { 0x1e0d, KEY_MENU }, | ||
3276 | { 0x1e0e, KEY_SUBTITLE }, /* also the # key */ | ||
3277 | { 0x1e0f, KEY_MUTE }, | ||
3278 | { 0x1e10, KEY_VOLUMEUP }, | ||
3279 | { 0x1e11, KEY_VOLUMEDOWN }, | ||
3280 | { 0x1e12, KEY_PREVIOUS }, /* previous channel */ | ||
3281 | { 0x1e14, KEY_UP }, | ||
3282 | { 0x1e15, KEY_DOWN }, | ||
3283 | { 0x1e16, KEY_LEFT }, | ||
3284 | { 0x1e17, KEY_RIGHT }, | ||
3285 | { 0x1e18, KEY_VIDEO }, /* Videos */ | ||
3286 | { 0x1e19, KEY_AUDIO }, /* Music */ | ||
3287 | /* 0x1e1a: Pictures - presume this means | ||
3288 | "Multimedia Home Platform" - | ||
3289 | no "PICTURES" key in input.h | ||
3290 | */ | ||
3291 | { 0x1e1a, KEY_MHP }, | ||
3292 | |||
3293 | { 0x1e1b, KEY_EPG }, /* Guide */ | ||
3294 | { 0x1e1c, KEY_TV }, | ||
3295 | { 0x1e1e, KEY_NEXTSONG }, /* skip >| */ | ||
3296 | { 0x1e1f, KEY_EXIT }, /* back/exit */ | ||
3297 | { 0x1e20, KEY_CHANNELUP }, /* channel / program + */ | ||
3298 | { 0x1e21, KEY_CHANNELDOWN }, /* channel / program - */ | ||
3299 | { 0x1e22, KEY_CHANNEL }, /* source (old black remote) */ | ||
3300 | { 0x1e24, KEY_PREVIOUSSONG }, /* replay |< */ | ||
3301 | { 0x1e25, KEY_ENTER }, /* OK */ | ||
3302 | { 0x1e26, KEY_SLEEP }, /* minimize (old black remote) */ | ||
3303 | { 0x1e29, KEY_BLUE }, /* blue key */ | ||
3304 | { 0x1e2e, KEY_GREEN }, /* green button */ | ||
3305 | { 0x1e30, KEY_PAUSE }, /* pause */ | ||
3306 | { 0x1e32, KEY_REWIND }, /* backward << */ | ||
3307 | { 0x1e34, KEY_FASTFORWARD }, /* forward >> */ | ||
3308 | { 0x1e35, KEY_PLAY }, | ||
3309 | { 0x1e36, KEY_STOP }, | ||
3310 | { 0x1e37, KEY_RECORD }, /* recording */ | ||
3311 | { 0x1e38, KEY_YELLOW }, /* yellow key */ | ||
3312 | { 0x1e3b, KEY_SELECT }, /* top right button */ | ||
3313 | { 0x1e3c, KEY_ZOOM }, /* full */ | ||
3314 | { 0x1e3d, KEY_POWER }, /* system power (green button) */ | ||
3315 | }; | ||
3316 | |||
3317 | struct ir_scancode_table ir_codes_rc5_hauppauge_new_table = { | ||
3318 | .scan = ir_codes_rc5_hauppauge_new, | ||
3319 | .size = ARRAY_SIZE(ir_codes_rc5_hauppauge_new), | ||
3320 | .ir_type = IR_TYPE_RC5, | ||
3321 | }; | ||
3322 | EXPORT_SYMBOL_GPL(ir_codes_rc5_hauppauge_new_table); | ||
3323 | |||
3324 | /* Terratec Cinergy Hybrid T USB XS FM | ||
3325 | Mauro Carvalho Chehab <mchehab@redhat.com> | ||
3326 | */ | ||
3327 | static struct ir_scancode ir_codes_nec_terratec_cinergy_xs[] = { | ||
3328 | { 0x1441, KEY_HOME}, | ||
3329 | { 0x1401, KEY_POWER2}, | ||
3330 | |||
3331 | { 0x1442, KEY_MENU}, /* DVD menu */ | ||
3332 | { 0x1443, KEY_SUBTITLE}, | ||
3333 | { 0x1444, KEY_TEXT}, /* Teletext */ | ||
3334 | { 0x1445, KEY_DELETE}, | ||
3335 | |||
3336 | { 0x1402, KEY_1}, | ||
3337 | { 0x1403, KEY_2}, | ||
3338 | { 0x1404, KEY_3}, | ||
3339 | { 0x1405, KEY_4}, | ||
3340 | { 0x1406, KEY_5}, | ||
3341 | { 0x1407, KEY_6}, | ||
3342 | { 0x1408, KEY_7}, | ||
3343 | { 0x1409, KEY_8}, | ||
3344 | { 0x140a, KEY_9}, | ||
3345 | { 0x140c, KEY_0}, | ||
3346 | |||
3347 | { 0x140b, KEY_TUNER}, /* AV */ | ||
3348 | { 0x140d, KEY_MODE}, /* A.B */ | ||
3349 | |||
3350 | { 0x1446, KEY_TV}, | ||
3351 | { 0x1447, KEY_DVD}, | ||
3352 | { 0x1449, KEY_VIDEO}, | ||
3353 | { 0x144a, KEY_RADIO}, /* Music */ | ||
3354 | { 0x144b, KEY_CAMERA}, /* PIC */ | ||
3355 | |||
3356 | { 0x1410, KEY_UP}, | ||
3357 | { 0x1411, KEY_LEFT}, | ||
3358 | { 0x1412, KEY_OK}, | ||
3359 | { 0x1413, KEY_RIGHT}, | ||
3360 | { 0x1414, KEY_DOWN}, | ||
3361 | |||
3362 | { 0x140f, KEY_EPG}, | ||
3363 | { 0x1416, KEY_INFO}, | ||
3364 | { 0x144d, KEY_BACKSPACE}, | ||
3365 | |||
3366 | { 0x141c, KEY_VOLUMEUP}, | ||
3367 | { 0x141e, KEY_VOLUMEDOWN}, | ||
3368 | |||
3369 | { 0x144c, KEY_PLAY}, | ||
3370 | { 0x141d, KEY_MUTE}, | ||
3371 | |||
3372 | { 0x141b, KEY_CHANNELUP}, | ||
3373 | { 0x141f, KEY_CHANNELDOWN}, | ||
3374 | |||
3375 | { 0x1417, KEY_RED}, | ||
3376 | { 0x1418, KEY_GREEN}, | ||
3377 | { 0x1419, KEY_YELLOW}, | ||
3378 | { 0x141a, KEY_BLUE}, | ||
3379 | |||
3380 | { 0x1458, KEY_RECORD}, | ||
3381 | { 0x1448, KEY_STOP}, | ||
3382 | { 0x1440, KEY_PAUSE}, | ||
3383 | |||
3384 | { 0x1454, KEY_LAST}, | ||
3385 | { 0x144e, KEY_REWIND}, | ||
3386 | { 0x144f, KEY_FASTFORWARD}, | ||
3387 | { 0x145c, KEY_NEXT}, | ||
3388 | }; | ||
3389 | struct ir_scancode_table ir_codes_nec_terratec_cinergy_xs_table = { | ||
3390 | .scan = ir_codes_nec_terratec_cinergy_xs, | ||
3391 | .size = ARRAY_SIZE(ir_codes_nec_terratec_cinergy_xs), | ||
3392 | .ir_type = IR_TYPE_NEC, | ||
3393 | }; | ||
3394 | EXPORT_SYMBOL_GPL(ir_codes_nec_terratec_cinergy_xs_table); | ||
3395 | |||
diff --git a/drivers/media/common/ir-keytable.c b/drivers/media/IR/ir-keytable.c index 26ce5bc2fdd5..b521ed9d6e2e 100644 --- a/drivers/media/common/ir-keytable.c +++ b/drivers/media/IR/ir-keytable.c | |||
@@ -1,10 +1,19 @@ | |||
1 | /* ir-register.c - handle IR scancode->keycode tables | 1 | /* ir-register.c - handle IR scancode->keycode tables |
2 | * | 2 | * |
3 | * Copyright (C) 2009 by Mauro Carvalho Chehab <mchehab@redhat.com> | 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. | ||
4 | */ | 13 | */ |
5 | 14 | ||
6 | #include <linux/usb/input.h> | ||
7 | 15 | ||
16 | #include <linux/input.h> | ||
8 | #include <media/ir-common.h> | 17 | #include <media/ir-common.h> |
9 | 18 | ||
10 | #define IR_TAB_MIN_SIZE 32 | 19 | #define IR_TAB_MIN_SIZE 32 |
@@ -72,6 +81,7 @@ int ir_roundup_tablesize(int n_elems) | |||
72 | 81 | ||
73 | return n_elems; | 82 | return n_elems; |
74 | } | 83 | } |
84 | EXPORT_SYMBOL_GPL(ir_roundup_tablesize); | ||
75 | 85 | ||
76 | /** | 86 | /** |
77 | * ir_copy_table() - copies a keytable, discarding the unused entries | 87 | * ir_copy_table() - copies a keytable, discarding the unused entries |
@@ -100,6 +110,7 @@ int ir_copy_table(struct ir_scancode_table *destin, | |||
100 | 110 | ||
101 | return 0; | 111 | return 0; |
102 | } | 112 | } |
113 | EXPORT_SYMBOL_GPL(ir_copy_table); | ||
103 | 114 | ||
104 | /** | 115 | /** |
105 | * ir_getkeycode() - get a keycode at the evdev scancode ->keycode table | 116 | * ir_getkeycode() - get a keycode at the evdev scancode ->keycode table |
@@ -114,7 +125,8 @@ static int ir_getkeycode(struct input_dev *dev, | |||
114 | int scancode, int *keycode) | 125 | int scancode, int *keycode) |
115 | { | 126 | { |
116 | int elem; | 127 | int elem; |
117 | struct ir_scancode_table *rc_tab = input_get_drvdata(dev); | 128 | struct ir_input_dev *ir_dev = input_get_drvdata(dev); |
129 | struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; | ||
118 | 130 | ||
119 | elem = ir_seek_table(rc_tab, scancode); | 131 | elem = ir_seek_table(rc_tab, scancode); |
120 | if (elem >= 0) { | 132 | if (elem >= 0) { |
@@ -136,7 +148,6 @@ static int ir_getkeycode(struct input_dev *dev, | |||
136 | return 0; | 148 | return 0; |
137 | } | 149 | } |
138 | 150 | ||
139 | |||
140 | /** | 151 | /** |
141 | * ir_is_resize_needed() - Check if the table needs rezise | 152 | * ir_is_resize_needed() - Check if the table needs rezise |
142 | * @table: keycode table that may need to resize | 153 | * @table: keycode table that may need to resize |
@@ -286,7 +297,8 @@ static int ir_setkeycode(struct input_dev *dev, | |||
286 | int scancode, int keycode) | 297 | int scancode, int keycode) |
287 | { | 298 | { |
288 | int rc = 0; | 299 | int rc = 0; |
289 | struct ir_scancode_table *rc_tab = input_get_drvdata(dev); | 300 | struct ir_input_dev *ir_dev = input_get_drvdata(dev); |
301 | struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; | ||
290 | struct ir_scancode *keymap = rc_tab->scan; | 302 | struct ir_scancode *keymap = rc_tab->scan; |
291 | unsigned long flags; | 303 | unsigned long flags; |
292 | 304 | ||
@@ -360,7 +372,8 @@ static int ir_setkeycode(struct input_dev *dev, | |||
360 | */ | 372 | */ |
361 | u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode) | 373 | u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode) |
362 | { | 374 | { |
363 | struct ir_scancode_table *rc_tab = input_get_drvdata(dev); | 375 | struct ir_input_dev *ir_dev = input_get_drvdata(dev); |
376 | struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; | ||
364 | struct ir_scancode *keymap = rc_tab->scan; | 377 | struct ir_scancode *keymap = rc_tab->scan; |
365 | int elem; | 378 | int elem; |
366 | 379 | ||
@@ -378,9 +391,10 @@ u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode) | |||
378 | /* Reports userspace that an unknown keycode were got */ | 391 | /* Reports userspace that an unknown keycode were got */ |
379 | return KEY_RESERVED; | 392 | return KEY_RESERVED; |
380 | } | 393 | } |
394 | EXPORT_SYMBOL_GPL(ir_g_keycode_from_table); | ||
381 | 395 | ||
382 | /** | 396 | /** |
383 | * ir_set_keycode_table() - sets the IR keycode table and add the handlers | 397 | * ir_input_register() - sets the IR keycode table and add the handlers |
384 | * for keymap table get/set | 398 | * for keymap table get/set |
385 | * @input_dev: the struct input_dev descriptor of the device | 399 | * @input_dev: the struct input_dev descriptor of the device |
386 | * @rc_tab: the struct ir_scancode_table table of scancode/keymap | 400 | * @rc_tab: the struct ir_scancode_table table of scancode/keymap |
@@ -389,17 +403,34 @@ u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode) | |||
389 | * an IR. | 403 | * an IR. |
390 | * It should be called before registering the IR device. | 404 | * It should be called before registering the IR device. |
391 | */ | 405 | */ |
392 | int ir_set_keycode_table(struct input_dev *input_dev, | 406 | int ir_input_register(struct input_dev *input_dev, |
393 | struct ir_scancode_table *rc_tab) | 407 | struct ir_scancode_table *rc_tab) |
394 | { | 408 | { |
395 | struct ir_scancode *keymap = rc_tab->scan; | 409 | struct ir_input_dev *ir_dev; |
396 | int i; | 410 | struct ir_scancode *keymap = rc_tab->scan; |
397 | 411 | int i, rc; | |
398 | spin_lock_init(&rc_tab->lock); | ||
399 | 412 | ||
400 | if (rc_tab->scan == NULL || !rc_tab->size) | 413 | if (rc_tab->scan == NULL || !rc_tab->size) |
401 | return -EINVAL; | 414 | return -EINVAL; |
402 | 415 | ||
416 | ir_dev = kzalloc(sizeof(*ir_dev), GFP_KERNEL); | ||
417 | if (!ir_dev) | ||
418 | return -ENOMEM; | ||
419 | |||
420 | spin_lock_init(&rc_tab->lock); | ||
421 | |||
422 | ir_dev->rc_tab.size = ir_roundup_tablesize(rc_tab->size); | ||
423 | ir_dev->rc_tab.scan = kzalloc(ir_dev->rc_tab.size * | ||
424 | sizeof(struct ir_scancode), GFP_KERNEL); | ||
425 | if (!ir_dev->rc_tab.scan) | ||
426 | return -ENOMEM; | ||
427 | |||
428 | IR_dprintk(1, "Allocated space for %d keycode entries (%zd bytes)\n", | ||
429 | ir_dev->rc_tab.size, | ||
430 | ir_dev->rc_tab.size * sizeof(ir_dev->rc_tab.scan)); | ||
431 | |||
432 | ir_copy_table(&ir_dev->rc_tab, rc_tab); | ||
433 | |||
403 | /* set the bits for the keys */ | 434 | /* set the bits for the keys */ |
404 | IR_dprintk(1, "key map size: %d\n", rc_tab->size); | 435 | IR_dprintk(1, "key map size: %d\n", rc_tab->size); |
405 | for (i = 0; i < rc_tab->size; i++) { | 436 | for (i = 0; i < rc_tab->size; i++) { |
@@ -407,23 +438,48 @@ int ir_set_keycode_table(struct input_dev *input_dev, | |||
407 | i, keymap[i].keycode); | 438 | i, keymap[i].keycode); |
408 | set_bit(keymap[i].keycode, input_dev->keybit); | 439 | set_bit(keymap[i].keycode, input_dev->keybit); |
409 | } | 440 | } |
441 | clear_bit(0, input_dev->keybit); | ||
442 | |||
443 | set_bit(EV_KEY, input_dev->evbit); | ||
410 | 444 | ||
411 | input_dev->getkeycode = ir_getkeycode; | 445 | input_dev->getkeycode = ir_getkeycode; |
412 | input_dev->setkeycode = ir_setkeycode; | 446 | input_dev->setkeycode = ir_setkeycode; |
413 | input_set_drvdata(input_dev, rc_tab); | 447 | input_set_drvdata(input_dev, ir_dev); |
414 | 448 | ||
415 | return 0; | 449 | rc = input_register_device(input_dev); |
450 | if (rc < 0) { | ||
451 | kfree(rc_tab->scan); | ||
452 | kfree(ir_dev); | ||
453 | input_set_drvdata(input_dev, NULL); | ||
454 | } | ||
455 | |||
456 | return rc; | ||
416 | } | 457 | } |
458 | EXPORT_SYMBOL_GPL(ir_input_register); | ||
417 | 459 | ||
418 | void ir_input_free(struct input_dev *dev) | 460 | void ir_input_unregister(struct input_dev *dev) |
419 | { | 461 | { |
420 | struct ir_scancode_table *rc_tab = input_get_drvdata(dev); | 462 | struct ir_input_dev *ir_dev = input_get_drvdata(dev); |
463 | struct ir_scancode_table *rc_tab; | ||
464 | |||
465 | if (!ir_dev) | ||
466 | return; | ||
421 | 467 | ||
422 | IR_dprintk(1, "Freed keycode table\n"); | 468 | IR_dprintk(1, "Freed keycode table\n"); |
423 | 469 | ||
470 | rc_tab = &ir_dev->rc_tab; | ||
424 | rc_tab->size = 0; | 471 | rc_tab->size = 0; |
425 | kfree(rc_tab->scan); | 472 | kfree(rc_tab->scan); |
426 | rc_tab->scan = NULL; | 473 | rc_tab->scan = NULL; |
474 | |||
475 | kfree(ir_dev); | ||
476 | input_unregister_device(dev); | ||
427 | } | 477 | } |
428 | EXPORT_SYMBOL_GPL(ir_input_free); | 478 | EXPORT_SYMBOL_GPL(ir_input_unregister); |
479 | |||
480 | int ir_core_debug; /* ir_debug level (0,1,2) */ | ||
481 | EXPORT_SYMBOL_GPL(ir_core_debug); | ||
482 | module_param_named(debug, ir_core_debug, int, 0644); | ||
429 | 483 | ||
484 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
485 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index ba69beeb0e21..a28541b2b1a2 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig | |||
@@ -99,6 +99,7 @@ config VIDEO_MEDIA | |||
99 | comment "Multimedia drivers" | 99 | comment "Multimedia drivers" |
100 | 100 | ||
101 | source "drivers/media/common/Kconfig" | 101 | source "drivers/media/common/Kconfig" |
102 | source "drivers/media/IR/Kconfig" | ||
102 | 103 | ||
103 | # | 104 | # |
104 | # Tuner drivers for DVB and V4L | 105 | # Tuner drivers for DVB and V4L |
diff --git a/drivers/media/Makefile b/drivers/media/Makefile index 09a829d8a7e7..499b0810d019 100644 --- a/drivers/media/Makefile +++ b/drivers/media/Makefile | |||
@@ -2,7 +2,7 @@ | |||
2 | # Makefile for the kernel multimedia device drivers. | 2 | # Makefile for the kernel multimedia device drivers. |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y += common/ video/ | 5 | obj-y += common/ IR/ video/ |
6 | 6 | ||
7 | obj-$(CONFIG_VIDEO_DEV) += radio/ | 7 | obj-$(CONFIG_VIDEO_DEV) += radio/ |
8 | obj-$(CONFIG_DVB_CORE) += dvb/ | 8 | obj-$(CONFIG_DVB_CORE) += dvb/ |
diff --git a/drivers/media/common/Makefile b/drivers/media/common/Makefile index 169b337b7c9d..e3ec9639321b 100644 --- a/drivers/media/common/Makefile +++ b/drivers/media/common/Makefile | |||
@@ -1,8 +1,6 @@ | |||
1 | saa7146-objs := saa7146_i2c.o saa7146_core.o | 1 | saa7146-objs := saa7146_i2c.o saa7146_core.o |
2 | saa7146_vv-objs := saa7146_fops.o saa7146_video.o saa7146_hlp.o saa7146_vbi.o | 2 | saa7146_vv-objs := saa7146_fops.o saa7146_video.o saa7146_hlp.o saa7146_vbi.o |
3 | ir-common-objs := ir-functions.o ir-keymaps.o ir-keytable.o | ||
4 | 3 | ||
5 | obj-y += tuners/ | 4 | obj-y += tuners/ |
6 | obj-$(CONFIG_VIDEO_SAA7146) += saa7146.o | 5 | obj-$(CONFIG_VIDEO_SAA7146) += saa7146.o |
7 | obj-$(CONFIG_VIDEO_SAA7146_VV) += saa7146_vv.o | 6 | obj-$(CONFIG_VIDEO_SAA7146_VV) += saa7146_vv.o |
8 | obj-$(CONFIG_VIDEO_IR) += ir-common.o | ||
diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c index 620f655fa9c5..7364b9642d00 100644 --- a/drivers/media/common/saa7146_fops.c +++ b/drivers/media/common/saa7146_fops.c | |||
@@ -1,7 +1,5 @@ | |||
1 | #include <media/saa7146_vv.h> | 1 | #include <media/saa7146_vv.h> |
2 | 2 | ||
3 | #define BOARD_CAN_DO_VBI(dev) (dev->revision != 0 && dev->vv_data->vbi_minor != -1) | ||
4 | |||
5 | /****************************************************************************/ | 3 | /****************************************************************************/ |
6 | /* resource management functions, shamelessly stolen from saa7134 driver */ | 4 | /* resource management functions, shamelessly stolen from saa7134 driver */ |
7 | 5 | ||
@@ -194,43 +192,24 @@ void saa7146_buffer_timeout(unsigned long data) | |||
194 | 192 | ||
195 | static int fops_open(struct file *file) | 193 | static int fops_open(struct file *file) |
196 | { | 194 | { |
197 | unsigned int minor = video_devdata(file)->minor; | 195 | struct video_device *vdev = video_devdata(file); |
198 | struct saa7146_dev *h = NULL, *dev = NULL; | 196 | struct saa7146_dev *dev = video_drvdata(file); |
199 | struct list_head *list; | ||
200 | struct saa7146_fh *fh = NULL; | 197 | struct saa7146_fh *fh = NULL; |
201 | int result = 0; | 198 | int result = 0; |
202 | 199 | ||
203 | enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 200 | enum v4l2_buf_type type; |
204 | 201 | ||
205 | DEB_EE(("file:%p, minor:%d\n", file, minor)); | 202 | DEB_EE(("file:%p, dev:%s\n", file, video_device_node_name(vdev))); |
206 | 203 | ||
207 | if (mutex_lock_interruptible(&saa7146_devices_lock)) | 204 | if (mutex_lock_interruptible(&saa7146_devices_lock)) |
208 | return -ERESTARTSYS; | 205 | return -ERESTARTSYS; |
209 | 206 | ||
210 | list_for_each(list,&saa7146_devices) { | ||
211 | h = list_entry(list, struct saa7146_dev, item); | ||
212 | if( NULL == h->vv_data ) { | ||
213 | DEB_D(("device %p has not registered video devices.\n",h)); | ||
214 | continue; | ||
215 | } | ||
216 | DEB_D(("trying: %p @ major %d,%d\n",h,h->vv_data->video_minor,h->vv_data->vbi_minor)); | ||
217 | |||
218 | if (h->vv_data->video_minor == minor) { | ||
219 | dev = h; | ||
220 | } | ||
221 | if (h->vv_data->vbi_minor == minor) { | ||
222 | type = V4L2_BUF_TYPE_VBI_CAPTURE; | ||
223 | dev = h; | ||
224 | } | ||
225 | } | ||
226 | if (NULL == dev) { | ||
227 | DEB_S(("no such video device.\n")); | ||
228 | result = -ENODEV; | ||
229 | goto out; | ||
230 | } | ||
231 | |||
232 | DEB_D(("using: %p\n",dev)); | 207 | DEB_D(("using: %p\n",dev)); |
233 | 208 | ||
209 | type = vdev->vfl_type == VFL_TYPE_GRABBER | ||
210 | ? V4L2_BUF_TYPE_VIDEO_CAPTURE | ||
211 | : V4L2_BUF_TYPE_VBI_CAPTURE; | ||
212 | |||
234 | /* check if an extension is registered */ | 213 | /* check if an extension is registered */ |
235 | if( NULL == dev->ext ) { | 214 | if( NULL == dev->ext ) { |
236 | DEB_S(("no extension registered for this device.\n")); | 215 | DEB_S(("no extension registered for this device.\n")); |
@@ -474,9 +453,6 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv) | |||
474 | configuration data) */ | 453 | configuration data) */ |
475 | dev->ext_vv_data = ext_vv; | 454 | dev->ext_vv_data = ext_vv; |
476 | 455 | ||
477 | vv->video_minor = -1; | ||
478 | vv->vbi_minor = -1; | ||
479 | |||
480 | vv->d_clipping.cpu_addr = pci_alloc_consistent(dev->pci, SAA7146_CLIPPING_MEM, &vv->d_clipping.dma_handle); | 456 | vv->d_clipping.cpu_addr = pci_alloc_consistent(dev->pci, SAA7146_CLIPPING_MEM, &vv->d_clipping.dma_handle); |
481 | if( NULL == vv->d_clipping.cpu_addr ) { | 457 | if( NULL == vv->d_clipping.cpu_addr ) { |
482 | ERR(("out of memory. aborting.\n")); | 458 | ERR(("out of memory. aborting.\n")); |
@@ -515,7 +491,6 @@ EXPORT_SYMBOL_GPL(saa7146_vv_release); | |||
515 | int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev, | 491 | int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev, |
516 | char *name, int type) | 492 | char *name, int type) |
517 | { | 493 | { |
518 | struct saa7146_vv *vv = dev->vv_data; | ||
519 | struct video_device *vfd; | 494 | struct video_device *vfd; |
520 | int err; | 495 | int err; |
521 | int i; | 496 | int i; |
@@ -543,15 +518,8 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev, | |||
543 | return err; | 518 | return err; |
544 | } | 519 | } |
545 | 520 | ||
546 | if( VFL_TYPE_GRABBER == type ) { | 521 | INFO(("%s: registered device %s [v4l2]\n", |
547 | vv->video_minor = vfd->minor; | 522 | dev->name, video_device_node_name(vfd))); |
548 | INFO(("%s: registered device video%d [v4l2]\n", | ||
549 | dev->name, vfd->num)); | ||
550 | } else { | ||
551 | vv->vbi_minor = vfd->minor; | ||
552 | INFO(("%s: registered device vbi%d [v4l2]\n", | ||
553 | dev->name, vfd->num)); | ||
554 | } | ||
555 | 523 | ||
556 | *vid = vfd; | 524 | *vid = vfd; |
557 | return 0; | 525 | return 0; |
@@ -560,16 +528,8 @@ EXPORT_SYMBOL_GPL(saa7146_register_device); | |||
560 | 528 | ||
561 | int saa7146_unregister_device(struct video_device **vid, struct saa7146_dev* dev) | 529 | int saa7146_unregister_device(struct video_device **vid, struct saa7146_dev* dev) |
562 | { | 530 | { |
563 | struct saa7146_vv *vv = dev->vv_data; | ||
564 | |||
565 | DEB_EE(("dev:%p\n",dev)); | 531 | DEB_EE(("dev:%p\n",dev)); |
566 | 532 | ||
567 | if ((*vid)->vfl_type == VFL_TYPE_GRABBER) { | ||
568 | vv->video_minor = -1; | ||
569 | } else { | ||
570 | vv->vbi_minor = -1; | ||
571 | } | ||
572 | |||
573 | video_unregister_device(*vid); | 533 | video_unregister_device(*vid); |
574 | *vid = NULL; | 534 | *vid = NULL; |
575 | 535 | ||
diff --git a/drivers/media/common/tuners/tda8290.c b/drivers/media/common/tuners/tda8290.c index c190b0dedee4..2833137fa819 100644 --- a/drivers/media/common/tuners/tda8290.c +++ b/drivers/media/common/tuners/tda8290.c | |||
@@ -144,7 +144,8 @@ static void set_audio(struct dvb_frontend *fe, | |||
144 | } | 144 | } |
145 | 145 | ||
146 | if (params->mode == V4L2_TUNER_RADIO) { | 146 | if (params->mode == V4L2_TUNER_RADIO) { |
147 | priv->tda8290_easy_mode = 0x01; /* Start with MN values */ | 147 | /* Set TDA8295 to FM radio; Start TDA8290 with MN values */ |
148 | priv->tda8290_easy_mode = (priv->ver & TDA8295) ? 0x80 : 0x01; | ||
148 | tuner_dbg("setting to radio FM\n"); | 149 | tuner_dbg("setting to radio FM\n"); |
149 | } else { | 150 | } else { |
150 | tuner_dbg("setting tda829x to system %s\n", mode); | 151 | tuner_dbg("setting tda829x to system %s\n", mode); |
@@ -672,16 +673,19 @@ static int tda8290_probe(struct tuner_i2c_props *i2c_props) | |||
672 | static int tda8295_probe(struct tuner_i2c_props *i2c_props) | 673 | static int tda8295_probe(struct tuner_i2c_props *i2c_props) |
673 | { | 674 | { |
674 | #define TDA8295_ID 0x8a | 675 | #define TDA8295_ID 0x8a |
676 | #define TDA8295C2_ID 0x8b | ||
675 | unsigned char tda8295_id[] = { 0x2f, 0x00 }; | 677 | unsigned char tda8295_id[] = { 0x2f, 0x00 }; |
676 | 678 | ||
677 | /* detect tda8295 */ | 679 | /* detect tda8295 */ |
678 | tuner_i2c_xfer_send(i2c_props, &tda8295_id[0], 1); | 680 | tuner_i2c_xfer_send(i2c_props, &tda8295_id[0], 1); |
679 | tuner_i2c_xfer_recv(i2c_props, &tda8295_id[1], 1); | 681 | tuner_i2c_xfer_recv(i2c_props, &tda8295_id[1], 1); |
680 | 682 | ||
681 | if (tda8295_id[1] == TDA8295_ID) { | 683 | if ((tda8295_id[1] & 0xfe) == TDA8295_ID) { |
682 | if (debug) | 684 | if (debug) |
683 | printk(KERN_DEBUG "%s: tda8295 detected @ %d-%04x\n", | 685 | printk(KERN_DEBUG "%s: %s detected @ %d-%04x\n", |
684 | __func__, i2c_adapter_id(i2c_props->adap), | 686 | __func__, (tda8295_id[1] == TDA8295_ID) ? |
687 | "tda8295c1" : "tda8295c2", | ||
688 | i2c_adapter_id(i2c_props->adap), | ||
685 | i2c_props->addr); | 689 | i2c_props->addr); |
686 | return 0; | 690 | return 0; |
687 | } | 691 | } |
diff --git a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig index 35d0817126e9..cf8f65f309da 100644 --- a/drivers/media/dvb/Kconfig +++ b/drivers/media/dvb/Kconfig | |||
@@ -72,6 +72,10 @@ comment "Supported Earthsoft PT1 Adapters" | |||
72 | depends on DVB_CORE && PCI && I2C | 72 | depends on DVB_CORE && PCI && I2C |
73 | source "drivers/media/dvb/pt1/Kconfig" | 73 | source "drivers/media/dvb/pt1/Kconfig" |
74 | 74 | ||
75 | comment "Supported Mantis Adapters" | ||
76 | depends on DVB_CORE && PCI && I2C | ||
77 | source "drivers/media/dvb/mantis/Kconfig" | ||
78 | |||
75 | comment "Supported DVB Frontends" | 79 | comment "Supported DVB Frontends" |
76 | depends on DVB_CORE | 80 | depends on DVB_CORE |
77 | source "drivers/media/dvb/frontends/Kconfig" | 81 | source "drivers/media/dvb/frontends/Kconfig" |
diff --git a/drivers/media/dvb/Makefile b/drivers/media/dvb/Makefile index 16d262ddb45d..c12922c3659b 100644 --- a/drivers/media/dvb/Makefile +++ b/drivers/media/dvb/Makefile | |||
@@ -2,6 +2,18 @@ | |||
2 | # Makefile for the kernel multimedia device drivers. | 2 | # Makefile for the kernel multimedia device drivers. |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ dvb-usb/ pluto2/ siano/ dm1105/ pt1/ | 5 | obj-y := dvb-core/ \ |
6 | frontends/ \ | ||
7 | ttpci/ \ | ||
8 | ttusb-dec/ \ | ||
9 | ttusb-budget/ \ | ||
10 | b2c2/ \ | ||
11 | bt8xx/ \ | ||
12 | dvb-usb/ \ | ||
13 | pluto2/ \ | ||
14 | siano/ \ | ||
15 | dm1105/ \ | ||
16 | pt1/ \ | ||
17 | mantis/ | ||
6 | 18 | ||
7 | obj-$(CONFIG_DVB_FIREDTV) += firewire/ | 19 | obj-$(CONFIG_DVB_FIREDTV) += firewire/ |
diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c index 53e3f2a7d31a..f0f483ac8b89 100644 --- a/drivers/media/dvb/dm1105/dm1105.c +++ b/drivers/media/dvb/dm1105/dm1105.c | |||
@@ -589,7 +589,7 @@ int __devinit dm1105_ir_init(struct dm1105dvb *dm1105) | |||
589 | snprintf(dm1105->ir.input_phys, sizeof(dm1105->ir.input_phys), | 589 | snprintf(dm1105->ir.input_phys, sizeof(dm1105->ir.input_phys), |
590 | "pci-%s/ir0", pci_name(dm1105->pdev)); | 590 | "pci-%s/ir0", pci_name(dm1105->pdev)); |
591 | 591 | ||
592 | err = ir_input_init(input_dev, &dm1105->ir.ir, ir_type, ir_codes); | 592 | err = ir_input_init(input_dev, &dm1105->ir.ir, ir_type); |
593 | if (err < 0) { | 593 | if (err < 0) { |
594 | input_free_device(input_dev); | 594 | input_free_device(input_dev); |
595 | return err; | 595 | return err; |
@@ -611,20 +611,14 @@ int __devinit dm1105_ir_init(struct dm1105dvb *dm1105) | |||
611 | 611 | ||
612 | INIT_WORK(&dm1105->ir.work, dm1105_emit_key); | 612 | INIT_WORK(&dm1105->ir.work, dm1105_emit_key); |
613 | 613 | ||
614 | err = input_register_device(input_dev); | 614 | err = ir_input_register(input_dev, ir_codes); |
615 | if (err) { | ||
616 | ir_input_free(input_dev); | ||
617 | input_free_device(input_dev); | ||
618 | return err; | ||
619 | } | ||
620 | 615 | ||
621 | return 0; | 616 | return err; |
622 | } | 617 | } |
623 | 618 | ||
624 | void __devexit dm1105_ir_exit(struct dm1105dvb *dm1105) | 619 | void __devexit dm1105_ir_exit(struct dm1105dvb *dm1105) |
625 | { | 620 | { |
626 | ir_input_free(dm1105->ir.input_dev); | 621 | ir_input_unregister(dm1105->ir.input_dev); |
627 | input_unregister_device(dm1105->ir.input_dev); | ||
628 | } | 622 | } |
629 | 623 | ||
630 | static int __devinit dm1105dvb_hw_init(struct dm1105dvb *dm1105dvb) | 624 | static int __devinit dm1105dvb_hw_init(struct dm1105dvb *dm1105dvb) |
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index 2dee1bf73577..1b249897c9fb 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig | |||
@@ -265,9 +265,13 @@ config DVB_USB_DW2102 | |||
265 | select DVB_TDA10021 if !DVB_FE_CUSTOMISE | 265 | select DVB_TDA10021 if !DVB_FE_CUSTOMISE |
266 | select DVB_MT312 if !DVB_FE_CUSTOMISE | 266 | select DVB_MT312 if !DVB_FE_CUSTOMISE |
267 | select DVB_ZL10039 if !DVB_FE_CUSTOMISE | 267 | select DVB_ZL10039 if !DVB_FE_CUSTOMISE |
268 | select DVB_DS3000 if !DVB_FE_CUSTOMISE | ||
269 | select DVB_STB6100 if !DVB_FE_CUSTOMISE | ||
270 | select DVB_STV6110 if !DVB_FE_CUSTOMISE | ||
271 | select DVB_STV0900 if !DVB_FE_CUSTOMISE | ||
268 | help | 272 | help |
269 | Say Y here to support the DvbWorld DVB-S/S2 USB2.0 receivers | 273 | Say Y here to support the DvbWorld, TeVii, Prof DVB-S/S2 USB2.0 |
270 | and the TeVii S650, S630. | 274 | receivers. |
271 | 275 | ||
272 | config DVB_USB_CINERGY_T2 | 276 | config DVB_USB_CINERGY_T2 |
273 | tristate "Terratec CinergyT2/qanu USB 2.0 DVB-T receiver" | 277 | tristate "Terratec CinergyT2/qanu USB 2.0 DVB-T receiver" |
diff --git a/drivers/media/dvb/dvb-usb/dib0700.h b/drivers/media/dvb/dvb-usb/dib0700.h index 8b544fe79b0d..495a90577c5f 100644 --- a/drivers/media/dvb/dvb-usb/dib0700.h +++ b/drivers/media/dvb/dvb-usb/dib0700.h | |||
@@ -20,20 +20,22 @@ extern int dvb_usb_dib0700_debug; | |||
20 | #define deb_fwdata(args...) dprintk(dvb_usb_dib0700_debug,0x04,args) | 20 | #define deb_fwdata(args...) dprintk(dvb_usb_dib0700_debug,0x04,args) |
21 | #define deb_data(args...) dprintk(dvb_usb_dib0700_debug,0x08,args) | 21 | #define deb_data(args...) dprintk(dvb_usb_dib0700_debug,0x08,args) |
22 | 22 | ||
23 | #define REQUEST_I2C_READ 0x2 | 23 | #define REQUEST_SET_USB_XFER_LEN 0x0 /* valid only for firmware version */ |
24 | #define REQUEST_I2C_WRITE 0x3 | 24 | /* higher than 1.21 */ |
25 | #define REQUEST_POLL_RC 0x4 /* deprecated in firmware v1.20 */ | 25 | #define REQUEST_I2C_READ 0x2 |
26 | #define REQUEST_JUMPRAM 0x8 | 26 | #define REQUEST_I2C_WRITE 0x3 |
27 | #define REQUEST_SET_CLOCK 0xB | 27 | #define REQUEST_POLL_RC 0x4 /* deprecated in firmware v1.20 */ |
28 | #define REQUEST_SET_GPIO 0xC | 28 | #define REQUEST_JUMPRAM 0x8 |
29 | #define REQUEST_ENABLE_VIDEO 0xF | 29 | #define REQUEST_SET_CLOCK 0xB |
30 | #define REQUEST_SET_GPIO 0xC | ||
31 | #define REQUEST_ENABLE_VIDEO 0xF | ||
30 | // 1 Byte: 4MSB(1 = enable streaming, 0 = disable streaming) 4LSB(Video Mode: 0 = MPEG2 188Bytes, 1 = Analog) | 32 | // 1 Byte: 4MSB(1 = enable streaming, 0 = disable streaming) 4LSB(Video Mode: 0 = MPEG2 188Bytes, 1 = Analog) |
31 | // 2 Byte: MPEG2 mode: 4MSB(1 = Master Mode, 0 = Slave Mode) 4LSB(Channel 1 = bit0, Channel 2 = bit1) | 33 | // 2 Byte: MPEG2 mode: 4MSB(1 = Master Mode, 0 = Slave Mode) 4LSB(Channel 1 = bit0, Channel 2 = bit1) |
32 | // 2 Byte: Analog mode: 4MSB(0 = 625 lines, 1 = 525 lines) 4LSB( " " ) | 34 | // 2 Byte: Analog mode: 4MSB(0 = 625 lines, 1 = 525 lines) 4LSB( " " ) |
33 | #define REQUEST_SET_RC 0x11 | 35 | #define REQUEST_SET_RC 0x11 |
34 | #define REQUEST_NEW_I2C_READ 0x12 | 36 | #define REQUEST_NEW_I2C_READ 0x12 |
35 | #define REQUEST_NEW_I2C_WRITE 0x13 | 37 | #define REQUEST_NEW_I2C_WRITE 0x13 |
36 | #define REQUEST_GET_VERSION 0x15 | 38 | #define REQUEST_GET_VERSION 0x15 |
37 | 39 | ||
38 | struct dib0700_state { | 40 | struct dib0700_state { |
39 | u8 channel_state; | 41 | u8 channel_state; |
@@ -44,6 +46,8 @@ struct dib0700_state { | |||
44 | u8 is_dib7000pc; | 46 | u8 is_dib7000pc; |
45 | u8 fw_use_new_i2c_api; | 47 | u8 fw_use_new_i2c_api; |
46 | u8 disable_streaming_master_mode; | 48 | u8 disable_streaming_master_mode; |
49 | u32 fw_version; | ||
50 | u32 nb_packet_buffer_size; | ||
47 | }; | 51 | }; |
48 | 52 | ||
49 | extern int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion, | 53 | extern int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion, |
diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c index db7f7f79a66c..0d3c9a9a33be 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_core.c +++ b/drivers/media/dvb/dvb-usb/dib0700_core.c | |||
@@ -17,6 +17,14 @@ int dvb_usb_dib0700_ir_proto = 1; | |||
17 | module_param(dvb_usb_dib0700_ir_proto, int, 0644); | 17 | module_param(dvb_usb_dib0700_ir_proto, int, 0644); |
18 | MODULE_PARM_DESC(dvb_usb_dib0700_ir_proto, "set ir protocol (0=NEC, 1=RC5 (default), 2=RC6)."); | 18 | MODULE_PARM_DESC(dvb_usb_dib0700_ir_proto, "set ir protocol (0=NEC, 1=RC5 (default), 2=RC6)."); |
19 | 19 | ||
20 | static int nb_packet_buffer_size = 21; | ||
21 | module_param(nb_packet_buffer_size, int, 0644); | ||
22 | MODULE_PARM_DESC(nb_packet_buffer_size, | ||
23 | "Set the dib0700 driver data buffer size. This parameter " | ||
24 | "corresponds to the number of TS packets. The actual size of " | ||
25 | "the data buffer corresponds to this parameter " | ||
26 | "multiplied by 188 (default: 21)"); | ||
27 | |||
20 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | 28 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
21 | 29 | ||
22 | 30 | ||
@@ -28,10 +36,14 @@ int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion, | |||
28 | REQUEST_GET_VERSION, | 36 | REQUEST_GET_VERSION, |
29 | USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, | 37 | USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, |
30 | b, sizeof(b), USB_CTRL_GET_TIMEOUT); | 38 | b, sizeof(b), USB_CTRL_GET_TIMEOUT); |
31 | *hwversion = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]; | 39 | if (hwversion != NULL) |
32 | *romversion = (b[4] << 24) | (b[5] << 16) | (b[6] << 8) | b[7]; | 40 | *hwversion = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]; |
33 | *ramversion = (b[8] << 24) | (b[9] << 16) | (b[10] << 8) | b[11]; | 41 | if (romversion != NULL) |
34 | *fwtype = (b[12] << 24) | (b[13] << 16) | (b[14] << 8) | b[15]; | 42 | *romversion = (b[4] << 24) | (b[5] << 16) | (b[6] << 8) | b[7]; |
43 | if (ramversion != NULL) | ||
44 | *ramversion = (b[8] << 24) | (b[9] << 16) | (b[10] << 8) | b[11]; | ||
45 | if (fwtype != NULL) | ||
46 | *fwtype = (b[12] << 24) | (b[13] << 16) | (b[14] << 8) | b[15]; | ||
35 | return ret; | 47 | return ret; |
36 | } | 48 | } |
37 | 49 | ||
@@ -97,6 +109,27 @@ int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_ | |||
97 | return dib0700_ctrl_wr(d,buf,3); | 109 | return dib0700_ctrl_wr(d,buf,3); |
98 | } | 110 | } |
99 | 111 | ||
112 | static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets) | ||
113 | { | ||
114 | struct dib0700_state *st = d->priv; | ||
115 | u8 b[3]; | ||
116 | int ret; | ||
117 | |||
118 | if (st->fw_version >= 0x10201) { | ||
119 | b[0] = REQUEST_SET_USB_XFER_LEN; | ||
120 | b[1] = (nb_ts_packets >> 8)&0xff; | ||
121 | b[2] = nb_ts_packets & 0xff; | ||
122 | |||
123 | deb_info("set the USB xfer len to %i Ts packet\n", nb_ts_packets); | ||
124 | |||
125 | ret = dib0700_ctrl_wr(d, b, 3); | ||
126 | } else { | ||
127 | deb_info("this firmware does not allow to change the USB xfer len\n"); | ||
128 | ret = -EIO; | ||
129 | } | ||
130 | return ret; | ||
131 | } | ||
132 | |||
100 | /* | 133 | /* |
101 | * I2C master xfer function (supported in 1.20 firmware) | 134 | * I2C master xfer function (supported in 1.20 firmware) |
102 | */ | 135 | */ |
@@ -328,7 +361,9 @@ static int dib0700_jumpram(struct usb_device *udev, u32 address) | |||
328 | int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw) | 361 | int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw) |
329 | { | 362 | { |
330 | struct hexline hx; | 363 | struct hexline hx; |
331 | int pos = 0, ret, act_len; | 364 | int pos = 0, ret, act_len, i, adap_num; |
365 | u8 b[16]; | ||
366 | u32 fw_version; | ||
332 | 367 | ||
333 | u8 buf[260]; | 368 | u8 buf[260]; |
334 | 369 | ||
@@ -364,6 +399,34 @@ int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw | |||
364 | } else | 399 | } else |
365 | ret = -EIO; | 400 | ret = -EIO; |
366 | 401 | ||
402 | /* the number of ts packet has to be at least 1 */ | ||
403 | if (nb_packet_buffer_size < 1) | ||
404 | nb_packet_buffer_size = 1; | ||
405 | |||
406 | /* get the fimware version */ | ||
407 | usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), | ||
408 | REQUEST_GET_VERSION, | ||
409 | USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, | ||
410 | b, sizeof(b), USB_CTRL_GET_TIMEOUT); | ||
411 | fw_version = (b[8] << 24) | (b[9] << 16) | (b[10] << 8) | b[11]; | ||
412 | |||
413 | /* set the buffer size - DVB-USB is allocating URB buffers | ||
414 | * only after the firwmare download was successful */ | ||
415 | for (i = 0; i < dib0700_device_count; i++) { | ||
416 | for (adap_num = 0; adap_num < dib0700_devices[i].num_adapters; | ||
417 | adap_num++) { | ||
418 | if (fw_version >= 0x10201) | ||
419 | dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize = 188*nb_packet_buffer_size; | ||
420 | else { | ||
421 | /* for fw version older than 1.20.1, | ||
422 | * the buffersize has to be n times 512 */ | ||
423 | dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize = ((188*nb_packet_buffer_size+188/2)/512)*512; | ||
424 | if (dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize < 512) | ||
425 | dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize = 512; | ||
426 | } | ||
427 | } | ||
428 | } | ||
429 | |||
367 | return ret; | 430 | return ret; |
368 | } | 431 | } |
369 | 432 | ||
@@ -371,6 +434,18 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | |||
371 | { | 434 | { |
372 | struct dib0700_state *st = adap->dev->priv; | 435 | struct dib0700_state *st = adap->dev->priv; |
373 | u8 b[4]; | 436 | u8 b[4]; |
437 | int ret; | ||
438 | |||
439 | if ((onoff != 0) && (st->fw_version >= 0x10201)) { | ||
440 | /* for firmware later than 1.20.1, | ||
441 | * the USB xfer length can be set */ | ||
442 | ret = dib0700_set_usb_xfer_len(adap->dev, | ||
443 | st->nb_packet_buffer_size); | ||
444 | if (ret < 0) { | ||
445 | deb_info("can not set the USB xfer len\n"); | ||
446 | return ret; | ||
447 | } | ||
448 | } | ||
374 | 449 | ||
375 | b[0] = REQUEST_ENABLE_VIDEO; | 450 | b[0] = REQUEST_ENABLE_VIDEO; |
376 | b[1] = (onoff << 4) | 0x00; /* this bit gives a kind of command, rather than enabling something or not */ | 451 | b[1] = (onoff << 4) | 0x00; /* this bit gives a kind of command, rather than enabling something or not */ |
@@ -415,9 +490,21 @@ static int dib0700_probe(struct usb_interface *intf, | |||
415 | 490 | ||
416 | for (i = 0; i < dib0700_device_count; i++) | 491 | for (i = 0; i < dib0700_device_count; i++) |
417 | if (dvb_usb_device_init(intf, &dib0700_devices[i], THIS_MODULE, | 492 | if (dvb_usb_device_init(intf, &dib0700_devices[i], THIS_MODULE, |
418 | &dev, adapter_nr) == 0) | 493 | &dev, adapter_nr) == 0) { |
419 | { | 494 | struct dib0700_state *st = dev->priv; |
495 | u32 hwversion, romversion, fw_version, fwtype; | ||
496 | |||
497 | dib0700_get_version(dev, &hwversion, &romversion, | ||
498 | &fw_version, &fwtype); | ||
499 | |||
500 | deb_info("Firmware version: %x, %d, 0x%x, %d\n", | ||
501 | hwversion, romversion, fw_version, fwtype); | ||
502 | |||
503 | st->fw_version = fw_version; | ||
504 | st->nb_packet_buffer_size = (u32)nb_packet_buffer_size; | ||
505 | |||
420 | dib0700_rc_setup(dev); | 506 | dib0700_rc_setup(dev); |
507 | |||
421 | return 0; | 508 | return 0; |
422 | } | 509 | } |
423 | 510 | ||
diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index 684146f98eb7..44972d01bbd0 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include "xc5000.h" | 18 | #include "xc5000.h" |
19 | #include "s5h1411.h" | 19 | #include "s5h1411.h" |
20 | #include "dib0070.h" | 20 | #include "dib0070.h" |
21 | #include "dib0090.h" | ||
21 | #include "lgdt3305.h" | 22 | #include "lgdt3305.h" |
22 | #include "mxl5007t.h" | 23 | #include "mxl5007t.h" |
23 | 24 | ||
@@ -130,93 +131,95 @@ static int bristol_tuner_attach(struct dvb_usb_adapter *adap) | |||
130 | /* MT226x */ | 131 | /* MT226x */ |
131 | static struct dibx000_agc_config stk7700d_7000p_mt2266_agc_config[2] = { | 132 | static struct dibx000_agc_config stk7700d_7000p_mt2266_agc_config[2] = { |
132 | { | 133 | { |
133 | BAND_UHF, // band_caps | 134 | BAND_UHF, |
134 | 135 | ||
135 | /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, P_agc_inv_pwm1=1, P_agc_inv_pwm2=1, | 136 | /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, P_agc_inv_pwm1=1, P_agc_inv_pwm2=1, |
136 | * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */ | 137 | * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */ |
137 | (0 << 15) | (0 << 14) | (1 << 11) | (1 << 10) | (1 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), // setup | 138 | (0 << 15) | (0 << 14) | (1 << 11) | (1 << 10) | (1 << 9) | (0 << 8) |
138 | 139 | | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), | |
139 | 1130, // inv_gain | 140 | |
140 | 21, // time_stabiliz | 141 | 1130, |
141 | 142 | 21, | |
142 | 0, // alpha_level | 143 | |
143 | 118, // thlock | 144 | 0, |
144 | 145 | 118, | |
145 | 0, // wbd_inv | 146 | |
146 | 3530, // wbd_ref | 147 | 0, |
147 | 1, // wbd_sel | 148 | 3530, |
148 | 0, // wbd_alpha | 149 | 1, |
149 | 150 | 0, | |
150 | 65535, // agc1_max | 151 | |
151 | 33770, // agc1_min | 152 | 65535, |
152 | 65535, // agc2_max | 153 | 33770, |
153 | 23592, // agc2_min | 154 | 65535, |
154 | 155 | 23592, | |
155 | 0, // agc1_pt1 | 156 | |
156 | 62, // agc1_pt2 | 157 | 0, |
157 | 255, // agc1_pt3 | 158 | 62, |
158 | 64, // agc1_slope1 | 159 | 255, |
159 | 64, // agc1_slope2 | 160 | 64, |
160 | 132, // agc2_pt1 | 161 | 64, |
161 | 192, // agc2_pt2 | 162 | 132, |
162 | 80, // agc2_slope1 | 163 | 192, |
163 | 80, // agc2_slope2 | 164 | 80, |
164 | 165 | 80, | |
165 | 17, // alpha_mant | 166 | |
166 | 27, // alpha_exp | 167 | 17, |
167 | 23, // beta_mant | 168 | 27, |
168 | 51, // beta_exp | 169 | 23, |
169 | 170 | 51, | |
170 | 1, // perform_agc_softsplit | 171 | |
172 | 1, | ||
171 | }, { | 173 | }, { |
172 | BAND_VHF | BAND_LBAND, // band_caps | 174 | BAND_VHF | BAND_LBAND, |
173 | 175 | ||
174 | /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, P_agc_inv_pwm1=1, P_agc_inv_pwm2=1, | 176 | /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, P_agc_inv_pwm1=1, P_agc_inv_pwm2=1, |
175 | * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */ | 177 | * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */ |
176 | (0 << 15) | (0 << 14) | (1 << 11) | (1 << 10) | (1 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), // setup | 178 | (0 << 15) | (0 << 14) | (1 << 11) | (1 << 10) | (1 << 9) | (0 << 8) |
177 | 179 | | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), | |
178 | 2372, // inv_gain | 180 | |
179 | 21, // time_stabiliz | 181 | 2372, |
180 | 182 | 21, | |
181 | 0, // alpha_level | 183 | |
182 | 118, // thlock | 184 | 0, |
183 | 185 | 118, | |
184 | 0, // wbd_inv | 186 | |
185 | 3530, // wbd_ref | 187 | 0, |
186 | 1, // wbd_sel | 188 | 3530, |
187 | 0, // wbd_alpha | 189 | 1, |
188 | 190 | 0, | |
189 | 65535, // agc1_max | 191 | |
190 | 0, // agc1_min | 192 | 65535, |
191 | 65535, // agc2_max | 193 | 0, |
192 | 23592, // agc2_min | 194 | 65535, |
193 | 195 | 23592, | |
194 | 0, // agc1_pt1 | 196 | |
195 | 128, // agc1_pt2 | 197 | 0, |
196 | 128, // agc1_pt3 | 198 | 128, |
197 | 128, // agc1_slope1 | 199 | 128, |
198 | 0, // agc1_slope2 | 200 | 128, |
199 | 128, // agc2_pt1 | 201 | 0, |
200 | 253, // agc2_pt2 | 202 | 128, |
201 | 81, // agc2_slope1 | 203 | 253, |
202 | 0, // agc2_slope2 | 204 | 81, |
203 | 205 | 0, | |
204 | 17, // alpha_mant | 206 | |
205 | 27, // alpha_exp | 207 | 17, |
206 | 23, // beta_mant | 208 | 27, |
207 | 51, // beta_exp | 209 | 23, |
208 | 210 | 51, | |
209 | 1, // perform_agc_softsplit | 211 | |
212 | 1, | ||
210 | } | 213 | } |
211 | }; | 214 | }; |
212 | 215 | ||
213 | static struct dibx000_bandwidth_config stk7700d_mt2266_pll_config = { | 216 | static struct dibx000_bandwidth_config stk7700d_mt2266_pll_config = { |
214 | 60000, 30000, // internal, sampling | 217 | 60000, 30000, |
215 | 1, 8, 3, 1, 0, // pll_cfg: prediv, ratio, range, reset, bypass | 218 | 1, 8, 3, 1, 0, |
216 | 0, 0, 1, 1, 2, // misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc, modulo | 219 | 0, 0, 1, 1, 2, |
217 | (3 << 14) | (1 << 12) | (524 << 0), // sad_cfg: refsel, sel, freq_15k | 220 | (3 << 14) | (1 << 12) | (524 << 0), |
218 | 0, // ifreq | 221 | 0, |
219 | 20452225, // timf | 222 | 20452225, |
220 | }; | 223 | }; |
221 | 224 | ||
222 | static struct dib7000p_config stk7700d_dib7000p_mt2266_config[] = { | 225 | static struct dib7000p_config stk7700d_dib7000p_mt2266_config[] = { |
@@ -605,17 +608,17 @@ static int dib0700_rc_query_v1_20(struct dvb_usb_device *d, u32 *event, | |||
605 | } | 608 | } |
606 | break; | 609 | break; |
607 | default: | 610 | default: |
608 | if (actlen != sizeof(buf)) { | 611 | if (actlen != sizeof(buf)) { |
609 | /* We didn't get back the 6 byte message we expected */ | 612 | /* We didn't get back the 6 byte message we expected */ |
610 | err("Unexpected RC response size [%d]", actlen); | 613 | err("Unexpected RC response size [%d]", actlen); |
611 | return -1; | 614 | return -1; |
612 | } | 615 | } |
613 | 616 | ||
614 | poll_reply.report_id = buf[0]; | 617 | poll_reply.report_id = buf[0]; |
615 | poll_reply.data_state = buf[1]; | 618 | poll_reply.data_state = buf[1]; |
616 | poll_reply.system = (buf[2] << 8) | buf[3]; | 619 | poll_reply.system = (buf[2] << 8) | buf[3]; |
617 | poll_reply.data = buf[4]; | 620 | poll_reply.data = buf[4]; |
618 | poll_reply.not_data = buf[5]; | 621 | poll_reply.not_data = buf[5]; |
619 | 622 | ||
620 | break; | 623 | break; |
621 | } | 624 | } |
@@ -632,7 +635,7 @@ static int dib0700_rc_query_v1_20(struct dvb_usb_device *d, u32 *event, | |||
632 | /* Find the key in the map */ | 635 | /* Find the key in the map */ |
633 | for (i = 0; i < d->props.rc_key_map_size; i++) { | 636 | for (i = 0; i < d->props.rc_key_map_size; i++) { |
634 | if (rc5_custom(&keymap[i]) == (poll_reply.system & 0xff) && | 637 | if (rc5_custom(&keymap[i]) == (poll_reply.system & 0xff) && |
635 | rc5_data(&keymap[i]) == poll_reply.data) { | 638 | rc5_data(&keymap[i]) == poll_reply.data) { |
636 | *event = keymap[i].event; | 639 | *event = keymap[i].event; |
637 | found = 1; | 640 | found = 1; |
638 | break; | 641 | break; |
@@ -641,8 +644,8 @@ static int dib0700_rc_query_v1_20(struct dvb_usb_device *d, u32 *event, | |||
641 | 644 | ||
642 | if (found == 0) { | 645 | if (found == 0) { |
643 | err("Unknown remote controller key: %04x %02x %02x", | 646 | err("Unknown remote controller key: %04x %02x %02x", |
644 | poll_reply.system, | 647 | poll_reply.system, |
645 | poll_reply.data, poll_reply.not_data); | 648 | poll_reply.data, poll_reply.not_data); |
646 | d->last_event = 0; | 649 | d->last_event = 0; |
647 | return 0; | 650 | return 0; |
648 | } | 651 | } |
@@ -933,47 +936,48 @@ static struct dvb_usb_rc_key dib0700_rc_keys[] = { | |||
933 | 936 | ||
934 | /* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */ | 937 | /* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */ |
935 | static struct dibx000_agc_config stk7700p_7000m_mt2060_agc_config = { | 938 | static struct dibx000_agc_config stk7700p_7000m_mt2060_agc_config = { |
936 | BAND_UHF | BAND_VHF, // band_caps | 939 | BAND_UHF | BAND_VHF, |
937 | 940 | ||
938 | /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, | 941 | /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, |
939 | * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */ | 942 | * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */ |
940 | (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), // setup | 943 | (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) |
941 | 944 | | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), | |
942 | 712, // inv_gain | 945 | |
943 | 41, // time_stabiliz | 946 | 712, |
944 | 947 | 41, | |
945 | 0, // alpha_level | 948 | |
946 | 118, // thlock | 949 | 0, |
947 | 950 | 118, | |
948 | 0, // wbd_inv | 951 | |
949 | 4095, // wbd_ref | 952 | 0, |
950 | 0, // wbd_sel | 953 | 4095, |
951 | 0, // wbd_alpha | 954 | 0, |
952 | 955 | 0, | |
953 | 42598, // agc1_max | 956 | |
954 | 17694, // agc1_min | 957 | 42598, |
955 | 45875, // agc2_max | 958 | 17694, |
956 | 2621, // agc2_min | 959 | 45875, |
957 | 0, // agc1_pt1 | 960 | 2621, |
958 | 76, // agc1_pt2 | 961 | 0, |
959 | 139, // agc1_pt3 | 962 | 76, |
960 | 52, // agc1_slope1 | 963 | 139, |
961 | 59, // agc1_slope2 | 964 | 52, |
962 | 107, // agc2_pt1 | 965 | 59, |
963 | 172, // agc2_pt2 | 966 | 107, |
964 | 57, // agc2_slope1 | 967 | 172, |
965 | 70, // agc2_slope2 | 968 | 57, |
966 | 969 | 70, | |
967 | 21, // alpha_mant | 970 | |
968 | 25, // alpha_exp | 971 | 21, |
969 | 28, // beta_mant | 972 | 25, |
970 | 48, // beta_exp | 973 | 28, |
971 | 974 | 48, | |
972 | 1, // perform_agc_softsplit | 975 | |
973 | { 0, // split_min | 976 | 1, |
974 | 107, // split_max | 977 | { 0, |
975 | 51800, // global_split_min | 978 | 107, |
976 | 24700 // global_split_max | 979 | 51800, |
980 | 24700 | ||
977 | }, | 981 | }, |
978 | }; | 982 | }; |
979 | 983 | ||
@@ -982,54 +986,55 @@ static struct dibx000_agc_config stk7700p_7000p_mt2060_agc_config = { | |||
982 | 986 | ||
983 | /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, | 987 | /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, |
984 | * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */ | 988 | * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */ |
985 | (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), // setup | 989 | (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) |
990 | | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), | ||
986 | 991 | ||
987 | 712, // inv_gain | 992 | 712, |
988 | 41, // time_stabiliz | 993 | 41, |
989 | 994 | ||
990 | 0, // alpha_level | 995 | 0, |
991 | 118, // thlock | 996 | 118, |
992 | 997 | ||
993 | 0, // wbd_inv | 998 | 0, |
994 | 4095, // wbd_ref | 999 | 4095, |
995 | 0, // wbd_sel | 1000 | 0, |
996 | 0, // wbd_alpha | 1001 | 0, |
997 | 1002 | ||
998 | 42598, // agc1_max | 1003 | 42598, |
999 | 16384, // agc1_min | 1004 | 16384, |
1000 | 42598, // agc2_max | 1005 | 42598, |
1001 | 0, // agc2_min | 1006 | 0, |
1002 | 1007 | ||
1003 | 0, // agc1_pt1 | 1008 | 0, |
1004 | 137, // agc1_pt2 | 1009 | 137, |
1005 | 255, // agc1_pt3 | 1010 | 255, |
1006 | 1011 | ||
1007 | 0, // agc1_slope1 | 1012 | 0, |
1008 | 255, // agc1_slope2 | 1013 | 255, |
1009 | 1014 | ||
1010 | 0, // agc2_pt1 | 1015 | 0, |
1011 | 0, // agc2_pt2 | 1016 | 0, |
1012 | 1017 | ||
1013 | 0, // agc2_slope1 | 1018 | 0, |
1014 | 41, // agc2_slope2 | 1019 | 41, |
1015 | 1020 | ||
1016 | 15, // alpha_mant | 1021 | 15, |
1017 | 25, // alpha_exp | 1022 | 25, |
1018 | 1023 | ||
1019 | 28, // beta_mant | 1024 | 28, |
1020 | 48, // beta_exp | 1025 | 48, |
1021 | 1026 | ||
1022 | 0, // perform_agc_softsplit | 1027 | 0, |
1023 | }; | 1028 | }; |
1024 | 1029 | ||
1025 | static struct dibx000_bandwidth_config stk7700p_pll_config = { | 1030 | static struct dibx000_bandwidth_config stk7700p_pll_config = { |
1026 | 60000, 30000, // internal, sampling | 1031 | 60000, 30000, |
1027 | 1, 8, 3, 1, 0, // pll_cfg: prediv, ratio, range, reset, bypass | 1032 | 1, 8, 3, 1, 0, |
1028 | 0, 0, 1, 1, 0, // misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc, modulo | 1033 | 0, 0, 1, 1, 0, |
1029 | (3 << 14) | (1 << 12) | (524 << 0), // sad_cfg: refsel, sel, freq_15k | 1034 | (3 << 14) | (1 << 12) | (524 << 0), |
1030 | 60258167, // ifreq | 1035 | 60258167, |
1031 | 20452225, // timf | 1036 | 20452225, |
1032 | 30000000, // xtal | 1037 | 30000000, |
1033 | }; | 1038 | }; |
1034 | 1039 | ||
1035 | static struct dib7000m_config stk7700p_dib7000m_config = { | 1040 | static struct dib7000m_config stk7700p_dib7000m_config = { |
@@ -1115,41 +1120,42 @@ static struct dibx000_agc_config dib7070_agc_config = { | |||
1115 | BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND, | 1120 | BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND, |
1116 | /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, | 1121 | /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, |
1117 | * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */ | 1122 | * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */ |
1118 | (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), // setup | 1123 | (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) |
1119 | 1124 | | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), | |
1120 | 600, // inv_gain | 1125 | |
1121 | 10, // time_stabiliz | 1126 | 600, |
1122 | 1127 | 10, | |
1123 | 0, // alpha_level | 1128 | |
1124 | 118, // thlock | 1129 | 0, |
1125 | 1130 | 118, | |
1126 | 0, // wbd_inv | 1131 | |
1127 | 3530, // wbd_ref | 1132 | 0, |
1128 | 1, // wbd_sel | 1133 | 3530, |
1129 | 5, // wbd_alpha | 1134 | 1, |
1130 | 1135 | 5, | |
1131 | 65535, // agc1_max | 1136 | |
1132 | 0, // agc1_min | 1137 | 65535, |
1133 | 1138 | 0, | |
1134 | 65535, // agc2_max | 1139 | |
1135 | 0, // agc2_min | 1140 | 65535, |
1136 | 1141 | 0, | |
1137 | 0, // agc1_pt1 | 1142 | |
1138 | 40, // agc1_pt2 | 1143 | 0, |
1139 | 183, // agc1_pt3 | 1144 | 40, |
1140 | 206, // agc1_slope1 | 1145 | 183, |
1141 | 255, // agc1_slope2 | 1146 | 206, |
1142 | 72, // agc2_pt1 | 1147 | 255, |
1143 | 152, // agc2_pt2 | 1148 | 72, |
1144 | 88, // agc2_slope1 | 1149 | 152, |
1145 | 90, // agc2_slope2 | 1150 | 88, |
1146 | 1151 | 90, | |
1147 | 17, // alpha_mant | 1152 | |
1148 | 27, // alpha_exp | 1153 | 17, |
1149 | 23, // beta_mant | 1154 | 27, |
1150 | 51, // beta_exp | 1155 | 23, |
1151 | 1156 | 51, | |
1152 | 0, // perform_agc_softsplit | 1157 | |
1158 | 0, | ||
1153 | }; | 1159 | }; |
1154 | 1160 | ||
1155 | static int dib7070_tuner_reset(struct dvb_frontend *fe, int onoff) | 1161 | static int dib7070_tuner_reset(struct dvb_frontend *fe, int onoff) |
@@ -1276,13 +1282,13 @@ static int stk70x0p_pid_filter_ctrl(struct dvb_usb_adapter *adapter, int onoff) | |||
1276 | } | 1282 | } |
1277 | 1283 | ||
1278 | static struct dibx000_bandwidth_config dib7070_bw_config_12_mhz = { | 1284 | static struct dibx000_bandwidth_config dib7070_bw_config_12_mhz = { |
1279 | 60000, 15000, // internal, sampling | 1285 | 60000, 15000, |
1280 | 1, 20, 3, 1, 0, // pll_cfg: prediv, ratio, range, reset, bypass | 1286 | 1, 20, 3, 1, 0, |
1281 | 0, 0, 1, 1, 2, // misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc, modulo | 1287 | 0, 0, 1, 1, 2, |
1282 | (3 << 14) | (1 << 12) | (524 << 0), // sad_cfg: refsel, sel, freq_15k | 1288 | (3 << 14) | (1 << 12) | (524 << 0), |
1283 | (0 << 25) | 0, // ifreq = 0.000000 MHz | 1289 | (0 << 25) | 0, |
1284 | 20452225, // timf | 1290 | 20452225, |
1285 | 12000000, // xtal_hz | 1291 | 12000000, |
1286 | }; | 1292 | }; |
1287 | 1293 | ||
1288 | static struct dib7000p_config dib7070p_dib7000p_config = { | 1294 | static struct dib7000p_config dib7070p_dib7000p_config = { |
@@ -1476,12 +1482,12 @@ static struct dib8000_config dib807x_dib8000_config[2] = { | |||
1476 | } | 1482 | } |
1477 | }; | 1483 | }; |
1478 | 1484 | ||
1479 | static int dib807x_tuner_reset(struct dvb_frontend *fe, int onoff) | 1485 | static int dib80xx_tuner_reset(struct dvb_frontend *fe, int onoff) |
1480 | { | 1486 | { |
1481 | return dib8000_set_gpio(fe, 5, 0, !onoff); | 1487 | return dib8000_set_gpio(fe, 5, 0, !onoff); |
1482 | } | 1488 | } |
1483 | 1489 | ||
1484 | static int dib807x_tuner_sleep(struct dvb_frontend *fe, int onoff) | 1490 | static int dib80xx_tuner_sleep(struct dvb_frontend *fe, int onoff) |
1485 | { | 1491 | { |
1486 | return dib8000_set_gpio(fe, 0, 0, onoff); | 1492 | return dib8000_set_gpio(fe, 0, 0, onoff); |
1487 | } | 1493 | } |
@@ -1494,8 +1500,8 @@ static const struct dib0070_wbd_gain_cfg dib8070_wbd_gain_cfg[] = { | |||
1494 | static struct dib0070_config dib807x_dib0070_config[2] = { | 1500 | static struct dib0070_config dib807x_dib0070_config[2] = { |
1495 | { | 1501 | { |
1496 | .i2c_address = DEFAULT_DIB0070_I2C_ADDRESS, | 1502 | .i2c_address = DEFAULT_DIB0070_I2C_ADDRESS, |
1497 | .reset = dib807x_tuner_reset, | 1503 | .reset = dib80xx_tuner_reset, |
1498 | .sleep = dib807x_tuner_sleep, | 1504 | .sleep = dib80xx_tuner_sleep, |
1499 | .clock_khz = 12000, | 1505 | .clock_khz = 12000, |
1500 | .clock_pad_drive = 4, | 1506 | .clock_pad_drive = 4, |
1501 | .vga_filter = 1, | 1507 | .vga_filter = 1, |
@@ -1508,8 +1514,8 @@ static struct dib0070_config dib807x_dib0070_config[2] = { | |||
1508 | .freq_offset_khz_vhf = -100, | 1514 | .freq_offset_khz_vhf = -100, |
1509 | }, { | 1515 | }, { |
1510 | .i2c_address = DEFAULT_DIB0070_I2C_ADDRESS, | 1516 | .i2c_address = DEFAULT_DIB0070_I2C_ADDRESS, |
1511 | .reset = dib807x_tuner_reset, | 1517 | .reset = dib80xx_tuner_reset, |
1512 | .sleep = dib807x_tuner_sleep, | 1518 | .sleep = dib80xx_tuner_sleep, |
1513 | .clock_khz = 12000, | 1519 | .clock_khz = 12000, |
1514 | .clock_pad_drive = 2, | 1520 | .clock_pad_drive = 2, |
1515 | .vga_filter = 1, | 1521 | .vga_filter = 1, |
@@ -1566,12 +1572,14 @@ static int dib807x_tuner_attach(struct dvb_usb_adapter *adap) | |||
1566 | return 0; | 1572 | return 0; |
1567 | } | 1573 | } |
1568 | 1574 | ||
1569 | static int stk807x_pid_filter(struct dvb_usb_adapter *adapter, int index, u16 pid, int onoff) | 1575 | static int stk80xx_pid_filter(struct dvb_usb_adapter *adapter, int index, |
1576 | u16 pid, int onoff) | ||
1570 | { | 1577 | { |
1571 | return dib8000_pid_filter(adapter->fe, index, pid, onoff); | 1578 | return dib8000_pid_filter(adapter->fe, index, pid, onoff); |
1572 | } | 1579 | } |
1573 | 1580 | ||
1574 | static int stk807x_pid_filter_ctrl(struct dvb_usb_adapter *adapter, int onoff) | 1581 | static int stk80xx_pid_filter_ctrl(struct dvb_usb_adapter *adapter, |
1582 | int onoff) | ||
1575 | { | 1583 | { |
1576 | return dib8000_pid_filter_ctrl(adapter->fe, onoff); | 1584 | return dib8000_pid_filter_ctrl(adapter->fe, onoff); |
1577 | } | 1585 | } |
@@ -1624,7 +1632,7 @@ static int stk807xpvr_frontend_attach0(struct dvb_usb_adapter *adap) | |||
1624 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); | 1632 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); |
1625 | 1633 | ||
1626 | /* initialize IC 0 */ | 1634 | /* initialize IC 0 */ |
1627 | dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x12, 0x80); | 1635 | dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x22, 0x80); |
1628 | 1636 | ||
1629 | adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, | 1637 | adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, |
1630 | &dib807x_dib8000_config[0]); | 1638 | &dib807x_dib8000_config[0]); |
@@ -1635,7 +1643,7 @@ static int stk807xpvr_frontend_attach0(struct dvb_usb_adapter *adap) | |||
1635 | static int stk807xpvr_frontend_attach1(struct dvb_usb_adapter *adap) | 1643 | static int stk807xpvr_frontend_attach1(struct dvb_usb_adapter *adap) |
1636 | { | 1644 | { |
1637 | /* initialize IC 1 */ | 1645 | /* initialize IC 1 */ |
1638 | dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x22, 0x82); | 1646 | dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x12, 0x82); |
1639 | 1647 | ||
1640 | adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x82, | 1648 | adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x82, |
1641 | &dib807x_dib8000_config[1]); | 1649 | &dib807x_dib8000_config[1]); |
@@ -1643,6 +1651,245 @@ static int stk807xpvr_frontend_attach1(struct dvb_usb_adapter *adap) | |||
1643 | return adap->fe == NULL ? -ENODEV : 0; | 1651 | return adap->fe == NULL ? -ENODEV : 0; |
1644 | } | 1652 | } |
1645 | 1653 | ||
1654 | /* STK8096GP */ | ||
1655 | struct dibx000_agc_config dib8090_agc_config[2] = { | ||
1656 | { | ||
1657 | BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND, | ||
1658 | /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, | ||
1659 | * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0, | ||
1660 | * P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */ | ||
1661 | (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | ||
1662 | | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), | ||
1663 | |||
1664 | 787, | ||
1665 | 10, | ||
1666 | |||
1667 | 0, | ||
1668 | 118, | ||
1669 | |||
1670 | 0, | ||
1671 | 3530, | ||
1672 | 1, | ||
1673 | 5, | ||
1674 | |||
1675 | 65535, | ||
1676 | 0, | ||
1677 | |||
1678 | 65535, | ||
1679 | 0, | ||
1680 | |||
1681 | 0, | ||
1682 | 32, | ||
1683 | 114, | ||
1684 | 143, | ||
1685 | 144, | ||
1686 | 114, | ||
1687 | 227, | ||
1688 | 116, | ||
1689 | 117, | ||
1690 | |||
1691 | 28, | ||
1692 | 26, | ||
1693 | 31, | ||
1694 | 51, | ||
1695 | |||
1696 | 0, | ||
1697 | }, | ||
1698 | { | ||
1699 | BAND_CBAND, | ||
1700 | /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, | ||
1701 | * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0, | ||
1702 | * P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */ | ||
1703 | (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | ||
1704 | | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), | ||
1705 | |||
1706 | 787, | ||
1707 | 10, | ||
1708 | |||
1709 | 0, | ||
1710 | 118, | ||
1711 | |||
1712 | 0, | ||
1713 | 3530, | ||
1714 | 1, | ||
1715 | 5, | ||
1716 | |||
1717 | 0, | ||
1718 | 0, | ||
1719 | |||
1720 | 65535, | ||
1721 | 0, | ||
1722 | |||
1723 | 0, | ||
1724 | 32, | ||
1725 | 114, | ||
1726 | 143, | ||
1727 | 144, | ||
1728 | 114, | ||
1729 | 227, | ||
1730 | 116, | ||
1731 | 117, | ||
1732 | |||
1733 | 28, | ||
1734 | 26, | ||
1735 | 31, | ||
1736 | 51, | ||
1737 | |||
1738 | 0, | ||
1739 | } | ||
1740 | }; | ||
1741 | |||
1742 | static struct dibx000_bandwidth_config dib8090_pll_config_12mhz = { | ||
1743 | 54000, 13500, | ||
1744 | 1, 18, 3, 1, 0, | ||
1745 | 0, 0, 1, 1, 2, | ||
1746 | (3 << 14) | (1 << 12) | (599 << 0), | ||
1747 | (0 << 25) | 0, | ||
1748 | 20199727, | ||
1749 | 12000000, | ||
1750 | }; | ||
1751 | |||
1752 | static int dib8090_get_adc_power(struct dvb_frontend *fe) | ||
1753 | { | ||
1754 | return dib8000_get_adc_power(fe, 1); | ||
1755 | } | ||
1756 | |||
1757 | static struct dib8000_config dib809x_dib8000_config = { | ||
1758 | .output_mpeg2_in_188_bytes = 1, | ||
1759 | |||
1760 | .agc_config_count = 2, | ||
1761 | .agc = dib8090_agc_config, | ||
1762 | .agc_control = dib0090_dcc_freq, | ||
1763 | .pll = &dib8090_pll_config_12mhz, | ||
1764 | .tuner_is_baseband = 1, | ||
1765 | |||
1766 | .gpio_dir = DIB8000_GPIO_DEFAULT_DIRECTIONS, | ||
1767 | .gpio_val = DIB8000_GPIO_DEFAULT_VALUES, | ||
1768 | .gpio_pwm_pos = DIB8000_GPIO_DEFAULT_PWM_POS, | ||
1769 | |||
1770 | .hostbus_diversity = 1, | ||
1771 | .div_cfg = 0x31, | ||
1772 | .output_mode = OUTMODE_MPEG2_FIFO, | ||
1773 | .drives = 0x2d98, | ||
1774 | .diversity_delay = 144, | ||
1775 | .refclksel = 3, | ||
1776 | }; | ||
1777 | |||
1778 | static struct dib0090_config dib809x_dib0090_config = { | ||
1779 | .io.pll_bypass = 1, | ||
1780 | .io.pll_range = 1, | ||
1781 | .io.pll_prediv = 1, | ||
1782 | .io.pll_loopdiv = 20, | ||
1783 | .io.adc_clock_ratio = 8, | ||
1784 | .io.pll_int_loop_filt = 0, | ||
1785 | .io.clock_khz = 12000, | ||
1786 | .reset = dib80xx_tuner_reset, | ||
1787 | .sleep = dib80xx_tuner_sleep, | ||
1788 | .clkouttobamse = 1, | ||
1789 | .analog_output = 1, | ||
1790 | .i2c_address = DEFAULT_DIB0090_I2C_ADDRESS, | ||
1791 | .wbd_vhf_offset = 100, | ||
1792 | .wbd_cband_offset = 450, | ||
1793 | .use_pwm_agc = 1, | ||
1794 | .clkoutdrive = 1, | ||
1795 | .get_adc_power = dib8090_get_adc_power, | ||
1796 | .freq_offset_khz_uhf = 0, | ||
1797 | .freq_offset_khz_vhf = -143, | ||
1798 | }; | ||
1799 | |||
1800 | static int dib8096_set_param_override(struct dvb_frontend *fe, | ||
1801 | struct dvb_frontend_parameters *fep) | ||
1802 | { | ||
1803 | struct dvb_usb_adapter *adap = fe->dvb->priv; | ||
1804 | struct dib0700_adapter_state *state = adap->priv; | ||
1805 | u8 band = BAND_OF_FREQUENCY(fep->frequency/1000); | ||
1806 | u16 offset; | ||
1807 | int ret = 0; | ||
1808 | enum frontend_tune_state tune_state = CT_SHUTDOWN; | ||
1809 | u16 ltgain, rf_gain_limit; | ||
1810 | |||
1811 | ret = state->set_param_save(fe, fep); | ||
1812 | if (ret < 0) | ||
1813 | return ret; | ||
1814 | |||
1815 | switch (band) { | ||
1816 | case BAND_VHF: | ||
1817 | offset = 100; | ||
1818 | break; | ||
1819 | case BAND_UHF: | ||
1820 | offset = 550; | ||
1821 | break; | ||
1822 | default: | ||
1823 | offset = 0; | ||
1824 | break; | ||
1825 | } | ||
1826 | offset += (dib0090_get_wbd_offset(fe) * 8 * 18 / 33 + 1) / 2; | ||
1827 | dib8000_set_wbd_ref(fe, offset); | ||
1828 | |||
1829 | |||
1830 | if (band == BAND_CBAND) { | ||
1831 | deb_info("tuning in CBAND - soft-AGC startup\n"); | ||
1832 | /* TODO specific wbd target for dib0090 - needed for startup ? */ | ||
1833 | dib0090_set_tune_state(fe, CT_AGC_START); | ||
1834 | do { | ||
1835 | ret = dib0090_gain_control(fe); | ||
1836 | msleep(ret); | ||
1837 | tune_state = dib0090_get_tune_state(fe); | ||
1838 | if (tune_state == CT_AGC_STEP_0) | ||
1839 | dib8000_set_gpio(fe, 6, 0, 1); | ||
1840 | else if (tune_state == CT_AGC_STEP_1) { | ||
1841 | dib0090_get_current_gain(fe, NULL, NULL, &rf_gain_limit, <gain); | ||
1842 | if (rf_gain_limit == 0) | ||
1843 | dib8000_set_gpio(fe, 6, 0, 0); | ||
1844 | } | ||
1845 | } while (tune_state < CT_AGC_STOP); | ||
1846 | dib0090_pwm_gain_reset(fe); | ||
1847 | dib8000_pwm_agc_reset(fe); | ||
1848 | dib8000_set_tune_state(fe, CT_DEMOD_START); | ||
1849 | } else { | ||
1850 | deb_info("not tuning in CBAND - standard AGC startup\n"); | ||
1851 | dib0090_pwm_gain_reset(fe); | ||
1852 | } | ||
1853 | |||
1854 | return 0; | ||
1855 | } | ||
1856 | |||
1857 | static int dib809x_tuner_attach(struct dvb_usb_adapter *adap) | ||
1858 | { | ||
1859 | struct dib0700_adapter_state *st = adap->priv; | ||
1860 | struct i2c_adapter *tun_i2c = dib8000_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1); | ||
1861 | |||
1862 | if (dvb_attach(dib0090_register, adap->fe, tun_i2c, &dib809x_dib0090_config) == NULL) | ||
1863 | return -ENODEV; | ||
1864 | |||
1865 | st->set_param_save = adap->fe->ops.tuner_ops.set_params; | ||
1866 | adap->fe->ops.tuner_ops.set_params = dib8096_set_param_override; | ||
1867 | return 0; | ||
1868 | } | ||
1869 | |||
1870 | static int stk809x_frontend_attach(struct dvb_usb_adapter *adap) | ||
1871 | { | ||
1872 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); | ||
1873 | msleep(10); | ||
1874 | dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); | ||
1875 | dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1); | ||
1876 | dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1); | ||
1877 | |||
1878 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); | ||
1879 | |||
1880 | dib0700_ctrl_clock(adap->dev, 72, 1); | ||
1881 | |||
1882 | msleep(10); | ||
1883 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); | ||
1884 | msleep(10); | ||
1885 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); | ||
1886 | |||
1887 | dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, 0x80); | ||
1888 | |||
1889 | adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config); | ||
1890 | |||
1891 | return adap->fe == NULL ? -ENODEV : 0; | ||
1892 | } | ||
1646 | 1893 | ||
1647 | /* STK7070PD */ | 1894 | /* STK7070PD */ |
1648 | static struct dib7000p_config stk7070pd_dib7000p_config[2] = { | 1895 | static struct dib7000p_config stk7070pd_dib7000p_config[2] = { |
@@ -1929,14 +2176,17 @@ struct usb_device_id dib0700_usb_id_table[] = { | |||
1929 | { USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_STK7700D) }, | 2176 | { USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_STK7700D) }, |
1930 | /* 55 */{ USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_STK7700D_2) }, | 2177 | /* 55 */{ USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_STK7700D_2) }, |
1931 | { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV73A) }, | 2178 | { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV73A) }, |
1932 | { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV73ESE) }, | 2179 | { USB_DEVICE(USB_VID_PCTV, USB_PID_PINNACLE_PCTV73ESE) }, |
1933 | { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV282E) }, | 2180 | { USB_DEVICE(USB_VID_PCTV, USB_PID_PINNACLE_PCTV282E) }, |
1934 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7770P) }, | 2181 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7770P) }, |
1935 | /* 60 */{ USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_XXS_2) }, | 2182 | /* 60 */{ USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_XXS_2) }, |
1936 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK807XPVR) }, | 2183 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK807XPVR) }, |
1937 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK807XP) }, | 2184 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK807XP) }, |
1938 | { USB_DEVICE(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD) }, | 2185 | { USB_DEVICE(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD) }, |
1939 | { USB_DEVICE(USB_VID_EVOLUTEPC, USB_PID_TVWAY_PLUS) }, | 2186 | { USB_DEVICE(USB_VID_EVOLUTEPC, USB_PID_TVWAY_PLUS) }, |
2187 | /* 65 */{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV73ESE) }, | ||
2188 | { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV282E) }, | ||
2189 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK8096GP) }, | ||
1940 | { 0 } /* Terminating entry */ | 2190 | { 0 } /* Terminating entry */ |
1941 | }; | 2191 | }; |
1942 | MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); | 2192 | MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); |
@@ -2238,11 +2488,11 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
2238 | { NULL }, | 2488 | { NULL }, |
2239 | }, | 2489 | }, |
2240 | { "Pinnacle PCTV 73e SE", | 2490 | { "Pinnacle PCTV 73e SE", |
2241 | { &dib0700_usb_id_table[57], NULL }, | 2491 | { &dib0700_usb_id_table[57], &dib0700_usb_id_table[65], NULL }, |
2242 | { NULL }, | 2492 | { NULL }, |
2243 | }, | 2493 | }, |
2244 | { "Pinnacle PCTV 282e", | 2494 | { "Pinnacle PCTV 282e", |
2245 | { &dib0700_usb_id_table[58], NULL }, | 2495 | { &dib0700_usb_id_table[58], &dib0700_usb_id_table[66], NULL }, |
2246 | { NULL }, | 2496 | { NULL }, |
2247 | }, | 2497 | }, |
2248 | }, | 2498 | }, |
@@ -2471,8 +2721,8 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
2471 | { | 2721 | { |
2472 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | 2722 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, |
2473 | .pid_filter_count = 32, | 2723 | .pid_filter_count = 32, |
2474 | .pid_filter = stk807x_pid_filter, | 2724 | .pid_filter = stk80xx_pid_filter, |
2475 | .pid_filter_ctrl = stk807x_pid_filter_ctrl, | 2725 | .pid_filter_ctrl = stk80xx_pid_filter_ctrl, |
2476 | .frontend_attach = stk807x_frontend_attach, | 2726 | .frontend_attach = stk807x_frontend_attach, |
2477 | .tuner_attach = dib807x_tuner_attach, | 2727 | .tuner_attach = dib807x_tuner_attach, |
2478 | 2728 | ||
@@ -2510,8 +2760,8 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
2510 | { | 2760 | { |
2511 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | 2761 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, |
2512 | .pid_filter_count = 32, | 2762 | .pid_filter_count = 32, |
2513 | .pid_filter = stk807x_pid_filter, | 2763 | .pid_filter = stk80xx_pid_filter, |
2514 | .pid_filter_ctrl = stk807x_pid_filter_ctrl, | 2764 | .pid_filter_ctrl = stk80xx_pid_filter_ctrl, |
2515 | .frontend_attach = stk807xpvr_frontend_attach0, | 2765 | .frontend_attach = stk807xpvr_frontend_attach0, |
2516 | .tuner_attach = dib807x_tuner_attach, | 2766 | .tuner_attach = dib807x_tuner_attach, |
2517 | 2767 | ||
@@ -2523,8 +2773,8 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
2523 | { | 2773 | { |
2524 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | 2774 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, |
2525 | .pid_filter_count = 32, | 2775 | .pid_filter_count = 32, |
2526 | .pid_filter = stk807x_pid_filter, | 2776 | .pid_filter = stk80xx_pid_filter, |
2527 | .pid_filter_ctrl = stk807x_pid_filter_ctrl, | 2777 | .pid_filter_ctrl = stk80xx_pid_filter_ctrl, |
2528 | .frontend_attach = stk807xpvr_frontend_attach1, | 2778 | .frontend_attach = stk807xpvr_frontend_attach1, |
2529 | .tuner_attach = dib807x_tuner_attach, | 2779 | .tuner_attach = dib807x_tuner_attach, |
2530 | 2780 | ||
@@ -2547,6 +2797,37 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
2547 | .rc_key_map = dib0700_rc_keys, | 2797 | .rc_key_map = dib0700_rc_keys, |
2548 | .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys), | 2798 | .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys), |
2549 | .rc_query = dib0700_rc_query | 2799 | .rc_query = dib0700_rc_query |
2800 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | ||
2801 | .num_adapters = 1, | ||
2802 | .adapter = { | ||
2803 | { | ||
2804 | .caps = DVB_USB_ADAP_HAS_PID_FILTER | | ||
2805 | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, | ||
2806 | .pid_filter_count = 32, | ||
2807 | .pid_filter = stk80xx_pid_filter, | ||
2808 | .pid_filter_ctrl = stk80xx_pid_filter_ctrl, | ||
2809 | .frontend_attach = stk809x_frontend_attach, | ||
2810 | .tuner_attach = dib809x_tuner_attach, | ||
2811 | |||
2812 | DIB0700_DEFAULT_STREAMING_CONFIG(0x02), | ||
2813 | |||
2814 | .size_of_priv = | ||
2815 | sizeof(struct dib0700_adapter_state), | ||
2816 | }, | ||
2817 | }, | ||
2818 | |||
2819 | .num_device_descs = 1, | ||
2820 | .devices = { | ||
2821 | { "DiBcom STK8096GP reference design", | ||
2822 | { &dib0700_usb_id_table[67], NULL }, | ||
2823 | { NULL }, | ||
2824 | }, | ||
2825 | }, | ||
2826 | |||
2827 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
2828 | .rc_key_map = dib0700_rc_keys, | ||
2829 | .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys), | ||
2830 | .rc_query = dib0700_rc_query | ||
2550 | }, | 2831 | }, |
2551 | }; | 2832 | }; |
2552 | 2833 | ||
diff --git a/drivers/media/dvb/dvb-usb/dibusb-common.c b/drivers/media/dvb/dvb-usb/dibusb-common.c index da34979b5337..9143b5631e88 100644 --- a/drivers/media/dvb/dvb-usb/dibusb-common.c +++ b/drivers/media/dvb/dvb-usb/dibusb-common.c | |||
@@ -142,8 +142,13 @@ static int dibusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num | |||
142 | } else if ((msg[i].flags & I2C_M_RD) == 0) { | 142 | } else if ((msg[i].flags & I2C_M_RD) == 0) { |
143 | if (dibusb_i2c_msg(d, msg[i].addr, msg[i].buf,msg[i].len,NULL,0) < 0) | 143 | if (dibusb_i2c_msg(d, msg[i].addr, msg[i].buf,msg[i].len,NULL,0) < 0) |
144 | break; | 144 | break; |
145 | } else | 145 | } else if (msg[i].addr != 0x50) { |
146 | break; | 146 | /* 0x50 is the address of the eeprom - we need to protect it |
147 | * from dibusb's bad i2c implementation: reads without | ||
148 | * writing the offset before are forbidden */ | ||
149 | if (dibusb_i2c_msg(d, msg[i].addr, NULL, 0, msg[i].buf, msg[i].len) < 0) | ||
150 | break; | ||
151 | } | ||
147 | } | 152 | } |
148 | 153 | ||
149 | mutex_unlock(&d->i2c_mutex); | 154 | mutex_unlock(&d->i2c_mutex); |
@@ -243,6 +248,12 @@ static struct dib3000mc_config mod3000p_dib3000p_config = { | |||
243 | 248 | ||
244 | int dibusb_dib3000mc_frontend_attach(struct dvb_usb_adapter *adap) | 249 | int dibusb_dib3000mc_frontend_attach(struct dvb_usb_adapter *adap) |
245 | { | 250 | { |
251 | if (adap->dev->udev->descriptor.idVendor == USB_VID_LITEON && | ||
252 | adap->dev->udev->descriptor.idProduct == | ||
253 | USB_PID_LITEON_DVB_T_WARM) { | ||
254 | msleep(1000); | ||
255 | } | ||
256 | |||
246 | if ((adap->fe = dvb_attach(dib3000mc_attach, &adap->dev->i2c_adap, DEFAULT_DIB3000P_I2C_ADDRESS, &mod3000p_dib3000p_config)) != NULL || | 257 | if ((adap->fe = dvb_attach(dib3000mc_attach, &adap->dev->i2c_adap, DEFAULT_DIB3000P_I2C_ADDRESS, &mod3000p_dib3000p_config)) != NULL || |
247 | (adap->fe = dvb_attach(dib3000mc_attach, &adap->dev->i2c_adap, DEFAULT_DIB3000MC_I2C_ADDRESS, &mod3000p_dib3000p_config)) != NULL) { | 258 | (adap->fe = dvb_attach(dib3000mc_attach, &adap->dev->i2c_adap, DEFAULT_DIB3000MC_I2C_ADDRESS, &mod3000p_dib3000p_config)) != NULL) { |
248 | if (adap->priv != NULL) { | 259 | if (adap->priv != NULL) { |
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index f1602d4ace6d..bc3581d58ced 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h | |||
@@ -47,6 +47,7 @@ | |||
47 | #define USB_VID_MSI_2 0x1462 | 47 | #define USB_VID_MSI_2 0x1462 |
48 | #define USB_VID_OPERA1 0x695c | 48 | #define USB_VID_OPERA1 0x695c |
49 | #define USB_VID_PINNACLE 0x2304 | 49 | #define USB_VID_PINNACLE 0x2304 |
50 | #define USB_VID_PCTV 0x2013 | ||
50 | #define USB_VID_PIXELVIEW 0x1554 | 51 | #define USB_VID_PIXELVIEW 0x1554 |
51 | #define USB_VID_TECHNOTREND 0x0b48 | 52 | #define USB_VID_TECHNOTREND 0x0b48 |
52 | #define USB_VID_TERRATEC 0x0ccd | 53 | #define USB_VID_TERRATEC 0x0ccd |
@@ -101,6 +102,7 @@ | |||
101 | #define USB_PID_DIBCOM_STK7070PD 0x1ebe | 102 | #define USB_PID_DIBCOM_STK7070PD 0x1ebe |
102 | #define USB_PID_DIBCOM_STK807XP 0x1f90 | 103 | #define USB_PID_DIBCOM_STK807XP 0x1f90 |
103 | #define USB_PID_DIBCOM_STK807XPVR 0x1f98 | 104 | #define USB_PID_DIBCOM_STK807XPVR 0x1f98 |
105 | #define USB_PID_DIBCOM_STK8096GP 0x1fa0 | ||
104 | #define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131 | 106 | #define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131 |
105 | #define USB_PID_DIBCOM_STK7770P 0x1e80 | 107 | #define USB_PID_DIBCOM_STK7770P 0x1e80 |
106 | #define USB_PID_DPOSH_M9206_COLD 0x9206 | 108 | #define USB_PID_DPOSH_M9206_COLD 0x9206 |
@@ -211,6 +213,7 @@ | |||
211 | #define USB_PID_PINNACLE_PCTV801E_SE 0x023b | 213 | #define USB_PID_PINNACLE_PCTV801E_SE 0x023b |
212 | #define USB_PID_PINNACLE_PCTV73A 0x0243 | 214 | #define USB_PID_PINNACLE_PCTV73A 0x0243 |
213 | #define USB_PID_PINNACLE_PCTV73ESE 0x0245 | 215 | #define USB_PID_PINNACLE_PCTV73ESE 0x0245 |
216 | #define USB_PID_PINNACLE_PCTV74E 0x0246 | ||
214 | #define USB_PID_PINNACLE_PCTV282E 0x0248 | 217 | #define USB_PID_PINNACLE_PCTV282E 0x0248 |
215 | #define USB_PID_PIXELVIEW_SBTVD 0x5010 | 218 | #define USB_PID_PIXELVIEW_SBTVD 0x5010 |
216 | #define USB_PID_PCTV_200E 0x020e | 219 | #define USB_PID_PCTV_200E 0x020e |
diff --git a/drivers/media/dvb/dvb-usb/dw2102.c b/drivers/media/dvb/dvb-usb/dw2102.c index 5bb9479d154e..64132c0cf80d 100644 --- a/drivers/media/dvb/dvb-usb/dw2102.c +++ b/drivers/media/dvb/dvb-usb/dw2102.c | |||
@@ -20,6 +20,11 @@ | |||
20 | #include "tda1002x.h" | 20 | #include "tda1002x.h" |
21 | #include "mt312.h" | 21 | #include "mt312.h" |
22 | #include "zl10039.h" | 22 | #include "zl10039.h" |
23 | #include "ds3000.h" | ||
24 | #include "stv0900.h" | ||
25 | #include "stv6110.h" | ||
26 | #include "stb6100.h" | ||
27 | #include "stb6100_proc.h" | ||
23 | 28 | ||
24 | #ifndef USB_PID_DW2102 | 29 | #ifndef USB_PID_DW2102 |
25 | #define USB_PID_DW2102 0x2102 | 30 | #define USB_PID_DW2102 0x2102 |
@@ -37,12 +42,20 @@ | |||
37 | #define USB_PID_CINERGY_S 0x0064 | 42 | #define USB_PID_CINERGY_S 0x0064 |
38 | #endif | 43 | #endif |
39 | 44 | ||
45 | #ifndef USB_PID_TEVII_S630 | ||
46 | #define USB_PID_TEVII_S630 0xd630 | ||
47 | #endif | ||
48 | |||
40 | #ifndef USB_PID_TEVII_S650 | 49 | #ifndef USB_PID_TEVII_S650 |
41 | #define USB_PID_TEVII_S650 0xd650 | 50 | #define USB_PID_TEVII_S650 0xd650 |
42 | #endif | 51 | #endif |
43 | 52 | ||
44 | #ifndef USB_PID_TEVII_S630 | 53 | #ifndef USB_PID_TEVII_S660 |
45 | #define USB_PID_TEVII_S630 0xd630 | 54 | #define USB_PID_TEVII_S660 0xd660 |
55 | #endif | ||
56 | |||
57 | #ifndef USB_PID_PROF_1100 | ||
58 | #define USB_PID_PROF_1100 0xb012 | ||
46 | #endif | 59 | #endif |
47 | 60 | ||
48 | #define DW210X_READ_MSG 0 | 61 | #define DW210X_READ_MSG 0 |
@@ -55,6 +68,10 @@ | |||
55 | #define DW2102_VOLTAGE_CTRL (0x1800) | 68 | #define DW2102_VOLTAGE_CTRL (0x1800) |
56 | #define DW2102_RC_QUERY (0x1a00) | 69 | #define DW2102_RC_QUERY (0x1a00) |
57 | 70 | ||
71 | #define err_str "did not find the firmware file. (%s) " \ | ||
72 | "Please see linux/Documentation/dvb/ for more details " \ | ||
73 | "on firmware-problems." | ||
74 | |||
58 | struct dvb_usb_rc_keys_table { | 75 | struct dvb_usb_rc_keys_table { |
59 | struct dvb_usb_rc_key *rc_keys; | 76 | struct dvb_usb_rc_key *rc_keys; |
60 | int rc_keys_size; | 77 | int rc_keys_size; |
@@ -71,6 +88,12 @@ static int ir_keymap; | |||
71 | module_param_named(keymap, ir_keymap, int, 0644); | 88 | module_param_named(keymap, ir_keymap, int, 0644); |
72 | MODULE_PARM_DESC(keymap, "set keymap 0=default 1=dvbworld 2=tevii 3=tbs ..."); | 89 | MODULE_PARM_DESC(keymap, "set keymap 0=default 1=dvbworld 2=tevii 3=tbs ..."); |
73 | 90 | ||
91 | /* demod probe */ | ||
92 | static int demod_probe = 1; | ||
93 | module_param_named(demod, demod_probe, int, 0644); | ||
94 | MODULE_PARM_DESC(demod, "demod to probe (1=cx24116 2=stv0903+stv6110 " | ||
95 | "4=stv0903+stb6100(or-able))."); | ||
96 | |||
74 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | 97 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
75 | 98 | ||
76 | static int dw210x_op_rw(struct usb_device *dev, u8 request, u16 value, | 99 | static int dw210x_op_rw(struct usb_device *dev, u8 request, u16 value, |
@@ -183,7 +206,7 @@ static int dw2102_serit_i2c_transfer(struct i2c_adapter *adap, | |||
183 | switch (num) { | 206 | switch (num) { |
184 | case 2: | 207 | case 2: |
185 | /* read si2109 register by number */ | 208 | /* read si2109 register by number */ |
186 | buf6[0] = 0xd0; | 209 | buf6[0] = msg[0].addr << 1; |
187 | buf6[1] = msg[0].len; | 210 | buf6[1] = msg[0].len; |
188 | buf6[2] = msg[0].buf[0]; | 211 | buf6[2] = msg[0].buf[0]; |
189 | ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, | 212 | ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, |
@@ -198,7 +221,7 @@ static int dw2102_serit_i2c_transfer(struct i2c_adapter *adap, | |||
198 | switch (msg[0].addr) { | 221 | switch (msg[0].addr) { |
199 | case 0x68: | 222 | case 0x68: |
200 | /* write to si2109 register */ | 223 | /* write to si2109 register */ |
201 | buf6[0] = 0xd0; | 224 | buf6[0] = msg[0].addr << 1; |
202 | buf6[1] = msg[0].len; | 225 | buf6[1] = msg[0].len; |
203 | memcpy(buf6 + 2, msg[0].buf, msg[0].len); | 226 | memcpy(buf6 + 2, msg[0].buf, msg[0].len); |
204 | ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, buf6, | 227 | ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, buf6, |
@@ -239,7 +262,7 @@ static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg ms | |||
239 | /* read */ | 262 | /* read */ |
240 | /* first write first register number */ | 263 | /* first write first register number */ |
241 | u8 ibuf[msg[1].len + 2], obuf[3]; | 264 | u8 ibuf[msg[1].len + 2], obuf[3]; |
242 | obuf[0] = 0xd0; | 265 | obuf[0] = msg[0].addr << 1; |
243 | obuf[1] = msg[0].len; | 266 | obuf[1] = msg[0].len; |
244 | obuf[2] = msg[0].buf[0]; | 267 | obuf[2] = msg[0].buf[0]; |
245 | ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, | 268 | ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, |
@@ -256,7 +279,7 @@ static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg ms | |||
256 | case 0x68: { | 279 | case 0x68: { |
257 | /* write to register */ | 280 | /* write to register */ |
258 | u8 obuf[msg[0].len + 2]; | 281 | u8 obuf[msg[0].len + 2]; |
259 | obuf[0] = 0xd0; | 282 | obuf[0] = msg[0].addr << 1; |
260 | obuf[1] = msg[0].len; | 283 | obuf[1] = msg[0].len; |
261 | memcpy(obuf + 2, msg[0].buf, msg[0].len); | 284 | memcpy(obuf + 2, msg[0].buf, msg[0].len); |
262 | ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, | 285 | ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, |
@@ -266,7 +289,7 @@ static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg ms | |||
266 | case 0x61: { | 289 | case 0x61: { |
267 | /* write to tuner */ | 290 | /* write to tuner */ |
268 | u8 obuf[msg[0].len + 2]; | 291 | u8 obuf[msg[0].len + 2]; |
269 | obuf[0] = 0xc2; | 292 | obuf[0] = msg[0].addr << 1; |
270 | obuf[1] = msg[0].len; | 293 | obuf[1] = msg[0].len; |
271 | memcpy(obuf + 2, msg[0].buf, msg[0].len); | 294 | memcpy(obuf + 2, msg[0].buf, msg[0].len); |
272 | ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, | 295 | ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, |
@@ -301,78 +324,78 @@ static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], i | |||
301 | { | 324 | { |
302 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | 325 | struct dvb_usb_device *d = i2c_get_adapdata(adap); |
303 | int ret = 0; | 326 | int ret = 0; |
304 | int len, i; | 327 | int len, i, j; |
305 | 328 | ||
306 | if (!d) | 329 | if (!d) |
307 | return -ENODEV; | 330 | return -ENODEV; |
308 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | 331 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) |
309 | return -EAGAIN; | 332 | return -EAGAIN; |
310 | 333 | ||
311 | switch (num) { | 334 | for (j = 0; j < num; j++) { |
312 | case 2: { | 335 | switch (msg[j].addr) { |
313 | /* read */ | ||
314 | /* first write first register number */ | ||
315 | u8 ibuf[msg[1].len + 2], obuf[3]; | ||
316 | obuf[0] = 0xaa; | ||
317 | obuf[1] = msg[0].len; | ||
318 | obuf[2] = msg[0].buf[0]; | ||
319 | ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, | ||
320 | obuf, msg[0].len + 2, DW210X_WRITE_MSG); | ||
321 | /* second read registers */ | ||
322 | ret = dw210x_op_rw(d->udev, 0xc3, 0xab , 0, | ||
323 | ibuf, msg[1].len + 2, DW210X_READ_MSG); | ||
324 | memcpy(msg[1].buf, ibuf + 2, msg[1].len); | ||
325 | |||
326 | break; | ||
327 | } | ||
328 | case 1: | ||
329 | switch (msg[0].addr) { | ||
330 | case 0x55: { | ||
331 | if (msg[0].buf[0] == 0xf7) { | ||
332 | /* firmware */ | ||
333 | /* Write in small blocks */ | ||
334 | u8 obuf[19]; | ||
335 | obuf[0] = 0xaa; | ||
336 | obuf[1] = 0x11; | ||
337 | obuf[2] = 0xf7; | ||
338 | len = msg[0].len - 1; | ||
339 | i = 1; | ||
340 | do { | ||
341 | memcpy(obuf + 3, msg[0].buf + i, (len > 16 ? 16 : len)); | ||
342 | ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, | ||
343 | obuf, (len > 16 ? 16 : len) + 3, DW210X_WRITE_MSG); | ||
344 | i += 16; | ||
345 | len -= 16; | ||
346 | } while (len > 0); | ||
347 | } else { | ||
348 | /* write to register */ | ||
349 | u8 obuf[msg[0].len + 2]; | ||
350 | obuf[0] = 0xaa; | ||
351 | obuf[1] = msg[0].len; | ||
352 | memcpy(obuf + 2, msg[0].buf, msg[0].len); | ||
353 | ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, | ||
354 | obuf, msg[0].len + 2, DW210X_WRITE_MSG); | ||
355 | } | ||
356 | break; | ||
357 | } | ||
358 | case(DW2102_RC_QUERY): { | 336 | case(DW2102_RC_QUERY): { |
359 | u8 ibuf[2]; | 337 | u8 ibuf[2]; |
360 | ret = dw210x_op_rw(d->udev, 0xb8, 0, 0, | 338 | ret = dw210x_op_rw(d->udev, 0xb8, 0, 0, |
361 | ibuf, 2, DW210X_READ_MSG); | 339 | ibuf, 2, DW210X_READ_MSG); |
362 | memcpy(msg[0].buf, ibuf , 2); | 340 | memcpy(msg[j].buf, ibuf , 2); |
363 | break; | 341 | break; |
364 | } | 342 | } |
365 | case(DW2102_VOLTAGE_CTRL): { | 343 | case(DW2102_VOLTAGE_CTRL): { |
366 | u8 obuf[2]; | 344 | u8 obuf[2]; |
367 | obuf[0] = 0x30; | 345 | obuf[0] = 0x30; |
368 | obuf[1] = msg[0].buf[0]; | 346 | obuf[1] = msg[j].buf[0]; |
369 | ret = dw210x_op_rw(d->udev, 0xb2, 0, 0, | 347 | ret = dw210x_op_rw(d->udev, 0xb2, 0, 0, |
370 | obuf, 2, DW210X_WRITE_MSG); | 348 | obuf, 2, DW210X_WRITE_MSG); |
371 | break; | 349 | break; |
372 | } | 350 | } |
351 | /*case 0x55: cx24116 | ||
352 | case 0x6a: stv0903 | ||
353 | case 0x68: ds3000, stv0903 | ||
354 | case 0x60: ts2020, stv6110, stb6100 */ | ||
355 | default: { | ||
356 | if (msg[j].flags == I2C_M_RD) { | ||
357 | /* read registers */ | ||
358 | u8 ibuf[msg[j].len + 2]; | ||
359 | ret = dw210x_op_rw(d->udev, 0xc3, | ||
360 | (msg[j].addr << 1) + 1, 0, | ||
361 | ibuf, msg[j].len + 2, | ||
362 | DW210X_READ_MSG); | ||
363 | memcpy(msg[j].buf, ibuf + 2, msg[j].len); | ||
364 | mdelay(10); | ||
365 | } else if (((msg[j].buf[0] == 0xb0) && | ||
366 | (msg[j].addr == 0x68)) || | ||
367 | ((msg[j].buf[0] == 0xf7) && | ||
368 | (msg[j].addr == 0x55))) { | ||
369 | /* write firmware */ | ||
370 | u8 obuf[19]; | ||
371 | obuf[0] = msg[j].addr << 1; | ||
372 | obuf[1] = (msg[j].len > 15 ? 17 : msg[j].len); | ||
373 | obuf[2] = msg[j].buf[0]; | ||
374 | len = msg[j].len - 1; | ||
375 | i = 1; | ||
376 | do { | ||
377 | memcpy(obuf + 3, msg[j].buf + i, | ||
378 | (len > 16 ? 16 : len)); | ||
379 | ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, | ||
380 | obuf, (len > 16 ? 16 : len) + 3, | ||
381 | DW210X_WRITE_MSG); | ||
382 | i += 16; | ||
383 | len -= 16; | ||
384 | } while (len > 0); | ||
385 | } else { | ||
386 | /* write registers */ | ||
387 | u8 obuf[msg[j].len + 2]; | ||
388 | obuf[0] = msg[j].addr << 1; | ||
389 | obuf[1] = msg[j].len; | ||
390 | memcpy(obuf + 2, msg[j].buf, msg[j].len); | ||
391 | ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, | ||
392 | obuf, msg[j].len + 2, | ||
393 | DW210X_WRITE_MSG); | ||
394 | } | ||
395 | break; | ||
396 | } | ||
373 | } | 397 | } |
374 | 398 | ||
375 | break; | ||
376 | } | 399 | } |
377 | 400 | ||
378 | mutex_unlock(&d->i2c_mutex); | 401 | mutex_unlock(&d->i2c_mutex); |
@@ -442,63 +465,85 @@ static int dw3101_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], | |||
442 | return num; | 465 | return num; |
443 | } | 466 | } |
444 | 467 | ||
445 | static int s630_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], | 468 | static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], |
446 | int num) | 469 | int num) |
447 | { | 470 | { |
448 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | 471 | struct dvb_usb_device *d = i2c_get_adapdata(adap); |
449 | int ret = 0; | 472 | int ret = 0; |
473 | int len, i, j; | ||
450 | 474 | ||
451 | if (!d) | 475 | if (!d) |
452 | return -ENODEV; | 476 | return -ENODEV; |
453 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | 477 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) |
454 | return -EAGAIN; | 478 | return -EAGAIN; |
455 | 479 | ||
456 | switch (num) { | 480 | for (j = 0; j < num; j++) { |
457 | case 2: { /* read */ | 481 | switch (msg[j].addr) { |
458 | u8 ibuf[msg[1].len], obuf[3]; | ||
459 | obuf[0] = msg[1].len; | ||
460 | obuf[1] = (msg[0].addr << 1); | ||
461 | obuf[2] = msg[0].buf[0]; | ||
462 | |||
463 | ret = dw210x_op_rw(d->udev, 0x90, 0, 0, | ||
464 | obuf, 3, DW210X_WRITE_MSG); | ||
465 | msleep(5); | ||
466 | ret = dw210x_op_rw(d->udev, 0x91, 0, 0, | ||
467 | ibuf, msg[1].len, DW210X_READ_MSG); | ||
468 | memcpy(msg[1].buf, ibuf, msg[1].len); | ||
469 | break; | ||
470 | } | ||
471 | case 1: | ||
472 | switch (msg[0].addr) { | ||
473 | case 0x60: | ||
474 | case 0x0e: { | ||
475 | /* write to zl10313, zl10039 register, */ | ||
476 | u8 obuf[msg[0].len + 2]; | ||
477 | obuf[0] = msg[0].len + 1; | ||
478 | obuf[1] = (msg[0].addr << 1); | ||
479 | memcpy(obuf + 2, msg[0].buf, msg[0].len); | ||
480 | ret = dw210x_op_rw(d->udev, 0x80, 0, 0, | ||
481 | obuf, msg[0].len + 2, DW210X_WRITE_MSG); | ||
482 | break; | ||
483 | } | ||
484 | case (DW2102_RC_QUERY): { | 482 | case (DW2102_RC_QUERY): { |
485 | u8 ibuf[4]; | 483 | u8 ibuf[4]; |
486 | ret = dw210x_op_rw(d->udev, 0xb8, 0, 0, | 484 | ret = dw210x_op_rw(d->udev, 0xb8, 0, 0, |
487 | ibuf, 4, DW210X_READ_MSG); | 485 | ibuf, 4, DW210X_READ_MSG); |
488 | msg[0].buf[0] = ibuf[3]; | 486 | memcpy(msg[j].buf, ibuf + 1, 2); |
489 | break; | 487 | break; |
490 | } | 488 | } |
491 | case (DW2102_VOLTAGE_CTRL): { | 489 | case (DW2102_VOLTAGE_CTRL): { |
492 | u8 obuf[2]; | 490 | u8 obuf[2]; |
493 | obuf[0] = 0x03; | 491 | obuf[0] = 3; |
494 | obuf[1] = msg[0].buf[0]; | 492 | obuf[1] = msg[j].buf[0]; |
495 | ret = dw210x_op_rw(d->udev, 0x8a, 0, 0, | 493 | ret = dw210x_op_rw(d->udev, 0x8a, 0, 0, |
496 | obuf, 2, DW210X_WRITE_MSG); | 494 | obuf, 2, DW210X_WRITE_MSG); |
497 | break; | 495 | break; |
498 | } | 496 | } |
497 | /*case 0x55: cx24116 | ||
498 | case 0x6a: stv0903 | ||
499 | case 0x68: ds3000, stv0903 | ||
500 | case 0x60: ts2020, stv6110, stb6100 | ||
501 | case 0xa0: eeprom */ | ||
502 | default: { | ||
503 | if (msg[j].flags == I2C_M_RD) { | ||
504 | /* read registers */ | ||
505 | u8 ibuf[msg[j].len]; | ||
506 | ret = dw210x_op_rw(d->udev, 0x91, 0, 0, | ||
507 | ibuf, msg[j].len, | ||
508 | DW210X_READ_MSG); | ||
509 | memcpy(msg[j].buf, ibuf, msg[j].len); | ||
510 | break; | ||
511 | } else if ((msg[j].buf[0] == 0xb0) && | ||
512 | (msg[j].addr == 0x68)) { | ||
513 | /* write firmware */ | ||
514 | u8 obuf[19]; | ||
515 | obuf[0] = (msg[j].len > 16 ? | ||
516 | 18 : msg[j].len + 1); | ||
517 | obuf[1] = msg[j].addr << 1; | ||
518 | obuf[2] = msg[j].buf[0]; | ||
519 | len = msg[j].len - 1; | ||
520 | i = 1; | ||
521 | do { | ||
522 | memcpy(obuf + 3, msg[j].buf + i, | ||
523 | (len > 16 ? 16 : len)); | ||
524 | ret = dw210x_op_rw(d->udev, 0x80, 0, 0, | ||
525 | obuf, (len > 16 ? 16 : len) + 3, | ||
526 | DW210X_WRITE_MSG); | ||
527 | i += 16; | ||
528 | len -= 16; | ||
529 | } while (len > 0); | ||
530 | } else { | ||
531 | /* write registers */ | ||
532 | u8 obuf[msg[j].len + 2]; | ||
533 | obuf[0] = msg[j].len + 1; | ||
534 | obuf[1] = (msg[j].addr << 1); | ||
535 | memcpy(obuf + 2, msg[j].buf, msg[j].len); | ||
536 | ret = dw210x_op_rw(d->udev, | ||
537 | (num > 1 ? 0x90 : 0x80), 0, 0, | ||
538 | obuf, msg[j].len + 2, | ||
539 | DW210X_WRITE_MSG); | ||
540 | break; | ||
541 | } | ||
542 | break; | ||
543 | } | ||
499 | } | 544 | } |
500 | 545 | ||
501 | break; | 546 | msleep(3); |
502 | } | 547 | } |
503 | 548 | ||
504 | mutex_unlock(&d->i2c_mutex); | 549 | mutex_unlock(&d->i2c_mutex); |
@@ -535,8 +580,8 @@ static struct i2c_algorithm dw3101_i2c_algo = { | |||
535 | .functionality = dw210x_i2c_func, | 580 | .functionality = dw210x_i2c_func, |
536 | }; | 581 | }; |
537 | 582 | ||
538 | static struct i2c_algorithm s630_i2c_algo = { | 583 | static struct i2c_algorithm s6x0_i2c_algo = { |
539 | .master_xfer = s630_i2c_transfer, | 584 | .master_xfer = s6x0_i2c_transfer, |
540 | .functionality = dw210x_i2c_func, | 585 | .functionality = dw210x_i2c_func, |
541 | }; | 586 | }; |
542 | 587 | ||
@@ -564,25 +609,34 @@ static int dw210x_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) | |||
564 | return 0; | 609 | return 0; |
565 | }; | 610 | }; |
566 | 611 | ||
567 | static int s630_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) | 612 | static int s6x0_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) |
568 | { | 613 | { |
569 | int i, ret; | 614 | int i, ret; |
570 | u8 buf[3], eeprom[256], eepromline[16]; | 615 | u8 ibuf[] = { 0 }, obuf[] = { 0 }; |
616 | u8 eeprom[256], eepromline[16]; | ||
617 | struct i2c_msg msg[] = { | ||
618 | { | ||
619 | .addr = 0xa0 >> 1, | ||
620 | .flags = 0, | ||
621 | .buf = obuf, | ||
622 | .len = 1, | ||
623 | }, { | ||
624 | .addr = 0xa0 >> 1, | ||
625 | .flags = I2C_M_RD, | ||
626 | .buf = ibuf, | ||
627 | .len = 1, | ||
628 | } | ||
629 | }; | ||
571 | 630 | ||
572 | for (i = 0; i < 256; i++) { | 631 | for (i = 0; i < 256; i++) { |
573 | buf[0] = 1; | 632 | obuf[0] = i; |
574 | buf[1] = 0xa0; | 633 | ret = s6x0_i2c_transfer(&d->i2c_adap, msg, 2); |
575 | buf[2] = i; | 634 | if (ret != 2) { |
576 | ret = dw210x_op_rw(d->udev, 0x90, 0, 0, | ||
577 | buf, 3, DW210X_WRITE_MSG); | ||
578 | ret = dw210x_op_rw(d->udev, 0x91, 0, 0, | ||
579 | buf, 1, DW210X_READ_MSG); | ||
580 | if (ret < 0) { | ||
581 | err("read eeprom failed."); | 635 | err("read eeprom failed."); |
582 | return -1; | 636 | return -1; |
583 | } else { | 637 | } else { |
584 | eepromline[i % 16] = buf[0]; | 638 | eepromline[i % 16] = ibuf[0]; |
585 | eeprom[i] = buf[0]; | 639 | eeprom[i] = ibuf[0]; |
586 | } | 640 | } |
587 | 641 | ||
588 | if ((i % 16) == 15) { | 642 | if ((i % 16) == 15) { |
@@ -644,19 +698,104 @@ static struct mt312_config zl313_config = { | |||
644 | .demod_address = 0x0e, | 698 | .demod_address = 0x0e, |
645 | }; | 699 | }; |
646 | 700 | ||
701 | static struct ds3000_config dw2104_ds3000_config = { | ||
702 | .demod_address = 0x68, | ||
703 | }; | ||
704 | |||
705 | static struct stv0900_config dw2104a_stv0900_config = { | ||
706 | .demod_address = 0x6a, | ||
707 | .demod_mode = 0, | ||
708 | .xtal = 27000000, | ||
709 | .clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */ | ||
710 | .diseqc_mode = 2,/* 2/3 PWM */ | ||
711 | .tun1_maddress = 0,/* 0x60 */ | ||
712 | .tun1_adc = 0,/* 2 Vpp */ | ||
713 | .path1_mode = 3, | ||
714 | }; | ||
715 | |||
716 | static struct stb6100_config dw2104a_stb6100_config = { | ||
717 | .tuner_address = 0x60, | ||
718 | .refclock = 27000000, | ||
719 | }; | ||
720 | |||
721 | static struct stv0900_config dw2104_stv0900_config = { | ||
722 | .demod_address = 0x68, | ||
723 | .demod_mode = 0, | ||
724 | .xtal = 8000000, | ||
725 | .clkmode = 3, | ||
726 | .diseqc_mode = 2, | ||
727 | .tun1_maddress = 0, | ||
728 | .tun1_adc = 1,/* 1 Vpp */ | ||
729 | .path1_mode = 3, | ||
730 | }; | ||
731 | |||
732 | static struct stv6110_config dw2104_stv6110_config = { | ||
733 | .i2c_address = 0x60, | ||
734 | .mclk = 16000000, | ||
735 | .clk_div = 1, | ||
736 | }; | ||
737 | |||
647 | static int dw2104_frontend_attach(struct dvb_usb_adapter *d) | 738 | static int dw2104_frontend_attach(struct dvb_usb_adapter *d) |
648 | { | 739 | { |
649 | if ((d->fe = dvb_attach(cx24116_attach, &dw2104_config, | 740 | struct dvb_tuner_ops *tuner_ops = NULL; |
650 | &d->dev->i2c_adap)) != NULL) { | 741 | |
742 | if (demod_probe & 4) { | ||
743 | d->fe = dvb_attach(stv0900_attach, &dw2104a_stv0900_config, | ||
744 | &d->dev->i2c_adap, 0); | ||
745 | if (d->fe != NULL) { | ||
746 | if (dvb_attach(stb6100_attach, d->fe, | ||
747 | &dw2104a_stb6100_config, | ||
748 | &d->dev->i2c_adap)) { | ||
749 | tuner_ops = &d->fe->ops.tuner_ops; | ||
750 | tuner_ops->set_frequency = stb6100_set_freq; | ||
751 | tuner_ops->get_frequency = stb6100_get_freq; | ||
752 | tuner_ops->set_bandwidth = stb6100_set_bandw; | ||
753 | tuner_ops->get_bandwidth = stb6100_get_bandw; | ||
754 | d->fe->ops.set_voltage = dw210x_set_voltage; | ||
755 | info("Attached STV0900+STB6100!\n"); | ||
756 | return 0; | ||
757 | } | ||
758 | } | ||
759 | } | ||
760 | |||
761 | if (demod_probe & 2) { | ||
762 | d->fe = dvb_attach(stv0900_attach, &dw2104_stv0900_config, | ||
763 | &d->dev->i2c_adap, 0); | ||
764 | if (d->fe != NULL) { | ||
765 | if (dvb_attach(stv6110_attach, d->fe, | ||
766 | &dw2104_stv6110_config, | ||
767 | &d->dev->i2c_adap)) { | ||
768 | d->fe->ops.set_voltage = dw210x_set_voltage; | ||
769 | info("Attached STV0900+STV6110A!\n"); | ||
770 | return 0; | ||
771 | } | ||
772 | } | ||
773 | } | ||
774 | |||
775 | if (demod_probe & 1) { | ||
776 | d->fe = dvb_attach(cx24116_attach, &dw2104_config, | ||
777 | &d->dev->i2c_adap); | ||
778 | if (d->fe != NULL) { | ||
779 | d->fe->ops.set_voltage = dw210x_set_voltage; | ||
780 | info("Attached cx24116!\n"); | ||
781 | return 0; | ||
782 | } | ||
783 | } | ||
784 | |||
785 | d->fe = dvb_attach(ds3000_attach, &dw2104_ds3000_config, | ||
786 | &d->dev->i2c_adap); | ||
787 | if (d->fe != NULL) { | ||
651 | d->fe->ops.set_voltage = dw210x_set_voltage; | 788 | d->fe->ops.set_voltage = dw210x_set_voltage; |
652 | info("Attached cx24116!\n"); | 789 | info("Attached DS3000!\n"); |
653 | return 0; | 790 | return 0; |
654 | } | 791 | } |
792 | |||
655 | return -EIO; | 793 | return -EIO; |
656 | } | 794 | } |
657 | 795 | ||
658 | static struct dvb_usb_device_properties dw2102_properties; | 796 | static struct dvb_usb_device_properties dw2102_properties; |
659 | static struct dvb_usb_device_properties dw2104_properties; | 797 | static struct dvb_usb_device_properties dw2104_properties; |
798 | static struct dvb_usb_device_properties s6x0_properties; | ||
660 | 799 | ||
661 | static int dw2102_frontend_attach(struct dvb_usb_adapter *d) | 800 | static int dw2102_frontend_attach(struct dvb_usb_adapter *d) |
662 | { | 801 | { |
@@ -670,14 +809,17 @@ static int dw2102_frontend_attach(struct dvb_usb_adapter *d) | |||
670 | return 0; | 809 | return 0; |
671 | } | 810 | } |
672 | } | 811 | } |
812 | |||
673 | if (dw2102_properties.i2c_algo == &dw2102_earda_i2c_algo) { | 813 | if (dw2102_properties.i2c_algo == &dw2102_earda_i2c_algo) { |
674 | /*dw2102_properties.adapter->tuner_attach = dw2102_tuner_attach;*/ | ||
675 | d->fe = dvb_attach(stv0288_attach, &earda_config, | 814 | d->fe = dvb_attach(stv0288_attach, &earda_config, |
676 | &d->dev->i2c_adap); | 815 | &d->dev->i2c_adap); |
677 | if (d->fe != NULL) { | 816 | if (d->fe != NULL) { |
678 | d->fe->ops.set_voltage = dw210x_set_voltage; | 817 | if (dvb_attach(stb6000_attach, d->fe, 0x61, |
679 | info("Attached stv0288!\n"); | 818 | &d->dev->i2c_adap)) { |
680 | return 0; | 819 | d->fe->ops.set_voltage = dw210x_set_voltage; |
820 | info("Attached stv0288!\n"); | ||
821 | return 0; | ||
822 | } | ||
681 | } | 823 | } |
682 | } | 824 | } |
683 | 825 | ||
@@ -705,15 +847,38 @@ static int dw3101_frontend_attach(struct dvb_usb_adapter *d) | |||
705 | return -EIO; | 847 | return -EIO; |
706 | } | 848 | } |
707 | 849 | ||
708 | static int s630_frontend_attach(struct dvb_usb_adapter *d) | 850 | static int s6x0_frontend_attach(struct dvb_usb_adapter *d) |
709 | { | 851 | { |
710 | d->fe = dvb_attach(mt312_attach, &zl313_config, | 852 | d->fe = dvb_attach(mt312_attach, &zl313_config, |
711 | &d->dev->i2c_adap); | 853 | &d->dev->i2c_adap); |
854 | if (d->fe != NULL) { | ||
855 | if (dvb_attach(zl10039_attach, d->fe, 0x60, | ||
856 | &d->dev->i2c_adap)) { | ||
857 | d->fe->ops.set_voltage = dw210x_set_voltage; | ||
858 | info("Attached zl100313+zl10039!\n"); | ||
859 | return 0; | ||
860 | } | ||
861 | } | ||
862 | |||
863 | d->fe = dvb_attach(stv0288_attach, &earda_config, | ||
864 | &d->dev->i2c_adap); | ||
865 | if (d->fe != NULL) { | ||
866 | if (dvb_attach(stb6000_attach, d->fe, 0x61, | ||
867 | &d->dev->i2c_adap)) { | ||
868 | d->fe->ops.set_voltage = dw210x_set_voltage; | ||
869 | info("Attached stv0288+stb6000!\n"); | ||
870 | return 0; | ||
871 | } | ||
872 | } | ||
873 | |||
874 | d->fe = dvb_attach(ds3000_attach, &dw2104_ds3000_config, | ||
875 | &d->dev->i2c_adap); | ||
712 | if (d->fe != NULL) { | 876 | if (d->fe != NULL) { |
713 | d->fe->ops.set_voltage = dw210x_set_voltage; | 877 | d->fe->ops.set_voltage = dw210x_set_voltage; |
714 | info("Attached zl10313!\n"); | 878 | info("Attached ds3000+ds2020!\n"); |
715 | return 0; | 879 | return 0; |
716 | } | 880 | } |
881 | |||
717 | return -EIO; | 882 | return -EIO; |
718 | } | 883 | } |
719 | 884 | ||
@@ -724,14 +889,6 @@ static int dw2102_tuner_attach(struct dvb_usb_adapter *adap) | |||
724 | return 0; | 889 | return 0; |
725 | } | 890 | } |
726 | 891 | ||
727 | static int dw2102_earda_tuner_attach(struct dvb_usb_adapter *adap) | ||
728 | { | ||
729 | dvb_attach(stb6000_attach, adap->fe, 0x61, | ||
730 | &adap->dev->i2c_adap); | ||
731 | |||
732 | return 0; | ||
733 | } | ||
734 | |||
735 | static int dw3101_tuner_attach(struct dvb_usb_adapter *adap) | 892 | static int dw3101_tuner_attach(struct dvb_usb_adapter *adap) |
736 | { | 893 | { |
737 | dvb_attach(dvb_pll_attach, adap->fe, 0x60, | 894 | dvb_attach(dvb_pll_attach, adap->fe, 0x60, |
@@ -740,14 +897,6 @@ static int dw3101_tuner_attach(struct dvb_usb_adapter *adap) | |||
740 | return 0; | 897 | return 0; |
741 | } | 898 | } |
742 | 899 | ||
743 | static int s630_zl10039_tuner_attach(struct dvb_usb_adapter *adap) | ||
744 | { | ||
745 | dvb_attach(zl10039_attach, adap->fe, 0x60, | ||
746 | &adap->dev->i2c_adap); | ||
747 | |||
748 | return 0; | ||
749 | } | ||
750 | |||
751 | static struct dvb_usb_rc_key dw210x_rc_keys[] = { | 900 | static struct dvb_usb_rc_key dw210x_rc_keys[] = { |
752 | { 0xf80a, KEY_Q }, /*power*/ | 901 | { 0xf80a, KEY_Q }, /*power*/ |
753 | { 0xf80c, KEY_M }, /*mute*/ | 902 | { 0xf80c, KEY_M }, /*mute*/ |
@@ -922,6 +1071,8 @@ static struct usb_device_id dw2102_table[] = { | |||
922 | {USB_DEVICE(USB_VID_TERRATEC, USB_PID_CINERGY_S)}, | 1071 | {USB_DEVICE(USB_VID_TERRATEC, USB_PID_CINERGY_S)}, |
923 | {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW3101)}, | 1072 | {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW3101)}, |
924 | {USB_DEVICE(0x9022, USB_PID_TEVII_S630)}, | 1073 | {USB_DEVICE(0x9022, USB_PID_TEVII_S630)}, |
1074 | {USB_DEVICE(0x3011, USB_PID_PROF_1100)}, | ||
1075 | {USB_DEVICE(0x9022, USB_PID_TEVII_S660)}, | ||
925 | { } | 1076 | { } |
926 | }; | 1077 | }; |
927 | 1078 | ||
@@ -935,15 +1086,13 @@ static int dw2102_load_firmware(struct usb_device *dev, | |||
935 | u8 reset; | 1086 | u8 reset; |
936 | u8 reset16[] = {0, 0, 0, 0, 0, 0, 0}; | 1087 | u8 reset16[] = {0, 0, 0, 0, 0, 0, 0}; |
937 | const struct firmware *fw; | 1088 | const struct firmware *fw; |
938 | const char *filename = "dvb-usb-dw2101.fw"; | 1089 | const char *fw_2101 = "dvb-usb-dw2101.fw"; |
939 | 1090 | ||
940 | switch (dev->descriptor.idProduct) { | 1091 | switch (dev->descriptor.idProduct) { |
941 | case 0x2101: | 1092 | case 0x2101: |
942 | ret = request_firmware(&fw, filename, &dev->dev); | 1093 | ret = request_firmware(&fw, fw_2101, &dev->dev); |
943 | if (ret != 0) { | 1094 | if (ret != 0) { |
944 | err("did not find the firmware file. (%s) " | 1095 | err(err_str, fw_2101); |
945 | "Please see linux/Documentation/dvb/ for more details " | ||
946 | "on firmware-problems.", filename); | ||
947 | return ret; | 1096 | return ret; |
948 | } | 1097 | } |
949 | break; | 1098 | break; |
@@ -983,6 +1132,11 @@ static int dw2102_load_firmware(struct usb_device *dev, | |||
983 | } | 1132 | } |
984 | /* init registers */ | 1133 | /* init registers */ |
985 | switch (dev->descriptor.idProduct) { | 1134 | switch (dev->descriptor.idProduct) { |
1135 | case USB_PID_PROF_1100: | ||
1136 | s6x0_properties.rc_key_map = tbs_rc_keys; | ||
1137 | s6x0_properties.rc_key_map_size = | ||
1138 | ARRAY_SIZE(tbs_rc_keys); | ||
1139 | break; | ||
986 | case USB_PID_TEVII_S650: | 1140 | case USB_PID_TEVII_S650: |
987 | dw2104_properties.rc_key_map = tevii_rc_keys; | 1141 | dw2104_properties.rc_key_map = tevii_rc_keys; |
988 | dw2104_properties.rc_key_map_size = | 1142 | dw2104_properties.rc_key_map_size = |
@@ -1021,7 +1175,6 @@ static int dw2102_load_firmware(struct usb_device *dev, | |||
1021 | DW210X_READ_MSG); | 1175 | DW210X_READ_MSG); |
1022 | if (reset16[2] == 0x11) { | 1176 | if (reset16[2] == 0x11) { |
1023 | dw2102_properties.i2c_algo = &dw2102_earda_i2c_algo; | 1177 | dw2102_properties.i2c_algo = &dw2102_earda_i2c_algo; |
1024 | dw2102_properties.adapter->tuner_attach = &dw2102_earda_tuner_attach; | ||
1025 | break; | 1178 | break; |
1026 | } | 1179 | } |
1027 | } | 1180 | } |
@@ -1184,13 +1337,13 @@ static struct dvb_usb_device_properties dw3101_properties = { | |||
1184 | } | 1337 | } |
1185 | }; | 1338 | }; |
1186 | 1339 | ||
1187 | static struct dvb_usb_device_properties s630_properties = { | 1340 | static struct dvb_usb_device_properties s6x0_properties = { |
1188 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | 1341 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, |
1189 | .usb_ctrl = DEVICE_SPECIFIC, | 1342 | .usb_ctrl = DEVICE_SPECIFIC, |
1190 | .firmware = "dvb-usb-s630.fw", | 1343 | .firmware = "dvb-usb-s630.fw", |
1191 | .no_reconnect = 1, | 1344 | .no_reconnect = 1, |
1192 | 1345 | ||
1193 | .i2c_algo = &s630_i2c_algo, | 1346 | .i2c_algo = &s6x0_i2c_algo, |
1194 | .rc_key_map = tevii_rc_keys, | 1347 | .rc_key_map = tevii_rc_keys, |
1195 | .rc_key_map_size = ARRAY_SIZE(tevii_rc_keys), | 1348 | .rc_key_map_size = ARRAY_SIZE(tevii_rc_keys), |
1196 | .rc_interval = 150, | 1349 | .rc_interval = 150, |
@@ -1199,12 +1352,12 @@ static struct dvb_usb_device_properties s630_properties = { | |||
1199 | .generic_bulk_ctrl_endpoint = 0x81, | 1352 | .generic_bulk_ctrl_endpoint = 0x81, |
1200 | .num_adapters = 1, | 1353 | .num_adapters = 1, |
1201 | .download_firmware = dw2102_load_firmware, | 1354 | .download_firmware = dw2102_load_firmware, |
1202 | .read_mac_address = s630_read_mac_address, | 1355 | .read_mac_address = s6x0_read_mac_address, |
1203 | .adapter = { | 1356 | .adapter = { |
1204 | { | 1357 | { |
1205 | .frontend_attach = s630_frontend_attach, | 1358 | .frontend_attach = s6x0_frontend_attach, |
1206 | .streaming_ctrl = NULL, | 1359 | .streaming_ctrl = NULL, |
1207 | .tuner_attach = s630_zl10039_tuner_attach, | 1360 | .tuner_attach = NULL, |
1208 | .stream = { | 1361 | .stream = { |
1209 | .type = USB_BULK, | 1362 | .type = USB_BULK, |
1210 | .count = 8, | 1363 | .count = 8, |
@@ -1217,12 +1370,20 @@ static struct dvb_usb_device_properties s630_properties = { | |||
1217 | }, | 1370 | }, |
1218 | } | 1371 | } |
1219 | }, | 1372 | }, |
1220 | .num_device_descs = 1, | 1373 | .num_device_descs = 3, |
1221 | .devices = { | 1374 | .devices = { |
1222 | {"TeVii S630 USB", | 1375 | {"TeVii S630 USB", |
1223 | {&dw2102_table[6], NULL}, | 1376 | {&dw2102_table[6], NULL}, |
1224 | {NULL}, | 1377 | {NULL}, |
1225 | }, | 1378 | }, |
1379 | {"Prof 1100 USB ", | ||
1380 | {&dw2102_table[7], NULL}, | ||
1381 | {NULL}, | ||
1382 | }, | ||
1383 | {"TeVii S660 USB", | ||
1384 | {&dw2102_table[8], NULL}, | ||
1385 | {NULL}, | ||
1386 | }, | ||
1226 | } | 1387 | } |
1227 | }; | 1388 | }; |
1228 | 1389 | ||
@@ -1235,10 +1396,10 @@ static int dw2102_probe(struct usb_interface *intf, | |||
1235 | THIS_MODULE, NULL, adapter_nr) || | 1396 | THIS_MODULE, NULL, adapter_nr) || |
1236 | 0 == dvb_usb_device_init(intf, &dw3101_properties, | 1397 | 0 == dvb_usb_device_init(intf, &dw3101_properties, |
1237 | THIS_MODULE, NULL, adapter_nr) || | 1398 | THIS_MODULE, NULL, adapter_nr) || |
1238 | 0 == dvb_usb_device_init(intf, &s630_properties, | 1399 | 0 == dvb_usb_device_init(intf, &s6x0_properties, |
1239 | THIS_MODULE, NULL, adapter_nr)) { | 1400 | THIS_MODULE, NULL, adapter_nr)) |
1240 | return 0; | 1401 | return 0; |
1241 | } | 1402 | |
1242 | return -ENODEV; | 1403 | return -ENODEV; |
1243 | } | 1404 | } |
1244 | 1405 | ||
@@ -1269,6 +1430,7 @@ module_exit(dw2102_module_exit); | |||
1269 | MODULE_AUTHOR("Igor M. Liplianin (c) liplianin@me.by"); | 1430 | MODULE_AUTHOR("Igor M. Liplianin (c) liplianin@me.by"); |
1270 | MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104," | 1431 | MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104," |
1271 | " DVB-C 3101 USB2.0," | 1432 | " DVB-C 3101 USB2.0," |
1272 | " TeVii S600, S630, S650 USB2.0 devices"); | 1433 | " TeVii S600, S630, S650, S660 USB2.0," |
1434 | " Prof 1100 USB2.0 devices"); | ||
1273 | MODULE_VERSION("0.1"); | 1435 | MODULE_VERSION("0.1"); |
1274 | MODULE_LICENSE("GPL"); | 1436 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/media/dvb/dvb-usb/friio-fe.c b/drivers/media/dvb/dvb-usb/friio-fe.c index 9cbbe42ca44b..ebb7b9fd115b 100644 --- a/drivers/media/dvb/dvb-usb/friio-fe.c +++ b/drivers/media/dvb/dvb-usb/friio-fe.c | |||
@@ -134,11 +134,13 @@ static int jdvbt90502_pll_set_freq(struct jdvbt90502_state *state, u32 freq) | |||
134 | deb_fe("%s: freq=%d, step=%d\n", __func__, freq, | 134 | deb_fe("%s: freq=%d, step=%d\n", __func__, freq, |
135 | state->frontend.ops.info.frequency_stepsize); | 135 | state->frontend.ops.info.frequency_stepsize); |
136 | /* freq -> oscilator frequency conversion. */ | 136 | /* freq -> oscilator frequency conversion. */ |
137 | /* freq: 473,000,000 + n*6,000,000 (no 1/7MHz shift to center freq) */ | 137 | /* freq: 473,000,000 + n*6,000,000 [+ 142857 (center freq. shift)] */ |
138 | /* add 400[1/7 MHZ] = 57.142857MHz. 57MHz for the IF, */ | ||
139 | /* 1/7MHz for center freq shift */ | ||
140 | f = freq / state->frontend.ops.info.frequency_stepsize; | 138 | f = freq / state->frontend.ops.info.frequency_stepsize; |
141 | f += 400; | 139 | /* add 399[1/7 MHZ] = 57MHz for the IF */ |
140 | f += 399; | ||
141 | /* add center frequency shift if necessary */ | ||
142 | if (f % 7 == 0) | ||
143 | f++; | ||
142 | pll_freq_cmd[DEMOD_REDIRECT_REG] = JDVBT90502_2ND_I2C_REG; /* 0xFE */ | 144 | pll_freq_cmd[DEMOD_REDIRECT_REG] = JDVBT90502_2ND_I2C_REG; /* 0xFE */ |
143 | pll_freq_cmd[ADDRESS_BYTE] = state->config.pll_address << 1; | 145 | pll_freq_cmd[ADDRESS_BYTE] = state->config.pll_address << 1; |
144 | pll_freq_cmd[DIVIDER_BYTE1] = (f >> 8) & 0x7F; | 146 | pll_freq_cmd[DIVIDER_BYTE1] = (f >> 8) & 0x7F; |
diff --git a/drivers/media/dvb/dvb-usb/gp8psk-fe.c b/drivers/media/dvb/dvb-usb/gp8psk-fe.c index 20eadf9318e0..7a7f1b2b681c 100644 --- a/drivers/media/dvb/dvb-usb/gp8psk-fe.c +++ b/drivers/media/dvb/dvb-usb/gp8psk-fe.c | |||
@@ -146,8 +146,8 @@ static int gp8psk_fe_set_frontend(struct dvb_frontend* fe, | |||
146 | 146 | ||
147 | switch (c->delivery_system) { | 147 | switch (c->delivery_system) { |
148 | case SYS_DVBS: | 148 | case SYS_DVBS: |
149 | /* Only QPSK is supported for DVB-S */ | 149 | /* Allow QPSK and 8PSK (even for DVB-S) */ |
150 | if (c->modulation != QPSK) { | 150 | if (c->modulation != QPSK && c->modulation != PSK_8) { |
151 | deb_fe("%s: unsupported modulation selected (%d)\n", | 151 | deb_fe("%s: unsupported modulation selected (%d)\n", |
152 | __func__, c->modulation); | 152 | __func__, c->modulation); |
153 | return -EOPNOTSUPP; | 153 | return -EOPNOTSUPP; |
diff --git a/drivers/media/dvb/firewire/firedtv-fw.c b/drivers/media/dvb/firewire/firedtv-fw.c index fe44789ab037..6223bf01efe9 100644 --- a/drivers/media/dvb/firewire/firedtv-fw.c +++ b/drivers/media/dvb/firewire/firedtv-fw.c | |||
@@ -202,14 +202,8 @@ static void handle_fcp(struct fw_card *card, struct fw_request *request, | |||
202 | unsigned long flags; | 202 | unsigned long flags; |
203 | int su; | 203 | int su; |
204 | 204 | ||
205 | if ((tcode != TCODE_WRITE_QUADLET_REQUEST && | 205 | if (length < 2 || (((u8 *)payload)[0] & 0xf0) != 0) |
206 | tcode != TCODE_WRITE_BLOCK_REQUEST) || | ||
207 | offset != CSR_REGISTER_BASE + CSR_FCP_RESPONSE || | ||
208 | length == 0 || | ||
209 | (((u8 *)payload)[0] & 0xf0) != 0) { | ||
210 | fw_send_response(card, request, RCODE_TYPE_ERROR); | ||
211 | return; | 206 | return; |
212 | } | ||
213 | 207 | ||
214 | su = ((u8 *)payload)[1] & 0x7; | 208 | su = ((u8 *)payload)[1] & 0x7; |
215 | 209 | ||
@@ -230,10 +224,8 @@ static void handle_fcp(struct fw_card *card, struct fw_request *request, | |||
230 | } | 224 | } |
231 | spin_unlock_irqrestore(&node_list_lock, flags); | 225 | spin_unlock_irqrestore(&node_list_lock, flags); |
232 | 226 | ||
233 | if (fdtv) { | 227 | if (fdtv) |
234 | avc_recv(fdtv, payload, length); | 228 | avc_recv(fdtv, payload, length); |
235 | fw_send_response(card, request, RCODE_COMPLETE); | ||
236 | } | ||
237 | } | 229 | } |
238 | 230 | ||
239 | static struct fw_address_handler fcp_handler = { | 231 | static struct fw_address_handler fcp_handler = { |
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 58aac018f109..cd7f9b7cbffa 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig | |||
@@ -208,6 +208,14 @@ config DVB_DS3000 | |||
208 | help | 208 | help |
209 | A DVB-S/S2 tuner module. Say Y when you want to support this frontend. | 209 | A DVB-S/S2 tuner module. Say Y when you want to support this frontend. |
210 | 210 | ||
211 | config DVB_MB86A16 | ||
212 | tristate "Fujitsu MB86A16 based" | ||
213 | depends on DVB_CORE && I2C | ||
214 | default m if DVB_FE_CUSTOMISE | ||
215 | help | ||
216 | A DVB-S/DSS Direct Conversion reveiver. | ||
217 | Say Y when you want to support this frontend. | ||
218 | |||
211 | comment "DVB-T (terrestrial) frontends" | 219 | comment "DVB-T (terrestrial) frontends" |
212 | depends on DVB_CORE | 220 | depends on DVB_CORE |
213 | 221 | ||
@@ -526,6 +534,15 @@ config DVB_TUNER_DIB0070 | |||
526 | This device is only used inside a SiP called together with a | 534 | This device is only used inside a SiP called together with a |
527 | demodulator for now. | 535 | demodulator for now. |
528 | 536 | ||
537 | config DVB_TUNER_DIB0090 | ||
538 | tristate "DiBcom DiB0090 silicon base-band tuner" | ||
539 | depends on I2C | ||
540 | default m if DVB_FE_CUSTOMISE | ||
541 | help | ||
542 | A driver for the silicon baseband tuner DiB0090 from DiBcom. | ||
543 | This device is only used inside a SiP called together with a | ||
544 | demodulator for now. | ||
545 | |||
529 | comment "SEC control devices for DVB-S" | 546 | comment "SEC control devices for DVB-S" |
530 | depends on DVB_CORE | 547 | depends on DVB_CORE |
531 | 548 | ||
@@ -578,6 +595,17 @@ config DVB_ATBM8830 | |||
578 | help | 595 | help |
579 | A DMB-TH tuner module. Say Y when you want to support this frontend. | 596 | A DMB-TH tuner module. Say Y when you want to support this frontend. |
580 | 597 | ||
598 | config DVB_TDA665x | ||
599 | tristate "TDA665x tuner" | ||
600 | depends on DVB_CORE && I2C | ||
601 | default m if DVB_FE_CUSTOMISE | ||
602 | help | ||
603 | Support for tuner modules based on Philips TDA6650/TDA6651 chips. | ||
604 | Say Y when you want to support this chip. | ||
605 | |||
606 | Currently supported tuners: | ||
607 | * Panasonic ENV57H12D5 (ET-50DT) | ||
608 | |||
581 | comment "Tools to develop new frontends" | 609 | comment "Tools to develop new frontends" |
582 | 610 | ||
583 | config DVB_DUMMY_FE | 611 | config DVB_DUMMY_FE |
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 823482535d11..874e8ada4d1d 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile | |||
@@ -55,6 +55,7 @@ obj-$(CONFIG_DVB_TDA10086) += tda10086.o | |||
55 | obj-$(CONFIG_DVB_TDA826X) += tda826x.o | 55 | obj-$(CONFIG_DVB_TDA826X) += tda826x.o |
56 | obj-$(CONFIG_DVB_TDA8261) += tda8261.o | 56 | obj-$(CONFIG_DVB_TDA8261) += tda8261.o |
57 | obj-$(CONFIG_DVB_TUNER_DIB0070) += dib0070.o | 57 | obj-$(CONFIG_DVB_TUNER_DIB0070) += dib0070.o |
58 | obj-$(CONFIG_DVB_TUNER_DIB0090) += dib0090.o | ||
58 | obj-$(CONFIG_DVB_TUA6100) += tua6100.o | 59 | obj-$(CONFIG_DVB_TUA6100) += tua6100.o |
59 | obj-$(CONFIG_DVB_S5H1409) += s5h1409.o | 60 | obj-$(CONFIG_DVB_S5H1409) += s5h1409.o |
60 | obj-$(CONFIG_DVB_TUNER_ITD1000) += itd1000.o | 61 | obj-$(CONFIG_DVB_TUNER_ITD1000) += itd1000.o |
@@ -63,6 +64,7 @@ obj-$(CONFIG_DVB_TDA10048) += tda10048.o | |||
63 | obj-$(CONFIG_DVB_TUNER_CX24113) += cx24113.o | 64 | obj-$(CONFIG_DVB_TUNER_CX24113) += cx24113.o |
64 | obj-$(CONFIG_DVB_S5H1411) += s5h1411.o | 65 | obj-$(CONFIG_DVB_S5H1411) += s5h1411.o |
65 | obj-$(CONFIG_DVB_LGS8GL5) += lgs8gl5.o | 66 | obj-$(CONFIG_DVB_LGS8GL5) += lgs8gl5.o |
67 | obj-$(CONFIG_DVB_TDA665x) += tda665x.o | ||
66 | obj-$(CONFIG_DVB_LGS8GXX) += lgs8gxx.o | 68 | obj-$(CONFIG_DVB_LGS8GXX) += lgs8gxx.o |
67 | obj-$(CONFIG_DVB_ATBM8830) += atbm8830.o | 69 | obj-$(CONFIG_DVB_ATBM8830) += atbm8830.o |
68 | obj-$(CONFIG_DVB_DUMMY_FE) += dvb_dummy_fe.o | 70 | obj-$(CONFIG_DVB_DUMMY_FE) += dvb_dummy_fe.o |
@@ -79,3 +81,4 @@ obj-$(CONFIG_DVB_STV6110x) += stv6110x.o | |||
79 | obj-$(CONFIG_DVB_ISL6423) += isl6423.o | 81 | obj-$(CONFIG_DVB_ISL6423) += isl6423.o |
80 | obj-$(CONFIG_DVB_EC100) += ec100.o | 82 | obj-$(CONFIG_DVB_EC100) += ec100.o |
81 | obj-$(CONFIG_DVB_DS3000) += ds3000.o | 83 | obj-$(CONFIG_DVB_DS3000) += ds3000.o |
84 | obj-$(CONFIG_DVB_MB86A16) += mb86a16.o | ||
diff --git a/drivers/media/dvb/frontends/au8522_decoder.c b/drivers/media/dvb/frontends/au8522_decoder.c index 2dc2723b724a..24268ef2753d 100644 --- a/drivers/media/dvb/frontends/au8522_decoder.c +++ b/drivers/media/dvb/frontends/au8522_decoder.c | |||
@@ -62,7 +62,7 @@ struct au8522_register_config { | |||
62 | The values are as follows from left to right | 62 | The values are as follows from left to right |
63 | 0="ATV RF" 1="ATV RF13" 2="CVBS" 3="S-Video" 4="PAL" 5=CVBS13" 6="SVideo13" | 63 | 0="ATV RF" 1="ATV RF13" 2="CVBS" 3="S-Video" 4="PAL" 5=CVBS13" 6="SVideo13" |
64 | */ | 64 | */ |
65 | struct au8522_register_config filter_coef[] = { | 65 | static const struct au8522_register_config filter_coef[] = { |
66 | {AU8522_FILTER_COEF_R410, {0x25, 0x00, 0x25, 0x25, 0x00, 0x00, 0x00} }, | 66 | {AU8522_FILTER_COEF_R410, {0x25, 0x00, 0x25, 0x25, 0x00, 0x00, 0x00} }, |
67 | {AU8522_FILTER_COEF_R411, {0x20, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00} }, | 67 | {AU8522_FILTER_COEF_R411, {0x20, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00} }, |
68 | {AU8522_FILTER_COEF_R412, {0x03, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00} }, | 68 | {AU8522_FILTER_COEF_R412, {0x03, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00} }, |
@@ -104,7 +104,7 @@ struct au8522_register_config filter_coef[] = { | |||
104 | 0="SIF" 1="ATVRF/ATVRF13" | 104 | 0="SIF" 1="ATVRF/ATVRF13" |
105 | Note: the "ATVRF/ATVRF13" mode has never been tested | 105 | Note: the "ATVRF/ATVRF13" mode has never been tested |
106 | */ | 106 | */ |
107 | struct au8522_register_config lpfilter_coef[] = { | 107 | static const struct au8522_register_config lpfilter_coef[] = { |
108 | {0x060b, {0x21, 0x0b} }, | 108 | {0x060b, {0x21, 0x0b} }, |
109 | {0x060c, {0xad, 0xad} }, | 109 | {0x060c, {0xad, 0xad} }, |
110 | {0x060d, {0x70, 0xf0} }, | 110 | {0x060d, {0x70, 0xf0} }, |
diff --git a/drivers/media/dvb/frontends/dib0070.c b/drivers/media/dvb/frontends/dib0070.c index 2be17b93e0bd..0d12763603b4 100644 --- a/drivers/media/dvb/frontends/dib0070.c +++ b/drivers/media/dvb/frontends/dib0070.c | |||
@@ -49,21 +49,6 @@ MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); | |||
49 | #define DIB0070_P1G 0x03 | 49 | #define DIB0070_P1G 0x03 |
50 | #define DIB0070S_P1A 0x02 | 50 | #define DIB0070S_P1A 0x02 |
51 | 51 | ||
52 | enum frontend_tune_state { | ||
53 | CT_TUNER_START = 10, | ||
54 | CT_TUNER_STEP_0, | ||
55 | CT_TUNER_STEP_1, | ||
56 | CT_TUNER_STEP_2, | ||
57 | CT_TUNER_STEP_3, | ||
58 | CT_TUNER_STEP_4, | ||
59 | CT_TUNER_STEP_5, | ||
60 | CT_TUNER_STEP_6, | ||
61 | CT_TUNER_STEP_7, | ||
62 | CT_TUNER_STOP, | ||
63 | }; | ||
64 | |||
65 | #define FE_CALLBACK_TIME_NEVER 0xffffffff | ||
66 | |||
67 | struct dib0070_state { | 52 | struct dib0070_state { |
68 | struct i2c_adapter *i2c; | 53 | struct i2c_adapter *i2c; |
69 | struct dvb_frontend *fe; | 54 | struct dvb_frontend *fe; |
@@ -71,10 +56,10 @@ struct dib0070_state { | |||
71 | u16 wbd_ff_offset; | 56 | u16 wbd_ff_offset; |
72 | u8 revision; | 57 | u8 revision; |
73 | 58 | ||
74 | enum frontend_tune_state tune_state; | 59 | enum frontend_tune_state tune_state; |
75 | u32 current_rf; | 60 | u32 current_rf; |
76 | 61 | ||
77 | /* for the captrim binary search */ | 62 | /* for the captrim binary search */ |
78 | s8 step; | 63 | s8 step; |
79 | u16 adc_diff; | 64 | u16 adc_diff; |
80 | 65 | ||
@@ -85,7 +70,7 @@ struct dib0070_state { | |||
85 | const struct dib0070_tuning *current_tune_table_index; | 70 | const struct dib0070_tuning *current_tune_table_index; |
86 | const struct dib0070_lna_match *lna_match; | 71 | const struct dib0070_lna_match *lna_match; |
87 | 72 | ||
88 | u8 wbd_gain_current; | 73 | u8 wbd_gain_current; |
89 | u16 wbd_offset_3_3[2]; | 74 | u16 wbd_offset_3_3[2]; |
90 | }; | 75 | }; |
91 | 76 | ||
@@ -93,8 +78,8 @@ static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg) | |||
93 | { | 78 | { |
94 | u8 b[2]; | 79 | u8 b[2]; |
95 | struct i2c_msg msg[2] = { | 80 | struct i2c_msg msg[2] = { |
96 | {.addr = state->cfg->i2c_address,.flags = 0,.buf = ®,.len = 1}, | 81 | { .addr = state->cfg->i2c_address, .flags = 0, .buf = ®, .len = 1 }, |
97 | {.addr = state->cfg->i2c_address,.flags = I2C_M_RD,.buf = b,.len = 2}, | 82 | { .addr = state->cfg->i2c_address, .flags = I2C_M_RD, .buf = b, .len = 2 }, |
98 | }; | 83 | }; |
99 | if (i2c_transfer(state->i2c, msg, 2) != 2) { | 84 | if (i2c_transfer(state->i2c, msg, 2) != 2) { |
100 | printk(KERN_WARNING "DiB0070 I2C read failed\n"); | 85 | printk(KERN_WARNING "DiB0070 I2C read failed\n"); |
@@ -106,7 +91,7 @@ static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg) | |||
106 | static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val) | 91 | static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val) |
107 | { | 92 | { |
108 | u8 b[3] = { reg, val >> 8, val & 0xff }; | 93 | u8 b[3] = { reg, val >> 8, val & 0xff }; |
109 | struct i2c_msg msg = {.addr = state->cfg->i2c_address,.flags = 0,.buf = b,.len = 3 }; | 94 | struct i2c_msg msg = { .addr = state->cfg->i2c_address, .flags = 0, .buf = b, .len = 3 }; |
110 | if (i2c_transfer(state->i2c, &msg, 1) != 1) { | 95 | if (i2c_transfer(state->i2c, &msg, 1) != 1) { |
111 | printk(KERN_WARNING "DiB0070 I2C write failed\n"); | 96 | printk(KERN_WARNING "DiB0070 I2C write failed\n"); |
112 | return -EREMOTEIO; | 97 | return -EREMOTEIO; |
@@ -124,30 +109,30 @@ static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val) | |||
124 | 109 | ||
125 | static int dib0070_set_bandwidth(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch) | 110 | static int dib0070_set_bandwidth(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch) |
126 | { | 111 | { |
127 | struct dib0070_state *state = fe->tuner_priv; | 112 | struct dib0070_state *state = fe->tuner_priv; |
128 | u16 tmp = dib0070_read_reg(state, 0x02) & 0x3fff; | 113 | u16 tmp = dib0070_read_reg(state, 0x02) & 0x3fff; |
129 | 114 | ||
130 | if (state->fe->dtv_property_cache.bandwidth_hz / 1000 > 7000) | 115 | if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 7000) |
131 | tmp |= (0 << 14); | 116 | tmp |= (0 << 14); |
132 | else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 > 6000) | 117 | else if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 6000) |
133 | tmp |= (1 << 14); | 118 | tmp |= (1 << 14); |
134 | else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 > 5000) | 119 | else if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 5000) |
135 | tmp |= (2 << 14); | 120 | tmp |= (2 << 14); |
136 | else | 121 | else |
137 | tmp |= (3 << 14); | 122 | tmp |= (3 << 14); |
138 | 123 | ||
139 | dib0070_write_reg(state, 0x02, tmp); | 124 | dib0070_write_reg(state, 0x02, tmp); |
140 | 125 | ||
141 | /* sharpen the BB filter in ISDB-T to have higher immunity to adjacent channels */ | 126 | /* sharpen the BB filter in ISDB-T to have higher immunity to adjacent channels */ |
142 | if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) { | 127 | if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) { |
143 | u16 value = dib0070_read_reg(state, 0x17); | 128 | u16 value = dib0070_read_reg(state, 0x17); |
144 | 129 | ||
145 | dib0070_write_reg(state, 0x17, value & 0xfffc); | 130 | dib0070_write_reg(state, 0x17, value & 0xfffc); |
146 | tmp = dib0070_read_reg(state, 0x01) & 0x01ff; | 131 | tmp = dib0070_read_reg(state, 0x01) & 0x01ff; |
147 | dib0070_write_reg(state, 0x01, tmp | (60 << 9)); | 132 | dib0070_write_reg(state, 0x01, tmp | (60 << 9)); |
148 | 133 | ||
149 | dib0070_write_reg(state, 0x17, value); | 134 | dib0070_write_reg(state, 0x17, value); |
150 | } | 135 | } |
151 | return 0; | 136 | return 0; |
152 | } | 137 | } |
153 | 138 | ||
@@ -160,14 +145,14 @@ static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state | |||
160 | if (*tune_state == CT_TUNER_STEP_0) { | 145 | if (*tune_state == CT_TUNER_STEP_0) { |
161 | 146 | ||
162 | dib0070_write_reg(state, 0x0f, 0xed10); | 147 | dib0070_write_reg(state, 0x0f, 0xed10); |
163 | dib0070_write_reg(state, 0x17, 0x0034); | 148 | dib0070_write_reg(state, 0x17, 0x0034); |
164 | 149 | ||
165 | dib0070_write_reg(state, 0x18, 0x0032); | 150 | dib0070_write_reg(state, 0x18, 0x0032); |
166 | state->step = state->captrim = state->fcaptrim = 64; | 151 | state->step = state->captrim = state->fcaptrim = 64; |
167 | state->adc_diff = 3000; | 152 | state->adc_diff = 3000; |
168 | ret = 20; | 153 | ret = 20; |
169 | 154 | ||
170 | *tune_state = CT_TUNER_STEP_1; | 155 | *tune_state = CT_TUNER_STEP_1; |
171 | } else if (*tune_state == CT_TUNER_STEP_1) { | 156 | } else if (*tune_state == CT_TUNER_STEP_1) { |
172 | state->step /= 2; | 157 | state->step /= 2; |
173 | dib0070_write_reg(state, 0x14, state->lo4 | state->captrim); | 158 | dib0070_write_reg(state, 0x14, state->lo4 | state->captrim); |
@@ -178,7 +163,7 @@ static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state | |||
178 | 163 | ||
179 | adc = dib0070_read_reg(state, 0x19); | 164 | adc = dib0070_read_reg(state, 0x19); |
180 | 165 | ||
181 | dprintk("CAPTRIM=%hd; ADC = %hd (ADC) & %dmV", state->captrim, adc, (u32) adc * (u32) 1800 / (u32) 1024); | 166 | dprintk("CAPTRIM=%hd; ADC = %hd (ADC) & %dmV", state->captrim, adc, (u32) adc*(u32)1800/(u32)1024); |
182 | 167 | ||
183 | if (adc >= 400) { | 168 | if (adc >= 400) { |
184 | adc -= 400; | 169 | adc -= 400; |
@@ -193,6 +178,8 @@ static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state | |||
193 | state->adc_diff = adc; | 178 | state->adc_diff = adc; |
194 | state->fcaptrim = state->captrim; | 179 | state->fcaptrim = state->captrim; |
195 | 180 | ||
181 | |||
182 | |||
196 | } | 183 | } |
197 | state->captrim += (step_sign * state->step); | 184 | state->captrim += (step_sign * state->step); |
198 | 185 | ||
@@ -213,7 +200,7 @@ static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state | |||
213 | static int dib0070_set_ctrl_lo5(struct dvb_frontend *fe, u8 vco_bias_trim, u8 hf_div_trim, u8 cp_current, u8 third_order_filt) | 200 | static int dib0070_set_ctrl_lo5(struct dvb_frontend *fe, u8 vco_bias_trim, u8 hf_div_trim, u8 cp_current, u8 third_order_filt) |
214 | { | 201 | { |
215 | struct dib0070_state *state = fe->tuner_priv; | 202 | struct dib0070_state *state = fe->tuner_priv; |
216 | u16 lo5 = (third_order_filt << 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current << 6) | (hf_div_trim << 3) | (vco_bias_trim << 0); | 203 | u16 lo5 = (third_order_filt << 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current << 6) | (hf_div_trim << 3) | (vco_bias_trim << 0); |
217 | dprintk("CTRL_LO5: 0x%x", lo5); | 204 | dprintk("CTRL_LO5: 0x%x", lo5); |
218 | return dib0070_write_reg(state, 0x15, lo5); | 205 | return dib0070_write_reg(state, 0x15, lo5); |
219 | } | 206 | } |
@@ -227,99 +214,99 @@ void dib0070_ctrl_agc_filter(struct dvb_frontend *fe, u8 open) | |||
227 | dib0070_write_reg(state, 0x1a, 0x0000); | 214 | dib0070_write_reg(state, 0x1a, 0x0000); |
228 | } else { | 215 | } else { |
229 | dib0070_write_reg(state, 0x1b, 0x4112); | 216 | dib0070_write_reg(state, 0x1b, 0x4112); |
230 | if (state->cfg->vga_filter != 0) { | 217 | if (state->cfg->vga_filter != 0) { |
231 | dib0070_write_reg(state, 0x1a, state->cfg->vga_filter); | 218 | dib0070_write_reg(state, 0x1a, state->cfg->vga_filter); |
232 | dprintk("vga filter register is set to %x", state->cfg->vga_filter); | 219 | dprintk("vga filter register is set to %x", state->cfg->vga_filter); |
233 | } else | 220 | } else |
234 | dib0070_write_reg(state, 0x1a, 0x0009); | 221 | dib0070_write_reg(state, 0x1a, 0x0009); |
235 | } | 222 | } |
236 | } | 223 | } |
237 | 224 | ||
238 | EXPORT_SYMBOL(dib0070_ctrl_agc_filter); | 225 | EXPORT_SYMBOL(dib0070_ctrl_agc_filter); |
239 | struct dib0070_tuning { | 226 | struct dib0070_tuning { |
240 | u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */ | 227 | u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */ |
241 | u8 switch_trim; | 228 | u8 switch_trim; |
242 | u8 vco_band; | 229 | u8 vco_band; |
243 | u8 hfdiv; | 230 | u8 hfdiv; |
244 | u8 vco_multi; | 231 | u8 vco_multi; |
245 | u8 presc; | 232 | u8 presc; |
246 | u8 wbdmux; | 233 | u8 wbdmux; |
247 | u16 tuner_enable; | 234 | u16 tuner_enable; |
248 | }; | 235 | }; |
249 | 236 | ||
250 | struct dib0070_lna_match { | 237 | struct dib0070_lna_match { |
251 | u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */ | 238 | u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */ |
252 | u8 lna_band; | 239 | u8 lna_band; |
253 | }; | 240 | }; |
254 | 241 | ||
255 | static const struct dib0070_tuning dib0070s_tuning_table[] = { | 242 | static const struct dib0070_tuning dib0070s_tuning_table[] = { |
256 | {570000, 2, 1, 3, 6, 6, 2, 0x4000 | 0x0800}, /* UHF */ | 243 | { 570000, 2, 1, 3, 6, 6, 2, 0x4000 | 0x0800 }, /* UHF */ |
257 | {700000, 2, 0, 2, 4, 2, 2, 0x4000 | 0x0800}, | 244 | { 700000, 2, 0, 2, 4, 2, 2, 0x4000 | 0x0800 }, |
258 | {863999, 2, 1, 2, 4, 2, 2, 0x4000 | 0x0800}, | 245 | { 863999, 2, 1, 2, 4, 2, 2, 0x4000 | 0x0800 }, |
259 | {1500000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400}, /* LBAND */ | 246 | { 1500000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 }, /* LBAND */ |
260 | {1600000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400}, | 247 | { 1600000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 }, |
261 | {2000000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400}, | 248 | { 2000000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 }, |
262 | {0xffffffff, 0, 0, 8, 1, 2, 1, 0x8000 | 0x1000}, /* SBAND */ | 249 | { 0xffffffff, 0, 0, 8, 1, 2, 1, 0x8000 | 0x1000 }, /* SBAND */ |
263 | }; | 250 | }; |
264 | 251 | ||
265 | static const struct dib0070_tuning dib0070_tuning_table[] = { | 252 | static const struct dib0070_tuning dib0070_tuning_table[] = { |
266 | {115000, 1, 0, 7, 24, 2, 1, 0x8000 | 0x1000}, /* FM below 92MHz cannot be tuned */ | 253 | { 115000, 1, 0, 7, 24, 2, 1, 0x8000 | 0x1000 }, /* FM below 92MHz cannot be tuned */ |
267 | {179500, 1, 0, 3, 16, 2, 1, 0x8000 | 0x1000}, /* VHF */ | 254 | { 179500, 1, 0, 3, 16, 2, 1, 0x8000 | 0x1000 }, /* VHF */ |
268 | {189999, 1, 1, 3, 16, 2, 1, 0x8000 | 0x1000}, | 255 | { 189999, 1, 1, 3, 16, 2, 1, 0x8000 | 0x1000 }, |
269 | {250000, 1, 0, 6, 12, 2, 1, 0x8000 | 0x1000}, | 256 | { 250000, 1, 0, 6, 12, 2, 1, 0x8000 | 0x1000 }, |
270 | {569999, 2, 1, 5, 6, 2, 2, 0x4000 | 0x0800}, /* UHF */ | 257 | { 569999, 2, 1, 5, 6, 2, 2, 0x4000 | 0x0800 }, /* UHF */ |
271 | {699999, 2, 0, 1, 4, 2, 2, 0x4000 | 0x0800}, | 258 | { 699999, 2, 0, 1, 4, 2, 2, 0x4000 | 0x0800 }, |
272 | {863999, 2, 1, 1, 4, 2, 2, 0x4000 | 0x0800}, | 259 | { 863999, 2, 1, 1, 4, 2, 2, 0x4000 | 0x0800 }, |
273 | {0xffffffff, 0, 1, 0, 2, 2, 4, 0x2000 | 0x0400}, /* LBAND or everything higher than UHF */ | 260 | { 0xffffffff, 0, 1, 0, 2, 2, 4, 0x2000 | 0x0400 }, /* LBAND or everything higher than UHF */ |
274 | }; | 261 | }; |
275 | 262 | ||
276 | static const struct dib0070_lna_match dib0070_lna_flip_chip[] = { | 263 | static const struct dib0070_lna_match dib0070_lna_flip_chip[] = { |
277 | {180000, 0}, /* VHF */ | 264 | { 180000, 0 }, /* VHF */ |
278 | {188000, 1}, | 265 | { 188000, 1 }, |
279 | {196400, 2}, | 266 | { 196400, 2 }, |
280 | {250000, 3}, | 267 | { 250000, 3 }, |
281 | {550000, 0}, /* UHF */ | 268 | { 550000, 0 }, /* UHF */ |
282 | {590000, 1}, | 269 | { 590000, 1 }, |
283 | {666000, 3}, | 270 | { 666000, 3 }, |
284 | {864000, 5}, | 271 | { 864000, 5 }, |
285 | {1500000, 0}, /* LBAND or everything higher than UHF */ | 272 | { 1500000, 0 }, /* LBAND or everything higher than UHF */ |
286 | {1600000, 1}, | 273 | { 1600000, 1 }, |
287 | {2000000, 3}, | 274 | { 2000000, 3 }, |
288 | {0xffffffff, 7}, | 275 | { 0xffffffff, 7 }, |
289 | }; | 276 | }; |
290 | 277 | ||
291 | static const struct dib0070_lna_match dib0070_lna[] = { | 278 | static const struct dib0070_lna_match dib0070_lna[] = { |
292 | {180000, 0}, /* VHF */ | 279 | { 180000, 0 }, /* VHF */ |
293 | {188000, 1}, | 280 | { 188000, 1 }, |
294 | {196400, 2}, | 281 | { 196400, 2 }, |
295 | {250000, 3}, | 282 | { 250000, 3 }, |
296 | {550000, 2}, /* UHF */ | 283 | { 550000, 2 }, /* UHF */ |
297 | {650000, 3}, | 284 | { 650000, 3 }, |
298 | {750000, 5}, | 285 | { 750000, 5 }, |
299 | {850000, 6}, | 286 | { 850000, 6 }, |
300 | {864000, 7}, | 287 | { 864000, 7 }, |
301 | {1500000, 0}, /* LBAND or everything higher than UHF */ | 288 | { 1500000, 0 }, /* LBAND or everything higher than UHF */ |
302 | {1600000, 1}, | 289 | { 1600000, 1 }, |
303 | {2000000, 3}, | 290 | { 2000000, 3 }, |
304 | {0xffffffff, 7}, | 291 | { 0xffffffff, 7 }, |
305 | }; | 292 | }; |
306 | 293 | ||
307 | #define LPF 100 // define for the loop filter 100kHz by default 16-07-06 | 294 | #define LPF 100 |
308 | static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch) | 295 | static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch) |
309 | { | 296 | { |
310 | struct dib0070_state *state = fe->tuner_priv; | 297 | struct dib0070_state *state = fe->tuner_priv; |
311 | 298 | ||
312 | const struct dib0070_tuning *tune; | 299 | const struct dib0070_tuning *tune; |
313 | const struct dib0070_lna_match *lna_match; | 300 | const struct dib0070_lna_match *lna_match; |
314 | 301 | ||
315 | enum frontend_tune_state *tune_state = &state->tune_state; | 302 | enum frontend_tune_state *tune_state = &state->tune_state; |
316 | int ret = 10; /* 1ms is the default delay most of the time */ | 303 | int ret = 10; /* 1ms is the default delay most of the time */ |
317 | 304 | ||
318 | u8 band = (u8) BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000); | 305 | u8 band = (u8)BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency/1000); |
319 | u32 freq = fe->dtv_property_cache.frequency / 1000 + (band == BAND_VHF ? state->cfg->freq_offset_khz_vhf : state->cfg->freq_offset_khz_uhf); | 306 | u32 freq = fe->dtv_property_cache.frequency/1000 + (band == BAND_VHF ? state->cfg->freq_offset_khz_vhf : state->cfg->freq_offset_khz_uhf); |
320 | 307 | ||
321 | #ifdef CONFIG_SYS_ISDBT | 308 | #ifdef CONFIG_SYS_ISDBT |
322 | if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1) | 309 | if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1) |
323 | if (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) | 310 | if (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) |
324 | && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1))) | 311 | && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1))) |
325 | || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0) | 312 | || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0) |
@@ -328,172 +315,180 @@ static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_par | |||
328 | && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1)))) | 315 | && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1)))) |
329 | freq += 850; | 316 | freq += 850; |
330 | #endif | 317 | #endif |
318 | if (state->current_rf != freq) { | ||
319 | |||
320 | switch (state->revision) { | ||
321 | case DIB0070S_P1A: | ||
322 | tune = dib0070s_tuning_table; | ||
323 | lna_match = dib0070_lna; | ||
324 | break; | ||
325 | default: | ||
326 | tune = dib0070_tuning_table; | ||
327 | if (state->cfg->flip_chip) | ||
328 | lna_match = dib0070_lna_flip_chip; | ||
329 | else | ||
330 | lna_match = dib0070_lna; | ||
331 | break; | ||
332 | } | ||
333 | while (freq > tune->max_freq) /* find the right one */ | ||
334 | tune++; | ||
335 | while (freq > lna_match->max_freq) /* find the right one */ | ||
336 | lna_match++; | ||
337 | |||
338 | state->current_tune_table_index = tune; | ||
339 | state->lna_match = lna_match; | ||
340 | } | ||
341 | |||
342 | if (*tune_state == CT_TUNER_START) { | ||
343 | dprintk("Tuning for Band: %hd (%d kHz)", band, freq); | ||
331 | if (state->current_rf != freq) { | 344 | if (state->current_rf != freq) { |
345 | u8 REFDIV; | ||
346 | u32 FBDiv, Rest, FREF, VCOF_kHz; | ||
347 | u8 Den; | ||
348 | |||
349 | state->current_rf = freq; | ||
350 | state->lo4 = (state->current_tune_table_index->vco_band << 11) | (state->current_tune_table_index->hfdiv << 7); | ||
351 | |||
352 | |||
353 | dib0070_write_reg(state, 0x17, 0x30); | ||
354 | |||
355 | |||
356 | VCOF_kHz = state->current_tune_table_index->vco_multi * freq * 2; | ||
357 | |||
358 | switch (band) { | ||
359 | case BAND_VHF: | ||
360 | REFDIV = (u8) ((state->cfg->clock_khz + 9999) / 10000); | ||
361 | break; | ||
362 | case BAND_FM: | ||
363 | REFDIV = (u8) ((state->cfg->clock_khz) / 1000); | ||
364 | break; | ||
365 | default: | ||
366 | REFDIV = (u8) (state->cfg->clock_khz / 10000); | ||
367 | break; | ||
368 | } | ||
369 | FREF = state->cfg->clock_khz / REFDIV; | ||
370 | |||
371 | |||
332 | 372 | ||
333 | switch (state->revision) { | 373 | switch (state->revision) { |
334 | case DIB0070S_P1A: | 374 | case DIB0070S_P1A: |
335 | tune = dib0070s_tuning_table; | 375 | FBDiv = (VCOF_kHz / state->current_tune_table_index->presc / FREF); |
336 | lna_match = dib0070_lna; | 376 | Rest = (VCOF_kHz / state->current_tune_table_index->presc) - FBDiv * FREF; |
337 | break; | 377 | break; |
378 | |||
379 | case DIB0070_P1G: | ||
380 | case DIB0070_P1F: | ||
338 | default: | 381 | default: |
339 | tune = dib0070_tuning_table; | 382 | FBDiv = (freq / (FREF / 2)); |
340 | if (state->cfg->flip_chip) | 383 | Rest = 2 * freq - FBDiv * FREF; |
341 | lna_match = dib0070_lna_flip_chip; | ||
342 | else | ||
343 | lna_match = dib0070_lna; | ||
344 | break; | 384 | break; |
345 | } | 385 | } |
346 | while (freq > tune->max_freq) /* find the right one */ | ||
347 | tune++; | ||
348 | while (freq > lna_match->max_freq) /* find the right one */ | ||
349 | lna_match++; | ||
350 | 386 | ||
351 | state->current_tune_table_index = tune; | 387 | if (Rest < LPF) |
352 | state->lna_match = lna_match; | 388 | Rest = 0; |
353 | } | 389 | else if (Rest < 2 * LPF) |
390 | Rest = 2 * LPF; | ||
391 | else if (Rest > (FREF - LPF)) { | ||
392 | Rest = 0; | ||
393 | FBDiv += 1; | ||
394 | } else if (Rest > (FREF - 2 * LPF)) | ||
395 | Rest = FREF - 2 * LPF; | ||
396 | Rest = (Rest * 6528) / (FREF / 10); | ||
397 | |||
398 | Den = 1; | ||
399 | if (Rest > 0) { | ||
400 | state->lo4 |= (1 << 14) | (1 << 12); | ||
401 | Den = 255; | ||
402 | } | ||
403 | |||
354 | 404 | ||
355 | if (*tune_state == CT_TUNER_START) { | 405 | dib0070_write_reg(state, 0x11, (u16)FBDiv); |
356 | dprintk("Tuning for Band: %hd (%d kHz)", band, freq); | 406 | dib0070_write_reg(state, 0x12, (Den << 8) | REFDIV); |
357 | if (state->current_rf != freq) { | 407 | dib0070_write_reg(state, 0x13, (u16) Rest); |
358 | u8 REFDIV; | 408 | |
359 | u32 FBDiv, Rest, FREF, VCOF_kHz; | 409 | if (state->revision == DIB0070S_P1A) { |
360 | u8 Den; | 410 | |
361 | 411 | if (band == BAND_SBAND) { | |
362 | state->current_rf = freq; | 412 | dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0); |
363 | state->lo4 = (state->current_tune_table_index->vco_band << 11) | (state->current_tune_table_index->hfdiv << 7); | 413 | dib0070_write_reg(state, 0x1d, 0xFFFF); |
364 | 414 | } else | |
365 | dib0070_write_reg(state, 0x17, 0x30); | 415 | dib0070_set_ctrl_lo5(fe, 5, 4, 3, 1); |
366 | |||
367 | VCOF_kHz = state->current_tune_table_index->vco_multi * freq * 2; | ||
368 | |||
369 | switch (band) { | ||
370 | case BAND_VHF: | ||
371 | REFDIV = (u8) ((state->cfg->clock_khz + 9999) / 10000); | ||
372 | break; | ||
373 | case BAND_FM: | ||
374 | REFDIV = (u8) ((state->cfg->clock_khz) / 1000); | ||
375 | break; | ||
376 | default: | ||
377 | REFDIV = (u8) (state->cfg->clock_khz / 10000); | ||
378 | break; | ||
379 | } | ||
380 | FREF = state->cfg->clock_khz / REFDIV; | ||
381 | |||
382 | switch (state->revision) { | ||
383 | case DIB0070S_P1A: | ||
384 | FBDiv = (VCOF_kHz / state->current_tune_table_index->presc / FREF); | ||
385 | Rest = (VCOF_kHz / state->current_tune_table_index->presc) - FBDiv * FREF; | ||
386 | break; | ||
387 | |||
388 | case DIB0070_P1G: | ||
389 | case DIB0070_P1F: | ||
390 | default: | ||
391 | FBDiv = (freq / (FREF / 2)); | ||
392 | Rest = 2 * freq - FBDiv * FREF; | ||
393 | break; | ||
394 | } | ||
395 | |||
396 | if (Rest < LPF) | ||
397 | Rest = 0; | ||
398 | else if (Rest < 2 * LPF) | ||
399 | Rest = 2 * LPF; | ||
400 | else if (Rest > (FREF - LPF)) { | ||
401 | Rest = 0; | ||
402 | FBDiv += 1; | ||
403 | } else if (Rest > (FREF - 2 * LPF)) | ||
404 | Rest = FREF - 2 * LPF; | ||
405 | Rest = (Rest * 6528) / (FREF / 10); | ||
406 | |||
407 | Den = 1; | ||
408 | if (Rest > 0) { | ||
409 | state->lo4 |= (1 << 14) | (1 << 12); | ||
410 | Den = 255; | ||
411 | } | ||
412 | |||
413 | dib0070_write_reg(state, 0x11, (u16) FBDiv); | ||
414 | dib0070_write_reg(state, 0x12, (Den << 8) | REFDIV); | ||
415 | dib0070_write_reg(state, 0x13, (u16) Rest); | ||
416 | |||
417 | if (state->revision == DIB0070S_P1A) { | ||
418 | |||
419 | if (band == BAND_SBAND) { | ||
420 | dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0); | ||
421 | dib0070_write_reg(state, 0x1d, 0xFFFF); | ||
422 | } else | ||
423 | dib0070_set_ctrl_lo5(fe, 5, 4, 3, 1); | ||
424 | } | ||
425 | |||
426 | dib0070_write_reg(state, 0x20, | ||
427 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001 | state->current_tune_table_index->tuner_enable); | ||
428 | |||
429 | dprintk("REFDIV: %hd, FREF: %d", REFDIV, FREF); | ||
430 | dprintk("FBDIV: %d, Rest: %d", FBDiv, Rest); | ||
431 | dprintk("Num: %hd, Den: %hd, SD: %hd", (u16) Rest, Den, (state->lo4 >> 12) & 0x1); | ||
432 | dprintk("HFDIV code: %hd", state->current_tune_table_index->hfdiv); | ||
433 | dprintk("VCO = %hd", state->current_tune_table_index->vco_band); | ||
434 | dprintk("VCOF: ((%hd*%d) << 1))", state->current_tune_table_index->vco_multi, freq); | ||
435 | |||
436 | *tune_state = CT_TUNER_STEP_0; | ||
437 | } else { /* we are already tuned to this frequency - the configuration is correct */ | ||
438 | ret = 50; /* wakeup time */ | ||
439 | *tune_state = CT_TUNER_STEP_5; | ||
440 | } | 416 | } |
441 | } else if ((*tune_state > CT_TUNER_START) && (*tune_state < CT_TUNER_STEP_4)) { | ||
442 | 417 | ||
443 | ret = dib0070_captrim(state, tune_state); | 418 | dib0070_write_reg(state, 0x20, |
419 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001 | state->current_tune_table_index->tuner_enable); | ||
444 | 420 | ||
445 | } else if (*tune_state == CT_TUNER_STEP_4) { | 421 | dprintk("REFDIV: %hd, FREF: %d", REFDIV, FREF); |
446 | const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain; | 422 | dprintk("FBDIV: %d, Rest: %d", FBDiv, Rest); |
447 | if (tmp != NULL) { | 423 | dprintk("Num: %hd, Den: %hd, SD: %hd", (u16) Rest, Den, (state->lo4 >> 12) & 0x1); |
448 | while (freq / 1000 > tmp->freq) /* find the right one */ | 424 | dprintk("HFDIV code: %hd", state->current_tune_table_index->hfdiv); |
449 | tmp++; | 425 | dprintk("VCO = %hd", state->current_tune_table_index->vco_band); |
450 | dib0070_write_reg(state, 0x0f, | 426 | dprintk("VCOF: ((%hd*%d) << 1))", state->current_tune_table_index->vco_multi, freq); |
451 | (0 << 15) | (1 << 14) | (3 << 12) | (tmp->wbd_gain_val << 9) | (0 << 8) | (1 << 7) | (state-> | 427 | |
452 | current_tune_table_index-> | 428 | *tune_state = CT_TUNER_STEP_0; |
453 | wbdmux << 0)); | 429 | } else { /* we are already tuned to this frequency - the configuration is correct */ |
454 | state->wbd_gain_current = tmp->wbd_gain_val; | 430 | ret = 50; /* wakeup time */ |
455 | } else { | 431 | *tune_state = CT_TUNER_STEP_5; |
432 | } | ||
433 | } else if ((*tune_state > CT_TUNER_START) && (*tune_state < CT_TUNER_STEP_4)) { | ||
434 | |||
435 | ret = dib0070_captrim(state, tune_state); | ||
436 | |||
437 | } else if (*tune_state == CT_TUNER_STEP_4) { | ||
438 | const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain; | ||
439 | if (tmp != NULL) { | ||
440 | while (freq/1000 > tmp->freq) /* find the right one */ | ||
441 | tmp++; | ||
442 | dib0070_write_reg(state, 0x0f, | ||
443 | (0 << 15) | (1 << 14) | (3 << 12) | ||
444 | | (tmp->wbd_gain_val << 9) | (0 << 8) | (1 << 7) | ||
445 | | (state->current_tune_table_index->wbdmux << 0)); | ||
446 | state->wbd_gain_current = tmp->wbd_gain_val; | ||
447 | } else { | ||
456 | dib0070_write_reg(state, 0x0f, | 448 | dib0070_write_reg(state, 0x0f, |
457 | (0 << 15) | (1 << 14) | (3 << 12) | (6 << 9) | (0 << 8) | (1 << 7) | (state->current_tune_table_index-> | 449 | (0 << 15) | (1 << 14) | (3 << 12) | (6 << 9) | (0 << 8) | (1 << 7) | (state->current_tune_table_index-> |
458 | wbdmux << 0)); | 450 | wbdmux << 0)); |
459 | state->wbd_gain_current = 6; | 451 | state->wbd_gain_current = 6; |
460 | } | 452 | } |
461 | 453 | ||
462 | dib0070_write_reg(state, 0x06, 0x3fff); | 454 | dib0070_write_reg(state, 0x06, 0x3fff); |
463 | dib0070_write_reg(state, 0x07, | 455 | dib0070_write_reg(state, 0x07, |
464 | (state->current_tune_table_index->switch_trim << 11) | (7 << 8) | (state->lna_match->lna_band << 3) | (3 << 0)); | 456 | (state->current_tune_table_index->switch_trim << 11) | (7 << 8) | (state->lna_match->lna_band << 3) | (3 << 0)); |
465 | dib0070_write_reg(state, 0x08, (state->lna_match->lna_band << 10) | (3 << 7) | (127)); | 457 | dib0070_write_reg(state, 0x08, (state->lna_match->lna_band << 10) | (3 << 7) | (127)); |
466 | dib0070_write_reg(state, 0x0d, 0x0d80); | 458 | dib0070_write_reg(state, 0x0d, 0x0d80); |
467 | 459 | ||
468 | dib0070_write_reg(state, 0x18, 0x07ff); | ||
469 | dib0070_write_reg(state, 0x17, 0x0033); | ||
470 | 460 | ||
471 | *tune_state = CT_TUNER_STEP_5; | 461 | dib0070_write_reg(state, 0x18, 0x07ff); |
472 | } else if (*tune_state == CT_TUNER_STEP_5) { | 462 | dib0070_write_reg(state, 0x17, 0x0033); |
473 | dib0070_set_bandwidth(fe, ch); | 463 | |
474 | *tune_state = CT_TUNER_STOP; | 464 | |
475 | } else { | 465 | *tune_state = CT_TUNER_STEP_5; |
476 | ret = FE_CALLBACK_TIME_NEVER; /* tuner finished, time to call again infinite */ | 466 | } else if (*tune_state == CT_TUNER_STEP_5) { |
477 | } | 467 | dib0070_set_bandwidth(fe, ch); |
478 | return ret; | 468 | *tune_state = CT_TUNER_STOP; |
469 | } else { | ||
470 | ret = FE_CALLBACK_TIME_NEVER; /* tuner finished, time to call again infinite */ | ||
471 | } | ||
472 | return ret; | ||
479 | } | 473 | } |
480 | 474 | ||
475 | |||
481 | static int dib0070_tune(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) | 476 | static int dib0070_tune(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) |
482 | { | 477 | { |
483 | struct dib0070_state *state = fe->tuner_priv; | 478 | struct dib0070_state *state = fe->tuner_priv; |
484 | uint32_t ret; | 479 | uint32_t ret; |
485 | 480 | ||
486 | state->tune_state = CT_TUNER_START; | 481 | state->tune_state = CT_TUNER_START; |
487 | 482 | ||
488 | do { | 483 | do { |
489 | ret = dib0070_tune_digital(fe, p); | 484 | ret = dib0070_tune_digital(fe, p); |
490 | if (ret != FE_CALLBACK_TIME_NEVER) | 485 | if (ret != FE_CALLBACK_TIME_NEVER) |
491 | msleep(ret / 10); | 486 | msleep(ret/10); |
492 | else | 487 | else |
493 | break; | 488 | break; |
494 | } while (state->tune_state != CT_TUNER_STOP); | 489 | } while (state->tune_state != CT_TUNER_STOP); |
495 | 490 | ||
496 | return 0; | 491 | return 0; |
497 | } | 492 | } |
498 | 493 | ||
499 | static int dib0070_wakeup(struct dvb_frontend *fe) | 494 | static int dib0070_wakeup(struct dvb_frontend *fe) |
@@ -512,92 +507,113 @@ static int dib0070_sleep(struct dvb_frontend *fe) | |||
512 | return 0; | 507 | return 0; |
513 | } | 508 | } |
514 | 509 | ||
515 | static const u16 dib0070_p1f_defaults[] = { | 510 | u8 dib0070_get_rf_output(struct dvb_frontend *fe) |
511 | { | ||
512 | struct dib0070_state *state = fe->tuner_priv; | ||
513 | return (dib0070_read_reg(state, 0x07) >> 11) & 0x3; | ||
514 | } | ||
515 | EXPORT_SYMBOL(dib0070_get_rf_output); | ||
516 | |||
517 | int dib0070_set_rf_output(struct dvb_frontend *fe, u8 no) | ||
518 | { | ||
519 | struct dib0070_state *state = fe->tuner_priv; | ||
520 | u16 rxrf2 = dib0070_read_reg(state, 0x07) & 0xfe7ff; | ||
521 | if (no > 3) | ||
522 | no = 3; | ||
523 | if (no < 1) | ||
524 | no = 1; | ||
525 | return dib0070_write_reg(state, 0x07, rxrf2 | (no << 11)); | ||
526 | } | ||
527 | EXPORT_SYMBOL(dib0070_set_rf_output); | ||
528 | |||
529 | static const u16 dib0070_p1f_defaults[] = | ||
530 | |||
531 | { | ||
516 | 7, 0x02, | 532 | 7, 0x02, |
517 | 0x0008, | 533 | 0x0008, |
518 | 0x0000, | 534 | 0x0000, |
519 | 0x0000, | 535 | 0x0000, |
520 | 0x0000, | 536 | 0x0000, |
521 | 0x0000, | 537 | 0x0000, |
522 | 0x0002, | 538 | 0x0002, |
523 | 0x0100, | 539 | 0x0100, |
524 | 540 | ||
525 | 3, 0x0d, | 541 | 3, 0x0d, |
526 | 0x0d80, | 542 | 0x0d80, |
527 | 0x0001, | 543 | 0x0001, |
528 | 0x0000, | 544 | 0x0000, |
529 | 545 | ||
530 | 4, 0x11, | 546 | 4, 0x11, |
531 | 0x0000, | 547 | 0x0000, |
532 | 0x0103, | 548 | 0x0103, |
533 | 0x0000, | 549 | 0x0000, |
534 | 0x0000, | 550 | 0x0000, |
535 | 551 | ||
536 | 3, 0x16, | 552 | 3, 0x16, |
537 | 0x0004 | 0x0040, | 553 | 0x0004 | 0x0040, |
538 | 0x0030, | 554 | 0x0030, |
539 | 0x07ff, | 555 | 0x07ff, |
540 | 556 | ||
541 | 6, 0x1b, | 557 | 6, 0x1b, |
542 | 0x4112, | 558 | 0x4112, |
543 | 0xff00, | 559 | 0xff00, |
544 | 0xc07f, | 560 | 0xc07f, |
545 | 0x0000, | 561 | 0x0000, |
546 | 0x0180, | 562 | 0x0180, |
547 | 0x4000 | 0x0800 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001, | 563 | 0x4000 | 0x0800 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001, |
548 | 564 | ||
549 | 0, | 565 | 0, |
550 | }; | 566 | }; |
551 | 567 | ||
552 | static u16 dib0070_read_wbd_offset(struct dib0070_state *state, u8 gain) | 568 | static u16 dib0070_read_wbd_offset(struct dib0070_state *state, u8 gain) |
553 | { | 569 | { |
554 | u16 tuner_en = dib0070_read_reg(state, 0x20); | 570 | u16 tuner_en = dib0070_read_reg(state, 0x20); |
555 | u16 offset; | 571 | u16 offset; |
556 | 572 | ||
557 | dib0070_write_reg(state, 0x18, 0x07ff); | 573 | dib0070_write_reg(state, 0x18, 0x07ff); |
558 | dib0070_write_reg(state, 0x20, 0x0800 | 0x4000 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001); | 574 | dib0070_write_reg(state, 0x20, 0x0800 | 0x4000 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001); |
559 | dib0070_write_reg(state, 0x0f, (1 << 14) | (2 << 12) | (gain << 9) | (1 << 8) | (1 << 7) | (0 << 0)); | 575 | dib0070_write_reg(state, 0x0f, (1 << 14) | (2 << 12) | (gain << 9) | (1 << 8) | (1 << 7) | (0 << 0)); |
560 | msleep(9); | 576 | msleep(9); |
561 | offset = dib0070_read_reg(state, 0x19); | 577 | offset = dib0070_read_reg(state, 0x19); |
562 | dib0070_write_reg(state, 0x20, tuner_en); | 578 | dib0070_write_reg(state, 0x20, tuner_en); |
563 | return offset; | 579 | return offset; |
564 | } | 580 | } |
565 | 581 | ||
566 | static void dib0070_wbd_offset_calibration(struct dib0070_state *state) | 582 | static void dib0070_wbd_offset_calibration(struct dib0070_state *state) |
567 | { | 583 | { |
568 | u8 gain; | 584 | u8 gain; |
569 | for (gain = 6; gain < 8; gain++) { | 585 | for (gain = 6; gain < 8; gain++) { |
570 | state->wbd_offset_3_3[gain - 6] = ((dib0070_read_wbd_offset(state, gain) * 8 * 18 / 33 + 1) / 2); | 586 | state->wbd_offset_3_3[gain - 6] = ((dib0070_read_wbd_offset(state, gain) * 8 * 18 / 33 + 1) / 2); |
571 | dprintk("Gain: %d, WBDOffset (3.3V) = %hd", gain, state->wbd_offset_3_3[gain - 6]); | 587 | dprintk("Gain: %d, WBDOffset (3.3V) = %hd", gain, state->wbd_offset_3_3[gain-6]); |
572 | } | 588 | } |
573 | } | 589 | } |
574 | 590 | ||
575 | u16 dib0070_wbd_offset(struct dvb_frontend *fe) | 591 | u16 dib0070_wbd_offset(struct dvb_frontend *fe) |
576 | { | 592 | { |
577 | struct dib0070_state *state = fe->tuner_priv; | 593 | struct dib0070_state *state = fe->tuner_priv; |
578 | const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain; | 594 | const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain; |
579 | u32 freq = fe->dtv_property_cache.frequency / 1000; | 595 | u32 freq = fe->dtv_property_cache.frequency/1000; |
580 | 596 | ||
581 | if (tmp != NULL) { | 597 | if (tmp != NULL) { |
582 | while (freq / 1000 > tmp->freq) /* find the right one */ | 598 | while (freq/1000 > tmp->freq) /* find the right one */ |
583 | tmp++; | 599 | tmp++; |
584 | state->wbd_gain_current = tmp->wbd_gain_val; | 600 | state->wbd_gain_current = tmp->wbd_gain_val; |
585 | } else | 601 | } else |
586 | state->wbd_gain_current = 6; | 602 | state->wbd_gain_current = 6; |
587 | 603 | ||
588 | return state->wbd_offset_3_3[state->wbd_gain_current - 6]; | 604 | return state->wbd_offset_3_3[state->wbd_gain_current - 6]; |
589 | } | 605 | } |
590 | |||
591 | EXPORT_SYMBOL(dib0070_wbd_offset); | 606 | EXPORT_SYMBOL(dib0070_wbd_offset); |
592 | 607 | ||
593 | #define pgm_read_word(w) (*w) | 608 | #define pgm_read_word(w) (*w) |
594 | static int dib0070_reset(struct dvb_frontend *fe) | 609 | static int dib0070_reset(struct dvb_frontend *fe) |
595 | { | 610 | { |
596 | struct dib0070_state *state = fe->tuner_priv; | 611 | struct dib0070_state *state = fe->tuner_priv; |
597 | u16 l, r, *n; | 612 | u16 l, r, *n; |
598 | 613 | ||
599 | HARD_RESET(state); | 614 | HARD_RESET(state); |
600 | 615 | ||
616 | |||
601 | #ifndef FORCE_SBAND_TUNER | 617 | #ifndef FORCE_SBAND_TUNER |
602 | if ((dib0070_read_reg(state, 0x22) >> 9) & 0x1) | 618 | if ((dib0070_read_reg(state, 0x22) >> 9) & 0x1) |
603 | state->revision = (dib0070_read_reg(state, 0x1f) >> 8) & 0xff; | 619 | state->revision = (dib0070_read_reg(state, 0x1f) >> 8) & 0xff; |
@@ -605,7 +621,7 @@ static int dib0070_reset(struct dvb_frontend *fe) | |||
605 | #else | 621 | #else |
606 | #warning forcing SBAND | 622 | #warning forcing SBAND |
607 | #endif | 623 | #endif |
608 | state->revision = DIB0070S_P1A; | 624 | state->revision = DIB0070S_P1A; |
609 | 625 | ||
610 | /* P1F or not */ | 626 | /* P1F or not */ |
611 | dprintk("Revision: %x", state->revision); | 627 | dprintk("Revision: %x", state->revision); |
@@ -620,7 +636,7 @@ static int dib0070_reset(struct dvb_frontend *fe) | |||
620 | while (l) { | 636 | while (l) { |
621 | r = pgm_read_word(n++); | 637 | r = pgm_read_word(n++); |
622 | do { | 638 | do { |
623 | dib0070_write_reg(state, (u8) r, pgm_read_word(n++)); | 639 | dib0070_write_reg(state, (u8)r, pgm_read_word(n++)); |
624 | r++; | 640 | r++; |
625 | } while (--l); | 641 | } while (--l); |
626 | l = pgm_read_word(n++); | 642 | l = pgm_read_word(n++); |
@@ -633,6 +649,7 @@ static int dib0070_reset(struct dvb_frontend *fe) | |||
633 | else | 649 | else |
634 | r = 2; | 650 | r = 2; |
635 | 651 | ||
652 | |||
636 | r |= state->cfg->osc_buffer_state << 3; | 653 | r |= state->cfg->osc_buffer_state << 3; |
637 | 654 | ||
638 | dib0070_write_reg(state, 0x10, r); | 655 | dib0070_write_reg(state, 0x10, r); |
@@ -643,16 +660,24 @@ static int dib0070_reset(struct dvb_frontend *fe) | |||
643 | dib0070_write_reg(state, 0x02, r | (1 << 5)); | 660 | dib0070_write_reg(state, 0x02, r | (1 << 5)); |
644 | } | 661 | } |
645 | 662 | ||
646 | if (state->revision == DIB0070S_P1A) | 663 | if (state->revision == DIB0070S_P1A) |
647 | dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0); | 664 | dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0); |
648 | else | 665 | else |
649 | dib0070_set_ctrl_lo5(fe, 5, 4, state->cfg->charge_pump, state->cfg->enable_third_order_filter); | 666 | dib0070_set_ctrl_lo5(fe, 5, 4, state->cfg->charge_pump, state->cfg->enable_third_order_filter); |
650 | 667 | ||
651 | dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8); | 668 | dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8); |
652 | 669 | ||
653 | dib0070_wbd_offset_calibration(state); | 670 | dib0070_wbd_offset_calibration(state); |
654 | 671 | ||
655 | return 0; | 672 | return 0; |
673 | } | ||
674 | |||
675 | static int dib0070_get_frequency(struct dvb_frontend *fe, u32 *frequency) | ||
676 | { | ||
677 | struct dib0070_state *state = fe->tuner_priv; | ||
678 | |||
679 | *frequency = 1000 * state->current_rf; | ||
680 | return 0; | ||
656 | } | 681 | } |
657 | 682 | ||
658 | static int dib0070_release(struct dvb_frontend *fe) | 683 | static int dib0070_release(struct dvb_frontend *fe) |
@@ -664,18 +689,18 @@ static int dib0070_release(struct dvb_frontend *fe) | |||
664 | 689 | ||
665 | static const struct dvb_tuner_ops dib0070_ops = { | 690 | static const struct dvb_tuner_ops dib0070_ops = { |
666 | .info = { | 691 | .info = { |
667 | .name = "DiBcom DiB0070", | 692 | .name = "DiBcom DiB0070", |
668 | .frequency_min = 45000000, | 693 | .frequency_min = 45000000, |
669 | .frequency_max = 860000000, | 694 | .frequency_max = 860000000, |
670 | .frequency_step = 1000, | 695 | .frequency_step = 1000, |
671 | }, | 696 | }, |
672 | .release = dib0070_release, | 697 | .release = dib0070_release, |
673 | 698 | ||
674 | .init = dib0070_wakeup, | 699 | .init = dib0070_wakeup, |
675 | .sleep = dib0070_sleep, | 700 | .sleep = dib0070_sleep, |
676 | .set_params = dib0070_tune, | 701 | .set_params = dib0070_tune, |
677 | 702 | ||
678 | // .get_frequency = dib0070_get_frequency, | 703 | .get_frequency = dib0070_get_frequency, |
679 | // .get_bandwidth = dib0070_get_bandwidth | 704 | // .get_bandwidth = dib0070_get_bandwidth |
680 | }; | 705 | }; |
681 | 706 | ||
@@ -687,7 +712,7 @@ struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter | |||
687 | 712 | ||
688 | state->cfg = cfg; | 713 | state->cfg = cfg; |
689 | state->i2c = i2c; | 714 | state->i2c = i2c; |
690 | state->fe = fe; | 715 | state->fe = fe; |
691 | fe->tuner_priv = state; | 716 | fe->tuner_priv = state; |
692 | 717 | ||
693 | if (dib0070_reset(fe) != 0) | 718 | if (dib0070_reset(fe) != 0) |
@@ -699,12 +724,11 @@ struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter | |||
699 | fe->tuner_priv = state; | 724 | fe->tuner_priv = state; |
700 | return fe; | 725 | return fe; |
701 | 726 | ||
702 | free_mem: | 727 | free_mem: |
703 | kfree(state); | 728 | kfree(state); |
704 | fe->tuner_priv = NULL; | 729 | fe->tuner_priv = NULL; |
705 | return NULL; | 730 | return NULL; |
706 | } | 731 | } |
707 | |||
708 | EXPORT_SYMBOL(dib0070_attach); | 732 | EXPORT_SYMBOL(dib0070_attach); |
709 | 733 | ||
710 | MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>"); | 734 | MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>"); |
diff --git a/drivers/media/dvb/frontends/dib0070.h b/drivers/media/dvb/frontends/dib0070.h index eec9e52ffa75..45c31fae3967 100644 --- a/drivers/media/dvb/frontends/dib0070.h +++ b/drivers/media/dvb/frontends/dib0070.h | |||
@@ -52,6 +52,8 @@ struct dib0070_config { | |||
52 | extern struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg); | 52 | extern struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg); |
53 | extern u16 dib0070_wbd_offset(struct dvb_frontend *); | 53 | extern u16 dib0070_wbd_offset(struct dvb_frontend *); |
54 | extern void dib0070_ctrl_agc_filter(struct dvb_frontend *, u8 open); | 54 | extern void dib0070_ctrl_agc_filter(struct dvb_frontend *, u8 open); |
55 | extern u8 dib0070_get_rf_output(struct dvb_frontend *fe); | ||
56 | extern int dib0070_set_rf_output(struct dvb_frontend *fe, u8 no); | ||
55 | #else | 57 | #else |
56 | static inline struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg) | 58 | static inline struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg) |
57 | { | 59 | { |
@@ -62,7 +64,7 @@ static inline struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struc | |||
62 | static inline u16 dib0070_wbd_offset(struct dvb_frontend *fe) | 64 | static inline u16 dib0070_wbd_offset(struct dvb_frontend *fe) |
63 | { | 65 | { |
64 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | 66 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); |
65 | return -ENODEV; | 67 | return 0; |
66 | } | 68 | } |
67 | 69 | ||
68 | static inline void dib0070_ctrl_agc_filter(struct dvb_frontend *fe, u8 open) | 70 | static inline void dib0070_ctrl_agc_filter(struct dvb_frontend *fe, u8 open) |
diff --git a/drivers/media/dvb/frontends/dib0090.c b/drivers/media/dvb/frontends/dib0090.c new file mode 100644 index 000000000000..614552709a6f --- /dev/null +++ b/drivers/media/dvb/frontends/dib0090.c | |||
@@ -0,0 +1,1522 @@ | |||
1 | /* | ||
2 | * Linux-DVB Driver for DiBcom's DiB0090 base-band RF Tuner. | ||
3 | * | ||
4 | * Copyright (C) 2005-9 DiBcom (http://www.dibcom.fr/) | ||
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 as | ||
8 | * published by the Free Software Foundation; either version 2 of the | ||
9 | * License, or (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * | ||
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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | * | ||
21 | * | ||
22 | * This code is more or less generated from another driver, please | ||
23 | * excuse some codingstyle oddities. | ||
24 | * | ||
25 | */ | ||
26 | |||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/i2c.h> | ||
29 | |||
30 | #include "dvb_frontend.h" | ||
31 | |||
32 | #include "dib0090.h" | ||
33 | #include "dibx000_common.h" | ||
34 | |||
35 | static int debug; | ||
36 | module_param(debug, int, 0644); | ||
37 | MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); | ||
38 | |||
39 | #define dprintk(args...) do { \ | ||
40 | if (debug) { \ | ||
41 | printk(KERN_DEBUG "DiB0090: "); \ | ||
42 | printk(args); \ | ||
43 | printk("\n"); \ | ||
44 | } \ | ||
45 | } while (0) | ||
46 | |||
47 | #define CONFIG_SYS_ISDBT | ||
48 | #define CONFIG_BAND_CBAND | ||
49 | #define CONFIG_BAND_VHF | ||
50 | #define CONFIG_BAND_UHF | ||
51 | #define CONFIG_DIB0090_USE_PWM_AGC | ||
52 | |||
53 | #define EN_LNA0 0x8000 | ||
54 | #define EN_LNA1 0x4000 | ||
55 | #define EN_LNA2 0x2000 | ||
56 | #define EN_LNA3 0x1000 | ||
57 | #define EN_MIX0 0x0800 | ||
58 | #define EN_MIX1 0x0400 | ||
59 | #define EN_MIX2 0x0200 | ||
60 | #define EN_MIX3 0x0100 | ||
61 | #define EN_IQADC 0x0040 | ||
62 | #define EN_PLL 0x0020 | ||
63 | #define EN_TX 0x0010 | ||
64 | #define EN_BB 0x0008 | ||
65 | #define EN_LO 0x0004 | ||
66 | #define EN_BIAS 0x0001 | ||
67 | |||
68 | #define EN_IQANA 0x0002 | ||
69 | #define EN_DIGCLK 0x0080 /* not in the 0x24 reg, only in 0x1b */ | ||
70 | #define EN_CRYSTAL 0x0002 | ||
71 | |||
72 | #define EN_UHF 0x22E9 | ||
73 | #define EN_VHF 0x44E9 | ||
74 | #define EN_LBD 0x11E9 | ||
75 | #define EN_SBD 0x44E9 | ||
76 | #define EN_CAB 0x88E9 | ||
77 | |||
78 | #define pgm_read_word(w) (*w) | ||
79 | |||
80 | struct dc_calibration; | ||
81 | |||
82 | struct dib0090_tuning { | ||
83 | u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */ | ||
84 | u8 switch_trim; | ||
85 | u8 lna_tune; | ||
86 | u8 lna_bias; | ||
87 | u16 v2i; | ||
88 | u16 mix; | ||
89 | u16 load; | ||
90 | u16 tuner_enable; | ||
91 | }; | ||
92 | |||
93 | struct dib0090_pll { | ||
94 | u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */ | ||
95 | u8 vco_band; | ||
96 | u8 hfdiv_code; | ||
97 | u8 hfdiv; | ||
98 | u8 topresc; | ||
99 | }; | ||
100 | |||
101 | struct dib0090_state { | ||
102 | struct i2c_adapter *i2c; | ||
103 | struct dvb_frontend *fe; | ||
104 | const struct dib0090_config *config; | ||
105 | |||
106 | u8 current_band; | ||
107 | u16 revision; | ||
108 | enum frontend_tune_state tune_state; | ||
109 | u32 current_rf; | ||
110 | |||
111 | u16 wbd_offset; | ||
112 | s16 wbd_target; /* in dB */ | ||
113 | |||
114 | s16 rf_gain_limit; /* take-over-point: where to split between bb and rf gain */ | ||
115 | s16 current_gain; /* keeps the currently programmed gain */ | ||
116 | u8 agc_step; /* new binary search */ | ||
117 | |||
118 | u16 gain[2]; /* for channel monitoring */ | ||
119 | |||
120 | const u16 *rf_ramp; | ||
121 | const u16 *bb_ramp; | ||
122 | |||
123 | /* for the software AGC ramps */ | ||
124 | u16 bb_1_def; | ||
125 | u16 rf_lt_def; | ||
126 | u16 gain_reg[4]; | ||
127 | |||
128 | /* for the captrim/dc-offset search */ | ||
129 | s8 step; | ||
130 | s16 adc_diff; | ||
131 | s16 min_adc_diff; | ||
132 | |||
133 | s8 captrim; | ||
134 | s8 fcaptrim; | ||
135 | |||
136 | const struct dc_calibration *dc; | ||
137 | u16 bb6, bb7; | ||
138 | |||
139 | const struct dib0090_tuning *current_tune_table_index; | ||
140 | const struct dib0090_pll *current_pll_table_index; | ||
141 | |||
142 | u8 tuner_is_tuned; | ||
143 | u8 agc_freeze; | ||
144 | |||
145 | u8 reset; | ||
146 | }; | ||
147 | |||
148 | static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg) | ||
149 | { | ||
150 | u8 b[2]; | ||
151 | struct i2c_msg msg[2] = { | ||
152 | {.addr = state->config->i2c_address, .flags = 0, .buf = ®, .len = 1}, | ||
153 | {.addr = state->config->i2c_address, .flags = I2C_M_RD, .buf = b, .len = 2}, | ||
154 | }; | ||
155 | if (i2c_transfer(state->i2c, msg, 2) != 2) { | ||
156 | printk(KERN_WARNING "DiB0090 I2C read failed\n"); | ||
157 | return 0; | ||
158 | } | ||
159 | return (b[0] << 8) | b[1]; | ||
160 | } | ||
161 | |||
162 | static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val) | ||
163 | { | ||
164 | u8 b[3] = { reg & 0xff, val >> 8, val & 0xff }; | ||
165 | struct i2c_msg msg = {.addr = state->config->i2c_address, .flags = 0, .buf = b, .len = 3 }; | ||
166 | if (i2c_transfer(state->i2c, &msg, 1) != 1) { | ||
167 | printk(KERN_WARNING "DiB0090 I2C write failed\n"); | ||
168 | return -EREMOTEIO; | ||
169 | } | ||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | #define HARD_RESET(state) do { if (cfg->reset) { if (cfg->sleep) cfg->sleep(fe, 0); msleep(10); cfg->reset(fe, 1); msleep(10); cfg->reset(fe, 0); msleep(10); } } while (0) | ||
174 | #define ADC_TARGET -220 | ||
175 | #define GAIN_ALPHA 5 | ||
176 | #define WBD_ALPHA 6 | ||
177 | #define LPF 100 | ||
178 | static void dib0090_write_regs(struct dib0090_state *state, u8 r, const u16 * b, u8 c) | ||
179 | { | ||
180 | do { | ||
181 | dib0090_write_reg(state, r++, *b++); | ||
182 | } while (--c); | ||
183 | } | ||
184 | |||
185 | static u16 dib0090_identify(struct dvb_frontend *fe) | ||
186 | { | ||
187 | struct dib0090_state *state = fe->tuner_priv; | ||
188 | u16 v; | ||
189 | |||
190 | v = dib0090_read_reg(state, 0x1a); | ||
191 | |||
192 | #ifdef FIRMWARE_FIREFLY | ||
193 | /* pll is not locked locked */ | ||
194 | if (!(v & 0x800)) | ||
195 | dprintk("FE%d : Identification : pll is not yet locked", fe->id); | ||
196 | #endif | ||
197 | |||
198 | /* without PLL lock info */ | ||
199 | v &= 0x3ff; | ||
200 | dprintk("P/V: %04x:", v); | ||
201 | |||
202 | if ((v >> 8) & 0xf) | ||
203 | dprintk("FE%d : Product ID = 0x%x : KROSUS", fe->id, (v >> 8) & 0xf); | ||
204 | else | ||
205 | return 0xff; | ||
206 | |||
207 | v &= 0xff; | ||
208 | if (((v >> 5) & 0x7) == 0x1) | ||
209 | dprintk("FE%d : MP001 : 9090/8096", fe->id); | ||
210 | else if (((v >> 5) & 0x7) == 0x4) | ||
211 | dprintk("FE%d : MP005 : Single Sband", fe->id); | ||
212 | else if (((v >> 5) & 0x7) == 0x6) | ||
213 | dprintk("FE%d : MP008 : diversity VHF-UHF-LBAND", fe->id); | ||
214 | else if (((v >> 5) & 0x7) == 0x7) | ||
215 | dprintk("FE%d : MP009 : diversity 29098 CBAND-UHF-LBAND-SBAND", fe->id); | ||
216 | else | ||
217 | return 0xff; | ||
218 | |||
219 | /* revision only */ | ||
220 | if ((v & 0x1f) == 0x3) | ||
221 | dprintk("FE%d : P1-D/E/F detected", fe->id); | ||
222 | else if ((v & 0x1f) == 0x1) | ||
223 | dprintk("FE%d : P1C detected", fe->id); | ||
224 | else if ((v & 0x1f) == 0x0) { | ||
225 | #ifdef CONFIG_TUNER_DIB0090_P1B_SUPPORT | ||
226 | dprintk("FE%d : P1-A/B detected: using previous driver - support will be removed soon", fe->id); | ||
227 | dib0090_p1b_register(fe); | ||
228 | #else | ||
229 | dprintk("FE%d : P1-A/B detected: driver is deactivated - not available", fe->id); | ||
230 | return 0xff; | ||
231 | #endif | ||
232 | } | ||
233 | |||
234 | return v; | ||
235 | } | ||
236 | |||
237 | static void dib0090_reset_digital(struct dvb_frontend *fe, const struct dib0090_config *cfg) | ||
238 | { | ||
239 | struct dib0090_state *state = fe->tuner_priv; | ||
240 | |||
241 | HARD_RESET(state); | ||
242 | |||
243 | dib0090_write_reg(state, 0x24, EN_PLL); | ||
244 | dib0090_write_reg(state, 0x1b, EN_DIGCLK | EN_PLL | EN_CRYSTAL); /* PLL, DIG_CLK and CRYSTAL remain */ | ||
245 | |||
246 | /* adcClkOutRatio=8->7, release reset */ | ||
247 | dib0090_write_reg(state, 0x20, ((cfg->io.adc_clock_ratio - 1) << 11) | (0 << 10) | (1 << 9) | (1 << 8) | (0 << 4) | 0); | ||
248 | if (cfg->clkoutdrive != 0) | ||
249 | dib0090_write_reg(state, 0x23, | ||
250 | (0 << 15) | ((!cfg->analog_output) << 14) | (1 << 10) | (1 << 9) | (0 << 8) | (cfg->clkoutdrive << 5) | (cfg-> | ||
251 | clkouttobamse | ||
252 | << 4) | (0 | ||
253 | << | ||
254 | 2) | ||
255 | | (0)); | ||
256 | else | ||
257 | dib0090_write_reg(state, 0x23, | ||
258 | (0 << 15) | ((!cfg->analog_output) << 14) | (1 << 10) | (1 << 9) | (0 << 8) | (7 << 5) | (cfg-> | ||
259 | clkouttobamse << 4) | (0 | ||
260 | << | ||
261 | 2) | ||
262 | | (0)); | ||
263 | |||
264 | /* enable pll, de-activate reset, ratio: 2/1 = 60MHz */ | ||
265 | dib0090_write_reg(state, 0x21, | ||
266 | (cfg->io.pll_bypass << 15) | (1 << 13) | (cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv)); | ||
267 | |||
268 | } | ||
269 | |||
270 | static int dib0090_wakeup(struct dvb_frontend *fe) | ||
271 | { | ||
272 | struct dib0090_state *state = fe->tuner_priv; | ||
273 | if (state->config->sleep) | ||
274 | state->config->sleep(fe, 0); | ||
275 | return 0; | ||
276 | } | ||
277 | |||
278 | static int dib0090_sleep(struct dvb_frontend *fe) | ||
279 | { | ||
280 | struct dib0090_state *state = fe->tuner_priv; | ||
281 | if (state->config->sleep) | ||
282 | state->config->sleep(fe, 1); | ||
283 | return 0; | ||
284 | } | ||
285 | |||
286 | extern void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast) | ||
287 | { | ||
288 | struct dib0090_state *state = fe->tuner_priv; | ||
289 | if (fast) | ||
290 | dib0090_write_reg(state, 0x04, 0); | ||
291 | else | ||
292 | dib0090_write_reg(state, 0x04, 1); | ||
293 | } | ||
294 | EXPORT_SYMBOL(dib0090_dcc_freq); | ||
295 | |||
296 | static const u16 rf_ramp_pwm_cband[] = { | ||
297 | 0, /* max RF gain in 10th of dB */ | ||
298 | 0, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */ | ||
299 | 0, /* ramp_max = maximum X used on the ramp */ | ||
300 | (0 << 10) | 0, /* 0x2c, LNA 1 = 0dB */ | ||
301 | (0 << 10) | 0, /* 0x2d, LNA 1 */ | ||
302 | (0 << 10) | 0, /* 0x2e, LNA 2 = 0dB */ | ||
303 | (0 << 10) | 0, /* 0x2f, LNA 2 */ | ||
304 | (0 << 10) | 0, /* 0x30, LNA 3 = 0dB */ | ||
305 | (0 << 10) | 0, /* 0x31, LNA 3 */ | ||
306 | (0 << 10) | 0, /* GAIN_4_1, LNA 4 = 0dB */ | ||
307 | (0 << 10) | 0, /* GAIN_4_2, LNA 4 */ | ||
308 | }; | ||
309 | |||
310 | static const u16 rf_ramp_vhf[] = { | ||
311 | 412, /* max RF gain in 10th of dB */ | ||
312 | 132, 307, 127, /* LNA1, 13.2dB */ | ||
313 | 105, 412, 255, /* LNA2, 10.5dB */ | ||
314 | 50, 50, 127, /* LNA3, 5dB */ | ||
315 | 125, 175, 127, /* LNA4, 12.5dB */ | ||
316 | 0, 0, 127, /* CBAND, 0dB */ | ||
317 | }; | ||
318 | |||
319 | static const u16 rf_ramp_uhf[] = { | ||
320 | 412, /* max RF gain in 10th of dB */ | ||
321 | 132, 307, 127, /* LNA1 : total gain = 13.2dB, point on the ramp where this amp is full gain, value to write to get full gain */ | ||
322 | 105, 412, 255, /* LNA2 : 10.5 dB */ | ||
323 | 50, 50, 127, /* LNA3 : 5.0 dB */ | ||
324 | 125, 175, 127, /* LNA4 : 12.5 dB */ | ||
325 | 0, 0, 127, /* CBAND : 0.0 dB */ | ||
326 | }; | ||
327 | |||
328 | static const u16 rf_ramp_cband[] = { | ||
329 | 332, /* max RF gain in 10th of dB */ | ||
330 | 132, 252, 127, /* LNA1, dB */ | ||
331 | 80, 332, 255, /* LNA2, dB */ | ||
332 | 0, 0, 127, /* LNA3, dB */ | ||
333 | 0, 0, 127, /* LNA4, dB */ | ||
334 | 120, 120, 127, /* LT1 CBAND */ | ||
335 | }; | ||
336 | |||
337 | static const u16 rf_ramp_pwm_vhf[] = { | ||
338 | 404, /* max RF gain in 10th of dB */ | ||
339 | 25, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */ | ||
340 | 1011, /* ramp_max = maximum X used on the ramp */ | ||
341 | (6 << 10) | 417, /* 0x2c, LNA 1 = 13.2dB */ | ||
342 | (0 << 10) | 756, /* 0x2d, LNA 1 */ | ||
343 | (16 << 10) | 756, /* 0x2e, LNA 2 = 10.5dB */ | ||
344 | (0 << 10) | 1011, /* 0x2f, LNA 2 */ | ||
345 | (16 << 10) | 290, /* 0x30, LNA 3 = 5dB */ | ||
346 | (0 << 10) | 417, /* 0x31, LNA 3 */ | ||
347 | (7 << 10) | 0, /* GAIN_4_1, LNA 4 = 12.5dB */ | ||
348 | (0 << 10) | 290, /* GAIN_4_2, LNA 4 */ | ||
349 | }; | ||
350 | |||
351 | static const u16 rf_ramp_pwm_uhf[] = { | ||
352 | 404, /* max RF gain in 10th of dB */ | ||
353 | 25, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */ | ||
354 | 1011, /* ramp_max = maximum X used on the ramp */ | ||
355 | (6 << 10) | 417, /* 0x2c, LNA 1 = 13.2dB */ | ||
356 | (0 << 10) | 756, /* 0x2d, LNA 1 */ | ||
357 | (16 << 10) | 756, /* 0x2e, LNA 2 = 10.5dB */ | ||
358 | (0 << 10) | 1011, /* 0x2f, LNA 2 */ | ||
359 | (16 << 10) | 0, /* 0x30, LNA 3 = 5dB */ | ||
360 | (0 << 10) | 127, /* 0x31, LNA 3 */ | ||
361 | (7 << 10) | 127, /* GAIN_4_1, LNA 4 = 12.5dB */ | ||
362 | (0 << 10) | 417, /* GAIN_4_2, LNA 4 */ | ||
363 | }; | ||
364 | |||
365 | static const u16 bb_ramp_boost[] = { | ||
366 | 550, /* max BB gain in 10th of dB */ | ||
367 | 260, 260, 26, /* BB1, 26dB */ | ||
368 | 290, 550, 29, /* BB2, 29dB */ | ||
369 | }; | ||
370 | |||
371 | static const u16 bb_ramp_pwm_normal[] = { | ||
372 | 500, /* max RF gain in 10th of dB */ | ||
373 | 8, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x34 */ | ||
374 | 400, | ||
375 | (2 << 9) | 0, /* 0x35 = 21dB */ | ||
376 | (0 << 9) | 168, /* 0x36 */ | ||
377 | (2 << 9) | 168, /* 0x37 = 29dB */ | ||
378 | (0 << 9) | 400, /* 0x38 */ | ||
379 | }; | ||
380 | |||
381 | struct slope { | ||
382 | int16_t range; | ||
383 | int16_t slope; | ||
384 | }; | ||
385 | static u16 slopes_to_scale(const struct slope *slopes, u8 num, s16 val) | ||
386 | { | ||
387 | u8 i; | ||
388 | u16 rest; | ||
389 | u16 ret = 0; | ||
390 | for (i = 0; i < num; i++) { | ||
391 | if (val > slopes[i].range) | ||
392 | rest = slopes[i].range; | ||
393 | else | ||
394 | rest = val; | ||
395 | ret += (rest * slopes[i].slope) / slopes[i].range; | ||
396 | val -= rest; | ||
397 | } | ||
398 | return ret; | ||
399 | } | ||
400 | |||
401 | static const struct slope dib0090_wbd_slopes[3] = { | ||
402 | {66, 120}, /* -64,-52: offset - 65 */ | ||
403 | {600, 170}, /* -52,-35: 65 - 665 */ | ||
404 | {170, 250}, /* -45,-10: 665 - 835 */ | ||
405 | }; | ||
406 | |||
407 | static s16 dib0090_wbd_to_db(struct dib0090_state *state, u16 wbd) | ||
408 | { | ||
409 | wbd &= 0x3ff; | ||
410 | if (wbd < state->wbd_offset) | ||
411 | wbd = 0; | ||
412 | else | ||
413 | wbd -= state->wbd_offset; | ||
414 | /* -64dB is the floor */ | ||
415 | return -640 + (s16) slopes_to_scale(dib0090_wbd_slopes, ARRAY_SIZE(dib0090_wbd_slopes), wbd); | ||
416 | } | ||
417 | |||
418 | static void dib0090_wbd_target(struct dib0090_state *state, u32 rf) | ||
419 | { | ||
420 | u16 offset = 250; | ||
421 | |||
422 | /* TODO : DAB digital N+/-1 interferer perfs : offset = 10 */ | ||
423 | |||
424 | if (state->current_band == BAND_VHF) | ||
425 | offset = 650; | ||
426 | #ifndef FIRMWARE_FIREFLY | ||
427 | if (state->current_band == BAND_VHF) | ||
428 | offset = state->config->wbd_vhf_offset; | ||
429 | if (state->current_band == BAND_CBAND) | ||
430 | offset = state->config->wbd_cband_offset; | ||
431 | #endif | ||
432 | |||
433 | state->wbd_target = dib0090_wbd_to_db(state, state->wbd_offset + offset); | ||
434 | dprintk("wbd-target: %d dB", (u32) state->wbd_target); | ||
435 | } | ||
436 | |||
437 | static const int gain_reg_addr[4] = { | ||
438 | 0x08, 0x0a, 0x0f, 0x01 | ||
439 | }; | ||
440 | |||
441 | static void dib0090_gain_apply(struct dib0090_state *state, s16 gain_delta, s16 top_delta, u8 force) | ||
442 | { | ||
443 | u16 rf, bb, ref; | ||
444 | u16 i, v, gain_reg[4] = { 0 }, gain; | ||
445 | const u16 *g; | ||
446 | |||
447 | if (top_delta < -511) | ||
448 | top_delta = -511; | ||
449 | if (top_delta > 511) | ||
450 | top_delta = 511; | ||
451 | |||
452 | if (force) { | ||
453 | top_delta *= (1 << WBD_ALPHA); | ||
454 | gain_delta *= (1 << GAIN_ALPHA); | ||
455 | } | ||
456 | |||
457 | if (top_delta >= ((s16) (state->rf_ramp[0] << WBD_ALPHA) - state->rf_gain_limit)) /* overflow */ | ||
458 | state->rf_gain_limit = state->rf_ramp[0] << WBD_ALPHA; | ||
459 | else | ||
460 | state->rf_gain_limit += top_delta; | ||
461 | |||
462 | if (state->rf_gain_limit < 0) /*underflow */ | ||
463 | state->rf_gain_limit = 0; | ||
464 | |||
465 | /* use gain as a temporary variable and correct current_gain */ | ||
466 | gain = ((state->rf_gain_limit >> WBD_ALPHA) + state->bb_ramp[0]) << GAIN_ALPHA; | ||
467 | if (gain_delta >= ((s16) gain - state->current_gain)) /* overflow */ | ||
468 | state->current_gain = gain; | ||
469 | else | ||
470 | state->current_gain += gain_delta; | ||
471 | /* cannot be less than 0 (only if gain_delta is less than 0 we can have current_gain < 0) */ | ||
472 | if (state->current_gain < 0) | ||
473 | state->current_gain = 0; | ||
474 | |||
475 | /* now split total gain to rf and bb gain */ | ||
476 | gain = state->current_gain >> GAIN_ALPHA; | ||
477 | |||
478 | /* requested gain is bigger than rf gain limit - ACI/WBD adjustment */ | ||
479 | if (gain > (state->rf_gain_limit >> WBD_ALPHA)) { | ||
480 | rf = state->rf_gain_limit >> WBD_ALPHA; | ||
481 | bb = gain - rf; | ||
482 | if (bb > state->bb_ramp[0]) | ||
483 | bb = state->bb_ramp[0]; | ||
484 | } else { /* high signal level -> all gains put on RF */ | ||
485 | rf = gain; | ||
486 | bb = 0; | ||
487 | } | ||
488 | |||
489 | state->gain[0] = rf; | ||
490 | state->gain[1] = bb; | ||
491 | |||
492 | /* software ramp */ | ||
493 | /* Start with RF gains */ | ||
494 | g = state->rf_ramp + 1; /* point on RF LNA1 max gain */ | ||
495 | ref = rf; | ||
496 | for (i = 0; i < 7; i++) { /* Go over all amplifiers => 5RF amps + 2 BB amps = 7 amps */ | ||
497 | if (g[0] == 0 || ref < (g[1] - g[0])) /* if total gain of the current amp is null or this amp is not concerned because it starts to work from an higher gain value */ | ||
498 | v = 0; /* force the gain to write for the current amp to be null */ | ||
499 | else if (ref >= g[1]) /* Gain to set is higher than the high working point of this amp */ | ||
500 | v = g[2]; /* force this amp to be full gain */ | ||
501 | else /* compute the value to set to this amp because we are somewhere in his range */ | ||
502 | v = ((ref - (g[1] - g[0])) * g[2]) / g[0]; | ||
503 | |||
504 | if (i == 0) /* LNA 1 reg mapping */ | ||
505 | gain_reg[0] = v; | ||
506 | else if (i == 1) /* LNA 2 reg mapping */ | ||
507 | gain_reg[0] |= v << 7; | ||
508 | else if (i == 2) /* LNA 3 reg mapping */ | ||
509 | gain_reg[1] = v; | ||
510 | else if (i == 3) /* LNA 4 reg mapping */ | ||
511 | gain_reg[1] |= v << 7; | ||
512 | else if (i == 4) /* CBAND LNA reg mapping */ | ||
513 | gain_reg[2] = v | state->rf_lt_def; | ||
514 | else if (i == 5) /* BB gain 1 reg mapping */ | ||
515 | gain_reg[3] = v << 3; | ||
516 | else if (i == 6) /* BB gain 2 reg mapping */ | ||
517 | gain_reg[3] |= v << 8; | ||
518 | |||
519 | g += 3; /* go to next gain bloc */ | ||
520 | |||
521 | /* When RF is finished, start with BB */ | ||
522 | if (i == 4) { | ||
523 | g = state->bb_ramp + 1; /* point on BB gain 1 max gain */ | ||
524 | ref = bb; | ||
525 | } | ||
526 | } | ||
527 | gain_reg[3] |= state->bb_1_def; | ||
528 | gain_reg[3] |= ((bb % 10) * 100) / 125; | ||
529 | |||
530 | #ifdef DEBUG_AGC | ||
531 | dprintk("GA CALC: DB: %3d(rf) + %3d(bb) = %3d gain_reg[0]=%04x gain_reg[1]=%04x gain_reg[2]=%04x gain_reg[0]=%04x", rf, bb, rf + bb, | ||
532 | gain_reg[0], gain_reg[1], gain_reg[2], gain_reg[3]); | ||
533 | #endif | ||
534 | |||
535 | /* Write the amplifier regs */ | ||
536 | for (i = 0; i < 4; i++) { | ||
537 | v = gain_reg[i]; | ||
538 | if (force || state->gain_reg[i] != v) { | ||
539 | state->gain_reg[i] = v; | ||
540 | dib0090_write_reg(state, gain_reg_addr[i], v); | ||
541 | } | ||
542 | } | ||
543 | } | ||
544 | |||
545 | static void dib0090_set_boost(struct dib0090_state *state, int onoff) | ||
546 | { | ||
547 | state->bb_1_def &= 0xdfff; | ||
548 | state->bb_1_def |= onoff << 13; | ||
549 | } | ||
550 | |||
551 | static void dib0090_set_rframp(struct dib0090_state *state, const u16 * cfg) | ||
552 | { | ||
553 | state->rf_ramp = cfg; | ||
554 | } | ||
555 | |||
556 | static void dib0090_set_rframp_pwm(struct dib0090_state *state, const u16 * cfg) | ||
557 | { | ||
558 | state->rf_ramp = cfg; | ||
559 | |||
560 | dib0090_write_reg(state, 0x2a, 0xffff); | ||
561 | |||
562 | dprintk("total RF gain: %ddB, step: %d", (u32) cfg[0], dib0090_read_reg(state, 0x2a)); | ||
563 | |||
564 | dib0090_write_regs(state, 0x2c, cfg + 3, 6); | ||
565 | dib0090_write_regs(state, 0x3e, cfg + 9, 2); | ||
566 | } | ||
567 | |||
568 | static void dib0090_set_bbramp(struct dib0090_state *state, const u16 * cfg) | ||
569 | { | ||
570 | state->bb_ramp = cfg; | ||
571 | dib0090_set_boost(state, cfg[0] > 500); /* we want the boost if the gain is higher that 50dB */ | ||
572 | } | ||
573 | |||
574 | static void dib0090_set_bbramp_pwm(struct dib0090_state *state, const u16 * cfg) | ||
575 | { | ||
576 | state->bb_ramp = cfg; | ||
577 | |||
578 | dib0090_set_boost(state, cfg[0] > 500); /* we want the boost if the gain is higher that 50dB */ | ||
579 | |||
580 | dib0090_write_reg(state, 0x33, 0xffff); | ||
581 | dprintk("total BB gain: %ddB, step: %d", (u32) cfg[0], dib0090_read_reg(state, 0x33)); | ||
582 | dib0090_write_regs(state, 0x35, cfg + 3, 4); | ||
583 | } | ||
584 | |||
585 | void dib0090_pwm_gain_reset(struct dvb_frontend *fe) | ||
586 | { | ||
587 | struct dib0090_state *state = fe->tuner_priv; | ||
588 | /* reset the AGC */ | ||
589 | |||
590 | if (state->config->use_pwm_agc) { | ||
591 | #ifdef CONFIG_BAND_SBAND | ||
592 | if (state->current_band == BAND_SBAND) { | ||
593 | dib0090_set_rframp_pwm(state, rf_ramp_pwm_sband); | ||
594 | dib0090_set_bbramp_pwm(state, bb_ramp_pwm_boost); | ||
595 | } else | ||
596 | #endif | ||
597 | #ifdef CONFIG_BAND_CBAND | ||
598 | if (state->current_band == BAND_CBAND) { | ||
599 | dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband); | ||
600 | dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal); | ||
601 | } else | ||
602 | #endif | ||
603 | #ifdef CONFIG_BAND_VHF | ||
604 | if (state->current_band == BAND_VHF) { | ||
605 | dib0090_set_rframp_pwm(state, rf_ramp_pwm_vhf); | ||
606 | dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal); | ||
607 | } else | ||
608 | #endif | ||
609 | { | ||
610 | dib0090_set_rframp_pwm(state, rf_ramp_pwm_uhf); | ||
611 | dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal); | ||
612 | } | ||
613 | |||
614 | if (state->rf_ramp[0] != 0) | ||
615 | dib0090_write_reg(state, 0x32, (3 << 11)); | ||
616 | else | ||
617 | dib0090_write_reg(state, 0x32, (0 << 11)); | ||
618 | |||
619 | dib0090_write_reg(state, 0x39, (1 << 10)); | ||
620 | } | ||
621 | } | ||
622 | EXPORT_SYMBOL(dib0090_pwm_gain_reset); | ||
623 | |||
624 | int dib0090_gain_control(struct dvb_frontend *fe) | ||
625 | { | ||
626 | struct dib0090_state *state = fe->tuner_priv; | ||
627 | enum frontend_tune_state *tune_state = &state->tune_state; | ||
628 | int ret = 10; | ||
629 | |||
630 | u16 wbd_val = 0; | ||
631 | u8 apply_gain_immediatly = 1; | ||
632 | s16 wbd_error = 0, adc_error = 0; | ||
633 | |||
634 | if (*tune_state == CT_AGC_START) { | ||
635 | state->agc_freeze = 0; | ||
636 | dib0090_write_reg(state, 0x04, 0x0); | ||
637 | |||
638 | #ifdef CONFIG_BAND_SBAND | ||
639 | if (state->current_band == BAND_SBAND) { | ||
640 | dib0090_set_rframp(state, rf_ramp_sband); | ||
641 | dib0090_set_bbramp(state, bb_ramp_boost); | ||
642 | } else | ||
643 | #endif | ||
644 | #ifdef CONFIG_BAND_VHF | ||
645 | if (state->current_band == BAND_VHF) { | ||
646 | dib0090_set_rframp(state, rf_ramp_vhf); | ||
647 | dib0090_set_bbramp(state, bb_ramp_boost); | ||
648 | } else | ||
649 | #endif | ||
650 | #ifdef CONFIG_BAND_CBAND | ||
651 | if (state->current_band == BAND_CBAND) { | ||
652 | dib0090_set_rframp(state, rf_ramp_cband); | ||
653 | dib0090_set_bbramp(state, bb_ramp_boost); | ||
654 | } else | ||
655 | #endif | ||
656 | { | ||
657 | dib0090_set_rframp(state, rf_ramp_uhf); | ||
658 | dib0090_set_bbramp(state, bb_ramp_boost); | ||
659 | } | ||
660 | |||
661 | dib0090_write_reg(state, 0x32, 0); | ||
662 | dib0090_write_reg(state, 0x39, 0); | ||
663 | |||
664 | dib0090_wbd_target(state, state->current_rf); | ||
665 | |||
666 | state->rf_gain_limit = state->rf_ramp[0] << WBD_ALPHA; | ||
667 | state->current_gain = ((state->rf_ramp[0] + state->bb_ramp[0]) / 2) << GAIN_ALPHA; | ||
668 | |||
669 | *tune_state = CT_AGC_STEP_0; | ||
670 | } else if (!state->agc_freeze) { | ||
671 | s16 wbd; | ||
672 | |||
673 | int adc; | ||
674 | wbd_val = dib0090_read_reg(state, 0x1d); | ||
675 | |||
676 | /* read and calc the wbd power */ | ||
677 | wbd = dib0090_wbd_to_db(state, wbd_val); | ||
678 | wbd_error = state->wbd_target - wbd; | ||
679 | |||
680 | if (*tune_state == CT_AGC_STEP_0) { | ||
681 | if (wbd_error < 0 && state->rf_gain_limit > 0) { | ||
682 | #ifdef CONFIG_BAND_CBAND | ||
683 | /* in case of CBAND tune reduce first the lt_gain2 before adjusting the RF gain */ | ||
684 | u8 ltg2 = (state->rf_lt_def >> 10) & 0x7; | ||
685 | if (state->current_band == BAND_CBAND && ltg2) { | ||
686 | ltg2 >>= 1; | ||
687 | state->rf_lt_def &= ltg2 << 10; /* reduce in 3 steps from 7 to 0 */ | ||
688 | } | ||
689 | #endif | ||
690 | } else { | ||
691 | state->agc_step = 0; | ||
692 | *tune_state = CT_AGC_STEP_1; | ||
693 | } | ||
694 | } else { | ||
695 | /* calc the adc power */ | ||
696 | adc = state->config->get_adc_power(fe); | ||
697 | adc = (adc * ((s32) 355774) + (((s32) 1) << 20)) >> 21; /* included in [0:-700] */ | ||
698 | |||
699 | adc_error = (s16) (((s32) ADC_TARGET) - adc); | ||
700 | #ifdef CONFIG_STANDARD_DAB | ||
701 | if (state->fe->dtv_property_cache.delivery_system == STANDARD_DAB) | ||
702 | adc_error += 130; | ||
703 | #endif | ||
704 | #ifdef CONFIG_STANDARD_DVBT | ||
705 | if (state->fe->dtv_property_cache.delivery_system == STANDARD_DVBT && | ||
706 | (state->fe->dtv_property_cache.modulation == QAM_64 || state->fe->dtv_property_cache.modulation == QAM_16)) | ||
707 | adc_error += 60; | ||
708 | #endif | ||
709 | #ifdef CONFIG_SYS_ISDBT | ||
710 | if ((state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) && (((state->fe->dtv_property_cache.layer[0].segment_count > | ||
711 | 0) | ||
712 | && | ||
713 | ((state->fe->dtv_property_cache.layer[0].modulation == | ||
714 | QAM_64) | ||
715 | || (state->fe->dtv_property_cache.layer[0]. | ||
716 | modulation == QAM_16))) | ||
717 | || | ||
718 | ((state->fe->dtv_property_cache.layer[1].segment_count > | ||
719 | 0) | ||
720 | && | ||
721 | ((state->fe->dtv_property_cache.layer[1].modulation == | ||
722 | QAM_64) | ||
723 | || (state->fe->dtv_property_cache.layer[1]. | ||
724 | modulation == QAM_16))) | ||
725 | || | ||
726 | ((state->fe->dtv_property_cache.layer[2].segment_count > | ||
727 | 0) | ||
728 | && | ||
729 | ((state->fe->dtv_property_cache.layer[2].modulation == | ||
730 | QAM_64) | ||
731 | || (state->fe->dtv_property_cache.layer[2]. | ||
732 | modulation == QAM_16))) | ||
733 | ) | ||
734 | ) | ||
735 | adc_error += 60; | ||
736 | #endif | ||
737 | |||
738 | if (*tune_state == CT_AGC_STEP_1) { /* quickly go to the correct range of the ADC power */ | ||
739 | if (ABS(adc_error) < 50 || state->agc_step++ > 5) { | ||
740 | |||
741 | #ifdef CONFIG_STANDARD_DAB | ||
742 | if (state->fe->dtv_property_cache.delivery_system == STANDARD_DAB) { | ||
743 | dib0090_write_reg(state, 0x02, (1 << 15) | (15 << 11) | (31 << 6) | (63)); /* cap value = 63 : narrow BB filter : Fc = 1.8MHz */ | ||
744 | dib0090_write_reg(state, 0x04, 0x0); | ||
745 | } else | ||
746 | #endif | ||
747 | { | ||
748 | dib0090_write_reg(state, 0x02, (1 << 15) | (3 << 11) | (6 << 6) | (32)); | ||
749 | dib0090_write_reg(state, 0x04, 0x01); /*0 = 1KHz ; 1 = 150Hz ; 2 = 50Hz ; 3 = 50KHz ; 4 = servo fast */ | ||
750 | } | ||
751 | |||
752 | *tune_state = CT_AGC_STOP; | ||
753 | } | ||
754 | } else { | ||
755 | /* everything higher than or equal to CT_AGC_STOP means tracking */ | ||
756 | ret = 100; /* 10ms interval */ | ||
757 | apply_gain_immediatly = 0; | ||
758 | } | ||
759 | } | ||
760 | #ifdef DEBUG_AGC | ||
761 | dprintk | ||
762 | ("FE: %d, tune state %d, ADC = %3ddB (ADC err %3d) WBD %3ddB (WBD err %3d, WBD val SADC: %4d), RFGainLimit (TOP): %3d, signal: %3ddBm", | ||
763 | (u32) fe->id, (u32) *tune_state, (u32) adc, (u32) adc_error, (u32) wbd, (u32) wbd_error, (u32) wbd_val, | ||
764 | (u32) state->rf_gain_limit >> WBD_ALPHA, (s32) 200 + adc - (state->current_gain >> GAIN_ALPHA)); | ||
765 | #endif | ||
766 | } | ||
767 | |||
768 | /* apply gain */ | ||
769 | if (!state->agc_freeze) | ||
770 | dib0090_gain_apply(state, adc_error, wbd_error, apply_gain_immediatly); | ||
771 | return ret; | ||
772 | } | ||
773 | EXPORT_SYMBOL(dib0090_gain_control); | ||
774 | |||
775 | void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt) | ||
776 | { | ||
777 | struct dib0090_state *state = fe->tuner_priv; | ||
778 | if (rf) | ||
779 | *rf = state->gain[0]; | ||
780 | if (bb) | ||
781 | *bb = state->gain[1]; | ||
782 | if (rf_gain_limit) | ||
783 | *rf_gain_limit = state->rf_gain_limit; | ||
784 | if (rflt) | ||
785 | *rflt = (state->rf_lt_def >> 10) & 0x7; | ||
786 | } | ||
787 | EXPORT_SYMBOL(dib0090_get_current_gain); | ||
788 | |||
789 | u16 dib0090_get_wbd_offset(struct dvb_frontend *tuner) | ||
790 | { | ||
791 | struct dib0090_state *st = tuner->tuner_priv; | ||
792 | return st->wbd_offset; | ||
793 | } | ||
794 | EXPORT_SYMBOL(dib0090_get_wbd_offset); | ||
795 | |||
796 | static const u16 dib0090_defaults[] = { | ||
797 | |||
798 | 25, 0x01, | ||
799 | 0x0000, | ||
800 | 0x99a0, | ||
801 | 0x6008, | ||
802 | 0x0000, | ||
803 | 0x8acb, | ||
804 | 0x0000, | ||
805 | 0x0405, | ||
806 | 0x0000, | ||
807 | 0x0000, | ||
808 | 0x0000, | ||
809 | 0xb802, | ||
810 | 0x0300, | ||
811 | 0x2d12, | ||
812 | 0xbac0, | ||
813 | 0x7c00, | ||
814 | 0xdbb9, | ||
815 | 0x0954, | ||
816 | 0x0743, | ||
817 | 0x8000, | ||
818 | 0x0001, | ||
819 | 0x0040, | ||
820 | 0x0100, | ||
821 | 0x0000, | ||
822 | 0xe910, | ||
823 | 0x149e, | ||
824 | |||
825 | 1, 0x1c, | ||
826 | 0xff2d, | ||
827 | |||
828 | 1, 0x39, | ||
829 | 0x0000, | ||
830 | |||
831 | 1, 0x1b, | ||
832 | EN_IQADC | EN_BB | EN_BIAS | EN_DIGCLK | EN_PLL | EN_CRYSTAL, | ||
833 | 2, 0x1e, | ||
834 | 0x07FF, | ||
835 | 0x0007, | ||
836 | |||
837 | 1, 0x24, | ||
838 | EN_UHF | EN_CRYSTAL, | ||
839 | |||
840 | 2, 0x3c, | ||
841 | 0x3ff, | ||
842 | 0x111, | ||
843 | 0 | ||
844 | }; | ||
845 | |||
846 | static int dib0090_reset(struct dvb_frontend *fe) | ||
847 | { | ||
848 | struct dib0090_state *state = fe->tuner_priv; | ||
849 | u16 l, r, *n; | ||
850 | |||
851 | dib0090_reset_digital(fe, state->config); | ||
852 | state->revision = dib0090_identify(fe); | ||
853 | |||
854 | /* Revision definition */ | ||
855 | if (state->revision == 0xff) | ||
856 | return -EINVAL; | ||
857 | #ifdef EFUSE | ||
858 | else if ((state->revision & 0x1f) >= 3) /* Update the efuse : Only available for KROSUS > P1C */ | ||
859 | dib0090_set_EFUSE(state); | ||
860 | #endif | ||
861 | |||
862 | #ifdef CONFIG_TUNER_DIB0090_P1B_SUPPORT | ||
863 | if (!(state->revision & 0x1)) /* it is P1B - reset is already done */ | ||
864 | return 0; | ||
865 | #endif | ||
866 | |||
867 | /* Upload the default values */ | ||
868 | n = (u16 *) dib0090_defaults; | ||
869 | l = pgm_read_word(n++); | ||
870 | while (l) { | ||
871 | r = pgm_read_word(n++); | ||
872 | do { | ||
873 | /* DEBUG_TUNER */ | ||
874 | /* dprintk("%d, %d, %d", l, r, pgm_read_word(n)); */ | ||
875 | dib0090_write_reg(state, r, pgm_read_word(n++)); | ||
876 | r++; | ||
877 | } while (--l); | ||
878 | l = pgm_read_word(n++); | ||
879 | } | ||
880 | |||
881 | /* Congigure in function of the crystal */ | ||
882 | if (state->config->io.clock_khz >= 24000) | ||
883 | l = 1; | ||
884 | else | ||
885 | l = 2; | ||
886 | dib0090_write_reg(state, 0x14, l); | ||
887 | dprintk("Pll lock : %d", (dib0090_read_reg(state, 0x1a) >> 11) & 0x1); | ||
888 | |||
889 | state->reset = 3; /* enable iq-offset-calibration and wbd-calibration when tuning next time */ | ||
890 | |||
891 | return 0; | ||
892 | } | ||
893 | |||
894 | #define steps(u) (((u) > 15) ? ((u)-16) : (u)) | ||
895 | #define INTERN_WAIT 10 | ||
896 | static int dib0090_get_offset(struct dib0090_state *state, enum frontend_tune_state *tune_state) | ||
897 | { | ||
898 | int ret = INTERN_WAIT * 10; | ||
899 | |||
900 | switch (*tune_state) { | ||
901 | case CT_TUNER_STEP_2: | ||
902 | /* Turns to positive */ | ||
903 | dib0090_write_reg(state, 0x1f, 0x7); | ||
904 | *tune_state = CT_TUNER_STEP_3; | ||
905 | break; | ||
906 | |||
907 | case CT_TUNER_STEP_3: | ||
908 | state->adc_diff = dib0090_read_reg(state, 0x1d); | ||
909 | |||
910 | /* Turns to negative */ | ||
911 | dib0090_write_reg(state, 0x1f, 0x4); | ||
912 | *tune_state = CT_TUNER_STEP_4; | ||
913 | break; | ||
914 | |||
915 | case CT_TUNER_STEP_4: | ||
916 | state->adc_diff -= dib0090_read_reg(state, 0x1d); | ||
917 | *tune_state = CT_TUNER_STEP_5; | ||
918 | ret = 0; | ||
919 | break; | ||
920 | |||
921 | default: | ||
922 | break; | ||
923 | } | ||
924 | |||
925 | return ret; | ||
926 | } | ||
927 | |||
928 | struct dc_calibration { | ||
929 | uint8_t addr; | ||
930 | uint8_t offset; | ||
931 | uint8_t pga:1; | ||
932 | uint16_t bb1; | ||
933 | uint8_t i:1; | ||
934 | }; | ||
935 | |||
936 | static const struct dc_calibration dc_table[] = { | ||
937 | /* Step1 BB gain1= 26 with boost 1, gain 2 = 0 */ | ||
938 | {0x06, 5, 1, (1 << 13) | (0 << 8) | (26 << 3), 1}, | ||
939 | {0x07, 11, 1, (1 << 13) | (0 << 8) | (26 << 3), 0}, | ||
940 | /* Step 2 BB gain 1 = 26 with boost = 1 & gain 2 = 29 */ | ||
941 | {0x06, 0, 0, (1 << 13) | (29 << 8) | (26 << 3), 1}, | ||
942 | {0x06, 10, 0, (1 << 13) | (29 << 8) | (26 << 3), 0}, | ||
943 | {0}, | ||
944 | }; | ||
945 | |||
946 | static void dib0090_set_trim(struct dib0090_state *state) | ||
947 | { | ||
948 | u16 *val; | ||
949 | |||
950 | if (state->dc->addr == 0x07) | ||
951 | val = &state->bb7; | ||
952 | else | ||
953 | val = &state->bb6; | ||
954 | |||
955 | *val &= ~(0x1f << state->dc->offset); | ||
956 | *val |= state->step << state->dc->offset; | ||
957 | |||
958 | dib0090_write_reg(state, state->dc->addr, *val); | ||
959 | } | ||
960 | |||
961 | static int dib0090_dc_offset_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state) | ||
962 | { | ||
963 | int ret = 0; | ||
964 | |||
965 | switch (*tune_state) { | ||
966 | |||
967 | case CT_TUNER_START: | ||
968 | /* init */ | ||
969 | dprintk("Internal DC calibration"); | ||
970 | |||
971 | /* the LNA is off */ | ||
972 | dib0090_write_reg(state, 0x24, 0x02ed); | ||
973 | |||
974 | /* force vcm2 = 0.8V */ | ||
975 | state->bb6 = 0; | ||
976 | state->bb7 = 0x040d; | ||
977 | |||
978 | state->dc = dc_table; | ||
979 | |||
980 | *tune_state = CT_TUNER_STEP_0; | ||
981 | |||
982 | /* fall through */ | ||
983 | |||
984 | case CT_TUNER_STEP_0: | ||
985 | dib0090_write_reg(state, 0x01, state->dc->bb1); | ||
986 | dib0090_write_reg(state, 0x07, state->bb7 | (state->dc->i << 7)); | ||
987 | |||
988 | state->step = 0; | ||
989 | |||
990 | state->min_adc_diff = 1023; | ||
991 | |||
992 | *tune_state = CT_TUNER_STEP_1; | ||
993 | ret = 50; | ||
994 | break; | ||
995 | |||
996 | case CT_TUNER_STEP_1: | ||
997 | dib0090_set_trim(state); | ||
998 | |||
999 | *tune_state = CT_TUNER_STEP_2; | ||
1000 | break; | ||
1001 | |||
1002 | case CT_TUNER_STEP_2: | ||
1003 | case CT_TUNER_STEP_3: | ||
1004 | case CT_TUNER_STEP_4: | ||
1005 | ret = dib0090_get_offset(state, tune_state); | ||
1006 | break; | ||
1007 | |||
1008 | case CT_TUNER_STEP_5: /* found an offset */ | ||
1009 | dprintk("FE%d: IQC read=%d, current=%x", state->fe->id, (u32) state->adc_diff, state->step); | ||
1010 | |||
1011 | /* first turn for this frequency */ | ||
1012 | if (state->step == 0) { | ||
1013 | if (state->dc->pga && state->adc_diff < 0) | ||
1014 | state->step = 0x10; | ||
1015 | if (state->dc->pga == 0 && state->adc_diff > 0) | ||
1016 | state->step = 0x10; | ||
1017 | } | ||
1018 | |||
1019 | state->adc_diff = ABS(state->adc_diff); | ||
1020 | |||
1021 | if (state->adc_diff < state->min_adc_diff && steps(state->step) < 15) { /* stop search when the delta to 0 is increasing */ | ||
1022 | state->step++; | ||
1023 | state->min_adc_diff = state->adc_diff; | ||
1024 | *tune_state = CT_TUNER_STEP_1; | ||
1025 | } else { | ||
1026 | |||
1027 | /* the minimum was what we have seen in the step before */ | ||
1028 | state->step--; | ||
1029 | dib0090_set_trim(state); | ||
1030 | |||
1031 | dprintk("FE%d: BB Offset Cal, BBreg=%hd,Offset=%hd,Value Set=%hd", state->fe->id, state->dc->addr, state->adc_diff, | ||
1032 | state->step); | ||
1033 | |||
1034 | state->dc++; | ||
1035 | if (state->dc->addr == 0) /* done */ | ||
1036 | *tune_state = CT_TUNER_STEP_6; | ||
1037 | else | ||
1038 | *tune_state = CT_TUNER_STEP_0; | ||
1039 | |||
1040 | } | ||
1041 | break; | ||
1042 | |||
1043 | case CT_TUNER_STEP_6: | ||
1044 | dib0090_write_reg(state, 0x07, state->bb7 & ~0x0008); | ||
1045 | dib0090_write_reg(state, 0x1f, 0x7); | ||
1046 | *tune_state = CT_TUNER_START; /* reset done -> real tuning can now begin */ | ||
1047 | state->reset &= ~0x1; | ||
1048 | default: | ||
1049 | break; | ||
1050 | } | ||
1051 | return ret; | ||
1052 | } | ||
1053 | |||
1054 | static int dib0090_wbd_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state) | ||
1055 | { | ||
1056 | switch (*tune_state) { | ||
1057 | case CT_TUNER_START: | ||
1058 | /* WBD-mode=log, Bias=2, Gain=6, Testmode=1, en=1, WBDMUX=1 */ | ||
1059 | dib0090_write_reg(state, 0x10, 0xdb09 | (1 << 10)); | ||
1060 | dib0090_write_reg(state, 0x24, EN_UHF & 0x0fff); | ||
1061 | |||
1062 | *tune_state = CT_TUNER_STEP_0; | ||
1063 | return 90; /* wait for the WBDMUX to switch and for the ADC to sample */ | ||
1064 | case CT_TUNER_STEP_0: | ||
1065 | state->wbd_offset = dib0090_read_reg(state, 0x1d); | ||
1066 | dprintk("WBD calibration offset = %d", state->wbd_offset); | ||
1067 | |||
1068 | *tune_state = CT_TUNER_START; /* reset done -> real tuning can now begin */ | ||
1069 | state->reset &= ~0x2; | ||
1070 | break; | ||
1071 | default: | ||
1072 | break; | ||
1073 | } | ||
1074 | return 0; | ||
1075 | } | ||
1076 | |||
1077 | static void dib0090_set_bandwidth(struct dib0090_state *state) | ||
1078 | { | ||
1079 | u16 tmp; | ||
1080 | |||
1081 | if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 5000) | ||
1082 | tmp = (3 << 14); | ||
1083 | else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 6000) | ||
1084 | tmp = (2 << 14); | ||
1085 | else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 7000) | ||
1086 | tmp = (1 << 14); | ||
1087 | else | ||
1088 | tmp = (0 << 14); | ||
1089 | |||
1090 | state->bb_1_def &= 0x3fff; | ||
1091 | state->bb_1_def |= tmp; | ||
1092 | |||
1093 | dib0090_write_reg(state, 0x01, state->bb_1_def); /* be sure that we have the right bb-filter */ | ||
1094 | } | ||
1095 | |||
1096 | static const struct dib0090_pll dib0090_pll_table[] = { | ||
1097 | #ifdef CONFIG_BAND_CBAND | ||
1098 | {56000, 0, 9, 48, 6}, | ||
1099 | {70000, 1, 9, 48, 6}, | ||
1100 | {87000, 0, 8, 32, 4}, | ||
1101 | {105000, 1, 8, 32, 4}, | ||
1102 | {115000, 0, 7, 24, 6}, | ||
1103 | {140000, 1, 7, 24, 6}, | ||
1104 | {170000, 0, 6, 16, 4}, | ||
1105 | #endif | ||
1106 | #ifdef CONFIG_BAND_VHF | ||
1107 | {200000, 1, 6, 16, 4}, | ||
1108 | {230000, 0, 5, 12, 6}, | ||
1109 | {280000, 1, 5, 12, 6}, | ||
1110 | {340000, 0, 4, 8, 4}, | ||
1111 | {380000, 1, 4, 8, 4}, | ||
1112 | {450000, 0, 3, 6, 6}, | ||
1113 | #endif | ||
1114 | #ifdef CONFIG_BAND_UHF | ||
1115 | {580000, 1, 3, 6, 6}, | ||
1116 | {700000, 0, 2, 4, 4}, | ||
1117 | {860000, 1, 2, 4, 4}, | ||
1118 | #endif | ||
1119 | #ifdef CONFIG_BAND_LBAND | ||
1120 | {1800000, 1, 0, 2, 4}, | ||
1121 | #endif | ||
1122 | #ifdef CONFIG_BAND_SBAND | ||
1123 | {2900000, 0, 14, 1, 4}, | ||
1124 | #endif | ||
1125 | }; | ||
1126 | |||
1127 | static const struct dib0090_tuning dib0090_tuning_table_fm_vhf_on_cband[] = { | ||
1128 | |||
1129 | #ifdef CONFIG_BAND_CBAND | ||
1130 | {184000, 4, 1, 15, 0x280, 0x2912, 0xb94e, EN_CAB}, | ||
1131 | {227000, 4, 3, 15, 0x280, 0x2912, 0xb94e, EN_CAB}, | ||
1132 | {380000, 4, 7, 15, 0x280, 0x2912, 0xb94e, EN_CAB}, | ||
1133 | #endif | ||
1134 | #ifdef CONFIG_BAND_UHF | ||
1135 | {520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, | ||
1136 | {550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, | ||
1137 | {650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, | ||
1138 | {750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, | ||
1139 | {850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, | ||
1140 | {900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, | ||
1141 | #endif | ||
1142 | #ifdef CONFIG_BAND_LBAND | ||
1143 | {1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD}, | ||
1144 | {1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD}, | ||
1145 | {1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD}, | ||
1146 | #endif | ||
1147 | #ifdef CONFIG_BAND_SBAND | ||
1148 | {2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD}, | ||
1149 | {2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD}, | ||
1150 | #endif | ||
1151 | }; | ||
1152 | |||
1153 | static const struct dib0090_tuning dib0090_tuning_table[] = { | ||
1154 | |||
1155 | #ifdef CONFIG_BAND_CBAND | ||
1156 | {170000, 4, 1, 15, 0x280, 0x2912, 0xb94e, EN_CAB}, | ||
1157 | #endif | ||
1158 | #ifdef CONFIG_BAND_VHF | ||
1159 | {184000, 1, 1, 15, 0x300, 0x4d12, 0xb94e, EN_VHF}, | ||
1160 | {227000, 1, 3, 15, 0x300, 0x4d12, 0xb94e, EN_VHF}, | ||
1161 | {380000, 1, 7, 15, 0x300, 0x4d12, 0xb94e, EN_VHF}, | ||
1162 | #endif | ||
1163 | #ifdef CONFIG_BAND_UHF | ||
1164 | {520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, | ||
1165 | {550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, | ||
1166 | {650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, | ||
1167 | {750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, | ||
1168 | {850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, | ||
1169 | {900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, | ||
1170 | #endif | ||
1171 | #ifdef CONFIG_BAND_LBAND | ||
1172 | {1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD}, | ||
1173 | {1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD}, | ||
1174 | {1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD}, | ||
1175 | #endif | ||
1176 | #ifdef CONFIG_BAND_SBAND | ||
1177 | {2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD}, | ||
1178 | {2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD}, | ||
1179 | #endif | ||
1180 | }; | ||
1181 | |||
1182 | #define WBD 0x781 /* 1 1 1 1 0000 0 0 1 */ | ||
1183 | static int dib0090_tune(struct dvb_frontend *fe) | ||
1184 | { | ||
1185 | struct dib0090_state *state = fe->tuner_priv; | ||
1186 | const struct dib0090_tuning *tune = state->current_tune_table_index; | ||
1187 | const struct dib0090_pll *pll = state->current_pll_table_index; | ||
1188 | enum frontend_tune_state *tune_state = &state->tune_state; | ||
1189 | |||
1190 | u32 rf; | ||
1191 | u16 lo4 = 0xe900, lo5, lo6, Den; | ||
1192 | u32 FBDiv, Rest, FREF, VCOF_kHz = 0; | ||
1193 | u16 tmp, adc; | ||
1194 | int8_t step_sign; | ||
1195 | int ret = 10; /* 1ms is the default delay most of the time */ | ||
1196 | u8 c, i; | ||
1197 | |||
1198 | state->current_band = (u8) BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000); | ||
1199 | rf = fe->dtv_property_cache.frequency / 1000 + (state->current_band == | ||
1200 | BAND_UHF ? state->config->freq_offset_khz_uhf : state->config->freq_offset_khz_vhf); | ||
1201 | /* in any case we first need to do a reset if needed */ | ||
1202 | if (state->reset & 0x1) | ||
1203 | return dib0090_dc_offset_calibration(state, tune_state); | ||
1204 | else if (state->reset & 0x2) | ||
1205 | return dib0090_wbd_calibration(state, tune_state); | ||
1206 | |||
1207 | /************************* VCO ***************************/ | ||
1208 | /* Default values for FG */ | ||
1209 | /* from these are needed : */ | ||
1210 | /* Cp,HFdiv,VCOband,SD,Num,Den,FB and REFDiv */ | ||
1211 | |||
1212 | #ifdef CONFIG_SYS_ISDBT | ||
1213 | if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1) | ||
1214 | rf += 850; | ||
1215 | #endif | ||
1216 | |||
1217 | if (state->current_rf != rf) { | ||
1218 | state->tuner_is_tuned = 0; | ||
1219 | |||
1220 | tune = dib0090_tuning_table; | ||
1221 | |||
1222 | tmp = (state->revision >> 5) & 0x7; | ||
1223 | if (tmp == 0x4 || tmp == 0x7) { | ||
1224 | /* CBAND tuner version for VHF */ | ||
1225 | if (state->current_band == BAND_FM || state->current_band == BAND_VHF) { | ||
1226 | /* Force CBAND */ | ||
1227 | state->current_band = BAND_CBAND; | ||
1228 | tune = dib0090_tuning_table_fm_vhf_on_cband; | ||
1229 | } | ||
1230 | } | ||
1231 | |||
1232 | pll = dib0090_pll_table; | ||
1233 | /* Look for the interval */ | ||
1234 | while (rf > tune->max_freq) | ||
1235 | tune++; | ||
1236 | while (rf > pll->max_freq) | ||
1237 | pll++; | ||
1238 | state->current_tune_table_index = tune; | ||
1239 | state->current_pll_table_index = pll; | ||
1240 | } | ||
1241 | |||
1242 | if (*tune_state == CT_TUNER_START) { | ||
1243 | |||
1244 | if (state->tuner_is_tuned == 0) | ||
1245 | state->current_rf = 0; | ||
1246 | |||
1247 | if (state->current_rf != rf) { | ||
1248 | |||
1249 | dib0090_write_reg(state, 0x0b, 0xb800 | (tune->switch_trim)); | ||
1250 | |||
1251 | /* external loop filter, otherwise: | ||
1252 | * lo5 = (0 << 15) | (0 << 12) | (0 << 11) | (3 << 9) | (4 << 6) | (3 << 4) | 4; | ||
1253 | * lo6 = 0x0e34 */ | ||
1254 | if (pll->vco_band) | ||
1255 | lo5 = 0x049e; | ||
1256 | else if (state->config->analog_output) | ||
1257 | lo5 = 0x041d; | ||
1258 | else | ||
1259 | lo5 = 0x041c; | ||
1260 | |||
1261 | lo5 |= (pll->hfdiv_code << 11) | (pll->vco_band << 7); /* bit 15 is the split to the slave, we do not do it here */ | ||
1262 | |||
1263 | if (!state->config->io.pll_int_loop_filt) | ||
1264 | lo6 = 0xff28; | ||
1265 | else | ||
1266 | lo6 = (state->config->io.pll_int_loop_filt << 3); | ||
1267 | |||
1268 | VCOF_kHz = (pll->hfdiv * rf) * 2; | ||
1269 | |||
1270 | FREF = state->config->io.clock_khz; | ||
1271 | |||
1272 | FBDiv = (VCOF_kHz / pll->topresc / FREF); | ||
1273 | Rest = (VCOF_kHz / pll->topresc) - FBDiv * FREF; | ||
1274 | |||
1275 | if (Rest < LPF) | ||
1276 | Rest = 0; | ||
1277 | else if (Rest < 2 * LPF) | ||
1278 | Rest = 2 * LPF; | ||
1279 | else if (Rest > (FREF - LPF)) { | ||
1280 | Rest = 0; | ||
1281 | FBDiv += 1; | ||
1282 | } else if (Rest > (FREF - 2 * LPF)) | ||
1283 | Rest = FREF - 2 * LPF; | ||
1284 | Rest = (Rest * 6528) / (FREF / 10); | ||
1285 | |||
1286 | Den = 1; | ||
1287 | |||
1288 | dprintk(" ***** ******* Rest value = %d", Rest); | ||
1289 | |||
1290 | if (Rest > 0) { | ||
1291 | if (state->config->analog_output) | ||
1292 | lo6 |= (1 << 2) | 2; | ||
1293 | else | ||
1294 | lo6 |= (1 << 2) | 1; | ||
1295 | Den = 255; | ||
1296 | } | ||
1297 | #ifdef CONFIG_BAND_SBAND | ||
1298 | if (state->current_band == BAND_SBAND) | ||
1299 | lo6 &= 0xfffb; | ||
1300 | #endif | ||
1301 | |||
1302 | dib0090_write_reg(state, 0x15, (u16) FBDiv); | ||
1303 | |||
1304 | dib0090_write_reg(state, 0x16, (Den << 8) | 1); | ||
1305 | |||
1306 | dib0090_write_reg(state, 0x17, (u16) Rest); | ||
1307 | |||
1308 | dib0090_write_reg(state, 0x19, lo5); | ||
1309 | |||
1310 | dib0090_write_reg(state, 0x1c, lo6); | ||
1311 | |||
1312 | lo6 = tune->tuner_enable; | ||
1313 | if (state->config->analog_output) | ||
1314 | lo6 = (lo6 & 0xff9f) | 0x2; | ||
1315 | |||
1316 | dib0090_write_reg(state, 0x24, lo6 | EN_LO | ||
1317 | #ifdef CONFIG_DIB0090_USE_PWM_AGC | ||
1318 | | state->config->use_pwm_agc * EN_CRYSTAL | ||
1319 | #endif | ||
1320 | ); | ||
1321 | |||
1322 | state->current_rf = rf; | ||
1323 | |||
1324 | /* prepare a complete captrim */ | ||
1325 | state->step = state->captrim = state->fcaptrim = 64; | ||
1326 | |||
1327 | } else { /* we are already tuned to this frequency - the configuration is correct */ | ||
1328 | |||
1329 | /* do a minimal captrim even if the frequency has not changed */ | ||
1330 | state->step = 4; | ||
1331 | state->captrim = state->fcaptrim = dib0090_read_reg(state, 0x18) & 0x7f; | ||
1332 | } | ||
1333 | state->adc_diff = 3000; | ||
1334 | |||
1335 | dib0090_write_reg(state, 0x10, 0x2B1); | ||
1336 | |||
1337 | dib0090_write_reg(state, 0x1e, 0x0032); | ||
1338 | |||
1339 | ret = 20; | ||
1340 | *tune_state = CT_TUNER_STEP_1; | ||
1341 | } else if (*tune_state == CT_TUNER_STEP_0) { | ||
1342 | /* nothing */ | ||
1343 | } else if (*tune_state == CT_TUNER_STEP_1) { | ||
1344 | state->step /= 2; | ||
1345 | dib0090_write_reg(state, 0x18, lo4 | state->captrim); | ||
1346 | *tune_state = CT_TUNER_STEP_2; | ||
1347 | } else if (*tune_state == CT_TUNER_STEP_2) { | ||
1348 | |||
1349 | adc = dib0090_read_reg(state, 0x1d); | ||
1350 | dprintk("FE %d CAPTRIM=%d; ADC = %d (ADC) & %dmV", (u32) fe->id, (u32) state->captrim, (u32) adc, | ||
1351 | (u32) (adc) * (u32) 1800 / (u32) 1024); | ||
1352 | |||
1353 | if (adc >= 400) { | ||
1354 | adc -= 400; | ||
1355 | step_sign = -1; | ||
1356 | } else { | ||
1357 | adc = 400 - adc; | ||
1358 | step_sign = 1; | ||
1359 | } | ||
1360 | |||
1361 | if (adc < state->adc_diff) { | ||
1362 | dprintk("FE %d CAPTRIM=%d is closer to target (%d/%d)", (u32) fe->id, (u32) state->captrim, (u32) adc, (u32) state->adc_diff); | ||
1363 | state->adc_diff = adc; | ||
1364 | state->fcaptrim = state->captrim; | ||
1365 | |||
1366 | } | ||
1367 | |||
1368 | state->captrim += step_sign * state->step; | ||
1369 | if (state->step >= 1) | ||
1370 | *tune_state = CT_TUNER_STEP_1; | ||
1371 | else | ||
1372 | *tune_state = CT_TUNER_STEP_3; | ||
1373 | |||
1374 | ret = 15; | ||
1375 | } else if (*tune_state == CT_TUNER_STEP_3) { | ||
1376 | /*write the final cptrim config */ | ||
1377 | dib0090_write_reg(state, 0x18, lo4 | state->fcaptrim); | ||
1378 | |||
1379 | #ifdef CONFIG_TUNER_DIB0090_CAPTRIM_MEMORY | ||
1380 | state->memory[state->memory_index].cap = state->fcaptrim; | ||
1381 | #endif | ||
1382 | |||
1383 | *tune_state = CT_TUNER_STEP_4; | ||
1384 | } else if (*tune_state == CT_TUNER_STEP_4) { | ||
1385 | dib0090_write_reg(state, 0x1e, 0x07ff); | ||
1386 | |||
1387 | dprintk("FE %d Final Captrim: %d", (u32) fe->id, (u32) state->fcaptrim); | ||
1388 | dprintk("FE %d HFDIV code: %d", (u32) fe->id, (u32) pll->hfdiv_code); | ||
1389 | dprintk("FE %d VCO = %d", (u32) fe->id, (u32) pll->vco_band); | ||
1390 | dprintk("FE %d VCOF in kHz: %d ((%d*%d) << 1))", (u32) fe->id, (u32) ((pll->hfdiv * rf) * 2), (u32) pll->hfdiv, (u32) rf); | ||
1391 | dprintk("FE %d REFDIV: %d, FREF: %d", (u32) fe->id, (u32) 1, (u32) state->config->io.clock_khz); | ||
1392 | dprintk("FE %d FBDIV: %d, Rest: %d", (u32) fe->id, (u32) dib0090_read_reg(state, 0x15), (u32) dib0090_read_reg(state, 0x17)); | ||
1393 | dprintk("FE %d Num: %d, Den: %d, SD: %d", (u32) fe->id, (u32) dib0090_read_reg(state, 0x17), | ||
1394 | (u32) (dib0090_read_reg(state, 0x16) >> 8), (u32) dib0090_read_reg(state, 0x1c) & 0x3); | ||
1395 | |||
1396 | c = 4; | ||
1397 | i = 3; | ||
1398 | #if defined(CONFIG_BAND_LBAND) || defined(CONFIG_BAND_SBAND) | ||
1399 | if ((state->current_band == BAND_LBAND) || (state->current_band == BAND_SBAND)) { | ||
1400 | c = 2; | ||
1401 | i = 2; | ||
1402 | } | ||
1403 | #endif | ||
1404 | dib0090_write_reg(state, 0x10, (c << 13) | (i << 11) | (WBD | ||
1405 | #ifdef CONFIG_DIB0090_USE_PWM_AGC | ||
1406 | | (state->config->use_pwm_agc << 1) | ||
1407 | #endif | ||
1408 | )); | ||
1409 | dib0090_write_reg(state, 0x09, (tune->lna_tune << 5) | (tune->lna_bias << 0)); | ||
1410 | dib0090_write_reg(state, 0x0c, tune->v2i); | ||
1411 | dib0090_write_reg(state, 0x0d, tune->mix); | ||
1412 | dib0090_write_reg(state, 0x0e, tune->load); | ||
1413 | |||
1414 | *tune_state = CT_TUNER_STEP_5; | ||
1415 | } else if (*tune_state == CT_TUNER_STEP_5) { | ||
1416 | |||
1417 | /* initialize the lt gain register */ | ||
1418 | state->rf_lt_def = 0x7c00; | ||
1419 | dib0090_write_reg(state, 0x0f, state->rf_lt_def); | ||
1420 | |||
1421 | dib0090_set_bandwidth(state); | ||
1422 | state->tuner_is_tuned = 1; | ||
1423 | *tune_state = CT_TUNER_STOP; | ||
1424 | } else | ||
1425 | ret = FE_CALLBACK_TIME_NEVER; | ||
1426 | return ret; | ||
1427 | } | ||
1428 | |||
1429 | static int dib0090_release(struct dvb_frontend *fe) | ||
1430 | { | ||
1431 | kfree(fe->tuner_priv); | ||
1432 | fe->tuner_priv = NULL; | ||
1433 | return 0; | ||
1434 | } | ||
1435 | |||
1436 | enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe) | ||
1437 | { | ||
1438 | struct dib0090_state *state = fe->tuner_priv; | ||
1439 | |||
1440 | return state->tune_state; | ||
1441 | } | ||
1442 | EXPORT_SYMBOL(dib0090_get_tune_state); | ||
1443 | |||
1444 | int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state) | ||
1445 | { | ||
1446 | struct dib0090_state *state = fe->tuner_priv; | ||
1447 | |||
1448 | state->tune_state = tune_state; | ||
1449 | return 0; | ||
1450 | } | ||
1451 | EXPORT_SYMBOL(dib0090_set_tune_state); | ||
1452 | |||
1453 | static int dib0090_get_frequency(struct dvb_frontend *fe, u32 * frequency) | ||
1454 | { | ||
1455 | struct dib0090_state *state = fe->tuner_priv; | ||
1456 | |||
1457 | *frequency = 1000 * state->current_rf; | ||
1458 | return 0; | ||
1459 | } | ||
1460 | |||
1461 | static int dib0090_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) | ||
1462 | { | ||
1463 | struct dib0090_state *state = fe->tuner_priv; | ||
1464 | uint32_t ret; | ||
1465 | |||
1466 | state->tune_state = CT_TUNER_START; | ||
1467 | |||
1468 | do { | ||
1469 | ret = dib0090_tune(fe); | ||
1470 | if (ret != FE_CALLBACK_TIME_NEVER) | ||
1471 | msleep(ret / 10); | ||
1472 | else | ||
1473 | break; | ||
1474 | } while (state->tune_state != CT_TUNER_STOP); | ||
1475 | |||
1476 | return 0; | ||
1477 | } | ||
1478 | |||
1479 | static const struct dvb_tuner_ops dib0090_ops = { | ||
1480 | .info = { | ||
1481 | .name = "DiBcom DiB0090", | ||
1482 | .frequency_min = 45000000, | ||
1483 | .frequency_max = 860000000, | ||
1484 | .frequency_step = 1000, | ||
1485 | }, | ||
1486 | .release = dib0090_release, | ||
1487 | |||
1488 | .init = dib0090_wakeup, | ||
1489 | .sleep = dib0090_sleep, | ||
1490 | .set_params = dib0090_set_params, | ||
1491 | .get_frequency = dib0090_get_frequency, | ||
1492 | }; | ||
1493 | |||
1494 | struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config) | ||
1495 | { | ||
1496 | struct dib0090_state *st = kzalloc(sizeof(struct dib0090_state), GFP_KERNEL); | ||
1497 | if (st == NULL) | ||
1498 | return NULL; | ||
1499 | |||
1500 | st->config = config; | ||
1501 | st->i2c = i2c; | ||
1502 | st->fe = fe; | ||
1503 | fe->tuner_priv = st; | ||
1504 | |||
1505 | if (dib0090_reset(fe) != 0) | ||
1506 | goto free_mem; | ||
1507 | |||
1508 | printk(KERN_INFO "DiB0090: successfully identified\n"); | ||
1509 | memcpy(&fe->ops.tuner_ops, &dib0090_ops, sizeof(struct dvb_tuner_ops)); | ||
1510 | |||
1511 | return fe; | ||
1512 | free_mem: | ||
1513 | kfree(st); | ||
1514 | fe->tuner_priv = NULL; | ||
1515 | return NULL; | ||
1516 | } | ||
1517 | EXPORT_SYMBOL(dib0090_register); | ||
1518 | |||
1519 | MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>"); | ||
1520 | MODULE_AUTHOR("Olivier Grenie <olivier.grenie@dibcom.fr>"); | ||
1521 | MODULE_DESCRIPTION("Driver for the DiBcom 0090 base-band RF Tuner"); | ||
1522 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/frontends/dib0090.h b/drivers/media/dvb/frontends/dib0090.h new file mode 100644 index 000000000000..aa7711e88776 --- /dev/null +++ b/drivers/media/dvb/frontends/dib0090.h | |||
@@ -0,0 +1,108 @@ | |||
1 | /* | ||
2 | * Linux-DVB Driver for DiBcom's DiB0090 base-band RF Tuner. | ||
3 | * | ||
4 | * Copyright (C) 2005-7 DiBcom (http://www.dibcom.fr/) | ||
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 as | ||
8 | * published by the Free Software Foundation, version 2. | ||
9 | */ | ||
10 | #ifndef DIB0090_H | ||
11 | #define DIB0090_H | ||
12 | |||
13 | struct dvb_frontend; | ||
14 | struct i2c_adapter; | ||
15 | |||
16 | #define DEFAULT_DIB0090_I2C_ADDRESS 0x60 | ||
17 | |||
18 | struct dib0090_io_config { | ||
19 | u32 clock_khz; | ||
20 | |||
21 | u8 pll_bypass:1; | ||
22 | u8 pll_range:1; | ||
23 | u8 pll_prediv:6; | ||
24 | u8 pll_loopdiv:6; | ||
25 | |||
26 | u8 adc_clock_ratio; /* valid is 8, 7 ,6 */ | ||
27 | u16 pll_int_loop_filt; | ||
28 | }; | ||
29 | |||
30 | struct dib0090_config { | ||
31 | struct dib0090_io_config io; | ||
32 | int (*reset) (struct dvb_frontend *, int); | ||
33 | int (*sleep) (struct dvb_frontend *, int); | ||
34 | |||
35 | /* offset in kHz */ | ||
36 | int freq_offset_khz_uhf; | ||
37 | int freq_offset_khz_vhf; | ||
38 | |||
39 | int (*get_adc_power) (struct dvb_frontend *); | ||
40 | |||
41 | u8 clkouttobamse:1; /* activate or deactivate clock output */ | ||
42 | u8 analog_output; | ||
43 | |||
44 | u8 i2c_address; | ||
45 | /* add drives and other things if necessary */ | ||
46 | u16 wbd_vhf_offset; | ||
47 | u16 wbd_cband_offset; | ||
48 | u8 use_pwm_agc; | ||
49 | u8 clkoutdrive; | ||
50 | }; | ||
51 | |||
52 | #if defined(CONFIG_DVB_TUNER_DIB0090) || (defined(CONFIG_DVB_TUNER_DIB0090_MODULE) && defined(MODULE)) | ||
53 | extern struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config); | ||
54 | extern void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast); | ||
55 | extern void dib0090_pwm_gain_reset(struct dvb_frontend *fe); | ||
56 | extern u16 dib0090_get_wbd_offset(struct dvb_frontend *tuner); | ||
57 | extern int dib0090_gain_control(struct dvb_frontend *fe); | ||
58 | extern enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe); | ||
59 | extern int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state); | ||
60 | extern void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt); | ||
61 | #else | ||
62 | static inline struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0090_config *config) | ||
63 | { | ||
64 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
65 | return NULL; | ||
66 | } | ||
67 | |||
68 | static inline void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast) | ||
69 | { | ||
70 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
71 | } | ||
72 | |||
73 | static inline void dib0090_pwm_gain_reset(struct dvb_frontend *fe) | ||
74 | { | ||
75 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
76 | } | ||
77 | |||
78 | static inline u16 dib0090_get_wbd_offset(struct dvb_frontend *tuner) | ||
79 | { | ||
80 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
81 | return 0; | ||
82 | } | ||
83 | |||
84 | static inline int dib0090_gain_control(struct dvb_frontend *fe) | ||
85 | { | ||
86 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
87 | return -ENODEV; | ||
88 | } | ||
89 | |||
90 | static inline enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe) | ||
91 | { | ||
92 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
93 | return CT_DONE; | ||
94 | } | ||
95 | |||
96 | static inline int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state) | ||
97 | { | ||
98 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
99 | return -ENODEV; | ||
100 | } | ||
101 | |||
102 | static inline void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt) | ||
103 | { | ||
104 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
105 | } | ||
106 | #endif | ||
107 | |||
108 | #endif | ||
diff --git a/drivers/media/dvb/frontends/dib8000.c b/drivers/media/dvb/frontends/dib8000.c index 898400d331a3..6f6fa29d9ea4 100644 --- a/drivers/media/dvb/frontends/dib8000.c +++ b/drivers/media/dvb/frontends/dib8000.c | |||
@@ -28,18 +28,6 @@ MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); | |||
28 | 28 | ||
29 | #define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB8000: "); printk(args); printk("\n"); } } while (0) | 29 | #define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB8000: "); printk(args); printk("\n"); } } while (0) |
30 | 30 | ||
31 | enum frontend_tune_state { | ||
32 | CT_AGC_START = 20, | ||
33 | CT_AGC_STEP_0, | ||
34 | CT_AGC_STEP_1, | ||
35 | CT_AGC_STEP_2, | ||
36 | CT_AGC_STEP_3, | ||
37 | CT_AGC_STEP_4, | ||
38 | CT_AGC_STOP, | ||
39 | |||
40 | CT_DEMOD_START = 30, | ||
41 | }; | ||
42 | |||
43 | #define FE_STATUS_TUNE_FAILED 0 | 31 | #define FE_STATUS_TUNE_FAILED 0 |
44 | 32 | ||
45 | struct i2c_device { | 33 | struct i2c_device { |
@@ -133,104 +121,104 @@ static int dib8000_write_word(struct dib8000_state *state, u16 reg, u16 val) | |||
133 | return dib8000_i2c_write16(&state->i2c, reg, val); | 121 | return dib8000_i2c_write16(&state->i2c, reg, val); |
134 | } | 122 | } |
135 | 123 | ||
136 | const int16_t coeff_2k_sb_1seg_dqpsk[8] = { | 124 | static const int16_t coeff_2k_sb_1seg_dqpsk[8] = { |
137 | (769 << 5) | 0x0a, (745 << 5) | 0x03, (595 << 5) | 0x0d, (769 << 5) | 0x0a, (920 << 5) | 0x09, (784 << 5) | 0x02, (519 << 5) | 0x0c, | 125 | (769 << 5) | 0x0a, (745 << 5) | 0x03, (595 << 5) | 0x0d, (769 << 5) | 0x0a, (920 << 5) | 0x09, (784 << 5) | 0x02, (519 << 5) | 0x0c, |
138 | (920 << 5) | 0x09 | 126 | (920 << 5) | 0x09 |
139 | }; | 127 | }; |
140 | 128 | ||
141 | const int16_t coeff_2k_sb_1seg[8] = { | 129 | static const int16_t coeff_2k_sb_1seg[8] = { |
142 | (692 << 5) | 0x0b, (683 << 5) | 0x01, (519 << 5) | 0x09, (692 << 5) | 0x0b, 0 | 0x1f, 0 | 0x1f, 0 | 0x1f, 0 | 0x1f | 130 | (692 << 5) | 0x0b, (683 << 5) | 0x01, (519 << 5) | 0x09, (692 << 5) | 0x0b, 0 | 0x1f, 0 | 0x1f, 0 | 0x1f, 0 | 0x1f |
143 | }; | 131 | }; |
144 | 132 | ||
145 | const int16_t coeff_2k_sb_3seg_0dqpsk_1dqpsk[8] = { | 133 | static const int16_t coeff_2k_sb_3seg_0dqpsk_1dqpsk[8] = { |
146 | (832 << 5) | 0x10, (912 << 5) | 0x05, (900 << 5) | 0x12, (832 << 5) | 0x10, (-931 << 5) | 0x0f, (912 << 5) | 0x04, (807 << 5) | 0x11, | 134 | (832 << 5) | 0x10, (912 << 5) | 0x05, (900 << 5) | 0x12, (832 << 5) | 0x10, (-931 << 5) | 0x0f, (912 << 5) | 0x04, (807 << 5) | 0x11, |
147 | (-931 << 5) | 0x0f | 135 | (-931 << 5) | 0x0f |
148 | }; | 136 | }; |
149 | 137 | ||
150 | const int16_t coeff_2k_sb_3seg_0dqpsk[8] = { | 138 | static const int16_t coeff_2k_sb_3seg_0dqpsk[8] = { |
151 | (622 << 5) | 0x0c, (941 << 5) | 0x04, (796 << 5) | 0x10, (622 << 5) | 0x0c, (982 << 5) | 0x0c, (519 << 5) | 0x02, (572 << 5) | 0x0e, | 139 | (622 << 5) | 0x0c, (941 << 5) | 0x04, (796 << 5) | 0x10, (622 << 5) | 0x0c, (982 << 5) | 0x0c, (519 << 5) | 0x02, (572 << 5) | 0x0e, |
152 | (982 << 5) | 0x0c | 140 | (982 << 5) | 0x0c |
153 | }; | 141 | }; |
154 | 142 | ||
155 | const int16_t coeff_2k_sb_3seg_1dqpsk[8] = { | 143 | static const int16_t coeff_2k_sb_3seg_1dqpsk[8] = { |
156 | (699 << 5) | 0x14, (607 << 5) | 0x04, (944 << 5) | 0x13, (699 << 5) | 0x14, (-720 << 5) | 0x0d, (640 << 5) | 0x03, (866 << 5) | 0x12, | 144 | (699 << 5) | 0x14, (607 << 5) | 0x04, (944 << 5) | 0x13, (699 << 5) | 0x14, (-720 << 5) | 0x0d, (640 << 5) | 0x03, (866 << 5) | 0x12, |
157 | (-720 << 5) | 0x0d | 145 | (-720 << 5) | 0x0d |
158 | }; | 146 | }; |
159 | 147 | ||
160 | const int16_t coeff_2k_sb_3seg[8] = { | 148 | static const int16_t coeff_2k_sb_3seg[8] = { |
161 | (664 << 5) | 0x0c, (925 << 5) | 0x03, (937 << 5) | 0x10, (664 << 5) | 0x0c, (-610 << 5) | 0x0a, (697 << 5) | 0x01, (836 << 5) | 0x0e, | 149 | (664 << 5) | 0x0c, (925 << 5) | 0x03, (937 << 5) | 0x10, (664 << 5) | 0x0c, (-610 << 5) | 0x0a, (697 << 5) | 0x01, (836 << 5) | 0x0e, |
162 | (-610 << 5) | 0x0a | 150 | (-610 << 5) | 0x0a |
163 | }; | 151 | }; |
164 | 152 | ||
165 | const int16_t coeff_4k_sb_1seg_dqpsk[8] = { | 153 | static const int16_t coeff_4k_sb_1seg_dqpsk[8] = { |
166 | (-955 << 5) | 0x0e, (687 << 5) | 0x04, (818 << 5) | 0x10, (-955 << 5) | 0x0e, (-922 << 5) | 0x0d, (750 << 5) | 0x03, (665 << 5) | 0x0f, | 154 | (-955 << 5) | 0x0e, (687 << 5) | 0x04, (818 << 5) | 0x10, (-955 << 5) | 0x0e, (-922 << 5) | 0x0d, (750 << 5) | 0x03, (665 << 5) | 0x0f, |
167 | (-922 << 5) | 0x0d | 155 | (-922 << 5) | 0x0d |
168 | }; | 156 | }; |
169 | 157 | ||
170 | const int16_t coeff_4k_sb_1seg[8] = { | 158 | static const int16_t coeff_4k_sb_1seg[8] = { |
171 | (638 << 5) | 0x0d, (683 << 5) | 0x02, (638 << 5) | 0x0d, (638 << 5) | 0x0d, (-655 << 5) | 0x0a, (517 << 5) | 0x00, (698 << 5) | 0x0d, | 159 | (638 << 5) | 0x0d, (683 << 5) | 0x02, (638 << 5) | 0x0d, (638 << 5) | 0x0d, (-655 << 5) | 0x0a, (517 << 5) | 0x00, (698 << 5) | 0x0d, |
172 | (-655 << 5) | 0x0a | 160 | (-655 << 5) | 0x0a |
173 | }; | 161 | }; |
174 | 162 | ||
175 | const int16_t coeff_4k_sb_3seg_0dqpsk_1dqpsk[8] = { | 163 | static const int16_t coeff_4k_sb_3seg_0dqpsk_1dqpsk[8] = { |
176 | (-707 << 5) | 0x14, (910 << 5) | 0x06, (889 << 5) | 0x16, (-707 << 5) | 0x14, (-958 << 5) | 0x13, (993 << 5) | 0x05, (523 << 5) | 0x14, | 164 | (-707 << 5) | 0x14, (910 << 5) | 0x06, (889 << 5) | 0x16, (-707 << 5) | 0x14, (-958 << 5) | 0x13, (993 << 5) | 0x05, (523 << 5) | 0x14, |
177 | (-958 << 5) | 0x13 | 165 | (-958 << 5) | 0x13 |
178 | }; | 166 | }; |
179 | 167 | ||
180 | const int16_t coeff_4k_sb_3seg_0dqpsk[8] = { | 168 | static const int16_t coeff_4k_sb_3seg_0dqpsk[8] = { |
181 | (-723 << 5) | 0x13, (910 << 5) | 0x05, (777 << 5) | 0x14, (-723 << 5) | 0x13, (-568 << 5) | 0x0f, (547 << 5) | 0x03, (696 << 5) | 0x12, | 169 | (-723 << 5) | 0x13, (910 << 5) | 0x05, (777 << 5) | 0x14, (-723 << 5) | 0x13, (-568 << 5) | 0x0f, (547 << 5) | 0x03, (696 << 5) | 0x12, |
182 | (-568 << 5) | 0x0f | 170 | (-568 << 5) | 0x0f |
183 | }; | 171 | }; |
184 | 172 | ||
185 | const int16_t coeff_4k_sb_3seg_1dqpsk[8] = { | 173 | static const int16_t coeff_4k_sb_3seg_1dqpsk[8] = { |
186 | (-940 << 5) | 0x15, (607 << 5) | 0x05, (915 << 5) | 0x16, (-940 << 5) | 0x15, (-848 << 5) | 0x13, (683 << 5) | 0x04, (543 << 5) | 0x14, | 174 | (-940 << 5) | 0x15, (607 << 5) | 0x05, (915 << 5) | 0x16, (-940 << 5) | 0x15, (-848 << 5) | 0x13, (683 << 5) | 0x04, (543 << 5) | 0x14, |
187 | (-848 << 5) | 0x13 | 175 | (-848 << 5) | 0x13 |
188 | }; | 176 | }; |
189 | 177 | ||
190 | const int16_t coeff_4k_sb_3seg[8] = { | 178 | static const int16_t coeff_4k_sb_3seg[8] = { |
191 | (612 << 5) | 0x12, (910 << 5) | 0x04, (864 << 5) | 0x14, (612 << 5) | 0x12, (-869 << 5) | 0x13, (683 << 5) | 0x02, (869 << 5) | 0x12, | 179 | (612 << 5) | 0x12, (910 << 5) | 0x04, (864 << 5) | 0x14, (612 << 5) | 0x12, (-869 << 5) | 0x13, (683 << 5) | 0x02, (869 << 5) | 0x12, |
192 | (-869 << 5) | 0x13 | 180 | (-869 << 5) | 0x13 |
193 | }; | 181 | }; |
194 | 182 | ||
195 | const int16_t coeff_8k_sb_1seg_dqpsk[8] = { | 183 | static const int16_t coeff_8k_sb_1seg_dqpsk[8] = { |
196 | (-835 << 5) | 0x12, (684 << 5) | 0x05, (735 << 5) | 0x14, (-835 << 5) | 0x12, (-598 << 5) | 0x10, (781 << 5) | 0x04, (739 << 5) | 0x13, | 184 | (-835 << 5) | 0x12, (684 << 5) | 0x05, (735 << 5) | 0x14, (-835 << 5) | 0x12, (-598 << 5) | 0x10, (781 << 5) | 0x04, (739 << 5) | 0x13, |
197 | (-598 << 5) | 0x10 | 185 | (-598 << 5) | 0x10 |
198 | }; | 186 | }; |
199 | 187 | ||
200 | const int16_t coeff_8k_sb_1seg[8] = { | 188 | static const int16_t coeff_8k_sb_1seg[8] = { |
201 | (673 << 5) | 0x0f, (683 << 5) | 0x03, (808 << 5) | 0x12, (673 << 5) | 0x0f, (585 << 5) | 0x0f, (512 << 5) | 0x01, (780 << 5) | 0x0f, | 189 | (673 << 5) | 0x0f, (683 << 5) | 0x03, (808 << 5) | 0x12, (673 << 5) | 0x0f, (585 << 5) | 0x0f, (512 << 5) | 0x01, (780 << 5) | 0x0f, |
202 | (585 << 5) | 0x0f | 190 | (585 << 5) | 0x0f |
203 | }; | 191 | }; |
204 | 192 | ||
205 | const int16_t coeff_8k_sb_3seg_0dqpsk_1dqpsk[8] = { | 193 | static const int16_t coeff_8k_sb_3seg_0dqpsk_1dqpsk[8] = { |
206 | (863 << 5) | 0x17, (930 << 5) | 0x07, (878 << 5) | 0x19, (863 << 5) | 0x17, (0 << 5) | 0x14, (521 << 5) | 0x05, (980 << 5) | 0x18, | 194 | (863 << 5) | 0x17, (930 << 5) | 0x07, (878 << 5) | 0x19, (863 << 5) | 0x17, (0 << 5) | 0x14, (521 << 5) | 0x05, (980 << 5) | 0x18, |
207 | (0 << 5) | 0x14 | 195 | (0 << 5) | 0x14 |
208 | }; | 196 | }; |
209 | 197 | ||
210 | const int16_t coeff_8k_sb_3seg_0dqpsk[8] = { | 198 | static const int16_t coeff_8k_sb_3seg_0dqpsk[8] = { |
211 | (-924 << 5) | 0x17, (910 << 5) | 0x06, (774 << 5) | 0x17, (-924 << 5) | 0x17, (-877 << 5) | 0x15, (565 << 5) | 0x04, (553 << 5) | 0x15, | 199 | (-924 << 5) | 0x17, (910 << 5) | 0x06, (774 << 5) | 0x17, (-924 << 5) | 0x17, (-877 << 5) | 0x15, (565 << 5) | 0x04, (553 << 5) | 0x15, |
212 | (-877 << 5) | 0x15 | 200 | (-877 << 5) | 0x15 |
213 | }; | 201 | }; |
214 | 202 | ||
215 | const int16_t coeff_8k_sb_3seg_1dqpsk[8] = { | 203 | static const int16_t coeff_8k_sb_3seg_1dqpsk[8] = { |
216 | (-921 << 5) | 0x19, (607 << 5) | 0x06, (881 << 5) | 0x19, (-921 << 5) | 0x19, (-921 << 5) | 0x14, (713 << 5) | 0x05, (1018 << 5) | 0x18, | 204 | (-921 << 5) | 0x19, (607 << 5) | 0x06, (881 << 5) | 0x19, (-921 << 5) | 0x19, (-921 << 5) | 0x14, (713 << 5) | 0x05, (1018 << 5) | 0x18, |
217 | (-921 << 5) | 0x14 | 205 | (-921 << 5) | 0x14 |
218 | }; | 206 | }; |
219 | 207 | ||
220 | const int16_t coeff_8k_sb_3seg[8] = { | 208 | static const int16_t coeff_8k_sb_3seg[8] = { |
221 | (514 << 5) | 0x14, (910 << 5) | 0x05, (861 << 5) | 0x17, (514 << 5) | 0x14, (690 << 5) | 0x14, (683 << 5) | 0x03, (662 << 5) | 0x15, | 209 | (514 << 5) | 0x14, (910 << 5) | 0x05, (861 << 5) | 0x17, (514 << 5) | 0x14, (690 << 5) | 0x14, (683 << 5) | 0x03, (662 << 5) | 0x15, |
222 | (690 << 5) | 0x14 | 210 | (690 << 5) | 0x14 |
223 | }; | 211 | }; |
224 | 212 | ||
225 | const int16_t ana_fe_coeff_3seg[24] = { | 213 | static const int16_t ana_fe_coeff_3seg[24] = { |
226 | 81, 80, 78, 74, 68, 61, 54, 45, 37, 28, 19, 11, 4, 1022, 1017, 1013, 1010, 1008, 1008, 1008, 1008, 1010, 1014, 1017 | 214 | 81, 80, 78, 74, 68, 61, 54, 45, 37, 28, 19, 11, 4, 1022, 1017, 1013, 1010, 1008, 1008, 1008, 1008, 1010, 1014, 1017 |
227 | }; | 215 | }; |
228 | 216 | ||
229 | const int16_t ana_fe_coeff_1seg[24] = { | 217 | static const int16_t ana_fe_coeff_1seg[24] = { |
230 | 249, 226, 164, 82, 5, 981, 970, 988, 1018, 20, 31, 26, 8, 1012, 1000, 1018, 1012, 8, 15, 14, 9, 3, 1017, 1003 | 218 | 249, 226, 164, 82, 5, 981, 970, 988, 1018, 20, 31, 26, 8, 1012, 1000, 1018, 1012, 8, 15, 14, 9, 3, 1017, 1003 |
231 | }; | 219 | }; |
232 | 220 | ||
233 | const int16_t ana_fe_coeff_13seg[24] = { | 221 | static const int16_t ana_fe_coeff_13seg[24] = { |
234 | 396, 305, 105, -51, -77, -12, 41, 31, -11, -30, -11, 14, 15, -2, -13, -7, 5, 8, 1, -6, -7, -3, 0, 1 | 222 | 396, 305, 105, -51, -77, -12, 41, 31, -11, -30, -11, 14, 15, -2, -13, -7, 5, 8, 1, -6, -7, -3, 0, 1 |
235 | }; | 223 | }; |
236 | 224 | ||
@@ -852,6 +840,14 @@ static int dib8000_set_agc_config(struct dib8000_state *state, u8 band) | |||
852 | return 0; | 840 | return 0; |
853 | } | 841 | } |
854 | 842 | ||
843 | void dib8000_pwm_agc_reset(struct dvb_frontend *fe) | ||
844 | { | ||
845 | struct dib8000_state *state = fe->demodulator_priv; | ||
846 | dib8000_set_adc_state(state, DIBX000_ADC_ON); | ||
847 | dib8000_set_agc_config(state, (unsigned char)(BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000))); | ||
848 | } | ||
849 | EXPORT_SYMBOL(dib8000_pwm_agc_reset); | ||
850 | |||
855 | static int dib8000_agc_soft_split(struct dib8000_state *state) | 851 | static int dib8000_agc_soft_split(struct dib8000_state *state) |
856 | { | 852 | { |
857 | u16 agc, split_offset; | 853 | u16 agc, split_offset; |
@@ -939,6 +935,32 @@ static int dib8000_agc_startup(struct dvb_frontend *fe) | |||
939 | 935 | ||
940 | } | 936 | } |
941 | 937 | ||
938 | static const int32_t lut_1000ln_mant[] = | ||
939 | { | ||
940 | 908, 7003, 7090, 7170, 7244, 7313, 7377, 7438, 7495, 7549, 7600 | ||
941 | }; | ||
942 | |||
943 | int32_t dib8000_get_adc_power(struct dvb_frontend *fe, uint8_t mode) | ||
944 | { | ||
945 | struct dib8000_state *state = fe->demodulator_priv; | ||
946 | uint32_t ix = 0, tmp_val = 0, exp = 0, mant = 0; | ||
947 | int32_t val; | ||
948 | |||
949 | val = dib8000_read32(state, 384); | ||
950 | /* mode = 1 : ln_agcpower calc using mant-exp conversion and mantis look up table */ | ||
951 | if (mode) { | ||
952 | tmp_val = val; | ||
953 | while (tmp_val >>= 1) | ||
954 | exp++; | ||
955 | mant = (val * 1000 / (1<<exp)); | ||
956 | ix = (uint8_t)((mant-1000)/100); /* index of the LUT */ | ||
957 | val = (lut_1000ln_mant[ix] + 693*(exp-20) - 6908); /* 1000 * ln(adcpower_real) ; 693 = 1000ln(2) ; 6908 = 1000*ln(1000) ; 20 comes from adc_real = adc_pow_int / 2**20 */ | ||
958 | val = (val*256)/1000; | ||
959 | } | ||
960 | return val; | ||
961 | } | ||
962 | EXPORT_SYMBOL(dib8000_get_adc_power); | ||
963 | |||
942 | static void dib8000_update_timf(struct dib8000_state *state) | 964 | static void dib8000_update_timf(struct dib8000_state *state) |
943 | { | 965 | { |
944 | u32 timf = state->timf = dib8000_read32(state, 435); | 966 | u32 timf = state->timf = dib8000_read32(state, 435); |
@@ -1401,10 +1423,9 @@ static void dib8000_set_channel(struct dib8000_state *state, u8 seq, u8 autosear | |||
1401 | } | 1423 | } |
1402 | break; | 1424 | break; |
1403 | } | 1425 | } |
1404 | } | ||
1405 | if (state->fe.dtv_property_cache.isdbt_sb_mode == 1) | ||
1406 | for (i = 0; i < 8; i++) | 1426 | for (i = 0; i < 8; i++) |
1407 | dib8000_write_word(state, 343 + i, ncoeff[i]); | 1427 | dib8000_write_word(state, 343 + i, ncoeff[i]); |
1428 | } | ||
1408 | 1429 | ||
1409 | // P_small_coef_ext_enable=ISDB-Tsb, P_small_narrow_band=ISDB-Tsb, P_small_last_seg=13, P_small_offset_num_car=5 | 1430 | // P_small_coef_ext_enable=ISDB-Tsb, P_small_narrow_band=ISDB-Tsb, P_small_last_seg=13, P_small_offset_num_car=5 |
1410 | dib8000_write_word(state, 351, | 1431 | dib8000_write_word(state, 351, |
@@ -1854,6 +1875,24 @@ static int dib8000_sleep(struct dvb_frontend *fe) | |||
1854 | } | 1875 | } |
1855 | } | 1876 | } |
1856 | 1877 | ||
1878 | enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe) | ||
1879 | { | ||
1880 | struct dib8000_state *state = fe->demodulator_priv; | ||
1881 | return state->tune_state; | ||
1882 | } | ||
1883 | EXPORT_SYMBOL(dib8000_get_tune_state); | ||
1884 | |||
1885 | int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state) | ||
1886 | { | ||
1887 | struct dib8000_state *state = fe->demodulator_priv; | ||
1888 | state->tune_state = tune_state; | ||
1889 | return 0; | ||
1890 | } | ||
1891 | EXPORT_SYMBOL(dib8000_set_tune_state); | ||
1892 | |||
1893 | |||
1894 | |||
1895 | |||
1857 | static int dib8000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep) | 1896 | static int dib8000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep) |
1858 | { | 1897 | { |
1859 | struct dib8000_state *state = fe->demodulator_priv; | 1898 | struct dib8000_state *state = fe->demodulator_priv; |
@@ -2043,29 +2082,31 @@ static int dib8000_read_status(struct dvb_frontend *fe, fe_status_t * stat) | |||
2043 | 2082 | ||
2044 | *stat = 0; | 2083 | *stat = 0; |
2045 | 2084 | ||
2046 | if ((lock >> 14) & 1) // AGC | 2085 | if ((lock >> 13) & 1) |
2047 | *stat |= FE_HAS_SIGNAL; | 2086 | *stat |= FE_HAS_SIGNAL; |
2048 | 2087 | ||
2049 | if ((lock >> 8) & 1) // Equal | 2088 | if ((lock >> 8) & 1) /* Equal */ |
2050 | *stat |= FE_HAS_CARRIER; | 2089 | *stat |= FE_HAS_CARRIER; |
2051 | 2090 | ||
2052 | if ((lock >> 3) & 1) // TMCC_SYNC | 2091 | if (((lock >> 1) & 0xf) == 0xf) /* TMCC_SYNC */ |
2053 | *stat |= FE_HAS_SYNC; | 2092 | *stat |= FE_HAS_SYNC; |
2054 | 2093 | ||
2055 | if ((lock >> 5) & 7) // FEC MPEG | 2094 | if (((lock >> 12) & 1) && ((lock >> 5) & 7)) /* FEC MPEG */ |
2056 | *stat |= FE_HAS_LOCK; | 2095 | *stat |= FE_HAS_LOCK; |
2057 | 2096 | ||
2058 | lock = dib8000_read_word(state, 554); // Viterbi Layer A | 2097 | if ((lock >> 12) & 1) { |
2059 | if (lock & 0x01) | 2098 | lock = dib8000_read_word(state, 554); /* Viterbi Layer A */ |
2060 | *stat |= FE_HAS_VITERBI; | 2099 | if (lock & 0x01) |
2100 | *stat |= FE_HAS_VITERBI; | ||
2061 | 2101 | ||
2062 | lock = dib8000_read_word(state, 555); // Viterbi Layer B | 2102 | lock = dib8000_read_word(state, 555); /* Viterbi Layer B */ |
2063 | if (lock & 0x01) | 2103 | if (lock & 0x01) |
2064 | *stat |= FE_HAS_VITERBI; | 2104 | *stat |= FE_HAS_VITERBI; |
2065 | 2105 | ||
2066 | lock = dib8000_read_word(state, 556); // Viterbi Layer C | 2106 | lock = dib8000_read_word(state, 556); /* Viterbi Layer C */ |
2067 | if (lock & 0x01) | 2107 | if (lock & 0x01) |
2068 | *stat |= FE_HAS_VITERBI; | 2108 | *stat |= FE_HAS_VITERBI; |
2109 | } | ||
2069 | 2110 | ||
2070 | return 0; | 2111 | return 0; |
2071 | } | 2112 | } |
diff --git a/drivers/media/dvb/frontends/dib8000.h b/drivers/media/dvb/frontends/dib8000.h index 8c89482b738a..b1ee20799639 100644 --- a/drivers/media/dvb/frontends/dib8000.h +++ b/drivers/media/dvb/frontends/dib8000.h | |||
@@ -46,6 +46,10 @@ extern int dib8000_set_gpio(struct dvb_frontend *, u8 num, u8 dir, u8 val); | |||
46 | extern int dib8000_set_wbd_ref(struct dvb_frontend *, u16 value); | 46 | extern int dib8000_set_wbd_ref(struct dvb_frontend *, u16 value); |
47 | extern int dib8000_pid_filter_ctrl(struct dvb_frontend *, u8 onoff); | 47 | extern int dib8000_pid_filter_ctrl(struct dvb_frontend *, u8 onoff); |
48 | extern int dib8000_pid_filter(struct dvb_frontend *, u8 id, u16 pid, u8 onoff); | 48 | extern int dib8000_pid_filter(struct dvb_frontend *, u8 id, u16 pid, u8 onoff); |
49 | extern int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state); | ||
50 | extern enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe); | ||
51 | extern void dib8000_pwm_agc_reset(struct dvb_frontend *fe); | ||
52 | extern s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode); | ||
49 | #else | 53 | #else |
50 | static inline struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg) | 54 | static inline struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg) |
51 | { | 55 | { |
@@ -59,35 +63,53 @@ static inline struct i2c_adapter *dib8000_get_i2c_master(struct dvb_frontend *fe | |||
59 | return NULL; | 63 | return NULL; |
60 | } | 64 | } |
61 | 65 | ||
62 | int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 default_addr, u8 first_addr) | 66 | static inline int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 default_addr, u8 first_addr) |
63 | { | 67 | { |
64 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | 68 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); |
65 | return -ENODEV; | 69 | return -ENODEV; |
66 | } | 70 | } |
67 | 71 | ||
68 | int dib8000_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val) | 72 | static inline int dib8000_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val) |
69 | { | 73 | { |
70 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | 74 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); |
71 | return -ENODEV; | 75 | return -ENODEV; |
72 | } | 76 | } |
73 | 77 | ||
74 | int dib8000_set_wbd_ref(struct dvb_frontend *fe, u16 value) | 78 | static inline int dib8000_set_wbd_ref(struct dvb_frontend *fe, u16 value) |
75 | { | 79 | { |
76 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | 80 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); |
77 | return -ENODEV; | 81 | return -ENODEV; |
78 | } | 82 | } |
79 | 83 | ||
80 | int dib8000_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff) | 84 | static inline int dib8000_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff) |
81 | { | 85 | { |
82 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | 86 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); |
83 | return -ENODEV; | 87 | return -ENODEV; |
84 | } | 88 | } |
85 | 89 | ||
86 | int dib8000_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff) | 90 | static inline int dib8000_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff) |
87 | { | 91 | { |
88 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | 92 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); |
89 | return -ENODEV; | 93 | return -ENODEV; |
90 | } | 94 | } |
95 | static inline int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state) | ||
96 | { | ||
97 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
98 | return -ENODEV; | ||
99 | } | ||
100 | static inline enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe) | ||
101 | { | ||
102 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
103 | return CT_SHUTDOWN; | ||
104 | } | ||
105 | static inline void dib8000_pwm_agc_reset(struct dvb_frontend *fe) | ||
106 | { | ||
107 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
108 | } | ||
109 | static inline s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode) | ||
110 | { | ||
111 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
112 | } | ||
91 | #endif | 113 | #endif |
92 | 114 | ||
93 | #endif | 115 | #endif |
diff --git a/drivers/media/dvb/frontends/dibx000_common.c b/drivers/media/dvb/frontends/dibx000_common.c index 4efca30d2127..e6f3d73db9d3 100644 --- a/drivers/media/dvb/frontends/dibx000_common.c +++ b/drivers/media/dvb/frontends/dibx000_common.c | |||
@@ -6,7 +6,7 @@ static int debug; | |||
6 | module_param(debug, int, 0644); | 6 | module_param(debug, int, 0644); |
7 | MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); | 7 | MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); |
8 | 8 | ||
9 | #define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiBX000: "); printk(args); } } while (0) | 9 | #define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiBX000: "); printk(args); printk("\n"); } } while (0) |
10 | 10 | ||
11 | static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val) | 11 | static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val) |
12 | { | 12 | { |
@@ -25,7 +25,7 @@ static int dibx000_i2c_select_interface(struct dibx000_i2c_master *mst, | |||
25 | enum dibx000_i2c_interface intf) | 25 | enum dibx000_i2c_interface intf) |
26 | { | 26 | { |
27 | if (mst->device_rev > DIB3000MC && mst->selected_interface != intf) { | 27 | if (mst->device_rev > DIB3000MC && mst->selected_interface != intf) { |
28 | dprintk("selecting interface: %d\n", intf); | 28 | dprintk("selecting interface: %d", intf); |
29 | mst->selected_interface = intf; | 29 | mst->selected_interface = intf; |
30 | return dibx000_write_word(mst, mst->base_reg + 4, intf); | 30 | return dibx000_write_word(mst, mst->base_reg + 4, intf); |
31 | } | 31 | } |
@@ -171,9 +171,18 @@ void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst) | |||
171 | { | 171 | { |
172 | i2c_del_adapter(&mst->gated_tuner_i2c_adap); | 172 | i2c_del_adapter(&mst->gated_tuner_i2c_adap); |
173 | } | 173 | } |
174 | |||
175 | EXPORT_SYMBOL(dibx000_exit_i2c_master); | 174 | EXPORT_SYMBOL(dibx000_exit_i2c_master); |
176 | 175 | ||
176 | |||
177 | u32 systime() | ||
178 | { | ||
179 | struct timespec t; | ||
180 | |||
181 | t = current_kernel_time(); | ||
182 | return (t.tv_sec * 10000) + (t.tv_nsec / 100000); | ||
183 | } | ||
184 | EXPORT_SYMBOL(systime); | ||
185 | |||
177 | MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>"); | 186 | MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>"); |
178 | MODULE_DESCRIPTION("Common function the DiBcom demodulator family"); | 187 | MODULE_DESCRIPTION("Common function the DiBcom demodulator family"); |
179 | MODULE_LICENSE("GPL"); | 188 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/media/dvb/frontends/dibx000_common.h b/drivers/media/dvb/frontends/dibx000_common.h index 5be10eca07c0..4f5d141a308d 100644 --- a/drivers/media/dvb/frontends/dibx000_common.h +++ b/drivers/media/dvb/frontends/dibx000_common.h | |||
@@ -36,13 +36,17 @@ extern struct i2c_adapter *dibx000_get_i2c_adapter(struct dibx000_i2c_master | |||
36 | extern void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst); | 36 | extern void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst); |
37 | extern void dibx000_reset_i2c_master(struct dibx000_i2c_master *mst); | 37 | extern void dibx000_reset_i2c_master(struct dibx000_i2c_master *mst); |
38 | 38 | ||
39 | extern u32 systime(void); | ||
40 | |||
39 | #define BAND_LBAND 0x01 | 41 | #define BAND_LBAND 0x01 |
40 | #define BAND_UHF 0x02 | 42 | #define BAND_UHF 0x02 |
41 | #define BAND_VHF 0x04 | 43 | #define BAND_VHF 0x04 |
42 | #define BAND_SBAND 0x08 | 44 | #define BAND_SBAND 0x08 |
43 | #define BAND_FM 0x10 | 45 | #define BAND_FM 0x10 |
46 | #define BAND_CBAND 0x20 | ||
44 | 47 | ||
45 | #define BAND_OF_FREQUENCY(freq_kHz) ( (freq_kHz) <= 115000 ? BAND_FM : \ | 48 | #define BAND_OF_FREQUENCY(freq_kHz) ((freq_kHz) <= 170000 ? BAND_CBAND : \ |
49 | (freq_kHz) <= 115000 ? BAND_FM : \ | ||
46 | (freq_kHz) <= 250000 ? BAND_VHF : \ | 50 | (freq_kHz) <= 250000 ? BAND_VHF : \ |
47 | (freq_kHz) <= 863000 ? BAND_UHF : \ | 51 | (freq_kHz) <= 863000 ? BAND_UHF : \ |
48 | (freq_kHz) <= 2000000 ? BAND_LBAND : BAND_SBAND ) | 52 | (freq_kHz) <= 2000000 ? BAND_LBAND : BAND_SBAND ) |
@@ -149,4 +153,67 @@ enum dibx000_adc_states { | |||
149 | #define OUTMODE_MPEG2_FIFO 5 | 153 | #define OUTMODE_MPEG2_FIFO 5 |
150 | #define OUTMODE_ANALOG_ADC 6 | 154 | #define OUTMODE_ANALOG_ADC 6 |
151 | 155 | ||
156 | enum frontend_tune_state { | ||
157 | CT_TUNER_START = 10, | ||
158 | CT_TUNER_STEP_0, | ||
159 | CT_TUNER_STEP_1, | ||
160 | CT_TUNER_STEP_2, | ||
161 | CT_TUNER_STEP_3, | ||
162 | CT_TUNER_STEP_4, | ||
163 | CT_TUNER_STEP_5, | ||
164 | CT_TUNER_STEP_6, | ||
165 | CT_TUNER_STEP_7, | ||
166 | CT_TUNER_STOP, | ||
167 | |||
168 | CT_AGC_START = 20, | ||
169 | CT_AGC_STEP_0, | ||
170 | CT_AGC_STEP_1, | ||
171 | CT_AGC_STEP_2, | ||
172 | CT_AGC_STEP_3, | ||
173 | CT_AGC_STEP_4, | ||
174 | CT_AGC_STOP, | ||
175 | |||
176 | CT_DEMOD_START = 30, | ||
177 | CT_DEMOD_STEP_1, | ||
178 | CT_DEMOD_STEP_2, | ||
179 | CT_DEMOD_STEP_3, | ||
180 | CT_DEMOD_STEP_4, | ||
181 | CT_DEMOD_STEP_5, | ||
182 | CT_DEMOD_STEP_6, | ||
183 | CT_DEMOD_STEP_7, | ||
184 | CT_DEMOD_STEP_8, | ||
185 | CT_DEMOD_STEP_9, | ||
186 | CT_DEMOD_STEP_10, | ||
187 | CT_DEMOD_SEARCH_NEXT = 41, | ||
188 | CT_DEMOD_STEP_LOCKED, | ||
189 | CT_DEMOD_STOP, | ||
190 | |||
191 | CT_DONE = 100, | ||
192 | CT_SHUTDOWN, | ||
193 | |||
194 | }; | ||
195 | |||
196 | struct dvb_frontend_parametersContext { | ||
197 | #define CHANNEL_STATUS_PARAMETERS_UNKNOWN 0x01 | ||
198 | #define CHANNEL_STATUS_PARAMETERS_SET 0x02 | ||
199 | u8 status; | ||
200 | u32 tune_time_estimation[2]; | ||
201 | s32 tps_available; | ||
202 | u16 tps[9]; | ||
203 | }; | ||
204 | |||
205 | #define FE_STATUS_TUNE_FAILED 0 | ||
206 | #define FE_STATUS_TUNE_TIMED_OUT -1 | ||
207 | #define FE_STATUS_TUNE_TIME_TOO_SHORT -2 | ||
208 | #define FE_STATUS_TUNE_PENDING -3 | ||
209 | #define FE_STATUS_STD_SUCCESS -4 | ||
210 | #define FE_STATUS_FFT_SUCCESS -5 | ||
211 | #define FE_STATUS_DEMOD_SUCCESS -6 | ||
212 | #define FE_STATUS_LOCKED -7 | ||
213 | #define FE_STATUS_DATA_LOCKED -8 | ||
214 | |||
215 | #define FE_CALLBACK_TIME_NEVER 0xffffffff | ||
216 | |||
217 | #define ABS(x) ((x < 0) ? (-x) : (x)) | ||
218 | |||
152 | #endif | 219 | #endif |
diff --git a/drivers/media/dvb/frontends/lgdt3305.h b/drivers/media/dvb/frontends/lgdt3305.h index 4fa6e52d1fe8..9cb11c9cae53 100644 --- a/drivers/media/dvb/frontends/lgdt3305.h +++ b/drivers/media/dvb/frontends/lgdt3305.h | |||
@@ -54,13 +54,13 @@ struct lgdt3305_config { | |||
54 | u16 usref_qam256; /* default: 0x2a80 */ | 54 | u16 usref_qam256; /* default: 0x2a80 */ |
55 | 55 | ||
56 | /* disable i2c repeater - 0:repeater enabled 1:repeater disabled */ | 56 | /* disable i2c repeater - 0:repeater enabled 1:repeater disabled */ |
57 | int deny_i2c_rptr:1; | 57 | unsigned int deny_i2c_rptr:1; |
58 | 58 | ||
59 | /* spectral inversion - 0:disabled 1:enabled */ | 59 | /* spectral inversion - 0:disabled 1:enabled */ |
60 | int spectral_inversion:1; | 60 | unsigned int spectral_inversion:1; |
61 | 61 | ||
62 | /* use RF AGC loop - 0:disabled 1:enabled */ | 62 | /* use RF AGC loop - 0:disabled 1:enabled */ |
63 | int rf_agc_loop:1; | 63 | unsigned int rf_agc_loop:1; |
64 | 64 | ||
65 | enum lgdt3305_mpeg_mode mpeg_mode; | 65 | enum lgdt3305_mpeg_mode mpeg_mode; |
66 | enum lgdt3305_tp_clock_edge tpclk_edge; | 66 | enum lgdt3305_tp_clock_edge tpclk_edge; |
diff --git a/drivers/media/dvb/frontends/lgs8gxx.c b/drivers/media/dvb/frontends/lgs8gxx.c index eabcadc425d5..dee53960e7e8 100644 --- a/drivers/media/dvb/frontends/lgs8gxx.c +++ b/drivers/media/dvb/frontends/lgs8gxx.c | |||
@@ -199,7 +199,7 @@ static int lgs8gxx_set_if_freq(struct lgs8gxx_state *priv, u32 freq /*in kHz*/) | |||
199 | 199 | ||
200 | val = freq; | 200 | val = freq; |
201 | if (freq != 0) { | 201 | if (freq != 0) { |
202 | val *= (u64)1 << 32; | 202 | val <<= 32; |
203 | if (if_clk != 0) | 203 | if (if_clk != 0) |
204 | do_div(val, if_clk); | 204 | do_div(val, if_clk); |
205 | v32 = val & 0xFFFFFFFF; | 205 | v32 = val & 0xFFFFFFFF; |
@@ -246,7 +246,7 @@ static int lgs8gxx_get_afc_phase(struct lgs8gxx_state *priv) | |||
246 | 246 | ||
247 | val = v32; | 247 | val = v32; |
248 | val *= priv->config->if_clk_freq; | 248 | val *= priv->config->if_clk_freq; |
249 | val /= (u64)1 << 32; | 249 | val >>= 32; |
250 | dprintk("AFC = %u kHz\n", (u32)val); | 250 | dprintk("AFC = %u kHz\n", (u32)val); |
251 | return 0; | 251 | return 0; |
252 | } | 252 | } |
diff --git a/drivers/media/dvb/frontends/lnbp21.c b/drivers/media/dvb/frontends/lnbp21.c index 71f607fe8fc7..b181bf023ada 100644 --- a/drivers/media/dvb/frontends/lnbp21.c +++ b/drivers/media/dvb/frontends/lnbp21.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * lnbp21.c - driver for lnb supply and control ic lnbp21 | 2 | * lnbp21.c - driver for lnb supply and control ic lnbp21 |
3 | * | 3 | * |
4 | * Copyright (C) 2006 Oliver Endriss | 4 | * Copyright (C) 2006, 2009 Oliver Endriss <o.endriss@gmx.de> |
5 | * Copyright (C) 2009 Igor M. Liplianin <liplianin@netup.ru> | 5 | * Copyright (C) 2009 Igor M. Liplianin <liplianin@netup.ru> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or | 7 | * This program is free software; you can redistribute it and/or |
@@ -91,6 +91,31 @@ static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg) | |||
91 | return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO; | 91 | return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO; |
92 | } | 92 | } |
93 | 93 | ||
94 | static int lnbp21_set_tone(struct dvb_frontend *fe, | ||
95 | fe_sec_tone_mode_t tone) | ||
96 | { | ||
97 | struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->sec_priv; | ||
98 | struct i2c_msg msg = { .addr = lnbp21->i2c_addr, .flags = 0, | ||
99 | .buf = &lnbp21->config, | ||
100 | .len = sizeof(lnbp21->config) }; | ||
101 | |||
102 | switch (tone) { | ||
103 | case SEC_TONE_OFF: | ||
104 | lnbp21->config &= ~LNBP21_TEN; | ||
105 | break; | ||
106 | case SEC_TONE_ON: | ||
107 | lnbp21->config |= LNBP21_TEN; | ||
108 | break; | ||
109 | default: | ||
110 | return -EINVAL; | ||
111 | }; | ||
112 | |||
113 | lnbp21->config |= lnbp21->override_or; | ||
114 | lnbp21->config &= lnbp21->override_and; | ||
115 | |||
116 | return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO; | ||
117 | } | ||
118 | |||
94 | static void lnbp21_release(struct dvb_frontend *fe) | 119 | static void lnbp21_release(struct dvb_frontend *fe) |
95 | { | 120 | { |
96 | /* LNBP power off */ | 121 | /* LNBP power off */ |
@@ -133,6 +158,7 @@ static struct dvb_frontend *lnbx2x_attach(struct dvb_frontend *fe, | |||
133 | /* override frontend ops */ | 158 | /* override frontend ops */ |
134 | fe->ops.set_voltage = lnbp21_set_voltage; | 159 | fe->ops.set_voltage = lnbp21_set_voltage; |
135 | 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; | ||
136 | printk(KERN_INFO "LNBx2x attached on addr=%x\n", lnbp21->i2c_addr); | 162 | printk(KERN_INFO "LNBx2x attached on addr=%x\n", lnbp21->i2c_addr); |
137 | 163 | ||
138 | return fe; | 164 | return fe; |
diff --git a/drivers/media/dvb/frontends/mb86a16.c b/drivers/media/dvb/frontends/mb86a16.c new file mode 100644 index 000000000000..d05f7500e0c5 --- /dev/null +++ b/drivers/media/dvb/frontends/mb86a16.c | |||
@@ -0,0 +1,1878 @@ | |||
1 | /* | ||
2 | Fujitsu MB86A16 DVB-S/DSS DC Receiver driver | ||
3 | |||
4 | Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/init.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/moduleparam.h> | ||
25 | |||
26 | #include "dvb_frontend.h" | ||
27 | #include "mb86a16.h" | ||
28 | #include "mb86a16_priv.h" | ||
29 | |||
30 | unsigned int verbose = 5; | ||
31 | module_param(verbose, int, 0644); | ||
32 | |||
33 | #define ABS(x) ((x) < 0 ? (-x) : (x)) | ||
34 | |||
35 | struct mb86a16_state { | ||
36 | struct i2c_adapter *i2c_adap; | ||
37 | const struct mb86a16_config *config; | ||
38 | struct dvb_frontend frontend; | ||
39 | |||
40 | /* tuning parameters */ | ||
41 | int frequency; | ||
42 | int srate; | ||
43 | |||
44 | /* Internal stuff */ | ||
45 | int master_clk; | ||
46 | int deci; | ||
47 | int csel; | ||
48 | int rsel; | ||
49 | }; | ||
50 | |||
51 | #define MB86A16_ERROR 0 | ||
52 | #define MB86A16_NOTICE 1 | ||
53 | #define MB86A16_INFO 2 | ||
54 | #define MB86A16_DEBUG 3 | ||
55 | |||
56 | #define dprintk(x, y, z, format, arg...) do { \ | ||
57 | if (z) { \ | ||
58 | if ((x > MB86A16_ERROR) && (x > y)) \ | ||
59 | printk(KERN_ERR "%s: " format "\n", __func__, ##arg); \ | ||
60 | else if ((x > MB86A16_NOTICE) && (x > y)) \ | ||
61 | printk(KERN_NOTICE "%s: " format "\n", __func__, ##arg); \ | ||
62 | else if ((x > MB86A16_INFO) && (x > y)) \ | ||
63 | printk(KERN_INFO "%s: " format "\n", __func__, ##arg); \ | ||
64 | else if ((x > MB86A16_DEBUG) && (x > y)) \ | ||
65 | printk(KERN_DEBUG "%s: " format "\n", __func__, ##arg); \ | ||
66 | } else { \ | ||
67 | if (x > y) \ | ||
68 | printk(format, ##arg); \ | ||
69 | } \ | ||
70 | } while (0) | ||
71 | |||
72 | #define TRACE_IN dprintk(verbose, MB86A16_DEBUG, 1, "-->()") | ||
73 | #define TRACE_OUT dprintk(verbose, MB86A16_DEBUG, 1, "()-->") | ||
74 | |||
75 | static int mb86a16_write(struct mb86a16_state *state, u8 reg, u8 val) | ||
76 | { | ||
77 | int ret; | ||
78 | u8 buf[] = { reg, val }; | ||
79 | |||
80 | struct i2c_msg msg = { | ||
81 | .addr = state->config->demod_address, | ||
82 | .flags = 0, | ||
83 | .buf = buf, | ||
84 | .len = 2 | ||
85 | }; | ||
86 | |||
87 | dprintk(verbose, MB86A16_DEBUG, 1, | ||
88 | "writing to [0x%02x],Reg[0x%02x],Data[0x%02x]", | ||
89 | state->config->demod_address, buf[0], buf[1]); | ||
90 | |||
91 | ret = i2c_transfer(state->i2c_adap, &msg, 1); | ||
92 | |||
93 | return (ret != 1) ? -EREMOTEIO : 0; | ||
94 | } | ||
95 | |||
96 | static int mb86a16_read(struct mb86a16_state *state, u8 reg, u8 *val) | ||
97 | { | ||
98 | int ret; | ||
99 | u8 b0[] = { reg }; | ||
100 | u8 b1[] = { 0 }; | ||
101 | |||
102 | struct i2c_msg msg[] = { | ||
103 | { | ||
104 | .addr = state->config->demod_address, | ||
105 | .flags = 0, | ||
106 | .buf = b0, | ||
107 | .len = 1 | ||
108 | }, { | ||
109 | .addr = state->config->demod_address, | ||
110 | .flags = I2C_M_RD, | ||
111 | .buf = b1, | ||
112 | .len = 1 | ||
113 | } | ||
114 | }; | ||
115 | ret = i2c_transfer(state->i2c_adap, msg, 2); | ||
116 | if (ret != 2) { | ||
117 | dprintk(verbose, MB86A16_ERROR, 1, "read error(reg=0x%02x, ret=0x%i)", | ||
118 | reg, ret); | ||
119 | |||
120 | return -EREMOTEIO; | ||
121 | } | ||
122 | *val = b1[0]; | ||
123 | |||
124 | return ret; | ||
125 | } | ||
126 | |||
127 | static int CNTM_set(struct mb86a16_state *state, | ||
128 | unsigned char timint1, | ||
129 | unsigned char timint2, | ||
130 | unsigned char cnext) | ||
131 | { | ||
132 | unsigned char val; | ||
133 | |||
134 | val = (timint1 << 4) | (timint2 << 2) | cnext; | ||
135 | if (mb86a16_write(state, MB86A16_CNTMR, val) < 0) | ||
136 | goto err; | ||
137 | |||
138 | return 0; | ||
139 | |||
140 | err: | ||
141 | dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); | ||
142 | return -EREMOTEIO; | ||
143 | } | ||
144 | |||
145 | static int smrt_set(struct mb86a16_state *state, int rate) | ||
146 | { | ||
147 | int tmp ; | ||
148 | int m ; | ||
149 | unsigned char STOFS0, STOFS1; | ||
150 | |||
151 | m = 1 << state->deci; | ||
152 | tmp = (8192 * state->master_clk - 2 * m * rate * 8192 + state->master_clk / 2) / state->master_clk; | ||
153 | |||
154 | STOFS0 = tmp & 0x0ff; | ||
155 | STOFS1 = (tmp & 0xf00) >> 8; | ||
156 | |||
157 | if (mb86a16_write(state, MB86A16_SRATE1, (state->deci << 2) | | ||
158 | (state->csel << 1) | | ||
159 | state->rsel) < 0) | ||
160 | goto err; | ||
161 | if (mb86a16_write(state, MB86A16_SRATE2, STOFS0) < 0) | ||
162 | goto err; | ||
163 | if (mb86a16_write(state, MB86A16_SRATE3, STOFS1) < 0) | ||
164 | goto err; | ||
165 | |||
166 | return 0; | ||
167 | err: | ||
168 | dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); | ||
169 | return -1; | ||
170 | } | ||
171 | |||
172 | static int srst(struct mb86a16_state *state) | ||
173 | { | ||
174 | if (mb86a16_write(state, MB86A16_RESET, 0x04) < 0) | ||
175 | goto err; | ||
176 | |||
177 | return 0; | ||
178 | err: | ||
179 | dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); | ||
180 | return -EREMOTEIO; | ||
181 | |||
182 | } | ||
183 | |||
184 | static int afcex_data_set(struct mb86a16_state *state, | ||
185 | unsigned char AFCEX_L, | ||
186 | unsigned char AFCEX_H) | ||
187 | { | ||
188 | if (mb86a16_write(state, MB86A16_AFCEXL, AFCEX_L) < 0) | ||
189 | goto err; | ||
190 | if (mb86a16_write(state, MB86A16_AFCEXH, AFCEX_H) < 0) | ||
191 | goto err; | ||
192 | |||
193 | return 0; | ||
194 | err: | ||
195 | dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); | ||
196 | |||
197 | return -1; | ||
198 | } | ||
199 | |||
200 | static int afcofs_data_set(struct mb86a16_state *state, | ||
201 | unsigned char AFCEX_L, | ||
202 | unsigned char AFCEX_H) | ||
203 | { | ||
204 | if (mb86a16_write(state, 0x58, AFCEX_L) < 0) | ||
205 | goto err; | ||
206 | if (mb86a16_write(state, 0x59, AFCEX_H) < 0) | ||
207 | goto err; | ||
208 | |||
209 | return 0; | ||
210 | err: | ||
211 | dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); | ||
212 | return -EREMOTEIO; | ||
213 | } | ||
214 | |||
215 | static int stlp_set(struct mb86a16_state *state, | ||
216 | unsigned char STRAS, | ||
217 | unsigned char STRBS) | ||
218 | { | ||
219 | if (mb86a16_write(state, MB86A16_STRFILTCOEF1, (STRBS << 3) | (STRAS)) < 0) | ||
220 | goto err; | ||
221 | |||
222 | return 0; | ||
223 | err: | ||
224 | dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); | ||
225 | return -EREMOTEIO; | ||
226 | } | ||
227 | |||
228 | static int Vi_set(struct mb86a16_state *state, unsigned char ETH, unsigned char VIA) | ||
229 | { | ||
230 | if (mb86a16_write(state, MB86A16_VISET2, 0x04) < 0) | ||
231 | goto err; | ||
232 | if (mb86a16_write(state, MB86A16_VISET3, 0xf5) < 0) | ||
233 | goto err; | ||
234 | |||
235 | return 0; | ||
236 | err: | ||
237 | dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); | ||
238 | return -EREMOTEIO; | ||
239 | } | ||
240 | |||
241 | static int initial_set(struct mb86a16_state *state) | ||
242 | { | ||
243 | if (stlp_set(state, 5, 7)) | ||
244 | goto err; | ||
245 | |||
246 | udelay(100); | ||
247 | if (afcex_data_set(state, 0, 0)) | ||
248 | goto err; | ||
249 | |||
250 | udelay(100); | ||
251 | if (afcofs_data_set(state, 0, 0)) | ||
252 | goto err; | ||
253 | |||
254 | udelay(100); | ||
255 | if (mb86a16_write(state, MB86A16_CRLFILTCOEF1, 0x16) < 0) | ||
256 | goto err; | ||
257 | if (mb86a16_write(state, 0x2f, 0x21) < 0) | ||
258 | goto err; | ||
259 | if (mb86a16_write(state, MB86A16_VIMAG, 0x38) < 0) | ||
260 | goto err; | ||
261 | if (mb86a16_write(state, MB86A16_FAGCS1, 0x00) < 0) | ||
262 | goto err; | ||
263 | if (mb86a16_write(state, MB86A16_FAGCS2, 0x1c) < 0) | ||
264 | goto err; | ||
265 | if (mb86a16_write(state, MB86A16_FAGCS3, 0x20) < 0) | ||
266 | goto err; | ||
267 | if (mb86a16_write(state, MB86A16_FAGCS4, 0x1e) < 0) | ||
268 | goto err; | ||
269 | if (mb86a16_write(state, MB86A16_FAGCS5, 0x23) < 0) | ||
270 | goto err; | ||
271 | if (mb86a16_write(state, 0x54, 0xff) < 0) | ||
272 | goto err; | ||
273 | if (mb86a16_write(state, MB86A16_TSOUT, 0x00) < 0) | ||
274 | goto err; | ||
275 | |||
276 | return 0; | ||
277 | |||
278 | err: | ||
279 | dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); | ||
280 | return -EREMOTEIO; | ||
281 | } | ||
282 | |||
283 | static int S01T_set(struct mb86a16_state *state, | ||
284 | unsigned char s1t, | ||
285 | unsigned s0t) | ||
286 | { | ||
287 | if (mb86a16_write(state, 0x33, (s1t << 3) | s0t) < 0) | ||
288 | goto err; | ||
289 | |||
290 | return 0; | ||
291 | err: | ||
292 | dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); | ||
293 | return -EREMOTEIO; | ||
294 | } | ||
295 | |||
296 | |||
297 | static int EN_set(struct mb86a16_state *state, | ||
298 | int cren, | ||
299 | int afcen) | ||
300 | { | ||
301 | unsigned char val; | ||
302 | |||
303 | val = 0x7a | (cren << 7) | (afcen << 2); | ||
304 | if (mb86a16_write(state, 0x49, val) < 0) | ||
305 | goto err; | ||
306 | |||
307 | return 0; | ||
308 | err: | ||
309 | dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); | ||
310 | return -EREMOTEIO; | ||
311 | } | ||
312 | |||
313 | static int AFCEXEN_set(struct mb86a16_state *state, | ||
314 | int afcexen, | ||
315 | int smrt) | ||
316 | { | ||
317 | unsigned char AFCA ; | ||
318 | |||
319 | if (smrt > 18875) | ||
320 | AFCA = 4; | ||
321 | else if (smrt > 9375) | ||
322 | AFCA = 3; | ||
323 | else if (smrt > 2250) | ||
324 | AFCA = 2; | ||
325 | else | ||
326 | AFCA = 1; | ||
327 | |||
328 | if (mb86a16_write(state, 0x2a, 0x02 | (afcexen << 5) | (AFCA << 2)) < 0) | ||
329 | goto err; | ||
330 | |||
331 | return 0; | ||
332 | |||
333 | err: | ||
334 | dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); | ||
335 | return -EREMOTEIO; | ||
336 | } | ||
337 | |||
338 | static int DAGC_data_set(struct mb86a16_state *state, | ||
339 | unsigned char DAGCA, | ||
340 | unsigned char DAGCW) | ||
341 | { | ||
342 | if (mb86a16_write(state, 0x2d, (DAGCA << 3) | DAGCW) < 0) | ||
343 | goto err; | ||
344 | |||
345 | return 0; | ||
346 | |||
347 | err: | ||
348 | dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); | ||
349 | return -EREMOTEIO; | ||
350 | } | ||
351 | |||
352 | static void smrt_info_get(struct mb86a16_state *state, int rate) | ||
353 | { | ||
354 | if (rate >= 37501) { | ||
355 | state->deci = 0; state->csel = 0; state->rsel = 0; | ||
356 | } else if (rate >= 30001) { | ||
357 | state->deci = 0; state->csel = 0; state->rsel = 1; | ||
358 | } else if (rate >= 26251) { | ||
359 | state->deci = 0; state->csel = 1; state->rsel = 0; | ||
360 | } else if (rate >= 22501) { | ||
361 | state->deci = 0; state->csel = 1; state->rsel = 1; | ||
362 | } else if (rate >= 18751) { | ||
363 | state->deci = 1; state->csel = 0; state->rsel = 0; | ||
364 | } else if (rate >= 15001) { | ||
365 | state->deci = 1; state->csel = 0; state->rsel = 1; | ||
366 | } else if (rate >= 13126) { | ||
367 | state->deci = 1; state->csel = 1; state->rsel = 0; | ||
368 | } else if (rate >= 11251) { | ||
369 | state->deci = 1; state->csel = 1; state->rsel = 1; | ||
370 | } else if (rate >= 9376) { | ||
371 | state->deci = 2; state->csel = 0; state->rsel = 0; | ||
372 | } else if (rate >= 7501) { | ||
373 | state->deci = 2; state->csel = 0; state->rsel = 1; | ||
374 | } else if (rate >= 6563) { | ||
375 | state->deci = 2; state->csel = 1; state->rsel = 0; | ||
376 | } else if (rate >= 5626) { | ||
377 | state->deci = 2; state->csel = 1; state->rsel = 1; | ||
378 | } else if (rate >= 4688) { | ||
379 | state->deci = 3; state->csel = 0; state->rsel = 0; | ||
380 | } else if (rate >= 3751) { | ||
381 | state->deci = 3; state->csel = 0; state->rsel = 1; | ||
382 | } else if (rate >= 3282) { | ||
383 | state->deci = 3; state->csel = 1; state->rsel = 0; | ||
384 | } else if (rate >= 2814) { | ||
385 | state->deci = 3; state->csel = 1; state->rsel = 1; | ||
386 | } else if (rate >= 2344) { | ||
387 | state->deci = 4; state->csel = 0; state->rsel = 0; | ||
388 | } else if (rate >= 1876) { | ||
389 | state->deci = 4; state->csel = 0; state->rsel = 1; | ||
390 | } else if (rate >= 1641) { | ||
391 | state->deci = 4; state->csel = 1; state->rsel = 0; | ||
392 | } else if (rate >= 1407) { | ||
393 | state->deci = 4; state->csel = 1; state->rsel = 1; | ||
394 | } else if (rate >= 1172) { | ||
395 | state->deci = 5; state->csel = 0; state->rsel = 0; | ||
396 | } else if (rate >= 939) { | ||
397 | state->deci = 5; state->csel = 0; state->rsel = 1; | ||
398 | } else if (rate >= 821) { | ||
399 | state->deci = 5; state->csel = 1; state->rsel = 0; | ||
400 | } else { | ||
401 | state->deci = 5; state->csel = 1; state->rsel = 1; | ||
402 | } | ||
403 | |||
404 | if (state->csel == 0) | ||
405 | state->master_clk = 92000; | ||
406 | else | ||
407 | state->master_clk = 61333; | ||
408 | |||
409 | } | ||
410 | |||
411 | static int signal_det(struct mb86a16_state *state, | ||
412 | int smrt, | ||
413 | unsigned char *SIG) | ||
414 | { | ||
415 | |||
416 | int ret ; | ||
417 | int smrtd ; | ||
418 | int wait_sym ; | ||
419 | |||
420 | u32 wait_t; | ||
421 | unsigned char S[3] ; | ||
422 | int i ; | ||
423 | |||
424 | if (*SIG > 45) { | ||
425 | if (CNTM_set(state, 2, 1, 2) < 0) { | ||
426 | dprintk(verbose, MB86A16_ERROR, 1, "CNTM set Error"); | ||
427 | return -1; | ||
428 | } | ||
429 | wait_sym = 40000; | ||
430 | } else { | ||
431 | if (CNTM_set(state, 3, 1, 2) < 0) { | ||
432 | dprintk(verbose, MB86A16_ERROR, 1, "CNTM set Error"); | ||
433 | return -1; | ||
434 | } | ||
435 | wait_sym = 80000; | ||
436 | } | ||
437 | for (i = 0; i < 3; i++) { | ||
438 | if (i == 0) | ||
439 | smrtd = smrt * 98 / 100; | ||
440 | else if (i == 1) | ||
441 | smrtd = smrt; | ||
442 | else | ||
443 | smrtd = smrt * 102 / 100; | ||
444 | smrt_info_get(state, smrtd); | ||
445 | smrt_set(state, smrtd); | ||
446 | srst(state); | ||
447 | wait_t = (wait_sym + 99 * smrtd / 100) / smrtd; | ||
448 | if (wait_t == 0) | ||
449 | wait_t = 1; | ||
450 | msleep_interruptible(10); | ||
451 | if (mb86a16_read(state, 0x37, &(S[i])) != 2) { | ||
452 | dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); | ||
453 | return -EREMOTEIO; | ||
454 | } | ||
455 | } | ||
456 | if ((S[1] > S[0] * 112 / 100) && | ||
457 | (S[1] > S[2] * 112 / 100)) { | ||
458 | |||
459 | ret = 1; | ||
460 | } else { | ||
461 | ret = 0; | ||
462 | } | ||
463 | *SIG = S[1]; | ||
464 | |||
465 | if (CNTM_set(state, 0, 1, 2) < 0) { | ||
466 | dprintk(verbose, MB86A16_ERROR, 1, "CNTM set Error"); | ||
467 | return -1; | ||
468 | } | ||
469 | |||
470 | return ret; | ||
471 | } | ||
472 | |||
473 | static int rf_val_set(struct mb86a16_state *state, | ||
474 | int f, | ||
475 | int smrt, | ||
476 | unsigned char R) | ||
477 | { | ||
478 | unsigned char C, F, B; | ||
479 | int M; | ||
480 | unsigned char rf_val[5]; | ||
481 | int ack = -1; | ||
482 | |||
483 | if (smrt > 37750) | ||
484 | C = 1; | ||
485 | else if (smrt > 18875) | ||
486 | C = 2; | ||
487 | else if (smrt > 5500) | ||
488 | C = 3; | ||
489 | else | ||
490 | C = 4; | ||
491 | |||
492 | if (smrt > 30500) | ||
493 | F = 3; | ||
494 | else if (smrt > 9375) | ||
495 | F = 1; | ||
496 | else if (smrt > 4625) | ||
497 | F = 0; | ||
498 | else | ||
499 | F = 2; | ||
500 | |||
501 | if (f < 1060) | ||
502 | B = 0; | ||
503 | else if (f < 1175) | ||
504 | B = 1; | ||
505 | else if (f < 1305) | ||
506 | B = 2; | ||
507 | else if (f < 1435) | ||
508 | B = 3; | ||
509 | else if (f < 1570) | ||
510 | B = 4; | ||
511 | else if (f < 1715) | ||
512 | B = 5; | ||
513 | else if (f < 1845) | ||
514 | B = 6; | ||
515 | else if (f < 1980) | ||
516 | B = 7; | ||
517 | else if (f < 2080) | ||
518 | B = 8; | ||
519 | else | ||
520 | B = 9; | ||
521 | |||
522 | M = f * (1 << R) / 2; | ||
523 | |||
524 | rf_val[0] = 0x01 | (C << 3) | (F << 1); | ||
525 | rf_val[1] = (R << 5) | ((M & 0x1f000) >> 12); | ||
526 | rf_val[2] = (M & 0x00ff0) >> 4; | ||
527 | rf_val[3] = ((M & 0x0000f) << 4) | B; | ||
528 | |||
529 | /* Frequency Set */ | ||
530 | if (mb86a16_write(state, 0x21, rf_val[0]) < 0) | ||
531 | ack = 0; | ||
532 | if (mb86a16_write(state, 0x22, rf_val[1]) < 0) | ||
533 | ack = 0; | ||
534 | if (mb86a16_write(state, 0x23, rf_val[2]) < 0) | ||
535 | ack = 0; | ||
536 | if (mb86a16_write(state, 0x24, rf_val[3]) < 0) | ||
537 | ack = 0; | ||
538 | if (mb86a16_write(state, 0x25, 0x01) < 0) | ||
539 | ack = 0; | ||
540 | if (ack == 0) { | ||
541 | dprintk(verbose, MB86A16_ERROR, 1, "RF Setup - I2C transfer error"); | ||
542 | return -EREMOTEIO; | ||
543 | } | ||
544 | |||
545 | return 0; | ||
546 | } | ||
547 | |||
548 | static int afcerr_chk(struct mb86a16_state *state) | ||
549 | { | ||
550 | unsigned char AFCM_L, AFCM_H ; | ||
551 | int AFCM ; | ||
552 | int afcm, afcerr ; | ||
553 | |||
554 | if (mb86a16_read(state, 0x0e, &AFCM_L) != 2) | ||
555 | goto err; | ||
556 | if (mb86a16_read(state, 0x0f, &AFCM_H) != 2) | ||
557 | goto err; | ||
558 | |||
559 | AFCM = (AFCM_H << 8) + AFCM_L; | ||
560 | |||
561 | if (AFCM > 2048) | ||
562 | afcm = AFCM - 4096; | ||
563 | else | ||
564 | afcm = AFCM; | ||
565 | afcerr = afcm * state->master_clk / 8192; | ||
566 | |||
567 | return afcerr; | ||
568 | |||
569 | err: | ||
570 | dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); | ||
571 | return -EREMOTEIO; | ||
572 | } | ||
573 | |||
574 | static int dagcm_val_get(struct mb86a16_state *state) | ||
575 | { | ||
576 | int DAGCM; | ||
577 | unsigned char DAGCM_H, DAGCM_L; | ||
578 | |||
579 | if (mb86a16_read(state, 0x45, &DAGCM_L) != 2) | ||
580 | goto err; | ||
581 | if (mb86a16_read(state, 0x46, &DAGCM_H) != 2) | ||
582 | goto err; | ||
583 | |||
584 | DAGCM = (DAGCM_H << 8) + DAGCM_L; | ||
585 | |||
586 | return DAGCM; | ||
587 | |||
588 | err: | ||
589 | dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); | ||
590 | return -EREMOTEIO; | ||
591 | } | ||
592 | |||
593 | static int mb86a16_read_status(struct dvb_frontend *fe, fe_status_t *status) | ||
594 | { | ||
595 | u8 stat, stat2; | ||
596 | struct mb86a16_state *state = fe->demodulator_priv; | ||
597 | |||
598 | *status = 0; | ||
599 | |||
600 | if (mb86a16_read(state, MB86A16_SIG1, &stat) != 2) | ||
601 | goto err; | ||
602 | if (mb86a16_read(state, MB86A16_SIG2, &stat2) != 2) | ||
603 | goto err; | ||
604 | if ((stat > 25) && (stat2 > 25)) | ||
605 | *status |= FE_HAS_SIGNAL; | ||
606 | if ((stat > 45) && (stat2 > 45)) | ||
607 | *status |= FE_HAS_CARRIER; | ||
608 | |||
609 | if (mb86a16_read(state, MB86A16_STATUS, &stat) != 2) | ||
610 | goto err; | ||
611 | |||
612 | if (stat & 0x01) | ||
613 | *status |= FE_HAS_SYNC; | ||
614 | if (stat & 0x01) | ||
615 | *status |= FE_HAS_VITERBI; | ||
616 | |||
617 | if (mb86a16_read(state, MB86A16_FRAMESYNC, &stat) != 2) | ||
618 | goto err; | ||
619 | |||
620 | if ((stat & 0x0f) && (*status & FE_HAS_VITERBI)) | ||
621 | *status |= FE_HAS_LOCK; | ||
622 | |||
623 | return 0; | ||
624 | |||
625 | err: | ||
626 | dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); | ||
627 | return -EREMOTEIO; | ||
628 | } | ||
629 | |||
630 | static int sync_chk(struct mb86a16_state *state, | ||
631 | unsigned char *VIRM) | ||
632 | { | ||
633 | unsigned char val; | ||
634 | int sync; | ||
635 | |||
636 | if (mb86a16_read(state, 0x0d, &val) != 2) | ||
637 | goto err; | ||
638 | |||
639 | dprintk(verbose, MB86A16_INFO, 1, "Status = %02x,", val); | ||
640 | sync = val & 0x01; | ||
641 | *VIRM = (val & 0x1c) >> 2; | ||
642 | |||
643 | return sync; | ||
644 | err: | ||
645 | dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); | ||
646 | return -EREMOTEIO; | ||
647 | |||
648 | } | ||
649 | |||
650 | static int freqerr_chk(struct mb86a16_state *state, | ||
651 | int fTP, | ||
652 | int smrt, | ||
653 | int unit) | ||
654 | { | ||
655 | unsigned char CRM, AFCML, AFCMH; | ||
656 | unsigned char temp1, temp2, temp3; | ||
657 | int crm, afcm, AFCM; | ||
658 | int crrerr, afcerr; /* kHz */ | ||
659 | int frqerr; /* MHz */ | ||
660 | int afcen, afcexen = 0; | ||
661 | int R, M, fOSC, fOSC_OFS; | ||
662 | |||
663 | if (mb86a16_read(state, 0x43, &CRM) != 2) | ||
664 | goto err; | ||
665 | |||
666 | if (CRM > 127) | ||
667 | crm = CRM - 256; | ||
668 | else | ||
669 | crm = CRM; | ||
670 | |||
671 | crrerr = smrt * crm / 256; | ||
672 | if (mb86a16_read(state, 0x49, &temp1) != 2) | ||
673 | goto err; | ||
674 | |||
675 | afcen = (temp1 & 0x04) >> 2; | ||
676 | if (afcen == 0) { | ||
677 | if (mb86a16_read(state, 0x2a, &temp1) != 2) | ||
678 | goto err; | ||
679 | afcexen = (temp1 & 0x20) >> 5; | ||
680 | } | ||
681 | |||
682 | if (afcen == 1) { | ||
683 | if (mb86a16_read(state, 0x0e, &AFCML) != 2) | ||
684 | goto err; | ||
685 | if (mb86a16_read(state, 0x0f, &AFCMH) != 2) | ||
686 | goto err; | ||
687 | } else if (afcexen == 1) { | ||
688 | if (mb86a16_read(state, 0x2b, &AFCML) != 2) | ||
689 | goto err; | ||
690 | if (mb86a16_read(state, 0x2c, &AFCMH) != 2) | ||
691 | goto err; | ||
692 | } | ||
693 | if ((afcen == 1) || (afcexen == 1)) { | ||
694 | smrt_info_get(state, smrt); | ||
695 | AFCM = ((AFCMH & 0x01) << 8) + AFCML; | ||
696 | if (AFCM > 255) | ||
697 | afcm = AFCM - 512; | ||
698 | else | ||
699 | afcm = AFCM; | ||
700 | |||
701 | afcerr = afcm * state->master_clk / 8192; | ||
702 | } else | ||
703 | afcerr = 0; | ||
704 | |||
705 | if (mb86a16_read(state, 0x22, &temp1) != 2) | ||
706 | goto err; | ||
707 | if (mb86a16_read(state, 0x23, &temp2) != 2) | ||
708 | goto err; | ||
709 | if (mb86a16_read(state, 0x24, &temp3) != 2) | ||
710 | goto err; | ||
711 | |||
712 | R = (temp1 & 0xe0) >> 5; | ||
713 | M = ((temp1 & 0x1f) << 12) + (temp2 << 4) + (temp3 >> 4); | ||
714 | if (R == 0) | ||
715 | fOSC = 2 * M; | ||
716 | else | ||
717 | fOSC = M; | ||
718 | |||
719 | fOSC_OFS = fOSC - fTP; | ||
720 | |||
721 | if (unit == 0) { /* MHz */ | ||
722 | if (crrerr + afcerr + fOSC_OFS * 1000 >= 0) | ||
723 | frqerr = (crrerr + afcerr + fOSC_OFS * 1000 + 500) / 1000; | ||
724 | else | ||
725 | frqerr = (crrerr + afcerr + fOSC_OFS * 1000 - 500) / 1000; | ||
726 | } else { /* kHz */ | ||
727 | frqerr = crrerr + afcerr + fOSC_OFS * 1000; | ||
728 | } | ||
729 | |||
730 | return frqerr; | ||
731 | err: | ||
732 | dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); | ||
733 | return -EREMOTEIO; | ||
734 | } | ||
735 | |||
736 | static unsigned char vco_dev_get(struct mb86a16_state *state, int smrt) | ||
737 | { | ||
738 | unsigned char R; | ||
739 | |||
740 | if (smrt > 9375) | ||
741 | R = 0; | ||
742 | else | ||
743 | R = 1; | ||
744 | |||
745 | return R; | ||
746 | } | ||
747 | |||
748 | static void swp_info_get(struct mb86a16_state *state, | ||
749 | int fOSC_start, | ||
750 | int smrt, | ||
751 | int v, int R, | ||
752 | int swp_ofs, | ||
753 | int *fOSC, | ||
754 | int *afcex_freq, | ||
755 | unsigned char *AFCEX_L, | ||
756 | unsigned char *AFCEX_H) | ||
757 | { | ||
758 | int AFCEX ; | ||
759 | int crnt_swp_freq ; | ||
760 | |||
761 | crnt_swp_freq = fOSC_start * 1000 + v * swp_ofs; | ||
762 | |||
763 | if (R == 0) | ||
764 | *fOSC = (crnt_swp_freq + 1000) / 2000 * 2; | ||
765 | else | ||
766 | *fOSC = (crnt_swp_freq + 500) / 1000; | ||
767 | |||
768 | if (*fOSC >= crnt_swp_freq) | ||
769 | *afcex_freq = *fOSC * 1000 - crnt_swp_freq; | ||
770 | else | ||
771 | *afcex_freq = crnt_swp_freq - *fOSC * 1000; | ||
772 | |||
773 | AFCEX = *afcex_freq * 8192 / state->master_clk; | ||
774 | *AFCEX_L = AFCEX & 0x00ff; | ||
775 | *AFCEX_H = (AFCEX & 0x0f00) >> 8; | ||
776 | } | ||
777 | |||
778 | |||
779 | static int swp_freq_calcuation(struct mb86a16_state *state, int i, int v, int *V, int vmax, int vmin, | ||
780 | int SIGMIN, int fOSC, int afcex_freq, int swp_ofs, unsigned char *SIG1) | ||
781 | { | ||
782 | int swp_freq ; | ||
783 | |||
784 | if ((i % 2 == 1) && (v <= vmax)) { | ||
785 | /* positive v (case 1) */ | ||
786 | if ((v - 1 == vmin) && | ||
787 | (*(V + 30 + v) >= 0) && | ||
788 | (*(V + 30 + v - 1) >= 0) && | ||
789 | (*(V + 30 + v - 1) > *(V + 30 + v)) && | ||
790 | (*(V + 30 + v - 1) > SIGMIN)) { | ||
791 | |||
792 | swp_freq = fOSC * 1000 + afcex_freq - swp_ofs; | ||
793 | *SIG1 = *(V + 30 + v - 1); | ||
794 | } else if ((v == vmax) && | ||
795 | (*(V + 30 + v) >= 0) && | ||
796 | (*(V + 30 + v - 1) >= 0) && | ||
797 | (*(V + 30 + v) > *(V + 30 + v - 1)) && | ||
798 | (*(V + 30 + v) > SIGMIN)) { | ||
799 | /* (case 2) */ | ||
800 | swp_freq = fOSC * 1000 + afcex_freq; | ||
801 | *SIG1 = *(V + 30 + v); | ||
802 | } else if ((*(V + 30 + v) > 0) && | ||
803 | (*(V + 30 + v - 1) > 0) && | ||
804 | (*(V + 30 + v - 2) > 0) && | ||
805 | (*(V + 30 + v - 3) > 0) && | ||
806 | (*(V + 30 + v - 1) > *(V + 30 + v)) && | ||
807 | (*(V + 30 + v - 2) > *(V + 30 + v - 3)) && | ||
808 | ((*(V + 30 + v - 1) > SIGMIN) || | ||
809 | (*(V + 30 + v - 2) > SIGMIN))) { | ||
810 | /* (case 3) */ | ||
811 | if (*(V + 30 + v - 1) >= *(V + 30 + v - 2)) { | ||
812 | swp_freq = fOSC * 1000 + afcex_freq - swp_ofs; | ||
813 | *SIG1 = *(V + 30 + v - 1); | ||
814 | } else { | ||
815 | swp_freq = fOSC * 1000 + afcex_freq - swp_ofs * 2; | ||
816 | *SIG1 = *(V + 30 + v - 2); | ||
817 | } | ||
818 | } else if ((v == vmax) && | ||
819 | (*(V + 30 + v) >= 0) && | ||
820 | (*(V + 30 + v - 1) >= 0) && | ||
821 | (*(V + 30 + v - 2) >= 0) && | ||
822 | (*(V + 30 + v) > *(V + 30 + v - 2)) && | ||
823 | (*(V + 30 + v - 1) > *(V + 30 + v - 2)) && | ||
824 | ((*(V + 30 + v) > SIGMIN) || | ||
825 | (*(V + 30 + v - 1) > SIGMIN))) { | ||
826 | /* (case 4) */ | ||
827 | if (*(V + 30 + v) >= *(V + 30 + v - 1)) { | ||
828 | swp_freq = fOSC * 1000 + afcex_freq; | ||
829 | *SIG1 = *(V + 30 + v); | ||
830 | } else { | ||
831 | swp_freq = fOSC * 1000 + afcex_freq - swp_ofs; | ||
832 | *SIG1 = *(V + 30 + v - 1); | ||
833 | } | ||
834 | } else { | ||
835 | swp_freq = -1 ; | ||
836 | } | ||
837 | } else if ((i % 2 == 0) && (v >= vmin)) { | ||
838 | /* Negative v (case 1) */ | ||
839 | if ((*(V + 30 + v) > 0) && | ||
840 | (*(V + 30 + v + 1) > 0) && | ||
841 | (*(V + 30 + v + 2) > 0) && | ||
842 | (*(V + 30 + v + 1) > *(V + 30 + v)) && | ||
843 | (*(V + 30 + v + 1) > *(V + 30 + v + 2)) && | ||
844 | (*(V + 30 + v + 1) > SIGMIN)) { | ||
845 | |||
846 | swp_freq = fOSC * 1000 + afcex_freq + swp_ofs; | ||
847 | *SIG1 = *(V + 30 + v + 1); | ||
848 | } else if ((v + 1 == vmax) && | ||
849 | (*(V + 30 + v) >= 0) && | ||
850 | (*(V + 30 + v + 1) >= 0) && | ||
851 | (*(V + 30 + v + 1) > *(V + 30 + v)) && | ||
852 | (*(V + 30 + v + 1) > SIGMIN)) { | ||
853 | /* (case 2) */ | ||
854 | swp_freq = fOSC * 1000 + afcex_freq + swp_ofs; | ||
855 | *SIG1 = *(V + 30 + v); | ||
856 | } else if ((v == vmin) && | ||
857 | (*(V + 30 + v) > 0) && | ||
858 | (*(V + 30 + v + 1) > 0) && | ||
859 | (*(V + 30 + v + 2) > 0) && | ||
860 | (*(V + 30 + v) > *(V + 30 + v + 1)) && | ||
861 | (*(V + 30 + v) > *(V + 30 + v + 2)) && | ||
862 | (*(V + 30 + v) > SIGMIN)) { | ||
863 | /* (case 3) */ | ||
864 | swp_freq = fOSC * 1000 + afcex_freq; | ||
865 | *SIG1 = *(V + 30 + v); | ||
866 | } else if ((*(V + 30 + v) >= 0) && | ||
867 | (*(V + 30 + v + 1) >= 0) && | ||
868 | (*(V + 30 + v + 2) >= 0) && | ||
869 | (*(V + 30 + v + 3) >= 0) && | ||
870 | (*(V + 30 + v + 1) > *(V + 30 + v)) && | ||
871 | (*(V + 30 + v + 2) > *(V + 30 + v + 3)) && | ||
872 | ((*(V + 30 + v + 1) > SIGMIN) || | ||
873 | (*(V + 30 + v + 2) > SIGMIN))) { | ||
874 | /* (case 4) */ | ||
875 | if (*(V + 30 + v + 1) >= *(V + 30 + v + 2)) { | ||
876 | swp_freq = fOSC * 1000 + afcex_freq + swp_ofs; | ||
877 | *SIG1 = *(V + 30 + v + 1); | ||
878 | } else { | ||
879 | swp_freq = fOSC * 1000 + afcex_freq + swp_ofs * 2; | ||
880 | *SIG1 = *(V + 30 + v + 2); | ||
881 | } | ||
882 | } else if ((*(V + 30 + v) >= 0) && | ||
883 | (*(V + 30 + v + 1) >= 0) && | ||
884 | (*(V + 30 + v + 2) >= 0) && | ||
885 | (*(V + 30 + v + 3) >= 0) && | ||
886 | (*(V + 30 + v) > *(V + 30 + v + 2)) && | ||
887 | (*(V + 30 + v + 1) > *(V + 30 + v + 2)) && | ||
888 | (*(V + 30 + v) > *(V + 30 + v + 3)) && | ||
889 | (*(V + 30 + v + 1) > *(V + 30 + v + 3)) && | ||
890 | ((*(V + 30 + v) > SIGMIN) || | ||
891 | (*(V + 30 + v + 1) > SIGMIN))) { | ||
892 | /* (case 5) */ | ||
893 | if (*(V + 30 + v) >= *(V + 30 + v + 1)) { | ||
894 | swp_freq = fOSC * 1000 + afcex_freq; | ||
895 | *SIG1 = *(V + 30 + v); | ||
896 | } else { | ||
897 | swp_freq = fOSC * 1000 + afcex_freq + swp_ofs; | ||
898 | *SIG1 = *(V + 30 + v + 1); | ||
899 | } | ||
900 | } else if ((v + 2 == vmin) && | ||
901 | (*(V + 30 + v) >= 0) && | ||
902 | (*(V + 30 + v + 1) >= 0) && | ||
903 | (*(V + 30 + v + 2) >= 0) && | ||
904 | (*(V + 30 + v + 1) > *(V + 30 + v)) && | ||
905 | (*(V + 30 + v + 2) > *(V + 30 + v)) && | ||
906 | ((*(V + 30 + v + 1) > SIGMIN) || | ||
907 | (*(V + 30 + v + 2) > SIGMIN))) { | ||
908 | /* (case 6) */ | ||
909 | if (*(V + 30 + v + 1) >= *(V + 30 + v + 2)) { | ||
910 | swp_freq = fOSC * 1000 + afcex_freq + swp_ofs; | ||
911 | *SIG1 = *(V + 30 + v + 1); | ||
912 | } else { | ||
913 | swp_freq = fOSC * 1000 + afcex_freq + swp_ofs * 2; | ||
914 | *SIG1 = *(V + 30 + v + 2); | ||
915 | } | ||
916 | } else if ((vmax == 0) && (vmin == 0) && (*(V + 30 + v) > SIGMIN)) { | ||
917 | swp_freq = fOSC * 1000; | ||
918 | *SIG1 = *(V + 30 + v); | ||
919 | } else | ||
920 | swp_freq = -1; | ||
921 | } else | ||
922 | swp_freq = -1; | ||
923 | |||
924 | return swp_freq; | ||
925 | } | ||
926 | |||
927 | static void swp_info_get2(struct mb86a16_state *state, | ||
928 | int smrt, | ||
929 | int R, | ||
930 | int swp_freq, | ||
931 | int *afcex_freq, | ||
932 | int *fOSC, | ||
933 | unsigned char *AFCEX_L, | ||
934 | unsigned char *AFCEX_H) | ||
935 | { | ||
936 | int AFCEX ; | ||
937 | |||
938 | if (R == 0) | ||
939 | *fOSC = (swp_freq + 1000) / 2000 * 2; | ||
940 | else | ||
941 | *fOSC = (swp_freq + 500) / 1000; | ||
942 | |||
943 | if (*fOSC >= swp_freq) | ||
944 | *afcex_freq = *fOSC * 1000 - swp_freq; | ||
945 | else | ||
946 | *afcex_freq = swp_freq - *fOSC * 1000; | ||
947 | |||
948 | AFCEX = *afcex_freq * 8192 / state->master_clk; | ||
949 | *AFCEX_L = AFCEX & 0x00ff; | ||
950 | *AFCEX_H = (AFCEX & 0x0f00) >> 8; | ||
951 | } | ||
952 | |||
953 | static void afcex_info_get(struct mb86a16_state *state, | ||
954 | int afcex_freq, | ||
955 | unsigned char *AFCEX_L, | ||
956 | unsigned char *AFCEX_H) | ||
957 | { | ||
958 | int AFCEX ; | ||
959 | |||
960 | AFCEX = afcex_freq * 8192 / state->master_clk; | ||
961 | *AFCEX_L = AFCEX & 0x00ff; | ||
962 | *AFCEX_H = (AFCEX & 0x0f00) >> 8; | ||
963 | } | ||
964 | |||
965 | static int SEQ_set(struct mb86a16_state *state, unsigned char loop) | ||
966 | { | ||
967 | /* SLOCK0 = 0 */ | ||
968 | if (mb86a16_write(state, 0x32, 0x02 | (loop << 2)) < 0) { | ||
969 | dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); | ||
970 | return -EREMOTEIO; | ||
971 | } | ||
972 | |||
973 | return 0; | ||
974 | } | ||
975 | |||
976 | static int iq_vt_set(struct mb86a16_state *state, unsigned char IQINV) | ||
977 | { | ||
978 | /* Viterbi Rate, IQ Settings */ | ||
979 | if (mb86a16_write(state, 0x06, 0xdf | (IQINV << 5)) < 0) { | ||
980 | dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); | ||
981 | return -EREMOTEIO; | ||
982 | } | ||
983 | |||
984 | return 0; | ||
985 | } | ||
986 | |||
987 | static int FEC_srst(struct mb86a16_state *state) | ||
988 | { | ||
989 | if (mb86a16_write(state, MB86A16_RESET, 0x02) < 0) { | ||
990 | dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); | ||
991 | return -EREMOTEIO; | ||
992 | } | ||
993 | |||
994 | return 0; | ||
995 | } | ||
996 | |||
997 | static int S2T_set(struct mb86a16_state *state, unsigned char S2T) | ||
998 | { | ||
999 | if (mb86a16_write(state, 0x34, 0x70 | S2T) < 0) { | ||
1000 | dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); | ||
1001 | return -EREMOTEIO; | ||
1002 | } | ||
1003 | |||
1004 | return 0; | ||
1005 | } | ||
1006 | |||
1007 | static int S45T_set(struct mb86a16_state *state, unsigned char S4T, unsigned char S5T) | ||
1008 | { | ||
1009 | if (mb86a16_write(state, 0x35, 0x00 | (S5T << 4) | S4T) < 0) { | ||
1010 | dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); | ||
1011 | return -EREMOTEIO; | ||
1012 | } | ||
1013 | |||
1014 | return 0; | ||
1015 | } | ||
1016 | |||
1017 | |||
1018 | static int mb86a16_set_fe(struct mb86a16_state *state) | ||
1019 | { | ||
1020 | u8 agcval, cnmval; | ||
1021 | |||
1022 | int i, j; | ||
1023 | int fOSC = 0; | ||
1024 | int fOSC_start = 0; | ||
1025 | int wait_t; | ||
1026 | int fcp; | ||
1027 | int swp_ofs; | ||
1028 | int V[60]; | ||
1029 | u8 SIG1MIN; | ||
1030 | |||
1031 | unsigned char CREN, AFCEN, AFCEXEN; | ||
1032 | unsigned char SIG1; | ||
1033 | unsigned char TIMINT1, TIMINT2, TIMEXT; | ||
1034 | unsigned char S0T, S1T; | ||
1035 | unsigned char S2T; | ||
1036 | /* unsigned char S2T, S3T; */ | ||
1037 | unsigned char S4T, S5T; | ||
1038 | unsigned char AFCEX_L, AFCEX_H; | ||
1039 | unsigned char R; | ||
1040 | unsigned char VIRM; | ||
1041 | unsigned char ETH, VIA; | ||
1042 | unsigned char junk; | ||
1043 | |||
1044 | int loop; | ||
1045 | int ftemp; | ||
1046 | int v, vmax, vmin; | ||
1047 | int vmax_his, vmin_his; | ||
1048 | int swp_freq, prev_swp_freq[20]; | ||
1049 | int prev_freq_num; | ||
1050 | int signal_dupl; | ||
1051 | int afcex_freq; | ||
1052 | int signal; | ||
1053 | int afcerr; | ||
1054 | int temp_freq, delta_freq; | ||
1055 | int dagcm[4]; | ||
1056 | int smrt_d; | ||
1057 | /* int freq_err; */ | ||
1058 | int n; | ||
1059 | int ret = -1; | ||
1060 | int sync; | ||
1061 | |||
1062 | dprintk(verbose, MB86A16_INFO, 1, "freq=%d Mhz, symbrt=%d Ksps", state->frequency, state->srate); | ||
1063 | |||
1064 | fcp = 3000; | ||
1065 | swp_ofs = state->srate / 4; | ||
1066 | |||
1067 | for (i = 0; i < 60; i++) | ||
1068 | V[i] = -1; | ||
1069 | |||
1070 | for (i = 0; i < 20; i++) | ||
1071 | prev_swp_freq[i] = 0; | ||
1072 | |||
1073 | SIG1MIN = 25; | ||
1074 | |||
1075 | for (n = 0; ((n < 3) && (ret == -1)); n++) { | ||
1076 | SEQ_set(state, 0); | ||
1077 | iq_vt_set(state, 0); | ||
1078 | |||
1079 | CREN = 0; | ||
1080 | AFCEN = 0; | ||
1081 | AFCEXEN = 1; | ||
1082 | TIMINT1 = 0; | ||
1083 | TIMINT2 = 1; | ||
1084 | TIMEXT = 2; | ||
1085 | S1T = 0; | ||
1086 | S0T = 0; | ||
1087 | |||
1088 | if (initial_set(state) < 0) { | ||
1089 | dprintk(verbose, MB86A16_ERROR, 1, "initial set failed"); | ||
1090 | return -1; | ||
1091 | } | ||
1092 | if (DAGC_data_set(state, 3, 2) < 0) { | ||
1093 | dprintk(verbose, MB86A16_ERROR, 1, "DAGC data set error"); | ||
1094 | return -1; | ||
1095 | } | ||
1096 | if (EN_set(state, CREN, AFCEN) < 0) { | ||
1097 | dprintk(verbose, MB86A16_ERROR, 1, "EN set error"); | ||
1098 | return -1; /* (0, 0) */ | ||
1099 | } | ||
1100 | if (AFCEXEN_set(state, AFCEXEN, state->srate) < 0) { | ||
1101 | dprintk(verbose, MB86A16_ERROR, 1, "AFCEXEN set error"); | ||
1102 | return -1; /* (1, smrt) = (1, symbolrate) */ | ||
1103 | } | ||
1104 | if (CNTM_set(state, TIMINT1, TIMINT2, TIMEXT) < 0) { | ||
1105 | dprintk(verbose, MB86A16_ERROR, 1, "CNTM set error"); | ||
1106 | return -1; /* (0, 1, 2) */ | ||
1107 | } | ||
1108 | if (S01T_set(state, S1T, S0T) < 0) { | ||
1109 | dprintk(verbose, MB86A16_ERROR, 1, "S01T set error"); | ||
1110 | return -1; /* (0, 0) */ | ||
1111 | } | ||
1112 | smrt_info_get(state, state->srate); | ||
1113 | if (smrt_set(state, state->srate) < 0) { | ||
1114 | dprintk(verbose, MB86A16_ERROR, 1, "smrt info get error"); | ||
1115 | return -1; | ||
1116 | } | ||
1117 | |||
1118 | R = vco_dev_get(state, state->srate); | ||
1119 | if (R == 1) | ||
1120 | fOSC_start = state->frequency; | ||
1121 | |||
1122 | else if (R == 0) { | ||
1123 | if (state->frequency % 2 == 0) { | ||
1124 | fOSC_start = state->frequency; | ||
1125 | } else { | ||
1126 | fOSC_start = state->frequency + 1; | ||
1127 | if (fOSC_start > 2150) | ||
1128 | fOSC_start = state->frequency - 1; | ||
1129 | } | ||
1130 | } | ||
1131 | loop = 1; | ||
1132 | ftemp = fOSC_start * 1000; | ||
1133 | vmax = 0 ; | ||
1134 | while (loop == 1) { | ||
1135 | ftemp = ftemp + swp_ofs; | ||
1136 | vmax++; | ||
1137 | |||
1138 | /* Upper bound */ | ||
1139 | if (ftemp > 2150000) { | ||
1140 | loop = 0; | ||
1141 | vmax--; | ||
1142 | } else { | ||
1143 | if ((ftemp == 2150000) || | ||
1144 | (ftemp - state->frequency * 1000 >= fcp + state->srate / 4)) | ||
1145 | loop = 0; | ||
1146 | } | ||
1147 | } | ||
1148 | |||
1149 | loop = 1; | ||
1150 | ftemp = fOSC_start * 1000; | ||
1151 | vmin = 0 ; | ||
1152 | while (loop == 1) { | ||
1153 | ftemp = ftemp - swp_ofs; | ||
1154 | vmin--; | ||
1155 | |||
1156 | /* Lower bound */ | ||
1157 | if (ftemp < 950000) { | ||
1158 | loop = 0; | ||
1159 | vmin++; | ||
1160 | } else { | ||
1161 | if ((ftemp == 950000) || | ||
1162 | (state->frequency * 1000 - ftemp >= fcp + state->srate / 4)) | ||
1163 | loop = 0; | ||
1164 | } | ||
1165 | } | ||
1166 | |||
1167 | wait_t = (8000 + state->srate / 2) / state->srate; | ||
1168 | if (wait_t == 0) | ||
1169 | wait_t = 1; | ||
1170 | |||
1171 | i = 0; | ||
1172 | j = 0; | ||
1173 | prev_freq_num = 0; | ||
1174 | loop = 1; | ||
1175 | signal = 0; | ||
1176 | vmax_his = 0; | ||
1177 | vmin_his = 0; | ||
1178 | v = 0; | ||
1179 | |||
1180 | while (loop == 1) { | ||
1181 | swp_info_get(state, fOSC_start, state->srate, | ||
1182 | v, R, swp_ofs, &fOSC, | ||
1183 | &afcex_freq, &AFCEX_L, &AFCEX_H); | ||
1184 | |||
1185 | udelay(100); | ||
1186 | if (rf_val_set(state, fOSC, state->srate, R) < 0) { | ||
1187 | dprintk(verbose, MB86A16_ERROR, 1, "rf val set error"); | ||
1188 | return -1; | ||
1189 | } | ||
1190 | udelay(100); | ||
1191 | if (afcex_data_set(state, AFCEX_L, AFCEX_H) < 0) { | ||
1192 | dprintk(verbose, MB86A16_ERROR, 1, "afcex data set error"); | ||
1193 | return -1; | ||
1194 | } | ||
1195 | if (srst(state) < 0) { | ||
1196 | dprintk(verbose, MB86A16_ERROR, 1, "srst error"); | ||
1197 | return -1; | ||
1198 | } | ||
1199 | msleep_interruptible(wait_t); | ||
1200 | |||
1201 | if (mb86a16_read(state, 0x37, &SIG1) != 2) { | ||
1202 | dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); | ||
1203 | return -1; | ||
1204 | } | ||
1205 | V[30 + v] = SIG1 ; | ||
1206 | swp_freq = swp_freq_calcuation(state, i, v, V, vmax, vmin, | ||
1207 | SIG1MIN, fOSC, afcex_freq, | ||
1208 | swp_ofs, &SIG1); /* changed */ | ||
1209 | |||
1210 | signal_dupl = 0; | ||
1211 | for (j = 0; j < prev_freq_num; j++) { | ||
1212 | if ((ABS(prev_swp_freq[j] - swp_freq)) < (swp_ofs * 3 / 2)) { | ||
1213 | signal_dupl = 1; | ||
1214 | dprintk(verbose, MB86A16_INFO, 1, "Probably Duplicate Signal, j = %d", j); | ||
1215 | } | ||
1216 | } | ||
1217 | if ((signal_dupl == 0) && (swp_freq > 0) && (ABS(swp_freq - state->frequency * 1000) < fcp + state->srate / 6)) { | ||
1218 | dprintk(verbose, MB86A16_DEBUG, 1, "------ Signal detect ------ [swp_freq=[%07d, srate=%05d]]", swp_freq, state->srate); | ||
1219 | prev_swp_freq[prev_freq_num] = swp_freq; | ||
1220 | prev_freq_num++; | ||
1221 | swp_info_get2(state, state->srate, R, swp_freq, | ||
1222 | &afcex_freq, &fOSC, | ||
1223 | &AFCEX_L, &AFCEX_H); | ||
1224 | |||
1225 | if (rf_val_set(state, fOSC, state->srate, R) < 0) { | ||
1226 | dprintk(verbose, MB86A16_ERROR, 1, "rf val set error"); | ||
1227 | return -1; | ||
1228 | } | ||
1229 | if (afcex_data_set(state, AFCEX_L, AFCEX_H) < 0) { | ||
1230 | dprintk(verbose, MB86A16_ERROR, 1, "afcex data set error"); | ||
1231 | return -1; | ||
1232 | } | ||
1233 | signal = signal_det(state, state->srate, &SIG1); | ||
1234 | if (signal == 1) { | ||
1235 | dprintk(verbose, MB86A16_ERROR, 1, "***** Signal Found *****"); | ||
1236 | loop = 0; | ||
1237 | } else { | ||
1238 | dprintk(verbose, MB86A16_ERROR, 1, "!!!!! No signal !!!!!, try again..."); | ||
1239 | smrt_info_get(state, state->srate); | ||
1240 | if (smrt_set(state, state->srate) < 0) { | ||
1241 | dprintk(verbose, MB86A16_ERROR, 1, "smrt set error"); | ||
1242 | return -1; | ||
1243 | } | ||
1244 | } | ||
1245 | } | ||
1246 | if (v > vmax) | ||
1247 | vmax_his = 1 ; | ||
1248 | if (v < vmin) | ||
1249 | vmin_his = 1 ; | ||
1250 | i++; | ||
1251 | |||
1252 | if ((i % 2 == 1) && (vmax_his == 1)) | ||
1253 | i++; | ||
1254 | if ((i % 2 == 0) && (vmin_his == 1)) | ||
1255 | i++; | ||
1256 | |||
1257 | if (i % 2 == 1) | ||
1258 | v = (i + 1) / 2; | ||
1259 | else | ||
1260 | v = -i / 2; | ||
1261 | |||
1262 | if ((vmax_his == 1) && (vmin_his == 1)) | ||
1263 | loop = 0 ; | ||
1264 | } | ||
1265 | |||
1266 | if (signal == 1) { | ||
1267 | dprintk(verbose, MB86A16_INFO, 1, " Start Freq Error Check"); | ||
1268 | S1T = 7 ; | ||
1269 | S0T = 1 ; | ||
1270 | CREN = 0 ; | ||
1271 | AFCEN = 1 ; | ||
1272 | AFCEXEN = 0 ; | ||
1273 | |||
1274 | if (S01T_set(state, S1T, S0T) < 0) { | ||
1275 | dprintk(verbose, MB86A16_ERROR, 1, "S01T set error"); | ||
1276 | return -1; | ||
1277 | } | ||
1278 | smrt_info_get(state, state->srate); | ||
1279 | if (smrt_set(state, state->srate) < 0) { | ||
1280 | dprintk(verbose, MB86A16_ERROR, 1, "smrt set error"); | ||
1281 | return -1; | ||
1282 | } | ||
1283 | if (EN_set(state, CREN, AFCEN) < 0) { | ||
1284 | dprintk(verbose, MB86A16_ERROR, 1, "EN set error"); | ||
1285 | return -1; | ||
1286 | } | ||
1287 | if (AFCEXEN_set(state, AFCEXEN, state->srate) < 0) { | ||
1288 | dprintk(verbose, MB86A16_ERROR, 1, "AFCEXEN set error"); | ||
1289 | return -1; | ||
1290 | } | ||
1291 | afcex_info_get(state, afcex_freq, &AFCEX_L, &AFCEX_H); | ||
1292 | if (afcofs_data_set(state, AFCEX_L, AFCEX_H) < 0) { | ||
1293 | dprintk(verbose, MB86A16_ERROR, 1, "AFCOFS data set error"); | ||
1294 | return -1; | ||
1295 | } | ||
1296 | if (srst(state) < 0) { | ||
1297 | dprintk(verbose, MB86A16_ERROR, 1, "srst error"); | ||
1298 | return -1; | ||
1299 | } | ||
1300 | /* delay 4~200 */ | ||
1301 | wait_t = 200000 / state->master_clk + 200000 / state->srate; | ||
1302 | msleep(wait_t); | ||
1303 | afcerr = afcerr_chk(state); | ||
1304 | if (afcerr == -1) | ||
1305 | return -1; | ||
1306 | |||
1307 | swp_freq = fOSC * 1000 + afcerr ; | ||
1308 | AFCEXEN = 1 ; | ||
1309 | if (state->srate >= 1500) | ||
1310 | smrt_d = state->srate / 3; | ||
1311 | else | ||
1312 | smrt_d = state->srate / 2; | ||
1313 | smrt_info_get(state, smrt_d); | ||
1314 | if (smrt_set(state, smrt_d) < 0) { | ||
1315 | dprintk(verbose, MB86A16_ERROR, 1, "smrt set error"); | ||
1316 | return -1; | ||
1317 | } | ||
1318 | if (AFCEXEN_set(state, AFCEXEN, smrt_d) < 0) { | ||
1319 | dprintk(verbose, MB86A16_ERROR, 1, "AFCEXEN set error"); | ||
1320 | return -1; | ||
1321 | } | ||
1322 | R = vco_dev_get(state, smrt_d); | ||
1323 | if (DAGC_data_set(state, 2, 0) < 0) { | ||
1324 | dprintk(verbose, MB86A16_ERROR, 1, "DAGC data set error"); | ||
1325 | return -1; | ||
1326 | } | ||
1327 | for (i = 0; i < 3; i++) { | ||
1328 | temp_freq = swp_freq + (i - 1) * state->srate / 8; | ||
1329 | swp_info_get2(state, smrt_d, R, temp_freq, &afcex_freq, &fOSC, &AFCEX_L, &AFCEX_H); | ||
1330 | if (rf_val_set(state, fOSC, smrt_d, R) < 0) { | ||
1331 | dprintk(verbose, MB86A16_ERROR, 1, "rf val set error"); | ||
1332 | return -1; | ||
1333 | } | ||
1334 | if (afcex_data_set(state, AFCEX_L, AFCEX_H) < 0) { | ||
1335 | dprintk(verbose, MB86A16_ERROR, 1, "afcex data set error"); | ||
1336 | return -1; | ||
1337 | } | ||
1338 | wait_t = 200000 / state->master_clk + 40000 / smrt_d; | ||
1339 | msleep(wait_t); | ||
1340 | dagcm[i] = dagcm_val_get(state); | ||
1341 | } | ||
1342 | if ((dagcm[0] > dagcm[1]) && | ||
1343 | (dagcm[0] > dagcm[2]) && | ||
1344 | (dagcm[0] - dagcm[1] > 2 * (dagcm[2] - dagcm[1]))) { | ||
1345 | |||
1346 | temp_freq = swp_freq - 2 * state->srate / 8; | ||
1347 | swp_info_get2(state, smrt_d, R, temp_freq, &afcex_freq, &fOSC, &AFCEX_L, &AFCEX_H); | ||
1348 | if (rf_val_set(state, fOSC, smrt_d, R) < 0) { | ||
1349 | dprintk(verbose, MB86A16_ERROR, 1, "rf val set error"); | ||
1350 | return -1; | ||
1351 | } | ||
1352 | if (afcex_data_set(state, AFCEX_L, AFCEX_H) < 0) { | ||
1353 | dprintk(verbose, MB86A16_ERROR, 1, "afcex data set"); | ||
1354 | return -1; | ||
1355 | } | ||
1356 | wait_t = 200000 / state->master_clk + 40000 / smrt_d; | ||
1357 | msleep(wait_t); | ||
1358 | dagcm[3] = dagcm_val_get(state); | ||
1359 | if (dagcm[3] > dagcm[1]) | ||
1360 | delta_freq = (dagcm[2] - dagcm[0] + dagcm[1] - dagcm[3]) * state->srate / 300; | ||
1361 | else | ||
1362 | delta_freq = 0; | ||
1363 | } else if ((dagcm[2] > dagcm[1]) && | ||
1364 | (dagcm[2] > dagcm[0]) && | ||
1365 | (dagcm[2] - dagcm[1] > 2 * (dagcm[0] - dagcm[1]))) { | ||
1366 | |||
1367 | temp_freq = swp_freq + 2 * state->srate / 8; | ||
1368 | swp_info_get2(state, smrt_d, R, temp_freq, &afcex_freq, &fOSC, &AFCEX_L, &AFCEX_H); | ||
1369 | if (rf_val_set(state, fOSC, smrt_d, R) < 0) { | ||
1370 | dprintk(verbose, MB86A16_ERROR, 1, "rf val set"); | ||
1371 | return -1; | ||
1372 | } | ||
1373 | if (afcex_data_set(state, AFCEX_L, AFCEX_H) < 0) { | ||
1374 | dprintk(verbose, MB86A16_ERROR, 1, "afcex data set"); | ||
1375 | return -1; | ||
1376 | } | ||
1377 | wait_t = 200000 / state->master_clk + 40000 / smrt_d; | ||
1378 | msleep(wait_t); | ||
1379 | dagcm[3] = dagcm_val_get(state); | ||
1380 | if (dagcm[3] > dagcm[1]) | ||
1381 | delta_freq = (dagcm[2] - dagcm[0] + dagcm[3] - dagcm[1]) * state->srate / 300; | ||
1382 | else | ||
1383 | delta_freq = 0 ; | ||
1384 | |||
1385 | } else { | ||
1386 | delta_freq = 0 ; | ||
1387 | } | ||
1388 | dprintk(verbose, MB86A16_INFO, 1, "SWEEP Frequency = %d", swp_freq); | ||
1389 | swp_freq += delta_freq; | ||
1390 | dprintk(verbose, MB86A16_INFO, 1, "Adjusting .., DELTA Freq = %d, SWEEP Freq=%d", delta_freq, swp_freq); | ||
1391 | if (ABS(state->frequency * 1000 - swp_freq) > 3800) { | ||
1392 | dprintk(verbose, MB86A16_INFO, 1, "NO -- SIGNAL !"); | ||
1393 | } else { | ||
1394 | |||
1395 | S1T = 0; | ||
1396 | S0T = 3; | ||
1397 | CREN = 1; | ||
1398 | AFCEN = 0; | ||
1399 | AFCEXEN = 1; | ||
1400 | |||
1401 | if (S01T_set(state, S1T, S0T) < 0) { | ||
1402 | dprintk(verbose, MB86A16_ERROR, 1, "S01T set error"); | ||
1403 | return -1; | ||
1404 | } | ||
1405 | if (DAGC_data_set(state, 0, 0) < 0) { | ||
1406 | dprintk(verbose, MB86A16_ERROR, 1, "DAGC data set error"); | ||
1407 | return -1; | ||
1408 | } | ||
1409 | R = vco_dev_get(state, state->srate); | ||
1410 | smrt_info_get(state, state->srate); | ||
1411 | if (smrt_set(state, state->srate) < 0) { | ||
1412 | dprintk(verbose, MB86A16_ERROR, 1, "smrt set error"); | ||
1413 | return -1; | ||
1414 | } | ||
1415 | if (EN_set(state, CREN, AFCEN) < 0) { | ||
1416 | dprintk(verbose, MB86A16_ERROR, 1, "EN set error"); | ||
1417 | return -1; | ||
1418 | } | ||
1419 | if (AFCEXEN_set(state, AFCEXEN, state->srate) < 0) { | ||
1420 | dprintk(verbose, MB86A16_ERROR, 1, "AFCEXEN set error"); | ||
1421 | return -1; | ||
1422 | } | ||
1423 | swp_info_get2(state, state->srate, R, swp_freq, &afcex_freq, &fOSC, &AFCEX_L, &AFCEX_H); | ||
1424 | if (rf_val_set(state, fOSC, state->srate, R) < 0) { | ||
1425 | dprintk(verbose, MB86A16_ERROR, 1, "rf val set error"); | ||
1426 | return -1; | ||
1427 | } | ||
1428 | if (afcex_data_set(state, AFCEX_L, AFCEX_H) < 0) { | ||
1429 | dprintk(verbose, MB86A16_ERROR, 1, "afcex data set error"); | ||
1430 | return -1; | ||
1431 | } | ||
1432 | if (srst(state) < 0) { | ||
1433 | dprintk(verbose, MB86A16_ERROR, 1, "srst error"); | ||
1434 | return -1; | ||
1435 | } | ||
1436 | wait_t = 7 + (10000 + state->srate / 2) / state->srate; | ||
1437 | if (wait_t == 0) | ||
1438 | wait_t = 1; | ||
1439 | msleep_interruptible(wait_t); | ||
1440 | if (mb86a16_read(state, 0x37, &SIG1) != 2) { | ||
1441 | dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); | ||
1442 | return -EREMOTEIO; | ||
1443 | } | ||
1444 | |||
1445 | if (SIG1 > 110) { | ||
1446 | S2T = 4; S4T = 1; S5T = 6; ETH = 4; VIA = 6; | ||
1447 | wait_t = 7 + (917504 + state->srate / 2) / state->srate; | ||
1448 | } else if (SIG1 > 105) { | ||
1449 | S2T = 4; S4T = 2; S5T = 8; ETH = 7; VIA = 2; | ||
1450 | wait_t = 7 + (1048576 + state->srate / 2) / state->srate; | ||
1451 | } else if (SIG1 > 85) { | ||
1452 | S2T = 5; S4T = 2; S5T = 8; ETH = 7; VIA = 2; | ||
1453 | wait_t = 7 + (1310720 + state->srate / 2) / state->srate; | ||
1454 | } else if (SIG1 > 65) { | ||
1455 | S2T = 6; S4T = 2; S5T = 8; ETH = 7; VIA = 2; | ||
1456 | wait_t = 7 + (1572864 + state->srate / 2) / state->srate; | ||
1457 | } else { | ||
1458 | S2T = 7; S4T = 2; S5T = 8; ETH = 7; VIA = 2; | ||
1459 | wait_t = 7 + (2097152 + state->srate / 2) / state->srate; | ||
1460 | } | ||
1461 | wait_t *= 2; /* FOS */ | ||
1462 | S2T_set(state, S2T); | ||
1463 | S45T_set(state, S4T, S5T); | ||
1464 | Vi_set(state, ETH, VIA); | ||
1465 | srst(state); | ||
1466 | msleep_interruptible(wait_t); | ||
1467 | sync = sync_chk(state, &VIRM); | ||
1468 | dprintk(verbose, MB86A16_INFO, 1, "-------- Viterbi=[%d] SYNC=[%d] ---------", VIRM, sync); | ||
1469 | if (VIRM) { | ||
1470 | if (VIRM == 4) { | ||
1471 | /* 5/6 */ | ||
1472 | if (SIG1 > 110) | ||
1473 | wait_t = (786432 + state->srate / 2) / state->srate; | ||
1474 | else | ||
1475 | wait_t = (1572864 + state->srate / 2) / state->srate; | ||
1476 | if (state->srate < 5000) | ||
1477 | /* FIXME ! , should be a long wait ! */ | ||
1478 | msleep_interruptible(wait_t); | ||
1479 | else | ||
1480 | msleep_interruptible(wait_t); | ||
1481 | |||
1482 | if (sync_chk(state, &junk) == 0) { | ||
1483 | iq_vt_set(state, 1); | ||
1484 | FEC_srst(state); | ||
1485 | } | ||
1486 | } | ||
1487 | /* 1/2, 2/3, 3/4, 7/8 */ | ||
1488 | if (SIG1 > 110) | ||
1489 | wait_t = (786432 + state->srate / 2) / state->srate; | ||
1490 | else | ||
1491 | wait_t = (1572864 + state->srate / 2) / state->srate; | ||
1492 | msleep_interruptible(wait_t); | ||
1493 | SEQ_set(state, 1); | ||
1494 | } else { | ||
1495 | dprintk(verbose, MB86A16_INFO, 1, "NO -- SYNC"); | ||
1496 | SEQ_set(state, 1); | ||
1497 | ret = -1; | ||
1498 | } | ||
1499 | } | ||
1500 | } else { | ||
1501 | dprintk(verbose, MB86A16_INFO, 1, "NO -- SIGNAL"); | ||
1502 | ret = -1; | ||
1503 | } | ||
1504 | |||
1505 | sync = sync_chk(state, &junk); | ||
1506 | if (sync) { | ||
1507 | dprintk(verbose, MB86A16_INFO, 1, "******* SYNC *******"); | ||
1508 | freqerr_chk(state, state->frequency, state->srate, 1); | ||
1509 | ret = 0; | ||
1510 | break; | ||
1511 | } | ||
1512 | } | ||
1513 | |||
1514 | mb86a16_read(state, 0x15, &agcval); | ||
1515 | mb86a16_read(state, 0x26, &cnmval); | ||
1516 | dprintk(verbose, MB86A16_INFO, 1, "AGC = %02x CNM = %02x", agcval, cnmval); | ||
1517 | |||
1518 | return ret; | ||
1519 | } | ||
1520 | |||
1521 | static int mb86a16_send_diseqc_msg(struct dvb_frontend *fe, | ||
1522 | struct dvb_diseqc_master_cmd *cmd) | ||
1523 | { | ||
1524 | struct mb86a16_state *state = fe->demodulator_priv; | ||
1525 | int i; | ||
1526 | u8 regs; | ||
1527 | |||
1528 | if (mb86a16_write(state, MB86A16_DCC1, MB86A16_DCC1_DISTA) < 0) | ||
1529 | goto err; | ||
1530 | if (mb86a16_write(state, MB86A16_DCCOUT, 0x00) < 0) | ||
1531 | goto err; | ||
1532 | if (mb86a16_write(state, MB86A16_TONEOUT2, 0x04) < 0) | ||
1533 | goto err; | ||
1534 | |||
1535 | regs = 0x18; | ||
1536 | |||
1537 | if (cmd->msg_len > 5 || cmd->msg_len < 4) | ||
1538 | return -EINVAL; | ||
1539 | |||
1540 | for (i = 0; i < cmd->msg_len; i++) { | ||
1541 | if (mb86a16_write(state, regs, cmd->msg[i]) < 0) | ||
1542 | goto err; | ||
1543 | |||
1544 | regs++; | ||
1545 | } | ||
1546 | i += 0x90; | ||
1547 | |||
1548 | msleep_interruptible(10); | ||
1549 | |||
1550 | if (mb86a16_write(state, MB86A16_DCC1, i) < 0) | ||
1551 | goto err; | ||
1552 | if (mb86a16_write(state, MB86A16_DCCOUT, MB86A16_DCCOUT_DISEN) < 0) | ||
1553 | goto err; | ||
1554 | |||
1555 | return 0; | ||
1556 | |||
1557 | err: | ||
1558 | dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); | ||
1559 | return -EREMOTEIO; | ||
1560 | } | ||
1561 | |||
1562 | static int mb86a16_send_diseqc_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t burst) | ||
1563 | { | ||
1564 | struct mb86a16_state *state = fe->demodulator_priv; | ||
1565 | |||
1566 | switch (burst) { | ||
1567 | case SEC_MINI_A: | ||
1568 | if (mb86a16_write(state, MB86A16_DCC1, MB86A16_DCC1_DISTA | | ||
1569 | MB86A16_DCC1_TBEN | | ||
1570 | MB86A16_DCC1_TBO) < 0) | ||
1571 | goto err; | ||
1572 | if (mb86a16_write(state, MB86A16_DCCOUT, MB86A16_DCCOUT_DISEN) < 0) | ||
1573 | goto err; | ||
1574 | break; | ||
1575 | case SEC_MINI_B: | ||
1576 | if (mb86a16_write(state, MB86A16_DCC1, MB86A16_DCC1_DISTA | | ||
1577 | MB86A16_DCC1_TBEN) < 0) | ||
1578 | goto err; | ||
1579 | if (mb86a16_write(state, MB86A16_DCCOUT, MB86A16_DCCOUT_DISEN) < 0) | ||
1580 | goto err; | ||
1581 | break; | ||
1582 | } | ||
1583 | |||
1584 | return 0; | ||
1585 | err: | ||
1586 | dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); | ||
1587 | return -EREMOTEIO; | ||
1588 | } | ||
1589 | |||
1590 | static int mb86a16_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) | ||
1591 | { | ||
1592 | struct mb86a16_state *state = fe->demodulator_priv; | ||
1593 | |||
1594 | switch (tone) { | ||
1595 | case SEC_TONE_ON: | ||
1596 | if (mb86a16_write(state, MB86A16_TONEOUT2, 0x00) < 0) | ||
1597 | goto err; | ||
1598 | if (mb86a16_write(state, MB86A16_DCC1, MB86A16_DCC1_DISTA | | ||
1599 | MB86A16_DCC1_CTOE) < 0) | ||
1600 | |||
1601 | goto err; | ||
1602 | if (mb86a16_write(state, MB86A16_DCCOUT, MB86A16_DCCOUT_DISEN) < 0) | ||
1603 | goto err; | ||
1604 | break; | ||
1605 | case SEC_TONE_OFF: | ||
1606 | if (mb86a16_write(state, MB86A16_TONEOUT2, 0x04) < 0) | ||
1607 | goto err; | ||
1608 | if (mb86a16_write(state, MB86A16_DCC1, MB86A16_DCC1_DISTA) < 0) | ||
1609 | goto err; | ||
1610 | if (mb86a16_write(state, MB86A16_DCCOUT, 0x00) < 0) | ||
1611 | goto err; | ||
1612 | break; | ||
1613 | default: | ||
1614 | return -EINVAL; | ||
1615 | } | ||
1616 | return 0; | ||
1617 | |||
1618 | err: | ||
1619 | dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); | ||
1620 | return -EREMOTEIO; | ||
1621 | } | ||
1622 | |||
1623 | static enum dvbfe_search mb86a16_search(struct dvb_frontend *fe, | ||
1624 | struct dvb_frontend_parameters *p) | ||
1625 | { | ||
1626 | struct mb86a16_state *state = fe->demodulator_priv; | ||
1627 | |||
1628 | state->frequency = p->frequency / 1000; | ||
1629 | state->srate = p->u.qpsk.symbol_rate / 1000; | ||
1630 | |||
1631 | if (!mb86a16_set_fe(state)) { | ||
1632 | dprintk(verbose, MB86A16_ERROR, 1, "Succesfully acquired LOCK"); | ||
1633 | return DVBFE_ALGO_SEARCH_SUCCESS; | ||
1634 | } | ||
1635 | |||
1636 | dprintk(verbose, MB86A16_ERROR, 1, "Lock acquisition failed!"); | ||
1637 | return DVBFE_ALGO_SEARCH_FAILED; | ||
1638 | } | ||
1639 | |||
1640 | static void mb86a16_release(struct dvb_frontend *fe) | ||
1641 | { | ||
1642 | struct mb86a16_state *state = fe->demodulator_priv; | ||
1643 | kfree(state); | ||
1644 | } | ||
1645 | |||
1646 | static int mb86a16_init(struct dvb_frontend *fe) | ||
1647 | { | ||
1648 | return 0; | ||
1649 | } | ||
1650 | |||
1651 | static int mb86a16_sleep(struct dvb_frontend *fe) | ||
1652 | { | ||
1653 | return 0; | ||
1654 | } | ||
1655 | |||
1656 | static int mb86a16_read_ber(struct dvb_frontend *fe, u32 *ber) | ||
1657 | { | ||
1658 | u8 ber_mon, ber_tab, ber_lsb, ber_mid, ber_msb, ber_tim, ber_rst; | ||
1659 | u32 timer; | ||
1660 | |||
1661 | struct mb86a16_state *state = fe->demodulator_priv; | ||
1662 | |||
1663 | *ber = 0; | ||
1664 | if (mb86a16_read(state, MB86A16_BERMON, &ber_mon) != 2) | ||
1665 | goto err; | ||
1666 | if (mb86a16_read(state, MB86A16_BERTAB, &ber_tab) != 2) | ||
1667 | goto err; | ||
1668 | if (mb86a16_read(state, MB86A16_BERLSB, &ber_lsb) != 2) | ||
1669 | goto err; | ||
1670 | if (mb86a16_read(state, MB86A16_BERMID, &ber_mid) != 2) | ||
1671 | goto err; | ||
1672 | if (mb86a16_read(state, MB86A16_BERMSB, &ber_msb) != 2) | ||
1673 | goto err; | ||
1674 | /* BER monitor invalid when BER_EN = 0 */ | ||
1675 | if (ber_mon & 0x04) { | ||
1676 | /* coarse, fast calculation */ | ||
1677 | *ber = ber_tab & 0x1f; | ||
1678 | dprintk(verbose, MB86A16_DEBUG, 1, "BER coarse=[0x%02x]", *ber); | ||
1679 | if (ber_mon & 0x01) { | ||
1680 | /* | ||
1681 | * BER_SEL = 1, The monitored BER is the estimated | ||
1682 | * value with a Reed-Solomon decoder error amount at | ||
1683 | * the deinterleaver output. | ||
1684 | * monitored BER is expressed as a 20 bit output in total | ||
1685 | */ | ||
1686 | ber_rst = ber_mon >> 3; | ||
1687 | *ber = (((ber_msb << 8) | ber_mid) << 8) | ber_lsb; | ||
1688 | if (ber_rst == 0) | ||
1689 | timer = 12500000; | ||
1690 | if (ber_rst == 1) | ||
1691 | timer = 25000000; | ||
1692 | if (ber_rst == 2) | ||
1693 | timer = 50000000; | ||
1694 | if (ber_rst == 3) | ||
1695 | timer = 100000000; | ||
1696 | |||
1697 | *ber /= timer; | ||
1698 | dprintk(verbose, MB86A16_DEBUG, 1, "BER fine=[0x%02x]", *ber); | ||
1699 | } else { | ||
1700 | /* | ||
1701 | * BER_SEL = 0, The monitored BER is the estimated | ||
1702 | * value with a Viterbi decoder error amount at the | ||
1703 | * QPSK demodulator output. | ||
1704 | * monitored BER is expressed as a 24 bit output in total | ||
1705 | */ | ||
1706 | ber_tim = ber_mon >> 1; | ||
1707 | *ber = (((ber_msb << 8) | ber_mid) << 8) | ber_lsb; | ||
1708 | if (ber_tim == 0) | ||
1709 | timer = 16; | ||
1710 | if (ber_tim == 1) | ||
1711 | timer = 24; | ||
1712 | |||
1713 | *ber /= 2 ^ timer; | ||
1714 | dprintk(verbose, MB86A16_DEBUG, 1, "BER fine=[0x%02x]", *ber); | ||
1715 | } | ||
1716 | } | ||
1717 | return 0; | ||
1718 | err: | ||
1719 | dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); | ||
1720 | return -EREMOTEIO; | ||
1721 | } | ||
1722 | |||
1723 | static int mb86a16_read_signal_strength(struct dvb_frontend *fe, u16 *strength) | ||
1724 | { | ||
1725 | u8 agcm = 0; | ||
1726 | struct mb86a16_state *state = fe->demodulator_priv; | ||
1727 | |||
1728 | *strength = 0; | ||
1729 | if (mb86a16_read(state, MB86A16_AGCM, &agcm) != 2) { | ||
1730 | dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); | ||
1731 | return -EREMOTEIO; | ||
1732 | } | ||
1733 | |||
1734 | *strength = ((0xff - agcm) * 100) / 256; | ||
1735 | dprintk(verbose, MB86A16_DEBUG, 1, "Signal strength=[%d %%]", (u8) *strength); | ||
1736 | *strength = (0xffff - 0xff) + agcm; | ||
1737 | |||
1738 | return 0; | ||
1739 | } | ||
1740 | |||
1741 | struct cnr { | ||
1742 | u8 cn_reg; | ||
1743 | u8 cn_val; | ||
1744 | }; | ||
1745 | |||
1746 | static const struct cnr cnr_tab[] = { | ||
1747 | { 35, 2 }, | ||
1748 | { 40, 3 }, | ||
1749 | { 50, 4 }, | ||
1750 | { 60, 5 }, | ||
1751 | { 70, 6 }, | ||
1752 | { 80, 7 }, | ||
1753 | { 92, 8 }, | ||
1754 | { 103, 9 }, | ||
1755 | { 115, 10 }, | ||
1756 | { 138, 12 }, | ||
1757 | { 162, 15 }, | ||
1758 | { 180, 18 }, | ||
1759 | { 185, 19 }, | ||
1760 | { 189, 20 }, | ||
1761 | { 195, 22 }, | ||
1762 | { 199, 24 }, | ||
1763 | { 201, 25 }, | ||
1764 | { 202, 26 }, | ||
1765 | { 203, 27 }, | ||
1766 | { 205, 28 }, | ||
1767 | { 208, 30 } | ||
1768 | }; | ||
1769 | |||
1770 | static int mb86a16_read_snr(struct dvb_frontend *fe, u16 *snr) | ||
1771 | { | ||
1772 | struct mb86a16_state *state = fe->demodulator_priv; | ||
1773 | int i = 0; | ||
1774 | int low_tide = 2, high_tide = 30, q_level; | ||
1775 | u8 cn; | ||
1776 | |||
1777 | *snr = 0; | ||
1778 | if (mb86a16_read(state, 0x26, &cn) != 2) { | ||
1779 | dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); | ||
1780 | return -EREMOTEIO; | ||
1781 | } | ||
1782 | |||
1783 | for (i = 0; i < ARRAY_SIZE(cnr_tab); i++) { | ||
1784 | if (cn < cnr_tab[i].cn_reg) { | ||
1785 | *snr = cnr_tab[i].cn_val; | ||
1786 | break; | ||
1787 | } | ||
1788 | } | ||
1789 | q_level = (*snr * 100) / (high_tide - low_tide); | ||
1790 | dprintk(verbose, MB86A16_ERROR, 1, "SNR (Quality) = [%d dB], Level=%d %%", *snr, q_level); | ||
1791 | *snr = (0xffff - 0xff) + *snr; | ||
1792 | |||
1793 | return 0; | ||
1794 | } | ||
1795 | |||
1796 | static int mb86a16_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) | ||
1797 | { | ||
1798 | u8 dist; | ||
1799 | struct mb86a16_state *state = fe->demodulator_priv; | ||
1800 | |||
1801 | if (mb86a16_read(state, MB86A16_DISTMON, &dist) != 2) { | ||
1802 | dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); | ||
1803 | return -EREMOTEIO; | ||
1804 | } | ||
1805 | *ucblocks = dist; | ||
1806 | |||
1807 | return 0; | ||
1808 | } | ||
1809 | |||
1810 | static enum dvbfe_algo mb86a16_frontend_algo(struct dvb_frontend *fe) | ||
1811 | { | ||
1812 | return DVBFE_ALGO_CUSTOM; | ||
1813 | } | ||
1814 | |||
1815 | static struct dvb_frontend_ops mb86a16_ops = { | ||
1816 | .info = { | ||
1817 | .name = "Fujitsu MB86A16 DVB-S", | ||
1818 | .type = FE_QPSK, | ||
1819 | .frequency_min = 950000, | ||
1820 | .frequency_max = 2150000, | ||
1821 | .frequency_stepsize = 3000, | ||
1822 | .frequency_tolerance = 0, | ||
1823 | .symbol_rate_min = 1000000, | ||
1824 | .symbol_rate_max = 45000000, | ||
1825 | .symbol_rate_tolerance = 500, | ||
1826 | .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | | ||
1827 | FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | | ||
1828 | FE_CAN_FEC_7_8 | FE_CAN_QPSK | | ||
1829 | FE_CAN_FEC_AUTO | ||
1830 | }, | ||
1831 | .release = mb86a16_release, | ||
1832 | |||
1833 | .get_frontend_algo = mb86a16_frontend_algo, | ||
1834 | .search = mb86a16_search, | ||
1835 | .read_status = mb86a16_read_status, | ||
1836 | .init = mb86a16_init, | ||
1837 | .sleep = mb86a16_sleep, | ||
1838 | .read_status = mb86a16_read_status, | ||
1839 | |||
1840 | .read_ber = mb86a16_read_ber, | ||
1841 | .read_signal_strength = mb86a16_read_signal_strength, | ||
1842 | .read_snr = mb86a16_read_snr, | ||
1843 | .read_ucblocks = mb86a16_read_ucblocks, | ||
1844 | |||
1845 | .diseqc_send_master_cmd = mb86a16_send_diseqc_msg, | ||
1846 | .diseqc_send_burst = mb86a16_send_diseqc_burst, | ||
1847 | .set_tone = mb86a16_set_tone, | ||
1848 | }; | ||
1849 | |||
1850 | struct dvb_frontend *mb86a16_attach(const struct mb86a16_config *config, | ||
1851 | struct i2c_adapter *i2c_adap) | ||
1852 | { | ||
1853 | u8 dev_id = 0; | ||
1854 | struct mb86a16_state *state = NULL; | ||
1855 | |||
1856 | state = kmalloc(sizeof(struct mb86a16_state), GFP_KERNEL); | ||
1857 | if (state == NULL) | ||
1858 | goto error; | ||
1859 | |||
1860 | state->config = config; | ||
1861 | state->i2c_adap = i2c_adap; | ||
1862 | |||
1863 | mb86a16_read(state, 0x7f, &dev_id); | ||
1864 | if (dev_id != 0xfe) | ||
1865 | goto error; | ||
1866 | |||
1867 | memcpy(&state->frontend.ops, &mb86a16_ops, sizeof(struct dvb_frontend_ops)); | ||
1868 | state->frontend.demodulator_priv = state; | ||
1869 | state->frontend.ops.set_voltage = state->config->set_voltage; | ||
1870 | |||
1871 | return &state->frontend; | ||
1872 | error: | ||
1873 | kfree(state); | ||
1874 | return NULL; | ||
1875 | } | ||
1876 | EXPORT_SYMBOL(mb86a16_attach); | ||
1877 | MODULE_LICENSE("GPL"); | ||
1878 | MODULE_AUTHOR("Manu Abraham"); | ||
diff --git a/drivers/media/dvb/frontends/mb86a16.h b/drivers/media/dvb/frontends/mb86a16.h new file mode 100644 index 000000000000..6ea8c376394f --- /dev/null +++ b/drivers/media/dvb/frontends/mb86a16.h | |||
@@ -0,0 +1,52 @@ | |||
1 | /* | ||
2 | Fujitsu MB86A16 DVB-S/DSS DC Receiver driver | ||
3 | |||
4 | Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #ifndef __MB86A16_H | ||
22 | #define __MB86A16_H | ||
23 | |||
24 | #include <linux/dvb/frontend.h> | ||
25 | #include "dvb_frontend.h" | ||
26 | |||
27 | |||
28 | struct mb86a16_config { | ||
29 | u8 demod_address; | ||
30 | |||
31 | int (*set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage); | ||
32 | }; | ||
33 | |||
34 | |||
35 | |||
36 | #if defined(CONFIG_DVB_MB86A16) || (defined(CONFIG_DVB_MB86A16_MODULE) && defined(MODULE)) | ||
37 | |||
38 | extern struct dvb_frontend *mb86a16_attach(const struct mb86a16_config *config, | ||
39 | struct i2c_adapter *i2c_adap); | ||
40 | |||
41 | #else | ||
42 | |||
43 | static inline struct dvb_frontend *mb86a16_attach(const struct mb86a16_config *config, | ||
44 | struct i2c_adapter *i2c_adap) | ||
45 | { | ||
46 | printk(KERN_WARNING "%s: Driver disabled by Kconfig\n", __func__); | ||
47 | return NULL; | ||
48 | } | ||
49 | |||
50 | #endif /* CONFIG_DVB_MB86A16 */ | ||
51 | |||
52 | #endif /* __MB86A16_H */ | ||
diff --git a/drivers/media/dvb/frontends/mb86a16_priv.h b/drivers/media/dvb/frontends/mb86a16_priv.h new file mode 100644 index 000000000000..360a35acfe84 --- /dev/null +++ b/drivers/media/dvb/frontends/mb86a16_priv.h | |||
@@ -0,0 +1,151 @@ | |||
1 | /* | ||
2 | Fujitsu MB86A16 DVB-S/DSS DC Receiver driver | ||
3 | |||
4 | Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #ifndef __MB86A16_PRIV_H | ||
22 | #define __MB86A16_PRIV_H | ||
23 | |||
24 | #define MB86A16_TSOUT 0x00 | ||
25 | #define MB86A16_TSOUT_HIZSEL (0x01 << 5) | ||
26 | #define MB86A16_TSOUT_HIZCNTI (0x01 << 4) | ||
27 | #define MB86A16_TSOUT_MODE (0x01 << 3) | ||
28 | #define MB86A16_TSOUT_ORDER (0x01 << 2) | ||
29 | #define MB86A16_TSOUT_ERROR (0x01 << 1) | ||
30 | #define Mb86A16_TSOUT_EDGE (0x01 << 0) | ||
31 | |||
32 | #define MB86A16_FEC 0x01 | ||
33 | #define MB86A16_FEC_FSYNC (0x01 << 5) | ||
34 | #define MB86A16_FEC_PCKB8 (0x01 << 4) | ||
35 | #define MB86A16_FEC_DVDS (0x01 << 3) | ||
36 | #define MB86A16_FEC_EREN (0x01 << 2) | ||
37 | #define Mb86A16_FEC_RSEN (0x01 << 1) | ||
38 | #define MB86A16_FEC_DIEN (0x01 << 0) | ||
39 | |||
40 | #define MB86A16_AGC 0x02 | ||
41 | #define MB86A16_AGC_AGMD (0x01 << 6) | ||
42 | #define MB86A16_AGC_AGCW (0x0f << 2) | ||
43 | #define MB86A16_AGC_AGCP (0x01 << 1) | ||
44 | #define MB86A16_AGC_AGCR (0x01 << 0) | ||
45 | |||
46 | #define MB86A16_SRATE1 0x03 | ||
47 | #define MB86A16_SRATE1_DECI (0x07 << 2) | ||
48 | #define MB86A16_SRATE1_CSEL (0x01 << 1) | ||
49 | #define MB86A16_SRATE1_RSEL (0x01 << 0) | ||
50 | |||
51 | #define MB86A16_SRATE2 0x04 | ||
52 | #define MB86A16_SRATE2_STOFSL (0xff << 0) | ||
53 | |||
54 | #define MB86A16_SRATE3 0x05 | ||
55 | #define MB86A16_SRATE2_STOFSH (0xff << 0) | ||
56 | |||
57 | #define MB86A16_VITERBI 0x06 | ||
58 | #define MB86A16_FRAMESYNC 0x07 | ||
59 | #define MB86A16_CRLFILTCOEF1 0x08 | ||
60 | #define MB86A16_CRLFILTCOEF2 0x09 | ||
61 | #define MB86A16_STRFILTCOEF1 0x0a | ||
62 | #define MB86A16_STRFILTCOEF2 0x0b | ||
63 | #define MB86A16_RESET 0x0c | ||
64 | #define MB86A16_STATUS 0x0d | ||
65 | #define MB86A16_AFCML 0x0e | ||
66 | #define MB86A16_AFCMH 0x0f | ||
67 | #define MB86A16_BERMON 0x10 | ||
68 | #define MB86A16_BERTAB 0x11 | ||
69 | #define MB86A16_BERLSB 0x12 | ||
70 | #define MB86A16_BERMID 0x13 | ||
71 | #define MB86A16_BERMSB 0x14 | ||
72 | #define MB86A16_AGCM 0x15 | ||
73 | |||
74 | #define MB86A16_DCC1 0x16 | ||
75 | #define MB86A16_DCC1_DISTA (0x01 << 7) | ||
76 | #define MB86A16_DCC1_PRTY (0x01 << 6) | ||
77 | #define MB86A16_DCC1_CTOE (0x01 << 5) | ||
78 | #define MB86A16_DCC1_TBEN (0x01 << 4) | ||
79 | #define MB86A16_DCC1_TBO (0x01 << 3) | ||
80 | #define MB86A16_DCC1_NUM (0x07 << 0) | ||
81 | |||
82 | #define MB86A16_DCC2 0x17 | ||
83 | #define MB86A16_DCC2_DCBST (0x01 << 0) | ||
84 | |||
85 | #define MB86A16_DCC3 0x18 | ||
86 | #define MB86A16_DCC3_CODE0 (0xff << 0) | ||
87 | |||
88 | #define MB86A16_DCC4 0x19 | ||
89 | #define MB86A16_DCC4_CODE1 (0xff << 0) | ||
90 | |||
91 | #define MB86A16_DCC5 0x1a | ||
92 | #define MB86A16_DCC5_CODE2 (0xff << 0) | ||
93 | |||
94 | #define MB86A16_DCC6 0x1b | ||
95 | #define MB86A16_DCC6_CODE3 (0xff << 0) | ||
96 | |||
97 | #define MB86A16_DCC7 0x1c | ||
98 | #define MB86A16_DCC7_CODE4 (0xff << 0) | ||
99 | |||
100 | #define MB86A16_DCC8 0x1d | ||
101 | #define MB86A16_DCC8_CODE5 (0xff << 0) | ||
102 | |||
103 | #define MB86A16_DCCOUT 0x1e | ||
104 | #define MB86A16_DCCOUT_DISEN (0x01 << 0) | ||
105 | |||
106 | #define MB86A16_TONEOUT1 0x1f | ||
107 | #define MB86A16_TONE_TDIVL (0xff << 0) | ||
108 | |||
109 | #define MB86A16_TONEOUT2 0x20 | ||
110 | #define MB86A16_TONE_TMD (0x03 << 2) | ||
111 | #define MB86A16_TONE_TDIVH (0x03 << 0) | ||
112 | |||
113 | #define MB86A16_FREQ1 0x21 | ||
114 | #define MB86A16_FREQ2 0x22 | ||
115 | #define MB86A16_FREQ3 0x23 | ||
116 | #define MB86A16_FREQ4 0x24 | ||
117 | #define MB86A16_FREQSET 0x25 | ||
118 | #define MB86A16_CNM 0x26 | ||
119 | #define MB86A16_PORT0 0x27 | ||
120 | #define MB86A16_PORT1 0x28 | ||
121 | #define MB86A16_DRCFILT 0x29 | ||
122 | #define MB86A16_AFC 0x2a | ||
123 | #define MB86A16_AFCEXL 0x2b | ||
124 | #define MB86A16_AFCEXH 0x2c | ||
125 | #define MB86A16_DAGC 0x2d | ||
126 | #define MB86A16_SEQMODE 0x32 | ||
127 | #define MB86A16_S0S1T 0x33 | ||
128 | #define MB86A16_S2S3T 0x34 | ||
129 | #define MB86A16_S4S5T 0x35 | ||
130 | #define MB86A16_CNTMR 0x36 | ||
131 | #define MB86A16_SIG1 0x37 | ||
132 | #define MB86A16_SIG2 0x38 | ||
133 | #define MB86A16_VIMAG 0x39 | ||
134 | #define MB86A16_VISET1 0x3a | ||
135 | #define MB86A16_VISET2 0x3b | ||
136 | #define MB86A16_VISET3 0x3c | ||
137 | #define MB86A16_FAGCS1 0x3d | ||
138 | #define MB86A16_FAGCS2 0x3e | ||
139 | #define MB86A16_FAGCS3 0x3f | ||
140 | #define MB86A16_FAGCS4 0x40 | ||
141 | #define MB86A16_FAGCS5 0x41 | ||
142 | #define MB86A16_FAGCS6 0x42 | ||
143 | #define MB86A16_CRM 0x43 | ||
144 | #define MB86A16_STRM 0x44 | ||
145 | #define MB86A16_DAGCML 0x45 | ||
146 | #define MB86A16_DAGCMH 0x46 | ||
147 | #define MB86A16_QPSKTST 0x49 | ||
148 | #define MB86A16_DISTMON 0x52 | ||
149 | #define MB86A16_VERSION 0x7f | ||
150 | |||
151 | #endif /* __MB86A16_PRIV_H */ | ||
diff --git a/drivers/media/dvb/frontends/stv0900_core.c b/drivers/media/dvb/frontends/stv0900_core.c index df49ea0983bc..8762c86044a5 100644 --- a/drivers/media/dvb/frontends/stv0900_core.c +++ b/drivers/media/dvb/frontends/stv0900_core.c | |||
@@ -1451,6 +1451,8 @@ static int stv0900_status(struct stv0900_internal *intp, | |||
1451 | { | 1451 | { |
1452 | enum fe_stv0900_search_state demod_state; | 1452 | enum fe_stv0900_search_state demod_state; |
1453 | int locked = FALSE; | 1453 | int locked = FALSE; |
1454 | u8 tsbitrate0_val, tsbitrate1_val; | ||
1455 | s32 bitrate; | ||
1454 | 1456 | ||
1455 | demod_state = stv0900_get_bits(intp, HEADER_MODE); | 1457 | demod_state = stv0900_get_bits(intp, HEADER_MODE); |
1456 | switch (demod_state) { | 1458 | switch (demod_state) { |
@@ -1473,6 +1475,17 @@ static int stv0900_status(struct stv0900_internal *intp, | |||
1473 | 1475 | ||
1474 | dprintk("%s: locked = %d\n", __func__, locked); | 1476 | dprintk("%s: locked = %d\n", __func__, locked); |
1475 | 1477 | ||
1478 | if (stvdebug) { | ||
1479 | /* Print TS bitrate */ | ||
1480 | tsbitrate0_val = stv0900_read_reg(intp, TSBITRATE0); | ||
1481 | tsbitrate1_val = stv0900_read_reg(intp, TSBITRATE1); | ||
1482 | /* Formula Bit rate = Mclk * px_tsfifo_bitrate / 16384 */ | ||
1483 | bitrate = (stv0900_get_mclk_freq(intp, intp->quartz)/1000000) | ||
1484 | * (tsbitrate1_val << 8 | tsbitrate0_val); | ||
1485 | bitrate /= 16384; | ||
1486 | dprintk("TS bitrate = %d Mbit/sec \n", bitrate); | ||
1487 | }; | ||
1488 | |||
1476 | return locked; | 1489 | return locked; |
1477 | } | 1490 | } |
1478 | 1491 | ||
diff --git a/drivers/media/dvb/frontends/stv090x.c b/drivers/media/dvb/frontends/stv090x.c index 48edd542242e..1573466a5c74 100644 --- a/drivers/media/dvb/frontends/stv090x.c +++ b/drivers/media/dvb/frontends/stv090x.c | |||
@@ -3597,7 +3597,8 @@ static int stv090x_send_diseqc_msg(struct dvb_frontend *fe, struct dvb_diseqc_ma | |||
3597 | 3597 | ||
3598 | reg = STV090x_READ_DEMOD(state, DISTXCTL); | 3598 | reg = STV090x_READ_DEMOD(state, DISTXCTL); |
3599 | 3599 | ||
3600 | STV090x_SETFIELD_Px(reg, DISTX_MODE_FIELD, 2); | 3600 | STV090x_SETFIELD_Px(reg, DISTX_MODE_FIELD, |
3601 | (state->config->diseqc_envelope_mode) ? 4 : 2); | ||
3601 | STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 1); | 3602 | STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 1); |
3602 | if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0) | 3603 | if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0) |
3603 | goto err; | 3604 | goto err; |
@@ -3649,10 +3650,10 @@ static int stv090x_send_diseqc_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t | |||
3649 | reg = STV090x_READ_DEMOD(state, DISTXCTL); | 3650 | reg = STV090x_READ_DEMOD(state, DISTXCTL); |
3650 | 3651 | ||
3651 | if (burst == SEC_MINI_A) { | 3652 | if (burst == SEC_MINI_A) { |
3652 | mode = 3; | 3653 | mode = (state->config->diseqc_envelope_mode) ? 5 : 3; |
3653 | value = 0x00; | 3654 | value = 0x00; |
3654 | } else { | 3655 | } else { |
3655 | mode = 2; | 3656 | mode = (state->config->diseqc_envelope_mode) ? 4 : 2; |
3656 | value = 0xFF; | 3657 | value = 0xFF; |
3657 | } | 3658 | } |
3658 | 3659 | ||
diff --git a/drivers/media/dvb/frontends/stv090x.h b/drivers/media/dvb/frontends/stv090x.h index e968c98bb70f..b133807663ea 100644 --- a/drivers/media/dvb/frontends/stv090x.h +++ b/drivers/media/dvb/frontends/stv090x.h | |||
@@ -75,6 +75,8 @@ struct stv090x_config { | |||
75 | 75 | ||
76 | enum stv090x_i2crpt repeater_level; | 76 | enum stv090x_i2crpt repeater_level; |
77 | 77 | ||
78 | bool diseqc_envelope_mode; | ||
79 | |||
78 | int (*tuner_init) (struct dvb_frontend *fe); | 80 | int (*tuner_init) (struct dvb_frontend *fe); |
79 | int (*tuner_set_mode) (struct dvb_frontend *fe, enum tuner_mode mode); | 81 | int (*tuner_set_mode) (struct dvb_frontend *fe, enum tuner_mode mode); |
80 | int (*tuner_set_frequency) (struct dvb_frontend *fe, u32 frequency); | 82 | int (*tuner_set_frequency) (struct dvb_frontend *fe, u32 frequency); |
diff --git a/drivers/media/dvb/frontends/tda10021.c b/drivers/media/dvb/frontends/tda10021.c index 6c1dbf9288d8..6ca533ea0f0e 100644 --- a/drivers/media/dvb/frontends/tda10021.c +++ b/drivers/media/dvb/frontends/tda10021.c | |||
@@ -426,6 +426,10 @@ struct dvb_frontend* tda10021_attach(const struct tda1002x_config* config, | |||
426 | id = tda10021_readreg(state, 0x1a); | 426 | id = tda10021_readreg(state, 0x1a); |
427 | if ((id & 0xf0) != 0x70) goto error; | 427 | if ((id & 0xf0) != 0x70) goto error; |
428 | 428 | ||
429 | /* Don't claim TDA10023 */ | ||
430 | if (id == 0x7d) | ||
431 | goto error; | ||
432 | |||
429 | printk("TDA10021: i2c-addr = 0x%02x, id = 0x%02x\n", | 433 | printk("TDA10021: i2c-addr = 0x%02x, id = 0x%02x\n", |
430 | state->config->demod_address, id); | 434 | state->config->demod_address, id); |
431 | 435 | ||
diff --git a/drivers/media/dvb/frontends/tda665x.c b/drivers/media/dvb/frontends/tda665x.c new file mode 100644 index 000000000000..87d52739c828 --- /dev/null +++ b/drivers/media/dvb/frontends/tda665x.c | |||
@@ -0,0 +1,257 @@ | |||
1 | /* | ||
2 | TDA665x tuner driver | ||
3 | Copyright (C) Manu Abraham (abraham.manu@gmail.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; either version 2 of the License, or | ||
8 | (at your option) any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; if not, write to the Free Software | ||
17 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | */ | ||
19 | |||
20 | #include <linux/init.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/module.h> | ||
23 | |||
24 | #include "dvb_frontend.h" | ||
25 | #include "tda665x.h" | ||
26 | |||
27 | struct tda665x_state { | ||
28 | struct dvb_frontend *fe; | ||
29 | struct i2c_adapter *i2c; | ||
30 | const struct tda665x_config *config; | ||
31 | |||
32 | u32 frequency; | ||
33 | u32 bandwidth; | ||
34 | }; | ||
35 | |||
36 | static int tda665x_read(struct tda665x_state *state, u8 *buf) | ||
37 | { | ||
38 | const struct tda665x_config *config = state->config; | ||
39 | int err = 0; | ||
40 | struct i2c_msg msg = { .addr = config->addr, .flags = I2C_M_RD, .buf = buf, .len = 2 }; | ||
41 | |||
42 | err = i2c_transfer(state->i2c, &msg, 1); | ||
43 | if (err != 1) | ||
44 | goto exit; | ||
45 | |||
46 | return err; | ||
47 | exit: | ||
48 | printk(KERN_ERR "%s: I/O Error err=<%d>\n", __func__, err); | ||
49 | return err; | ||
50 | } | ||
51 | |||
52 | static int tda665x_write(struct tda665x_state *state, u8 *buf, u8 length) | ||
53 | { | ||
54 | const struct tda665x_config *config = state->config; | ||
55 | int err = 0; | ||
56 | struct i2c_msg msg = { .addr = config->addr, .flags = 0, .buf = buf, .len = length }; | ||
57 | |||
58 | err = i2c_transfer(state->i2c, &msg, 1); | ||
59 | if (err != 1) | ||
60 | goto exit; | ||
61 | |||
62 | return err; | ||
63 | exit: | ||
64 | printk(KERN_ERR "%s: I/O Error err=<%d>\n", __func__, err); | ||
65 | return err; | ||
66 | } | ||
67 | |||
68 | static int tda665x_get_state(struct dvb_frontend *fe, | ||
69 | enum tuner_param param, | ||
70 | struct tuner_state *tstate) | ||
71 | { | ||
72 | struct tda665x_state *state = fe->tuner_priv; | ||
73 | int err = 0; | ||
74 | |||
75 | switch (param) { | ||
76 | case DVBFE_TUNER_FREQUENCY: | ||
77 | tstate->frequency = state->frequency; | ||
78 | break; | ||
79 | case DVBFE_TUNER_BANDWIDTH: | ||
80 | break; | ||
81 | default: | ||
82 | printk(KERN_ERR "%s: Unknown parameter (param=%d)\n", __func__, param); | ||
83 | err = -EINVAL; | ||
84 | break; | ||
85 | } | ||
86 | |||
87 | return err; | ||
88 | } | ||
89 | |||
90 | static int tda665x_get_status(struct dvb_frontend *fe, u32 *status) | ||
91 | { | ||
92 | struct tda665x_state *state = fe->tuner_priv; | ||
93 | u8 result = 0; | ||
94 | int err = 0; | ||
95 | |||
96 | *status = 0; | ||
97 | |||
98 | err = tda665x_read(state, &result); | ||
99 | if (err < 0) | ||
100 | goto exit; | ||
101 | |||
102 | if ((result >> 6) & 0x01) { | ||
103 | printk(KERN_DEBUG "%s: Tuner Phase Locked\n", __func__); | ||
104 | *status = 1; | ||
105 | } | ||
106 | |||
107 | return err; | ||
108 | exit: | ||
109 | printk(KERN_ERR "%s: I/O Error\n", __func__); | ||
110 | return err; | ||
111 | } | ||
112 | |||
113 | static int tda665x_set_state(struct dvb_frontend *fe, | ||
114 | enum tuner_param param, | ||
115 | struct tuner_state *tstate) | ||
116 | { | ||
117 | struct tda665x_state *state = fe->tuner_priv; | ||
118 | const struct tda665x_config *config = state->config; | ||
119 | u32 frequency, status = 0; | ||
120 | u8 buf[4]; | ||
121 | int err = 0; | ||
122 | |||
123 | if (param & DVBFE_TUNER_FREQUENCY) { | ||
124 | |||
125 | frequency = tstate->frequency; | ||
126 | if ((frequency < config->frequency_max) || (frequency > config->frequency_min)) { | ||
127 | printk(KERN_ERR "%s: Frequency beyond limits, frequency=%d\n", __func__, frequency); | ||
128 | return -EINVAL; | ||
129 | } | ||
130 | |||
131 | frequency += config->frequency_offst; | ||
132 | frequency *= config->ref_multiplier; | ||
133 | frequency += config->ref_divider >> 1; | ||
134 | frequency /= config->ref_divider; | ||
135 | |||
136 | buf[0] = (u8) (frequency & 0x7f00) >> 8; | ||
137 | buf[1] = (u8) (frequency & 0x00ff) >> 0; | ||
138 | buf[2] = 0x80 | 0x40 | 0x02; | ||
139 | buf[3] = 0x00; | ||
140 | |||
141 | /* restore frequency */ | ||
142 | frequency = tstate->frequency; | ||
143 | |||
144 | if (frequency < 153000000) { | ||
145 | /* VHF-L */ | ||
146 | buf[3] |= 0x01; /* fc, Low Band, 47 - 153 MHz */ | ||
147 | if (frequency < 68000000) | ||
148 | buf[3] |= 0x40; /* 83uA */ | ||
149 | if (frequency < 1040000000) | ||
150 | buf[3] |= 0x60; /* 122uA */ | ||
151 | if (frequency < 1250000000) | ||
152 | buf[3] |= 0x80; /* 163uA */ | ||
153 | else | ||
154 | buf[3] |= 0xa0; /* 254uA */ | ||
155 | } else if (frequency < 438000000) { | ||
156 | /* VHF-H */ | ||
157 | buf[3] |= 0x02; /* fc, Mid Band, 153 - 438 MHz */ | ||
158 | if (frequency < 230000000) | ||
159 | buf[3] |= 0x40; | ||
160 | if (frequency < 300000000) | ||
161 | buf[3] |= 0x60; | ||
162 | else | ||
163 | buf[3] |= 0x80; | ||
164 | } else { | ||
165 | /* UHF */ | ||
166 | buf[3] |= 0x04; /* fc, High Band, 438 - 862 MHz */ | ||
167 | if (frequency < 470000000) | ||
168 | buf[3] |= 0x60; | ||
169 | if (frequency < 526000000) | ||
170 | buf[3] |= 0x80; | ||
171 | else | ||
172 | buf[3] |= 0xa0; | ||
173 | } | ||
174 | |||
175 | /* Set params */ | ||
176 | err = tda665x_write(state, buf, 5); | ||
177 | if (err < 0) | ||
178 | goto exit; | ||
179 | |||
180 | /* sleep for some time */ | ||
181 | printk(KERN_DEBUG "%s: Waiting to Phase LOCK\n", __func__); | ||
182 | msleep(20); | ||
183 | /* check status */ | ||
184 | err = tda665x_get_status(fe, &status); | ||
185 | if (err < 0) | ||
186 | goto exit; | ||
187 | |||
188 | if (status == 1) { | ||
189 | printk(KERN_DEBUG "%s: Tuner Phase locked: status=%d\n", __func__, status); | ||
190 | state->frequency = frequency; /* cache successful state */ | ||
191 | } else { | ||
192 | printk(KERN_ERR "%s: No Phase lock: status=%d\n", __func__, status); | ||
193 | } | ||
194 | } else { | ||
195 | printk(KERN_ERR "%s: Unknown parameter (param=%d)\n", __func__, param); | ||
196 | return -EINVAL; | ||
197 | } | ||
198 | |||
199 | return 0; | ||
200 | exit: | ||
201 | printk(KERN_ERR "%s: I/O Error\n", __func__); | ||
202 | return err; | ||
203 | } | ||
204 | |||
205 | static int tda665x_release(struct dvb_frontend *fe) | ||
206 | { | ||
207 | struct tda665x_state *state = fe->tuner_priv; | ||
208 | |||
209 | fe->tuner_priv = NULL; | ||
210 | kfree(state); | ||
211 | return 0; | ||
212 | } | ||
213 | |||
214 | static struct dvb_tuner_ops tda665x_ops = { | ||
215 | |||
216 | .set_state = tda665x_set_state, | ||
217 | .get_state = tda665x_get_state, | ||
218 | .get_status = tda665x_get_status, | ||
219 | .release = tda665x_release | ||
220 | }; | ||
221 | |||
222 | struct dvb_frontend *tda665x_attach(struct dvb_frontend *fe, | ||
223 | const struct tda665x_config *config, | ||
224 | struct i2c_adapter *i2c) | ||
225 | { | ||
226 | struct tda665x_state *state = NULL; | ||
227 | struct dvb_tuner_info *info; | ||
228 | |||
229 | state = kzalloc(sizeof(struct tda665x_state), GFP_KERNEL); | ||
230 | if (state == NULL) | ||
231 | goto exit; | ||
232 | |||
233 | state->config = config; | ||
234 | state->i2c = i2c; | ||
235 | state->fe = fe; | ||
236 | fe->tuner_priv = state; | ||
237 | fe->ops.tuner_ops = tda665x_ops; | ||
238 | info = &fe->ops.tuner_ops.info; | ||
239 | |||
240 | memcpy(info->name, config->name, sizeof(config->name)); | ||
241 | info->frequency_min = config->frequency_min; | ||
242 | info->frequency_max = config->frequency_max; | ||
243 | info->frequency_step = config->frequency_offst; | ||
244 | |||
245 | printk(KERN_DEBUG "%s: Attaching TDA665x (%s) tuner\n", __func__, info->name); | ||
246 | |||
247 | return fe; | ||
248 | |||
249 | exit: | ||
250 | kfree(state); | ||
251 | return NULL; | ||
252 | } | ||
253 | EXPORT_SYMBOL(tda665x_attach); | ||
254 | |||
255 | MODULE_DESCRIPTION("TDA665x driver"); | ||
256 | MODULE_AUTHOR("Manu Abraham"); | ||
257 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/frontends/tda665x.h b/drivers/media/dvb/frontends/tda665x.h new file mode 100644 index 000000000000..ec7927aa75ae --- /dev/null +++ b/drivers/media/dvb/frontends/tda665x.h | |||
@@ -0,0 +1,52 @@ | |||
1 | /* | ||
2 | TDA665x tuner driver | ||
3 | Copyright (C) Manu Abraham (abraham.manu@gmail.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; either version 2 of the License, or | ||
8 | (at your option) any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; if not, write to the Free Software | ||
17 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | */ | ||
19 | |||
20 | #ifndef __TDA665x_H | ||
21 | #define __TDA665x_H | ||
22 | |||
23 | struct tda665x_config { | ||
24 | char name[128]; | ||
25 | |||
26 | u8 addr; | ||
27 | u32 frequency_min; | ||
28 | u32 frequency_max; | ||
29 | u32 frequency_offst; | ||
30 | u32 ref_multiplier; | ||
31 | u32 ref_divider; | ||
32 | }; | ||
33 | |||
34 | #if defined(CONFIG_DVB_TDA665x) || (defined(CONFIG_DVB_TDA665x_MODULE) && defined(MODULE)) | ||
35 | |||
36 | extern struct dvb_frontend *tda665x_attach(struct dvb_frontend *fe, | ||
37 | const struct tda665x_config *config, | ||
38 | struct i2c_adapter *i2c); | ||
39 | |||
40 | #else | ||
41 | |||
42 | static inline struct dvb_frontend *tda665x_attach(struct dvb_frontend *fe, | ||
43 | const struct tda665x_config *config, | ||
44 | struct i2c_adapter *i2c) | ||
45 | { | ||
46 | printk(KERN_WARNING "%s: Driver disabled by Kconfig\n", __func__); | ||
47 | return NULL; | ||
48 | } | ||
49 | |||
50 | #endif /* CONFIG_DVB_TDA665x */ | ||
51 | |||
52 | #endif /* __TDA665x_H */ | ||
diff --git a/drivers/media/dvb/mantis/Kconfig b/drivers/media/dvb/mantis/Kconfig new file mode 100644 index 000000000000..f7b72a32adf3 --- /dev/null +++ b/drivers/media/dvb/mantis/Kconfig | |||
@@ -0,0 +1,32 @@ | |||
1 | config MANTIS_CORE | ||
2 | tristate "Mantis/Hopper PCI bridge based devices" | ||
3 | depends on PCI && I2C && INPUT | ||
4 | |||
5 | help | ||
6 | Support for PCI cards based on the Mantis and Hopper PCi bridge. | ||
7 | |||
8 | Say Y if you own such a device and want to use it. | ||
9 | |||
10 | config DVB_MANTIS | ||
11 | tristate "MANTIS based cards" | ||
12 | depends on MANTIS_CORE && DVB_CORE && PCI && I2C | ||
13 | select DVB_MB86A16 | ||
14 | select DVB_ZL10353 | ||
15 | select DVB_STV0299 | ||
16 | select DVB_PLL | ||
17 | help | ||
18 | Support for PCI cards based on the Mantis PCI bridge. | ||
19 | Say Y when you have a Mantis based DVB card and want to use it. | ||
20 | |||
21 | If unsure say N. | ||
22 | |||
23 | config DVB_HOPPER | ||
24 | tristate "HOPPER based cards" | ||
25 | depends on MANTIS_CORE && DVB_CORE && PCI && I2C | ||
26 | select DVB_ZL10353 | ||
27 | select DVB_PLL | ||
28 | help | ||
29 | Support for PCI cards based on the Hopper PCI bridge. | ||
30 | Say Y when you have a Hopper based DVB card and want to use it. | ||
31 | |||
32 | If unsure say N | ||
diff --git a/drivers/media/dvb/mantis/Makefile b/drivers/media/dvb/mantis/Makefile new file mode 100644 index 000000000000..98dc5cd258ac --- /dev/null +++ b/drivers/media/dvb/mantis/Makefile | |||
@@ -0,0 +1,28 @@ | |||
1 | mantis_core-objs := mantis_ioc.o \ | ||
2 | mantis_uart.o \ | ||
3 | mantis_dma.o \ | ||
4 | mantis_pci.o \ | ||
5 | mantis_i2c.o \ | ||
6 | mantis_dvb.o \ | ||
7 | mantis_evm.o \ | ||
8 | mantis_hif.o \ | ||
9 | mantis_ca.o \ | ||
10 | mantis_pcmcia.o \ | ||
11 | mantis_input.o | ||
12 | |||
13 | mantis-objs := mantis_cards.o \ | ||
14 | mantis_vp1033.o \ | ||
15 | mantis_vp1034.o \ | ||
16 | mantis_vp1041.o \ | ||
17 | mantis_vp2033.o \ | ||
18 | mantis_vp2040.o \ | ||
19 | mantis_vp3030.o | ||
20 | |||
21 | hopper-objs := hopper_cards.o \ | ||
22 | hopper_vp3028.o | ||
23 | |||
24 | obj-$(CONFIG_MANTIS_CORE) += mantis_core.o | ||
25 | obj-$(CONFIG_DVB_MANTIS) += mantis.o | ||
26 | obj-$(CONFIG_DVB_HOPPER) += hopper.o | ||
27 | |||
28 | EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ | ||
diff --git a/drivers/media/dvb/mantis/hopper_cards.c b/drivers/media/dvb/mantis/hopper_cards.c new file mode 100644 index 000000000000..d073c61e3c0d --- /dev/null +++ b/drivers/media/dvb/mantis/hopper_cards.c | |||
@@ -0,0 +1,275 @@ | |||
1 | /* | ||
2 | Hopper PCI bridge driver | ||
3 | |||
4 | Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/module.h> | ||
22 | #include <linux/moduleparam.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/pci.h> | ||
25 | #include <asm/irq.h> | ||
26 | #include <linux/interrupt.h> | ||
27 | |||
28 | #include "dmxdev.h" | ||
29 | #include "dvbdev.h" | ||
30 | #include "dvb_demux.h" | ||
31 | #include "dvb_frontend.h" | ||
32 | #include "dvb_net.h" | ||
33 | |||
34 | #include "mantis_common.h" | ||
35 | #include "hopper_vp3028.h" | ||
36 | #include "mantis_dma.h" | ||
37 | #include "mantis_dvb.h" | ||
38 | #include "mantis_uart.h" | ||
39 | #include "mantis_ioc.h" | ||
40 | #include "mantis_pci.h" | ||
41 | #include "mantis_i2c.h" | ||
42 | #include "mantis_reg.h" | ||
43 | |||
44 | static unsigned int verbose; | ||
45 | module_param(verbose, int, 0644); | ||
46 | MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)"); | ||
47 | |||
48 | #define DRIVER_NAME "Hopper" | ||
49 | |||
50 | static char *label[10] = { | ||
51 | "DMA", | ||
52 | "IRQ-0", | ||
53 | "IRQ-1", | ||
54 | "OCERR", | ||
55 | "PABRT", | ||
56 | "RIPRR", | ||
57 | "PPERR", | ||
58 | "FTRGT", | ||
59 | "RISCI", | ||
60 | "RACK" | ||
61 | }; | ||
62 | |||
63 | static int devs; | ||
64 | |||
65 | static irqreturn_t hopper_irq_handler(int irq, void *dev_id) | ||
66 | { | ||
67 | u32 stat = 0, mask = 0, lstat = 0, mstat = 0; | ||
68 | u32 rst_stat = 0, rst_mask = 0; | ||
69 | |||
70 | struct mantis_pci *mantis; | ||
71 | struct mantis_ca *ca; | ||
72 | |||
73 | mantis = (struct mantis_pci *) dev_id; | ||
74 | if (unlikely(mantis == NULL)) { | ||
75 | dprintk(MANTIS_ERROR, 1, "Mantis == NULL"); | ||
76 | return IRQ_NONE; | ||
77 | } | ||
78 | ca = mantis->mantis_ca; | ||
79 | |||
80 | stat = mmread(MANTIS_INT_STAT); | ||
81 | mask = mmread(MANTIS_INT_MASK); | ||
82 | mstat = lstat = stat & ~MANTIS_INT_RISCSTAT; | ||
83 | if (!(stat & mask)) | ||
84 | return IRQ_NONE; | ||
85 | |||
86 | rst_mask = MANTIS_GPIF_WRACK | | ||
87 | MANTIS_GPIF_OTHERR | | ||
88 | MANTIS_SBUF_WSTO | | ||
89 | MANTIS_GPIF_EXTIRQ; | ||
90 | |||
91 | rst_stat = mmread(MANTIS_GPIF_STATUS); | ||
92 | rst_stat &= rst_mask; | ||
93 | mmwrite(rst_stat, MANTIS_GPIF_STATUS); | ||
94 | |||
95 | mantis->mantis_int_stat = stat; | ||
96 | mantis->mantis_int_mask = mask; | ||
97 | dprintk(MANTIS_DEBUG, 0, "\n-- Stat=<%02x> Mask=<%02x> --", stat, mask); | ||
98 | if (stat & MANTIS_INT_RISCEN) { | ||
99 | dprintk(MANTIS_DEBUG, 0, "<%s>", label[0]); | ||
100 | } | ||
101 | if (stat & MANTIS_INT_IRQ0) { | ||
102 | dprintk(MANTIS_DEBUG, 0, "<%s>", label[1]); | ||
103 | mantis->gpif_status = rst_stat; | ||
104 | wake_up(&ca->hif_write_wq); | ||
105 | schedule_work(&ca->hif_evm_work); | ||
106 | } | ||
107 | if (stat & MANTIS_INT_IRQ1) { | ||
108 | dprintk(MANTIS_DEBUG, 0, "<%s>", label[2]); | ||
109 | schedule_work(&mantis->uart_work); | ||
110 | } | ||
111 | if (stat & MANTIS_INT_OCERR) { | ||
112 | dprintk(MANTIS_DEBUG, 0, "<%s>", label[3]); | ||
113 | } | ||
114 | if (stat & MANTIS_INT_PABORT) { | ||
115 | dprintk(MANTIS_DEBUG, 0, "<%s>", label[4]); | ||
116 | } | ||
117 | if (stat & MANTIS_INT_RIPERR) { | ||
118 | dprintk(MANTIS_DEBUG, 0, "<%s>", label[5]); | ||
119 | } | ||
120 | if (stat & MANTIS_INT_PPERR) { | ||
121 | dprintk(MANTIS_DEBUG, 0, "<%s>", label[6]); | ||
122 | } | ||
123 | if (stat & MANTIS_INT_FTRGT) { | ||
124 | dprintk(MANTIS_DEBUG, 0, "<%s>", label[7]); | ||
125 | } | ||
126 | if (stat & MANTIS_INT_RISCI) { | ||
127 | dprintk(MANTIS_DEBUG, 0, "<%s>", label[8]); | ||
128 | mantis->finished_block = (stat & MANTIS_INT_RISCSTAT) >> 28; | ||
129 | tasklet_schedule(&mantis->tasklet); | ||
130 | } | ||
131 | if (stat & MANTIS_INT_I2CDONE) { | ||
132 | dprintk(MANTIS_DEBUG, 0, "<%s>", label[9]); | ||
133 | wake_up(&mantis->i2c_wq); | ||
134 | } | ||
135 | mmwrite(stat, MANTIS_INT_STAT); | ||
136 | stat &= ~(MANTIS_INT_RISCEN | MANTIS_INT_I2CDONE | | ||
137 | MANTIS_INT_I2CRACK | MANTIS_INT_PCMCIA7 | | ||
138 | MANTIS_INT_PCMCIA6 | MANTIS_INT_PCMCIA5 | | ||
139 | MANTIS_INT_PCMCIA4 | MANTIS_INT_PCMCIA3 | | ||
140 | MANTIS_INT_PCMCIA2 | MANTIS_INT_PCMCIA1 | | ||
141 | MANTIS_INT_PCMCIA0 | MANTIS_INT_IRQ1 | | ||
142 | MANTIS_INT_IRQ0 | MANTIS_INT_OCERR | | ||
143 | MANTIS_INT_PABORT | MANTIS_INT_RIPERR | | ||
144 | MANTIS_INT_PPERR | MANTIS_INT_FTRGT | | ||
145 | MANTIS_INT_RISCI); | ||
146 | |||
147 | if (stat) | ||
148 | dprintk(MANTIS_DEBUG, 0, "<Unknown> Stat=<%02x> Mask=<%02x>", stat, mask); | ||
149 | |||
150 | dprintk(MANTIS_DEBUG, 0, "\n"); | ||
151 | return IRQ_HANDLED; | ||
152 | } | ||
153 | |||
154 | static int __devinit hopper_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) | ||
155 | { | ||
156 | struct mantis_pci *mantis; | ||
157 | struct mantis_hwconfig *config; | ||
158 | int err = 0; | ||
159 | |||
160 | mantis = kzalloc(sizeof(struct mantis_pci), GFP_KERNEL); | ||
161 | if (mantis == NULL) { | ||
162 | printk(KERN_ERR "%s ERROR: Out of memory\n", __func__); | ||
163 | err = -ENOMEM; | ||
164 | goto fail0; | ||
165 | } | ||
166 | |||
167 | mantis->num = devs; | ||
168 | mantis->verbose = verbose; | ||
169 | mantis->pdev = pdev; | ||
170 | config = (struct mantis_hwconfig *) pci_id->driver_data; | ||
171 | config->irq_handler = &hopper_irq_handler; | ||
172 | mantis->hwconfig = config; | ||
173 | |||
174 | err = mantis_pci_init(mantis); | ||
175 | if (err) { | ||
176 | dprintk(MANTIS_ERROR, 1, "ERROR: Mantis PCI initialization failed <%d>", err); | ||
177 | goto fail1; | ||
178 | } | ||
179 | |||
180 | err = mantis_stream_control(mantis, STREAM_TO_HIF); | ||
181 | if (err < 0) { | ||
182 | dprintk(MANTIS_ERROR, 1, "ERROR: Mantis stream control failed <%d>", err); | ||
183 | goto fail1; | ||
184 | } | ||
185 | |||
186 | err = mantis_i2c_init(mantis); | ||
187 | if (err < 0) { | ||
188 | dprintk(MANTIS_ERROR, 1, "ERROR: Mantis I2C initialization failed <%d>", err); | ||
189 | goto fail2; | ||
190 | } | ||
191 | |||
192 | err = mantis_get_mac(mantis); | ||
193 | if (err < 0) { | ||
194 | dprintk(MANTIS_ERROR, 1, "ERROR: Mantis MAC address read failed <%d>", err); | ||
195 | goto fail2; | ||
196 | } | ||
197 | |||
198 | err = mantis_dma_init(mantis); | ||
199 | if (err < 0) { | ||
200 | dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA initialization failed <%d>", err); | ||
201 | goto fail3; | ||
202 | } | ||
203 | |||
204 | err = mantis_dvb_init(mantis); | ||
205 | if (err < 0) { | ||
206 | dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DVB initialization failed <%d>", err); | ||
207 | goto fail4; | ||
208 | } | ||
209 | devs++; | ||
210 | |||
211 | return err; | ||
212 | |||
213 | fail4: | ||
214 | dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA exit! <%d>", err); | ||
215 | mantis_dma_exit(mantis); | ||
216 | |||
217 | fail3: | ||
218 | dprintk(MANTIS_ERROR, 1, "ERROR: Mantis I2C exit! <%d>", err); | ||
219 | mantis_i2c_exit(mantis); | ||
220 | |||
221 | fail2: | ||
222 | dprintk(MANTIS_ERROR, 1, "ERROR: Mantis PCI exit! <%d>", err); | ||
223 | mantis_pci_exit(mantis); | ||
224 | |||
225 | fail1: | ||
226 | dprintk(MANTIS_ERROR, 1, "ERROR: Mantis free! <%d>", err); | ||
227 | kfree(mantis); | ||
228 | |||
229 | fail0: | ||
230 | return err; | ||
231 | } | ||
232 | |||
233 | static void __devexit hopper_pci_remove(struct pci_dev *pdev) | ||
234 | { | ||
235 | struct mantis_pci *mantis = pci_get_drvdata(pdev); | ||
236 | |||
237 | if (mantis) { | ||
238 | mantis_dvb_exit(mantis); | ||
239 | mantis_dma_exit(mantis); | ||
240 | mantis_i2c_exit(mantis); | ||
241 | mantis_pci_exit(mantis); | ||
242 | kfree(mantis); | ||
243 | } | ||
244 | return; | ||
245 | |||
246 | } | ||
247 | |||
248 | static struct pci_device_id hopper_pci_table[] = { | ||
249 | MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_3028_DVB_T, &vp3028_config), | ||
250 | { } | ||
251 | }; | ||
252 | |||
253 | static struct pci_driver hopper_pci_driver = { | ||
254 | .name = DRIVER_NAME, | ||
255 | .id_table = hopper_pci_table, | ||
256 | .probe = hopper_pci_probe, | ||
257 | .remove = hopper_pci_remove, | ||
258 | }; | ||
259 | |||
260 | static int __devinit hopper_init(void) | ||
261 | { | ||
262 | return pci_register_driver(&hopper_pci_driver); | ||
263 | } | ||
264 | |||
265 | static void __devexit hopper_exit(void) | ||
266 | { | ||
267 | return pci_unregister_driver(&hopper_pci_driver); | ||
268 | } | ||
269 | |||
270 | module_init(hopper_init); | ||
271 | module_exit(hopper_exit); | ||
272 | |||
273 | MODULE_DESCRIPTION("HOPPER driver"); | ||
274 | MODULE_AUTHOR("Manu Abraham"); | ||
275 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/mantis/hopper_vp3028.c b/drivers/media/dvb/mantis/hopper_vp3028.c new file mode 100644 index 000000000000..96674c78e86b --- /dev/null +++ b/drivers/media/dvb/mantis/hopper_vp3028.c | |||
@@ -0,0 +1,88 @@ | |||
1 | /* | ||
2 | Hopper VP-3028 driver | ||
3 | |||
4 | Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/signal.h> | ||
22 | #include <linux/sched.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | |||
25 | #include "dmxdev.h" | ||
26 | #include "dvbdev.h" | ||
27 | #include "dvb_demux.h" | ||
28 | #include "dvb_frontend.h" | ||
29 | #include "dvb_net.h" | ||
30 | |||
31 | #include "zl10353.h" | ||
32 | #include "mantis_common.h" | ||
33 | #include "mantis_ioc.h" | ||
34 | #include "mantis_dvb.h" | ||
35 | #include "hopper_vp3028.h" | ||
36 | |||
37 | struct zl10353_config hopper_vp3028_config = { | ||
38 | .demod_address = 0x0f, | ||
39 | }; | ||
40 | |||
41 | #define MANTIS_MODEL_NAME "VP-3028" | ||
42 | #define MANTIS_DEV_TYPE "DVB-T" | ||
43 | |||
44 | static int vp3028_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe) | ||
45 | { | ||
46 | struct i2c_adapter *adapter = &mantis->adapter; | ||
47 | struct mantis_hwconfig *config = mantis->hwconfig; | ||
48 | int err = 0; | ||
49 | |||
50 | gpio_set_bits(mantis, config->reset, 0); | ||
51 | msleep(100); | ||
52 | err = mantis_frontend_power(mantis, POWER_ON); | ||
53 | msleep(100); | ||
54 | gpio_set_bits(mantis, config->reset, 1); | ||
55 | |||
56 | err = mantis_frontend_power(mantis, POWER_ON); | ||
57 | if (err == 0) { | ||
58 | msleep(250); | ||
59 | dprintk(MANTIS_ERROR, 1, "Probing for 10353 (DVB-T)"); | ||
60 | fe = zl10353_attach(&hopper_vp3028_config, adapter); | ||
61 | |||
62 | if (!fe) | ||
63 | return -1; | ||
64 | } else { | ||
65 | dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>", | ||
66 | adapter->name, | ||
67 | err); | ||
68 | |||
69 | return -EIO; | ||
70 | } | ||
71 | dprintk(MANTIS_ERROR, 1, "Done!"); | ||
72 | |||
73 | return 0; | ||
74 | } | ||
75 | |||
76 | struct mantis_hwconfig vp3028_config = { | ||
77 | .model_name = MANTIS_MODEL_NAME, | ||
78 | .dev_type = MANTIS_DEV_TYPE, | ||
79 | .ts_size = MANTIS_TS_188, | ||
80 | |||
81 | .baud_rate = MANTIS_BAUD_9600, | ||
82 | .parity = MANTIS_PARITY_NONE, | ||
83 | .bytes = 0, | ||
84 | |||
85 | .frontend_init = vp3028_frontend_init, | ||
86 | .power = GPIF_A00, | ||
87 | .reset = GPIF_A03, | ||
88 | }; | ||
diff --git a/drivers/media/dvb/mantis/hopper_vp3028.h b/drivers/media/dvb/mantis/hopper_vp3028.h new file mode 100644 index 000000000000..57239498bc87 --- /dev/null +++ b/drivers/media/dvb/mantis/hopper_vp3028.h | |||
@@ -0,0 +1,30 @@ | |||
1 | /* | ||
2 | Hopper VP-3028 driver | ||
3 | |||
4 | Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #ifndef __MANTIS_VP3028_H | ||
22 | #define __MANTIS_VP3028_H | ||
23 | |||
24 | #include "mantis_common.h" | ||
25 | |||
26 | #define MANTIS_VP_3028_DVB_T 0x0028 | ||
27 | |||
28 | extern struct mantis_hwconfig vp3028_config; | ||
29 | |||
30 | #endif /* __MANTIS_VP3028_H */ | ||
diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/dvb/mantis/mantis_ca.c new file mode 100644 index 000000000000..403ce043d00e --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_ca.c | |||
@@ -0,0 +1,207 @@ | |||
1 | /* | ||
2 | Mantis PCI bridge driver | ||
3 | |||
4 | Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/signal.h> | ||
22 | #include <linux/sched.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | |||
25 | #include "dmxdev.h" | ||
26 | #include "dvbdev.h" | ||
27 | #include "dvb_demux.h" | ||
28 | #include "dvb_frontend.h" | ||
29 | #include "dvb_net.h" | ||
30 | |||
31 | #include "mantis_common.h" | ||
32 | #include "mantis_link.h" | ||
33 | #include "mantis_hif.h" | ||
34 | #include "mantis_reg.h" | ||
35 | |||
36 | #include "mantis_ca.h" | ||
37 | |||
38 | static int mantis_ca_read_attr_mem(struct dvb_ca_en50221 *en50221, int slot, int addr) | ||
39 | { | ||
40 | struct mantis_ca *ca = en50221->data; | ||
41 | struct mantis_pci *mantis = ca->ca_priv; | ||
42 | |||
43 | dprintk(MANTIS_DEBUG, 1, "Slot(%d): Request Attribute Mem Read", slot); | ||
44 | |||
45 | if (slot != 0) | ||
46 | return -EINVAL; | ||
47 | |||
48 | return mantis_hif_read_mem(ca, addr); | ||
49 | } | ||
50 | |||
51 | static int mantis_ca_write_attr_mem(struct dvb_ca_en50221 *en50221, int slot, int addr, u8 data) | ||
52 | { | ||
53 | struct mantis_ca *ca = en50221->data; | ||
54 | struct mantis_pci *mantis = ca->ca_priv; | ||
55 | |||
56 | dprintk(MANTIS_DEBUG, 1, "Slot(%d): Request Attribute Mem Write", slot); | ||
57 | |||
58 | if (slot != 0) | ||
59 | return -EINVAL; | ||
60 | |||
61 | return mantis_hif_write_mem(ca, addr, data); | ||
62 | } | ||
63 | |||
64 | static int mantis_ca_read_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 addr) | ||
65 | { | ||
66 | struct mantis_ca *ca = en50221->data; | ||
67 | struct mantis_pci *mantis = ca->ca_priv; | ||
68 | |||
69 | dprintk(MANTIS_DEBUG, 1, "Slot(%d): Request CAM control Read", slot); | ||
70 | |||
71 | if (slot != 0) | ||
72 | return -EINVAL; | ||
73 | |||
74 | return mantis_hif_read_iom(ca, addr); | ||
75 | } | ||
76 | |||
77 | static int mantis_ca_write_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 addr, u8 data) | ||
78 | { | ||
79 | struct mantis_ca *ca = en50221->data; | ||
80 | struct mantis_pci *mantis = ca->ca_priv; | ||
81 | |||
82 | dprintk(MANTIS_DEBUG, 1, "Slot(%d): Request CAM control Write", slot); | ||
83 | |||
84 | if (slot != 0) | ||
85 | return -EINVAL; | ||
86 | |||
87 | return mantis_hif_write_iom(ca, addr, data); | ||
88 | } | ||
89 | |||
90 | static int mantis_ca_slot_reset(struct dvb_ca_en50221 *en50221, int slot) | ||
91 | { | ||
92 | struct mantis_ca *ca = en50221->data; | ||
93 | struct mantis_pci *mantis = ca->ca_priv; | ||
94 | |||
95 | dprintk(MANTIS_DEBUG, 1, "Slot(%d): Slot RESET", slot); | ||
96 | udelay(500); /* Wait.. */ | ||
97 | mmwrite(0xda, MANTIS_PCMCIA_RESET); /* Leading edge assert */ | ||
98 | udelay(500); | ||
99 | mmwrite(0x00, MANTIS_PCMCIA_RESET); /* Trailing edge deassert */ | ||
100 | msleep(1000); | ||
101 | dvb_ca_en50221_camready_irq(&ca->en50221, 0); | ||
102 | |||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | static int mantis_ca_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot) | ||
107 | { | ||
108 | struct mantis_ca *ca = en50221->data; | ||
109 | struct mantis_pci *mantis = ca->ca_priv; | ||
110 | |||
111 | dprintk(MANTIS_DEBUG, 1, "Slot(%d): Slot shutdown", slot); | ||
112 | |||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | static int mantis_ts_control(struct dvb_ca_en50221 *en50221, int slot) | ||
117 | { | ||
118 | struct mantis_ca *ca = en50221->data; | ||
119 | struct mantis_pci *mantis = ca->ca_priv; | ||
120 | |||
121 | dprintk(MANTIS_DEBUG, 1, "Slot(%d): TS control", slot); | ||
122 | /* mantis_set_direction(mantis, 1); */ /* Enable TS through CAM */ | ||
123 | |||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | static int mantis_slot_status(struct dvb_ca_en50221 *en50221, int slot, int open) | ||
128 | { | ||
129 | struct mantis_ca *ca = en50221->data; | ||
130 | struct mantis_pci *mantis = ca->ca_priv; | ||
131 | |||
132 | dprintk(MANTIS_DEBUG, 1, "Slot(%d): Poll Slot status", slot); | ||
133 | |||
134 | if (ca->slot_state == MODULE_INSERTED) { | ||
135 | dprintk(MANTIS_DEBUG, 1, "CA Module present and ready"); | ||
136 | return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY; | ||
137 | } else { | ||
138 | dprintk(MANTIS_DEBUG, 1, "CA Module not present or not ready"); | ||
139 | } | ||
140 | |||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | int mantis_ca_init(struct mantis_pci *mantis) | ||
145 | { | ||
146 | struct dvb_adapter *dvb_adapter = &mantis->dvb_adapter; | ||
147 | struct mantis_ca *ca; | ||
148 | int ca_flags = 0, result; | ||
149 | |||
150 | dprintk(MANTIS_DEBUG, 1, "Initializing Mantis CA"); | ||
151 | ca = kzalloc(sizeof(struct mantis_ca), GFP_KERNEL); | ||
152 | if (!ca) { | ||
153 | dprintk(MANTIS_ERROR, 1, "Out of memory!, exiting .."); | ||
154 | result = -ENOMEM; | ||
155 | goto err; | ||
156 | } | ||
157 | |||
158 | ca->ca_priv = mantis; | ||
159 | mantis->mantis_ca = ca; | ||
160 | ca_flags = DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE; | ||
161 | /* register CA interface */ | ||
162 | ca->en50221.owner = THIS_MODULE; | ||
163 | ca->en50221.read_attribute_mem = mantis_ca_read_attr_mem; | ||
164 | ca->en50221.write_attribute_mem = mantis_ca_write_attr_mem; | ||
165 | ca->en50221.read_cam_control = mantis_ca_read_cam_ctl; | ||
166 | ca->en50221.write_cam_control = mantis_ca_write_cam_ctl; | ||
167 | ca->en50221.slot_reset = mantis_ca_slot_reset; | ||
168 | ca->en50221.slot_shutdown = mantis_ca_slot_shutdown; | ||
169 | ca->en50221.slot_ts_enable = mantis_ts_control; | ||
170 | ca->en50221.poll_slot_status = mantis_slot_status; | ||
171 | ca->en50221.data = ca; | ||
172 | |||
173 | mutex_init(&ca->ca_lock); | ||
174 | |||
175 | init_waitqueue_head(&ca->hif_data_wq); | ||
176 | init_waitqueue_head(&ca->hif_opdone_wq); | ||
177 | init_waitqueue_head(&ca->hif_write_wq); | ||
178 | |||
179 | dprintk(MANTIS_ERROR, 1, "Registering EN50221 device"); | ||
180 | result = dvb_ca_en50221_init(dvb_adapter, &ca->en50221, ca_flags, 1); | ||
181 | if (result != 0) { | ||
182 | dprintk(MANTIS_ERROR, 1, "EN50221: Initialization failed <%d>", result); | ||
183 | goto err; | ||
184 | } | ||
185 | dprintk(MANTIS_ERROR, 1, "Registered EN50221 device"); | ||
186 | mantis_evmgr_init(ca); | ||
187 | return 0; | ||
188 | err: | ||
189 | kfree(ca); | ||
190 | return result; | ||
191 | } | ||
192 | EXPORT_SYMBOL_GPL(mantis_ca_init); | ||
193 | |||
194 | void mantis_ca_exit(struct mantis_pci *mantis) | ||
195 | { | ||
196 | struct mantis_ca *ca = mantis->mantis_ca; | ||
197 | |||
198 | dprintk(MANTIS_DEBUG, 1, "Mantis CA exit"); | ||
199 | |||
200 | mantis_evmgr_exit(ca); | ||
201 | dprintk(MANTIS_ERROR, 1, "Unregistering EN50221 device"); | ||
202 | if (ca) | ||
203 | dvb_ca_en50221_release(&ca->en50221); | ||
204 | |||
205 | kfree(ca); | ||
206 | } | ||
207 | EXPORT_SYMBOL_GPL(mantis_ca_exit); | ||
diff --git a/drivers/media/dvb/mantis/mantis_ca.h b/drivers/media/dvb/mantis/mantis_ca.h new file mode 100644 index 000000000000..dc63e55f7eca --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_ca.h | |||
@@ -0,0 +1,27 @@ | |||
1 | /* | ||
2 | Mantis PCI bridge driver | ||
3 | |||
4 | Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #ifndef __MANTIS_CA_H | ||
22 | #define __MANTIS_CA_H | ||
23 | |||
24 | extern int mantis_ca_init(struct mantis_pci *mantis); | ||
25 | extern void mantis_ca_exit(struct mantis_pci *mantis); | ||
26 | |||
27 | #endif /* __MANTIS_CA_H */ | ||
diff --git a/drivers/media/dvb/mantis/mantis_cards.c b/drivers/media/dvb/mantis/mantis_cards.c new file mode 100644 index 000000000000..16f1708fd3bc --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_cards.c | |||
@@ -0,0 +1,305 @@ | |||
1 | /* | ||
2 | Mantis PCI bridge driver | ||
3 | |||
4 | Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/module.h> | ||
22 | #include <linux/moduleparam.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/pci.h> | ||
25 | #include <asm/irq.h> | ||
26 | #include <linux/interrupt.h> | ||
27 | |||
28 | #include "dmxdev.h" | ||
29 | #include "dvbdev.h" | ||
30 | #include "dvb_demux.h" | ||
31 | #include "dvb_frontend.h" | ||
32 | #include "dvb_net.h" | ||
33 | |||
34 | #include "mantis_common.h" | ||
35 | |||
36 | #include "mantis_vp1033.h" | ||
37 | #include "mantis_vp1034.h" | ||
38 | #include "mantis_vp1041.h" | ||
39 | #include "mantis_vp2033.h" | ||
40 | #include "mantis_vp2040.h" | ||
41 | #include "mantis_vp3030.h" | ||
42 | |||
43 | #include "mantis_dma.h" | ||
44 | #include "mantis_ca.h" | ||
45 | #include "mantis_dvb.h" | ||
46 | #include "mantis_uart.h" | ||
47 | #include "mantis_ioc.h" | ||
48 | #include "mantis_pci.h" | ||
49 | #include "mantis_i2c.h" | ||
50 | #include "mantis_reg.h" | ||
51 | |||
52 | static unsigned int verbose; | ||
53 | module_param(verbose, int, 0644); | ||
54 | MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)"); | ||
55 | |||
56 | static int devs; | ||
57 | |||
58 | #define DRIVER_NAME "Mantis" | ||
59 | |||
60 | static char *label[10] = { | ||
61 | "DMA", | ||
62 | "IRQ-0", | ||
63 | "IRQ-1", | ||
64 | "OCERR", | ||
65 | "PABRT", | ||
66 | "RIPRR", | ||
67 | "PPERR", | ||
68 | "FTRGT", | ||
69 | "RISCI", | ||
70 | "RACK" | ||
71 | }; | ||
72 | |||
73 | static irqreturn_t mantis_irq_handler(int irq, void *dev_id) | ||
74 | { | ||
75 | u32 stat = 0, mask = 0, lstat = 0, mstat = 0; | ||
76 | u32 rst_stat = 0, rst_mask = 0; | ||
77 | |||
78 | struct mantis_pci *mantis; | ||
79 | struct mantis_ca *ca; | ||
80 | |||
81 | mantis = (struct mantis_pci *) dev_id; | ||
82 | if (unlikely(mantis == NULL)) { | ||
83 | dprintk(MANTIS_ERROR, 1, "Mantis == NULL"); | ||
84 | return IRQ_NONE; | ||
85 | } | ||
86 | ca = mantis->mantis_ca; | ||
87 | |||
88 | stat = mmread(MANTIS_INT_STAT); | ||
89 | mask = mmread(MANTIS_INT_MASK); | ||
90 | mstat = lstat = stat & ~MANTIS_INT_RISCSTAT; | ||
91 | if (!(stat & mask)) | ||
92 | return IRQ_NONE; | ||
93 | |||
94 | rst_mask = MANTIS_GPIF_WRACK | | ||
95 | MANTIS_GPIF_OTHERR | | ||
96 | MANTIS_SBUF_WSTO | | ||
97 | MANTIS_GPIF_EXTIRQ; | ||
98 | |||
99 | rst_stat = mmread(MANTIS_GPIF_STATUS); | ||
100 | rst_stat &= rst_mask; | ||
101 | mmwrite(rst_stat, MANTIS_GPIF_STATUS); | ||
102 | |||
103 | mantis->mantis_int_stat = stat; | ||
104 | mantis->mantis_int_mask = mask; | ||
105 | dprintk(MANTIS_DEBUG, 0, "\n-- Stat=<%02x> Mask=<%02x> --", stat, mask); | ||
106 | if (stat & MANTIS_INT_RISCEN) { | ||
107 | dprintk(MANTIS_DEBUG, 0, "<%s>", label[0]); | ||
108 | } | ||
109 | if (stat & MANTIS_INT_IRQ0) { | ||
110 | dprintk(MANTIS_DEBUG, 0, "<%s>", label[1]); | ||
111 | mantis->gpif_status = rst_stat; | ||
112 | wake_up(&ca->hif_write_wq); | ||
113 | schedule_work(&ca->hif_evm_work); | ||
114 | } | ||
115 | if (stat & MANTIS_INT_IRQ1) { | ||
116 | dprintk(MANTIS_DEBUG, 0, "<%s>", label[2]); | ||
117 | schedule_work(&mantis->uart_work); | ||
118 | } | ||
119 | if (stat & MANTIS_INT_OCERR) { | ||
120 | dprintk(MANTIS_DEBUG, 0, "<%s>", label[3]); | ||
121 | } | ||
122 | if (stat & MANTIS_INT_PABORT) { | ||
123 | dprintk(MANTIS_DEBUG, 0, "<%s>", label[4]); | ||
124 | } | ||
125 | if (stat & MANTIS_INT_RIPERR) { | ||
126 | dprintk(MANTIS_DEBUG, 0, "<%s>", label[5]); | ||
127 | } | ||
128 | if (stat & MANTIS_INT_PPERR) { | ||
129 | dprintk(MANTIS_DEBUG, 0, "<%s>", label[6]); | ||
130 | } | ||
131 | if (stat & MANTIS_INT_FTRGT) { | ||
132 | dprintk(MANTIS_DEBUG, 0, "<%s>", label[7]); | ||
133 | } | ||
134 | if (stat & MANTIS_INT_RISCI) { | ||
135 | dprintk(MANTIS_DEBUG, 0, "<%s>", label[8]); | ||
136 | mantis->finished_block = (stat & MANTIS_INT_RISCSTAT) >> 28; | ||
137 | tasklet_schedule(&mantis->tasklet); | ||
138 | } | ||
139 | if (stat & MANTIS_INT_I2CDONE) { | ||
140 | dprintk(MANTIS_DEBUG, 0, "<%s>", label[9]); | ||
141 | wake_up(&mantis->i2c_wq); | ||
142 | } | ||
143 | mmwrite(stat, MANTIS_INT_STAT); | ||
144 | stat &= ~(MANTIS_INT_RISCEN | MANTIS_INT_I2CDONE | | ||
145 | MANTIS_INT_I2CRACK | MANTIS_INT_PCMCIA7 | | ||
146 | MANTIS_INT_PCMCIA6 | MANTIS_INT_PCMCIA5 | | ||
147 | MANTIS_INT_PCMCIA4 | MANTIS_INT_PCMCIA3 | | ||
148 | MANTIS_INT_PCMCIA2 | MANTIS_INT_PCMCIA1 | | ||
149 | MANTIS_INT_PCMCIA0 | MANTIS_INT_IRQ1 | | ||
150 | MANTIS_INT_IRQ0 | MANTIS_INT_OCERR | | ||
151 | MANTIS_INT_PABORT | MANTIS_INT_RIPERR | | ||
152 | MANTIS_INT_PPERR | MANTIS_INT_FTRGT | | ||
153 | MANTIS_INT_RISCI); | ||
154 | |||
155 | if (stat) | ||
156 | dprintk(MANTIS_DEBUG, 0, "<Unknown> Stat=<%02x> Mask=<%02x>", stat, mask); | ||
157 | |||
158 | dprintk(MANTIS_DEBUG, 0, "\n"); | ||
159 | return IRQ_HANDLED; | ||
160 | } | ||
161 | |||
162 | static int __devinit mantis_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) | ||
163 | { | ||
164 | struct mantis_pci *mantis; | ||
165 | struct mantis_hwconfig *config; | ||
166 | int err = 0; | ||
167 | |||
168 | mantis = kzalloc(sizeof(struct mantis_pci), GFP_KERNEL); | ||
169 | if (mantis == NULL) { | ||
170 | printk(KERN_ERR "%s ERROR: Out of memory\n", __func__); | ||
171 | err = -ENOMEM; | ||
172 | goto fail0; | ||
173 | } | ||
174 | |||
175 | mantis->num = devs; | ||
176 | mantis->verbose = verbose; | ||
177 | mantis->pdev = pdev; | ||
178 | config = (struct mantis_hwconfig *) pci_id->driver_data; | ||
179 | config->irq_handler = &mantis_irq_handler; | ||
180 | mantis->hwconfig = config; | ||
181 | |||
182 | err = mantis_pci_init(mantis); | ||
183 | if (err) { | ||
184 | dprintk(MANTIS_ERROR, 1, "ERROR: Mantis PCI initialization failed <%d>", err); | ||
185 | goto fail1; | ||
186 | } | ||
187 | |||
188 | err = mantis_stream_control(mantis, STREAM_TO_HIF); | ||
189 | if (err < 0) { | ||
190 | dprintk(MANTIS_ERROR, 1, "ERROR: Mantis stream control failed <%d>", err); | ||
191 | goto fail1; | ||
192 | } | ||
193 | |||
194 | err = mantis_i2c_init(mantis); | ||
195 | if (err < 0) { | ||
196 | dprintk(MANTIS_ERROR, 1, "ERROR: Mantis I2C initialization failed <%d>", err); | ||
197 | goto fail2; | ||
198 | } | ||
199 | |||
200 | err = mantis_get_mac(mantis); | ||
201 | if (err < 0) { | ||
202 | dprintk(MANTIS_ERROR, 1, "ERROR: Mantis MAC address read failed <%d>", err); | ||
203 | goto fail2; | ||
204 | } | ||
205 | |||
206 | err = mantis_dma_init(mantis); | ||
207 | if (err < 0) { | ||
208 | dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA initialization failed <%d>", err); | ||
209 | goto fail3; | ||
210 | } | ||
211 | |||
212 | err = mantis_dvb_init(mantis); | ||
213 | if (err < 0) { | ||
214 | dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DVB initialization failed <%d>", err); | ||
215 | goto fail4; | ||
216 | } | ||
217 | err = mantis_uart_init(mantis); | ||
218 | if (err < 0) { | ||
219 | dprintk(MANTIS_ERROR, 1, "ERROR: Mantis UART initialization failed <%d>", err); | ||
220 | goto fail6; | ||
221 | } | ||
222 | |||
223 | devs++; | ||
224 | |||
225 | return err; | ||
226 | |||
227 | |||
228 | dprintk(MANTIS_ERROR, 1, "ERROR: Mantis UART exit! <%d>", err); | ||
229 | mantis_uart_exit(mantis); | ||
230 | |||
231 | fail6: | ||
232 | fail4: | ||
233 | dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA exit! <%d>", err); | ||
234 | mantis_dma_exit(mantis); | ||
235 | |||
236 | fail3: | ||
237 | dprintk(MANTIS_ERROR, 1, "ERROR: Mantis I2C exit! <%d>", err); | ||
238 | mantis_i2c_exit(mantis); | ||
239 | |||
240 | fail2: | ||
241 | dprintk(MANTIS_ERROR, 1, "ERROR: Mantis PCI exit! <%d>", err); | ||
242 | mantis_pci_exit(mantis); | ||
243 | |||
244 | fail1: | ||
245 | dprintk(MANTIS_ERROR, 1, "ERROR: Mantis free! <%d>", err); | ||
246 | kfree(mantis); | ||
247 | |||
248 | fail0: | ||
249 | return err; | ||
250 | } | ||
251 | |||
252 | static void __devexit mantis_pci_remove(struct pci_dev *pdev) | ||
253 | { | ||
254 | struct mantis_pci *mantis = pci_get_drvdata(pdev); | ||
255 | |||
256 | if (mantis) { | ||
257 | |||
258 | mantis_uart_exit(mantis); | ||
259 | mantis_dvb_exit(mantis); | ||
260 | mantis_dma_exit(mantis); | ||
261 | mantis_i2c_exit(mantis); | ||
262 | mantis_pci_exit(mantis); | ||
263 | kfree(mantis); | ||
264 | } | ||
265 | return; | ||
266 | } | ||
267 | |||
268 | static struct pci_device_id mantis_pci_table[] = { | ||
269 | MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_1033_DVB_S, &vp1033_config), | ||
270 | MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_1034_DVB_S, &vp1034_config), | ||
271 | MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_1041_DVB_S2, &vp1041_config), | ||
272 | MAKE_ENTRY(TECHNISAT, SKYSTAR_HD2_10, &vp1041_config), | ||
273 | MAKE_ENTRY(TECHNISAT, SKYSTAR_HD2_20, &vp1041_config), | ||
274 | MAKE_ENTRY(TERRATEC, CINERGY_S2_PCI_HD, &vp1041_config), | ||
275 | MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_2033_DVB_C, &vp2033_config), | ||
276 | MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_2040_DVB_C, &vp2040_config), | ||
277 | MAKE_ENTRY(TECHNISAT, CABLESTAR_HD2, &vp2040_config), | ||
278 | MAKE_ENTRY(TERRATEC, CINERGY_C, &vp2033_config), | ||
279 | MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_3030_DVB_T, &vp3030_config), | ||
280 | { } | ||
281 | }; | ||
282 | |||
283 | static struct pci_driver mantis_pci_driver = { | ||
284 | .name = DRIVER_NAME, | ||
285 | .id_table = mantis_pci_table, | ||
286 | .probe = mantis_pci_probe, | ||
287 | .remove = mantis_pci_remove, | ||
288 | }; | ||
289 | |||
290 | static int __devinit mantis_init(void) | ||
291 | { | ||
292 | return pci_register_driver(&mantis_pci_driver); | ||
293 | } | ||
294 | |||
295 | static void __devexit mantis_exit(void) | ||
296 | { | ||
297 | return pci_unregister_driver(&mantis_pci_driver); | ||
298 | } | ||
299 | |||
300 | module_init(mantis_init); | ||
301 | module_exit(mantis_exit); | ||
302 | |||
303 | MODULE_DESCRIPTION("MANTIS driver"); | ||
304 | MODULE_AUTHOR("Manu Abraham"); | ||
305 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h new file mode 100644 index 000000000000..d0b645a483c9 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_common.h | |||
@@ -0,0 +1,179 @@ | |||
1 | /* | ||
2 | Mantis PCI bridge driver | ||
3 | |||
4 | Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #ifndef __MANTIS_COMMON_H | ||
22 | #define __MANTIS_COMMON_H | ||
23 | |||
24 | #include <linux/mutex.h> | ||
25 | #include <linux/workqueue.h> | ||
26 | |||
27 | #include "mantis_uart.h" | ||
28 | |||
29 | #include "mantis_link.h" | ||
30 | |||
31 | #define MANTIS_ERROR 0 | ||
32 | #define MANTIS_NOTICE 1 | ||
33 | #define MANTIS_INFO 2 | ||
34 | #define MANTIS_DEBUG 3 | ||
35 | #define MANTIS_TMG 9 | ||
36 | |||
37 | #define dprintk(y, z, format, arg...) do { \ | ||
38 | if (z) { \ | ||
39 | if ((mantis->verbose > MANTIS_ERROR) && (mantis->verbose > y)) \ | ||
40 | printk(KERN_ERR "%s (%d): " format "\n" , __func__ , mantis->num , ##arg); \ | ||
41 | else if ((mantis->verbose > MANTIS_NOTICE) && (mantis->verbose > y)) \ | ||
42 | printk(KERN_NOTICE "%s (%d): " format "\n" , __func__ , mantis->num , ##arg); \ | ||
43 | else if ((mantis->verbose > MANTIS_INFO) && (mantis->verbose > y)) \ | ||
44 | printk(KERN_INFO "%s (%d): " format "\n" , __func__ , mantis->num , ##arg); \ | ||
45 | else if ((mantis->verbose > MANTIS_DEBUG) && (mantis->verbose > y)) \ | ||
46 | printk(KERN_DEBUG "%s (%d): " format "\n" , __func__ , mantis->num , ##arg); \ | ||
47 | else if ((mantis->verbose > MANTIS_TMG) && (mantis->verbose > y)) \ | ||
48 | printk(KERN_DEBUG "%s (%d): " format "\n" , __func__ , mantis->num , ##arg); \ | ||
49 | } else { \ | ||
50 | if (mantis->verbose > y) \ | ||
51 | printk(format , ##arg); \ | ||
52 | } \ | ||
53 | } while(0) | ||
54 | |||
55 | #define mwrite(dat, addr) writel((dat), addr) | ||
56 | #define mread(addr) readl(addr) | ||
57 | |||
58 | #define mmwrite(dat, addr) mwrite((dat), (mantis->mmio + (addr))) | ||
59 | #define mmread(addr) mread(mantis->mmio + (addr)) | ||
60 | |||
61 | #define MANTIS_TS_188 0 | ||
62 | #define MANTIS_TS_204 1 | ||
63 | |||
64 | #define TWINHAN_TECHNOLOGIES 0x1822 | ||
65 | #define MANTIS 0x4e35 | ||
66 | |||
67 | #define TECHNISAT 0x1ae4 | ||
68 | #define TERRATEC 0x153b | ||
69 | |||
70 | #define MAKE_ENTRY(__subven, __subdev, __configptr) { \ | ||
71 | .vendor = TWINHAN_TECHNOLOGIES, \ | ||
72 | .device = MANTIS, \ | ||
73 | .subvendor = (__subven), \ | ||
74 | .subdevice = (__subdev), \ | ||
75 | .driver_data = (unsigned long) (__configptr) \ | ||
76 | } | ||
77 | |||
78 | enum mantis_i2c_mode { | ||
79 | MANTIS_PAGE_MODE = 0, | ||
80 | MANTIS_BYTE_MODE, | ||
81 | }; | ||
82 | |||
83 | struct mantis_pci; | ||
84 | |||
85 | struct mantis_hwconfig { | ||
86 | char *model_name; | ||
87 | char *dev_type; | ||
88 | u32 ts_size; | ||
89 | |||
90 | enum mantis_baud baud_rate; | ||
91 | enum mantis_parity parity; | ||
92 | u32 bytes; | ||
93 | |||
94 | irqreturn_t (*irq_handler)(int irq, void *dev_id); | ||
95 | int (*frontend_init)(struct mantis_pci *mantis, struct dvb_frontend *fe); | ||
96 | |||
97 | u8 power; | ||
98 | u8 reset; | ||
99 | |||
100 | enum mantis_i2c_mode i2c_mode; | ||
101 | }; | ||
102 | |||
103 | struct mantis_pci { | ||
104 | unsigned int verbose; | ||
105 | |||
106 | /* PCI stuff */ | ||
107 | u16 vendor_id; | ||
108 | u16 device_id; | ||
109 | u16 subsystem_vendor; | ||
110 | u16 subsystem_device; | ||
111 | |||
112 | u8 latency; | ||
113 | |||
114 | struct pci_dev *pdev; | ||
115 | |||
116 | unsigned long mantis_addr; | ||
117 | void __iomem *mmio; | ||
118 | |||
119 | u8 irq; | ||
120 | u8 revision; | ||
121 | |||
122 | unsigned int num; | ||
123 | |||
124 | /* RISC Core */ | ||
125 | u32 finished_block; | ||
126 | u32 last_block; | ||
127 | u32 line_bytes; | ||
128 | u32 line_count; | ||
129 | u32 risc_pos; | ||
130 | u8 *buf_cpu; | ||
131 | dma_addr_t buf_dma; | ||
132 | u32 *risc_cpu; | ||
133 | dma_addr_t risc_dma; | ||
134 | |||
135 | struct tasklet_struct tasklet; | ||
136 | |||
137 | struct i2c_adapter adapter; | ||
138 | int i2c_rc; | ||
139 | wait_queue_head_t i2c_wq; | ||
140 | struct mutex i2c_lock; | ||
141 | |||
142 | /* DVB stuff */ | ||
143 | struct dvb_adapter dvb_adapter; | ||
144 | struct dvb_frontend *fe; | ||
145 | struct dvb_demux demux; | ||
146 | struct dmxdev dmxdev; | ||
147 | struct dmx_frontend fe_hw; | ||
148 | struct dmx_frontend fe_mem; | ||
149 | struct dvb_net dvbnet; | ||
150 | |||
151 | u8 feeds; | ||
152 | |||
153 | struct mantis_hwconfig *hwconfig; | ||
154 | |||
155 | u32 mantis_int_stat; | ||
156 | u32 mantis_int_mask; | ||
157 | |||
158 | /* board specific */ | ||
159 | u8 mac_address[8]; | ||
160 | u32 sub_vendor_id; | ||
161 | u32 sub_device_id; | ||
162 | |||
163 | /* A12 A13 A14 */ | ||
164 | u32 gpio_status; | ||
165 | |||
166 | u32 gpif_status; | ||
167 | |||
168 | struct mantis_ca *mantis_ca; | ||
169 | |||
170 | wait_queue_head_t uart_wq; | ||
171 | struct work_struct uart_work; | ||
172 | spinlock_t uart_lock; | ||
173 | |||
174 | struct input_dev *rc; | ||
175 | }; | ||
176 | |||
177 | #define MANTIS_HIF_STATUS (mantis->gpio_status) | ||
178 | |||
179 | #endif /* __MANTIS_COMMON_H */ | ||
diff --git a/drivers/media/dvb/mantis/mantis_core.c b/drivers/media/dvb/mantis/mantis_core.c new file mode 100644 index 000000000000..8113b23ce448 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_core.c | |||
@@ -0,0 +1,238 @@ | |||
1 | /* | ||
2 | Mantis PCI bridge driver | ||
3 | |||
4 | Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include "mantis_common.h" | ||
22 | #include "mantis_core.h" | ||
23 | #include "mantis_vp1033.h" | ||
24 | #include "mantis_vp1034.h" | ||
25 | #include "mantis_vp1041.h" | ||
26 | #include "mantis_vp2033.h" | ||
27 | #include "mantis_vp2040.h" | ||
28 | #include "mantis_vp3030.h" | ||
29 | |||
30 | static int read_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length) | ||
31 | { | ||
32 | int err; | ||
33 | struct i2c_msg msg[] = { | ||
34 | { | ||
35 | .addr = 0x50, | ||
36 | .flags = 0, | ||
37 | .buf = data, | ||
38 | .len = 1 | ||
39 | }, { | ||
40 | .addr = 0x50, | ||
41 | .flags = I2C_M_RD, | ||
42 | .buf = data, | ||
43 | .len = length | ||
44 | }, | ||
45 | }; | ||
46 | |||
47 | err = i2c_transfer(&mantis->adapter, msg, 2); | ||
48 | if (err < 0) { | ||
49 | dprintk(verbose, MANTIS_ERROR, 1, | ||
50 | "ERROR: i2c read: < err=%i d0=0x%02x d1=0x%02x >", | ||
51 | err, data[0], data[1]); | ||
52 | |||
53 | return err; | ||
54 | } | ||
55 | |||
56 | return 0; | ||
57 | } | ||
58 | |||
59 | static int write_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length) | ||
60 | { | ||
61 | int err; | ||
62 | |||
63 | struct i2c_msg msg = { | ||
64 | .addr = 0x50, | ||
65 | .flags = 0, | ||
66 | .buf = data, | ||
67 | .len = length | ||
68 | }; | ||
69 | |||
70 | err = i2c_transfer(&mantis->adapter, &msg, 1); | ||
71 | if (err < 0) { | ||
72 | dprintk(verbose, MANTIS_ERROR, 1, | ||
73 | "ERROR: i2c write: < err=%i length=0x%02x d0=0x%02x, d1=0x%02x >", | ||
74 | err, length, data[0], data[1]); | ||
75 | |||
76 | return err; | ||
77 | } | ||
78 | |||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | static int get_mac_address(struct mantis_pci *mantis) | ||
83 | { | ||
84 | int err; | ||
85 | |||
86 | mantis->mac_address[0] = 0x08; | ||
87 | err = read_eeprom_byte(mantis, &mantis->mac_address[0], 6); | ||
88 | if (err < 0) { | ||
89 | dprintk(verbose, MANTIS_ERROR, 1, "Mantis EEPROM read error"); | ||
90 | |||
91 | return err; | ||
92 | } | ||
93 | dprintk(verbose, MANTIS_ERROR, 0, | ||
94 | " MAC Address=[%02x:%02x:%02x:%02x:%02x:%02x]\n", | ||
95 | mantis->mac_address[0], mantis->mac_address[1], | ||
96 | mantis->mac_address[2], mantis->mac_address[3], | ||
97 | mantis->mac_address[4], mantis->mac_address[5]); | ||
98 | |||
99 | return 0; | ||
100 | } | ||
101 | |||
102 | #define MANTIS_MODEL_UNKNOWN "UNKNOWN" | ||
103 | #define MANTIS_DEV_UNKNOWN "UNKNOWN" | ||
104 | |||
105 | struct mantis_hwconfig unknown_device = { | ||
106 | .model_name = MANTIS_MODEL_UNKNOWN, | ||
107 | .dev_type = MANTIS_DEV_UNKNOWN, | ||
108 | }; | ||
109 | |||
110 | static void mantis_load_config(struct mantis_pci *mantis) | ||
111 | { | ||
112 | switch (mantis->subsystem_device) { | ||
113 | case MANTIS_VP_1033_DVB_S: /* VP-1033 */ | ||
114 | mantis->hwconfig = &vp1033_mantis_config; | ||
115 | break; | ||
116 | case MANTIS_VP_1034_DVB_S: /* VP-1034 */ | ||
117 | mantis->hwconfig = &vp1034_mantis_config; | ||
118 | break; | ||
119 | case MANTIS_VP_1041_DVB_S2: /* VP-1041 */ | ||
120 | case TECHNISAT_SKYSTAR_HD2: | ||
121 | mantis->hwconfig = &vp1041_mantis_config; | ||
122 | break; | ||
123 | case MANTIS_VP_2033_DVB_C: /* VP-2033 */ | ||
124 | mantis->hwconfig = &vp2033_mantis_config; | ||
125 | break; | ||
126 | case MANTIS_VP_2040_DVB_C: /* VP-2040 */ | ||
127 | case TERRATEC_CINERGY_C_PCI: /* VP-2040 clone */ | ||
128 | case TECHNISAT_CABLESTAR_HD2: | ||
129 | mantis->hwconfig = &vp2040_mantis_config; | ||
130 | break; | ||
131 | case MANTIS_VP_3030_DVB_T: /* VP-3030 */ | ||
132 | mantis->hwconfig = &vp3030_mantis_config; | ||
133 | break; | ||
134 | default: | ||
135 | mantis->hwconfig = &unknown_device; | ||
136 | break; | ||
137 | } | ||
138 | } | ||
139 | |||
140 | int mantis_core_init(struct mantis_pci *mantis) | ||
141 | { | ||
142 | int err = 0; | ||
143 | |||
144 | mantis_load_config(mantis); | ||
145 | dprintk(verbose, MANTIS_ERROR, 0, "found a %s PCI %s device on (%02x:%02x.%x),\n", | ||
146 | mantis->hwconfig->model_name, mantis->hwconfig->dev_type, | ||
147 | mantis->pdev->bus->number, PCI_SLOT(mantis->pdev->devfn), PCI_FUNC(mantis->pdev->devfn)); | ||
148 | dprintk(verbose, MANTIS_ERROR, 0, " Mantis Rev %d [%04x:%04x], ", | ||
149 | mantis->revision, | ||
150 | mantis->subsystem_vendor, mantis->subsystem_device); | ||
151 | dprintk(verbose, MANTIS_ERROR, 0, | ||
152 | "irq: %d, latency: %d\n memory: 0x%lx, mmio: 0x%p\n", | ||
153 | mantis->pdev->irq, mantis->latency, | ||
154 | mantis->mantis_addr, mantis->mantis_mmio); | ||
155 | |||
156 | err = mantis_i2c_init(mantis); | ||
157 | if (err < 0) { | ||
158 | dprintk(verbose, MANTIS_ERROR, 1, "Mantis I2C init failed"); | ||
159 | return err; | ||
160 | } | ||
161 | err = get_mac_address(mantis); | ||
162 | if (err < 0) { | ||
163 | dprintk(verbose, MANTIS_ERROR, 1, "get MAC address failed"); | ||
164 | return err; | ||
165 | } | ||
166 | err = mantis_dma_init(mantis); | ||
167 | if (err < 0) { | ||
168 | dprintk(verbose, MANTIS_ERROR, 1, "Mantis DMA init failed"); | ||
169 | return err; | ||
170 | } | ||
171 | err = mantis_dvb_init(mantis); | ||
172 | if (err < 0) { | ||
173 | dprintk(verbose, MANTIS_DEBUG, 1, "Mantis DVB init failed"); | ||
174 | return err; | ||
175 | } | ||
176 | err = mantis_uart_init(mantis); | ||
177 | if (err < 0) { | ||
178 | dprintk(verbose, MANTIS_DEBUG, 1, "Mantis UART init failed"); | ||
179 | return err; | ||
180 | } | ||
181 | |||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | int mantis_core_exit(struct mantis_pci *mantis) | ||
186 | { | ||
187 | mantis_dma_stop(mantis); | ||
188 | dprintk(verbose, MANTIS_ERROR, 1, "DMA engine stopping"); | ||
189 | |||
190 | mantis_uart_exit(mantis); | ||
191 | dprintk(verbose, MANTIS_ERROR, 1, "UART exit failed"); | ||
192 | |||
193 | if (mantis_dma_exit(mantis) < 0) | ||
194 | dprintk(verbose, MANTIS_ERROR, 1, "DMA exit failed"); | ||
195 | if (mantis_dvb_exit(mantis) < 0) | ||
196 | dprintk(verbose, MANTIS_ERROR, 1, "DVB exit failed"); | ||
197 | if (mantis_i2c_exit(mantis) < 0) | ||
198 | dprintk(verbose, MANTIS_ERROR, 1, "I2C adapter delete.. failed"); | ||
199 | |||
200 | return 0; | ||
201 | } | ||
202 | |||
203 | /* Turn the given bit on or off. */ | ||
204 | void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value) | ||
205 | { | ||
206 | u32 cur; | ||
207 | |||
208 | cur = mmread(MANTIS_GPIF_ADDR); | ||
209 | if (value) | ||
210 | mantis->gpio_status = cur | (1 << bitpos); | ||
211 | else | ||
212 | mantis->gpio_status = cur & (~(1 << bitpos)); | ||
213 | |||
214 | mmwrite(mantis->gpio_status, MANTIS_GPIF_ADDR); | ||
215 | mmwrite(0x00, MANTIS_GPIF_DOUT); | ||
216 | udelay(100); | ||
217 | } | ||
218 | |||
219 | /* direction = 0 , no CI passthrough ; 1 , CI passthrough */ | ||
220 | void mantis_set_direction(struct mantis_pci *mantis, int direction) | ||
221 | { | ||
222 | u32 reg; | ||
223 | |||
224 | reg = mmread(0x28); | ||
225 | dprintk(verbose, MANTIS_DEBUG, 1, "TS direction setup"); | ||
226 | if (direction == 0x01) { | ||
227 | /* to CI */ | ||
228 | reg |= 0x04; | ||
229 | mmwrite(reg, 0x28); | ||
230 | reg &= 0xff - 0x04; | ||
231 | mmwrite(reg, 0x28); | ||
232 | } else { | ||
233 | reg &= 0xff - 0x04; | ||
234 | mmwrite(reg, 0x28); | ||
235 | reg |= 0x04; | ||
236 | mmwrite(reg, 0x28); | ||
237 | } | ||
238 | } | ||
diff --git a/drivers/media/dvb/mantis/mantis_core.h b/drivers/media/dvb/mantis/mantis_core.h new file mode 100644 index 000000000000..833ee42e694e --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_core.h | |||
@@ -0,0 +1,57 @@ | |||
1 | /* | ||
2 | Mantis PCI bridge driver | ||
3 | |||
4 | Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #ifndef __MANTIS_CORE_H | ||
22 | #define __MANTIS_CORE_H | ||
23 | |||
24 | #include "mantis_common.h" | ||
25 | |||
26 | |||
27 | #define FE_TYPE_SAT 0 | ||
28 | #define FE_TYPE_CAB 1 | ||
29 | #define FE_TYPE_TER 2 | ||
30 | |||
31 | #define FE_TYPE_TS204 0 | ||
32 | #define FE_TYPE_TS188 1 | ||
33 | |||
34 | |||
35 | struct vendorname { | ||
36 | u8 *sub_vendor_name; | ||
37 | u32 sub_vendor_id; | ||
38 | }; | ||
39 | |||
40 | struct devicetype { | ||
41 | u8 *sub_device_name; | ||
42 | u32 sub_device_id; | ||
43 | u8 device_type; | ||
44 | u32 type_flags; | ||
45 | }; | ||
46 | |||
47 | |||
48 | extern int mantis_dma_init(struct mantis_pci *mantis); | ||
49 | extern int mantis_dma_exit(struct mantis_pci *mantis); | ||
50 | extern void mantis_dma_start(struct mantis_pci *mantis); | ||
51 | extern void mantis_dma_stop(struct mantis_pci *mantis); | ||
52 | extern int mantis_i2c_init(struct mantis_pci *mantis); | ||
53 | extern int mantis_i2c_exit(struct mantis_pci *mantis); | ||
54 | extern int mantis_core_init(struct mantis_pci *mantis); | ||
55 | extern int mantis_core_exit(struct mantis_pci *mantis); | ||
56 | |||
57 | #endif /* __MANTIS_CORE_H */ | ||
diff --git a/drivers/media/dvb/mantis/mantis_dma.c b/drivers/media/dvb/mantis/mantis_dma.c new file mode 100644 index 000000000000..46202a4012aa --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_dma.c | |||
@@ -0,0 +1,256 @@ | |||
1 | /* | ||
2 | Mantis PCI bridge driver | ||
3 | |||
4 | Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <asm/page.h> | ||
23 | #include <linux/vmalloc.h> | ||
24 | #include <linux/pci.h> | ||
25 | |||
26 | #include <asm/irq.h> | ||
27 | #include <linux/signal.h> | ||
28 | #include <linux/sched.h> | ||
29 | #include <linux/interrupt.h> | ||
30 | |||
31 | #include "dmxdev.h" | ||
32 | #include "dvbdev.h" | ||
33 | #include "dvb_demux.h" | ||
34 | #include "dvb_frontend.h" | ||
35 | #include "dvb_net.h" | ||
36 | |||
37 | #include "mantis_common.h" | ||
38 | #include "mantis_reg.h" | ||
39 | #include "mantis_dma.h" | ||
40 | |||
41 | #define RISC_WRITE (0x01 << 28) | ||
42 | #define RISC_JUMP (0x07 << 28) | ||
43 | #define RISC_IRQ (0x01 << 24) | ||
44 | |||
45 | #define RISC_STATUS(status) ((((~status) & 0x0f) << 20) | ((status & 0x0f) << 16)) | ||
46 | #define RISC_FLUSH() (mantis->risc_pos = 0) | ||
47 | #define RISC_INSTR(opcode) (mantis->risc_cpu[mantis->risc_pos++] = cpu_to_le32(opcode)) | ||
48 | |||
49 | #define MANTIS_BUF_SIZE (64 * 1024) | ||
50 | #define MANTIS_BLOCK_BYTES (MANTIS_BUF_SIZE >> 4) | ||
51 | #define MANTIS_BLOCK_COUNT (1 << 4) | ||
52 | #define MANTIS_RISC_SIZE PAGE_SIZE | ||
53 | |||
54 | int mantis_dma_exit(struct mantis_pci *mantis) | ||
55 | { | ||
56 | if (mantis->buf_cpu) { | ||
57 | dprintk(MANTIS_ERROR, 1, | ||
58 | "DMA=0x%lx cpu=0x%p size=%d", | ||
59 | (unsigned long) mantis->buf_dma, | ||
60 | mantis->buf_cpu, | ||
61 | MANTIS_BUF_SIZE); | ||
62 | |||
63 | pci_free_consistent(mantis->pdev, MANTIS_BUF_SIZE, | ||
64 | mantis->buf_cpu, mantis->buf_dma); | ||
65 | |||
66 | mantis->buf_cpu = NULL; | ||
67 | } | ||
68 | if (mantis->risc_cpu) { | ||
69 | dprintk(MANTIS_ERROR, 1, | ||
70 | "RISC=0x%lx cpu=0x%p size=%lx", | ||
71 | (unsigned long) mantis->risc_dma, | ||
72 | mantis->risc_cpu, | ||
73 | MANTIS_RISC_SIZE); | ||
74 | |||
75 | pci_free_consistent(mantis->pdev, MANTIS_RISC_SIZE, | ||
76 | mantis->risc_cpu, mantis->risc_dma); | ||
77 | |||
78 | mantis->risc_cpu = NULL; | ||
79 | } | ||
80 | |||
81 | return 0; | ||
82 | } | ||
83 | EXPORT_SYMBOL_GPL(mantis_dma_exit); | ||
84 | |||
85 | static inline int mantis_alloc_buffers(struct mantis_pci *mantis) | ||
86 | { | ||
87 | if (!mantis->buf_cpu) { | ||
88 | mantis->buf_cpu = pci_alloc_consistent(mantis->pdev, | ||
89 | MANTIS_BUF_SIZE, | ||
90 | &mantis->buf_dma); | ||
91 | if (!mantis->buf_cpu) { | ||
92 | dprintk(MANTIS_ERROR, 1, | ||
93 | "DMA buffer allocation failed"); | ||
94 | |||
95 | goto err; | ||
96 | } | ||
97 | dprintk(MANTIS_ERROR, 1, | ||
98 | "DMA=0x%lx cpu=0x%p size=%d", | ||
99 | (unsigned long) mantis->buf_dma, | ||
100 | mantis->buf_cpu, MANTIS_BUF_SIZE); | ||
101 | } | ||
102 | if (!mantis->risc_cpu) { | ||
103 | mantis->risc_cpu = pci_alloc_consistent(mantis->pdev, | ||
104 | MANTIS_RISC_SIZE, | ||
105 | &mantis->risc_dma); | ||
106 | |||
107 | if (!mantis->risc_cpu) { | ||
108 | dprintk(MANTIS_ERROR, 1, | ||
109 | "RISC program allocation failed"); | ||
110 | |||
111 | mantis_dma_exit(mantis); | ||
112 | |||
113 | goto err; | ||
114 | } | ||
115 | dprintk(MANTIS_ERROR, 1, | ||
116 | "RISC=0x%lx cpu=0x%p size=%lx", | ||
117 | (unsigned long) mantis->risc_dma, | ||
118 | mantis->risc_cpu, MANTIS_RISC_SIZE); | ||
119 | } | ||
120 | |||
121 | return 0; | ||
122 | err: | ||
123 | dprintk(MANTIS_ERROR, 1, "Out of memory (?) ....."); | ||
124 | return -ENOMEM; | ||
125 | } | ||
126 | |||
127 | static inline int mantis_calc_lines(struct mantis_pci *mantis) | ||
128 | { | ||
129 | mantis->line_bytes = MANTIS_BLOCK_BYTES; | ||
130 | mantis->line_count = MANTIS_BLOCK_COUNT; | ||
131 | |||
132 | while (mantis->line_bytes > 4095) { | ||
133 | mantis->line_bytes >>= 1; | ||
134 | mantis->line_count <<= 1; | ||
135 | } | ||
136 | |||
137 | dprintk(MANTIS_DEBUG, 1, "Mantis RISC block bytes=[%d], line bytes=[%d], line count=[%d]", | ||
138 | MANTIS_BLOCK_BYTES, mantis->line_bytes, mantis->line_count); | ||
139 | |||
140 | if (mantis->line_count > 255) { | ||
141 | dprintk(MANTIS_ERROR, 1, "Buffer size error"); | ||
142 | return -EINVAL; | ||
143 | } | ||
144 | |||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | int mantis_dma_init(struct mantis_pci *mantis) | ||
149 | { | ||
150 | int err = 0; | ||
151 | |||
152 | dprintk(MANTIS_DEBUG, 1, "Mantis DMA init"); | ||
153 | if (mantis_alloc_buffers(mantis) < 0) { | ||
154 | dprintk(MANTIS_ERROR, 1, "Error allocating DMA buffer"); | ||
155 | |||
156 | /* Stop RISC Engine */ | ||
157 | mmwrite(0, MANTIS_DMA_CTL); | ||
158 | |||
159 | goto err; | ||
160 | } | ||
161 | err = mantis_calc_lines(mantis); | ||
162 | if (err < 0) { | ||
163 | dprintk(MANTIS_ERROR, 1, "Mantis calc lines failed"); | ||
164 | |||
165 | goto err; | ||
166 | } | ||
167 | |||
168 | return 0; | ||
169 | err: | ||
170 | return err; | ||
171 | } | ||
172 | EXPORT_SYMBOL_GPL(mantis_dma_init); | ||
173 | |||
174 | static inline void mantis_risc_program(struct mantis_pci *mantis) | ||
175 | { | ||
176 | u32 buf_pos = 0; | ||
177 | u32 line; | ||
178 | |||
179 | dprintk(MANTIS_DEBUG, 1, "Mantis create RISC program"); | ||
180 | RISC_FLUSH(); | ||
181 | |||
182 | dprintk(MANTIS_DEBUG, 1, "risc len lines %u, bytes per line %u", | ||
183 | mantis->line_count, mantis->line_bytes); | ||
184 | |||
185 | for (line = 0; line < mantis->line_count; line++) { | ||
186 | dprintk(MANTIS_DEBUG, 1, "RISC PROG line=[%d]", line); | ||
187 | if (!(buf_pos % MANTIS_BLOCK_BYTES)) { | ||
188 | RISC_INSTR(RISC_WRITE | | ||
189 | RISC_IRQ | | ||
190 | RISC_STATUS(((buf_pos / MANTIS_BLOCK_BYTES) + | ||
191 | (MANTIS_BLOCK_COUNT - 1)) % | ||
192 | MANTIS_BLOCK_COUNT) | | ||
193 | mantis->line_bytes); | ||
194 | } else { | ||
195 | RISC_INSTR(RISC_WRITE | mantis->line_bytes); | ||
196 | } | ||
197 | RISC_INSTR(mantis->buf_dma + buf_pos); | ||
198 | buf_pos += mantis->line_bytes; | ||
199 | } | ||
200 | RISC_INSTR(RISC_JUMP); | ||
201 | RISC_INSTR(mantis->risc_dma); | ||
202 | } | ||
203 | |||
204 | void mantis_dma_start(struct mantis_pci *mantis) | ||
205 | { | ||
206 | dprintk(MANTIS_DEBUG, 1, "Mantis Start DMA engine"); | ||
207 | |||
208 | mantis_risc_program(mantis); | ||
209 | mmwrite(mantis->risc_dma, MANTIS_RISC_START); | ||
210 | mmwrite(mmread(MANTIS_GPIF_ADDR) | MANTIS_GPIF_HIFRDWRN, MANTIS_GPIF_ADDR); | ||
211 | |||
212 | mmwrite(0, MANTIS_DMA_CTL); | ||
213 | mantis->last_block = mantis->finished_block = 0; | ||
214 | |||
215 | mmwrite(mmread(MANTIS_INT_MASK) | MANTIS_INT_RISCI, MANTIS_INT_MASK); | ||
216 | |||
217 | mmwrite(MANTIS_FIFO_EN | MANTIS_DCAP_EN | ||
218 | | MANTIS_RISC_EN, MANTIS_DMA_CTL); | ||
219 | |||
220 | } | ||
221 | |||
222 | void mantis_dma_stop(struct mantis_pci *mantis) | ||
223 | { | ||
224 | u32 stat = 0, mask = 0; | ||
225 | |||
226 | stat = mmread(MANTIS_INT_STAT); | ||
227 | mask = mmread(MANTIS_INT_MASK); | ||
228 | dprintk(MANTIS_DEBUG, 1, "Mantis Stop DMA engine"); | ||
229 | |||
230 | mmwrite((mmread(MANTIS_GPIF_ADDR) & (~(MANTIS_GPIF_HIFRDWRN))), MANTIS_GPIF_ADDR); | ||
231 | |||
232 | mmwrite((mmread(MANTIS_DMA_CTL) & ~(MANTIS_FIFO_EN | | ||
233 | MANTIS_DCAP_EN | | ||
234 | MANTIS_RISC_EN)), MANTIS_DMA_CTL); | ||
235 | |||
236 | mmwrite(mmread(MANTIS_INT_STAT), MANTIS_INT_STAT); | ||
237 | |||
238 | mmwrite(mmread(MANTIS_INT_MASK) & ~(MANTIS_INT_RISCI | | ||
239 | MANTIS_INT_RISCEN), MANTIS_INT_MASK); | ||
240 | } | ||
241 | |||
242 | |||
243 | void mantis_dma_xfer(unsigned long data) | ||
244 | { | ||
245 | struct mantis_pci *mantis = (struct mantis_pci *) data; | ||
246 | struct mantis_hwconfig *config = mantis->hwconfig; | ||
247 | |||
248 | while (mantis->last_block != mantis->finished_block) { | ||
249 | dprintk(MANTIS_DEBUG, 1, "last block=[%d] finished block=[%d]", | ||
250 | mantis->last_block, mantis->finished_block); | ||
251 | |||
252 | (config->ts_size ? dvb_dmx_swfilter_204 : dvb_dmx_swfilter) | ||
253 | (&mantis->demux, &mantis->buf_cpu[mantis->last_block * MANTIS_BLOCK_BYTES], MANTIS_BLOCK_BYTES); | ||
254 | mantis->last_block = (mantis->last_block + 1) % MANTIS_BLOCK_COUNT; | ||
255 | } | ||
256 | } | ||
diff --git a/drivers/media/dvb/mantis/mantis_dma.h b/drivers/media/dvb/mantis/mantis_dma.h new file mode 100644 index 000000000000..6be00fa82094 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_dma.h | |||
@@ -0,0 +1,30 @@ | |||
1 | /* | ||
2 | Mantis PCI bridge driver | ||
3 | |||
4 | Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #ifndef __MANTIS_DMA_H | ||
22 | #define __MANTIS_DMA_H | ||
23 | |||
24 | extern int mantis_dma_init(struct mantis_pci *mantis); | ||
25 | extern int mantis_dma_exit(struct mantis_pci *mantis); | ||
26 | extern void mantis_dma_start(struct mantis_pci *mantis); | ||
27 | extern void mantis_dma_stop(struct mantis_pci *mantis); | ||
28 | extern void mantis_dma_xfer(unsigned long data); | ||
29 | |||
30 | #endif /* __MANTIS_DMA_H */ | ||
diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c new file mode 100644 index 000000000000..99d82eec3b03 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_dvb.c | |||
@@ -0,0 +1,296 @@ | |||
1 | /* | ||
2 | Mantis PCI bridge driver | ||
3 | Copyright (C) Manu Abraham (abraham.manu@gmail.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; either version 2 of the License, or | ||
8 | (at your option) any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; if not, write to the Free Software | ||
17 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | */ | ||
19 | |||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/bitops.h> | ||
22 | |||
23 | #include <linux/signal.h> | ||
24 | #include <linux/sched.h> | ||
25 | #include <linux/interrupt.h> | ||
26 | #include <linux/pci.h> | ||
27 | #include <linux/i2c.h> | ||
28 | |||
29 | #include "dmxdev.h" | ||
30 | #include "dvbdev.h" | ||
31 | #include "dvb_demux.h" | ||
32 | #include "dvb_frontend.h" | ||
33 | #include "dvb_net.h" | ||
34 | |||
35 | #include "mantis_common.h" | ||
36 | #include "mantis_dma.h" | ||
37 | #include "mantis_ca.h" | ||
38 | #include "mantis_ioc.h" | ||
39 | #include "mantis_dvb.h" | ||
40 | |||
41 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
42 | |||
43 | int mantis_frontend_power(struct mantis_pci *mantis, enum mantis_power power) | ||
44 | { | ||
45 | struct mantis_hwconfig *config = mantis->hwconfig; | ||
46 | |||
47 | switch (power) { | ||
48 | case POWER_ON: | ||
49 | dprintk(MANTIS_DEBUG, 1, "Power ON"); | ||
50 | gpio_set_bits(mantis, config->power, POWER_ON); | ||
51 | msleep(100); | ||
52 | gpio_set_bits(mantis, config->power, POWER_ON); | ||
53 | msleep(100); | ||
54 | break; | ||
55 | |||
56 | case POWER_OFF: | ||
57 | dprintk(MANTIS_DEBUG, 1, "Power OFF"); | ||
58 | gpio_set_bits(mantis, config->power, POWER_OFF); | ||
59 | msleep(100); | ||
60 | break; | ||
61 | |||
62 | default: | ||
63 | dprintk(MANTIS_DEBUG, 1, "Unknown state <%02x>", power); | ||
64 | return -1; | ||
65 | } | ||
66 | |||
67 | return 0; | ||
68 | } | ||
69 | EXPORT_SYMBOL_GPL(mantis_frontend_power); | ||
70 | |||
71 | void mantis_frontend_soft_reset(struct mantis_pci *mantis) | ||
72 | { | ||
73 | struct mantis_hwconfig *config = mantis->hwconfig; | ||
74 | |||
75 | dprintk(MANTIS_DEBUG, 1, "Frontend RESET"); | ||
76 | gpio_set_bits(mantis, config->reset, 0); | ||
77 | msleep(100); | ||
78 | gpio_set_bits(mantis, config->reset, 0); | ||
79 | msleep(100); | ||
80 | gpio_set_bits(mantis, config->reset, 1); | ||
81 | msleep(100); | ||
82 | gpio_set_bits(mantis, config->reset, 1); | ||
83 | msleep(100); | ||
84 | |||
85 | return; | ||
86 | } | ||
87 | EXPORT_SYMBOL_GPL(mantis_frontend_soft_reset); | ||
88 | |||
89 | static int mantis_frontend_shutdown(struct mantis_pci *mantis) | ||
90 | { | ||
91 | int err; | ||
92 | |||
93 | mantis_frontend_soft_reset(mantis); | ||
94 | err = mantis_frontend_power(mantis, POWER_OFF); | ||
95 | if (err != 0) { | ||
96 | dprintk(MANTIS_ERROR, 1, "Frontend POWER OFF failed! <%d>", err); | ||
97 | return 1; | ||
98 | } | ||
99 | |||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | static int mantis_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed) | ||
104 | { | ||
105 | struct dvb_demux *dvbdmx = dvbdmxfeed->demux; | ||
106 | struct mantis_pci *mantis = dvbdmx->priv; | ||
107 | |||
108 | dprintk(MANTIS_DEBUG, 1, "Mantis DVB Start feed"); | ||
109 | if (!dvbdmx->dmx.frontend) { | ||
110 | dprintk(MANTIS_DEBUG, 1, "no frontend ?"); | ||
111 | return -EINVAL; | ||
112 | } | ||
113 | |||
114 | mantis->feeds++; | ||
115 | dprintk(MANTIS_DEBUG, 1, "mantis start feed, feeds=%d", mantis->feeds); | ||
116 | |||
117 | if (mantis->feeds == 1) { | ||
118 | dprintk(MANTIS_DEBUG, 1, "mantis start feed & dma"); | ||
119 | mantis_dma_start(mantis); | ||
120 | } | ||
121 | |||
122 | return mantis->feeds; | ||
123 | } | ||
124 | |||
125 | static int mantis_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) | ||
126 | { | ||
127 | struct dvb_demux *dvbdmx = dvbdmxfeed->demux; | ||
128 | struct mantis_pci *mantis = dvbdmx->priv; | ||
129 | |||
130 | dprintk(MANTIS_DEBUG, 1, "Mantis DVB Stop feed"); | ||
131 | if (!dvbdmx->dmx.frontend) { | ||
132 | dprintk(MANTIS_DEBUG, 1, "no frontend ?"); | ||
133 | return -EINVAL; | ||
134 | } | ||
135 | |||
136 | mantis->feeds--; | ||
137 | if (mantis->feeds == 0) { | ||
138 | dprintk(MANTIS_DEBUG, 1, "mantis stop feed and dma"); | ||
139 | mantis_dma_stop(mantis); | ||
140 | } | ||
141 | |||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | int __devinit mantis_dvb_init(struct mantis_pci *mantis) | ||
146 | { | ||
147 | struct mantis_hwconfig *config = mantis->hwconfig; | ||
148 | int result = -1; | ||
149 | |||
150 | dprintk(MANTIS_DEBUG, 1, "dvb_register_adapter"); | ||
151 | |||
152 | result = dvb_register_adapter(&mantis->dvb_adapter, | ||
153 | "Mantis DVB adapter", | ||
154 | THIS_MODULE, | ||
155 | &mantis->pdev->dev, | ||
156 | adapter_nr); | ||
157 | |||
158 | if (result < 0) { | ||
159 | |||
160 | dprintk(MANTIS_ERROR, 1, "Error registering adapter"); | ||
161 | return -ENODEV; | ||
162 | } | ||
163 | |||
164 | mantis->dvb_adapter.priv = mantis; | ||
165 | mantis->demux.dmx.capabilities = DMX_TS_FILTERING | | ||
166 | DMX_SECTION_FILTERING | | ||
167 | DMX_MEMORY_BASED_FILTERING; | ||
168 | |||
169 | mantis->demux.priv = mantis; | ||
170 | mantis->demux.filternum = 256; | ||
171 | mantis->demux.feednum = 256; | ||
172 | mantis->demux.start_feed = mantis_dvb_start_feed; | ||
173 | mantis->demux.stop_feed = mantis_dvb_stop_feed; | ||
174 | mantis->demux.write_to_decoder = NULL; | ||
175 | |||
176 | dprintk(MANTIS_DEBUG, 1, "dvb_dmx_init"); | ||
177 | result = dvb_dmx_init(&mantis->demux); | ||
178 | if (result < 0) { | ||
179 | dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); | ||
180 | |||
181 | goto err0; | ||
182 | } | ||
183 | |||
184 | mantis->dmxdev.filternum = 256; | ||
185 | mantis->dmxdev.demux = &mantis->demux.dmx; | ||
186 | mantis->dmxdev.capabilities = 0; | ||
187 | dprintk(MANTIS_DEBUG, 1, "dvb_dmxdev_init"); | ||
188 | |||
189 | result = dvb_dmxdev_init(&mantis->dmxdev, &mantis->dvb_adapter); | ||
190 | if (result < 0) { | ||
191 | |||
192 | dprintk(MANTIS_ERROR, 1, "dvb_dmxdev_init failed, ERROR=%d", result); | ||
193 | goto err1; | ||
194 | } | ||
195 | |||
196 | mantis->fe_hw.source = DMX_FRONTEND_0; | ||
197 | result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx, &mantis->fe_hw); | ||
198 | if (result < 0) { | ||
199 | |||
200 | dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); | ||
201 | goto err2; | ||
202 | } | ||
203 | |||
204 | mantis->fe_mem.source = DMX_MEMORY_FE; | ||
205 | result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx, &mantis->fe_mem); | ||
206 | if (result < 0) { | ||
207 | dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); | ||
208 | goto err3; | ||
209 | } | ||
210 | |||
211 | result = mantis->demux.dmx.connect_frontend(&mantis->demux.dmx, &mantis->fe_hw); | ||
212 | if (result < 0) { | ||
213 | dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); | ||
214 | goto err4; | ||
215 | } | ||
216 | |||
217 | dvb_net_init(&mantis->dvb_adapter, &mantis->dvbnet, &mantis->demux.dmx); | ||
218 | tasklet_init(&mantis->tasklet, mantis_dma_xfer, (unsigned long) mantis); | ||
219 | if (mantis->hwconfig) { | ||
220 | result = config->frontend_init(mantis, mantis->fe); | ||
221 | if (result < 0) { | ||
222 | dprintk(MANTIS_ERROR, 1, "!!! NO Frontends found !!!"); | ||
223 | goto err5; | ||
224 | } else { | ||
225 | if (mantis->fe == NULL) { | ||
226 | dprintk(MANTIS_ERROR, 1, "FE <NULL>"); | ||
227 | goto err5; | ||
228 | } | ||
229 | |||
230 | if (dvb_register_frontend(&mantis->dvb_adapter, mantis->fe)) { | ||
231 | dprintk(MANTIS_ERROR, 1, "ERROR: Frontend registration failed"); | ||
232 | |||
233 | if (mantis->fe->ops.release) | ||
234 | mantis->fe->ops.release(mantis->fe); | ||
235 | |||
236 | mantis->fe = NULL; | ||
237 | goto err5; | ||
238 | } | ||
239 | } | ||
240 | } | ||
241 | |||
242 | return 0; | ||
243 | |||
244 | /* Error conditions .. */ | ||
245 | err5: | ||
246 | tasklet_kill(&mantis->tasklet); | ||
247 | dvb_net_release(&mantis->dvbnet); | ||
248 | dvb_unregister_frontend(mantis->fe); | ||
249 | dvb_frontend_detach(mantis->fe); | ||
250 | err4: | ||
251 | mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem); | ||
252 | |||
253 | err3: | ||
254 | mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw); | ||
255 | |||
256 | err2: | ||
257 | dvb_dmxdev_release(&mantis->dmxdev); | ||
258 | |||
259 | err1: | ||
260 | dvb_dmx_release(&mantis->demux); | ||
261 | |||
262 | err0: | ||
263 | dvb_unregister_adapter(&mantis->dvb_adapter); | ||
264 | |||
265 | return result; | ||
266 | } | ||
267 | EXPORT_SYMBOL_GPL(mantis_dvb_init); | ||
268 | |||
269 | int __devexit mantis_dvb_exit(struct mantis_pci *mantis) | ||
270 | { | ||
271 | int err; | ||
272 | |||
273 | if (mantis->fe) { | ||
274 | /* mantis_ca_exit(mantis); */ | ||
275 | err = mantis_frontend_shutdown(mantis); | ||
276 | if (err != 0) | ||
277 | dprintk(MANTIS_ERROR, 1, "Frontend exit while POWER ON! <%d>", err); | ||
278 | dvb_unregister_frontend(mantis->fe); | ||
279 | dvb_frontend_detach(mantis->fe); | ||
280 | } | ||
281 | |||
282 | tasklet_kill(&mantis->tasklet); | ||
283 | dvb_net_release(&mantis->dvbnet); | ||
284 | |||
285 | mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem); | ||
286 | mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw); | ||
287 | |||
288 | dvb_dmxdev_release(&mantis->dmxdev); | ||
289 | dvb_dmx_release(&mantis->demux); | ||
290 | |||
291 | dprintk(MANTIS_DEBUG, 1, "dvb_unregister_adapter"); | ||
292 | dvb_unregister_adapter(&mantis->dvb_adapter); | ||
293 | |||
294 | return 0; | ||
295 | } | ||
296 | EXPORT_SYMBOL_GPL(mantis_dvb_exit); | ||
diff --git a/drivers/media/dvb/mantis/mantis_dvb.h b/drivers/media/dvb/mantis/mantis_dvb.h new file mode 100644 index 000000000000..464199db304e --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_dvb.h | |||
@@ -0,0 +1,35 @@ | |||
1 | /* | ||
2 | Mantis PCI bridge driver | ||
3 | |||
4 | Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #ifndef __MANTIS_DVB_H | ||
22 | #define __MANTIS_DVB_H | ||
23 | |||
24 | enum mantis_power { | ||
25 | POWER_OFF = 0, | ||
26 | POWER_ON = 1 | ||
27 | }; | ||
28 | |||
29 | extern int mantis_frontend_power(struct mantis_pci *mantis, enum mantis_power power); | ||
30 | extern void mantis_frontend_soft_reset(struct mantis_pci *mantis); | ||
31 | |||
32 | extern int mantis_dvb_init(struct mantis_pci *mantis); | ||
33 | extern int mantis_dvb_exit(struct mantis_pci *mantis); | ||
34 | |||
35 | #endif /* __MANTIS_DVB_H */ | ||
diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c new file mode 100644 index 000000000000..a7b369a439d6 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_evm.c | |||
@@ -0,0 +1,117 @@ | |||
1 | /* | ||
2 | Mantis PCI bridge driver | ||
3 | |||
4 | Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | |||
23 | #include <linux/signal.h> | ||
24 | #include <linux/sched.h> | ||
25 | #include <linux/interrupt.h> | ||
26 | |||
27 | #include "dmxdev.h" | ||
28 | #include "dvbdev.h" | ||
29 | #include "dvb_demux.h" | ||
30 | #include "dvb_frontend.h" | ||
31 | #include "dvb_net.h" | ||
32 | |||
33 | #include "mantis_common.h" | ||
34 | #include "mantis_link.h" | ||
35 | #include "mantis_hif.h" | ||
36 | #include "mantis_reg.h" | ||
37 | |||
38 | static void mantis_hifevm_work(struct work_struct *work) | ||
39 | { | ||
40 | struct mantis_ca *ca = container_of(work, struct mantis_ca, hif_evm_work); | ||
41 | struct mantis_pci *mantis = ca->ca_priv; | ||
42 | |||
43 | u32 gpif_stat, gpif_mask; | ||
44 | |||
45 | gpif_stat = mmread(MANTIS_GPIF_STATUS); | ||
46 | gpif_mask = mmread(MANTIS_GPIF_IRQCFG); | ||
47 | |||
48 | if (gpif_stat & MANTIS_GPIF_DETSTAT) { | ||
49 | if (gpif_stat & MANTIS_CARD_PLUGIN) { | ||
50 | dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): CAM Plugin", mantis->num); | ||
51 | mmwrite(0xdada0000, MANTIS_CARD_RESET); | ||
52 | mantis_event_cam_plugin(ca); | ||
53 | dvb_ca_en50221_camchange_irq(&ca->en50221, | ||
54 | 0, | ||
55 | DVB_CA_EN50221_CAMCHANGE_INSERTED); | ||
56 | } | ||
57 | } else { | ||
58 | if (gpif_stat & MANTIS_CARD_PLUGOUT) { | ||
59 | dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): CAM Unplug", mantis->num); | ||
60 | mmwrite(0xdada0000, MANTIS_CARD_RESET); | ||
61 | mantis_event_cam_unplug(ca); | ||
62 | dvb_ca_en50221_camchange_irq(&ca->en50221, | ||
63 | 0, | ||
64 | DVB_CA_EN50221_CAMCHANGE_REMOVED); | ||
65 | } | ||
66 | } | ||
67 | |||
68 | if (mantis->gpif_status & MANTIS_GPIF_EXTIRQ) | ||
69 | dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Ext IRQ", mantis->num); | ||
70 | |||
71 | if (mantis->gpif_status & MANTIS_SBUF_WSTO) | ||
72 | dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Timeout", mantis->num); | ||
73 | |||
74 | if (mantis->gpif_status & MANTIS_GPIF_OTHERR) | ||
75 | dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Alignment Error", mantis->num); | ||
76 | |||
77 | if (gpif_stat & MANTIS_SBUF_OVFLW) | ||
78 | dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Overflow", mantis->num); | ||
79 | |||
80 | if (gpif_stat & MANTIS_GPIF_BRRDY) | ||
81 | dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Read Ready", mantis->num); | ||
82 | |||
83 | if (gpif_stat & MANTIS_GPIF_INTSTAT) | ||
84 | dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): GPIF IRQ", mantis->num); | ||
85 | |||
86 | if (gpif_stat & MANTIS_SBUF_EMPTY) | ||
87 | dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Empty", mantis->num); | ||
88 | |||
89 | if (gpif_stat & MANTIS_SBUF_OPDONE) { | ||
90 | dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer operation complete", mantis->num); | ||
91 | ca->sbuf_status = MANTIS_SBUF_DATA_AVAIL; | ||
92 | ca->hif_event = MANTIS_SBUF_OPDONE; | ||
93 | wake_up(&ca->hif_opdone_wq); | ||
94 | } | ||
95 | } | ||
96 | |||
97 | int mantis_evmgr_init(struct mantis_ca *ca) | ||
98 | { | ||
99 | struct mantis_pci *mantis = ca->ca_priv; | ||
100 | |||
101 | dprintk(MANTIS_DEBUG, 1, "Initializing Mantis Host I/F Event manager"); | ||
102 | INIT_WORK(&ca->hif_evm_work, mantis_hifevm_work); | ||
103 | mantis_pcmcia_init(ca); | ||
104 | schedule_work(&ca->hif_evm_work); | ||
105 | mantis_hif_init(ca); | ||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | void mantis_evmgr_exit(struct mantis_ca *ca) | ||
110 | { | ||
111 | struct mantis_pci *mantis = ca->ca_priv; | ||
112 | |||
113 | dprintk(MANTIS_DEBUG, 1, "Mantis Host I/F Event manager exiting"); | ||
114 | flush_scheduled_work(); | ||
115 | mantis_hif_exit(ca); | ||
116 | mantis_pcmcia_exit(ca); | ||
117 | } | ||
diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c new file mode 100644 index 000000000000..7477dac628b4 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_hif.c | |||
@@ -0,0 +1,240 @@ | |||
1 | /* | ||
2 | Mantis PCI bridge driver | ||
3 | |||
4 | Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/signal.h> | ||
23 | #include <linux/sched.h> | ||
24 | |||
25 | #include <linux/signal.h> | ||
26 | #include <linux/sched.h> | ||
27 | #include <linux/interrupt.h> | ||
28 | |||
29 | #include "dmxdev.h" | ||
30 | #include "dvbdev.h" | ||
31 | #include "dvb_demux.h" | ||
32 | #include "dvb_frontend.h" | ||
33 | #include "dvb_net.h" | ||
34 | |||
35 | #include "mantis_common.h" | ||
36 | |||
37 | #include "mantis_hif.h" | ||
38 | #include "mantis_link.h" /* temporary due to physical layer stuff */ | ||
39 | |||
40 | #include "mantis_reg.h" | ||
41 | |||
42 | |||
43 | static int mantis_hif_sbuf_opdone_wait(struct mantis_ca *ca) | ||
44 | { | ||
45 | struct mantis_pci *mantis = ca->ca_priv; | ||
46 | int rc = 0; | ||
47 | |||
48 | if (wait_event_timeout(ca->hif_opdone_wq, | ||
49 | ca->hif_event & MANTIS_SBUF_OPDONE, | ||
50 | msecs_to_jiffies(500)) == -ERESTARTSYS) { | ||
51 | |||
52 | dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): Smart buffer operation timeout !", mantis->num); | ||
53 | rc = -EREMOTEIO; | ||
54 | } | ||
55 | dprintk(MANTIS_DEBUG, 1, "Smart Buffer Operation complete"); | ||
56 | ca->hif_event &= ~MANTIS_SBUF_OPDONE; | ||
57 | return rc; | ||
58 | } | ||
59 | |||
60 | static int mantis_hif_write_wait(struct mantis_ca *ca) | ||
61 | { | ||
62 | struct mantis_pci *mantis = ca->ca_priv; | ||
63 | u32 opdone = 0, timeout = 0; | ||
64 | int rc = 0; | ||
65 | |||
66 | if (wait_event_timeout(ca->hif_write_wq, | ||
67 | mantis->gpif_status & MANTIS_GPIF_WRACK, | ||
68 | msecs_to_jiffies(500)) == -ERESTARTSYS) { | ||
69 | |||
70 | dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): Write ACK timed out !", mantis->num); | ||
71 | rc = -EREMOTEIO; | ||
72 | } | ||
73 | dprintk(MANTIS_DEBUG, 1, "Write Acknowledged"); | ||
74 | mantis->gpif_status &= ~MANTIS_GPIF_WRACK; | ||
75 | while (!opdone) { | ||
76 | opdone = (mmread(MANTIS_GPIF_STATUS) & MANTIS_SBUF_OPDONE); | ||
77 | udelay(500); | ||
78 | timeout++; | ||
79 | if (timeout > 100) { | ||
80 | dprintk(MANTIS_ERROR, 1, "Adater(%d) Slot(0): Write operation timed out!", mantis->num); | ||
81 | rc = -ETIMEDOUT; | ||
82 | break; | ||
83 | } | ||
84 | } | ||
85 | dprintk(MANTIS_DEBUG, 1, "HIF Write success"); | ||
86 | return rc; | ||
87 | } | ||
88 | |||
89 | |||
90 | int mantis_hif_read_mem(struct mantis_ca *ca, u32 addr) | ||
91 | { | ||
92 | struct mantis_pci *mantis = ca->ca_priv; | ||
93 | u32 hif_addr = 0, data, count = 4; | ||
94 | |||
95 | dprintk(MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF Mem Read", mantis->num); | ||
96 | mutex_lock(&ca->ca_lock); | ||
97 | hif_addr &= ~MANTIS_GPIF_PCMCIAREG; | ||
98 | hif_addr &= ~MANTIS_GPIF_PCMCIAIOM; | ||
99 | hif_addr |= MANTIS_HIF_STATUS; | ||
100 | hif_addr |= addr; | ||
101 | |||
102 | mmwrite(hif_addr, MANTIS_GPIF_BRADDR); | ||
103 | mmwrite(count, MANTIS_GPIF_BRBYTES); | ||
104 | udelay(20); | ||
105 | mmwrite(hif_addr | MANTIS_GPIF_HIFRDWRN, MANTIS_GPIF_ADDR); | ||
106 | |||
107 | if (mantis_hif_sbuf_opdone_wait(ca) != 0) { | ||
108 | dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): GPIF Smart Buffer operation failed", mantis->num); | ||
109 | mutex_unlock(&ca->ca_lock); | ||
110 | return -EREMOTEIO; | ||
111 | } | ||
112 | data = mmread(MANTIS_GPIF_DIN); | ||
113 | mutex_unlock(&ca->ca_lock); | ||
114 | dprintk(MANTIS_DEBUG, 1, "Mem Read: 0x%02x", data); | ||
115 | return (data >> 24) & 0xff; | ||
116 | } | ||
117 | |||
118 | int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data) | ||
119 | { | ||
120 | struct mantis_slot *slot = ca->slot; | ||
121 | struct mantis_pci *mantis = ca->ca_priv; | ||
122 | u32 hif_addr = 0; | ||
123 | |||
124 | dprintk(MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF Mem Write", mantis->num); | ||
125 | mutex_lock(&ca->ca_lock); | ||
126 | hif_addr &= ~MANTIS_GPIF_HIFRDWRN; | ||
127 | hif_addr &= ~MANTIS_GPIF_PCMCIAREG; | ||
128 | hif_addr &= ~MANTIS_GPIF_PCMCIAIOM; | ||
129 | hif_addr |= MANTIS_HIF_STATUS; | ||
130 | hif_addr |= addr; | ||
131 | |||
132 | mmwrite(slot->slave_cfg, MANTIS_GPIF_CFGSLA); /* Slot0 alone for now */ | ||
133 | mmwrite(hif_addr, MANTIS_GPIF_ADDR); | ||
134 | mmwrite(data, MANTIS_GPIF_DOUT); | ||
135 | |||
136 | if (mantis_hif_write_wait(ca) != 0) { | ||
137 | dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num); | ||
138 | mutex_unlock(&ca->ca_lock); | ||
139 | return -EREMOTEIO; | ||
140 | } | ||
141 | dprintk(MANTIS_DEBUG, 1, "Mem Write: (0x%02x to 0x%02x)", data, addr); | ||
142 | mutex_unlock(&ca->ca_lock); | ||
143 | |||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr) | ||
148 | { | ||
149 | struct mantis_pci *mantis = ca->ca_priv; | ||
150 | u32 data, hif_addr = 0; | ||
151 | |||
152 | dprintk(MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF I/O Read", mantis->num); | ||
153 | mutex_lock(&ca->ca_lock); | ||
154 | hif_addr &= ~MANTIS_GPIF_PCMCIAREG; | ||
155 | hif_addr |= MANTIS_GPIF_PCMCIAIOM; | ||
156 | hif_addr |= MANTIS_HIF_STATUS; | ||
157 | hif_addr |= addr; | ||
158 | |||
159 | mmwrite(hif_addr, MANTIS_GPIF_BRADDR); | ||
160 | mmwrite(1, MANTIS_GPIF_BRBYTES); | ||
161 | udelay(20); | ||
162 | mmwrite(hif_addr | MANTIS_GPIF_HIFRDWRN, MANTIS_GPIF_ADDR); | ||
163 | |||
164 | if (mantis_hif_sbuf_opdone_wait(ca) != 0) { | ||
165 | dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num); | ||
166 | mutex_unlock(&ca->ca_lock); | ||
167 | return -EREMOTEIO; | ||
168 | } | ||
169 | data = mmread(MANTIS_GPIF_DIN); | ||
170 | dprintk(MANTIS_DEBUG, 1, "I/O Read: 0x%02x", data); | ||
171 | udelay(50); | ||
172 | mutex_unlock(&ca->ca_lock); | ||
173 | |||
174 | return (u8) data; | ||
175 | } | ||
176 | |||
177 | int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data) | ||
178 | { | ||
179 | struct mantis_pci *mantis = ca->ca_priv; | ||
180 | u32 hif_addr = 0; | ||
181 | |||
182 | dprintk(MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF I/O Write", mantis->num); | ||
183 | mutex_lock(&ca->ca_lock); | ||
184 | hif_addr &= ~MANTIS_GPIF_PCMCIAREG; | ||
185 | hif_addr &= ~MANTIS_GPIF_HIFRDWRN; | ||
186 | hif_addr |= MANTIS_GPIF_PCMCIAIOM; | ||
187 | hif_addr |= MANTIS_HIF_STATUS; | ||
188 | hif_addr |= addr; | ||
189 | |||
190 | mmwrite(hif_addr, MANTIS_GPIF_ADDR); | ||
191 | mmwrite(data, MANTIS_GPIF_DOUT); | ||
192 | |||
193 | if (mantis_hif_write_wait(ca) != 0) { | ||
194 | dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num); | ||
195 | mutex_unlock(&ca->ca_lock); | ||
196 | return -EREMOTEIO; | ||
197 | } | ||
198 | dprintk(MANTIS_DEBUG, 1, "I/O Write: (0x%02x to 0x%02x)", data, addr); | ||
199 | mutex_unlock(&ca->ca_lock); | ||
200 | udelay(50); | ||
201 | |||
202 | return 0; | ||
203 | } | ||
204 | |||
205 | int mantis_hif_init(struct mantis_ca *ca) | ||
206 | { | ||
207 | struct mantis_slot *slot = ca->slot; | ||
208 | struct mantis_pci *mantis = ca->ca_priv; | ||
209 | u32 irqcfg; | ||
210 | |||
211 | slot[0].slave_cfg = 0x70773028; | ||
212 | dprintk(MANTIS_ERROR, 1, "Adapter(%d) Initializing Mantis Host Interface", mantis->num); | ||
213 | |||
214 | mutex_lock(&ca->ca_lock); | ||
215 | irqcfg = mmread(MANTIS_GPIF_IRQCFG); | ||
216 | irqcfg = MANTIS_MASK_BRRDY | | ||
217 | MANTIS_MASK_WRACK | | ||
218 | MANTIS_MASK_EXTIRQ | | ||
219 | MANTIS_MASK_WSTO | | ||
220 | MANTIS_MASK_OTHERR | | ||
221 | MANTIS_MASK_OVFLW; | ||
222 | |||
223 | mmwrite(irqcfg, MANTIS_GPIF_IRQCFG); | ||
224 | mutex_unlock(&ca->ca_lock); | ||
225 | |||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | void mantis_hif_exit(struct mantis_ca *ca) | ||
230 | { | ||
231 | struct mantis_pci *mantis = ca->ca_priv; | ||
232 | u32 irqcfg; | ||
233 | |||
234 | dprintk(MANTIS_ERROR, 1, "Adapter(%d) Exiting Mantis Host Interface", mantis->num); | ||
235 | mutex_lock(&ca->ca_lock); | ||
236 | irqcfg = mmread(MANTIS_GPIF_IRQCFG); | ||
237 | irqcfg &= ~MANTIS_MASK_BRRDY; | ||
238 | mmwrite(irqcfg, MANTIS_GPIF_IRQCFG); | ||
239 | mutex_unlock(&ca->ca_lock); | ||
240 | } | ||
diff --git a/drivers/media/dvb/mantis/mantis_hif.h b/drivers/media/dvb/mantis/mantis_hif.h new file mode 100644 index 000000000000..9094f9ed2362 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_hif.h | |||
@@ -0,0 +1,29 @@ | |||
1 | /* | ||
2 | Mantis PCI bridge driver | ||
3 | |||
4 | Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #ifndef __MANTIS_HIF_H | ||
22 | #define __MANTIS_HIF_H | ||
23 | |||
24 | #define MANTIS_HIF_MEMRD 1 | ||
25 | #define MANTIS_HIF_MEMWR 2 | ||
26 | #define MANTIS_HIF_IOMRD 3 | ||
27 | #define MANTIS_HIF_IOMWR 4 | ||
28 | |||
29 | #endif /* __MANTIS_HIF_H */ | ||
diff --git a/drivers/media/dvb/mantis/mantis_i2c.c b/drivers/media/dvb/mantis/mantis_i2c.c new file mode 100644 index 000000000000..7870bcf9689a --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_i2c.c | |||
@@ -0,0 +1,267 @@ | |||
1 | /* | ||
2 | Mantis PCI bridge driver | ||
3 | |||
4 | Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include <asm/io.h> | ||
22 | #include <linux/ioport.h> | ||
23 | #include <linux/pci.h> | ||
24 | #include <linux/i2c.h> | ||
25 | |||
26 | #include "dmxdev.h" | ||
27 | #include "dvbdev.h" | ||
28 | #include "dvb_demux.h" | ||
29 | #include "dvb_frontend.h" | ||
30 | #include "dvb_net.h" | ||
31 | |||
32 | #include "mantis_common.h" | ||
33 | #include "mantis_reg.h" | ||
34 | #include "mantis_i2c.h" | ||
35 | |||
36 | #define TRIALS 10000 | ||
37 | |||
38 | static int mantis_i2c_read(struct mantis_pci *mantis, const struct i2c_msg *msg) | ||
39 | { | ||
40 | u32 rxd, i, stat, trials; | ||
41 | |||
42 | dprintk(MANTIS_INFO, 0, " %s: Address=[0x%02x] <R>[ ", | ||
43 | __func__, msg->addr); | ||
44 | |||
45 | for (i = 0; i < msg->len; i++) { | ||
46 | rxd = (msg->addr << 25) | (1 << 24) | ||
47 | | MANTIS_I2C_RATE_3 | ||
48 | | MANTIS_I2C_STOP | ||
49 | | MANTIS_I2C_PGMODE; | ||
50 | |||
51 | if (i == (msg->len - 1)) | ||
52 | rxd &= ~MANTIS_I2C_STOP; | ||
53 | |||
54 | mmwrite(MANTIS_INT_I2CDONE, MANTIS_INT_STAT); | ||
55 | mmwrite(rxd, MANTIS_I2CDATA_CTL); | ||
56 | |||
57 | /* wait for xfer completion */ | ||
58 | for (trials = 0; trials < TRIALS; trials++) { | ||
59 | stat = mmread(MANTIS_INT_STAT); | ||
60 | if (stat & MANTIS_INT_I2CDONE) | ||
61 | break; | ||
62 | } | ||
63 | |||
64 | dprintk(MANTIS_TMG, 0, "I2CDONE: trials=%d\n", trials); | ||
65 | |||
66 | /* wait for xfer completion */ | ||
67 | for (trials = 0; trials < TRIALS; trials++) { | ||
68 | stat = mmread(MANTIS_INT_STAT); | ||
69 | if (stat & MANTIS_INT_I2CRACK) | ||
70 | break; | ||
71 | } | ||
72 | |||
73 | dprintk(MANTIS_TMG, 0, "I2CRACK: trials=%d\n", trials); | ||
74 | |||
75 | rxd = mmread(MANTIS_I2CDATA_CTL); | ||
76 | msg->buf[i] = (u8)((rxd >> 8) & 0xFF); | ||
77 | dprintk(MANTIS_INFO, 0, "%02x ", msg->buf[i]); | ||
78 | } | ||
79 | dprintk(MANTIS_INFO, 0, "]\n"); | ||
80 | |||
81 | return 0; | ||
82 | } | ||
83 | |||
84 | static int mantis_i2c_write(struct mantis_pci *mantis, const struct i2c_msg *msg) | ||
85 | { | ||
86 | int i; | ||
87 | u32 txd = 0, stat, trials; | ||
88 | |||
89 | dprintk(MANTIS_INFO, 0, " %s: Address=[0x%02x] <W>[ ", | ||
90 | __func__, msg->addr); | ||
91 | |||
92 | for (i = 0; i < msg->len; i++) { | ||
93 | dprintk(MANTIS_INFO, 0, "%02x ", msg->buf[i]); | ||
94 | txd = (msg->addr << 25) | (msg->buf[i] << 8) | ||
95 | | MANTIS_I2C_RATE_3 | ||
96 | | MANTIS_I2C_STOP | ||
97 | | MANTIS_I2C_PGMODE; | ||
98 | |||
99 | if (i == (msg->len - 1)) | ||
100 | txd &= ~MANTIS_I2C_STOP; | ||
101 | |||
102 | mmwrite(MANTIS_INT_I2CDONE, MANTIS_INT_STAT); | ||
103 | mmwrite(txd, MANTIS_I2CDATA_CTL); | ||
104 | |||
105 | /* wait for xfer completion */ | ||
106 | for (trials = 0; trials < TRIALS; trials++) { | ||
107 | stat = mmread(MANTIS_INT_STAT); | ||
108 | if (stat & MANTIS_INT_I2CDONE) | ||
109 | break; | ||
110 | } | ||
111 | |||
112 | dprintk(MANTIS_TMG, 0, "I2CDONE: trials=%d\n", trials); | ||
113 | |||
114 | /* wait for xfer completion */ | ||
115 | for (trials = 0; trials < TRIALS; trials++) { | ||
116 | stat = mmread(MANTIS_INT_STAT); | ||
117 | if (stat & MANTIS_INT_I2CRACK) | ||
118 | break; | ||
119 | } | ||
120 | |||
121 | dprintk(MANTIS_TMG, 0, "I2CRACK: trials=%d\n", trials); | ||
122 | } | ||
123 | dprintk(MANTIS_INFO, 0, "]\n"); | ||
124 | |||
125 | return 0; | ||
126 | } | ||
127 | |||
128 | static int mantis_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) | ||
129 | { | ||
130 | int ret = 0, i = 0, trials; | ||
131 | u32 stat, data, txd; | ||
132 | struct mantis_pci *mantis; | ||
133 | struct mantis_hwconfig *config; | ||
134 | |||
135 | mantis = i2c_get_adapdata(adapter); | ||
136 | BUG_ON(!mantis); | ||
137 | config = mantis->hwconfig; | ||
138 | BUG_ON(!config); | ||
139 | |||
140 | dprintk(MANTIS_DEBUG, 1, "Messages:%d", num); | ||
141 | mutex_lock(&mantis->i2c_lock); | ||
142 | |||
143 | while (i < num) { | ||
144 | /* Byte MODE */ | ||
145 | if ((config->i2c_mode & MANTIS_BYTE_MODE) && | ||
146 | ((i + 1) < num) && | ||
147 | (msgs[i].len < 2) && | ||
148 | (msgs[i + 1].len < 2) && | ||
149 | (msgs[i + 1].flags & I2C_M_RD)) { | ||
150 | |||
151 | dprintk(MANTIS_DEBUG, 0, " Byte MODE:\n"); | ||
152 | |||
153 | /* Read operation */ | ||
154 | txd = msgs[i].addr << 25 | (0x1 << 24) | ||
155 | | (msgs[i].buf[0] << 16) | ||
156 | | MANTIS_I2C_RATE_3; | ||
157 | |||
158 | mmwrite(txd, MANTIS_I2CDATA_CTL); | ||
159 | /* wait for xfer completion */ | ||
160 | for (trials = 0; trials < TRIALS; trials++) { | ||
161 | stat = mmread(MANTIS_INT_STAT); | ||
162 | if (stat & MANTIS_INT_I2CDONE) | ||
163 | break; | ||
164 | } | ||
165 | |||
166 | /* check for xfer completion */ | ||
167 | if (stat & MANTIS_INT_I2CDONE) { | ||
168 | /* check xfer was acknowledged */ | ||
169 | if (stat & MANTIS_INT_I2CRACK) { | ||
170 | data = mmread(MANTIS_I2CDATA_CTL); | ||
171 | msgs[i + 1].buf[0] = (data >> 8) & 0xff; | ||
172 | dprintk(MANTIS_DEBUG, 0, " Byte <%d> RXD=0x%02x [%02x]\n", 0x0, data, msgs[i + 1].buf[0]); | ||
173 | } else { | ||
174 | /* I/O error */ | ||
175 | dprintk(MANTIS_ERROR, 1, " I/O error, LINE:%d", __LINE__); | ||
176 | ret = -EIO; | ||
177 | break; | ||
178 | } | ||
179 | } else { | ||
180 | /* I/O error */ | ||
181 | dprintk(MANTIS_ERROR, 1, " I/O error, LINE:%d", __LINE__); | ||
182 | ret = -EIO; | ||
183 | break; | ||
184 | } | ||
185 | i += 2; /* Write/Read operation in one go */ | ||
186 | } | ||
187 | |||
188 | if (i < num) { | ||
189 | if (msgs[i].flags & I2C_M_RD) | ||
190 | ret = mantis_i2c_read(mantis, &msgs[i]); | ||
191 | else | ||
192 | ret = mantis_i2c_write(mantis, &msgs[i]); | ||
193 | |||
194 | i++; | ||
195 | if (ret < 0) | ||
196 | goto bail_out; | ||
197 | } | ||
198 | |||
199 | } | ||
200 | |||
201 | mutex_unlock(&mantis->i2c_lock); | ||
202 | |||
203 | return num; | ||
204 | |||
205 | bail_out: | ||
206 | mutex_unlock(&mantis->i2c_lock); | ||
207 | return ret; | ||
208 | } | ||
209 | |||
210 | static u32 mantis_i2c_func(struct i2c_adapter *adapter) | ||
211 | { | ||
212 | return I2C_FUNC_SMBUS_EMUL; | ||
213 | } | ||
214 | |||
215 | static struct i2c_algorithm mantis_algo = { | ||
216 | .master_xfer = mantis_i2c_xfer, | ||
217 | .functionality = mantis_i2c_func, | ||
218 | }; | ||
219 | |||
220 | int __devinit mantis_i2c_init(struct mantis_pci *mantis) | ||
221 | { | ||
222 | u32 intstat, intmask; | ||
223 | struct i2c_adapter *i2c_adapter = &mantis->adapter; | ||
224 | struct pci_dev *pdev = mantis->pdev; | ||
225 | |||
226 | init_waitqueue_head(&mantis->i2c_wq); | ||
227 | mutex_init(&mantis->i2c_lock); | ||
228 | strncpy(i2c_adapter->name, "Mantis I2C", sizeof(i2c_adapter->name)); | ||
229 | i2c_set_adapdata(i2c_adapter, mantis); | ||
230 | |||
231 | i2c_adapter->owner = THIS_MODULE; | ||
232 | i2c_adapter->class = I2C_CLASS_TV_DIGITAL; | ||
233 | i2c_adapter->algo = &mantis_algo; | ||
234 | i2c_adapter->algo_data = NULL; | ||
235 | i2c_adapter->timeout = 500; | ||
236 | i2c_adapter->retries = 3; | ||
237 | i2c_adapter->dev.parent = &pdev->dev; | ||
238 | |||
239 | mantis->i2c_rc = i2c_add_adapter(i2c_adapter); | ||
240 | if (mantis->i2c_rc < 0) | ||
241 | return mantis->i2c_rc; | ||
242 | |||
243 | dprintk(MANTIS_DEBUG, 1, "Initializing I2C .."); | ||
244 | |||
245 | intstat = mmread(MANTIS_INT_STAT); | ||
246 | intmask = mmread(MANTIS_INT_MASK); | ||
247 | mmwrite(intstat, MANTIS_INT_STAT); | ||
248 | dprintk(MANTIS_DEBUG, 1, "Disabling I2C interrupt"); | ||
249 | intmask = mmread(MANTIS_INT_MASK); | ||
250 | mmwrite((intmask & ~MANTIS_INT_I2CDONE), MANTIS_INT_MASK); | ||
251 | |||
252 | return 0; | ||
253 | } | ||
254 | EXPORT_SYMBOL_GPL(mantis_i2c_init); | ||
255 | |||
256 | int mantis_i2c_exit(struct mantis_pci *mantis) | ||
257 | { | ||
258 | u32 intmask; | ||
259 | |||
260 | dprintk(MANTIS_DEBUG, 1, "Disabling I2C interrupt"); | ||
261 | intmask = mmread(MANTIS_INT_MASK); | ||
262 | mmwrite((intmask & ~MANTIS_INT_I2CDONE), MANTIS_INT_MASK); | ||
263 | |||
264 | dprintk(MANTIS_DEBUG, 1, "Removing I2C adapter"); | ||
265 | return i2c_del_adapter(&mantis->adapter); | ||
266 | } | ||
267 | EXPORT_SYMBOL_GPL(mantis_i2c_exit); | ||
diff --git a/drivers/media/dvb/mantis/mantis_i2c.h b/drivers/media/dvb/mantis/mantis_i2c.h new file mode 100644 index 000000000000..1342df2faed8 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_i2c.h | |||
@@ -0,0 +1,30 @@ | |||
1 | /* | ||
2 | Mantis PCI bridge driver | ||
3 | |||
4 | Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #ifndef __MANTIS_I2C_H | ||
22 | #define __MANTIS_I2C_H | ||
23 | |||
24 | #define I2C_STOP (1 << 0) | ||
25 | #define I2C_READ (1 << 1) | ||
26 | |||
27 | extern int mantis_i2c_init(struct mantis_pci *mantis); | ||
28 | extern int mantis_i2c_exit(struct mantis_pci *mantis); | ||
29 | |||
30 | #endif /* __MANTIS_I2C_H */ | ||
diff --git a/drivers/media/dvb/mantis/mantis_input.c b/drivers/media/dvb/mantis/mantis_input.c new file mode 100644 index 000000000000..6a9df779441f --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_input.c | |||
@@ -0,0 +1,148 @@ | |||
1 | /* | ||
2 | Mantis PCI bridge driver | ||
3 | |||
4 | Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/input.h> | ||
22 | #include <media/ir-common.h> | ||
23 | #include <linux/pci.h> | ||
24 | |||
25 | #include "dmxdev.h" | ||
26 | #include "dvbdev.h" | ||
27 | #include "dvb_demux.h" | ||
28 | #include "dvb_frontend.h" | ||
29 | #include "dvb_net.h" | ||
30 | |||
31 | #include "mantis_common.h" | ||
32 | #include "mantis_reg.h" | ||
33 | #include "mantis_uart.h" | ||
34 | |||
35 | static struct ir_scancode mantis_ir_table[] = { | ||
36 | { 0x29, KEY_POWER }, | ||
37 | { 0x28, KEY_FAVORITES }, | ||
38 | { 0x30, KEY_TEXT }, | ||
39 | { 0x17, KEY_INFO }, /* Preview */ | ||
40 | { 0x23, KEY_EPG }, | ||
41 | { 0x3b, KEY_F22 }, /* Record List */ | ||
42 | { 0x3c, KEY_1 }, | ||
43 | { 0x3e, KEY_2 }, | ||
44 | { 0x39, KEY_3 }, | ||
45 | { 0x36, KEY_4 }, | ||
46 | { 0x22, KEY_5 }, | ||
47 | { 0x20, KEY_6 }, | ||
48 | { 0x32, KEY_7 }, | ||
49 | { 0x26, KEY_8 }, | ||
50 | { 0x24, KEY_9 }, | ||
51 | { 0x2a, KEY_0 }, | ||
52 | |||
53 | { 0x33, KEY_CANCEL }, | ||
54 | { 0x2c, KEY_BACK }, | ||
55 | { 0x15, KEY_CLEAR }, | ||
56 | { 0x3f, KEY_TAB }, | ||
57 | { 0x10, KEY_ENTER }, | ||
58 | { 0x14, KEY_UP }, | ||
59 | { 0x0d, KEY_RIGHT }, | ||
60 | { 0x0e, KEY_DOWN }, | ||
61 | { 0x11, KEY_LEFT }, | ||
62 | |||
63 | { 0x21, KEY_VOLUMEUP }, | ||
64 | { 0x35, KEY_VOLUMEDOWN }, | ||
65 | { 0x3d, KEY_CHANNELDOWN }, | ||
66 | { 0x3a, KEY_CHANNELUP }, | ||
67 | { 0x2e, KEY_RECORD }, | ||
68 | { 0x2b, KEY_PLAY }, | ||
69 | { 0x13, KEY_PAUSE }, | ||
70 | { 0x25, KEY_STOP }, | ||
71 | |||
72 | { 0x1f, KEY_REWIND }, | ||
73 | { 0x2d, KEY_FASTFORWARD }, | ||
74 | { 0x1e, KEY_PREVIOUS }, /* Replay |< */ | ||
75 | { 0x1d, KEY_NEXT }, /* Skip >| */ | ||
76 | |||
77 | { 0x0b, KEY_CAMERA }, /* Capture */ | ||
78 | { 0x0f, KEY_LANGUAGE }, /* SAP */ | ||
79 | { 0x18, KEY_MODE }, /* PIP */ | ||
80 | { 0x12, KEY_ZOOM }, /* Full screen */ | ||
81 | { 0x1c, KEY_SUBTITLE }, | ||
82 | { 0x2f, KEY_MUTE }, | ||
83 | { 0x16, KEY_F20 }, /* L/R */ | ||
84 | { 0x38, KEY_F21 }, /* Hibernate */ | ||
85 | |||
86 | { 0x37, KEY_SWITCHVIDEOMODE }, /* A/V */ | ||
87 | { 0x31, KEY_AGAIN }, /* Recall */ | ||
88 | { 0x1a, KEY_KPPLUS }, /* Zoom+ */ | ||
89 | { 0x19, KEY_KPMINUS }, /* Zoom- */ | ||
90 | { 0x27, KEY_RED }, | ||
91 | { 0x0C, KEY_GREEN }, | ||
92 | { 0x01, KEY_YELLOW }, | ||
93 | { 0x00, KEY_BLUE }, | ||
94 | }; | ||
95 | |||
96 | struct ir_scancode_table ir_mantis = { | ||
97 | .scan = mantis_ir_table, | ||
98 | .size = ARRAY_SIZE(mantis_ir_table), | ||
99 | }; | ||
100 | EXPORT_SYMBOL_GPL(ir_mantis); | ||
101 | |||
102 | int mantis_input_init(struct mantis_pci *mantis) | ||
103 | { | ||
104 | struct input_dev *rc; | ||
105 | struct ir_input_state rc_state; | ||
106 | char name[80], dev[80]; | ||
107 | int err; | ||
108 | |||
109 | rc = input_allocate_device(); | ||
110 | if (!rc) { | ||
111 | dprintk(MANTIS_ERROR, 1, "Input device allocate failed"); | ||
112 | return -ENOMEM; | ||
113 | } | ||
114 | |||
115 | sprintf(name, "Mantis %s IR receiver", mantis->hwconfig->model_name); | ||
116 | sprintf(dev, "pci-%s/ir0", pci_name(mantis->pdev)); | ||
117 | |||
118 | rc->name = name; | ||
119 | rc->phys = dev; | ||
120 | |||
121 | ir_input_init(rc, &rc_state, IR_TYPE_OTHER); | ||
122 | |||
123 | rc->id.bustype = BUS_PCI; | ||
124 | rc->id.vendor = mantis->vendor_id; | ||
125 | rc->id.product = mantis->device_id; | ||
126 | rc->id.version = 1; | ||
127 | rc->dev = mantis->pdev->dev; | ||
128 | |||
129 | err = ir_input_register(rc, &ir_mantis); | ||
130 | if (err) { | ||
131 | dprintk(MANTIS_ERROR, 1, "IR device registration failed, ret = %d", err); | ||
132 | input_free_device(rc); | ||
133 | return -ENODEV; | ||
134 | } | ||
135 | |||
136 | mantis->rc = rc; | ||
137 | |||
138 | return 0; | ||
139 | } | ||
140 | |||
141 | int mantis_exit(struct mantis_pci *mantis) | ||
142 | { | ||
143 | struct input_dev *rc = mantis->rc; | ||
144 | |||
145 | ir_input_unregister(rc); | ||
146 | |||
147 | return 0; | ||
148 | } | ||
diff --git a/drivers/media/dvb/mantis/mantis_ioc.c b/drivers/media/dvb/mantis/mantis_ioc.c new file mode 100644 index 000000000000..de148ded52d8 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_ioc.c | |||
@@ -0,0 +1,130 @@ | |||
1 | /* | ||
2 | Mantis PCI bridge driver | ||
3 | |||
4 | Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/i2c.h> | ||
23 | |||
24 | #include <linux/signal.h> | ||
25 | #include <linux/sched.h> | ||
26 | #include <linux/interrupt.h> | ||
27 | |||
28 | #include "dmxdev.h" | ||
29 | #include "dvbdev.h" | ||
30 | #include "dvb_demux.h" | ||
31 | #include "dvb_frontend.h" | ||
32 | #include "dvb_net.h" | ||
33 | |||
34 | #include "mantis_common.h" | ||
35 | #include "mantis_reg.h" | ||
36 | #include "mantis_ioc.h" | ||
37 | |||
38 | static int read_eeprom_bytes(struct mantis_pci *mantis, u8 reg, u8 *data, u8 length) | ||
39 | { | ||
40 | struct i2c_adapter *adapter = &mantis->adapter; | ||
41 | int err; | ||
42 | u8 buf = reg; | ||
43 | |||
44 | struct i2c_msg msg[] = { | ||
45 | { .addr = 0x50, .flags = 0, .buf = &buf, .len = 1 }, | ||
46 | { .addr = 0x50, .flags = I2C_M_RD, .buf = data, .len = length }, | ||
47 | }; | ||
48 | |||
49 | err = i2c_transfer(adapter, msg, 2); | ||
50 | if (err < 0) { | ||
51 | dprintk(MANTIS_ERROR, 1, "ERROR: i2c read: < err=%i d0=0x%02x d1=0x%02x >", | ||
52 | err, data[0], data[1]); | ||
53 | |||
54 | return err; | ||
55 | } | ||
56 | |||
57 | return 0; | ||
58 | } | ||
59 | int mantis_get_mac(struct mantis_pci *mantis) | ||
60 | { | ||
61 | int err; | ||
62 | u8 mac_addr[6] = {0}; | ||
63 | |||
64 | err = read_eeprom_bytes(mantis, 0x08, mac_addr, 6); | ||
65 | if (err < 0) { | ||
66 | dprintk(MANTIS_ERROR, 1, "ERROR: Mantis EEPROM read error <%d>", err); | ||
67 | |||
68 | return err; | ||
69 | } | ||
70 | |||
71 | dprintk(MANTIS_ERROR, 0, | ||
72 | " MAC Address=[%02x:%02x:%02x:%02x:%02x:%02x]\n", | ||
73 | mac_addr[0], | ||
74 | mac_addr[1], | ||
75 | mac_addr[2], | ||
76 | mac_addr[3], | ||
77 | mac_addr[4], | ||
78 | mac_addr[5]); | ||
79 | |||
80 | return 0; | ||
81 | } | ||
82 | EXPORT_SYMBOL_GPL(mantis_get_mac); | ||
83 | |||
84 | /* Turn the given bit on or off. */ | ||
85 | void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value) | ||
86 | { | ||
87 | u32 cur; | ||
88 | |||
89 | dprintk(MANTIS_DEBUG, 1, "Set Bit <%d> to <%d>", bitpos, value); | ||
90 | cur = mmread(MANTIS_GPIF_ADDR); | ||
91 | if (value) | ||
92 | mantis->gpio_status = cur | (1 << bitpos); | ||
93 | else | ||
94 | mantis->gpio_status = cur & (~(1 << bitpos)); | ||
95 | |||
96 | dprintk(MANTIS_DEBUG, 1, "GPIO Value <%02x>", mantis->gpio_status); | ||
97 | mmwrite(mantis->gpio_status, MANTIS_GPIF_ADDR); | ||
98 | mmwrite(0x00, MANTIS_GPIF_DOUT); | ||
99 | } | ||
100 | EXPORT_SYMBOL_GPL(gpio_set_bits); | ||
101 | |||
102 | int mantis_stream_control(struct mantis_pci *mantis, enum mantis_stream_control stream_ctl) | ||
103 | { | ||
104 | u32 reg; | ||
105 | |||
106 | reg = mmread(MANTIS_CONTROL); | ||
107 | switch (stream_ctl) { | ||
108 | case STREAM_TO_HIF: | ||
109 | dprintk(MANTIS_DEBUG, 1, "Set stream to HIF"); | ||
110 | reg &= 0xff - MANTIS_BYPASS; | ||
111 | mmwrite(reg, MANTIS_CONTROL); | ||
112 | reg |= MANTIS_BYPASS; | ||
113 | mmwrite(reg, MANTIS_CONTROL); | ||
114 | break; | ||
115 | |||
116 | case STREAM_TO_CAM: | ||
117 | dprintk(MANTIS_DEBUG, 1, "Set stream to CAM"); | ||
118 | reg |= MANTIS_BYPASS; | ||
119 | mmwrite(reg, MANTIS_CONTROL); | ||
120 | reg &= 0xff - MANTIS_BYPASS; | ||
121 | mmwrite(reg, MANTIS_CONTROL); | ||
122 | break; | ||
123 | default: | ||
124 | dprintk(MANTIS_ERROR, 1, "Unknown MODE <%02x>", stream_ctl); | ||
125 | return -1; | ||
126 | } | ||
127 | |||
128 | return 0; | ||
129 | } | ||
130 | EXPORT_SYMBOL_GPL(mantis_stream_control); | ||
diff --git a/drivers/media/dvb/mantis/mantis_ioc.h b/drivers/media/dvb/mantis/mantis_ioc.h new file mode 100644 index 000000000000..188fe5a81614 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_ioc.h | |||
@@ -0,0 +1,51 @@ | |||
1 | /* | ||
2 | Mantis PCI bridge driver | ||
3 | |||
4 | Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #ifndef __MANTIS_IOC_H | ||
22 | #define __MANTIS_IOC_H | ||
23 | |||
24 | #define GPIF_A00 0x00 | ||
25 | #define GPIF_A01 0x01 | ||
26 | #define GPIF_A02 0x02 | ||
27 | #define GPIF_A03 0x03 | ||
28 | #define GPIF_A04 0x04 | ||
29 | #define GPIF_A05 0x05 | ||
30 | #define GPIF_A06 0x06 | ||
31 | #define GPIF_A07 0x07 | ||
32 | #define GPIF_A08 0x08 | ||
33 | #define GPIF_A09 0x09 | ||
34 | #define GPIF_A10 0x0a | ||
35 | #define GPIF_A11 0x0b | ||
36 | |||
37 | #define GPIF_A12 0x0c | ||
38 | #define GPIF_A13 0x0d | ||
39 | #define GPIF_A14 0x0e | ||
40 | |||
41 | enum mantis_stream_control { | ||
42 | STREAM_TO_HIF = 0, | ||
43 | STREAM_TO_CAM | ||
44 | }; | ||
45 | |||
46 | extern int mantis_get_mac(struct mantis_pci *mantis); | ||
47 | extern void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value); | ||
48 | |||
49 | extern int mantis_stream_control(struct mantis_pci *mantis, enum mantis_stream_control stream_ctl); | ||
50 | |||
51 | #endif /* __MANTIS_IOC_H */ | ||
diff --git a/drivers/media/dvb/mantis/mantis_link.h b/drivers/media/dvb/mantis/mantis_link.h new file mode 100644 index 000000000000..2a814774a001 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_link.h | |||
@@ -0,0 +1,83 @@ | |||
1 | /* | ||
2 | Mantis PCI bridge driver | ||
3 | |||
4 | Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #ifndef __MANTIS_LINK_H | ||
22 | #define __MANTIS_LINK_H | ||
23 | |||
24 | #include <linux/mutex.h> | ||
25 | #include <linux/workqueue.h> | ||
26 | #include "dvb_ca_en50221.h" | ||
27 | |||
28 | enum mantis_sbuf_status { | ||
29 | MANTIS_SBUF_DATA_AVAIL = 1, | ||
30 | MANTIS_SBUF_DATA_EMPTY = 2, | ||
31 | MANTIS_SBUF_DATA_OVFLW = 3 | ||
32 | }; | ||
33 | |||
34 | struct mantis_slot { | ||
35 | u32 timeout; | ||
36 | u32 slave_cfg; | ||
37 | u32 bar; | ||
38 | }; | ||
39 | |||
40 | /* Physical layer */ | ||
41 | enum mantis_slot_state { | ||
42 | MODULE_INSERTED = 3, | ||
43 | MODULE_XTRACTED = 4 | ||
44 | }; | ||
45 | |||
46 | struct mantis_ca { | ||
47 | struct mantis_slot slot[4]; | ||
48 | |||
49 | struct work_struct hif_evm_work; | ||
50 | |||
51 | u32 hif_event; | ||
52 | wait_queue_head_t hif_opdone_wq; | ||
53 | wait_queue_head_t hif_brrdyw_wq; | ||
54 | wait_queue_head_t hif_data_wq; | ||
55 | wait_queue_head_t hif_write_wq; /* HIF Write op */ | ||
56 | |||
57 | enum mantis_sbuf_status sbuf_status; | ||
58 | |||
59 | enum mantis_slot_state slot_state; | ||
60 | |||
61 | void *ca_priv; | ||
62 | |||
63 | struct dvb_ca_en50221 en50221; | ||
64 | struct mutex ca_lock; | ||
65 | }; | ||
66 | |||
67 | /* CA */ | ||
68 | extern void mantis_event_cam_plugin(struct mantis_ca *ca); | ||
69 | extern void mantis_event_cam_unplug(struct mantis_ca *ca); | ||
70 | extern int mantis_pcmcia_init(struct mantis_ca *ca); | ||
71 | extern void mantis_pcmcia_exit(struct mantis_ca *ca); | ||
72 | extern int mantis_evmgr_init(struct mantis_ca *ca); | ||
73 | extern void mantis_evmgr_exit(struct mantis_ca *ca); | ||
74 | |||
75 | /* HIF */ | ||
76 | extern int mantis_hif_init(struct mantis_ca *ca); | ||
77 | extern void mantis_hif_exit(struct mantis_ca *ca); | ||
78 | extern int mantis_hif_read_mem(struct mantis_ca *ca, u32 addr); | ||
79 | extern int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data); | ||
80 | extern int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr); | ||
81 | extern int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data); | ||
82 | |||
83 | #endif /* __MANTIS_LINK_H */ | ||
diff --git a/drivers/media/dvb/mantis/mantis_pci.c b/drivers/media/dvb/mantis/mantis_pci.c new file mode 100644 index 000000000000..6c7534af6b44 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_pci.c | |||
@@ -0,0 +1,177 @@ | |||
1 | /* | ||
2 | Mantis PCI bridge driver | ||
3 | |||
4 | Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/module.h> | ||
22 | #include <linux/moduleparam.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <asm/io.h> | ||
25 | #include <asm/pgtable.h> | ||
26 | #include <asm/page.h> | ||
27 | #include <linux/kmod.h> | ||
28 | #include <linux/vmalloc.h> | ||
29 | #include <linux/init.h> | ||
30 | #include <linux/device.h> | ||
31 | #include <linux/pci.h> | ||
32 | |||
33 | #include <asm/irq.h> | ||
34 | #include <linux/signal.h> | ||
35 | #include <linux/sched.h> | ||
36 | #include <linux/interrupt.h> | ||
37 | |||
38 | #include "dmxdev.h" | ||
39 | #include "dvbdev.h" | ||
40 | #include "dvb_demux.h" | ||
41 | #include "dvb_frontend.h" | ||
42 | #include "dvb_net.h" | ||
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" | ||
50 | #include "mantis_reg.h" | ||
51 | #include "mantis_pci.h" | ||
52 | |||
53 | #define DRIVER_NAME "Mantis Core" | ||
54 | |||
55 | int __devinit mantis_pci_init(struct mantis_pci *mantis) | ||
56 | { | ||
57 | u8 revision, latency; | ||
58 | struct mantis_hwconfig *config = mantis->hwconfig; | ||
59 | struct pci_dev *pdev = mantis->pdev; | ||
60 | int err, ret = 0; | ||
61 | |||
62 | dprintk(MANTIS_ERROR, 0, "found a %s PCI %s device on (%02x:%02x.%x),\n", | ||
63 | config->model_name, | ||
64 | config->dev_type, | ||
65 | mantis->pdev->bus->number, | ||
66 | PCI_SLOT(mantis->pdev->devfn), | ||
67 | PCI_FUNC(mantis->pdev->devfn)); | ||
68 | |||
69 | err = pci_enable_device(pdev); | ||
70 | if (err != 0) { | ||
71 | ret = -ENODEV; | ||
72 | dprintk(MANTIS_ERROR, 1, "ERROR: PCI enable failed <%i>", err); | ||
73 | goto fail0; | ||
74 | } | ||
75 | |||
76 | err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); | ||
77 | if (err != 0) { | ||
78 | dprintk(MANTIS_ERROR, 1, "ERROR: Unable to obtain 32 bit DMA <%i>", err); | ||
79 | ret = -ENOMEM; | ||
80 | goto fail1; | ||
81 | } | ||
82 | |||
83 | pci_set_master(pdev); | ||
84 | |||
85 | if (!request_mem_region(pci_resource_start(pdev, 0), | ||
86 | pci_resource_len(pdev, 0), | ||
87 | DRIVER_NAME)) { | ||
88 | |||
89 | dprintk(MANTIS_ERROR, 1, "ERROR: BAR0 Request failed !"); | ||
90 | ret = -ENODEV; | ||
91 | goto fail1; | ||
92 | } | ||
93 | |||
94 | mantis->mmio = ioremap(pci_resource_start(pdev, 0), | ||
95 | pci_resource_len(pdev, 0)); | ||
96 | |||
97 | if (!mantis->mmio) { | ||
98 | dprintk(MANTIS_ERROR, 1, "ERROR: BAR0 remap failed !"); | ||
99 | ret = -ENODEV; | ||
100 | goto fail2; | ||
101 | } | ||
102 | |||
103 | pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency); | ||
104 | pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); | ||
105 | mantis->latency = latency; | ||
106 | mantis->revision = revision; | ||
107 | |||
108 | dprintk(MANTIS_ERROR, 0, " Mantis Rev %d [%04x:%04x], ", | ||
109 | mantis->revision, | ||
110 | mantis->pdev->subsystem_vendor, | ||
111 | mantis->pdev->subsystem_device); | ||
112 | |||
113 | dprintk(MANTIS_ERROR, 0, | ||
114 | "irq: %d, latency: %d\n memory: 0x%lx, mmio: 0x%p\n", | ||
115 | mantis->pdev->irq, | ||
116 | mantis->latency, | ||
117 | mantis->mantis_addr, | ||
118 | mantis->mmio); | ||
119 | |||
120 | err = request_irq(pdev->irq, | ||
121 | config->irq_handler, | ||
122 | IRQF_SHARED, | ||
123 | DRIVER_NAME, | ||
124 | mantis); | ||
125 | |||
126 | if (err != 0) { | ||
127 | |||
128 | dprintk(MANTIS_ERROR, 1, "ERROR: IRQ registration failed ! <%d>", err); | ||
129 | ret = -ENODEV; | ||
130 | goto fail3; | ||
131 | } | ||
132 | |||
133 | pci_set_drvdata(pdev, mantis); | ||
134 | return ret; | ||
135 | |||
136 | /* Error conditions */ | ||
137 | fail3: | ||
138 | dprintk(MANTIS_ERROR, 1, "ERROR: <%d> I/O unmap", ret); | ||
139 | if (mantis->mmio) | ||
140 | iounmap(mantis->mmio); | ||
141 | |||
142 | fail2: | ||
143 | dprintk(MANTIS_ERROR, 1, "ERROR: <%d> releasing regions", ret); | ||
144 | release_mem_region(pci_resource_start(pdev, 0), | ||
145 | pci_resource_len(pdev, 0)); | ||
146 | |||
147 | fail1: | ||
148 | dprintk(MANTIS_ERROR, 1, "ERROR: <%d> disabling device", ret); | ||
149 | pci_disable_device(pdev); | ||
150 | |||
151 | fail0: | ||
152 | dprintk(MANTIS_ERROR, 1, "ERROR: <%d> exiting", ret); | ||
153 | pci_set_drvdata(pdev, NULL); | ||
154 | return ret; | ||
155 | } | ||
156 | EXPORT_SYMBOL_GPL(mantis_pci_init); | ||
157 | |||
158 | void mantis_pci_exit(struct mantis_pci *mantis) | ||
159 | { | ||
160 | struct pci_dev *pdev = mantis->pdev; | ||
161 | |||
162 | dprintk(MANTIS_NOTICE, 1, " mem: 0x%p", mantis->mmio); | ||
163 | free_irq(pdev->irq, mantis); | ||
164 | if (mantis->mmio) { | ||
165 | iounmap(mantis->mmio); | ||
166 | release_mem_region(pci_resource_start(pdev, 0), | ||
167 | pci_resource_len(pdev, 0)); | ||
168 | } | ||
169 | |||
170 | pci_disable_device(pdev); | ||
171 | pci_set_drvdata(pdev, NULL); | ||
172 | } | ||
173 | EXPORT_SYMBOL_GPL(mantis_pci_exit); | ||
174 | |||
175 | MODULE_DESCRIPTION("Mantis PCI DTV bridge driver"); | ||
176 | MODULE_AUTHOR("Manu Abraham"); | ||
177 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/mantis/mantis_pci.h b/drivers/media/dvb/mantis/mantis_pci.h new file mode 100644 index 000000000000..65f004519086 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_pci.h | |||
@@ -0,0 +1,27 @@ | |||
1 | /* | ||
2 | Mantis PCI bridge driver | ||
3 | |||
4 | Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #ifndef __MANTIS_PCI_H | ||
22 | #define __MANTIS_PCI_H | ||
23 | |||
24 | extern int mantis_pci_init(struct mantis_pci *mantis); | ||
25 | extern void mantis_pci_exit(struct mantis_pci *mantis); | ||
26 | |||
27 | #endif /* __MANTIS_PCI_H */ | ||
diff --git a/drivers/media/dvb/mantis/mantis_pcmcia.c b/drivers/media/dvb/mantis/mantis_pcmcia.c new file mode 100644 index 000000000000..5cb545b913f6 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_pcmcia.c | |||
@@ -0,0 +1,120 @@ | |||
1 | /* | ||
2 | Mantis PCI bridge driver | ||
3 | |||
4 | Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | |||
23 | #include <linux/signal.h> | ||
24 | #include <linux/sched.h> | ||
25 | #include <linux/interrupt.h> | ||
26 | |||
27 | #include "dmxdev.h" | ||
28 | #include "dvbdev.h" | ||
29 | #include "dvb_demux.h" | ||
30 | #include "dvb_frontend.h" | ||
31 | #include "dvb_net.h" | ||
32 | |||
33 | #include "mantis_common.h" | ||
34 | #include "mantis_link.h" /* temporary due to physical layer stuff */ | ||
35 | #include "mantis_reg.h" | ||
36 | |||
37 | /* | ||
38 | * If Slot state is already PLUG_IN event and we are called | ||
39 | * again, definitely it is jitter alone | ||
40 | */ | ||
41 | void mantis_event_cam_plugin(struct mantis_ca *ca) | ||
42 | { | ||
43 | struct mantis_pci *mantis = ca->ca_priv; | ||
44 | |||
45 | u32 gpif_irqcfg; | ||
46 | |||
47 | if (ca->slot_state == MODULE_XTRACTED) { | ||
48 | dprintk(MANTIS_DEBUG, 1, "Event: CAM Plugged IN: Adapter(%d) Slot(0)", mantis->num); | ||
49 | udelay(50); | ||
50 | mmwrite(0xda000000, MANTIS_CARD_RESET); | ||
51 | gpif_irqcfg = mmread(MANTIS_GPIF_IRQCFG); | ||
52 | gpif_irqcfg |= MANTIS_MASK_PLUGOUT; | ||
53 | gpif_irqcfg &= ~MANTIS_MASK_PLUGIN; | ||
54 | mmwrite(gpif_irqcfg, MANTIS_GPIF_IRQCFG); | ||
55 | udelay(500); | ||
56 | ca->slot_state = MODULE_INSERTED; | ||
57 | } | ||
58 | udelay(100); | ||
59 | } | ||
60 | |||
61 | /* | ||
62 | * If Slot state is already UN_PLUG event and we are called | ||
63 | * again, definitely it is jitter alone | ||
64 | */ | ||
65 | void mantis_event_cam_unplug(struct mantis_ca *ca) | ||
66 | { | ||
67 | struct mantis_pci *mantis = ca->ca_priv; | ||
68 | |||
69 | u32 gpif_irqcfg; | ||
70 | |||
71 | if (ca->slot_state == MODULE_INSERTED) { | ||
72 | dprintk(MANTIS_DEBUG, 1, "Event: CAM Unplugged: Adapter(%d) Slot(0)", mantis->num); | ||
73 | udelay(50); | ||
74 | mmwrite(0x00da0000, MANTIS_CARD_RESET); | ||
75 | gpif_irqcfg = mmread(MANTIS_GPIF_IRQCFG); | ||
76 | gpif_irqcfg |= MANTIS_MASK_PLUGIN; | ||
77 | gpif_irqcfg &= ~MANTIS_MASK_PLUGOUT; | ||
78 | mmwrite(gpif_irqcfg, MANTIS_GPIF_IRQCFG); | ||
79 | udelay(500); | ||
80 | ca->slot_state = MODULE_XTRACTED; | ||
81 | } | ||
82 | udelay(100); | ||
83 | } | ||
84 | |||
85 | int mantis_pcmcia_init(struct mantis_ca *ca) | ||
86 | { | ||
87 | struct mantis_pci *mantis = ca->ca_priv; | ||
88 | |||
89 | u32 gpif_stat, card_stat; | ||
90 | |||
91 | mmwrite(mmread(MANTIS_INT_MASK) | MANTIS_INT_IRQ0, MANTIS_INT_MASK); | ||
92 | gpif_stat = mmread(MANTIS_GPIF_STATUS); | ||
93 | card_stat = mmread(MANTIS_GPIF_IRQCFG); | ||
94 | |||
95 | if (gpif_stat & MANTIS_GPIF_DETSTAT) { | ||
96 | dprintk(MANTIS_DEBUG, 1, "CAM found on Adapter(%d) Slot(0)", mantis->num); | ||
97 | mmwrite(card_stat | MANTIS_MASK_PLUGOUT, MANTIS_GPIF_IRQCFG); | ||
98 | ca->slot_state = MODULE_INSERTED; | ||
99 | dvb_ca_en50221_camchange_irq(&ca->en50221, | ||
100 | 0, | ||
101 | DVB_CA_EN50221_CAMCHANGE_INSERTED); | ||
102 | } else { | ||
103 | dprintk(MANTIS_DEBUG, 1, "Empty Slot on Adapter(%d) Slot(0)", mantis->num); | ||
104 | mmwrite(card_stat | MANTIS_MASK_PLUGIN, MANTIS_GPIF_IRQCFG); | ||
105 | ca->slot_state = MODULE_XTRACTED; | ||
106 | dvb_ca_en50221_camchange_irq(&ca->en50221, | ||
107 | 0, | ||
108 | DVB_CA_EN50221_CAMCHANGE_REMOVED); | ||
109 | } | ||
110 | |||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | void mantis_pcmcia_exit(struct mantis_ca *ca) | ||
115 | { | ||
116 | struct mantis_pci *mantis = ca->ca_priv; | ||
117 | |||
118 | mmwrite(mmread(MANTIS_GPIF_STATUS) & (~MANTIS_CARD_PLUGOUT | ~MANTIS_CARD_PLUGIN), MANTIS_GPIF_STATUS); | ||
119 | mmwrite(mmread(MANTIS_INT_MASK) & ~MANTIS_INT_IRQ0, MANTIS_INT_MASK); | ||
120 | } | ||
diff --git a/drivers/media/dvb/mantis/mantis_reg.h b/drivers/media/dvb/mantis/mantis_reg.h new file mode 100644 index 000000000000..7761f9dc7fe0 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_reg.h | |||
@@ -0,0 +1,197 @@ | |||
1 | /* | ||
2 | Mantis PCI bridge driver | ||
3 | |||
4 | Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #ifndef __MANTIS_REG_H | ||
22 | #define __MANTIS_REG_H | ||
23 | |||
24 | /* Interrupts */ | ||
25 | #define MANTIS_INT_STAT 0x00 | ||
26 | #define MANTIS_INT_MASK 0x04 | ||
27 | |||
28 | #define MANTIS_INT_RISCSTAT (0x0f << 28) | ||
29 | #define MANTIS_INT_RISCEN (0x01 << 27) | ||
30 | #define MANTIS_INT_I2CRACK (0x01 << 26) | ||
31 | |||
32 | /* #define MANTIS_INT_GPIF (0xff << 12) */ | ||
33 | |||
34 | #define MANTIS_INT_PCMCIA7 (0x01 << 19) | ||
35 | #define MANTIS_INT_PCMCIA6 (0x01 << 18) | ||
36 | #define MANTIS_INT_PCMCIA5 (0x01 << 17) | ||
37 | #define MANTIS_INT_PCMCIA4 (0x01 << 16) | ||
38 | #define MANTIS_INT_PCMCIA3 (0x01 << 15) | ||
39 | #define MANTIS_INT_PCMCIA2 (0x01 << 14) | ||
40 | #define MANTIS_INT_PCMCIA1 (0x01 << 13) | ||
41 | #define MANTIS_INT_PCMCIA0 (0x01 << 12) | ||
42 | #define MANTIS_INT_IRQ1 (0x01 << 11) | ||
43 | #define MANTIS_INT_IRQ0 (0x01 << 10) | ||
44 | #define MANTIS_INT_OCERR (0x01 << 8) | ||
45 | #define MANTIS_INT_PABORT (0x01 << 7) | ||
46 | #define MANTIS_INT_RIPERR (0x01 << 6) | ||
47 | #define MANTIS_INT_PPERR (0x01 << 5) | ||
48 | #define MANTIS_INT_FTRGT (0x01 << 3) | ||
49 | #define MANTIS_INT_RISCI (0x01 << 1) | ||
50 | #define MANTIS_INT_I2CDONE (0x01 << 0) | ||
51 | |||
52 | /* DMA */ | ||
53 | #define MANTIS_DMA_CTL 0x08 | ||
54 | #define MANTIS_GPIF_RD (0xff << 24) | ||
55 | #define MANTIS_GPIF_WR (0xff << 16) | ||
56 | #define MANTIS_CPU_DO (0x01 << 10) | ||
57 | #define MANTIS_DRV_DO (0x01 << 9) | ||
58 | #define MANTIS_I2C_RD (0x01 << 7) | ||
59 | #define MANTIS_I2C_WR (0x01 << 6) | ||
60 | #define MANTIS_DCAP_MODE (0x01 << 5) | ||
61 | #define MANTIS_FIFO_TP_4 (0x00 << 3) | ||
62 | #define MANTIS_FIFO_TP_8 (0x01 << 3) | ||
63 | #define MANTIS_FIFO_TP_16 (0x02 << 3) | ||
64 | #define MANTIS_FIFO_EN (0x01 << 2) | ||
65 | #define MANTIS_DCAP_EN (0x01 << 1) | ||
66 | #define MANTIS_RISC_EN (0x01 << 0) | ||
67 | |||
68 | /* DEBUG */ | ||
69 | #define MANTIS_DEBUGREG 0x0c | ||
70 | #define MANTIS_DATINV (0x0e << 7) | ||
71 | #define MANTIS_TOP_DEBUGSEL (0x07 << 4) | ||
72 | #define MANTIS_PCMCIA_DEBUGSEL (0x0f << 0) | ||
73 | |||
74 | #define MANTIS_RISC_START 0x10 | ||
75 | #define MANTIS_RISC_PC 0x14 | ||
76 | |||
77 | /* I2C */ | ||
78 | #define MANTIS_I2CDATA_CTL 0x18 | ||
79 | #define MANTIS_I2C_RATE_1 (0x00 << 6) | ||
80 | #define MANTIS_I2C_RATE_2 (0x01 << 6) | ||
81 | #define MANTIS_I2C_RATE_3 (0x02 << 6) | ||
82 | #define MANTIS_I2C_RATE_4 (0x03 << 6) | ||
83 | #define MANTIS_I2C_STOP (0x01 << 5) | ||
84 | #define MANTIS_I2C_PGMODE (0x01 << 3) | ||
85 | |||
86 | /* DATA */ | ||
87 | #define MANTIS_CMD_DATA_R1 0x20 | ||
88 | #define MANTIS_CMD_DATA_3 (0xff << 24) | ||
89 | #define MANTIS_CMD_DATA_2 (0xff << 16) | ||
90 | #define MANTIS_CMD_DATA_1 (0xff << 8) | ||
91 | #define MANTIS_CMD_DATA_0 (0xff << 0) | ||
92 | |||
93 | #define MANTIS_CMD_DATA_R2 0x24 | ||
94 | #define MANTIS_CMD_DATA_7 (0xff << 24) | ||
95 | #define MANTIS_CMD_DATA_6 (0xff << 16) | ||
96 | #define MANTIS_CMD_DATA_5 (0xff << 8) | ||
97 | #define MANTIS_CMD_DATA_4 (0xff << 0) | ||
98 | |||
99 | #define MANTIS_CONTROL 0x28 | ||
100 | #define MANTIS_DET (0x01 << 7) | ||
101 | #define MANTIS_DAT_CF_EN (0x01 << 6) | ||
102 | #define MANTIS_ACS (0x03 << 4) | ||
103 | #define MANTIS_VCCEN (0x01 << 3) | ||
104 | #define MANTIS_BYPASS (0x01 << 2) | ||
105 | #define MANTIS_MRST (0x01 << 1) | ||
106 | #define MANTIS_CRST_INT (0x01 << 0) | ||
107 | |||
108 | #define MANTIS_GPIF_CFGSLA 0x84 | ||
109 | #define MANTIS_GPIF_WAITSMPL (0x07 << 28) | ||
110 | #define MANTIS_GPIF_BYTEADDRSUB (0x01 << 25) | ||
111 | #define MANTIS_GPIF_WAITPOL (0x01 << 24) | ||
112 | #define MANTIS_GPIF_NCDELAY (0x07 << 20) | ||
113 | #define MANTIS_GPIF_RW2CSDELAY (0x07 << 16) | ||
114 | #define MANTIS_GPIF_SLFTIMEDMODE (0x01 << 15) | ||
115 | #define MANTIS_GPIF_SLFTIMEDDELY (0x7f << 8) | ||
116 | #define MANTIS_GPIF_DEVTYPE (0x07 << 4) | ||
117 | #define MANTIS_GPIF_BIGENDIAN (0x01 << 3) | ||
118 | #define MANTIS_GPIF_FETCHCMD (0x03 << 1) | ||
119 | #define MANTIS_GPIF_HWORDDEV (0x01 << 0) | ||
120 | |||
121 | #define MANTIS_GPIF_WSTOPER 0x90 | ||
122 | #define MANTIS_GPIF_WSTOPERWREN3 (0x01 << 31) | ||
123 | #define MANTIS_GPIF_PARBOOTN (0x01 << 29) | ||
124 | #define MANTIS_GPIF_WSTOPERSLID3 (0x1f << 24) | ||
125 | #define MANTIS_GPIF_WSTOPERWREN2 (0x01 << 23) | ||
126 | #define MANTIS_GPIF_WSTOPERSLID2 (0x1f << 16) | ||
127 | #define MANTIS_GPIF_WSTOPERWREN1 (0x01 << 15) | ||
128 | #define MANTIS_GPIF_WSTOPERSLID1 (0x1f << 8) | ||
129 | #define MANTIS_GPIF_WSTOPERWREN0 (0x01 << 7) | ||
130 | #define MANTIS_GPIF_WSTOPERSLID0 (0x1f << 0) | ||
131 | |||
132 | #define MANTIS_GPIF_CS2RW 0x94 | ||
133 | #define MANTIS_GPIF_CS2RWWREN3 (0x01 << 31) | ||
134 | #define MANTIS_GPIF_CS2RWDELY3 (0x3f << 24) | ||
135 | #define MANTIS_GPIF_CS2RWWREN2 (0x01 << 23) | ||
136 | #define MANTIS_GPIF_CS2RWDELY2 (0x3f << 16) | ||
137 | #define MANTIS_GPIF_CS2RWWREN1 (0x01 << 15) | ||
138 | #define MANTIS_GPIF_CS2RWDELY1 (0x3f << 8) | ||
139 | #define MANTIS_GPIF_CS2RWWREN0 (0x01 << 7) | ||
140 | #define MANTIS_GPIF_CS2RWDELY0 (0x3f << 0) | ||
141 | |||
142 | #define MANTIS_GPIF_IRQCFG 0x98 | ||
143 | #define MANTIS_GPIF_IRQPOL (0x01 << 8) | ||
144 | #define MANTIS_MASK_WRACK (0x01 << 7) | ||
145 | #define MANTIS_MASK_BRRDY (0x01 << 6) | ||
146 | #define MANTIS_MASK_OVFLW (0x01 << 5) | ||
147 | #define MANTIS_MASK_OTHERR (0x01 << 4) | ||
148 | #define MANTIS_MASK_WSTO (0x01 << 3) | ||
149 | #define MANTIS_MASK_EXTIRQ (0x01 << 2) | ||
150 | #define MANTIS_MASK_PLUGIN (0x01 << 1) | ||
151 | #define MANTIS_MASK_PLUGOUT (0x01 << 0) | ||
152 | |||
153 | #define MANTIS_GPIF_STATUS 0x9c | ||
154 | #define MANTIS_SBUF_KILLOP (0x01 << 15) | ||
155 | #define MANTIS_SBUF_OPDONE (0x01 << 14) | ||
156 | #define MANTIS_SBUF_EMPTY (0x01 << 13) | ||
157 | #define MANTIS_GPIF_DETSTAT (0x01 << 9) | ||
158 | #define MANTIS_GPIF_INTSTAT (0x01 << 8) | ||
159 | #define MANTIS_GPIF_WRACK (0x01 << 7) | ||
160 | #define MANTIS_GPIF_BRRDY (0x01 << 6) | ||
161 | #define MANTIS_SBUF_OVFLW (0x01 << 5) | ||
162 | #define MANTIS_GPIF_OTHERR (0x01 << 4) | ||
163 | #define MANTIS_SBUF_WSTO (0x01 << 3) | ||
164 | #define MANTIS_GPIF_EXTIRQ (0x01 << 2) | ||
165 | #define MANTIS_CARD_PLUGIN (0x01 << 1) | ||
166 | #define MANTIS_CARD_PLUGOUT (0x01 << 0) | ||
167 | |||
168 | #define MANTIS_GPIF_BRADDR 0xa0 | ||
169 | #define MANTIS_GPIF_PCMCIAREG (0x01 << 27) | ||
170 | #define MANTIS_GPIF_PCMCIAIOM (0x01 << 26) | ||
171 | #define MANTIS_GPIF_BR_ADDR (0xfffffff << 0) | ||
172 | |||
173 | #define MANTIS_GPIF_BRBYTES 0xa4 | ||
174 | #define MANTIS_GPIF_BRCNT (0xfff << 0) | ||
175 | |||
176 | #define MANTIS_PCMCIA_RESET 0xa8 | ||
177 | #define MANTIS_PCMCIA_RSTVAL (0xff << 0) | ||
178 | |||
179 | #define MANTIS_CARD_RESET 0xac | ||
180 | |||
181 | #define MANTIS_GPIF_ADDR 0xb0 | ||
182 | #define MANTIS_GPIF_HIFRDWRN (0x01 << 31) | ||
183 | #define MANTIS_GPIF_PCMCIAREG (0x01 << 27) | ||
184 | #define MANTIS_GPIF_PCMCIAIOM (0x01 << 26) | ||
185 | #define MANTIS_GPIF_HIFADDR (0xfffffff << 0) | ||
186 | |||
187 | #define MANTIS_GPIF_DOUT 0xb4 | ||
188 | #define MANTIS_GPIF_HIFDOUT (0xfffffff << 0) | ||
189 | |||
190 | #define MANTIS_GPIF_DIN 0xb8 | ||
191 | #define MANTIS_GPIF_HIFDIN (0xfffffff << 0) | ||
192 | |||
193 | #define MANTIS_GPIF_SPARE 0xbc | ||
194 | #define MANTIS_GPIF_LOGICRD (0xffff << 16) | ||
195 | #define MANTIS_GPIF_LOGICRW (0xffff << 0) | ||
196 | |||
197 | #endif /* __MANTIS_REG_H */ | ||
diff --git a/drivers/media/dvb/mantis/mantis_uart.c b/drivers/media/dvb/mantis/mantis_uart.c new file mode 100644 index 000000000000..7d2f2398fa8b --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_uart.c | |||
@@ -0,0 +1,186 @@ | |||
1 | /* | ||
2 | Mantis PCI bridge driver | ||
3 | |||
4 | Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/spinlock.h> | ||
23 | |||
24 | #include <linux/signal.h> | ||
25 | #include <linux/sched.h> | ||
26 | #include <linux/interrupt.h> | ||
27 | |||
28 | #include "dmxdev.h" | ||
29 | #include "dvbdev.h" | ||
30 | #include "dvb_demux.h" | ||
31 | #include "dvb_frontend.h" | ||
32 | #include "dvb_net.h" | ||
33 | |||
34 | #include "mantis_common.h" | ||
35 | #include "mantis_reg.h" | ||
36 | #include "mantis_uart.h" | ||
37 | |||
38 | struct mantis_uart_params { | ||
39 | enum mantis_baud baud_rate; | ||
40 | enum mantis_parity parity; | ||
41 | }; | ||
42 | |||
43 | static struct { | ||
44 | char string[7]; | ||
45 | } rates[5] = { | ||
46 | { "9600" }, | ||
47 | { "19200" }, | ||
48 | { "38400" }, | ||
49 | { "57600" }, | ||
50 | { "115200" } | ||
51 | }; | ||
52 | |||
53 | static struct { | ||
54 | char string[5]; | ||
55 | } parity[3] = { | ||
56 | { "NONE" }, | ||
57 | { "ODD" }, | ||
58 | { "EVEN" } | ||
59 | }; | ||
60 | |||
61 | #define UART_MAX_BUF 16 | ||
62 | |||
63 | int mantis_uart_read(struct mantis_pci *mantis, u8 *data) | ||
64 | { | ||
65 | struct mantis_hwconfig *config = mantis->hwconfig; | ||
66 | u32 stat = 0, i; | ||
67 | |||
68 | /* get data */ | ||
69 | for (i = 0; i < (config->bytes + 1); i++) { | ||
70 | |||
71 | stat = mmread(MANTIS_UART_STAT); | ||
72 | |||
73 | if (stat & MANTIS_UART_RXFIFO_FULL) { | ||
74 | dprintk(MANTIS_ERROR, 1, "RX Fifo FULL"); | ||
75 | } | ||
76 | data[i] = mmread(MANTIS_UART_RXD) & 0x3f; | ||
77 | |||
78 | dprintk(MANTIS_DEBUG, 1, "Reading ... <%02x>", data[i] & 0x3f); | ||
79 | |||
80 | if (data[i] & (1 << 7)) { | ||
81 | dprintk(MANTIS_ERROR, 1, "UART framing error"); | ||
82 | return -EINVAL; | ||
83 | } | ||
84 | if (data[i] & (1 << 6)) { | ||
85 | dprintk(MANTIS_ERROR, 1, "UART parity error"); | ||
86 | return -EINVAL; | ||
87 | } | ||
88 | } | ||
89 | |||
90 | return 0; | ||
91 | } | ||
92 | |||
93 | static void mantis_uart_work(struct work_struct *work) | ||
94 | { | ||
95 | struct mantis_pci *mantis = container_of(work, struct mantis_pci, uart_work); | ||
96 | struct mantis_hwconfig *config = mantis->hwconfig; | ||
97 | u8 buf[16]; | ||
98 | int i; | ||
99 | |||
100 | mantis_uart_read(mantis, buf); | ||
101 | |||
102 | for (i = 0; i < (config->bytes + 1); i++) | ||
103 | dprintk(MANTIS_INFO, 1, "UART BUF:%d <%02x> ", i, buf[i]); | ||
104 | |||
105 | dprintk(MANTIS_DEBUG, 0, "\n"); | ||
106 | } | ||
107 | |||
108 | static int mantis_uart_setup(struct mantis_pci *mantis, | ||
109 | struct mantis_uart_params *params) | ||
110 | { | ||
111 | u32 reg; | ||
112 | |||
113 | mmwrite((mmread(MANTIS_UART_CTL) | (params->parity & 0x3)), MANTIS_UART_CTL); | ||
114 | |||
115 | reg = mmread(MANTIS_UART_BAUD); | ||
116 | |||
117 | switch (params->baud_rate) { | ||
118 | case MANTIS_BAUD_9600: | ||
119 | reg |= 0xd8; | ||
120 | break; | ||
121 | case MANTIS_BAUD_19200: | ||
122 | reg |= 0x6c; | ||
123 | break; | ||
124 | case MANTIS_BAUD_38400: | ||
125 | reg |= 0x36; | ||
126 | break; | ||
127 | case MANTIS_BAUD_57600: | ||
128 | reg |= 0x23; | ||
129 | break; | ||
130 | case MANTIS_BAUD_115200: | ||
131 | reg |= 0x11; | ||
132 | break; | ||
133 | default: | ||
134 | return -EINVAL; | ||
135 | } | ||
136 | |||
137 | mmwrite(reg, MANTIS_UART_BAUD); | ||
138 | |||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | int mantis_uart_init(struct mantis_pci *mantis) | ||
143 | { | ||
144 | struct mantis_hwconfig *config = mantis->hwconfig; | ||
145 | struct mantis_uart_params params; | ||
146 | |||
147 | /* default parity: */ | ||
148 | params.baud_rate = config->baud_rate; | ||
149 | params.parity = config->parity; | ||
150 | dprintk(MANTIS_INFO, 1, "Initializing UART @ %sbps parity:%s", | ||
151 | rates[params.baud_rate].string, | ||
152 | parity[params.parity].string); | ||
153 | |||
154 | init_waitqueue_head(&mantis->uart_wq); | ||
155 | spin_lock_init(&mantis->uart_lock); | ||
156 | |||
157 | INIT_WORK(&mantis->uart_work, mantis_uart_work); | ||
158 | |||
159 | /* disable interrupt */ | ||
160 | mmwrite(mmread(MANTIS_UART_CTL) & 0xffef, MANTIS_UART_CTL); | ||
161 | |||
162 | mantis_uart_setup(mantis, ¶ms); | ||
163 | |||
164 | /* default 1 byte */ | ||
165 | mmwrite((mmread(MANTIS_UART_BAUD) | (config->bytes << 8)), MANTIS_UART_BAUD); | ||
166 | |||
167 | /* flush buffer */ | ||
168 | mmwrite((mmread(MANTIS_UART_CTL) | MANTIS_UART_RXFLUSH), MANTIS_UART_CTL); | ||
169 | |||
170 | /* enable interrupt */ | ||
171 | mmwrite(mmread(MANTIS_INT_MASK) | 0x800, MANTIS_INT_MASK); | ||
172 | mmwrite(mmread(MANTIS_UART_CTL) | MANTIS_UART_RXINT, MANTIS_UART_CTL); | ||
173 | |||
174 | schedule_work(&mantis->uart_work); | ||
175 | dprintk(MANTIS_DEBUG, 1, "UART succesfully initialized"); | ||
176 | |||
177 | return 0; | ||
178 | } | ||
179 | EXPORT_SYMBOL_GPL(mantis_uart_init); | ||
180 | |||
181 | void mantis_uart_exit(struct mantis_pci *mantis) | ||
182 | { | ||
183 | /* disable interrupt */ | ||
184 | mmwrite(mmread(MANTIS_UART_CTL) & 0xffef, MANTIS_UART_CTL); | ||
185 | } | ||
186 | EXPORT_SYMBOL_GPL(mantis_uart_exit); | ||
diff --git a/drivers/media/dvb/mantis/mantis_uart.h b/drivers/media/dvb/mantis/mantis_uart.h new file mode 100644 index 000000000000..ffb62a0a5a13 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_uart.h | |||
@@ -0,0 +1,58 @@ | |||
1 | /* | ||
2 | Mantis PCI bridge driver | ||
3 | |||
4 | Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #ifndef __MANTIS_UART_H | ||
22 | #define __MANTIS_UART_H | ||
23 | |||
24 | #define MANTIS_UART_CTL 0xe0 | ||
25 | #define MANTIS_UART_RXINT (1 << 4) | ||
26 | #define MANTIS_UART_RXFLUSH (1 << 2) | ||
27 | |||
28 | #define MANTIS_UART_RXD 0xe8 | ||
29 | #define MANTIS_UART_BAUD 0xec | ||
30 | |||
31 | #define MANTIS_UART_STAT 0xf0 | ||
32 | #define MANTIS_UART_RXFIFO_DATA (1 << 7) | ||
33 | #define MANTIS_UART_RXFIFO_EMPTY (1 << 6) | ||
34 | #define MANTIS_UART_RXFIFO_FULL (1 << 3) | ||
35 | #define MANTIS_UART_FRAME_ERR (1 << 2) | ||
36 | #define MANTIS_UART_PARITY_ERR (1 << 1) | ||
37 | #define MANTIS_UART_RXTHRESH_INT (1 << 0) | ||
38 | |||
39 | enum mantis_baud { | ||
40 | MANTIS_BAUD_9600 = 0, | ||
41 | MANTIS_BAUD_19200, | ||
42 | MANTIS_BAUD_38400, | ||
43 | MANTIS_BAUD_57600, | ||
44 | MANTIS_BAUD_115200 | ||
45 | }; | ||
46 | |||
47 | enum mantis_parity { | ||
48 | MANTIS_PARITY_NONE = 0, | ||
49 | MANTIS_PARITY_EVEN, | ||
50 | MANTIS_PARITY_ODD, | ||
51 | }; | ||
52 | |||
53 | struct mantis_pci; | ||
54 | |||
55 | extern int mantis_uart_init(struct mantis_pci *mantis); | ||
56 | extern void mantis_uart_exit(struct mantis_pci *mantis); | ||
57 | |||
58 | #endif /* __MANTIS_UART_H */ | ||
diff --git a/drivers/media/dvb/mantis/mantis_vp1033.c b/drivers/media/dvb/mantis/mantis_vp1033.c new file mode 100644 index 000000000000..4a723bda0031 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_vp1033.c | |||
@@ -0,0 +1,212 @@ | |||
1 | /* | ||
2 | Mantis VP-1033 driver | ||
3 | |||
4 | Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/signal.h> | ||
22 | #include <linux/sched.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | |||
25 | #include "dmxdev.h" | ||
26 | #include "dvbdev.h" | ||
27 | #include "dvb_demux.h" | ||
28 | #include "dvb_frontend.h" | ||
29 | #include "dvb_net.h" | ||
30 | |||
31 | #include "stv0299.h" | ||
32 | #include "mantis_common.h" | ||
33 | #include "mantis_ioc.h" | ||
34 | #include "mantis_dvb.h" | ||
35 | #include "mantis_vp1033.h" | ||
36 | #include "mantis_reg.h" | ||
37 | |||
38 | u8 lgtdqcs001f_inittab[] = { | ||
39 | 0x01, 0x15, | ||
40 | 0x02, 0x00, | ||
41 | 0x03, 0x00, | ||
42 | 0x04, 0x2a, | ||
43 | 0x05, 0x85, | ||
44 | 0x06, 0x02, | ||
45 | 0x07, 0x00, | ||
46 | 0x08, 0x00, | ||
47 | 0x0c, 0x01, | ||
48 | 0x0d, 0x81, | ||
49 | 0x0e, 0x44, | ||
50 | 0x0f, 0x94, | ||
51 | 0x10, 0x3c, | ||
52 | 0x11, 0x84, | ||
53 | 0x12, 0xb9, | ||
54 | 0x13, 0xb5, | ||
55 | 0x14, 0x4f, | ||
56 | 0x15, 0xc9, | ||
57 | 0x16, 0x80, | ||
58 | 0x17, 0x36, | ||
59 | 0x18, 0xfb, | ||
60 | 0x19, 0xcf, | ||
61 | 0x1a, 0xbc, | ||
62 | 0x1c, 0x2b, | ||
63 | 0x1d, 0x27, | ||
64 | 0x1e, 0x00, | ||
65 | 0x1f, 0x0b, | ||
66 | 0x20, 0xa1, | ||
67 | 0x21, 0x60, | ||
68 | 0x22, 0x00, | ||
69 | 0x23, 0x00, | ||
70 | 0x28, 0x00, | ||
71 | 0x29, 0x28, | ||
72 | 0x2a, 0x14, | ||
73 | 0x2b, 0x0f, | ||
74 | 0x2c, 0x09, | ||
75 | 0x2d, 0x05, | ||
76 | 0x31, 0x1f, | ||
77 | 0x32, 0x19, | ||
78 | 0x33, 0xfc, | ||
79 | 0x34, 0x13, | ||
80 | 0xff, 0xff, | ||
81 | }; | ||
82 | |||
83 | #define MANTIS_MODEL_NAME "VP-1033" | ||
84 | #define MANTIS_DEV_TYPE "DVB-S/DSS" | ||
85 | |||
86 | int lgtdqcs001f_tuner_set(struct dvb_frontend *fe, | ||
87 | struct dvb_frontend_parameters *params) | ||
88 | { | ||
89 | struct mantis_pci *mantis = fe->dvb->priv; | ||
90 | struct i2c_adapter *adapter = &mantis->adapter; | ||
91 | |||
92 | u8 buf[4]; | ||
93 | u32 div; | ||
94 | |||
95 | |||
96 | struct i2c_msg msg = {.addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf)}; | ||
97 | |||
98 | div = params->frequency / 250; | ||
99 | |||
100 | buf[0] = (div >> 8) & 0x7f; | ||
101 | buf[1] = div & 0xff; | ||
102 | buf[2] = 0x83; | ||
103 | buf[3] = 0xc0; | ||
104 | |||
105 | if (params->frequency < 1531000) | ||
106 | buf[3] |= 0x04; | ||
107 | else | ||
108 | buf[3] &= ~0x04; | ||
109 | if (i2c_transfer(adapter, &msg, 1) < 0) { | ||
110 | dprintk(MANTIS_ERROR, 1, "Write: I2C Transfer failed"); | ||
111 | return -EIO; | ||
112 | } | ||
113 | msleep_interruptible(100); | ||
114 | |||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | int lgtdqcs001f_set_symbol_rate(struct dvb_frontend *fe, | ||
119 | u32 srate, u32 ratio) | ||
120 | { | ||
121 | u8 aclk = 0; | ||
122 | u8 bclk = 0; | ||
123 | |||
124 | if (srate < 1500000) { | ||
125 | aclk = 0xb7; | ||
126 | bclk = 0x47; | ||
127 | } else if (srate < 3000000) { | ||
128 | aclk = 0xb7; | ||
129 | bclk = 0x4b; | ||
130 | } else if (srate < 7000000) { | ||
131 | aclk = 0xb7; | ||
132 | bclk = 0x4f; | ||
133 | } else if (srate < 14000000) { | ||
134 | aclk = 0xb7; | ||
135 | bclk = 0x53; | ||
136 | } else if (srate < 30000000) { | ||
137 | aclk = 0xb6; | ||
138 | bclk = 0x53; | ||
139 | } else if (srate < 45000000) { | ||
140 | aclk = 0xb4; | ||
141 | bclk = 0x51; | ||
142 | } | ||
143 | stv0299_writereg(fe, 0x13, aclk); | ||
144 | stv0299_writereg(fe, 0x14, bclk); | ||
145 | |||
146 | stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff); | ||
147 | stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff); | ||
148 | stv0299_writereg(fe, 0x21, ratio & 0xf0); | ||
149 | |||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | struct stv0299_config lgtdqcs001f_config = { | ||
154 | .demod_address = 0x68, | ||
155 | .inittab = lgtdqcs001f_inittab, | ||
156 | .mclk = 88000000UL, | ||
157 | .invert = 0, | ||
158 | .skip_reinit = 0, | ||
159 | .volt13_op0_op1 = STV0299_VOLT13_OP0, | ||
160 | .min_delay_ms = 100, | ||
161 | .set_symbol_rate = lgtdqcs001f_set_symbol_rate, | ||
162 | }; | ||
163 | |||
164 | static int vp1033_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe) | ||
165 | { | ||
166 | struct i2c_adapter *adapter = &mantis->adapter; | ||
167 | |||
168 | int err = 0; | ||
169 | |||
170 | err = mantis_frontend_power(mantis, POWER_ON); | ||
171 | if (err == 0) { | ||
172 | mantis_frontend_soft_reset(mantis); | ||
173 | msleep(250); | ||
174 | |||
175 | dprintk(MANTIS_ERROR, 1, "Probing for STV0299 (DVB-S)"); | ||
176 | fe = stv0299_attach(&lgtdqcs001f_config, adapter); | ||
177 | |||
178 | if (fe) { | ||
179 | fe->ops.tuner_ops.set_params = lgtdqcs001f_tuner_set; | ||
180 | dprintk(MANTIS_ERROR, 1, "found STV0299 DVB-S frontend @ 0x%02x", | ||
181 | lgtdqcs001f_config.demod_address); | ||
182 | |||
183 | dprintk(MANTIS_ERROR, 1, "Mantis DVB-S STV0299 frontend attach success"); | ||
184 | } else { | ||
185 | return -1; | ||
186 | } | ||
187 | } else { | ||
188 | dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>", | ||
189 | adapter->name, | ||
190 | err); | ||
191 | |||
192 | return -EIO; | ||
193 | } | ||
194 | mantis->fe = fe; | ||
195 | dprintk(MANTIS_ERROR, 1, "Done!"); | ||
196 | |||
197 | return 0; | ||
198 | } | ||
199 | |||
200 | struct mantis_hwconfig vp1033_config = { | ||
201 | .model_name = MANTIS_MODEL_NAME, | ||
202 | .dev_type = MANTIS_DEV_TYPE, | ||
203 | .ts_size = MANTIS_TS_204, | ||
204 | |||
205 | .baud_rate = MANTIS_BAUD_9600, | ||
206 | .parity = MANTIS_PARITY_NONE, | ||
207 | .bytes = 0, | ||
208 | |||
209 | .frontend_init = vp1033_frontend_init, | ||
210 | .power = GPIF_A12, | ||
211 | .reset = GPIF_A13, | ||
212 | }; | ||
diff --git a/drivers/media/dvb/mantis/mantis_vp1033.h b/drivers/media/dvb/mantis/mantis_vp1033.h new file mode 100644 index 000000000000..7daaa1bf127d --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_vp1033.h | |||
@@ -0,0 +1,30 @@ | |||
1 | /* | ||
2 | Mantis VP-1033 driver | ||
3 | |||
4 | Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #ifndef __MANTIS_VP1033_H | ||
22 | #define __MANTIS_VP1033_H | ||
23 | |||
24 | #include "mantis_common.h" | ||
25 | |||
26 | #define MANTIS_VP_1033_DVB_S 0x0016 | ||
27 | |||
28 | extern struct mantis_hwconfig vp1033_config; | ||
29 | |||
30 | #endif /* __MANTIS_VP1033_H */ | ||
diff --git a/drivers/media/dvb/mantis/mantis_vp1034.c b/drivers/media/dvb/mantis/mantis_vp1034.c new file mode 100644 index 000000000000..8e6ae558ee57 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_vp1034.c | |||
@@ -0,0 +1,119 @@ | |||
1 | /* | ||
2 | Mantis VP-1034 driver | ||
3 | |||
4 | Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/signal.h> | ||
22 | #include <linux/sched.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | |||
25 | #include "dmxdev.h" | ||
26 | #include "dvbdev.h" | ||
27 | #include "dvb_demux.h" | ||
28 | #include "dvb_frontend.h" | ||
29 | #include "dvb_net.h" | ||
30 | |||
31 | #include "mb86a16.h" | ||
32 | #include "mantis_common.h" | ||
33 | #include "mantis_ioc.h" | ||
34 | #include "mantis_dvb.h" | ||
35 | #include "mantis_vp1034.h" | ||
36 | #include "mantis_reg.h" | ||
37 | |||
38 | struct mb86a16_config vp1034_mb86a16_config = { | ||
39 | .demod_address = 0x08, | ||
40 | .set_voltage = vp1034_set_voltage, | ||
41 | }; | ||
42 | |||
43 | #define MANTIS_MODEL_NAME "VP-1034" | ||
44 | #define MANTIS_DEV_TYPE "DVB-S/DSS" | ||
45 | |||
46 | int vp1034_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) | ||
47 | { | ||
48 | struct mantis_pci *mantis = fe->dvb->priv; | ||
49 | |||
50 | switch (voltage) { | ||
51 | case SEC_VOLTAGE_13: | ||
52 | dprintk(MANTIS_ERROR, 1, "Polarization=[13V]"); | ||
53 | gpio_set_bits(mantis, 13, 1); | ||
54 | gpio_set_bits(mantis, 14, 0); | ||
55 | break; | ||
56 | case SEC_VOLTAGE_18: | ||
57 | dprintk(MANTIS_ERROR, 1, "Polarization=[18V]"); | ||
58 | gpio_set_bits(mantis, 13, 1); | ||
59 | gpio_set_bits(mantis, 14, 1); | ||
60 | break; | ||
61 | case SEC_VOLTAGE_OFF: | ||
62 | dprintk(MANTIS_ERROR, 1, "Frontend (dummy) POWERDOWN"); | ||
63 | break; | ||
64 | default: | ||
65 | dprintk(MANTIS_ERROR, 1, "Invalid = (%d)", (u32) voltage); | ||
66 | return -EINVAL; | ||
67 | } | ||
68 | mmwrite(0x00, MANTIS_GPIF_DOUT); | ||
69 | |||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | static int vp1034_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe) | ||
74 | { | ||
75 | struct i2c_adapter *adapter = &mantis->adapter; | ||
76 | |||
77 | int err = 0; | ||
78 | |||
79 | err = mantis_frontend_power(mantis, POWER_ON); | ||
80 | if (err == 0) { | ||
81 | mantis_frontend_soft_reset(mantis); | ||
82 | msleep(250); | ||
83 | |||
84 | dprintk(MANTIS_ERROR, 1, "Probing for MB86A16 (DVB-S/DSS)"); | ||
85 | fe = mb86a16_attach(&vp1034_mb86a16_config, adapter); | ||
86 | if (fe) { | ||
87 | dprintk(MANTIS_ERROR, 1, | ||
88 | "found MB86A16 DVB-S/DSS frontend @0x%02x", | ||
89 | vp1034_mb86a16_config.demod_address); | ||
90 | |||
91 | } else { | ||
92 | return -1; | ||
93 | } | ||
94 | } else { | ||
95 | dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>", | ||
96 | adapter->name, | ||
97 | err); | ||
98 | |||
99 | return -EIO; | ||
100 | } | ||
101 | mantis->fe = fe; | ||
102 | dprintk(MANTIS_ERROR, 1, "Done!"); | ||
103 | |||
104 | return 0; | ||
105 | } | ||
106 | |||
107 | struct mantis_hwconfig vp1034_config = { | ||
108 | .model_name = MANTIS_MODEL_NAME, | ||
109 | .dev_type = MANTIS_DEV_TYPE, | ||
110 | .ts_size = MANTIS_TS_204, | ||
111 | |||
112 | .baud_rate = MANTIS_BAUD_9600, | ||
113 | .parity = MANTIS_PARITY_NONE, | ||
114 | .bytes = 0, | ||
115 | |||
116 | .frontend_init = vp1034_frontend_init, | ||
117 | .power = GPIF_A12, | ||
118 | .reset = GPIF_A13, | ||
119 | }; | ||
diff --git a/drivers/media/dvb/mantis/mantis_vp1034.h b/drivers/media/dvb/mantis/mantis_vp1034.h new file mode 100644 index 000000000000..323f38ef8e3d --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_vp1034.h | |||
@@ -0,0 +1,33 @@ | |||
1 | /* | ||
2 | Mantis VP-1034 driver | ||
3 | |||
4 | Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #ifndef __MANTIS_VP1034_H | ||
22 | #define __MANTIS_VP1034_H | ||
23 | |||
24 | #include "dvb_frontend.h" | ||
25 | #include "mantis_common.h" | ||
26 | |||
27 | |||
28 | #define MANTIS_VP_1034_DVB_S 0x0014 | ||
29 | |||
30 | extern struct mantis_hwconfig vp1034_config; | ||
31 | extern int vp1034_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage); | ||
32 | |||
33 | #endif /* __MANTIS_VP1034_H */ | ||
diff --git a/drivers/media/dvb/mantis/mantis_vp1041.c b/drivers/media/dvb/mantis/mantis_vp1041.c new file mode 100644 index 000000000000..515346dd31d0 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_vp1041.c | |||
@@ -0,0 +1,358 @@ | |||
1 | /* | ||
2 | Mantis VP-1041 driver | ||
3 | |||
4 | Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/signal.h> | ||
22 | #include <linux/sched.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | |||
25 | #include "dmxdev.h" | ||
26 | #include "dvbdev.h" | ||
27 | #include "dvb_demux.h" | ||
28 | #include "dvb_frontend.h" | ||
29 | #include "dvb_net.h" | ||
30 | |||
31 | #include "mantis_common.h" | ||
32 | #include "mantis_ioc.h" | ||
33 | #include "mantis_dvb.h" | ||
34 | #include "mantis_vp1041.h" | ||
35 | #include "stb0899_reg.h" | ||
36 | #include "stb0899_drv.h" | ||
37 | #include "stb0899_cfg.h" | ||
38 | #include "stb6100_cfg.h" | ||
39 | #include "stb6100.h" | ||
40 | #include "lnbp21.h" | ||
41 | |||
42 | #define MANTIS_MODEL_NAME "VP-1041" | ||
43 | #define MANTIS_DEV_TYPE "DSS/DVB-S/DVB-S2" | ||
44 | |||
45 | static const struct stb0899_s1_reg vp1041_stb0899_s1_init_1[] = { | ||
46 | |||
47 | /* 0x0000000b, *//* SYSREG */ | ||
48 | { STB0899_DEV_ID , 0x30 }, | ||
49 | { STB0899_DISCNTRL1 , 0x32 }, | ||
50 | { STB0899_DISCNTRL2 , 0x80 }, | ||
51 | { STB0899_DISRX_ST0 , 0x04 }, | ||
52 | { STB0899_DISRX_ST1 , 0x00 }, | ||
53 | { STB0899_DISPARITY , 0x00 }, | ||
54 | { STB0899_DISFIFO , 0x00 }, | ||
55 | { STB0899_DISSTATUS , 0x20 }, | ||
56 | { STB0899_DISF22 , 0x99 }, | ||
57 | { STB0899_DISF22RX , 0xa8 }, | ||
58 | /* SYSREG ? */ | ||
59 | { STB0899_ACRPRESC , 0x11 }, | ||
60 | { STB0899_ACRDIV1 , 0x0a }, | ||
61 | { STB0899_ACRDIV2 , 0x05 }, | ||
62 | { STB0899_DACR1 , 0x00 }, | ||
63 | { STB0899_DACR2 , 0x00 }, | ||
64 | { STB0899_OUTCFG , 0x00 }, | ||
65 | { STB0899_MODECFG , 0x00 }, | ||
66 | { STB0899_IRQSTATUS_3 , 0xfe }, | ||
67 | { STB0899_IRQSTATUS_2 , 0x03 }, | ||
68 | { STB0899_IRQSTATUS_1 , 0x7c }, | ||
69 | { STB0899_IRQSTATUS_0 , 0xf4 }, | ||
70 | { STB0899_IRQMSK_3 , 0xf3 }, | ||
71 | { STB0899_IRQMSK_2 , 0xfc }, | ||
72 | { STB0899_IRQMSK_1 , 0xff }, | ||
73 | { STB0899_IRQMSK_0 , 0xff }, | ||
74 | { STB0899_IRQCFG , 0x00 }, | ||
75 | { STB0899_I2CCFG , 0x88 }, | ||
76 | { STB0899_I2CRPT , 0x58 }, | ||
77 | { STB0899_IOPVALUE5 , 0x00 }, | ||
78 | { STB0899_IOPVALUE4 , 0x33 }, | ||
79 | { STB0899_IOPVALUE3 , 0x6d }, | ||
80 | { STB0899_IOPVALUE2 , 0x90 }, | ||
81 | { STB0899_IOPVALUE1 , 0x60 }, | ||
82 | { STB0899_IOPVALUE0 , 0x00 }, | ||
83 | { STB0899_GPIO00CFG , 0x82 }, | ||
84 | { STB0899_GPIO01CFG , 0x82 }, | ||
85 | { STB0899_GPIO02CFG , 0x82 }, | ||
86 | { STB0899_GPIO03CFG , 0x82 }, | ||
87 | { STB0899_GPIO04CFG , 0x82 }, | ||
88 | { STB0899_GPIO05CFG , 0x82 }, | ||
89 | { STB0899_GPIO06CFG , 0x82 }, | ||
90 | { STB0899_GPIO07CFG , 0x82 }, | ||
91 | { STB0899_GPIO08CFG , 0x82 }, | ||
92 | { STB0899_GPIO09CFG , 0x82 }, | ||
93 | { STB0899_GPIO10CFG , 0x82 }, | ||
94 | { STB0899_GPIO11CFG , 0x82 }, | ||
95 | { STB0899_GPIO12CFG , 0x82 }, | ||
96 | { STB0899_GPIO13CFG , 0x82 }, | ||
97 | { STB0899_GPIO14CFG , 0x82 }, | ||
98 | { STB0899_GPIO15CFG , 0x82 }, | ||
99 | { STB0899_GPIO16CFG , 0x82 }, | ||
100 | { STB0899_GPIO17CFG , 0x82 }, | ||
101 | { STB0899_GPIO18CFG , 0x82 }, | ||
102 | { STB0899_GPIO19CFG , 0x82 }, | ||
103 | { STB0899_GPIO20CFG , 0x82 }, | ||
104 | { STB0899_SDATCFG , 0xb8 }, | ||
105 | { STB0899_SCLTCFG , 0xba }, | ||
106 | { STB0899_AGCRFCFG , 0x1c }, /* 0x11 */ | ||
107 | { STB0899_GPIO22 , 0x82 }, /* AGCBB2CFG */ | ||
108 | { STB0899_GPIO21 , 0x91 }, /* AGCBB1CFG */ | ||
109 | { STB0899_DIRCLKCFG , 0x82 }, | ||
110 | { STB0899_CLKOUT27CFG , 0x7e }, | ||
111 | { STB0899_STDBYCFG , 0x82 }, | ||
112 | { STB0899_CS0CFG , 0x82 }, | ||
113 | { STB0899_CS1CFG , 0x82 }, | ||
114 | { STB0899_DISEQCOCFG , 0x20 }, | ||
115 | { STB0899_GPIO32CFG , 0x82 }, | ||
116 | { STB0899_GPIO33CFG , 0x82 }, | ||
117 | { STB0899_GPIO34CFG , 0x82 }, | ||
118 | { STB0899_GPIO35CFG , 0x82 }, | ||
119 | { STB0899_GPIO36CFG , 0x82 }, | ||
120 | { STB0899_GPIO37CFG , 0x82 }, | ||
121 | { STB0899_GPIO38CFG , 0x82 }, | ||
122 | { STB0899_GPIO39CFG , 0x82 }, | ||
123 | { STB0899_NCOARSE , 0x17 }, /* 0x15 = 27 Mhz Clock, F/3 = 198MHz, F/6 = 99MHz */ | ||
124 | { STB0899_SYNTCTRL , 0x02 }, /* 0x00 = CLK from CLKI, 0x02 = CLK from XTALI */ | ||
125 | { STB0899_FILTCTRL , 0x00 }, | ||
126 | { STB0899_SYSCTRL , 0x01 }, | ||
127 | { STB0899_STOPCLK1 , 0x20 }, | ||
128 | { STB0899_STOPCLK2 , 0x00 }, | ||
129 | { STB0899_INTBUFSTATUS , 0x00 }, | ||
130 | { STB0899_INTBUFCTRL , 0x0a }, | ||
131 | { 0xffff , 0xff }, | ||
132 | }; | ||
133 | |||
134 | static const struct stb0899_s1_reg vp1041_stb0899_s1_init_3[] = { | ||
135 | { STB0899_DEMOD , 0x00 }, | ||
136 | { STB0899_RCOMPC , 0xc9 }, | ||
137 | { STB0899_AGC1CN , 0x01 }, | ||
138 | { STB0899_AGC1REF , 0x10 }, | ||
139 | { STB0899_RTC , 0x23 }, | ||
140 | { STB0899_TMGCFG , 0x4e }, | ||
141 | { STB0899_AGC2REF , 0x34 }, | ||
142 | { STB0899_TLSR , 0x84 }, | ||
143 | { STB0899_CFD , 0xf7 }, | ||
144 | { STB0899_ACLC , 0x87 }, | ||
145 | { STB0899_BCLC , 0x94 }, | ||
146 | { STB0899_EQON , 0x41 }, | ||
147 | { STB0899_LDT , 0xf1 }, | ||
148 | { STB0899_LDT2 , 0xe3 }, | ||
149 | { STB0899_EQUALREF , 0xb4 }, | ||
150 | { STB0899_TMGRAMP , 0x10 }, | ||
151 | { STB0899_TMGTHD , 0x30 }, | ||
152 | { STB0899_IDCCOMP , 0xfd }, | ||
153 | { STB0899_QDCCOMP , 0xff }, | ||
154 | { STB0899_POWERI , 0x0c }, | ||
155 | { STB0899_POWERQ , 0x0f }, | ||
156 | { STB0899_RCOMP , 0x6c }, | ||
157 | { STB0899_AGCIQIN , 0x80 }, | ||
158 | { STB0899_AGC2I1 , 0x06 }, | ||
159 | { STB0899_AGC2I2 , 0x00 }, | ||
160 | { STB0899_TLIR , 0x30 }, | ||
161 | { STB0899_RTF , 0x7f }, | ||
162 | { STB0899_DSTATUS , 0x00 }, | ||
163 | { STB0899_LDI , 0xbc }, | ||
164 | { STB0899_CFRM , 0xea }, | ||
165 | { STB0899_CFRL , 0x31 }, | ||
166 | { STB0899_NIRM , 0x2b }, | ||
167 | { STB0899_NIRL , 0x80 }, | ||
168 | { STB0899_ISYMB , 0x1d }, | ||
169 | { STB0899_QSYMB , 0xa6 }, | ||
170 | { STB0899_SFRH , 0x2f }, | ||
171 | { STB0899_SFRM , 0x68 }, | ||
172 | { STB0899_SFRL , 0x40 }, | ||
173 | { STB0899_SFRUPH , 0x2f }, | ||
174 | { STB0899_SFRUPM , 0x68 }, | ||
175 | { STB0899_SFRUPL , 0x40 }, | ||
176 | { STB0899_EQUAI1 , 0x02 }, | ||
177 | { STB0899_EQUAQ1 , 0xff }, | ||
178 | { STB0899_EQUAI2 , 0x04 }, | ||
179 | { STB0899_EQUAQ2 , 0x05 }, | ||
180 | { STB0899_EQUAI3 , 0x02 }, | ||
181 | { STB0899_EQUAQ3 , 0xfd }, | ||
182 | { STB0899_EQUAI4 , 0x03 }, | ||
183 | { STB0899_EQUAQ4 , 0x07 }, | ||
184 | { STB0899_EQUAI5 , 0x08 }, | ||
185 | { STB0899_EQUAQ5 , 0xf5 }, | ||
186 | { STB0899_DSTATUS2 , 0x00 }, | ||
187 | { STB0899_VSTATUS , 0x00 }, | ||
188 | { STB0899_VERROR , 0x86 }, | ||
189 | { STB0899_IQSWAP , 0x2a }, | ||
190 | { STB0899_ECNT1M , 0x00 }, | ||
191 | { STB0899_ECNT1L , 0x00 }, | ||
192 | { STB0899_ECNT2M , 0x00 }, | ||
193 | { STB0899_ECNT2L , 0x00 }, | ||
194 | { STB0899_ECNT3M , 0x0a }, | ||
195 | { STB0899_ECNT3L , 0xad }, | ||
196 | { STB0899_FECAUTO1 , 0x06 }, | ||
197 | { STB0899_FECM , 0x01 }, | ||
198 | { STB0899_VTH12 , 0xb0 }, | ||
199 | { STB0899_VTH23 , 0x7a }, | ||
200 | { STB0899_VTH34 , 0x58 }, | ||
201 | { STB0899_VTH56 , 0x38 }, | ||
202 | { STB0899_VTH67 , 0x34 }, | ||
203 | { STB0899_VTH78 , 0x24 }, | ||
204 | { STB0899_PRVIT , 0xff }, | ||
205 | { STB0899_VITSYNC , 0x19 }, | ||
206 | { STB0899_RSULC , 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */ | ||
207 | { STB0899_TSULC , 0x42 }, | ||
208 | { STB0899_RSLLC , 0x41 }, | ||
209 | { STB0899_TSLPL , 0x12 }, | ||
210 | { STB0899_TSCFGH , 0x0c }, | ||
211 | { STB0899_TSCFGM , 0x00 }, | ||
212 | { STB0899_TSCFGL , 0x00 }, | ||
213 | { STB0899_TSOUT , 0x69 }, /* 0x0d for CAM */ | ||
214 | { STB0899_RSSYNCDEL , 0x00 }, | ||
215 | { STB0899_TSINHDELH , 0x02 }, | ||
216 | { STB0899_TSINHDELM , 0x00 }, | ||
217 | { STB0899_TSINHDELL , 0x00 }, | ||
218 | { STB0899_TSLLSTKM , 0x1b }, | ||
219 | { STB0899_TSLLSTKL , 0xb3 }, | ||
220 | { STB0899_TSULSTKM , 0x00 }, | ||
221 | { STB0899_TSULSTKL , 0x00 }, | ||
222 | { STB0899_PCKLENUL , 0xbc }, | ||
223 | { STB0899_PCKLENLL , 0xcc }, | ||
224 | { STB0899_RSPCKLEN , 0xbd }, | ||
225 | { STB0899_TSSTATUS , 0x90 }, | ||
226 | { STB0899_ERRCTRL1 , 0xb6 }, | ||
227 | { STB0899_ERRCTRL2 , 0x95 }, | ||
228 | { STB0899_ERRCTRL3 , 0x8d }, | ||
229 | { STB0899_DMONMSK1 , 0x27 }, | ||
230 | { STB0899_DMONMSK0 , 0x03 }, | ||
231 | { STB0899_DEMAPVIT , 0x5c }, | ||
232 | { STB0899_PLPARM , 0x19 }, | ||
233 | { STB0899_PDELCTRL , 0x48 }, | ||
234 | { STB0899_PDELCTRL2 , 0x00 }, | ||
235 | { STB0899_BBHCTRL1 , 0x00 }, | ||
236 | { STB0899_BBHCTRL2 , 0x00 }, | ||
237 | { STB0899_HYSTTHRESH , 0x77 }, | ||
238 | { STB0899_MATCSTM , 0x00 }, | ||
239 | { STB0899_MATCSTL , 0x00 }, | ||
240 | { STB0899_UPLCSTM , 0x00 }, | ||
241 | { STB0899_UPLCSTL , 0x00 }, | ||
242 | { STB0899_DFLCSTM , 0x00 }, | ||
243 | { STB0899_DFLCSTL , 0x00 }, | ||
244 | { STB0899_SYNCCST , 0x00 }, | ||
245 | { STB0899_SYNCDCSTM , 0x00 }, | ||
246 | { STB0899_SYNCDCSTL , 0x00 }, | ||
247 | { STB0899_ISI_ENTRY , 0x00 }, | ||
248 | { STB0899_ISI_BIT_EN , 0x00 }, | ||
249 | { STB0899_MATSTRM , 0xf0 }, | ||
250 | { STB0899_MATSTRL , 0x02 }, | ||
251 | { STB0899_UPLSTRM , 0x45 }, | ||
252 | { STB0899_UPLSTRL , 0x60 }, | ||
253 | { STB0899_DFLSTRM , 0xe3 }, | ||
254 | { STB0899_DFLSTRL , 0x00 }, | ||
255 | { STB0899_SYNCSTR , 0x47 }, | ||
256 | { STB0899_SYNCDSTRM , 0x05 }, | ||
257 | { STB0899_SYNCDSTRL , 0x18 }, | ||
258 | { STB0899_CFGPDELSTATUS1 , 0x19 }, | ||
259 | { STB0899_CFGPDELSTATUS2 , 0x2b }, | ||
260 | { STB0899_BBFERRORM , 0x00 }, | ||
261 | { STB0899_BBFERRORL , 0x01 }, | ||
262 | { STB0899_UPKTERRORM , 0x00 }, | ||
263 | { STB0899_UPKTERRORL , 0x00 }, | ||
264 | { 0xffff , 0xff }, | ||
265 | }; | ||
266 | |||
267 | struct stb0899_config vp1041_stb0899_config = { | ||
268 | .init_dev = vp1041_stb0899_s1_init_1, | ||
269 | .init_s2_demod = stb0899_s2_init_2, | ||
270 | .init_s1_demod = vp1041_stb0899_s1_init_3, | ||
271 | .init_s2_fec = stb0899_s2_init_4, | ||
272 | .init_tst = stb0899_s1_init_5, | ||
273 | |||
274 | .demod_address = 0x68, /* 0xd0 >> 1 */ | ||
275 | |||
276 | .xtal_freq = 27000000, | ||
277 | .inversion = IQ_SWAP_ON, /* 1 */ | ||
278 | |||
279 | .lo_clk = 76500000, | ||
280 | .hi_clk = 99000000, | ||
281 | |||
282 | .esno_ave = STB0899_DVBS2_ESNO_AVE, | ||
283 | .esno_quant = STB0899_DVBS2_ESNO_QUANT, | ||
284 | .avframes_coarse = STB0899_DVBS2_AVFRAMES_COARSE, | ||
285 | .avframes_fine = STB0899_DVBS2_AVFRAMES_FINE, | ||
286 | .miss_threshold = STB0899_DVBS2_MISS_THRESHOLD, | ||
287 | .uwp_threshold_acq = STB0899_DVBS2_UWP_THRESHOLD_ACQ, | ||
288 | .uwp_threshold_track = STB0899_DVBS2_UWP_THRESHOLD_TRACK, | ||
289 | .uwp_threshold_sof = STB0899_DVBS2_UWP_THRESHOLD_SOF, | ||
290 | .sof_search_timeout = STB0899_DVBS2_SOF_SEARCH_TIMEOUT, | ||
291 | |||
292 | .btr_nco_bits = STB0899_DVBS2_BTR_NCO_BITS, | ||
293 | .btr_gain_shift_offset = STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET, | ||
294 | .crl_nco_bits = STB0899_DVBS2_CRL_NCO_BITS, | ||
295 | .ldpc_max_iter = STB0899_DVBS2_LDPC_MAX_ITER, | ||
296 | |||
297 | .tuner_get_frequency = stb6100_get_frequency, | ||
298 | .tuner_set_frequency = stb6100_set_frequency, | ||
299 | .tuner_set_bandwidth = stb6100_set_bandwidth, | ||
300 | .tuner_get_bandwidth = stb6100_get_bandwidth, | ||
301 | .tuner_set_rfsiggain = NULL, | ||
302 | }; | ||
303 | |||
304 | struct stb6100_config vp1041_stb6100_config = { | ||
305 | .tuner_address = 0x60, | ||
306 | .refclock = 27000000, | ||
307 | }; | ||
308 | |||
309 | static int vp1041_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe) | ||
310 | { | ||
311 | struct i2c_adapter *adapter = &mantis->adapter; | ||
312 | |||
313 | int err = 0; | ||
314 | |||
315 | err = mantis_frontend_power(mantis, POWER_ON); | ||
316 | if (err == 0) { | ||
317 | mantis_frontend_soft_reset(mantis); | ||
318 | msleep(250); | ||
319 | mantis->fe = stb0899_attach(&vp1041_stb0899_config, adapter); | ||
320 | if (mantis->fe) { | ||
321 | dprintk(MANTIS_ERROR, 1, | ||
322 | "found STB0899 DVB-S/DVB-S2 frontend @0x%02x", | ||
323 | vp1041_stb0899_config.demod_address); | ||
324 | |||
325 | if (stb6100_attach(mantis->fe, &vp1041_stb6100_config, adapter)) { | ||
326 | if (!lnbp21_attach(mantis->fe, adapter, 0, 0)) | ||
327 | dprintk(MANTIS_ERROR, 1, "No LNBP21 found!"); | ||
328 | } | ||
329 | } else { | ||
330 | return -EREMOTEIO; | ||
331 | } | ||
332 | } else { | ||
333 | dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>", | ||
334 | adapter->name, | ||
335 | err); | ||
336 | |||
337 | return -EIO; | ||
338 | } | ||
339 | |||
340 | |||
341 | dprintk(MANTIS_ERROR, 1, "Done!"); | ||
342 | |||
343 | return 0; | ||
344 | } | ||
345 | |||
346 | struct mantis_hwconfig vp1041_config = { | ||
347 | .model_name = MANTIS_MODEL_NAME, | ||
348 | .dev_type = MANTIS_DEV_TYPE, | ||
349 | .ts_size = MANTIS_TS_188, | ||
350 | |||
351 | .baud_rate = MANTIS_BAUD_9600, | ||
352 | .parity = MANTIS_PARITY_NONE, | ||
353 | .bytes = 0, | ||
354 | |||
355 | .frontend_init = vp1041_frontend_init, | ||
356 | .power = GPIF_A12, | ||
357 | .reset = GPIF_A13, | ||
358 | }; | ||
diff --git a/drivers/media/dvb/mantis/mantis_vp1041.h b/drivers/media/dvb/mantis/mantis_vp1041.h new file mode 100644 index 000000000000..1ae5b3de8081 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_vp1041.h | |||
@@ -0,0 +1,33 @@ | |||
1 | /* | ||
2 | Mantis VP-1041 driver | ||
3 | |||
4 | Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #ifndef __MANTIS_VP1041_H | ||
22 | #define __MANTIS_VP1041_H | ||
23 | |||
24 | #include "mantis_common.h" | ||
25 | |||
26 | #define MANTIS_VP_1041_DVB_S2 0x0031 | ||
27 | #define SKYSTAR_HD2_10 0x0001 | ||
28 | #define SKYSTAR_HD2_20 0x0003 | ||
29 | #define CINERGY_S2_PCI_HD 0x1179 | ||
30 | |||
31 | extern struct mantis_hwconfig vp1041_config; | ||
32 | |||
33 | #endif /* __MANTIS_VP1041_H */ | ||
diff --git a/drivers/media/dvb/mantis/mantis_vp2033.c b/drivers/media/dvb/mantis/mantis_vp2033.c new file mode 100644 index 000000000000..10ce81790a8c --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_vp2033.c | |||
@@ -0,0 +1,187 @@ | |||
1 | /* | ||
2 | Mantis VP-2033 driver | ||
3 | |||
4 | Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/signal.h> | ||
22 | #include <linux/sched.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | |||
25 | #include "dmxdev.h" | ||
26 | #include "dvbdev.h" | ||
27 | #include "dvb_demux.h" | ||
28 | #include "dvb_frontend.h" | ||
29 | #include "dvb_net.h" | ||
30 | |||
31 | #include "tda1002x.h" | ||
32 | #include "mantis_common.h" | ||
33 | #include "mantis_ioc.h" | ||
34 | #include "mantis_dvb.h" | ||
35 | #include "mantis_vp2033.h" | ||
36 | |||
37 | #define MANTIS_MODEL_NAME "VP-2033" | ||
38 | #define MANTIS_DEV_TYPE "DVB-C" | ||
39 | |||
40 | struct tda1002x_config vp2033_tda1002x_cu1216_config = { | ||
41 | .demod_address = 0x18 >> 1, | ||
42 | .invert = 1, | ||
43 | }; | ||
44 | |||
45 | struct tda10023_config vp2033_tda10023_cu1216_config = { | ||
46 | .demod_address = 0x18 >> 1, | ||
47 | .invert = 1, | ||
48 | }; | ||
49 | |||
50 | static u8 read_pwm(struct mantis_pci *mantis) | ||
51 | { | ||
52 | struct i2c_adapter *adapter = &mantis->adapter; | ||
53 | |||
54 | u8 b = 0xff; | ||
55 | u8 pwm; | ||
56 | struct i2c_msg msg[] = { | ||
57 | {.addr = 0x50, .flags = 0, .buf = &b, .len = 1}, | ||
58 | {.addr = 0x50, .flags = I2C_M_RD, .buf = &pwm, .len = 1} | ||
59 | }; | ||
60 | |||
61 | if ((i2c_transfer(adapter, msg, 2) != 2) | ||
62 | || (pwm == 0xff)) | ||
63 | pwm = 0x48; | ||
64 | |||
65 | return pwm; | ||
66 | } | ||
67 | |||
68 | static int tda1002x_cu1216_tuner_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) | ||
69 | { | ||
70 | struct mantis_pci *mantis = fe->dvb->priv; | ||
71 | struct i2c_adapter *adapter = &mantis->adapter; | ||
72 | |||
73 | u8 buf[6]; | ||
74 | struct i2c_msg msg = {.addr = 0x60, .flags = 0, .buf = buf, .len = sizeof(buf)}; | ||
75 | int i; | ||
76 | |||
77 | #define CU1216_IF 36125000 | ||
78 | #define TUNER_MUL 62500 | ||
79 | |||
80 | u32 div = (params->frequency + CU1216_IF + TUNER_MUL / 2) / TUNER_MUL; | ||
81 | |||
82 | buf[0] = (div >> 8) & 0x7f; | ||
83 | buf[1] = div & 0xff; | ||
84 | buf[2] = 0xce; | ||
85 | buf[3] = (params->frequency < 150000000 ? 0x01 : | ||
86 | params->frequency < 445000000 ? 0x02 : 0x04); | ||
87 | buf[4] = 0xde; | ||
88 | buf[5] = 0x20; | ||
89 | |||
90 | if (fe->ops.i2c_gate_ctrl) | ||
91 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
92 | |||
93 | if (i2c_transfer(adapter, &msg, 1) != 1) | ||
94 | return -EIO; | ||
95 | |||
96 | /* wait for the pll lock */ | ||
97 | msg.flags = I2C_M_RD; | ||
98 | msg.len = 1; | ||
99 | for (i = 0; i < 20; i++) { | ||
100 | if (fe->ops.i2c_gate_ctrl) | ||
101 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
102 | |||
103 | if (i2c_transfer(adapter, &msg, 1) == 1 && (buf[0] & 0x40)) | ||
104 | break; | ||
105 | |||
106 | msleep(10); | ||
107 | } | ||
108 | |||
109 | /* switch the charge pump to the lower current */ | ||
110 | msg.flags = 0; | ||
111 | msg.len = 2; | ||
112 | msg.buf = &buf[2]; | ||
113 | buf[2] &= ~0x40; | ||
114 | if (fe->ops.i2c_gate_ctrl) | ||
115 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
116 | |||
117 | if (i2c_transfer(adapter, &msg, 1) != 1) | ||
118 | return -EIO; | ||
119 | |||
120 | return 0; | ||
121 | } | ||
122 | |||
123 | static int vp2033_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe) | ||
124 | { | ||
125 | struct i2c_adapter *adapter = &mantis->adapter; | ||
126 | |||
127 | int err = 0; | ||
128 | |||
129 | err = mantis_frontend_power(mantis, POWER_ON); | ||
130 | if (err == 0) { | ||
131 | mantis_frontend_soft_reset(mantis); | ||
132 | msleep(250); | ||
133 | |||
134 | dprintk(MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)"); | ||
135 | fe = tda10021_attach(&vp2033_tda1002x_cu1216_config, | ||
136 | adapter, | ||
137 | read_pwm(mantis)); | ||
138 | |||
139 | if (fe) { | ||
140 | dprintk(MANTIS_ERROR, 1, | ||
141 | "found Philips CU1216 DVB-C frontend (TDA10021) @ 0x%02x", | ||
142 | vp2033_tda1002x_cu1216_config.demod_address); | ||
143 | } else { | ||
144 | fe = tda10023_attach(&vp2033_tda10023_cu1216_config, | ||
145 | adapter, | ||
146 | read_pwm(mantis)); | ||
147 | |||
148 | if (fe) { | ||
149 | dprintk(MANTIS_ERROR, 1, | ||
150 | "found Philips CU1216 DVB-C frontend (TDA10023) @ 0x%02x", | ||
151 | vp2033_tda1002x_cu1216_config.demod_address); | ||
152 | } | ||
153 | } | ||
154 | |||
155 | if (fe) { | ||
156 | fe->ops.tuner_ops.set_params = tda1002x_cu1216_tuner_set; | ||
157 | dprintk(MANTIS_ERROR, 1, "Mantis DVB-C Philips CU1216 frontend attach success"); | ||
158 | } else { | ||
159 | return -1; | ||
160 | } | ||
161 | } else { | ||
162 | dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>", | ||
163 | adapter->name, | ||
164 | err); | ||
165 | |||
166 | return -EIO; | ||
167 | } | ||
168 | |||
169 | mantis->fe = fe; | ||
170 | dprintk(MANTIS_DEBUG, 1, "Done!"); | ||
171 | |||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | struct mantis_hwconfig vp2033_config = { | ||
176 | .model_name = MANTIS_MODEL_NAME, | ||
177 | .dev_type = MANTIS_DEV_TYPE, | ||
178 | .ts_size = MANTIS_TS_204, | ||
179 | |||
180 | .baud_rate = MANTIS_BAUD_9600, | ||
181 | .parity = MANTIS_PARITY_NONE, | ||
182 | .bytes = 0, | ||
183 | |||
184 | .frontend_init = vp2033_frontend_init, | ||
185 | .power = GPIF_A12, | ||
186 | .reset = GPIF_A13, | ||
187 | }; | ||
diff --git a/drivers/media/dvb/mantis/mantis_vp2033.h b/drivers/media/dvb/mantis/mantis_vp2033.h new file mode 100644 index 000000000000..c55242b79d54 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_vp2033.h | |||
@@ -0,0 +1,30 @@ | |||
1 | /* | ||
2 | Mantis VP-2033 driver | ||
3 | |||
4 | Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #ifndef __MANTIS_VP2033_H | ||
22 | #define __MANTIS_VP2033_H | ||
23 | |||
24 | #include "mantis_common.h" | ||
25 | |||
26 | #define MANTIS_VP_2033_DVB_C 0x0008 | ||
27 | |||
28 | extern struct mantis_hwconfig vp2033_config; | ||
29 | |||
30 | #endif /* __MANTIS_VP2033_H */ | ||
diff --git a/drivers/media/dvb/mantis/mantis_vp2040.c b/drivers/media/dvb/mantis/mantis_vp2040.c new file mode 100644 index 000000000000..a7ca233e800b --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_vp2040.c | |||
@@ -0,0 +1,186 @@ | |||
1 | /* | ||
2 | Mantis VP-2040 driver | ||
3 | |||
4 | Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/signal.h> | ||
22 | #include <linux/sched.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | |||
25 | #include "dmxdev.h" | ||
26 | #include "dvbdev.h" | ||
27 | #include "dvb_demux.h" | ||
28 | #include "dvb_frontend.h" | ||
29 | #include "dvb_net.h" | ||
30 | |||
31 | #include "tda1002x.h" | ||
32 | #include "mantis_common.h" | ||
33 | #include "mantis_ioc.h" | ||
34 | #include "mantis_dvb.h" | ||
35 | #include "mantis_vp2040.h" | ||
36 | |||
37 | #define MANTIS_MODEL_NAME "VP-2040" | ||
38 | #define MANTIS_DEV_TYPE "DVB-C" | ||
39 | |||
40 | struct tda1002x_config vp2040_tda1002x_cu1216_config = { | ||
41 | .demod_address = 0x18 >> 1, | ||
42 | .invert = 1, | ||
43 | }; | ||
44 | |||
45 | struct tda10023_config vp2040_tda10023_cu1216_config = { | ||
46 | .demod_address = 0x18 >> 1, | ||
47 | .invert = 1, | ||
48 | }; | ||
49 | |||
50 | static int tda1002x_cu1216_tuner_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) | ||
51 | { | ||
52 | struct mantis_pci *mantis = fe->dvb->priv; | ||
53 | struct i2c_adapter *adapter = &mantis->adapter; | ||
54 | |||
55 | u8 buf[6]; | ||
56 | struct i2c_msg msg = {.addr = 0x60, .flags = 0, .buf = buf, .len = sizeof(buf)}; | ||
57 | int i; | ||
58 | |||
59 | #define CU1216_IF 36125000 | ||
60 | #define TUNER_MUL 62500 | ||
61 | |||
62 | u32 div = (params->frequency + CU1216_IF + TUNER_MUL / 2) / TUNER_MUL; | ||
63 | |||
64 | buf[0] = (div >> 8) & 0x7f; | ||
65 | buf[1] = div & 0xff; | ||
66 | buf[2] = 0xce; | ||
67 | buf[3] = (params->frequency < 150000000 ? 0x01 : | ||
68 | params->frequency < 445000000 ? 0x02 : 0x04); | ||
69 | buf[4] = 0xde; | ||
70 | buf[5] = 0x20; | ||
71 | |||
72 | if (fe->ops.i2c_gate_ctrl) | ||
73 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
74 | |||
75 | if (i2c_transfer(adapter, &msg, 1) != 1) | ||
76 | return -EIO; | ||
77 | |||
78 | /* wait for the pll lock */ | ||
79 | msg.flags = I2C_M_RD; | ||
80 | msg.len = 1; | ||
81 | for (i = 0; i < 20; i++) { | ||
82 | if (fe->ops.i2c_gate_ctrl) | ||
83 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
84 | |||
85 | if (i2c_transfer(adapter, &msg, 1) == 1 && (buf[0] & 0x40)) | ||
86 | break; | ||
87 | |||
88 | msleep(10); | ||
89 | } | ||
90 | |||
91 | /* switch the charge pump to the lower current */ | ||
92 | msg.flags = 0; | ||
93 | msg.len = 2; | ||
94 | msg.buf = &buf[2]; | ||
95 | buf[2] &= ~0x40; | ||
96 | if (fe->ops.i2c_gate_ctrl) | ||
97 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
98 | |||
99 | if (i2c_transfer(adapter, &msg, 1) != 1) | ||
100 | return -EIO; | ||
101 | |||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | static u8 read_pwm(struct mantis_pci *mantis) | ||
106 | { | ||
107 | struct i2c_adapter *adapter = &mantis->adapter; | ||
108 | |||
109 | u8 b = 0xff; | ||
110 | u8 pwm; | ||
111 | struct i2c_msg msg[] = { | ||
112 | {.addr = 0x50, .flags = 0, .buf = &b, .len = 1}, | ||
113 | {.addr = 0x50, .flags = I2C_M_RD, .buf = &pwm, .len = 1} | ||
114 | }; | ||
115 | |||
116 | if ((i2c_transfer(adapter, msg, 2) != 2) | ||
117 | || (pwm == 0xff)) | ||
118 | pwm = 0x48; | ||
119 | |||
120 | return pwm; | ||
121 | } | ||
122 | |||
123 | static int vp2040_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe) | ||
124 | { | ||
125 | struct i2c_adapter *adapter = &mantis->adapter; | ||
126 | |||
127 | int err = 0; | ||
128 | |||
129 | err = mantis_frontend_power(mantis, POWER_ON); | ||
130 | if (err == 0) { | ||
131 | mantis_frontend_soft_reset(mantis); | ||
132 | msleep(250); | ||
133 | |||
134 | dprintk(MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)"); | ||
135 | fe = tda10021_attach(&vp2040_tda1002x_cu1216_config, | ||
136 | adapter, | ||
137 | read_pwm(mantis)); | ||
138 | |||
139 | if (fe) { | ||
140 | dprintk(MANTIS_ERROR, 1, | ||
141 | "found Philips CU1216 DVB-C frontend (TDA10021) @ 0x%02x", | ||
142 | vp2040_tda1002x_cu1216_config.demod_address); | ||
143 | } else { | ||
144 | fe = tda10023_attach(&vp2040_tda10023_cu1216_config, | ||
145 | adapter, | ||
146 | read_pwm(mantis)); | ||
147 | |||
148 | if (fe) { | ||
149 | dprintk(MANTIS_ERROR, 1, | ||
150 | "found Philips CU1216 DVB-C frontend (TDA10023) @ 0x%02x", | ||
151 | vp2040_tda1002x_cu1216_config.demod_address); | ||
152 | } | ||
153 | } | ||
154 | |||
155 | if (fe) { | ||
156 | fe->ops.tuner_ops.set_params = tda1002x_cu1216_tuner_set; | ||
157 | dprintk(MANTIS_ERROR, 1, "Mantis DVB-C Philips CU1216 frontend attach success"); | ||
158 | } else { | ||
159 | return -1; | ||
160 | } | ||
161 | } else { | ||
162 | dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>", | ||
163 | adapter->name, | ||
164 | err); | ||
165 | |||
166 | return -EIO; | ||
167 | } | ||
168 | mantis->fe = fe; | ||
169 | dprintk(MANTIS_DEBUG, 1, "Done!"); | ||
170 | |||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | struct mantis_hwconfig vp2040_config = { | ||
175 | .model_name = MANTIS_MODEL_NAME, | ||
176 | .dev_type = MANTIS_DEV_TYPE, | ||
177 | .ts_size = MANTIS_TS_204, | ||
178 | |||
179 | .baud_rate = MANTIS_BAUD_9600, | ||
180 | .parity = MANTIS_PARITY_NONE, | ||
181 | .bytes = 0, | ||
182 | |||
183 | .frontend_init = vp2040_frontend_init, | ||
184 | .power = GPIF_A12, | ||
185 | .reset = GPIF_A13, | ||
186 | }; | ||
diff --git a/drivers/media/dvb/mantis/mantis_vp2040.h b/drivers/media/dvb/mantis/mantis_vp2040.h new file mode 100644 index 000000000000..d125e219b685 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_vp2040.h | |||
@@ -0,0 +1,32 @@ | |||
1 | /* | ||
2 | Mantis VP-2040 driver | ||
3 | |||
4 | Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #ifndef __MANTIS_VP2040_H | ||
22 | #define __MANTIS_VP2040_H | ||
23 | |||
24 | #include "mantis_common.h" | ||
25 | |||
26 | #define MANTIS_VP_2040_DVB_C 0x0043 | ||
27 | #define CINERGY_C 0x1178 | ||
28 | #define CABLESTAR_HD2 0x0002 | ||
29 | |||
30 | extern struct mantis_hwconfig vp2040_config; | ||
31 | |||
32 | #endif /* __MANTIS_VP2040_H */ | ||
diff --git a/drivers/media/dvb/mantis/mantis_vp3028.c b/drivers/media/dvb/mantis/mantis_vp3028.c new file mode 100644 index 000000000000..4155c838a18a --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_vp3028.c | |||
@@ -0,0 +1,38 @@ | |||
1 | /* | ||
2 | Mantis VP-3028 driver | ||
3 | |||
4 | Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include "mantis_common.h" | ||
22 | #include "mantis_vp3028.h" | ||
23 | |||
24 | struct zl10353_config mantis_vp3028_config = { | ||
25 | .demod_address = 0x0f, | ||
26 | }; | ||
27 | |||
28 | #define MANTIS_MODEL_NAME "VP-3028" | ||
29 | #define MANTIS_DEV_TYPE "DVB-T" | ||
30 | |||
31 | struct mantis_hwconfig vp3028_mantis_config = { | ||
32 | .model_name = MANTIS_MODEL_NAME, | ||
33 | .dev_type = MANTIS_DEV_TYPE, | ||
34 | .ts_size = MANTIS_TS_188, | ||
35 | .baud_rate = MANTIS_BAUD_9600, | ||
36 | .parity = MANTIS_PARITY_NONE, | ||
37 | .bytes = 0, | ||
38 | }; | ||
diff --git a/drivers/media/dvb/mantis/mantis_vp3028.h b/drivers/media/dvb/mantis/mantis_vp3028.h new file mode 100644 index 000000000000..b07be6adc522 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_vp3028.h | |||
@@ -0,0 +1,33 @@ | |||
1 | /* | ||
2 | Mantis VP-3028 driver | ||
3 | |||
4 | Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #ifndef __MANTIS_VP3028_H | ||
22 | #define __MANTIS_VP3028_H | ||
23 | |||
24 | #include "dvb_frontend.h" | ||
25 | #include "mantis_common.h" | ||
26 | #include "zl10353.h" | ||
27 | |||
28 | #define MANTIS_VP_3028_DVB_T 0x0028 | ||
29 | |||
30 | extern struct zl10353_config mantis_vp3028_config; | ||
31 | extern struct mantis_hwconfig vp3028_mantis_config; | ||
32 | |||
33 | #endif /* __MANTIS_VP3028_H */ | ||
diff --git a/drivers/media/dvb/mantis/mantis_vp3030.c b/drivers/media/dvb/mantis/mantis_vp3030.c new file mode 100644 index 000000000000..1f4334214953 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_vp3030.c | |||
@@ -0,0 +1,105 @@ | |||
1 | /* | ||
2 | Mantis VP-3030 driver | ||
3 | |||
4 | Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/signal.h> | ||
22 | #include <linux/sched.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | |||
25 | #include "dmxdev.h" | ||
26 | #include "dvbdev.h" | ||
27 | #include "dvb_demux.h" | ||
28 | #include "dvb_frontend.h" | ||
29 | #include "dvb_net.h" | ||
30 | |||
31 | #include "zl10353.h" | ||
32 | #include "tda665x.h" | ||
33 | #include "mantis_common.h" | ||
34 | #include "mantis_ioc.h" | ||
35 | #include "mantis_dvb.h" | ||
36 | #include "mantis_vp3030.h" | ||
37 | |||
38 | struct zl10353_config mantis_vp3030_config = { | ||
39 | .demod_address = 0x0f, | ||
40 | }; | ||
41 | |||
42 | struct tda665x_config env57h12d5_config = { | ||
43 | .name = "ENV57H12D5 (ET-50DT)", | ||
44 | .addr = 0x60, | ||
45 | .frequency_min = 47000000, | ||
46 | .frequency_max = 862000000, | ||
47 | .frequency_offst = 3616667, | ||
48 | .ref_multiplier = 6, /* 1/6 MHz */ | ||
49 | .ref_divider = 100000, /* 1/6 MHz */ | ||
50 | }; | ||
51 | |||
52 | #define MANTIS_MODEL_NAME "VP-3030" | ||
53 | #define MANTIS_DEV_TYPE "DVB-T" | ||
54 | |||
55 | |||
56 | static int vp3030_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe) | ||
57 | { | ||
58 | struct i2c_adapter *adapter = &mantis->adapter; | ||
59 | struct mantis_hwconfig *config = mantis->hwconfig; | ||
60 | int err = 0; | ||
61 | |||
62 | gpio_set_bits(mantis, config->reset, 0); | ||
63 | msleep(100); | ||
64 | err = mantis_frontend_power(mantis, POWER_ON); | ||
65 | msleep(100); | ||
66 | gpio_set_bits(mantis, config->reset, 1); | ||
67 | |||
68 | if (err == 0) { | ||
69 | msleep(250); | ||
70 | dprintk(MANTIS_ERROR, 1, "Probing for 10353 (DVB-T)"); | ||
71 | fe = zl10353_attach(&mantis_vp3030_config, adapter); | ||
72 | |||
73 | if (!fe) | ||
74 | return -1; | ||
75 | |||
76 | tda665x_attach(fe, &env57h12d5_config, adapter); | ||
77 | } else { | ||
78 | dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>", | ||
79 | adapter->name, | ||
80 | err); | ||
81 | |||
82 | return -EIO; | ||
83 | |||
84 | } | ||
85 | mantis->fe = fe; | ||
86 | dprintk(MANTIS_ERROR, 1, "Done!"); | ||
87 | |||
88 | return 0; | ||
89 | } | ||
90 | |||
91 | struct mantis_hwconfig vp3030_config = { | ||
92 | .model_name = MANTIS_MODEL_NAME, | ||
93 | .dev_type = MANTIS_DEV_TYPE, | ||
94 | .ts_size = MANTIS_TS_188, | ||
95 | |||
96 | .baud_rate = MANTIS_BAUD_9600, | ||
97 | .parity = MANTIS_PARITY_NONE, | ||
98 | .bytes = 0, | ||
99 | |||
100 | .frontend_init = vp3030_frontend_init, | ||
101 | .power = GPIF_A12, | ||
102 | .reset = GPIF_A13, | ||
103 | |||
104 | .i2c_mode = MANTIS_BYTE_MODE | ||
105 | }; | ||
diff --git a/drivers/media/dvb/mantis/mantis_vp3030.h b/drivers/media/dvb/mantis/mantis_vp3030.h new file mode 100644 index 000000000000..5f12c4266277 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_vp3030.h | |||
@@ -0,0 +1,30 @@ | |||
1 | /* | ||
2 | Mantis VP-3030 driver | ||
3 | |||
4 | Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #ifndef __MANTIS_VP3030_H | ||
22 | #define __MANTIS_VP3030_H | ||
23 | |||
24 | #include "mantis_common.h" | ||
25 | |||
26 | #define MANTIS_VP_3030_DVB_T 0x0024 | ||
27 | |||
28 | extern struct mantis_hwconfig vp3030_config; | ||
29 | |||
30 | #endif /* __MANTIS_VP3030_H */ | ||
diff --git a/drivers/media/dvb/siano/smsdvb.c b/drivers/media/dvb/siano/smsdvb.c index 266033ae2784..68bf9fbd8fed 100644 --- a/drivers/media/dvb/siano/smsdvb.c +++ b/drivers/media/dvb/siano/smsdvb.c | |||
@@ -662,7 +662,7 @@ adapter_error: | |||
662 | return rc; | 662 | return rc; |
663 | } | 663 | } |
664 | 664 | ||
665 | int smsdvb_module_init(void) | 665 | static int __init smsdvb_module_init(void) |
666 | { | 666 | { |
667 | int rc; | 667 | int rc; |
668 | 668 | ||
@@ -676,7 +676,7 @@ int smsdvb_module_init(void) | |||
676 | return rc; | 676 | return rc; |
677 | } | 677 | } |
678 | 678 | ||
679 | void smsdvb_module_exit(void) | 679 | static void __exit smsdvb_module_exit(void) |
680 | { | 680 | { |
681 | smscore_unregister_hotplug(smsdvb_hotplug); | 681 | smscore_unregister_hotplug(smsdvb_hotplug); |
682 | 682 | ||
diff --git a/drivers/media/dvb/siano/smssdio.c b/drivers/media/dvb/siano/smssdio.c index 24206cbda264..195244a3e69b 100644 --- a/drivers/media/dvb/siano/smssdio.c +++ b/drivers/media/dvb/siano/smssdio.c | |||
@@ -48,7 +48,7 @@ | |||
48 | #define SMSSDIO_INT 0x04 | 48 | #define SMSSDIO_INT 0x04 |
49 | #define SMSSDIO_BLOCK_SIZE 128 | 49 | #define SMSSDIO_BLOCK_SIZE 128 |
50 | 50 | ||
51 | static const struct sdio_device_id smssdio_ids[] = { | 51 | static const struct sdio_device_id smssdio_ids[] __devinitconst = { |
52 | {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_STELLAR), | 52 | {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_STELLAR), |
53 | .driver_data = SMS1XXX_BOARD_SIANO_STELLAR}, | 53 | .driver_data = SMS1XXX_BOARD_SIANO_STELLAR}, |
54 | {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_NOVA_A0), | 54 | {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_NOVA_A0), |
@@ -222,7 +222,7 @@ static void smssdio_interrupt(struct sdio_func *func) | |||
222 | smscore_onresponse(smsdev->coredev, cb); | 222 | smscore_onresponse(smsdev->coredev, cb); |
223 | } | 223 | } |
224 | 224 | ||
225 | static int smssdio_probe(struct sdio_func *func, | 225 | static int __devinit smssdio_probe(struct sdio_func *func, |
226 | const struct sdio_device_id *id) | 226 | const struct sdio_device_id *id) |
227 | { | 227 | { |
228 | int ret; | 228 | int ret; |
@@ -338,7 +338,7 @@ static struct sdio_driver smssdio_driver = { | |||
338 | /* Module functions */ | 338 | /* Module functions */ |
339 | /*******************************************************************/ | 339 | /*******************************************************************/ |
340 | 340 | ||
341 | int smssdio_module_init(void) | 341 | static int __init smssdio_module_init(void) |
342 | { | 342 | { |
343 | int ret = 0; | 343 | int ret = 0; |
344 | 344 | ||
@@ -350,7 +350,7 @@ int smssdio_module_init(void) | |||
350 | return ret; | 350 | return ret; |
351 | } | 351 | } |
352 | 352 | ||
353 | void smssdio_module_exit(void) | 353 | static void __exit smssdio_module_exit(void) |
354 | { | 354 | { |
355 | sdio_unregister_driver(&smssdio_driver); | 355 | sdio_unregister_driver(&smssdio_driver); |
356 | } | 356 | } |
diff --git a/drivers/media/dvb/siano/smsusb.c b/drivers/media/dvb/siano/smsusb.c index 8f88a586b0dd..5eac27287d9c 100644 --- a/drivers/media/dvb/siano/smsusb.c +++ b/drivers/media/dvb/siano/smsusb.c | |||
@@ -390,7 +390,7 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id) | |||
390 | return rc; | 390 | return rc; |
391 | } | 391 | } |
392 | 392 | ||
393 | static int smsusb_probe(struct usb_interface *intf, | 393 | static int __devinit smsusb_probe(struct usb_interface *intf, |
394 | const struct usb_device_id *id) | 394 | const struct usb_device_id *id) |
395 | { | 395 | { |
396 | struct usb_device *udev = interface_to_usbdev(intf); | 396 | struct usb_device *udev = interface_to_usbdev(intf); |
@@ -484,7 +484,7 @@ static int smsusb_resume(struct usb_interface *intf) | |||
484 | return 0; | 484 | return 0; |
485 | } | 485 | } |
486 | 486 | ||
487 | struct usb_device_id smsusb_id_table[] = { | 487 | static const struct usb_device_id smsusb_id_table[] __devinitconst = { |
488 | { USB_DEVICE(0x187f, 0x0010), | 488 | { USB_DEVICE(0x187f, 0x0010), |
489 | .driver_info = SMS1XXX_BOARD_SIANO_STELLAR }, | 489 | .driver_info = SMS1XXX_BOARD_SIANO_STELLAR }, |
490 | { USB_DEVICE(0x187f, 0x0100), | 490 | { USB_DEVICE(0x187f, 0x0100), |
@@ -533,8 +533,18 @@ struct usb_device_id smsusb_id_table[] = { | |||
533 | .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, | 533 | .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, |
534 | { USB_DEVICE(0x2040, 0xb910), | 534 | { USB_DEVICE(0x2040, 0xb910), |
535 | .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, | 535 | .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, |
536 | { USB_DEVICE(0x2040, 0xb980), | ||
537 | .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, | ||
538 | { USB_DEVICE(0x2040, 0xb990), | ||
539 | .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, | ||
536 | { USB_DEVICE(0x2040, 0xc000), | 540 | { USB_DEVICE(0x2040, 0xc000), |
537 | .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, | 541 | .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, |
542 | { USB_DEVICE(0x2040, 0xc010), | ||
543 | .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, | ||
544 | { USB_DEVICE(0x2040, 0xc080), | ||
545 | .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, | ||
546 | { USB_DEVICE(0x2040, 0xc090), | ||
547 | .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, | ||
538 | { } /* Terminating entry */ | 548 | { } /* Terminating entry */ |
539 | }; | 549 | }; |
540 | 550 | ||
@@ -550,7 +560,7 @@ static struct usb_driver smsusb_driver = { | |||
550 | .resume = smsusb_resume, | 560 | .resume = smsusb_resume, |
551 | }; | 561 | }; |
552 | 562 | ||
553 | int smsusb_module_init(void) | 563 | static int __init smsusb_module_init(void) |
554 | { | 564 | { |
555 | int rc = usb_register(&smsusb_driver); | 565 | int rc = usb_register(&smsusb_driver); |
556 | if (rc) | 566 | if (rc) |
@@ -561,7 +571,7 @@ int smsusb_module_init(void) | |||
561 | return rc; | 571 | return rc; |
562 | } | 572 | } |
563 | 573 | ||
564 | void smsusb_module_exit(void) | 574 | static void __exit smsusb_module_exit(void) |
565 | { | 575 | { |
566 | /* Regular USB Cleanup */ | 576 | /* Regular USB Cleanup */ |
567 | usb_deregister(&smsusb_driver); | 577 | usb_deregister(&smsusb_driver); |
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index 7d193ebc0aea..9782e0593733 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c | |||
@@ -190,12 +190,13 @@ static int msp430_ir_init(struct budget_ci *budget_ci) | |||
190 | struct saa7146_dev *saa = budget_ci->budget.dev; | 190 | struct saa7146_dev *saa = budget_ci->budget.dev; |
191 | struct input_dev *input_dev = budget_ci->ir.dev; | 191 | struct input_dev *input_dev = budget_ci->ir.dev; |
192 | int error; | 192 | int error; |
193 | struct ir_scancode_table *ir_codes; | ||
194 | |||
193 | 195 | ||
194 | budget_ci->ir.dev = input_dev = input_allocate_device(); | 196 | budget_ci->ir.dev = input_dev = input_allocate_device(); |
195 | if (!input_dev) { | 197 | if (!input_dev) { |
196 | printk(KERN_ERR "budget_ci: IR interface initialisation failed\n"); | 198 | printk(KERN_ERR "budget_ci: IR interface initialisation failed\n"); |
197 | error = -ENOMEM; | 199 | return -ENOMEM; |
198 | goto out1; | ||
199 | } | 200 | } |
200 | 201 | ||
201 | snprintf(budget_ci->ir.name, sizeof(budget_ci->ir.name), | 202 | snprintf(budget_ci->ir.name, sizeof(budget_ci->ir.name), |
@@ -217,6 +218,11 @@ static int msp430_ir_init(struct budget_ci *budget_ci) | |||
217 | } | 218 | } |
218 | input_dev->dev.parent = &saa->pci->dev; | 219 | input_dev->dev.parent = &saa->pci->dev; |
219 | 220 | ||
221 | if (rc5_device < 0) | ||
222 | budget_ci->ir.rc5_device = IR_DEVICE_ANY; | ||
223 | else | ||
224 | budget_ci->ir.rc5_device = rc5_device; | ||
225 | |||
220 | /* Select keymap and address */ | 226 | /* Select keymap and address */ |
221 | switch (budget_ci->budget.dev->pci->subsystem_device) { | 227 | switch (budget_ci->budget.dev->pci->subsystem_device) { |
222 | case 0x100c: | 228 | case 0x100c: |
@@ -224,53 +230,34 @@ static int msp430_ir_init(struct budget_ci *budget_ci) | |||
224 | case 0x1011: | 230 | case 0x1011: |
225 | case 0x1012: | 231 | case 0x1012: |
226 | /* The hauppauge keymap is a superset of these remotes */ | 232 | /* The hauppauge keymap is a superset of these remotes */ |
227 | error = ir_input_init(input_dev, &budget_ci->ir.state, | 233 | ir_codes = &ir_codes_hauppauge_new_table; |
228 | IR_TYPE_RC5, &ir_codes_hauppauge_new_table); | ||
229 | if (error < 0) | ||
230 | goto out2; | ||
231 | 234 | ||
232 | if (rc5_device < 0) | 235 | if (rc5_device < 0) |
233 | budget_ci->ir.rc5_device = 0x1f; | 236 | budget_ci->ir.rc5_device = 0x1f; |
234 | else | ||
235 | budget_ci->ir.rc5_device = rc5_device; | ||
236 | break; | 237 | break; |
237 | case 0x1010: | 238 | case 0x1010: |
238 | case 0x1017: | 239 | case 0x1017: |
239 | case 0x101a: | 240 | case 0x101a: |
240 | /* for the Technotrend 1500 bundled remote */ | 241 | /* for the Technotrend 1500 bundled remote */ |
241 | error = ir_input_init(input_dev, &budget_ci->ir.state, | 242 | ir_codes = &ir_codes_tt_1500_table; |
242 | IR_TYPE_RC5, &ir_codes_tt_1500_table); | ||
243 | if (error < 0) | ||
244 | goto out2; | ||
245 | |||
246 | if (rc5_device < 0) | ||
247 | budget_ci->ir.rc5_device = IR_DEVICE_ANY; | ||
248 | else | ||
249 | budget_ci->ir.rc5_device = rc5_device; | ||
250 | break; | 243 | break; |
251 | default: | 244 | default: |
252 | /* unknown remote */ | 245 | /* unknown remote */ |
253 | error = ir_input_init(input_dev, &budget_ci->ir.state, | 246 | ir_codes = &ir_codes_budget_ci_old_table; |
254 | IR_TYPE_RC5, &ir_codes_budget_ci_old_table); | ||
255 | if (error < 0) | ||
256 | goto out2; | ||
257 | |||
258 | if (rc5_device < 0) | ||
259 | budget_ci->ir.rc5_device = IR_DEVICE_ANY; | ||
260 | else | ||
261 | budget_ci->ir.rc5_device = rc5_device; | ||
262 | break; | 247 | break; |
263 | } | 248 | } |
264 | 249 | ||
250 | ir_input_init(input_dev, &budget_ci->ir.state, IR_TYPE_RC5); | ||
251 | |||
265 | /* initialise the key-up timeout handler */ | 252 | /* initialise the key-up timeout handler */ |
266 | init_timer(&budget_ci->ir.timer_keyup); | 253 | init_timer(&budget_ci->ir.timer_keyup); |
267 | budget_ci->ir.timer_keyup.function = msp430_ir_keyup; | 254 | budget_ci->ir.timer_keyup.function = msp430_ir_keyup; |
268 | budget_ci->ir.timer_keyup.data = (unsigned long) &budget_ci->ir; | 255 | budget_ci->ir.timer_keyup.data = (unsigned long) &budget_ci->ir; |
269 | budget_ci->ir.last_raw = 0xffff; /* An impossible value */ | 256 | budget_ci->ir.last_raw = 0xffff; /* An impossible value */ |
270 | error = input_register_device(input_dev); | 257 | error = ir_input_register(input_dev, ir_codes); |
271 | if (error) { | 258 | if (error) { |
272 | 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); |
273 | goto out2; | 260 | return error; |
274 | } | 261 | } |
275 | 262 | ||
276 | /* note: these must be after input_register_device */ | 263 | /* note: these must be after input_register_device */ |
@@ -284,12 +271,6 @@ static int msp430_ir_init(struct budget_ci *budget_ci) | |||
284 | saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI); | 271 | saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI); |
285 | 272 | ||
286 | return 0; | 273 | return 0; |
287 | |||
288 | out2: | ||
289 | ir_input_free(input_dev); | ||
290 | input_free_device(input_dev); | ||
291 | out1: | ||
292 | return error; | ||
293 | } | 274 | } |
294 | 275 | ||
295 | static void msp430_ir_deinit(struct budget_ci *budget_ci) | 276 | static void msp430_ir_deinit(struct budget_ci *budget_ci) |
@@ -304,8 +285,7 @@ static void msp430_ir_deinit(struct budget_ci *budget_ci) | |||
304 | del_timer_sync(&dev->timer); | 285 | del_timer_sync(&dev->timer); |
305 | ir_input_nokey(dev, &budget_ci->ir.state); | 286 | ir_input_nokey(dev, &budget_ci->ir.state); |
306 | 287 | ||
307 | ir_input_free(dev); | 288 | ir_input_unregister(dev); |
308 | input_unregister_device(dev); | ||
309 | } | 289 | } |
310 | 290 | ||
311 | static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address) | 291 | static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address) |
diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig index 4c2b8a246772..3f40f375981b 100644 --- a/drivers/media/radio/Kconfig +++ b/drivers/media/radio/Kconfig | |||
@@ -215,13 +215,10 @@ config RADIO_MIROPCM20 | |||
215 | module will be called radio-miropcm20. | 215 | module will be called radio-miropcm20. |
216 | 216 | ||
217 | config RADIO_SF16FMI | 217 | config RADIO_SF16FMI |
218 | tristate "SF16FMI Radio" | 218 | tristate "SF16-FMI/SF16-FMP Radio" |
219 | depends on ISA && VIDEO_V4L2 | 219 | depends on ISA && VIDEO_V4L2 |
220 | ---help--- | 220 | ---help--- |
221 | Choose Y here if you have one of these FM radio cards. If you | 221 | Choose Y here if you have one of these FM radio cards. |
222 | compile the driver into the kernel and your card is not PnP one, you | ||
223 | have to add "sf16fm=<io>" to the kernel command line (I/O address is | ||
224 | 0x284 or 0x384). | ||
225 | 222 | ||
226 | In order to control your radio card, you will need to use programs | 223 | In order to control your radio card, you will need to use programs |
227 | that are compatible with the Video For Linux API. Information on | 224 | that are compatible with the Video For Linux API. Information on |
diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c index 35edee009ba8..5bf4985daede 100644 --- a/drivers/media/radio/radio-aimslab.c +++ b/drivers/media/radio/radio-aimslab.c | |||
@@ -268,6 +268,8 @@ static int vidioc_s_frequency(struct file *file, void *priv, | |||
268 | { | 268 | { |
269 | struct rtrack *rt = video_drvdata(file); | 269 | struct rtrack *rt = video_drvdata(file); |
270 | 270 | ||
271 | if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) | ||
272 | return -EINVAL; | ||
271 | rt_setfreq(rt, f->frequency); | 273 | rt_setfreq(rt, f->frequency); |
272 | return 0; | 274 | return 0; |
273 | } | 275 | } |
@@ -277,6 +279,8 @@ static int vidioc_g_frequency(struct file *file, void *priv, | |||
277 | { | 279 | { |
278 | struct rtrack *rt = video_drvdata(file); | 280 | struct rtrack *rt = video_drvdata(file); |
279 | 281 | ||
282 | if (f->tuner != 0) | ||
283 | return -EINVAL; | ||
280 | f->type = V4L2_TUNER_RADIO; | 284 | f->type = V4L2_TUNER_RADIO; |
281 | f->frequency = rt->curfreq; | 285 | f->frequency = rt->curfreq; |
282 | return 0; | 286 | return 0; |
diff --git a/drivers/media/radio/radio-aztech.c b/drivers/media/radio/radio-aztech.c index 8daf809eb01a..c22311393624 100644 --- a/drivers/media/radio/radio-aztech.c +++ b/drivers/media/radio/radio-aztech.c | |||
@@ -254,6 +254,8 @@ static int vidioc_s_frequency(struct file *file, void *priv, | |||
254 | { | 254 | { |
255 | struct aztech *az = video_drvdata(file); | 255 | struct aztech *az = video_drvdata(file); |
256 | 256 | ||
257 | if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) | ||
258 | return -EINVAL; | ||
257 | az_setfreq(az, f->frequency); | 259 | az_setfreq(az, f->frequency); |
258 | return 0; | 260 | return 0; |
259 | } | 261 | } |
@@ -263,6 +265,8 @@ static int vidioc_g_frequency(struct file *file, void *priv, | |||
263 | { | 265 | { |
264 | struct aztech *az = video_drvdata(file); | 266 | struct aztech *az = video_drvdata(file); |
265 | 267 | ||
268 | if (f->tuner != 0) | ||
269 | return -EINVAL; | ||
266 | f->type = V4L2_TUNER_RADIO; | 270 | f->type = V4L2_TUNER_RADIO; |
267 | f->frequency = az->curfreq; | 271 | f->frequency = az->curfreq; |
268 | return 0; | 272 | return 0; |
diff --git a/drivers/media/radio/radio-gemtek-pci.c b/drivers/media/radio/radio-gemtek-pci.c index c6cf11661868..000f4d34087c 100644 --- a/drivers/media/radio/radio-gemtek-pci.c +++ b/drivers/media/radio/radio-gemtek-pci.c | |||
@@ -240,6 +240,8 @@ static int vidioc_s_frequency(struct file *file, void *priv, | |||
240 | { | 240 | { |
241 | struct gemtek_pci *card = video_drvdata(file); | 241 | struct gemtek_pci *card = video_drvdata(file); |
242 | 242 | ||
243 | if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) | ||
244 | return -EINVAL; | ||
243 | if (f->frequency < GEMTEK_PCI_RANGE_LOW || | 245 | if (f->frequency < GEMTEK_PCI_RANGE_LOW || |
244 | f->frequency > GEMTEK_PCI_RANGE_HIGH) | 246 | f->frequency > GEMTEK_PCI_RANGE_HIGH) |
245 | return -EINVAL; | 247 | return -EINVAL; |
@@ -253,6 +255,8 @@ static int vidioc_g_frequency(struct file *file, void *priv, | |||
253 | { | 255 | { |
254 | struct gemtek_pci *card = video_drvdata(file); | 256 | struct gemtek_pci *card = video_drvdata(file); |
255 | 257 | ||
258 | if (f->tuner != 0) | ||
259 | return -EINVAL; | ||
256 | f->type = V4L2_TUNER_RADIO; | 260 | f->type = V4L2_TUNER_RADIO; |
257 | f->frequency = card->current_frequency; | 261 | f->frequency = card->current_frequency; |
258 | return 0; | 262 | return 0; |
diff --git a/drivers/media/radio/radio-maestro.c b/drivers/media/radio/radio-maestro.c index 64d737c35acf..f8213b7c8ddc 100644 --- a/drivers/media/radio/radio-maestro.c +++ b/drivers/media/radio/radio-maestro.c | |||
@@ -200,6 +200,8 @@ static int vidioc_s_frequency(struct file *file, void *priv, | |||
200 | { | 200 | { |
201 | struct maestro *dev = video_drvdata(file); | 201 | struct maestro *dev = video_drvdata(file); |
202 | 202 | ||
203 | if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) | ||
204 | return -EINVAL; | ||
203 | if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) | 205 | if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) |
204 | return -EINVAL; | 206 | return -EINVAL; |
205 | mutex_lock(&dev->lock); | 207 | mutex_lock(&dev->lock); |
@@ -213,6 +215,8 @@ static int vidioc_g_frequency(struct file *file, void *priv, | |||
213 | { | 215 | { |
214 | struct maestro *dev = video_drvdata(file); | 216 | struct maestro *dev = video_drvdata(file); |
215 | 217 | ||
218 | if (f->tuner != 0) | ||
219 | return -EINVAL; | ||
216 | f->type = V4L2_TUNER_RADIO; | 220 | f->type = V4L2_TUNER_RADIO; |
217 | mutex_lock(&dev->lock); | 221 | mutex_lock(&dev->lock); |
218 | f->frequency = BITS2FREQ(radio_bits_get(dev)); | 222 | f->frequency = BITS2FREQ(radio_bits_get(dev)); |
diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c index 3da51fe8fb93..44b4dbedb322 100644 --- a/drivers/media/radio/radio-maxiradio.c +++ b/drivers/media/radio/radio-maxiradio.c | |||
@@ -262,6 +262,8 @@ static int vidioc_s_frequency(struct file *file, void *priv, | |||
262 | { | 262 | { |
263 | struct maxiradio *dev = video_drvdata(file); | 263 | struct maxiradio *dev = video_drvdata(file); |
264 | 264 | ||
265 | if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) | ||
266 | return -EINVAL; | ||
265 | if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) { | 267 | if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) { |
266 | dprintk(dev, 1, "radio freq (%d.%02d MHz) out of range (%d-%d)\n", | 268 | dprintk(dev, 1, "radio freq (%d.%02d MHz) out of range (%d-%d)\n", |
267 | f->frequency / 16000, | 269 | f->frequency / 16000, |
@@ -285,6 +287,8 @@ static int vidioc_g_frequency(struct file *file, void *priv, | |||
285 | { | 287 | { |
286 | struct maxiradio *dev = video_drvdata(file); | 288 | struct maxiradio *dev = video_drvdata(file); |
287 | 289 | ||
290 | if (f->tuner != 0) | ||
291 | return -EINVAL; | ||
288 | f->type = V4L2_TUNER_RADIO; | 292 | f->type = V4L2_TUNER_RADIO; |
289 | f->frequency = dev->freq; | 293 | f->frequency = dev->freq; |
290 | 294 | ||
diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index 949f60513d9e..02a9cefc9a00 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c | |||
@@ -374,6 +374,8 @@ static int vidioc_s_frequency(struct file *file, void *priv, | |||
374 | { | 374 | { |
375 | struct amradio_device *radio = file->private_data; | 375 | struct amradio_device *radio = file->private_data; |
376 | 376 | ||
377 | if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) | ||
378 | return -EINVAL; | ||
377 | return amradio_setfreq(radio, f->frequency); | 379 | return amradio_setfreq(radio, f->frequency); |
378 | } | 380 | } |
379 | 381 | ||
@@ -383,6 +385,8 @@ static int vidioc_g_frequency(struct file *file, void *priv, | |||
383 | { | 385 | { |
384 | struct amradio_device *radio = file->private_data; | 386 | struct amradio_device *radio = file->private_data; |
385 | 387 | ||
388 | if (f->tuner != 0) | ||
389 | return -EINVAL; | ||
386 | f->type = V4L2_TUNER_RADIO; | 390 | f->type = V4L2_TUNER_RADIO; |
387 | f->frequency = radio->curfreq; | 391 | f->frequency = radio->curfreq; |
388 | 392 | ||
diff --git a/drivers/media/radio/radio-rtrack2.c b/drivers/media/radio/radio-rtrack2.c index 9cb193fa6e33..a79296aac9a9 100644 --- a/drivers/media/radio/radio-rtrack2.c +++ b/drivers/media/radio/radio-rtrack2.c | |||
@@ -167,6 +167,8 @@ static int vidioc_s_frequency(struct file *file, void *priv, | |||
167 | { | 167 | { |
168 | struct rtrack2 *rt = video_drvdata(file); | 168 | struct rtrack2 *rt = video_drvdata(file); |
169 | 169 | ||
170 | if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) | ||
171 | return -EINVAL; | ||
170 | rt_setfreq(rt, f->frequency); | 172 | rt_setfreq(rt, f->frequency); |
171 | return 0; | 173 | return 0; |
172 | } | 174 | } |
@@ -176,6 +178,8 @@ static int vidioc_g_frequency(struct file *file, void *priv, | |||
176 | { | 178 | { |
177 | struct rtrack2 *rt = video_drvdata(file); | 179 | struct rtrack2 *rt = video_drvdata(file); |
178 | 180 | ||
181 | if (f->tuner != 0) | ||
182 | return -EINVAL; | ||
179 | f->type = V4L2_TUNER_RADIO; | 183 | f->type = V4L2_TUNER_RADIO; |
180 | f->frequency = rt->curfreq; | 184 | f->frequency = rt->curfreq; |
181 | return 0; | 185 | return 0; |
diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c index 49c4aab95dab..985359d18aa5 100644 --- a/drivers/media/radio/radio-sf16fmi.c +++ b/drivers/media/radio/radio-sf16fmi.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* SF16FMI radio driver for Linux radio support | 1 | /* SF16-FMI and SF16-FMP radio driver for Linux radio support |
2 | * heavily based on rtrack driver... | 2 | * heavily based on rtrack driver... |
3 | * (c) 1997 M. Kirkwood | 3 | * (c) 1997 M. Kirkwood |
4 | * (c) 1998 Petr Vandrovec, vandrove@vc.cvut.cz | 4 | * (c) 1998 Petr Vandrovec, vandrove@vc.cvut.cz |
@@ -11,7 +11,7 @@ | |||
11 | * | 11 | * |
12 | * Frequency control is done digitally -- ie out(port,encodefreq(95.8)); | 12 | * Frequency control is done digitally -- ie out(port,encodefreq(95.8)); |
13 | * No volume control - only mute/unmute - you have to use line volume | 13 | * No volume control - only mute/unmute - you have to use line volume |
14 | * control on SB-part of SF16FMI | 14 | * control on SB-part of SF16-FMI/SF16-FMP |
15 | * | 15 | * |
16 | * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org> | 16 | * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org> |
17 | */ | 17 | */ |
@@ -30,14 +30,14 @@ | |||
30 | #include <media/v4l2-ioctl.h> | 30 | #include <media/v4l2-ioctl.h> |
31 | 31 | ||
32 | MODULE_AUTHOR("Petr Vandrovec, vandrove@vc.cvut.cz and M. Kirkwood"); | 32 | MODULE_AUTHOR("Petr Vandrovec, vandrove@vc.cvut.cz and M. Kirkwood"); |
33 | MODULE_DESCRIPTION("A driver for the SF16MI radio."); | 33 | MODULE_DESCRIPTION("A driver for the SF16-FMI and SF16-FMP radio."); |
34 | MODULE_LICENSE("GPL"); | 34 | MODULE_LICENSE("GPL"); |
35 | 35 | ||
36 | static int io = -1; | 36 | static int io = -1; |
37 | static int radio_nr = -1; | 37 | static int radio_nr = -1; |
38 | 38 | ||
39 | module_param(io, int, 0); | 39 | module_param(io, int, 0); |
40 | MODULE_PARM_DESC(io, "I/O address of the SF16MI card (0x284 or 0x384)"); | 40 | MODULE_PARM_DESC(io, "I/O address of the SF16-FMI or SF16-FMP card (0x284 or 0x384)"); |
41 | module_param(radio_nr, int, 0); | 41 | module_param(radio_nr, int, 0); |
42 | 42 | ||
43 | #define RADIO_VERSION KERNEL_VERSION(0, 0, 2) | 43 | #define RADIO_VERSION KERNEL_VERSION(0, 0, 2) |
@@ -47,13 +47,14 @@ struct fmi | |||
47 | struct v4l2_device v4l2_dev; | 47 | struct v4l2_device v4l2_dev; |
48 | struct video_device vdev; | 48 | struct video_device vdev; |
49 | int io; | 49 | int io; |
50 | int curvol; /* 1 or 0 */ | 50 | bool mute; |
51 | unsigned long curfreq; /* freq in kHz */ | 51 | unsigned long curfreq; /* freq in kHz */ |
52 | struct mutex lock; | 52 | struct mutex lock; |
53 | }; | 53 | }; |
54 | 54 | ||
55 | static struct fmi fmi_card; | 55 | static struct fmi fmi_card; |
56 | static struct pnp_dev *dev; | 56 | static struct pnp_dev *dev; |
57 | bool pnp_attached; | ||
57 | 58 | ||
58 | /* freq is in 1/16 kHz to internal number, hw precision is 50 kHz */ | 59 | /* freq is in 1/16 kHz to internal number, hw precision is 50 kHz */ |
59 | /* It is only useful to give freq in interval of 800 (=0.05Mhz), | 60 | /* It is only useful to give freq in interval of 800 (=0.05Mhz), |
@@ -105,7 +106,7 @@ static inline int fmi_setfreq(struct fmi *fmi, unsigned long freq) | |||
105 | outbits(8, 0xC0, fmi->io); | 106 | outbits(8, 0xC0, fmi->io); |
106 | msleep(143); /* was schedule_timeout(HZ/7) */ | 107 | msleep(143); /* was schedule_timeout(HZ/7) */ |
107 | mutex_unlock(&fmi->lock); | 108 | mutex_unlock(&fmi->lock); |
108 | if (fmi->curvol) | 109 | if (!fmi->mute) |
109 | fmi_unmute(fmi); | 110 | fmi_unmute(fmi); |
110 | return 0; | 111 | return 0; |
111 | } | 112 | } |
@@ -116,7 +117,7 @@ static inline int fmi_getsigstr(struct fmi *fmi) | |||
116 | int res; | 117 | int res; |
117 | 118 | ||
118 | mutex_lock(&fmi->lock); | 119 | mutex_lock(&fmi->lock); |
119 | val = fmi->curvol ? 0x08 : 0x00; /* unmute/mute */ | 120 | val = fmi->mute ? 0x00 : 0x08; /* mute/unmute */ |
120 | outb(val, fmi->io); | 121 | outb(val, fmi->io); |
121 | outb(val | 0x10, fmi->io); | 122 | outb(val | 0x10, fmi->io); |
122 | msleep(143); /* was schedule_timeout(HZ/7) */ | 123 | msleep(143); /* was schedule_timeout(HZ/7) */ |
@@ -168,6 +169,8 @@ static int vidioc_s_frequency(struct file *file, void *priv, | |||
168 | { | 169 | { |
169 | struct fmi *fmi = video_drvdata(file); | 170 | struct fmi *fmi = video_drvdata(file); |
170 | 171 | ||
172 | if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) | ||
173 | return -EINVAL; | ||
171 | if (f->frequency < RSF16_MINFREQ || | 174 | if (f->frequency < RSF16_MINFREQ || |
172 | f->frequency > RSF16_MAXFREQ) | 175 | f->frequency > RSF16_MAXFREQ) |
173 | return -EINVAL; | 176 | return -EINVAL; |
@@ -182,6 +185,8 @@ static int vidioc_g_frequency(struct file *file, void *priv, | |||
182 | { | 185 | { |
183 | struct fmi *fmi = video_drvdata(file); | 186 | struct fmi *fmi = video_drvdata(file); |
184 | 187 | ||
188 | if (f->tuner != 0) | ||
189 | return -EINVAL; | ||
185 | f->type = V4L2_TUNER_RADIO; | 190 | f->type = V4L2_TUNER_RADIO; |
186 | f->frequency = fmi->curfreq; | 191 | f->frequency = fmi->curfreq; |
187 | return 0; | 192 | return 0; |
@@ -204,7 +209,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, | |||
204 | 209 | ||
205 | switch (ctrl->id) { | 210 | switch (ctrl->id) { |
206 | case V4L2_CID_AUDIO_MUTE: | 211 | case V4L2_CID_AUDIO_MUTE: |
207 | ctrl->value = fmi->curvol; | 212 | ctrl->value = fmi->mute; |
208 | return 0; | 213 | return 0; |
209 | } | 214 | } |
210 | return -EINVAL; | 215 | return -EINVAL; |
@@ -221,7 +226,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, | |||
221 | fmi_mute(fmi); | 226 | fmi_mute(fmi); |
222 | else | 227 | else |
223 | fmi_unmute(fmi); | 228 | fmi_unmute(fmi); |
224 | fmi->curvol = ctrl->value; | 229 | fmi->mute = ctrl->value; |
225 | return 0; | 230 | return 0; |
226 | } | 231 | } |
227 | return -EINVAL; | 232 | return -EINVAL; |
@@ -316,26 +321,54 @@ static int __init fmi_init(void) | |||
316 | { | 321 | { |
317 | struct fmi *fmi = &fmi_card; | 322 | struct fmi *fmi = &fmi_card; |
318 | struct v4l2_device *v4l2_dev = &fmi->v4l2_dev; | 323 | struct v4l2_device *v4l2_dev = &fmi->v4l2_dev; |
319 | int res; | 324 | int res, i; |
325 | int probe_ports[] = { 0, 0x284, 0x384 }; | ||
326 | |||
327 | if (io < 0) { | ||
328 | for (i = 0; i < ARRAY_SIZE(probe_ports); i++) { | ||
329 | io = probe_ports[i]; | ||
330 | if (io == 0) { | ||
331 | io = isapnp_fmi_probe(); | ||
332 | if (io < 0) | ||
333 | continue; | ||
334 | pnp_attached = 1; | ||
335 | } | ||
336 | if (!request_region(io, 2, "radio-sf16fmi")) { | ||
337 | if (pnp_attached) | ||
338 | pnp_device_detach(dev); | ||
339 | io = -1; | ||
340 | continue; | ||
341 | } | ||
342 | if (pnp_attached || | ||
343 | ((inb(io) & 0xf9) == 0xf9 && (inb(io) & 0x4) == 0)) | ||
344 | break; | ||
345 | release_region(io, 2); | ||
346 | io = -1; | ||
347 | } | ||
348 | } else { | ||
349 | if (!request_region(io, 2, "radio-sf16fmi")) { | ||
350 | printk(KERN_ERR "radio-sf16fmi: port %#x already in use\n", io); | ||
351 | return -EBUSY; | ||
352 | } | ||
353 | if (inb(io) == 0xff) { | ||
354 | printk(KERN_ERR "radio-sf16fmi: card not present at %#x\n", io); | ||
355 | release_region(io, 2); | ||
356 | return -ENODEV; | ||
357 | } | ||
358 | } | ||
359 | if (io < 0) { | ||
360 | printk(KERN_ERR "radio-sf16fmi: no cards found\n"); | ||
361 | return -ENODEV; | ||
362 | } | ||
320 | 363 | ||
321 | if (io < 0) | ||
322 | io = isapnp_fmi_probe(); | ||
323 | strlcpy(v4l2_dev->name, "sf16fmi", sizeof(v4l2_dev->name)); | 364 | strlcpy(v4l2_dev->name, "sf16fmi", sizeof(v4l2_dev->name)); |
324 | fmi->io = io; | 365 | fmi->io = io; |
325 | if (fmi->io < 0) { | ||
326 | v4l2_err(v4l2_dev, "No PnP card found.\n"); | ||
327 | return fmi->io; | ||
328 | } | ||
329 | if (!request_region(io, 2, "radio-sf16fmi")) { | ||
330 | v4l2_err(v4l2_dev, "port 0x%x already in use\n", fmi->io); | ||
331 | pnp_device_detach(dev); | ||
332 | return -EBUSY; | ||
333 | } | ||
334 | 366 | ||
335 | res = v4l2_device_register(NULL, v4l2_dev); | 367 | res = v4l2_device_register(NULL, v4l2_dev); |
336 | if (res < 0) { | 368 | if (res < 0) { |
337 | release_region(fmi->io, 2); | 369 | release_region(fmi->io, 2); |
338 | pnp_device_detach(dev); | 370 | if (pnp_attached) |
371 | pnp_device_detach(dev); | ||
339 | v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); | 372 | v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); |
340 | return res; | 373 | return res; |
341 | } | 374 | } |
@@ -352,7 +385,8 @@ static int __init fmi_init(void) | |||
352 | if (video_register_device(&fmi->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { | 385 | if (video_register_device(&fmi->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { |
353 | v4l2_device_unregister(v4l2_dev); | 386 | v4l2_device_unregister(v4l2_dev); |
354 | release_region(fmi->io, 2); | 387 | release_region(fmi->io, 2); |
355 | pnp_device_detach(dev); | 388 | if (pnp_attached) |
389 | pnp_device_detach(dev); | ||
356 | return -EINVAL; | 390 | return -EINVAL; |
357 | } | 391 | } |
358 | 392 | ||
@@ -369,7 +403,7 @@ static void __exit fmi_exit(void) | |||
369 | video_unregister_device(&fmi->vdev); | 403 | video_unregister_device(&fmi->vdev); |
370 | v4l2_device_unregister(&fmi->v4l2_dev); | 404 | v4l2_device_unregister(&fmi->v4l2_dev); |
371 | release_region(fmi->io, 2); | 405 | release_region(fmi->io, 2); |
372 | if (dev) | 406 | if (dev && pnp_attached) |
373 | pnp_device_detach(dev); | 407 | pnp_device_detach(dev); |
374 | } | 408 | } |
375 | 409 | ||
diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c index a11414f648d4..52c7bbb32b8b 100644 --- a/drivers/media/radio/radio-sf16fmr2.c +++ b/drivers/media/radio/radio-sf16fmr2.c | |||
@@ -251,6 +251,8 @@ static int vidioc_s_frequency(struct file *file, void *priv, | |||
251 | { | 251 | { |
252 | struct fmr2 *fmr2 = video_drvdata(file); | 252 | struct fmr2 *fmr2 = video_drvdata(file); |
253 | 253 | ||
254 | if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) | ||
255 | return -EINVAL; | ||
254 | if (f->frequency < RSF16_MINFREQ || | 256 | if (f->frequency < RSF16_MINFREQ || |
255 | f->frequency > RSF16_MAXFREQ) | 257 | f->frequency > RSF16_MAXFREQ) |
256 | return -EINVAL; | 258 | return -EINVAL; |
@@ -272,6 +274,8 @@ static int vidioc_g_frequency(struct file *file, void *priv, | |||
272 | { | 274 | { |
273 | struct fmr2 *fmr2 = video_drvdata(file); | 275 | struct fmr2 *fmr2 = video_drvdata(file); |
274 | 276 | ||
277 | if (f->tuner != 0) | ||
278 | return -EINVAL; | ||
275 | f->type = V4L2_TUNER_RADIO; | 279 | f->type = V4L2_TUNER_RADIO; |
276 | f->frequency = fmr2->curfreq; | 280 | f->frequency = fmr2->curfreq; |
277 | return 0; | 281 | return 0; |
diff --git a/drivers/media/radio/radio-tea5764.c b/drivers/media/radio/radio-tea5764.c index 3cd76dddb6aa..8e718bfcdad3 100644 --- a/drivers/media/radio/radio-tea5764.c +++ b/drivers/media/radio/radio-tea5764.c | |||
@@ -314,7 +314,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, | |||
314 | if (v->index > 0) | 314 | if (v->index > 0) |
315 | return -EINVAL; | 315 | return -EINVAL; |
316 | 316 | ||
317 | memset(v, 0, sizeof(v)); | 317 | memset(v, 0, sizeof(*v)); |
318 | strcpy(v->name, "FM"); | 318 | strcpy(v->name, "FM"); |
319 | v->type = V4L2_TUNER_RADIO; | 319 | v->type = V4L2_TUNER_RADIO; |
320 | tea5764_i2c_read(radio); | 320 | tea5764_i2c_read(radio); |
@@ -349,7 +349,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, | |||
349 | { | 349 | { |
350 | struct tea5764_device *radio = video_drvdata(file); | 350 | struct tea5764_device *radio = video_drvdata(file); |
351 | 351 | ||
352 | if (f->tuner != 0) | 352 | if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) |
353 | return -EINVAL; | 353 | return -EINVAL; |
354 | if (f->frequency == 0) { | 354 | if (f->frequency == 0) { |
355 | /* We special case this as a power down control. */ | 355 | /* We special case this as a power down control. */ |
@@ -370,8 +370,10 @@ static int vidioc_g_frequency(struct file *file, void *priv, | |||
370 | struct tea5764_device *radio = video_drvdata(file); | 370 | struct tea5764_device *radio = video_drvdata(file); |
371 | struct tea5764_regs *r = &radio->regs; | 371 | struct tea5764_regs *r = &radio->regs; |
372 | 372 | ||
373 | if (f->tuner != 0) | ||
374 | return -EINVAL; | ||
373 | tea5764_i2c_read(radio); | 375 | tea5764_i2c_read(radio); |
374 | memset(f, 0, sizeof(f)); | 376 | memset(f, 0, sizeof(*f)); |
375 | f->type = V4L2_TUNER_RADIO; | 377 | f->type = V4L2_TUNER_RADIO; |
376 | if (r->tnctrl & TEA5764_TNCTRL_PUPD0) | 378 | if (r->tnctrl & TEA5764_TNCTRL_PUPD0) |
377 | f->frequency = (tea5764_get_freq(radio) * 2) / 125; | 379 | f->frequency = (tea5764_get_freq(radio) * 2) / 125; |
@@ -458,12 +460,8 @@ static int vidioc_s_audio(struct file *file, void *priv, | |||
458 | static int tea5764_open(struct file *file) | 460 | static int tea5764_open(struct file *file) |
459 | { | 461 | { |
460 | /* Currently we support only one device */ | 462 | /* Currently we support only one device */ |
461 | int minor = video_devdata(file)->minor; | ||
462 | struct tea5764_device *radio = video_drvdata(file); | 463 | struct tea5764_device *radio = video_drvdata(file); |
463 | 464 | ||
464 | if (radio->videodev->minor != minor) | ||
465 | return -ENODEV; | ||
466 | |||
467 | mutex_lock(&radio->mutex); | 465 | mutex_lock(&radio->mutex); |
468 | /* Only exclusive access */ | 466 | /* Only exclusive access */ |
469 | if (radio->users) { | 467 | if (radio->users) { |
diff --git a/drivers/media/radio/radio-terratec.c b/drivers/media/radio/radio-terratec.c index 699db9acaaf7..fc1c860fd438 100644 --- a/drivers/media/radio/radio-terratec.c +++ b/drivers/media/radio/radio-terratec.c | |||
@@ -240,6 +240,8 @@ static int vidioc_s_frequency(struct file *file, void *priv, | |||
240 | { | 240 | { |
241 | struct terratec *tt = video_drvdata(file); | 241 | struct terratec *tt = video_drvdata(file); |
242 | 242 | ||
243 | if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) | ||
244 | return -EINVAL; | ||
243 | tt_setfreq(tt, f->frequency); | 245 | tt_setfreq(tt, f->frequency); |
244 | return 0; | 246 | return 0; |
245 | } | 247 | } |
@@ -249,6 +251,8 @@ static int vidioc_g_frequency(struct file *file, void *priv, | |||
249 | { | 251 | { |
250 | struct terratec *tt = video_drvdata(file); | 252 | struct terratec *tt = video_drvdata(file); |
251 | 253 | ||
254 | if (f->tuner != 0) | ||
255 | return -EINVAL; | ||
252 | f->type = V4L2_TUNER_RADIO; | 256 | f->type = V4L2_TUNER_RADIO; |
253 | f->frequency = tt->curfreq; | 257 | f->frequency = tt->curfreq; |
254 | return 0; | 258 | return 0; |
diff --git a/drivers/media/radio/radio-trust.c b/drivers/media/radio/radio-trust.c index 6f9ecc359356..9d6dcf8af5b0 100644 --- a/drivers/media/radio/radio-trust.c +++ b/drivers/media/radio/radio-trust.c | |||
@@ -239,6 +239,8 @@ static int vidioc_s_frequency(struct file *file, void *priv, | |||
239 | { | 239 | { |
240 | struct trust *tr = video_drvdata(file); | 240 | struct trust *tr = video_drvdata(file); |
241 | 241 | ||
242 | if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) | ||
243 | return -EINVAL; | ||
242 | tr_setfreq(tr, f->frequency); | 244 | tr_setfreq(tr, f->frequency); |
243 | return 0; | 245 | return 0; |
244 | } | 246 | } |
@@ -248,6 +250,8 @@ static int vidioc_g_frequency(struct file *file, void *priv, | |||
248 | { | 250 | { |
249 | struct trust *tr = video_drvdata(file); | 251 | struct trust *tr = video_drvdata(file); |
250 | 252 | ||
253 | if (f->tuner != 0) | ||
254 | return -EINVAL; | ||
251 | f->type = V4L2_TUNER_RADIO; | 255 | f->type = V4L2_TUNER_RADIO; |
252 | f->frequency = tr->curfreq; | 256 | f->frequency = tr->curfreq; |
253 | return 0; | 257 | return 0; |
diff --git a/drivers/media/radio/radio-typhoon.c b/drivers/media/radio/radio-typhoon.c index 3a98f1399495..03439282dfce 100644 --- a/drivers/media/radio/radio-typhoon.c +++ b/drivers/media/radio/radio-typhoon.c | |||
@@ -207,6 +207,8 @@ static int vidioc_g_frequency(struct file *file, void *priv, | |||
207 | { | 207 | { |
208 | struct typhoon *dev = video_drvdata(file); | 208 | struct typhoon *dev = video_drvdata(file); |
209 | 209 | ||
210 | if (f->tuner != 0) | ||
211 | return -EINVAL; | ||
210 | f->type = V4L2_TUNER_RADIO; | 212 | f->type = V4L2_TUNER_RADIO; |
211 | f->frequency = dev->curfreq; | 213 | f->frequency = dev->curfreq; |
212 | return 0; | 214 | return 0; |
@@ -217,6 +219,8 @@ static int vidioc_s_frequency(struct file *file, void *priv, | |||
217 | { | 219 | { |
218 | struct typhoon *dev = video_drvdata(file); | 220 | struct typhoon *dev = video_drvdata(file); |
219 | 221 | ||
222 | if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) | ||
223 | return -EINVAL; | ||
220 | dev->curfreq = f->frequency; | 224 | dev->curfreq = f->frequency; |
221 | typhoon_setfreq(dev, dev->curfreq); | 225 | typhoon_setfreq(dev, dev->curfreq); |
222 | return 0; | 226 | return 0; |
diff --git a/drivers/media/radio/radio-zoltrix.c b/drivers/media/radio/radio-zoltrix.c index 80e98b6422fe..f31eab99c943 100644 --- a/drivers/media/radio/radio-zoltrix.c +++ b/drivers/media/radio/radio-zoltrix.c | |||
@@ -266,6 +266,8 @@ static int vidioc_s_frequency(struct file *file, void *priv, | |||
266 | { | 266 | { |
267 | struct zoltrix *zol = video_drvdata(file); | 267 | struct zoltrix *zol = video_drvdata(file); |
268 | 268 | ||
269 | if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) | ||
270 | return -EINVAL; | ||
269 | if (zol_setfreq(zol, f->frequency) != 0) | 271 | if (zol_setfreq(zol, f->frequency) != 0) |
270 | return -EINVAL; | 272 | return -EINVAL; |
271 | return 0; | 273 | return 0; |
@@ -276,6 +278,8 @@ static int vidioc_g_frequency(struct file *file, void *priv, | |||
276 | { | 278 | { |
277 | struct zoltrix *zol = video_drvdata(file); | 279 | struct zoltrix *zol = video_drvdata(file); |
278 | 280 | ||
281 | if (f->tuner != 0) | ||
282 | return -EINVAL; | ||
279 | f->type = V4L2_TUNER_RADIO; | 283 | f->type = V4L2_TUNER_RADIO; |
280 | f->frequency = zol->curfreq; | 284 | f->frequency = zol->curfreq; |
281 | return 0; | 285 | return 0; |
diff --git a/drivers/media/radio/si470x/radio-si470x-common.c b/drivers/media/radio/si470x/radio-si470x-common.c index f33315f2c543..4da0f150c6e2 100644 --- a/drivers/media/radio/si470x/radio-si470x-common.c +++ b/drivers/media/radio/si470x/radio-si470x-common.c | |||
@@ -426,6 +426,104 @@ int si470x_rds_on(struct si470x_device *radio) | |||
426 | 426 | ||
427 | 427 | ||
428 | /************************************************************************** | 428 | /************************************************************************** |
429 | * File Operations Interface | ||
430 | **************************************************************************/ | ||
431 | |||
432 | /* | ||
433 | * si470x_fops_read - read RDS data | ||
434 | */ | ||
435 | static ssize_t si470x_fops_read(struct file *file, char __user *buf, | ||
436 | size_t count, loff_t *ppos) | ||
437 | { | ||
438 | struct si470x_device *radio = video_drvdata(file); | ||
439 | int retval = 0; | ||
440 | unsigned int block_count = 0; | ||
441 | |||
442 | /* switch on rds reception */ | ||
443 | if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) | ||
444 | si470x_rds_on(radio); | ||
445 | |||
446 | /* block if no new data available */ | ||
447 | while (radio->wr_index == radio->rd_index) { | ||
448 | if (file->f_flags & O_NONBLOCK) { | ||
449 | retval = -EWOULDBLOCK; | ||
450 | goto done; | ||
451 | } | ||
452 | if (wait_event_interruptible(radio->read_queue, | ||
453 | radio->wr_index != radio->rd_index) < 0) { | ||
454 | retval = -EINTR; | ||
455 | goto done; | ||
456 | } | ||
457 | } | ||
458 | |||
459 | /* calculate block count from byte count */ | ||
460 | count /= 3; | ||
461 | |||
462 | /* copy RDS block out of internal buffer and to user buffer */ | ||
463 | mutex_lock(&radio->lock); | ||
464 | while (block_count < count) { | ||
465 | if (radio->rd_index == radio->wr_index) | ||
466 | break; | ||
467 | |||
468 | /* always transfer rds complete blocks */ | ||
469 | if (copy_to_user(buf, &radio->buffer[radio->rd_index], 3)) | ||
470 | /* retval = -EFAULT; */ | ||
471 | break; | ||
472 | |||
473 | /* increment and wrap read pointer */ | ||
474 | radio->rd_index += 3; | ||
475 | if (radio->rd_index >= radio->buf_size) | ||
476 | radio->rd_index = 0; | ||
477 | |||
478 | /* increment counters */ | ||
479 | block_count++; | ||
480 | buf += 3; | ||
481 | retval += 3; | ||
482 | } | ||
483 | mutex_unlock(&radio->lock); | ||
484 | |||
485 | done: | ||
486 | return retval; | ||
487 | } | ||
488 | |||
489 | |||
490 | /* | ||
491 | * si470x_fops_poll - poll RDS data | ||
492 | */ | ||
493 | static unsigned int si470x_fops_poll(struct file *file, | ||
494 | struct poll_table_struct *pts) | ||
495 | { | ||
496 | struct si470x_device *radio = video_drvdata(file); | ||
497 | int retval = 0; | ||
498 | |||
499 | /* switch on rds reception */ | ||
500 | if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) | ||
501 | si470x_rds_on(radio); | ||
502 | |||
503 | poll_wait(file, &radio->read_queue, pts); | ||
504 | |||
505 | if (radio->rd_index != radio->wr_index) | ||
506 | retval = POLLIN | POLLRDNORM; | ||
507 | |||
508 | return retval; | ||
509 | } | ||
510 | |||
511 | |||
512 | /* | ||
513 | * si470x_fops - file operations interface | ||
514 | */ | ||
515 | static const struct v4l2_file_operations si470x_fops = { | ||
516 | .owner = THIS_MODULE, | ||
517 | .read = si470x_fops_read, | ||
518 | .poll = si470x_fops_poll, | ||
519 | .ioctl = video_ioctl2, | ||
520 | .open = si470x_fops_open, | ||
521 | .release = si470x_fops_release, | ||
522 | }; | ||
523 | |||
524 | |||
525 | |||
526 | /************************************************************************** | ||
429 | * Video4Linux Interface | 527 | * Video4Linux Interface |
430 | **************************************************************************/ | 528 | **************************************************************************/ |
431 | 529 | ||
diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c b/drivers/media/radio/si470x/radio-si470x-i2c.c index 2d53b6a9409b..5466015346a1 100644 --- a/drivers/media/radio/si470x/radio-si470x-i2c.c +++ b/drivers/media/radio/si470x/radio-si470x-i2c.c | |||
@@ -22,22 +22,17 @@ | |||
22 | */ | 22 | */ |
23 | 23 | ||
24 | 24 | ||
25 | /* | ||
26 | * ToDo: | ||
27 | * - RDS support | ||
28 | */ | ||
29 | |||
30 | |||
31 | /* driver definitions */ | 25 | /* driver definitions */ |
32 | #define DRIVER_AUTHOR "Joonyoung Shim <jy0922.shim@samsung.com>"; | 26 | #define DRIVER_AUTHOR "Joonyoung Shim <jy0922.shim@samsung.com>"; |
33 | #define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 0) | 27 | #define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 1) |
34 | #define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver" | 28 | #define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver" |
35 | #define DRIVER_DESC "I2C radio driver for Si470x FM Radio Receivers" | 29 | #define DRIVER_DESC "I2C radio driver for Si470x FM Radio Receivers" |
36 | #define DRIVER_VERSION "1.0.0" | 30 | #define DRIVER_VERSION "1.0.1" |
37 | 31 | ||
38 | /* kernel includes */ | 32 | /* kernel includes */ |
39 | #include <linux/i2c.h> | 33 | #include <linux/i2c.h> |
40 | #include <linux/delay.h> | 34 | #include <linux/delay.h> |
35 | #include <linux/interrupt.h> | ||
41 | 36 | ||
42 | #include "radio-si470x.h" | 37 | #include "radio-si470x.h" |
43 | 38 | ||
@@ -62,6 +57,20 @@ static int radio_nr = -1; | |||
62 | module_param(radio_nr, int, 0444); | 57 | module_param(radio_nr, int, 0444); |
63 | MODULE_PARM_DESC(radio_nr, "Radio Nr"); | 58 | MODULE_PARM_DESC(radio_nr, "Radio Nr"); |
64 | 59 | ||
60 | /* RDS buffer blocks */ | ||
61 | static unsigned int rds_buf = 100; | ||
62 | module_param(rds_buf, uint, 0444); | ||
63 | MODULE_PARM_DESC(rds_buf, "RDS buffer entries: *100*"); | ||
64 | |||
65 | /* RDS maximum block errors */ | ||
66 | static unsigned short max_rds_errors = 1; | ||
67 | /* 0 means 0 errors requiring correction */ | ||
68 | /* 1 means 1-2 errors requiring correction (used by original USBRadio.exe) */ | ||
69 | /* 2 means 3-5 errors requiring correction */ | ||
70 | /* 3 means 6+ errors or errors in checkword, correction not possible */ | ||
71 | module_param(max_rds_errors, ushort, 0644); | ||
72 | MODULE_PARM_DESC(max_rds_errors, "RDS maximum block errors: *1*"); | ||
73 | |||
65 | 74 | ||
66 | 75 | ||
67 | /************************************************************************** | 76 | /************************************************************************** |
@@ -173,7 +182,7 @@ int si470x_disconnect_check(struct si470x_device *radio) | |||
173 | /* | 182 | /* |
174 | * si470x_fops_open - file open | 183 | * si470x_fops_open - file open |
175 | */ | 184 | */ |
176 | static int si470x_fops_open(struct file *file) | 185 | int si470x_fops_open(struct file *file) |
177 | { | 186 | { |
178 | struct si470x_device *radio = video_drvdata(file); | 187 | struct si470x_device *radio = video_drvdata(file); |
179 | int retval = 0; | 188 | int retval = 0; |
@@ -181,12 +190,21 @@ static int si470x_fops_open(struct file *file) | |||
181 | mutex_lock(&radio->lock); | 190 | mutex_lock(&radio->lock); |
182 | radio->users++; | 191 | radio->users++; |
183 | 192 | ||
184 | if (radio->users == 1) | 193 | if (radio->users == 1) { |
185 | /* start radio */ | 194 | /* start radio */ |
186 | retval = si470x_start(radio); | 195 | retval = si470x_start(radio); |
196 | if (retval < 0) | ||
197 | goto done; | ||
198 | |||
199 | /* enable RDS interrupt */ | ||
200 | radio->registers[SYSCONFIG1] |= SYSCONFIG1_RDSIEN; | ||
201 | radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_GPIO2; | ||
202 | radio->registers[SYSCONFIG1] |= 0x1 << 2; | ||
203 | retval = si470x_set_register(radio, SYSCONFIG1); | ||
204 | } | ||
187 | 205 | ||
206 | done: | ||
188 | mutex_unlock(&radio->lock); | 207 | mutex_unlock(&radio->lock); |
189 | |||
190 | return retval; | 208 | return retval; |
191 | } | 209 | } |
192 | 210 | ||
@@ -194,7 +212,7 @@ static int si470x_fops_open(struct file *file) | |||
194 | /* | 212 | /* |
195 | * si470x_fops_release - file release | 213 | * si470x_fops_release - file release |
196 | */ | 214 | */ |
197 | static int si470x_fops_release(struct file *file) | 215 | int si470x_fops_release(struct file *file) |
198 | { | 216 | { |
199 | struct si470x_device *radio = video_drvdata(file); | 217 | struct si470x_device *radio = video_drvdata(file); |
200 | int retval = 0; | 218 | int retval = 0; |
@@ -215,17 +233,6 @@ static int si470x_fops_release(struct file *file) | |||
215 | } | 233 | } |
216 | 234 | ||
217 | 235 | ||
218 | /* | ||
219 | * si470x_fops - file operations interface | ||
220 | */ | ||
221 | const struct v4l2_file_operations si470x_fops = { | ||
222 | .owner = THIS_MODULE, | ||
223 | .ioctl = video_ioctl2, | ||
224 | .open = si470x_fops_open, | ||
225 | .release = si470x_fops_release, | ||
226 | }; | ||
227 | |||
228 | |||
229 | 236 | ||
230 | /************************************************************************** | 237 | /************************************************************************** |
231 | * Video4Linux Interface | 238 | * Video4Linux Interface |
@@ -253,6 +260,105 @@ int si470x_vidioc_querycap(struct file *file, void *priv, | |||
253 | **************************************************************************/ | 260 | **************************************************************************/ |
254 | 261 | ||
255 | /* | 262 | /* |
263 | * si470x_i2c_interrupt_work - rds processing function | ||
264 | */ | ||
265 | static void si470x_i2c_interrupt_work(struct work_struct *work) | ||
266 | { | ||
267 | struct si470x_device *radio = container_of(work, | ||
268 | struct si470x_device, radio_work); | ||
269 | unsigned char regnr; | ||
270 | unsigned char blocknum; | ||
271 | unsigned short bler; /* rds block errors */ | ||
272 | unsigned short rds; | ||
273 | unsigned char tmpbuf[3]; | ||
274 | int retval = 0; | ||
275 | |||
276 | /* safety checks */ | ||
277 | if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) | ||
278 | return; | ||
279 | |||
280 | /* Update RDS registers */ | ||
281 | for (regnr = 0; regnr < RDS_REGISTER_NUM; regnr++) { | ||
282 | retval = si470x_get_register(radio, STATUSRSSI + regnr); | ||
283 | if (retval < 0) | ||
284 | return; | ||
285 | } | ||
286 | |||
287 | /* get rds blocks */ | ||
288 | if ((radio->registers[STATUSRSSI] & STATUSRSSI_RDSR) == 0) | ||
289 | /* No RDS group ready, better luck next time */ | ||
290 | return; | ||
291 | |||
292 | for (blocknum = 0; blocknum < 4; blocknum++) { | ||
293 | switch (blocknum) { | ||
294 | default: | ||
295 | bler = (radio->registers[STATUSRSSI] & | ||
296 | STATUSRSSI_BLERA) >> 9; | ||
297 | rds = radio->registers[RDSA]; | ||
298 | break; | ||
299 | case 1: | ||
300 | bler = (radio->registers[READCHAN] & | ||
301 | READCHAN_BLERB) >> 14; | ||
302 | rds = radio->registers[RDSB]; | ||
303 | break; | ||
304 | case 2: | ||
305 | bler = (radio->registers[READCHAN] & | ||
306 | READCHAN_BLERC) >> 12; | ||
307 | rds = radio->registers[RDSC]; | ||
308 | break; | ||
309 | case 3: | ||
310 | bler = (radio->registers[READCHAN] & | ||
311 | READCHAN_BLERD) >> 10; | ||
312 | rds = radio->registers[RDSD]; | ||
313 | break; | ||
314 | }; | ||
315 | |||
316 | /* Fill the V4L2 RDS buffer */ | ||
317 | put_unaligned_le16(rds, &tmpbuf); | ||
318 | tmpbuf[2] = blocknum; /* offset name */ | ||
319 | tmpbuf[2] |= blocknum << 3; /* received offset */ | ||
320 | if (bler > max_rds_errors) | ||
321 | tmpbuf[2] |= 0x80; /* uncorrectable errors */ | ||
322 | else if (bler > 0) | ||
323 | tmpbuf[2] |= 0x40; /* corrected error(s) */ | ||
324 | |||
325 | /* copy RDS block to internal buffer */ | ||
326 | memcpy(&radio->buffer[radio->wr_index], &tmpbuf, 3); | ||
327 | radio->wr_index += 3; | ||
328 | |||
329 | /* wrap write pointer */ | ||
330 | if (radio->wr_index >= radio->buf_size) | ||
331 | radio->wr_index = 0; | ||
332 | |||
333 | /* check for overflow */ | ||
334 | if (radio->wr_index == radio->rd_index) { | ||
335 | /* increment and wrap read pointer */ | ||
336 | radio->rd_index += 3; | ||
337 | if (radio->rd_index >= radio->buf_size) | ||
338 | radio->rd_index = 0; | ||
339 | } | ||
340 | } | ||
341 | |||
342 | if (radio->wr_index != radio->rd_index) | ||
343 | wake_up_interruptible(&radio->read_queue); | ||
344 | } | ||
345 | |||
346 | |||
347 | /* | ||
348 | * si470x_i2c_interrupt - interrupt handler | ||
349 | */ | ||
350 | static irqreturn_t si470x_i2c_interrupt(int irq, void *dev_id) | ||
351 | { | ||
352 | struct si470x_device *radio = dev_id; | ||
353 | |||
354 | if (!work_pending(&radio->radio_work)) | ||
355 | schedule_work(&radio->radio_work); | ||
356 | |||
357 | return IRQ_HANDLED; | ||
358 | } | ||
359 | |||
360 | |||
361 | /* | ||
256 | * si470x_i2c_probe - probe for the device | 362 | * si470x_i2c_probe - probe for the device |
257 | */ | 363 | */ |
258 | static int __devinit si470x_i2c_probe(struct i2c_client *client, | 364 | static int __devinit si470x_i2c_probe(struct i2c_client *client, |
@@ -268,6 +374,8 @@ static int __devinit si470x_i2c_probe(struct i2c_client *client, | |||
268 | retval = -ENOMEM; | 374 | retval = -ENOMEM; |
269 | goto err_initial; | 375 | goto err_initial; |
270 | } | 376 | } |
377 | |||
378 | INIT_WORK(&radio->radio_work, si470x_i2c_interrupt_work); | ||
271 | radio->users = 0; | 379 | radio->users = 0; |
272 | radio->client = client; | 380 | radio->client = client; |
273 | mutex_init(&radio->lock); | 381 | mutex_init(&radio->lock); |
@@ -319,6 +427,26 @@ static int __devinit si470x_i2c_probe(struct i2c_client *client, | |||
319 | /* set initial frequency */ | 427 | /* set initial frequency */ |
320 | si470x_set_freq(radio, 87.5 * FREQ_MUL); /* available in all regions */ | 428 | si470x_set_freq(radio, 87.5 * FREQ_MUL); /* available in all regions */ |
321 | 429 | ||
430 | /* rds buffer allocation */ | ||
431 | radio->buf_size = rds_buf * 3; | ||
432 | radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL); | ||
433 | if (!radio->buffer) { | ||
434 | retval = -EIO; | ||
435 | goto err_video; | ||
436 | } | ||
437 | |||
438 | /* rds buffer configuration */ | ||
439 | radio->wr_index = 0; | ||
440 | radio->rd_index = 0; | ||
441 | init_waitqueue_head(&radio->read_queue); | ||
442 | |||
443 | retval = request_irq(client->irq, si470x_i2c_interrupt, | ||
444 | IRQF_TRIGGER_FALLING, DRIVER_NAME, radio); | ||
445 | if (retval) { | ||
446 | dev_err(&client->dev, "Failed to register interrupt\n"); | ||
447 | goto err_rds; | ||
448 | } | ||
449 | |||
322 | /* register video device */ | 450 | /* register video device */ |
323 | retval = video_register_device(radio->videodev, VFL_TYPE_RADIO, | 451 | retval = video_register_device(radio->videodev, VFL_TYPE_RADIO, |
324 | radio_nr); | 452 | radio_nr); |
@@ -330,6 +458,9 @@ static int __devinit si470x_i2c_probe(struct i2c_client *client, | |||
330 | 458 | ||
331 | return 0; | 459 | return 0; |
332 | err_all: | 460 | err_all: |
461 | free_irq(client->irq, radio); | ||
462 | err_rds: | ||
463 | kfree(radio->buffer); | ||
333 | err_video: | 464 | err_video: |
334 | video_device_release(radio->videodev); | 465 | video_device_release(radio->videodev); |
335 | err_radio: | 466 | err_radio: |
@@ -346,6 +477,8 @@ static __devexit int si470x_i2c_remove(struct i2c_client *client) | |||
346 | { | 477 | { |
347 | struct si470x_device *radio = i2c_get_clientdata(client); | 478 | struct si470x_device *radio = i2c_get_clientdata(client); |
348 | 479 | ||
480 | free_irq(client->irq, radio); | ||
481 | cancel_work_sync(&radio->radio_work); | ||
349 | video_unregister_device(radio->videodev); | 482 | video_unregister_device(radio->videodev); |
350 | kfree(radio); | 483 | kfree(radio); |
351 | i2c_set_clientdata(client, NULL); | 484 | i2c_set_clientdata(client, NULL); |
@@ -354,6 +487,44 @@ static __devexit int si470x_i2c_remove(struct i2c_client *client) | |||
354 | } | 487 | } |
355 | 488 | ||
356 | 489 | ||
490 | #ifdef CONFIG_PM | ||
491 | /* | ||
492 | * si470x_i2c_suspend - suspend the device | ||
493 | */ | ||
494 | static int si470x_i2c_suspend(struct i2c_client *client, pm_message_t mesg) | ||
495 | { | ||
496 | struct si470x_device *radio = i2c_get_clientdata(client); | ||
497 | |||
498 | /* power down */ | ||
499 | radio->registers[POWERCFG] |= POWERCFG_DISABLE; | ||
500 | if (si470x_set_register(radio, POWERCFG) < 0) | ||
501 | return -EIO; | ||
502 | |||
503 | return 0; | ||
504 | } | ||
505 | |||
506 | |||
507 | /* | ||
508 | * si470x_i2c_resume - resume the device | ||
509 | */ | ||
510 | static int si470x_i2c_resume(struct i2c_client *client) | ||
511 | { | ||
512 | struct si470x_device *radio = i2c_get_clientdata(client); | ||
513 | |||
514 | /* power up : need 110ms */ | ||
515 | radio->registers[POWERCFG] |= POWERCFG_ENABLE; | ||
516 | if (si470x_set_register(radio, POWERCFG) < 0) | ||
517 | return -EIO; | ||
518 | msleep(110); | ||
519 | |||
520 | return 0; | ||
521 | } | ||
522 | #else | ||
523 | #define si470x_i2c_suspend NULL | ||
524 | #define si470x_i2c_resume NULL | ||
525 | #endif | ||
526 | |||
527 | |||
357 | /* | 528 | /* |
358 | * si470x_i2c_driver - i2c driver interface | 529 | * si470x_i2c_driver - i2c driver interface |
359 | */ | 530 | */ |
@@ -364,6 +535,8 @@ static struct i2c_driver si470x_i2c_driver = { | |||
364 | }, | 535 | }, |
365 | .probe = si470x_i2c_probe, | 536 | .probe = si470x_i2c_probe, |
366 | .remove = __devexit_p(si470x_i2c_remove), | 537 | .remove = __devexit_p(si470x_i2c_remove), |
538 | .suspend = si470x_i2c_suspend, | ||
539 | .resume = si470x_i2c_resume, | ||
367 | .id_table = si470x_i2c_id, | 540 | .id_table = si470x_i2c_id, |
368 | }; | 541 | }; |
369 | 542 | ||
diff --git a/drivers/media/radio/si470x/radio-si470x-usb.c b/drivers/media/radio/si470x/radio-si470x-usb.c index f2d0e1ddb301..a96e1b9dd646 100644 --- a/drivers/media/radio/si470x/radio-si470x-usb.c +++ b/drivers/media/radio/si470x/radio-si470x-usb.c | |||
@@ -509,89 +509,9 @@ resubmit: | |||
509 | **************************************************************************/ | 509 | **************************************************************************/ |
510 | 510 | ||
511 | /* | 511 | /* |
512 | * si470x_fops_read - read RDS data | ||
513 | */ | ||
514 | static ssize_t si470x_fops_read(struct file *file, char __user *buf, | ||
515 | size_t count, loff_t *ppos) | ||
516 | { | ||
517 | struct si470x_device *radio = video_drvdata(file); | ||
518 | int retval = 0; | ||
519 | unsigned int block_count = 0; | ||
520 | |||
521 | /* switch on rds reception */ | ||
522 | if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) | ||
523 | si470x_rds_on(radio); | ||
524 | |||
525 | /* block if no new data available */ | ||
526 | while (radio->wr_index == radio->rd_index) { | ||
527 | if (file->f_flags & O_NONBLOCK) { | ||
528 | retval = -EWOULDBLOCK; | ||
529 | goto done; | ||
530 | } | ||
531 | if (wait_event_interruptible(radio->read_queue, | ||
532 | radio->wr_index != radio->rd_index) < 0) { | ||
533 | retval = -EINTR; | ||
534 | goto done; | ||
535 | } | ||
536 | } | ||
537 | |||
538 | /* calculate block count from byte count */ | ||
539 | count /= 3; | ||
540 | |||
541 | /* copy RDS block out of internal buffer and to user buffer */ | ||
542 | mutex_lock(&radio->lock); | ||
543 | while (block_count < count) { | ||
544 | if (radio->rd_index == radio->wr_index) | ||
545 | break; | ||
546 | |||
547 | /* always transfer rds complete blocks */ | ||
548 | if (copy_to_user(buf, &radio->buffer[radio->rd_index], 3)) | ||
549 | /* retval = -EFAULT; */ | ||
550 | break; | ||
551 | |||
552 | /* increment and wrap read pointer */ | ||
553 | radio->rd_index += 3; | ||
554 | if (radio->rd_index >= radio->buf_size) | ||
555 | radio->rd_index = 0; | ||
556 | |||
557 | /* increment counters */ | ||
558 | block_count++; | ||
559 | buf += 3; | ||
560 | retval += 3; | ||
561 | } | ||
562 | mutex_unlock(&radio->lock); | ||
563 | |||
564 | done: | ||
565 | return retval; | ||
566 | } | ||
567 | |||
568 | |||
569 | /* | ||
570 | * si470x_fops_poll - poll RDS data | ||
571 | */ | ||
572 | static unsigned int si470x_fops_poll(struct file *file, | ||
573 | struct poll_table_struct *pts) | ||
574 | { | ||
575 | struct si470x_device *radio = video_drvdata(file); | ||
576 | int retval = 0; | ||
577 | |||
578 | /* switch on rds reception */ | ||
579 | if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) | ||
580 | si470x_rds_on(radio); | ||
581 | |||
582 | poll_wait(file, &radio->read_queue, pts); | ||
583 | |||
584 | if (radio->rd_index != radio->wr_index) | ||
585 | retval = POLLIN | POLLRDNORM; | ||
586 | |||
587 | return retval; | ||
588 | } | ||
589 | |||
590 | |||
591 | /* | ||
592 | * si470x_fops_open - file open | 512 | * si470x_fops_open - file open |
593 | */ | 513 | */ |
594 | static int si470x_fops_open(struct file *file) | 514 | int si470x_fops_open(struct file *file) |
595 | { | 515 | { |
596 | struct si470x_device *radio = video_drvdata(file); | 516 | struct si470x_device *radio = video_drvdata(file); |
597 | int retval; | 517 | int retval; |
@@ -645,7 +565,7 @@ done: | |||
645 | /* | 565 | /* |
646 | * si470x_fops_release - file release | 566 | * si470x_fops_release - file release |
647 | */ | 567 | */ |
648 | static int si470x_fops_release(struct file *file) | 568 | int si470x_fops_release(struct file *file) |
649 | { | 569 | { |
650 | struct si470x_device *radio = video_drvdata(file); | 570 | struct si470x_device *radio = video_drvdata(file); |
651 | int retval = 0; | 571 | int retval = 0; |
@@ -688,19 +608,6 @@ done: | |||
688 | } | 608 | } |
689 | 609 | ||
690 | 610 | ||
691 | /* | ||
692 | * si470x_fops - file operations interface | ||
693 | */ | ||
694 | const struct v4l2_file_operations si470x_fops = { | ||
695 | .owner = THIS_MODULE, | ||
696 | .read = si470x_fops_read, | ||
697 | .poll = si470x_fops_poll, | ||
698 | .ioctl = video_ioctl2, | ||
699 | .open = si470x_fops_open, | ||
700 | .release = si470x_fops_release, | ||
701 | }; | ||
702 | |||
703 | |||
704 | 611 | ||
705 | /************************************************************************** | 612 | /************************************************************************** |
706 | * Video4Linux Interface | 613 | * Video4Linux Interface |
diff --git a/drivers/media/radio/si470x/radio-si470x.h b/drivers/media/radio/si470x/radio-si470x.h index d0af194d194c..3cd0a29cd6e7 100644 --- a/drivers/media/radio/si470x/radio-si470x.h +++ b/drivers/media/radio/si470x/radio-si470x.h | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <linux/init.h> | 31 | #include <linux/init.h> |
32 | #include <linux/sched.h> | ||
32 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
33 | #include <linux/smp_lock.h> | 34 | #include <linux/smp_lock.h> |
34 | #include <linux/input.h> | 35 | #include <linux/input.h> |
@@ -181,6 +182,7 @@ struct si470x_device { | |||
181 | 182 | ||
182 | #if defined(CONFIG_I2C_SI470X) || defined(CONFIG_I2C_SI470X_MODULE) | 183 | #if defined(CONFIG_I2C_SI470X) || defined(CONFIG_I2C_SI470X_MODULE) |
183 | struct i2c_client *client; | 184 | struct i2c_client *client; |
185 | struct work_struct radio_work; | ||
184 | #endif | 186 | #endif |
185 | }; | 187 | }; |
186 | 188 | ||
@@ -212,7 +214,6 @@ struct si470x_device { | |||
212 | /************************************************************************** | 214 | /************************************************************************** |
213 | * Common Functions | 215 | * Common Functions |
214 | **************************************************************************/ | 216 | **************************************************************************/ |
215 | extern const struct v4l2_file_operations si470x_fops; | ||
216 | extern struct video_device si470x_viddev_template; | 217 | extern struct video_device si470x_viddev_template; |
217 | int si470x_get_register(struct si470x_device *radio, int regnr); | 218 | int si470x_get_register(struct si470x_device *radio, int regnr); |
218 | int si470x_set_register(struct si470x_device *radio, int regnr); | 219 | int si470x_set_register(struct si470x_device *radio, int regnr); |
@@ -221,5 +222,7 @@ int si470x_set_freq(struct si470x_device *radio, unsigned int freq); | |||
221 | int si470x_start(struct si470x_device *radio); | 222 | int si470x_start(struct si470x_device *radio); |
222 | int si470x_stop(struct si470x_device *radio); | 223 | int si470x_stop(struct si470x_device *radio); |
223 | int si470x_rds_on(struct si470x_device *radio); | 224 | int si470x_rds_on(struct si470x_device *radio); |
225 | int si470x_fops_open(struct file *file); | ||
226 | int si470x_fops_release(struct file *file); | ||
224 | int si470x_vidioc_querycap(struct file *file, void *priv, | 227 | int si470x_vidioc_querycap(struct file *file, void *priv, |
225 | struct v4l2_capability *capability); | 228 | struct v4l2_capability *capability); |
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 9dc74c93bf24..2f83be766d9f 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig | |||
@@ -37,10 +37,6 @@ config VIDEO_BTCX | |||
37 | depends on PCI | 37 | depends on PCI |
38 | tristate | 38 | tristate |
39 | 39 | ||
40 | config VIDEO_IR | ||
41 | tristate | ||
42 | depends on INPUT | ||
43 | |||
44 | config VIDEO_TVEEPROM | 40 | config VIDEO_TVEEPROM |
45 | tristate | 41 | tristate |
46 | depends on I2C | 42 | depends on I2C |
@@ -840,6 +836,12 @@ config SOC_CAMERA_MT9T031 | |||
840 | help | 836 | help |
841 | This driver supports MT9T031 cameras from Micron. | 837 | This driver supports MT9T031 cameras from Micron. |
842 | 838 | ||
839 | config SOC_CAMERA_MT9T112 | ||
840 | tristate "mt9t112 support" | ||
841 | depends on SOC_CAMERA && I2C | ||
842 | help | ||
843 | This driver supports MT9T112 cameras from Aptina. | ||
844 | |||
843 | config SOC_CAMERA_MT9V022 | 845 | config SOC_CAMERA_MT9V022 |
844 | tristate "mt9v022 support" | 846 | tristate "mt9v022 support" |
845 | depends on SOC_CAMERA && I2C | 847 | depends on SOC_CAMERA && I2C |
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 7a2dcc34111c..2af68ee84122 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile | |||
@@ -75,6 +75,7 @@ obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o | |||
75 | obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o | 75 | obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o |
76 | obj-$(CONFIG_SOC_CAMERA_MT9M111) += mt9m111.o | 76 | obj-$(CONFIG_SOC_CAMERA_MT9M111) += mt9m111.o |
77 | obj-$(CONFIG_SOC_CAMERA_MT9T031) += mt9t031.o | 77 | obj-$(CONFIG_SOC_CAMERA_MT9T031) += mt9t031.o |
78 | obj-$(CONFIG_SOC_CAMERA_MT9T112) += mt9t112.o | ||
78 | obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o | 79 | obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o |
79 | obj-$(CONFIG_SOC_CAMERA_OV772X) += ov772x.o | 80 | obj-$(CONFIG_SOC_CAMERA_OV772X) += ov772x.o |
80 | obj-$(CONFIG_SOC_CAMERA_OV9640) += ov9640.o | 81 | obj-$(CONFIG_SOC_CAMERA_OV9640) += ov9640.o |
@@ -149,7 +150,7 @@ obj-$(CONFIG_VIDEO_VIVI) += vivi.o | |||
149 | obj-$(CONFIG_VIDEO_CX23885) += cx23885/ | 150 | obj-$(CONFIG_VIDEO_CX23885) += cx23885/ |
150 | 151 | ||
151 | obj-$(CONFIG_VIDEO_OMAP2) += omap2cam.o | 152 | obj-$(CONFIG_VIDEO_OMAP2) += omap2cam.o |
152 | obj-$(CONFIG_SOC_CAMERA) += soc_camera.o | 153 | obj-$(CONFIG_SOC_CAMERA) += soc_camera.o soc_mediabus.o |
153 | obj-$(CONFIG_SOC_CAMERA_PLATFORM) += soc_camera_platform.o | 154 | obj-$(CONFIG_SOC_CAMERA_PLATFORM) += soc_camera_platform.o |
154 | # soc-camera host drivers have to be linked after camera drivers | 155 | # soc-camera host drivers have to be linked after camera drivers |
155 | obj-$(CONFIG_VIDEO_MX1) += mx1_camera.o | 156 | obj-$(CONFIG_VIDEO_MX1) += mx1_camera.o |
diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c index d137bac84511..a356d6bd3131 100644 --- a/drivers/media/video/arv.c +++ b/drivers/media/video/arv.c | |||
@@ -767,7 +767,6 @@ static struct video_device ar_template = { | |||
767 | .name = "Colour AR VGA", | 767 | .name = "Colour AR VGA", |
768 | .fops = &ar_fops, | 768 | .fops = &ar_fops, |
769 | .release = ar_release, | 769 | .release = ar_release, |
770 | .minor = -1, | ||
771 | }; | 770 | }; |
772 | 771 | ||
773 | #define ALIGN4(x) ((((int)(x)) & 0x3) == 0) | 772 | #define ALIGN4(x) ((((int)(x)) & 0x3) == 0) |
@@ -860,8 +859,8 @@ static int __init ar_init(void) | |||
860 | goto out_dev; | 859 | goto out_dev; |
861 | } | 860 | } |
862 | 861 | ||
863 | printk("video%d: Found M64278 VGA (IRQ %d, Freq %dMHz).\n", | 862 | printk("%s: Found M64278 VGA (IRQ %d, Freq %dMHz).\n", |
864 | ar->vdev->num, M32R_IRQ_INT3, freq); | 863 | video_device_node_name(ar->vdev), M32R_IRQ_INT3, freq); |
865 | 864 | ||
866 | return 0; | 865 | return 0; |
867 | 866 | ||
diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c index 1485aee18d58..dc67bc40f36f 100644 --- a/drivers/media/video/au0828/au0828-video.c +++ b/drivers/media/video/au0828/au0828-video.c | |||
@@ -40,7 +40,6 @@ | |||
40 | #include "au0828.h" | 40 | #include "au0828.h" |
41 | #include "au0828-reg.h" | 41 | #include "au0828-reg.h" |
42 | 42 | ||
43 | static LIST_HEAD(au0828_devlist); | ||
44 | static DEFINE_MUTEX(au0828_sysfs_lock); | 43 | static DEFINE_MUTEX(au0828_sysfs_lock); |
45 | 44 | ||
46 | #define AU0828_VERSION_CODE KERNEL_VERSION(0, 0, 1) | 45 | #define AU0828_VERSION_CODE KERNEL_VERSION(0, 0, 1) |
@@ -693,10 +692,8 @@ void au0828_analog_unregister(struct au0828_dev *dev) | |||
693 | dprintk(1, "au0828_release_resources called\n"); | 692 | dprintk(1, "au0828_release_resources called\n"); |
694 | mutex_lock(&au0828_sysfs_lock); | 693 | mutex_lock(&au0828_sysfs_lock); |
695 | 694 | ||
696 | if (dev->vdev) { | 695 | if (dev->vdev) |
697 | list_del(&dev->au0828list); | ||
698 | video_unregister_device(dev->vdev); | 696 | video_unregister_device(dev->vdev); |
699 | } | ||
700 | if (dev->vbi_dev) | 697 | if (dev->vbi_dev) |
701 | video_unregister_device(dev->vbi_dev); | 698 | video_unregister_device(dev->vbi_dev); |
702 | 699 | ||
@@ -737,29 +734,15 @@ static void res_free(struct au0828_fh *fh) | |||
737 | 734 | ||
738 | static int au0828_v4l2_open(struct file *filp) | 735 | static int au0828_v4l2_open(struct file *filp) |
739 | { | 736 | { |
740 | int minor = video_devdata(filp)->minor; | ||
741 | int ret = 0; | 737 | int ret = 0; |
742 | struct au0828_dev *h, *dev = NULL; | 738 | struct au0828_dev *dev = video_drvdata(filp); |
743 | struct au0828_fh *fh; | 739 | struct au0828_fh *fh; |
744 | int type = 0; | 740 | int type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
745 | struct list_head *list; | 741 | |
746 | |||
747 | list_for_each(list, &au0828_devlist) { | ||
748 | h = list_entry(list, struct au0828_dev, au0828list); | ||
749 | if (h->vdev->minor == minor) { | ||
750 | dev = h; | ||
751 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
752 | } | ||
753 | #ifdef VBI_IS_WORKING | 742 | #ifdef VBI_IS_WORKING |
754 | if (h->vbi_dev->minor == minor) { | 743 | if (video_devdata(filp)->vfl_type == VFL_TYPE_GRABBER) |
755 | dev = h; | 744 | type = V4L2_BUF_TYPE_VBI_CAPTURE; |
756 | type = V4L2_BUF_TYPE_VBI_CAPTURE; | ||
757 | } | ||
758 | #endif | 745 | #endif |
759 | } | ||
760 | |||
761 | if (NULL == dev) | ||
762 | return -ENODEV; | ||
763 | 746 | ||
764 | fh = kzalloc(sizeof(struct au0828_fh), GFP_KERNEL); | 747 | fh = kzalloc(sizeof(struct au0828_fh), GFP_KERNEL); |
765 | if (NULL == fh) { | 748 | if (NULL == fh) { |
@@ -1587,7 +1570,6 @@ static const struct video_device au0828_video_template = { | |||
1587 | .fops = &au0828_v4l_fops, | 1570 | .fops = &au0828_v4l_fops, |
1588 | .release = video_device_release, | 1571 | .release = video_device_release, |
1589 | .ioctl_ops = &video_ioctl_ops, | 1572 | .ioctl_ops = &video_ioctl_ops, |
1590 | .minor = -1, | ||
1591 | .tvnorms = V4L2_STD_NTSC_M, | 1573 | .tvnorms = V4L2_STD_NTSC_M, |
1592 | .current_norm = V4L2_STD_NTSC_M, | 1574 | .current_norm = V4L2_STD_NTSC_M, |
1593 | }; | 1575 | }; |
@@ -1676,25 +1658,23 @@ int au0828_analog_register(struct au0828_dev *dev, | |||
1676 | strcpy(dev->vbi_dev->name, "au0828a vbi"); | 1658 | strcpy(dev->vbi_dev->name, "au0828a vbi"); |
1677 | #endif | 1659 | #endif |
1678 | 1660 | ||
1679 | list_add_tail(&dev->au0828list, &au0828_devlist); | ||
1680 | |||
1681 | /* Register the v4l2 device */ | 1661 | /* Register the v4l2 device */ |
1662 | video_set_drvdata(dev->vdev, dev); | ||
1682 | retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, -1); | 1663 | retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, -1); |
1683 | if (retval != 0) { | 1664 | if (retval != 0) { |
1684 | dprintk(1, "unable to register video device (error = %d).\n", | 1665 | dprintk(1, "unable to register video device (error = %d).\n", |
1685 | retval); | 1666 | retval); |
1686 | list_del(&dev->au0828list); | ||
1687 | video_device_release(dev->vdev); | 1667 | video_device_release(dev->vdev); |
1688 | return -ENODEV; | 1668 | return -ENODEV; |
1689 | } | 1669 | } |
1690 | 1670 | ||
1691 | #ifdef VBI_IS_WORKING | 1671 | #ifdef VBI_IS_WORKING |
1692 | /* Register the vbi device */ | 1672 | /* Register the vbi device */ |
1673 | video_set_drvdata(dev->vbi_dev, dev); | ||
1693 | retval = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, -1); | 1674 | retval = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, -1); |
1694 | if (retval != 0) { | 1675 | if (retval != 0) { |
1695 | dprintk(1, "unable to register vbi device (error = %d).\n", | 1676 | dprintk(1, "unable to register vbi device (error = %d).\n", |
1696 | retval); | 1677 | retval); |
1697 | list_del(&dev->au0828list); | ||
1698 | video_device_release(dev->vbi_dev); | 1678 | video_device_release(dev->vbi_dev); |
1699 | video_device_release(dev->vdev); | 1679 | video_device_release(dev->vdev); |
1700 | return -ENODEV; | 1680 | return -ENODEV; |
diff --git a/drivers/media/video/au0828/au0828.h b/drivers/media/video/au0828/au0828.h index b977915efbd0..207f32dec6a6 100644 --- a/drivers/media/video/au0828/au0828.h +++ b/drivers/media/video/au0828/au0828.h | |||
@@ -192,7 +192,6 @@ struct au0828_dev { | |||
192 | struct au0828_dvb dvb; | 192 | struct au0828_dvb dvb; |
193 | 193 | ||
194 | /* Analog */ | 194 | /* Analog */ |
195 | struct list_head au0828list; | ||
196 | struct v4l2_device v4l2_dev; | 195 | struct v4l2_device v4l2_dev; |
197 | int users; | 196 | int users; |
198 | unsigned int stream_on:1; /* Locks streams */ | 197 | unsigned int stream_on:1; /* Locks streams */ |
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index a6724019c66f..3182a406bdd1 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c | |||
@@ -3206,24 +3206,24 @@ err: | |||
3206 | 3206 | ||
3207 | static int bttv_open(struct file *file) | 3207 | static int bttv_open(struct file *file) |
3208 | { | 3208 | { |
3209 | int minor = video_devdata(file)->minor; | 3209 | struct video_device *vdev = video_devdata(file); |
3210 | struct bttv *btv = video_drvdata(file); | 3210 | struct bttv *btv = video_drvdata(file); |
3211 | struct bttv_fh *fh; | 3211 | struct bttv_fh *fh; |
3212 | enum v4l2_buf_type type = 0; | 3212 | enum v4l2_buf_type type = 0; |
3213 | 3213 | ||
3214 | dprintk(KERN_DEBUG "bttv: open minor=%d\n",minor); | 3214 | dprintk(KERN_DEBUG "bttv: open dev=%s\n", video_device_node_name(vdev)); |
3215 | 3215 | ||
3216 | lock_kernel(); | 3216 | if (vdev->vfl_type == VFL_TYPE_GRABBER) { |
3217 | if (btv->video_dev->minor == minor) { | ||
3218 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 3217 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
3219 | } else if (btv->vbi_dev->minor == minor) { | 3218 | } else if (vdev->vfl_type == VFL_TYPE_VBI) { |
3220 | type = V4L2_BUF_TYPE_VBI_CAPTURE; | 3219 | type = V4L2_BUF_TYPE_VBI_CAPTURE; |
3221 | } else { | 3220 | } else { |
3222 | WARN_ON(1); | 3221 | WARN_ON(1); |
3223 | unlock_kernel(); | ||
3224 | return -ENODEV; | 3222 | return -ENODEV; |
3225 | } | 3223 | } |
3226 | 3224 | ||
3225 | lock_kernel(); | ||
3226 | |||
3227 | dprintk(KERN_DEBUG "bttv%d: open called (type=%s)\n", | 3227 | dprintk(KERN_DEBUG "bttv%d: open called (type=%s)\n", |
3228 | btv->c.nr,v4l2_type_names[type]); | 3228 | btv->c.nr,v4l2_type_names[type]); |
3229 | 3229 | ||
@@ -3397,7 +3397,6 @@ static const struct v4l2_ioctl_ops bttv_ioctl_ops = { | |||
3397 | 3397 | ||
3398 | static struct video_device bttv_video_template = { | 3398 | static struct video_device bttv_video_template = { |
3399 | .fops = &bttv_fops, | 3399 | .fops = &bttv_fops, |
3400 | .minor = -1, | ||
3401 | .ioctl_ops = &bttv_ioctl_ops, | 3400 | .ioctl_ops = &bttv_ioctl_ops, |
3402 | .tvnorms = BTTV_NORMS, | 3401 | .tvnorms = BTTV_NORMS, |
3403 | .current_norm = V4L2_STD_PAL, | 3402 | .current_norm = V4L2_STD_PAL, |
@@ -3408,18 +3407,13 @@ static struct video_device bttv_video_template = { | |||
3408 | 3407 | ||
3409 | static int radio_open(struct file *file) | 3408 | static int radio_open(struct file *file) |
3410 | { | 3409 | { |
3411 | int minor = video_devdata(file)->minor; | 3410 | struct video_device *vdev = video_devdata(file); |
3412 | struct bttv *btv = video_drvdata(file); | 3411 | struct bttv *btv = video_drvdata(file); |
3413 | struct bttv_fh *fh; | 3412 | struct bttv_fh *fh; |
3414 | 3413 | ||
3415 | dprintk("bttv: open minor=%d\n",minor); | 3414 | dprintk("bttv: open dev=%s\n", video_device_node_name(vdev)); |
3416 | 3415 | ||
3417 | lock_kernel(); | 3416 | lock_kernel(); |
3418 | WARN_ON(btv->radio_dev && btv->radio_dev->minor != minor); | ||
3419 | if (!btv->radio_dev || btv->radio_dev->minor != minor) { | ||
3420 | unlock_kernel(); | ||
3421 | return -ENODEV; | ||
3422 | } | ||
3423 | 3417 | ||
3424 | dprintk("bttv%d: open called (radio)\n",btv->c.nr); | 3418 | dprintk("bttv%d: open called (radio)\n",btv->c.nr); |
3425 | 3419 | ||
@@ -3640,7 +3634,6 @@ static const struct v4l2_ioctl_ops radio_ioctl_ops = { | |||
3640 | 3634 | ||
3641 | static struct video_device radio_template = { | 3635 | static struct video_device radio_template = { |
3642 | .fops = &radio_fops, | 3636 | .fops = &radio_fops, |
3643 | .minor = -1, | ||
3644 | .ioctl_ops = &radio_ioctl_ops, | 3637 | .ioctl_ops = &radio_ioctl_ops, |
3645 | }; | 3638 | }; |
3646 | 3639 | ||
@@ -4208,21 +4201,21 @@ static struct video_device *vdev_init(struct bttv *btv, | |||
4208 | static void bttv_unregister_video(struct bttv *btv) | 4201 | static void bttv_unregister_video(struct bttv *btv) |
4209 | { | 4202 | { |
4210 | if (btv->video_dev) { | 4203 | if (btv->video_dev) { |
4211 | if (-1 != btv->video_dev->minor) | 4204 | if (video_is_registered(btv->video_dev)) |
4212 | video_unregister_device(btv->video_dev); | 4205 | video_unregister_device(btv->video_dev); |
4213 | else | 4206 | else |
4214 | video_device_release(btv->video_dev); | 4207 | video_device_release(btv->video_dev); |
4215 | btv->video_dev = NULL; | 4208 | btv->video_dev = NULL; |
4216 | } | 4209 | } |
4217 | if (btv->vbi_dev) { | 4210 | if (btv->vbi_dev) { |
4218 | if (-1 != btv->vbi_dev->minor) | 4211 | if (video_is_registered(btv->vbi_dev)) |
4219 | video_unregister_device(btv->vbi_dev); | 4212 | video_unregister_device(btv->vbi_dev); |
4220 | else | 4213 | else |
4221 | video_device_release(btv->vbi_dev); | 4214 | video_device_release(btv->vbi_dev); |
4222 | btv->vbi_dev = NULL; | 4215 | btv->vbi_dev = NULL; |
4223 | } | 4216 | } |
4224 | if (btv->radio_dev) { | 4217 | if (btv->radio_dev) { |
4225 | if (-1 != btv->radio_dev->minor) | 4218 | if (video_is_registered(btv->radio_dev)) |
4226 | video_unregister_device(btv->radio_dev); | 4219 | video_unregister_device(btv->radio_dev); |
4227 | else | 4220 | else |
4228 | video_device_release(btv->radio_dev); | 4221 | video_device_release(btv->radio_dev); |
@@ -4244,8 +4237,8 @@ static int __devinit bttv_register_video(struct bttv *btv) | |||
4244 | if (video_register_device(btv->video_dev, VFL_TYPE_GRABBER, | 4237 | if (video_register_device(btv->video_dev, VFL_TYPE_GRABBER, |
4245 | video_nr[btv->c.nr]) < 0) | 4238 | video_nr[btv->c.nr]) < 0) |
4246 | goto err; | 4239 | goto err; |
4247 | printk(KERN_INFO "bttv%d: registered device video%d\n", | 4240 | printk(KERN_INFO "bttv%d: registered device %s\n", |
4248 | btv->c.nr, btv->video_dev->num); | 4241 | btv->c.nr, video_device_node_name(btv->video_dev)); |
4249 | if (device_create_file(&btv->video_dev->dev, | 4242 | if (device_create_file(&btv->video_dev->dev, |
4250 | &dev_attr_card)<0) { | 4243 | &dev_attr_card)<0) { |
4251 | printk(KERN_ERR "bttv%d: device_create_file 'card' " | 4244 | printk(KERN_ERR "bttv%d: device_create_file 'card' " |
@@ -4261,8 +4254,8 @@ static int __devinit bttv_register_video(struct bttv *btv) | |||
4261 | if (video_register_device(btv->vbi_dev, VFL_TYPE_VBI, | 4254 | if (video_register_device(btv->vbi_dev, VFL_TYPE_VBI, |
4262 | vbi_nr[btv->c.nr]) < 0) | 4255 | vbi_nr[btv->c.nr]) < 0) |
4263 | goto err; | 4256 | goto err; |
4264 | printk(KERN_INFO "bttv%d: registered device vbi%d\n", | 4257 | printk(KERN_INFO "bttv%d: registered device %s\n", |
4265 | btv->c.nr, btv->vbi_dev->num); | 4258 | btv->c.nr, video_device_node_name(btv->vbi_dev)); |
4266 | 4259 | ||
4267 | if (!btv->has_radio) | 4260 | if (!btv->has_radio) |
4268 | return 0; | 4261 | return 0; |
@@ -4273,8 +4266,8 @@ static int __devinit bttv_register_video(struct bttv *btv) | |||
4273 | if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO, | 4266 | if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO, |
4274 | radio_nr[btv->c.nr]) < 0) | 4267 | radio_nr[btv->c.nr]) < 0) |
4275 | goto err; | 4268 | goto err; |
4276 | printk(KERN_INFO "bttv%d: registered device radio%d\n", | 4269 | printk(KERN_INFO "bttv%d: registered device %s\n", |
4277 | btv->c.nr, btv->radio_dev->num); | 4270 | btv->c.nr, video_device_node_name(btv->radio_dev)); |
4278 | 4271 | ||
4279 | /* all done */ | 4272 | /* all done */ |
4280 | return 0; | 4273 | return 0; |
diff --git a/drivers/media/video/bt8xx/bttv-i2c.c b/drivers/media/video/bt8xx/bttv-i2c.c index beda363418b0..63aa31a041e8 100644 --- a/drivers/media/video/bt8xx/bttv-i2c.c +++ b/drivers/media/video/bt8xx/bttv-i2c.c | |||
@@ -40,7 +40,7 @@ static int i2c_debug; | |||
40 | static int i2c_hw; | 40 | static int i2c_hw; |
41 | static int i2c_scan; | 41 | static int i2c_scan; |
42 | module_param(i2c_debug, int, 0644); | 42 | module_param(i2c_debug, int, 0644); |
43 | MODULE_PARM_DESC(i2c_hw,"configure i2c debug level"); | 43 | MODULE_PARM_DESC(i2c_debug, "configure i2c debug level"); |
44 | module_param(i2c_hw, int, 0444); | 44 | module_param(i2c_hw, int, 0444); |
45 | MODULE_PARM_DESC(i2c_hw,"force use of hardware i2c support, " | 45 | MODULE_PARM_DESC(i2c_hw,"force use of hardware i2c support, " |
46 | "instead of software bitbang"); | 46 | "instead of software bitbang"); |
@@ -400,7 +400,7 @@ int __devinit init_bttv_i2c(struct bttv *btv) | |||
400 | That's why we probe 0x1a (~0x34) first. CB | 400 | That's why we probe 0x1a (~0x34) first. CB |
401 | */ | 401 | */ |
402 | const unsigned short addr_list[] = { | 402 | const unsigned short addr_list[] = { |
403 | 0x1a, 0x18, 0x4b, 0x64, 0x30, | 403 | 0x1a, 0x18, 0x4b, 0x64, 0x30, 0x71, |
404 | I2C_CLIENT_END | 404 | I2C_CLIENT_END |
405 | }; | 405 | }; |
406 | 406 | ||
diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c index 84a957e52c4b..277a092e1214 100644 --- a/drivers/media/video/bt8xx/bttv-input.c +++ b/drivers/media/video/bt8xx/bttv-input.c | |||
@@ -368,7 +368,7 @@ int bttv_input_init(struct bttv *btv) | |||
368 | snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", | 368 | snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", |
369 | pci_name(btv->c.pci)); | 369 | pci_name(btv->c.pci)); |
370 | 370 | ||
371 | err = ir_input_init(input_dev, &ir->ir, ir_type, ir_codes); | 371 | err = ir_input_init(input_dev, &ir->ir, ir_type); |
372 | if (err < 0) | 372 | if (err < 0) |
373 | goto err_out_free; | 373 | goto err_out_free; |
374 | 374 | ||
@@ -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 = input_register_device(btv->remote->dev); | 392 | err = ir_input_register(btv->remote->dev, ir_codes); |
393 | if (err) | 393 | if (err) |
394 | goto err_out_stop; | 394 | goto err_out_stop; |
395 | 395 | ||
@@ -403,8 +403,6 @@ int bttv_input_init(struct bttv *btv) | |||
403 | bttv_ir_stop(btv); | 403 | bttv_ir_stop(btv); |
404 | btv->remote = NULL; | 404 | btv->remote = NULL; |
405 | err_out_free: | 405 | err_out_free: |
406 | ir_input_free(input_dev); | ||
407 | input_free_device(input_dev); | ||
408 | kfree(ir); | 406 | kfree(ir); |
409 | return err; | 407 | return err; |
410 | } | 408 | } |
@@ -415,8 +413,7 @@ void bttv_input_fini(struct bttv *btv) | |||
415 | return; | 413 | return; |
416 | 414 | ||
417 | bttv_ir_stop(btv); | 415 | bttv_ir_stop(btv); |
418 | ir_input_free(btv->remote->dev); | 416 | ir_input_unregister(btv->remote->dev); |
419 | input_unregister_device(btv->remote->dev); | ||
420 | kfree(btv->remote); | 417 | kfree(btv->remote); |
421 | btv->remote = NULL; | 418 | btv->remote = NULL; |
422 | } | 419 | } |
diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c index 85cf1778827a..e2cbebab959b 100644 --- a/drivers/media/video/c-qcam.c +++ b/drivers/media/video/c-qcam.c | |||
@@ -809,8 +809,8 @@ static int init_cqcam(struct parport *port) | |||
809 | return -ENODEV; | 809 | return -ENODEV; |
810 | } | 810 | } |
811 | 811 | ||
812 | printk(KERN_INFO "video%d: Colour QuickCam found on %s\n", | 812 | printk(KERN_INFO "%s: Colour QuickCam found on %s\n", |
813 | qcam->vdev.num, qcam->pport->name); | 813 | video_device_node_name(&qcam->vdev), qcam->pport->name); |
814 | 814 | ||
815 | qcams[num_cams++] = qcam; | 815 | qcams[num_cams++] = qcam; |
816 | 816 | ||
diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c index 10230cb3d210..7bb9c1ec7819 100644 --- a/drivers/media/video/cafe_ccic.c +++ b/drivers/media/video/cafe_ccic.c | |||
@@ -1723,7 +1723,6 @@ static const struct v4l2_ioctl_ops cafe_v4l_ioctl_ops = { | |||
1723 | 1723 | ||
1724 | static struct video_device cafe_v4l_template = { | 1724 | static struct video_device cafe_v4l_template = { |
1725 | .name = "cafe", | 1725 | .name = "cafe", |
1726 | .minor = -1, /* Get one dynamically */ | ||
1727 | .tvnorms = V4L2_STD_NTSC_M, | 1726 | .tvnorms = V4L2_STD_NTSC_M, |
1728 | .current_norm = V4L2_STD_NTSC_M, /* make mplayer happy */ | 1727 | .current_norm = V4L2_STD_NTSC_M, /* make mplayer happy */ |
1729 | 1728 | ||
diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c index 2377313c041a..551ddf216a4b 100644 --- a/drivers/media/video/cpia.c +++ b/drivers/media/video/cpia.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/fs.h> | 32 | #include <linux/fs.h> |
33 | #include <linux/vmalloc.h> | 33 | #include <linux/vmalloc.h> |
34 | #include <linux/sched.h> | 34 | #include <linux/sched.h> |
35 | #include <linux/seq_file.h> | ||
35 | #include <linux/slab.h> | 36 | #include <linux/slab.h> |
36 | #include <linux/proc_fs.h> | 37 | #include <linux/proc_fs.h> |
37 | #include <linux/ctype.h> | 38 | #include <linux/ctype.h> |
@@ -244,72 +245,67 @@ static void rvfree(void *mem, unsigned long size) | |||
244 | #ifdef CONFIG_PROC_FS | 245 | #ifdef CONFIG_PROC_FS |
245 | static struct proc_dir_entry *cpia_proc_root=NULL; | 246 | static struct proc_dir_entry *cpia_proc_root=NULL; |
246 | 247 | ||
247 | static int cpia_read_proc(char *page, char **start, off_t off, | 248 | static int cpia_proc_show(struct seq_file *m, void *v) |
248 | int count, int *eof, void *data) | ||
249 | { | 249 | { |
250 | char *out = page; | 250 | struct cam_data *cam = m->private; |
251 | int len, tmp; | 251 | int tmp; |
252 | struct cam_data *cam = data; | ||
253 | char tmpstr[29]; | 252 | char tmpstr[29]; |
254 | 253 | ||
255 | /* IMPORTANT: This output MUST be kept under PAGE_SIZE | 254 | seq_printf(m, "read-only\n-----------------------\n"); |
256 | * or we need to get more sophisticated. */ | 255 | seq_printf(m, "V4L Driver version: %d.%d.%d\n", |
257 | |||
258 | out += sprintf(out, "read-only\n-----------------------\n"); | ||
259 | out += sprintf(out, "V4L Driver version: %d.%d.%d\n", | ||
260 | CPIA_MAJ_VER, CPIA_MIN_VER, CPIA_PATCH_VER); | 256 | CPIA_MAJ_VER, CPIA_MIN_VER, CPIA_PATCH_VER); |
261 | out += sprintf(out, "CPIA Version: %d.%02d (%d.%d)\n", | 257 | seq_printf(m, "CPIA Version: %d.%02d (%d.%d)\n", |
262 | cam->params.version.firmwareVersion, | 258 | cam->params.version.firmwareVersion, |
263 | cam->params.version.firmwareRevision, | 259 | cam->params.version.firmwareRevision, |
264 | cam->params.version.vcVersion, | 260 | cam->params.version.vcVersion, |
265 | cam->params.version.vcRevision); | 261 | cam->params.version.vcRevision); |
266 | out += sprintf(out, "CPIA PnP-ID: %04x:%04x:%04x\n", | 262 | seq_printf(m, "CPIA PnP-ID: %04x:%04x:%04x\n", |
267 | cam->params.pnpID.vendor, cam->params.pnpID.product, | 263 | cam->params.pnpID.vendor, cam->params.pnpID.product, |
268 | cam->params.pnpID.deviceRevision); | 264 | cam->params.pnpID.deviceRevision); |
269 | out += sprintf(out, "VP-Version: %d.%d %04x\n", | 265 | seq_printf(m, "VP-Version: %d.%d %04x\n", |
270 | cam->params.vpVersion.vpVersion, | 266 | cam->params.vpVersion.vpVersion, |
271 | cam->params.vpVersion.vpRevision, | 267 | cam->params.vpVersion.vpRevision, |
272 | cam->params.vpVersion.cameraHeadID); | 268 | cam->params.vpVersion.cameraHeadID); |
273 | 269 | ||
274 | out += sprintf(out, "system_state: %#04x\n", | 270 | seq_printf(m, "system_state: %#04x\n", |
275 | cam->params.status.systemState); | 271 | cam->params.status.systemState); |
276 | out += sprintf(out, "grab_state: %#04x\n", | 272 | seq_printf(m, "grab_state: %#04x\n", |
277 | cam->params.status.grabState); | 273 | cam->params.status.grabState); |
278 | out += sprintf(out, "stream_state: %#04x\n", | 274 | seq_printf(m, "stream_state: %#04x\n", |
279 | cam->params.status.streamState); | 275 | cam->params.status.streamState); |
280 | out += sprintf(out, "fatal_error: %#04x\n", | 276 | seq_printf(m, "fatal_error: %#04x\n", |
281 | cam->params.status.fatalError); | 277 | cam->params.status.fatalError); |
282 | out += sprintf(out, "cmd_error: %#04x\n", | 278 | seq_printf(m, "cmd_error: %#04x\n", |
283 | cam->params.status.cmdError); | 279 | cam->params.status.cmdError); |
284 | out += sprintf(out, "debug_flags: %#04x\n", | 280 | seq_printf(m, "debug_flags: %#04x\n", |
285 | cam->params.status.debugFlags); | 281 | cam->params.status.debugFlags); |
286 | out += sprintf(out, "vp_status: %#04x\n", | 282 | seq_printf(m, "vp_status: %#04x\n", |
287 | cam->params.status.vpStatus); | 283 | cam->params.status.vpStatus); |
288 | out += sprintf(out, "error_code: %#04x\n", | 284 | seq_printf(m, "error_code: %#04x\n", |
289 | cam->params.status.errorCode); | 285 | cam->params.status.errorCode); |
290 | /* QX3 specific entries */ | 286 | /* QX3 specific entries */ |
291 | if (cam->params.qx3.qx3_detected) { | 287 | if (cam->params.qx3.qx3_detected) { |
292 | out += sprintf(out, "button: %4d\n", | 288 | seq_printf(m, "button: %4d\n", |
293 | cam->params.qx3.button); | 289 | cam->params.qx3.button); |
294 | out += sprintf(out, "cradled: %4d\n", | 290 | seq_printf(m, "cradled: %4d\n", |
295 | cam->params.qx3.cradled); | 291 | cam->params.qx3.cradled); |
296 | } | 292 | } |
297 | out += sprintf(out, "video_size: %s\n", | 293 | seq_printf(m, "video_size: %s\n", |
298 | cam->params.format.videoSize == VIDEOSIZE_CIF ? | 294 | cam->params.format.videoSize == VIDEOSIZE_CIF ? |
299 | "CIF " : "QCIF"); | 295 | "CIF " : "QCIF"); |
300 | out += sprintf(out, "roi: (%3d, %3d) to (%3d, %3d)\n", | 296 | seq_printf(m, "roi: (%3d, %3d) to (%3d, %3d)\n", |
301 | cam->params.roi.colStart*8, | 297 | cam->params.roi.colStart*8, |
302 | cam->params.roi.rowStart*4, | 298 | cam->params.roi.rowStart*4, |
303 | cam->params.roi.colEnd*8, | 299 | cam->params.roi.colEnd*8, |
304 | cam->params.roi.rowEnd*4); | 300 | cam->params.roi.rowEnd*4); |
305 | out += sprintf(out, "actual_fps: %3d\n", cam->fps); | 301 | seq_printf(m, "actual_fps: %3d\n", cam->fps); |
306 | out += sprintf(out, "transfer_rate: %4dkB/s\n", | 302 | seq_printf(m, "transfer_rate: %4dkB/s\n", |
307 | cam->transfer_rate); | 303 | cam->transfer_rate); |
308 | 304 | ||
309 | out += sprintf(out, "\nread-write\n"); | 305 | seq_printf(m, "\nread-write\n"); |
310 | out += sprintf(out, "----------------------- current min" | 306 | seq_printf(m, "----------------------- current min" |
311 | " max default comment\n"); | 307 | " max default comment\n"); |
312 | out += sprintf(out, "brightness: %8d %8d %8d %8d\n", | 308 | seq_printf(m, "brightness: %8d %8d %8d %8d\n", |
313 | cam->params.colourParams.brightness, 0, 100, 50); | 309 | cam->params.colourParams.brightness, 0, 100, 50); |
314 | if (cam->params.version.firmwareVersion == 1 && | 310 | if (cam->params.version.firmwareVersion == 1 && |
315 | cam->params.version.firmwareRevision == 2) | 311 | cam->params.version.firmwareRevision == 2) |
@@ -318,26 +314,26 @@ static int cpia_read_proc(char *page, char **start, off_t off, | |||
318 | else | 314 | else |
319 | tmp = 96; | 315 | tmp = 96; |
320 | 316 | ||
321 | out += sprintf(out, "contrast: %8d %8d %8d %8d" | 317 | seq_printf(m, "contrast: %8d %8d %8d %8d" |
322 | " steps of 8\n", | 318 | " steps of 8\n", |
323 | cam->params.colourParams.contrast, 0, tmp, 48); | 319 | cam->params.colourParams.contrast, 0, tmp, 48); |
324 | out += sprintf(out, "saturation: %8d %8d %8d %8d\n", | 320 | seq_printf(m, "saturation: %8d %8d %8d %8d\n", |
325 | cam->params.colourParams.saturation, 0, 100, 50); | 321 | cam->params.colourParams.saturation, 0, 100, 50); |
326 | tmp = (25000+5000*cam->params.sensorFps.baserate)/ | 322 | tmp = (25000+5000*cam->params.sensorFps.baserate)/ |
327 | (1<<cam->params.sensorFps.divisor); | 323 | (1<<cam->params.sensorFps.divisor); |
328 | out += sprintf(out, "sensor_fps: %4d.%03d %8d %8d %8d\n", | 324 | seq_printf(m, "sensor_fps: %4d.%03d %8d %8d %8d\n", |
329 | tmp/1000, tmp%1000, 3, 30, 15); | 325 | tmp/1000, tmp%1000, 3, 30, 15); |
330 | out += sprintf(out, "stream_start_line: %8d %8d %8d %8d\n", | 326 | seq_printf(m, "stream_start_line: %8d %8d %8d %8d\n", |
331 | 2*cam->params.streamStartLine, 0, | 327 | 2*cam->params.streamStartLine, 0, |
332 | cam->params.format.videoSize == VIDEOSIZE_CIF ? 288:144, | 328 | cam->params.format.videoSize == VIDEOSIZE_CIF ? 288:144, |
333 | cam->params.format.videoSize == VIDEOSIZE_CIF ? 240:120); | 329 | cam->params.format.videoSize == VIDEOSIZE_CIF ? 240:120); |
334 | out += sprintf(out, "sub_sample: %8s %8s %8s %8s\n", | 330 | seq_printf(m, "sub_sample: %8s %8s %8s %8s\n", |
335 | cam->params.format.subSample == SUBSAMPLE_420 ? | 331 | cam->params.format.subSample == SUBSAMPLE_420 ? |
336 | "420" : "422", "420", "422", "422"); | 332 | "420" : "422", "420", "422", "422"); |
337 | out += sprintf(out, "yuv_order: %8s %8s %8s %8s\n", | 333 | seq_printf(m, "yuv_order: %8s %8s %8s %8s\n", |
338 | cam->params.format.yuvOrder == YUVORDER_YUYV ? | 334 | cam->params.format.yuvOrder == YUVORDER_YUYV ? |
339 | "YUYV" : "UYVY", "YUYV" , "UYVY", "YUYV"); | 335 | "YUYV" : "UYVY", "YUYV" , "UYVY", "YUYV"); |
340 | out += sprintf(out, "ecp_timing: %8s %8s %8s %8s\n", | 336 | seq_printf(m, "ecp_timing: %8s %8s %8s %8s\n", |
341 | cam->params.ecpTiming ? "slow" : "normal", "slow", | 337 | cam->params.ecpTiming ? "slow" : "normal", "slow", |
342 | "normal", "normal"); | 338 | "normal", "normal"); |
343 | 339 | ||
@@ -346,13 +342,13 @@ static int cpia_read_proc(char *page, char **start, off_t off, | |||
346 | } else { | 342 | } else { |
347 | sprintf(tmpstr, "manual"); | 343 | sprintf(tmpstr, "manual"); |
348 | } | 344 | } |
349 | out += sprintf(out, "color_balance_mode: %8s %8s %8s" | 345 | seq_printf(m, "color_balance_mode: %8s %8s %8s" |
350 | " %8s\n", tmpstr, "manual", "auto", "auto"); | 346 | " %8s\n", tmpstr, "manual", "auto", "auto"); |
351 | out += sprintf(out, "red_gain: %8d %8d %8d %8d\n", | 347 | seq_printf(m, "red_gain: %8d %8d %8d %8d\n", |
352 | cam->params.colourBalance.redGain, 0, 212, 32); | 348 | cam->params.colourBalance.redGain, 0, 212, 32); |
353 | out += sprintf(out, "green_gain: %8d %8d %8d %8d\n", | 349 | seq_printf(m, "green_gain: %8d %8d %8d %8d\n", |
354 | cam->params.colourBalance.greenGain, 0, 212, 6); | 350 | cam->params.colourBalance.greenGain, 0, 212, 6); |
355 | out += sprintf(out, "blue_gain: %8d %8d %8d %8d\n", | 351 | seq_printf(m, "blue_gain: %8d %8d %8d %8d\n", |
356 | cam->params.colourBalance.blueGain, 0, 212, 92); | 352 | cam->params.colourBalance.blueGain, 0, 212, 92); |
357 | 353 | ||
358 | if (cam->params.version.firmwareVersion == 1 && | 354 | if (cam->params.version.firmwareVersion == 1 && |
@@ -363,10 +359,10 @@ static int cpia_read_proc(char *page, char **start, off_t off, | |||
363 | sprintf(tmpstr, "%8d %8d %8d", 1, 8, 2); | 359 | sprintf(tmpstr, "%8d %8d %8d", 1, 8, 2); |
364 | 360 | ||
365 | if (cam->params.exposure.gainMode == 0) | 361 | if (cam->params.exposure.gainMode == 0) |
366 | out += sprintf(out, "max_gain: unknown %28s" | 362 | seq_printf(m, "max_gain: unknown %28s" |
367 | " powers of 2\n", tmpstr); | 363 | " powers of 2\n", tmpstr); |
368 | else | 364 | else |
369 | out += sprintf(out, "max_gain: %8d %28s" | 365 | seq_printf(m, "max_gain: %8d %28s" |
370 | " 1,2,4 or 8 \n", | 366 | " 1,2,4 or 8 \n", |
371 | 1<<(cam->params.exposure.gainMode-1), tmpstr); | 367 | 1<<(cam->params.exposure.gainMode-1), tmpstr); |
372 | 368 | ||
@@ -382,12 +378,12 @@ static int cpia_read_proc(char *page, char **start, off_t off, | |||
382 | sprintf(tmpstr, "unknown"); | 378 | sprintf(tmpstr, "unknown"); |
383 | break; | 379 | break; |
384 | } | 380 | } |
385 | out += sprintf(out, "exposure_mode: %8s %8s %8s" | 381 | seq_printf(m, "exposure_mode: %8s %8s %8s" |
386 | " %8s\n", tmpstr, "manual", "auto", "auto"); | 382 | " %8s\n", tmpstr, "manual", "auto", "auto"); |
387 | out += sprintf(out, "centre_weight: %8s %8s %8s %8s\n", | 383 | seq_printf(m, "centre_weight: %8s %8s %8s %8s\n", |
388 | (2-cam->params.exposure.centreWeight) ? "on" : "off", | 384 | (2-cam->params.exposure.centreWeight) ? "on" : "off", |
389 | "off", "on", "on"); | 385 | "off", "on", "on"); |
390 | out += sprintf(out, "gain: %8d %8d max_gain %8d 1,2,4,8 possible\n", | 386 | seq_printf(m, "gain: %8d %8d max_gain %8d 1,2,4,8 possible\n", |
391 | 1<<cam->params.exposure.gain, 1, 1); | 387 | 1<<cam->params.exposure.gain, 1, 1); |
392 | if (cam->params.version.firmwareVersion == 1 && | 388 | if (cam->params.version.firmwareVersion == 1 && |
393 | cam->params.version.firmwareRevision == 2) | 389 | cam->params.version.firmwareRevision == 2) |
@@ -396,7 +392,7 @@ static int cpia_read_proc(char *page, char **start, off_t off, | |||
396 | else | 392 | else |
397 | tmp = 510; | 393 | tmp = 510; |
398 | 394 | ||
399 | out += sprintf(out, "fine_exp: %8d %8d %8d %8d\n", | 395 | seq_printf(m, "fine_exp: %8d %8d %8d %8d\n", |
400 | cam->params.exposure.fineExp*2, 0, tmp, 0); | 396 | cam->params.exposure.fineExp*2, 0, tmp, 0); |
401 | if (cam->params.version.firmwareVersion == 1 && | 397 | if (cam->params.version.firmwareVersion == 1 && |
402 | cam->params.version.firmwareRevision == 2) | 398 | cam->params.version.firmwareRevision == 2) |
@@ -405,127 +401,122 @@ static int cpia_read_proc(char *page, char **start, off_t off, | |||
405 | else | 401 | else |
406 | tmp = MAX_EXP; | 402 | tmp = MAX_EXP; |
407 | 403 | ||
408 | out += sprintf(out, "coarse_exp: %8d %8d %8d" | 404 | seq_printf(m, "coarse_exp: %8d %8d %8d" |
409 | " %8d\n", cam->params.exposure.coarseExpLo+ | 405 | " %8d\n", cam->params.exposure.coarseExpLo+ |
410 | 256*cam->params.exposure.coarseExpHi, 0, tmp, 185); | 406 | 256*cam->params.exposure.coarseExpHi, 0, tmp, 185); |
411 | out += sprintf(out, "red_comp: %8d %8d %8d %8d\n", | 407 | seq_printf(m, "red_comp: %8d %8d %8d %8d\n", |
412 | cam->params.exposure.redComp, COMP_RED, 255, COMP_RED); | 408 | cam->params.exposure.redComp, COMP_RED, 255, COMP_RED); |
413 | out += sprintf(out, "green1_comp: %8d %8d %8d %8d\n", | 409 | seq_printf(m, "green1_comp: %8d %8d %8d %8d\n", |
414 | cam->params.exposure.green1Comp, COMP_GREEN1, 255, | 410 | cam->params.exposure.green1Comp, COMP_GREEN1, 255, |
415 | COMP_GREEN1); | 411 | COMP_GREEN1); |
416 | out += sprintf(out, "green2_comp: %8d %8d %8d %8d\n", | 412 | seq_printf(m, "green2_comp: %8d %8d %8d %8d\n", |
417 | cam->params.exposure.green2Comp, COMP_GREEN2, 255, | 413 | cam->params.exposure.green2Comp, COMP_GREEN2, 255, |
418 | COMP_GREEN2); | 414 | COMP_GREEN2); |
419 | out += sprintf(out, "blue_comp: %8d %8d %8d %8d\n", | 415 | seq_printf(m, "blue_comp: %8d %8d %8d %8d\n", |
420 | cam->params.exposure.blueComp, COMP_BLUE, 255, COMP_BLUE); | 416 | cam->params.exposure.blueComp, COMP_BLUE, 255, COMP_BLUE); |
421 | 417 | ||
422 | out += sprintf(out, "apcor_gain1: %#8x %#8x %#8x %#8x\n", | 418 | seq_printf(m, "apcor_gain1: %#8x %#8x %#8x %#8x\n", |
423 | cam->params.apcor.gain1, 0, 0xff, 0x1c); | 419 | cam->params.apcor.gain1, 0, 0xff, 0x1c); |
424 | out += sprintf(out, "apcor_gain2: %#8x %#8x %#8x %#8x\n", | 420 | seq_printf(m, "apcor_gain2: %#8x %#8x %#8x %#8x\n", |
425 | cam->params.apcor.gain2, 0, 0xff, 0x1a); | 421 | cam->params.apcor.gain2, 0, 0xff, 0x1a); |
426 | out += sprintf(out, "apcor_gain4: %#8x %#8x %#8x %#8x\n", | 422 | seq_printf(m, "apcor_gain4: %#8x %#8x %#8x %#8x\n", |
427 | cam->params.apcor.gain4, 0, 0xff, 0x2d); | 423 | cam->params.apcor.gain4, 0, 0xff, 0x2d); |
428 | out += sprintf(out, "apcor_gain8: %#8x %#8x %#8x %#8x\n", | 424 | seq_printf(m, "apcor_gain8: %#8x %#8x %#8x %#8x\n", |
429 | cam->params.apcor.gain8, 0, 0xff, 0x2a); | 425 | cam->params.apcor.gain8, 0, 0xff, 0x2a); |
430 | out += sprintf(out, "vl_offset_gain1: %8d %8d %8d %8d\n", | 426 | seq_printf(m, "vl_offset_gain1: %8d %8d %8d %8d\n", |
431 | cam->params.vlOffset.gain1, 0, 255, 24); | 427 | cam->params.vlOffset.gain1, 0, 255, 24); |
432 | out += sprintf(out, "vl_offset_gain2: %8d %8d %8d %8d\n", | 428 | seq_printf(m, "vl_offset_gain2: %8d %8d %8d %8d\n", |
433 | cam->params.vlOffset.gain2, 0, 255, 28); | 429 | cam->params.vlOffset.gain2, 0, 255, 28); |
434 | out += sprintf(out, "vl_offset_gain4: %8d %8d %8d %8d\n", | 430 | seq_printf(m, "vl_offset_gain4: %8d %8d %8d %8d\n", |
435 | cam->params.vlOffset.gain4, 0, 255, 30); | 431 | cam->params.vlOffset.gain4, 0, 255, 30); |
436 | out += sprintf(out, "vl_offset_gain8: %8d %8d %8d %8d\n", | 432 | seq_printf(m, "vl_offset_gain8: %8d %8d %8d %8d\n", |
437 | cam->params.vlOffset.gain8, 0, 255, 30); | 433 | cam->params.vlOffset.gain8, 0, 255, 30); |
438 | out += sprintf(out, "flicker_control: %8s %8s %8s %8s\n", | 434 | seq_printf(m, "flicker_control: %8s %8s %8s %8s\n", |
439 | cam->params.flickerControl.flickerMode ? "on" : "off", | 435 | cam->params.flickerControl.flickerMode ? "on" : "off", |
440 | "off", "on", "off"); | 436 | "off", "on", "off"); |
441 | out += sprintf(out, "mains_frequency: %8d %8d %8d %8d" | 437 | seq_printf(m, "mains_frequency: %8d %8d %8d %8d" |
442 | " only 50/60\n", | 438 | " only 50/60\n", |
443 | cam->mainsFreq ? 60 : 50, 50, 60, 50); | 439 | cam->mainsFreq ? 60 : 50, 50, 60, 50); |
444 | if(cam->params.flickerControl.allowableOverExposure < 0) | 440 | if(cam->params.flickerControl.allowableOverExposure < 0) |
445 | out += sprintf(out, "allowable_overexposure: %4dauto auto %8d auto\n", | 441 | seq_printf(m, "allowable_overexposure: %4dauto auto %8d auto\n", |
446 | -cam->params.flickerControl.allowableOverExposure, | 442 | -cam->params.flickerControl.allowableOverExposure, |
447 | 255); | 443 | 255); |
448 | else | 444 | else |
449 | out += sprintf(out, "allowable_overexposure: %8d auto %8d auto\n", | 445 | seq_printf(m, "allowable_overexposure: %8d auto %8d auto\n", |
450 | cam->params.flickerControl.allowableOverExposure, | 446 | cam->params.flickerControl.allowableOverExposure, |
451 | 255); | 447 | 255); |
452 | out += sprintf(out, "compression_mode: "); | 448 | seq_printf(m, "compression_mode: "); |
453 | switch(cam->params.compression.mode) { | 449 | switch(cam->params.compression.mode) { |
454 | case CPIA_COMPRESSION_NONE: | 450 | case CPIA_COMPRESSION_NONE: |
455 | out += sprintf(out, "%8s", "none"); | 451 | seq_printf(m, "%8s", "none"); |
456 | break; | 452 | break; |
457 | case CPIA_COMPRESSION_AUTO: | 453 | case CPIA_COMPRESSION_AUTO: |
458 | out += sprintf(out, "%8s", "auto"); | 454 | seq_printf(m, "%8s", "auto"); |
459 | break; | 455 | break; |
460 | case CPIA_COMPRESSION_MANUAL: | 456 | case CPIA_COMPRESSION_MANUAL: |
461 | out += sprintf(out, "%8s", "manual"); | 457 | seq_printf(m, "%8s", "manual"); |
462 | break; | 458 | break; |
463 | default: | 459 | default: |
464 | out += sprintf(out, "%8s", "unknown"); | 460 | seq_printf(m, "%8s", "unknown"); |
465 | break; | 461 | break; |
466 | } | 462 | } |
467 | out += sprintf(out, " none,auto,manual auto\n"); | 463 | seq_printf(m, " none,auto,manual auto\n"); |
468 | out += sprintf(out, "decimation_enable: %8s %8s %8s %8s\n", | 464 | seq_printf(m, "decimation_enable: %8s %8s %8s %8s\n", |
469 | cam->params.compression.decimation == | 465 | cam->params.compression.decimation == |
470 | DECIMATION_ENAB ? "on":"off", "off", "on", | 466 | DECIMATION_ENAB ? "on":"off", "off", "on", |
471 | "off"); | 467 | "off"); |
472 | out += sprintf(out, "compression_target: %9s %9s %9s %9s\n", | 468 | seq_printf(m, "compression_target: %9s %9s %9s %9s\n", |
473 | cam->params.compressionTarget.frTargeting == | 469 | cam->params.compressionTarget.frTargeting == |
474 | CPIA_COMPRESSION_TARGET_FRAMERATE ? | 470 | CPIA_COMPRESSION_TARGET_FRAMERATE ? |
475 | "framerate":"quality", | 471 | "framerate":"quality", |
476 | "framerate", "quality", "quality"); | 472 | "framerate", "quality", "quality"); |
477 | out += sprintf(out, "target_framerate: %8d %8d %8d %8d\n", | 473 | seq_printf(m, "target_framerate: %8d %8d %8d %8d\n", |
478 | cam->params.compressionTarget.targetFR, 1, 30, 15); | 474 | cam->params.compressionTarget.targetFR, 1, 30, 15); |
479 | out += sprintf(out, "target_quality: %8d %8d %8d %8d\n", | 475 | seq_printf(m, "target_quality: %8d %8d %8d %8d\n", |
480 | cam->params.compressionTarget.targetQ, 1, 64, 5); | 476 | cam->params.compressionTarget.targetQ, 1, 64, 5); |
481 | out += sprintf(out, "y_threshold: %8d %8d %8d %8d\n", | 477 | seq_printf(m, "y_threshold: %8d %8d %8d %8d\n", |
482 | cam->params.yuvThreshold.yThreshold, 0, 31, 6); | 478 | cam->params.yuvThreshold.yThreshold, 0, 31, 6); |
483 | out += sprintf(out, "uv_threshold: %8d %8d %8d %8d\n", | 479 | seq_printf(m, "uv_threshold: %8d %8d %8d %8d\n", |
484 | cam->params.yuvThreshold.uvThreshold, 0, 31, 6); | 480 | cam->params.yuvThreshold.uvThreshold, 0, 31, 6); |
485 | out += sprintf(out, "hysteresis: %8d %8d %8d %8d\n", | 481 | seq_printf(m, "hysteresis: %8d %8d %8d %8d\n", |
486 | cam->params.compressionParams.hysteresis, 0, 255, 3); | 482 | cam->params.compressionParams.hysteresis, 0, 255, 3); |
487 | out += sprintf(out, "threshold_max: %8d %8d %8d %8d\n", | 483 | seq_printf(m, "threshold_max: %8d %8d %8d %8d\n", |
488 | cam->params.compressionParams.threshMax, 0, 255, 11); | 484 | cam->params.compressionParams.threshMax, 0, 255, 11); |
489 | out += sprintf(out, "small_step: %8d %8d %8d %8d\n", | 485 | seq_printf(m, "small_step: %8d %8d %8d %8d\n", |
490 | cam->params.compressionParams.smallStep, 0, 255, 1); | 486 | cam->params.compressionParams.smallStep, 0, 255, 1); |
491 | out += sprintf(out, "large_step: %8d %8d %8d %8d\n", | 487 | seq_printf(m, "large_step: %8d %8d %8d %8d\n", |
492 | cam->params.compressionParams.largeStep, 0, 255, 3); | 488 | cam->params.compressionParams.largeStep, 0, 255, 3); |
493 | out += sprintf(out, "decimation_hysteresis: %8d %8d %8d %8d\n", | 489 | seq_printf(m, "decimation_hysteresis: %8d %8d %8d %8d\n", |
494 | cam->params.compressionParams.decimationHysteresis, | 490 | cam->params.compressionParams.decimationHysteresis, |
495 | 0, 255, 2); | 491 | 0, 255, 2); |
496 | out += sprintf(out, "fr_diff_step_thresh: %8d %8d %8d %8d\n", | 492 | seq_printf(m, "fr_diff_step_thresh: %8d %8d %8d %8d\n", |
497 | cam->params.compressionParams.frDiffStepThresh, | 493 | cam->params.compressionParams.frDiffStepThresh, |
498 | 0, 255, 5); | 494 | 0, 255, 5); |
499 | out += sprintf(out, "q_diff_step_thresh: %8d %8d %8d %8d\n", | 495 | seq_printf(m, "q_diff_step_thresh: %8d %8d %8d %8d\n", |
500 | cam->params.compressionParams.qDiffStepThresh, | 496 | cam->params.compressionParams.qDiffStepThresh, |
501 | 0, 255, 3); | 497 | 0, 255, 3); |
502 | out += sprintf(out, "decimation_thresh_mod: %8d %8d %8d %8d\n", | 498 | seq_printf(m, "decimation_thresh_mod: %8d %8d %8d %8d\n", |
503 | cam->params.compressionParams.decimationThreshMod, | 499 | cam->params.compressionParams.decimationThreshMod, |
504 | 0, 255, 2); | 500 | 0, 255, 2); |
505 | /* QX3 specific entries */ | 501 | /* QX3 specific entries */ |
506 | if (cam->params.qx3.qx3_detected) { | 502 | if (cam->params.qx3.qx3_detected) { |
507 | out += sprintf(out, "toplight: %8s %8s %8s %8s\n", | 503 | seq_printf(m, "toplight: %8s %8s %8s %8s\n", |
508 | cam->params.qx3.toplight ? "on" : "off", | 504 | cam->params.qx3.toplight ? "on" : "off", |
509 | "off", "on", "off"); | 505 | "off", "on", "off"); |
510 | out += sprintf(out, "bottomlight: %8s %8s %8s %8s\n", | 506 | seq_printf(m, "bottomlight: %8s %8s %8s %8s\n", |
511 | cam->params.qx3.bottomlight ? "on" : "off", | 507 | cam->params.qx3.bottomlight ? "on" : "off", |
512 | "off", "on", "off"); | 508 | "off", "on", "off"); |
513 | } | 509 | } |
514 | 510 | ||
515 | len = out - page; | 511 | return 0; |
516 | len -= off; | ||
517 | if (len < count) { | ||
518 | *eof = 1; | ||
519 | if (len <= 0) return 0; | ||
520 | } else | ||
521 | len = count; | ||
522 | |||
523 | *start = page + off; | ||
524 | return len; | ||
525 | } | 512 | } |
526 | 513 | ||
514 | static int cpia_proc_open(struct inode *inode, struct file *file) | ||
515 | { | ||
516 | return single_open(file, cpia_proc_show, PDE(inode)->data); | ||
517 | } | ||
527 | 518 | ||
528 | static int match(char *checkstr, char **buffer, unsigned long *count, | 519 | static int match(char *checkstr, char **buffer, size_t *count, |
529 | int *find_colon, int *err) | 520 | int *find_colon, int *err) |
530 | { | 521 | { |
531 | int ret, colon_found = 1; | 522 | int ret, colon_found = 1; |
@@ -551,7 +542,7 @@ static int match(char *checkstr, char **buffer, unsigned long *count, | |||
551 | return ret; | 542 | return ret; |
552 | } | 543 | } |
553 | 544 | ||
554 | static unsigned long int value(char **buffer, unsigned long *count, int *err) | 545 | static unsigned long int value(char **buffer, size_t *count, int *err) |
555 | { | 546 | { |
556 | char *p; | 547 | char *p; |
557 | unsigned long int ret; | 548 | unsigned long int ret; |
@@ -565,10 +556,10 @@ static unsigned long int value(char **buffer, unsigned long *count, int *err) | |||
565 | return ret; | 556 | return ret; |
566 | } | 557 | } |
567 | 558 | ||
568 | static int cpia_write_proc(struct file *file, const char __user *buf, | 559 | static ssize_t cpia_proc_write(struct file *file, const char __user *buf, |
569 | unsigned long count, void *data) | 560 | size_t count, loff_t *pos) |
570 | { | 561 | { |
571 | struct cam_data *cam = data; | 562 | struct cam_data *cam = PDE(file->f_path.dentry->d_inode)->data; |
572 | struct cam_params new_params; | 563 | struct cam_params new_params; |
573 | char *page, *buffer; | 564 | char *page, *buffer; |
574 | int retval, find_colon; | 565 | int retval, find_colon; |
@@ -582,7 +573,7 @@ static int cpia_write_proc(struct file *file, const char __user *buf, | |||
582 | * from the comx driver | 573 | * from the comx driver |
583 | */ | 574 | */ |
584 | if (count > PAGE_SIZE) { | 575 | if (count > PAGE_SIZE) { |
585 | printk(KERN_ERR "count is %lu > %d!!!\n", count, (int)PAGE_SIZE); | 576 | printk(KERN_ERR "count is %zu > %d!!!\n", count, (int)PAGE_SIZE); |
586 | return -ENOSPC; | 577 | return -ENOSPC; |
587 | } | 578 | } |
588 | 579 | ||
@@ -1340,23 +1331,28 @@ out: | |||
1340 | return retval; | 1331 | return retval; |
1341 | } | 1332 | } |
1342 | 1333 | ||
1334 | static const struct file_operations cpia_proc_fops = { | ||
1335 | .owner = THIS_MODULE, | ||
1336 | .open = cpia_proc_open, | ||
1337 | .read = seq_read, | ||
1338 | .llseek = seq_lseek, | ||
1339 | .release = single_release, | ||
1340 | .write = cpia_proc_write, | ||
1341 | }; | ||
1342 | |||
1343 | static void create_proc_cpia_cam(struct cam_data *cam) | 1343 | static void create_proc_cpia_cam(struct cam_data *cam) |
1344 | { | 1344 | { |
1345 | char name[5 + 1 + 10 + 1]; | ||
1346 | struct proc_dir_entry *ent; | 1345 | struct proc_dir_entry *ent; |
1347 | 1346 | ||
1348 | if (!cpia_proc_root || !cam) | 1347 | if (!cpia_proc_root || !cam) |
1349 | return; | 1348 | return; |
1350 | 1349 | ||
1351 | snprintf(name, sizeof(name), "video%d", cam->vdev.num); | 1350 | ent = proc_create_data(video_device_node_name(&cam->vdev), |
1352 | 1351 | S_IRUGO|S_IWUSR, cpia_proc_root, | |
1353 | ent = create_proc_entry(name, S_IFREG|S_IRUGO|S_IWUSR, cpia_proc_root); | 1352 | &cpia_proc_fops, cam); |
1354 | if (!ent) | 1353 | if (!ent) |
1355 | return; | 1354 | return; |
1356 | 1355 | ||
1357 | ent->data = cam; | ||
1358 | ent->read_proc = cpia_read_proc; | ||
1359 | ent->write_proc = cpia_write_proc; | ||
1360 | /* | 1356 | /* |
1361 | size of the proc entry is 3736 bytes for the standard webcam; | 1357 | size of the proc entry is 3736 bytes for the standard webcam; |
1362 | the extra features of the QX3 microscope add 189 bytes. | 1358 | the extra features of the QX3 microscope add 189 bytes. |
@@ -1368,13 +1364,10 @@ static void create_proc_cpia_cam(struct cam_data *cam) | |||
1368 | 1364 | ||
1369 | static void destroy_proc_cpia_cam(struct cam_data *cam) | 1365 | static void destroy_proc_cpia_cam(struct cam_data *cam) |
1370 | { | 1366 | { |
1371 | char name[5 + 1 + 10 + 1]; | ||
1372 | |||
1373 | if (!cam || !cam->proc_entry) | 1367 | if (!cam || !cam->proc_entry) |
1374 | return; | 1368 | return; |
1375 | 1369 | ||
1376 | snprintf(name, sizeof(name), "video%d", cam->vdev.num); | 1370 | remove_proc_entry(video_device_node_name(&cam->vdev), cpia_proc_root); |
1377 | remove_proc_entry(name, cpia_proc_root); | ||
1378 | cam->proc_entry = NULL; | 1371 | cam->proc_entry = NULL; |
1379 | } | 1372 | } |
1380 | 1373 | ||
@@ -3999,7 +3992,7 @@ void cpia_unregister_camera(struct cam_data *cam) | |||
3999 | } | 3992 | } |
4000 | 3993 | ||
4001 | #ifdef CONFIG_PROC_FS | 3994 | #ifdef CONFIG_PROC_FS |
4002 | DBG("destroying /proc/cpia/video%d\n", cam->vdev.num); | 3995 | DBG("destroying /proc/cpia/%s\n", video_device_node_name(&cam->vdev)); |
4003 | destroy_proc_cpia_cam(cam); | 3996 | destroy_proc_cpia_cam(cam); |
4004 | #endif | 3997 | #endif |
4005 | if (!cam->open_count) { | 3998 | if (!cam->open_count) { |
diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c index 0b4a8f309cfa..6f91415eb7b4 100644 --- a/drivers/media/video/cpia2/cpia2_v4l.c +++ b/drivers/media/video/cpia2/cpia2_v4l.c | |||
@@ -38,17 +38,12 @@ | |||
38 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
39 | #include <linux/init.h> | 39 | #include <linux/init.h> |
40 | #include <linux/videodev.h> | 40 | #include <linux/videodev.h> |
41 | #include <linux/stringify.h> | ||
41 | #include <media/v4l2-ioctl.h> | 42 | #include <media/v4l2-ioctl.h> |
42 | 43 | ||
43 | #include "cpia2.h" | 44 | #include "cpia2.h" |
44 | #include "cpia2dev.h" | 45 | #include "cpia2dev.h" |
45 | 46 | ||
46 | |||
47 | //#define _CPIA2_DEBUG_ | ||
48 | |||
49 | #define MAKE_STRING_1(x) #x | ||
50 | #define MAKE_STRING(x) MAKE_STRING_1(x) | ||
51 | |||
52 | static int video_nr = -1; | 47 | static int video_nr = -1; |
53 | module_param(video_nr, int, 0); | 48 | module_param(video_nr, int, 0); |
54 | MODULE_PARM_DESC(video_nr,"video device to register (0=/dev/video0, etc)"); | 49 | MODULE_PARM_DESC(video_nr,"video device to register (0=/dev/video0, etc)"); |
@@ -60,26 +55,26 @@ MODULE_PARM_DESC(buffer_size, "Size for each frame buffer in bytes (default 68k) | |||
60 | static int num_buffers = 3; | 55 | static int num_buffers = 3; |
61 | module_param(num_buffers, int, 0); | 56 | module_param(num_buffers, int, 0); |
62 | MODULE_PARM_DESC(num_buffers, "Number of frame buffers (1-" | 57 | MODULE_PARM_DESC(num_buffers, "Number of frame buffers (1-" |
63 | MAKE_STRING(VIDEO_MAX_FRAME) ", default 3)"); | 58 | __stringify(VIDEO_MAX_FRAME) ", default 3)"); |
64 | 59 | ||
65 | static int alternate = DEFAULT_ALT; | 60 | static int alternate = DEFAULT_ALT; |
66 | module_param(alternate, int, 0); | 61 | module_param(alternate, int, 0); |
67 | MODULE_PARM_DESC(alternate, "USB Alternate (" MAKE_STRING(USBIF_ISO_1) "-" | 62 | MODULE_PARM_DESC(alternate, "USB Alternate (" __stringify(USBIF_ISO_1) "-" |
68 | MAKE_STRING(USBIF_ISO_6) ", default " | 63 | __stringify(USBIF_ISO_6) ", default " |
69 | MAKE_STRING(DEFAULT_ALT) ")"); | 64 | __stringify(DEFAULT_ALT) ")"); |
70 | 65 | ||
71 | static int flicker_freq = 60; | 66 | static int flicker_freq = 60; |
72 | module_param(flicker_freq, int, 0); | 67 | module_param(flicker_freq, int, 0); |
73 | MODULE_PARM_DESC(flicker_freq, "Flicker frequency (" MAKE_STRING(50) "or" | 68 | MODULE_PARM_DESC(flicker_freq, "Flicker frequency (" __stringify(50) "or" |
74 | MAKE_STRING(60) ", default " | 69 | __stringify(60) ", default " |
75 | MAKE_STRING(60) ")"); | 70 | __stringify(60) ")"); |
76 | 71 | ||
77 | static int flicker_mode = NEVER_FLICKER; | 72 | static int flicker_mode = NEVER_FLICKER; |
78 | module_param(flicker_mode, int, 0); | 73 | module_param(flicker_mode, int, 0); |
79 | MODULE_PARM_DESC(flicker_mode, | 74 | MODULE_PARM_DESC(flicker_mode, |
80 | "Flicker supression (" MAKE_STRING(NEVER_FLICKER) "or" | 75 | "Flicker supression (" __stringify(NEVER_FLICKER) "or" |
81 | MAKE_STRING(ANTI_FLICKER_ON) ", default " | 76 | __stringify(ANTI_FLICKER_ON) ", default " |
82 | MAKE_STRING(NEVER_FLICKER) ")"); | 77 | __stringify(NEVER_FLICKER) ")"); |
83 | 78 | ||
84 | MODULE_AUTHOR("Steve Miller (STMicroelectronics) <steve.miller@st.com>"); | 79 | MODULE_AUTHOR("Steve Miller (STMicroelectronics) <steve.miller@st.com>"); |
85 | MODULE_DESCRIPTION("V4L-driver for STMicroelectronics CPiA2 based cameras"); | 80 | MODULE_DESCRIPTION("V4L-driver for STMicroelectronics CPiA2 based cameras"); |
@@ -1926,7 +1921,6 @@ static const struct v4l2_file_operations fops_template = { | |||
1926 | static struct video_device cpia2_template = { | 1921 | static struct video_device cpia2_template = { |
1927 | /* I could not find any place for the old .initialize initializer?? */ | 1922 | /* I could not find any place for the old .initialize initializer?? */ |
1928 | .name= "CPiA2 Camera", | 1923 | .name= "CPiA2 Camera", |
1929 | .minor= -1, | ||
1930 | .fops= &fops_template, | 1924 | .fops= &fops_template, |
1931 | .release= video_device_release, | 1925 | .release= video_device_release, |
1932 | }; | 1926 | }; |
@@ -1967,9 +1961,9 @@ void cpia2_unregister_camera(struct camera_data *cam) | |||
1967 | if (!cam->open_count) { | 1961 | if (!cam->open_count) { |
1968 | video_unregister_device(cam->vdev); | 1962 | video_unregister_device(cam->vdev); |
1969 | } else { | 1963 | } else { |
1970 | LOG("/dev/video%d removed while open, " | 1964 | LOG("%s removed while open, deferring " |
1971 | "deferring video_unregister_device\n", | 1965 | "video_unregister_device\n", |
1972 | cam->vdev->num); | 1966 | video_device_node_name(cam->vdev)); |
1973 | } | 1967 | } |
1974 | } | 1968 | } |
1975 | 1969 | ||
diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c index 4e278db31cc9..c0885c69fd89 100644 --- a/drivers/media/video/cx18/cx18-fileops.c +++ b/drivers/media/video/cx18/cx18-fileops.c | |||
@@ -758,8 +758,8 @@ int cx18_v4l2_open(struct file *filp) | |||
758 | 758 | ||
759 | mutex_lock(&cx->serialize_lock); | 759 | mutex_lock(&cx->serialize_lock); |
760 | if (cx18_init_on_first_open(cx)) { | 760 | if (cx18_init_on_first_open(cx)) { |
761 | CX18_ERR("Failed to initialize on minor %d\n", | 761 | CX18_ERR("Failed to initialize on %s\n", |
762 | video_dev->minor); | 762 | video_device_node_name(video_dev)); |
763 | mutex_unlock(&cx->serialize_lock); | 763 | mutex_unlock(&cx->serialize_lock); |
764 | return -ENXIO; | 764 | return -ENXIO; |
765 | } | 765 | } |
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index c398651dd74c..987a9308d938 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c | |||
@@ -219,6 +219,7 @@ static int cx18_reg_dev(struct cx18 *cx, int type) | |||
219 | { | 219 | { |
220 | struct cx18_stream *s = &cx->streams[type]; | 220 | struct cx18_stream *s = &cx->streams[type]; |
221 | int vfl_type = cx18_stream_info[type].vfl_type; | 221 | int vfl_type = cx18_stream_info[type].vfl_type; |
222 | const char *name; | ||
222 | int num, ret; | 223 | int num, ret; |
223 | 224 | ||
224 | /* TODO: Shouldn't this be a VFL_TYPE_TRANSPORT or something? | 225 | /* TODO: Shouldn't this be a VFL_TYPE_TRANSPORT or something? |
@@ -258,31 +259,30 @@ static int cx18_reg_dev(struct cx18 *cx, int type) | |||
258 | s->video_dev = NULL; | 259 | s->video_dev = NULL; |
259 | return ret; | 260 | return ret; |
260 | } | 261 | } |
261 | num = s->video_dev->num; | 262 | |
263 | name = video_device_node_name(s->video_dev); | ||
262 | 264 | ||
263 | switch (vfl_type) { | 265 | switch (vfl_type) { |
264 | case VFL_TYPE_GRABBER: | 266 | case VFL_TYPE_GRABBER: |
265 | CX18_INFO("Registered device video%d for %s " | 267 | CX18_INFO("Registered device %s for %s (%d x %d.%02d kB)\n", |
266 | "(%d x %d.%02d kB)\n", | 268 | name, s->name, cx->stream_buffers[type], |
267 | num, s->name, cx->stream_buffers[type], | ||
268 | cx->stream_buf_size[type] / 1024, | 269 | cx->stream_buf_size[type] / 1024, |
269 | (cx->stream_buf_size[type] * 100 / 1024) % 100); | 270 | (cx->stream_buf_size[type] * 100 / 1024) % 100); |
270 | break; | 271 | break; |
271 | 272 | ||
272 | case VFL_TYPE_RADIO: | 273 | case VFL_TYPE_RADIO: |
273 | CX18_INFO("Registered device radio%d for %s\n", | 274 | CX18_INFO("Registered device %s for %s\n", name, s->name); |
274 | num, s->name); | ||
275 | break; | 275 | break; |
276 | 276 | ||
277 | case VFL_TYPE_VBI: | 277 | case VFL_TYPE_VBI: |
278 | if (cx->stream_buffers[type]) | 278 | if (cx->stream_buffers[type]) |
279 | CX18_INFO("Registered device vbi%d for %s " | 279 | CX18_INFO("Registered device %s for %s " |
280 | "(%d x %d bytes)\n", | 280 | "(%d x %d bytes)\n", |
281 | num, s->name, cx->stream_buffers[type], | 281 | name, s->name, cx->stream_buffers[type], |
282 | cx->stream_buf_size[type]); | 282 | cx->stream_buf_size[type]); |
283 | else | 283 | else |
284 | CX18_INFO("Registered device vbi%d for %s\n", | 284 | CX18_INFO("Registered device %s for %s\n", |
285 | num, s->name); | 285 | name, s->name); |
286 | break; | 286 | break; |
287 | } | 287 | } |
288 | 288 | ||
diff --git a/drivers/media/video/cx231xx/cx231xx-cards.c b/drivers/media/video/cx231xx/cx231xx-cards.c index 319c459459e0..a54908235009 100644 --- a/drivers/media/video/cx231xx/cx231xx-cards.c +++ b/drivers/media/video/cx231xx/cx231xx-cards.c | |||
@@ -68,19 +68,19 @@ struct cx231xx_board cx231xx_boards[] = { | |||
68 | .type = CX231XX_VMUX_TELEVISION, | 68 | .type = CX231XX_VMUX_TELEVISION, |
69 | .vmux = CX231XX_VIN_3_1, | 69 | .vmux = CX231XX_VIN_3_1, |
70 | .amux = CX231XX_AMUX_VIDEO, | 70 | .amux = CX231XX_AMUX_VIDEO, |
71 | .gpio = 0, | 71 | .gpio = NULL, |
72 | }, { | 72 | }, { |
73 | .type = CX231XX_VMUX_COMPOSITE1, | 73 | .type = CX231XX_VMUX_COMPOSITE1, |
74 | .vmux = CX231XX_VIN_2_1, | 74 | .vmux = CX231XX_VIN_2_1, |
75 | .amux = CX231XX_AMUX_LINE_IN, | 75 | .amux = CX231XX_AMUX_LINE_IN, |
76 | .gpio = 0, | 76 | .gpio = NULL, |
77 | }, { | 77 | }, { |
78 | .type = CX231XX_VMUX_SVIDEO, | 78 | .type = CX231XX_VMUX_SVIDEO, |
79 | .vmux = CX231XX_VIN_1_1 | | 79 | .vmux = CX231XX_VIN_1_1 | |
80 | (CX231XX_VIN_1_2 << 8) | | 80 | (CX231XX_VIN_1_2 << 8) | |
81 | CX25840_SVIDEO_ON, | 81 | CX25840_SVIDEO_ON, |
82 | .amux = CX231XX_AMUX_LINE_IN, | 82 | .amux = CX231XX_AMUX_LINE_IN, |
83 | .gpio = 0, | 83 | .gpio = NULL, |
84 | } | 84 | } |
85 | }, | 85 | }, |
86 | }, | 86 | }, |
@@ -107,19 +107,19 @@ struct cx231xx_board cx231xx_boards[] = { | |||
107 | .type = CX231XX_VMUX_TELEVISION, | 107 | .type = CX231XX_VMUX_TELEVISION, |
108 | .vmux = CX231XX_VIN_3_1, | 108 | .vmux = CX231XX_VIN_3_1, |
109 | .amux = CX231XX_AMUX_VIDEO, | 109 | .amux = CX231XX_AMUX_VIDEO, |
110 | .gpio = 0, | 110 | .gpio = NULL, |
111 | }, { | 111 | }, { |
112 | .type = CX231XX_VMUX_COMPOSITE1, | 112 | .type = CX231XX_VMUX_COMPOSITE1, |
113 | .vmux = CX231XX_VIN_2_1, | 113 | .vmux = CX231XX_VIN_2_1, |
114 | .amux = CX231XX_AMUX_LINE_IN, | 114 | .amux = CX231XX_AMUX_LINE_IN, |
115 | .gpio = 0, | 115 | .gpio = NULL, |
116 | }, { | 116 | }, { |
117 | .type = CX231XX_VMUX_SVIDEO, | 117 | .type = CX231XX_VMUX_SVIDEO, |
118 | .vmux = CX231XX_VIN_1_1 | | 118 | .vmux = CX231XX_VIN_1_1 | |
119 | (CX231XX_VIN_1_2 << 8) | | 119 | (CX231XX_VIN_1_2 << 8) | |
120 | CX25840_SVIDEO_ON, | 120 | CX25840_SVIDEO_ON, |
121 | .amux = CX231XX_AMUX_LINE_IN, | 121 | .amux = CX231XX_AMUX_LINE_IN, |
122 | .gpio = 0, | 122 | .gpio = NULL, |
123 | } | 123 | } |
124 | }, | 124 | }, |
125 | }, | 125 | }, |
@@ -147,19 +147,19 @@ struct cx231xx_board cx231xx_boards[] = { | |||
147 | .type = CX231XX_VMUX_TELEVISION, | 147 | .type = CX231XX_VMUX_TELEVISION, |
148 | .vmux = CX231XX_VIN_3_1, | 148 | .vmux = CX231XX_VIN_3_1, |
149 | .amux = CX231XX_AMUX_VIDEO, | 149 | .amux = CX231XX_AMUX_VIDEO, |
150 | .gpio = 0, | 150 | .gpio = NULL, |
151 | }, { | 151 | }, { |
152 | .type = CX231XX_VMUX_COMPOSITE1, | 152 | .type = CX231XX_VMUX_COMPOSITE1, |
153 | .vmux = CX231XX_VIN_2_1, | 153 | .vmux = CX231XX_VIN_2_1, |
154 | .amux = CX231XX_AMUX_LINE_IN, | 154 | .amux = CX231XX_AMUX_LINE_IN, |
155 | .gpio = 0, | 155 | .gpio = NULL, |
156 | }, { | 156 | }, { |
157 | .type = CX231XX_VMUX_SVIDEO, | 157 | .type = CX231XX_VMUX_SVIDEO, |
158 | .vmux = CX231XX_VIN_1_1 | | 158 | .vmux = CX231XX_VIN_1_1 | |
159 | (CX231XX_VIN_1_2 << 8) | | 159 | (CX231XX_VIN_1_2 << 8) | |
160 | CX25840_SVIDEO_ON, | 160 | CX25840_SVIDEO_ON, |
161 | .amux = CX231XX_AMUX_LINE_IN, | 161 | .amux = CX231XX_AMUX_LINE_IN, |
162 | .gpio = 0, | 162 | .gpio = NULL, |
163 | } | 163 | } |
164 | }, | 164 | }, |
165 | }, | 165 | }, |
@@ -856,8 +856,9 @@ static void cx231xx_usb_disconnect(struct usb_interface *interface) | |||
856 | 856 | ||
857 | if (dev->users) { | 857 | if (dev->users) { |
858 | cx231xx_warn | 858 | cx231xx_warn |
859 | ("device /dev/video%d is open! Deregistration and memory " | 859 | ("device %s is open! Deregistration and memory " |
860 | "deallocation are deferred on close.\n", dev->vdev->num); | 860 | "deallocation are deferred on close.\n", |
861 | video_device_node_name(dev->vdev)); | ||
861 | 862 | ||
862 | dev->state |= DEV_MISCONFIGURED; | 863 | dev->state |= DEV_MISCONFIGURED; |
863 | cx231xx_uninit_isoc(dev); | 864 | cx231xx_uninit_isoc(dev); |
diff --git a/drivers/media/video/cx231xx/cx231xx-core.c b/drivers/media/video/cx231xx/cx231xx-core.c index 0d333e679f70..4a60dfbc347d 100644 --- a/drivers/media/video/cx231xx/cx231xx-core.c +++ b/drivers/media/video/cx231xx/cx231xx-core.c | |||
@@ -66,32 +66,6 @@ MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint"); | |||
66 | static LIST_HEAD(cx231xx_devlist); | 66 | static LIST_HEAD(cx231xx_devlist); |
67 | static DEFINE_MUTEX(cx231xx_devlist_mutex); | 67 | static DEFINE_MUTEX(cx231xx_devlist_mutex); |
68 | 68 | ||
69 | struct cx231xx *cx231xx_get_device(int minor, | ||
70 | enum v4l2_buf_type *fh_type, int *has_radio) | ||
71 | { | ||
72 | struct cx231xx *h, *dev = NULL; | ||
73 | |||
74 | *fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
75 | *has_radio = 0; | ||
76 | |||
77 | mutex_lock(&cx231xx_devlist_mutex); | ||
78 | list_for_each_entry(h, &cx231xx_devlist, devlist) { | ||
79 | if (h->vdev->minor == minor) | ||
80 | dev = h; | ||
81 | if (h->vbi_dev->minor == minor) { | ||
82 | dev = h; | ||
83 | *fh_type = V4L2_BUF_TYPE_VBI_CAPTURE; | ||
84 | } | ||
85 | if (h->radio_dev && h->radio_dev->minor == minor) { | ||
86 | dev = h; | ||
87 | *has_radio = 1; | ||
88 | } | ||
89 | } | ||
90 | mutex_unlock(&cx231xx_devlist_mutex); | ||
91 | |||
92 | return dev; | ||
93 | } | ||
94 | |||
95 | /* | 69 | /* |
96 | * cx231xx_realease_resources() | 70 | * cx231xx_realease_resources() |
97 | * unregisters the v4l2,i2c and usb devices | 71 | * unregisters the v4l2,i2c and usb devices |
diff --git a/drivers/media/video/cx231xx/cx231xx-input.c b/drivers/media/video/cx231xx/cx231xx-input.c index cd135f01b9c1..15826f98b688 100644 --- a/drivers/media/video/cx231xx/cx231xx-input.c +++ b/drivers/media/video/cx231xx/cx231xx-input.c | |||
@@ -197,8 +197,7 @@ int cx231xx_ir_init(struct cx231xx *dev) | |||
197 | usb_make_path(dev->udev, ir->phys, sizeof(ir->phys)); | 197 | usb_make_path(dev->udev, ir->phys, sizeof(ir->phys)); |
198 | strlcat(ir->phys, "/input0", sizeof(ir->phys)); | 198 | strlcat(ir->phys, "/input0", sizeof(ir->phys)); |
199 | 199 | ||
200 | err = ir_input_init(input_dev, &ir->ir, IR_TYPE_OTHER, | 200 | err = ir_input_init(input_dev, &ir->ir, IR_TYPE_OTHER); |
201 | dev->board.ir_codes); | ||
202 | if (err < 0) | 201 | if (err < 0) |
203 | goto err_out_free; | 202 | goto err_out_free; |
204 | 203 | ||
@@ -217,7 +216,7 @@ int cx231xx_ir_init(struct cx231xx *dev) | |||
217 | cx231xx_ir_start(ir); | 216 | cx231xx_ir_start(ir); |
218 | 217 | ||
219 | /* all done */ | 218 | /* all done */ |
220 | err = input_register_device(ir->input); | 219 | err = ir_input_register(ir->input, dev->board.ir_codes); |
221 | if (err) | 220 | if (err) |
222 | goto err_out_stop; | 221 | goto err_out_stop; |
223 | 222 | ||
@@ -226,8 +225,6 @@ err_out_stop: | |||
226 | cx231xx_ir_stop(ir); | 225 | cx231xx_ir_stop(ir); |
227 | dev->ir = NULL; | 226 | dev->ir = NULL; |
228 | err_out_free: | 227 | err_out_free: |
229 | ir_input_free(input_dev); | ||
230 | input_free_device(input_dev); | ||
231 | kfree(ir); | 228 | kfree(ir); |
232 | return err; | 229 | return err; |
233 | } | 230 | } |
@@ -241,8 +238,7 @@ int cx231xx_ir_fini(struct cx231xx *dev) | |||
241 | return 0; | 238 | return 0; |
242 | 239 | ||
243 | cx231xx_ir_stop(ir); | 240 | cx231xx_ir_stop(ir); |
244 | ir_input_free(ir->input); | 241 | ir_input_unregister(ir->input); |
245 | input_unregister_device(ir->input); | ||
246 | kfree(ir); | 242 | kfree(ir); |
247 | 243 | ||
248 | /* done */ | 244 | /* done */ |
diff --git a/drivers/media/video/cx231xx/cx231xx-video.c b/drivers/media/video/cx231xx/cx231xx-video.c index d095aa0d6d19..d4f546f11d74 100644 --- a/drivers/media/video/cx231xx/cx231xx-video.c +++ b/drivers/media/video/cx231xx/cx231xx-video.c | |||
@@ -1916,20 +1916,29 @@ static int radio_queryctrl(struct file *file, void *priv, | |||
1916 | */ | 1916 | */ |
1917 | static int cx231xx_v4l2_open(struct file *filp) | 1917 | static int cx231xx_v4l2_open(struct file *filp) |
1918 | { | 1918 | { |
1919 | int minor = video_devdata(filp)->minor; | ||
1920 | int errCode = 0, radio = 0; | 1919 | int errCode = 0, radio = 0; |
1921 | struct cx231xx *dev = NULL; | 1920 | struct video_device *vdev = video_devdata(filp); |
1921 | struct cx231xx *dev = video_drvdata(filp); | ||
1922 | struct cx231xx_fh *fh; | 1922 | struct cx231xx_fh *fh; |
1923 | enum v4l2_buf_type fh_type = 0; | 1923 | enum v4l2_buf_type fh_type = 0; |
1924 | 1924 | ||
1925 | dev = cx231xx_get_device(minor, &fh_type, &radio); | 1925 | switch (vdev->vfl_type) { |
1926 | if (NULL == dev) | 1926 | case VFL_TYPE_GRABBER: |
1927 | return -ENODEV; | 1927 | fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
1928 | break; | ||
1929 | case VFL_TYPE_VBI: | ||
1930 | fh_type = V4L2_BUF_TYPE_VBI_CAPTURE; | ||
1931 | break; | ||
1932 | case VFL_TYPE_RADIO: | ||
1933 | radio = 1; | ||
1934 | break; | ||
1935 | } | ||
1928 | 1936 | ||
1929 | mutex_lock(&dev->lock); | 1937 | mutex_lock(&dev->lock); |
1930 | 1938 | ||
1931 | cx231xx_videodbg("open minor=%d type=%s users=%d\n", | 1939 | cx231xx_videodbg("open dev=%s type=%s users=%d\n", |
1932 | minor, v4l2_type_names[fh_type], dev->users); | 1940 | video_device_node_name(vdev), v4l2_type_names[fh_type], |
1941 | dev->users); | ||
1933 | 1942 | ||
1934 | #if 0 | 1943 | #if 0 |
1935 | errCode = cx231xx_set_mode(dev, CX231XX_ANALOG_MODE); | 1944 | errCode = cx231xx_set_mode(dev, CX231XX_ANALOG_MODE); |
@@ -2020,25 +2029,25 @@ void cx231xx_release_analog_resources(struct cx231xx *dev) | |||
2020 | /*FIXME: I2C IR should be disconnected */ | 2029 | /*FIXME: I2C IR should be disconnected */ |
2021 | 2030 | ||
2022 | if (dev->radio_dev) { | 2031 | if (dev->radio_dev) { |
2023 | if (-1 != dev->radio_dev->minor) | 2032 | if (video_is_registered(dev->radio_dev)) |
2024 | video_unregister_device(dev->radio_dev); | 2033 | video_unregister_device(dev->radio_dev); |
2025 | else | 2034 | else |
2026 | video_device_release(dev->radio_dev); | 2035 | video_device_release(dev->radio_dev); |
2027 | dev->radio_dev = NULL; | 2036 | dev->radio_dev = NULL; |
2028 | } | 2037 | } |
2029 | if (dev->vbi_dev) { | 2038 | if (dev->vbi_dev) { |
2030 | cx231xx_info("V4L2 device /dev/vbi%d deregistered\n", | 2039 | cx231xx_info("V4L2 device %s deregistered\n", |
2031 | dev->vbi_dev->num); | 2040 | video_device_node_name(dev->vbi_dev)); |
2032 | if (-1 != dev->vbi_dev->minor) | 2041 | if (video_is_registered(dev->vbi_dev)) |
2033 | video_unregister_device(dev->vbi_dev); | 2042 | video_unregister_device(dev->vbi_dev); |
2034 | else | 2043 | else |
2035 | video_device_release(dev->vbi_dev); | 2044 | video_device_release(dev->vbi_dev); |
2036 | dev->vbi_dev = NULL; | 2045 | dev->vbi_dev = NULL; |
2037 | } | 2046 | } |
2038 | if (dev->vdev) { | 2047 | if (dev->vdev) { |
2039 | cx231xx_info("V4L2 device /dev/video%d deregistered\n", | 2048 | cx231xx_info("V4L2 device %s deregistered\n", |
2040 | dev->vdev->num); | 2049 | video_device_node_name(dev->vdev)); |
2041 | if (-1 != dev->vdev->minor) | 2050 | if (video_is_registered(dev->vdev)) |
2042 | video_unregister_device(dev->vdev); | 2051 | video_unregister_device(dev->vdev); |
2043 | else | 2052 | else |
2044 | video_device_release(dev->vdev); | 2053 | video_device_release(dev->vdev); |
@@ -2268,7 +2277,6 @@ static const struct video_device cx231xx_video_template = { | |||
2268 | .fops = &cx231xx_v4l_fops, | 2277 | .fops = &cx231xx_v4l_fops, |
2269 | .release = video_device_release, | 2278 | .release = video_device_release, |
2270 | .ioctl_ops = &video_ioctl_ops, | 2279 | .ioctl_ops = &video_ioctl_ops, |
2271 | .minor = -1, | ||
2272 | .tvnorms = V4L2_STD_ALL, | 2280 | .tvnorms = V4L2_STD_ALL, |
2273 | .current_norm = V4L2_STD_PAL, | 2281 | .current_norm = V4L2_STD_PAL, |
2274 | }; | 2282 | }; |
@@ -2303,7 +2311,6 @@ static struct video_device cx231xx_radio_template = { | |||
2303 | .name = "cx231xx-radio", | 2311 | .name = "cx231xx-radio", |
2304 | .fops = &radio_fops, | 2312 | .fops = &radio_fops, |
2305 | .ioctl_ops = &radio_ioctl_ops, | 2313 | .ioctl_ops = &radio_ioctl_ops, |
2306 | .minor = -1, | ||
2307 | }; | 2314 | }; |
2308 | 2315 | ||
2309 | /******************************** usb interface ******************************/ | 2316 | /******************************** usb interface ******************************/ |
@@ -2319,13 +2326,13 @@ static struct video_device *cx231xx_vdev_init(struct cx231xx *dev, | |||
2319 | return NULL; | 2326 | return NULL; |
2320 | 2327 | ||
2321 | *vfd = *template; | 2328 | *vfd = *template; |
2322 | vfd->minor = -1; | ||
2323 | vfd->v4l2_dev = &dev->v4l2_dev; | 2329 | vfd->v4l2_dev = &dev->v4l2_dev; |
2324 | vfd->release = video_device_release; | 2330 | vfd->release = video_device_release; |
2325 | vfd->debug = video_debug; | 2331 | vfd->debug = video_debug; |
2326 | 2332 | ||
2327 | snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name); | 2333 | snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name); |
2328 | 2334 | ||
2335 | video_set_drvdata(vfd, dev); | ||
2329 | return vfd; | 2336 | return vfd; |
2330 | } | 2337 | } |
2331 | 2338 | ||
@@ -2374,8 +2381,8 @@ int cx231xx_register_analog_devices(struct cx231xx *dev) | |||
2374 | return ret; | 2381 | return ret; |
2375 | } | 2382 | } |
2376 | 2383 | ||
2377 | cx231xx_info("%s/0: registered device video%d [v4l2]\n", | 2384 | cx231xx_info("%s/0: registered device %s [v4l2]\n", |
2378 | dev->name, dev->vdev->num); | 2385 | dev->name, video_device_node_name(dev->vdev)); |
2379 | 2386 | ||
2380 | /* Initialize VBI template */ | 2387 | /* Initialize VBI template */ |
2381 | memcpy(&cx231xx_vbi_template, &cx231xx_video_template, | 2388 | memcpy(&cx231xx_vbi_template, &cx231xx_video_template, |
@@ -2393,8 +2400,8 @@ int cx231xx_register_analog_devices(struct cx231xx *dev) | |||
2393 | return ret; | 2400 | return ret; |
2394 | } | 2401 | } |
2395 | 2402 | ||
2396 | cx231xx_info("%s/0: registered device vbi%d\n", | 2403 | cx231xx_info("%s/0: registered device %s\n", |
2397 | dev->name, dev->vbi_dev->num); | 2404 | dev->name, video_device_node_name(dev->vbi_dev)); |
2398 | 2405 | ||
2399 | if (cx231xx_boards[dev->model].radio.type == CX231XX_RADIO) { | 2406 | if (cx231xx_boards[dev->model].radio.type == CX231XX_RADIO) { |
2400 | dev->radio_dev = cx231xx_vdev_init(dev, &cx231xx_radio_template, | 2407 | dev->radio_dev = cx231xx_vdev_init(dev, &cx231xx_radio_template, |
@@ -2409,12 +2416,13 @@ int cx231xx_register_analog_devices(struct cx231xx *dev) | |||
2409 | cx231xx_errdev("can't register radio device\n"); | 2416 | cx231xx_errdev("can't register radio device\n"); |
2410 | return ret; | 2417 | return ret; |
2411 | } | 2418 | } |
2412 | cx231xx_info("Registered radio device as /dev/radio%d\n", | 2419 | cx231xx_info("Registered radio device as %s\n", |
2413 | dev->radio_dev->num); | 2420 | video_device_node_name(dev->radio_dev)); |
2414 | } | 2421 | } |
2415 | 2422 | ||
2416 | cx231xx_info("V4L2 device registered as /dev/video%d and /dev/vbi%d\n", | 2423 | cx231xx_info("V4L2 device registered as %s and %s\n", |
2417 | dev->vdev->num, dev->vbi_dev->num); | 2424 | video_device_node_name(dev->vdev), |
2425 | video_device_node_name(dev->vbi_dev)); | ||
2418 | 2426 | ||
2419 | return 0; | 2427 | return 0; |
2420 | } | 2428 | } |
diff --git a/drivers/media/video/cx231xx/cx231xx.h b/drivers/media/video/cx231xx/cx231xx.h index 64e2ddd3c401..17d4d1a800ce 100644 --- a/drivers/media/video/cx231xx/cx231xx.h +++ b/drivers/media/video/cx231xx/cx231xx.h | |||
@@ -689,8 +689,6 @@ void cx231xx_release_analog_resources(struct cx231xx *dev); | |||
689 | int cx231xx_register_analog_devices(struct cx231xx *dev); | 689 | int cx231xx_register_analog_devices(struct cx231xx *dev); |
690 | void cx231xx_remove_from_devlist(struct cx231xx *dev); | 690 | void cx231xx_remove_from_devlist(struct cx231xx *dev); |
691 | void cx231xx_add_into_devlist(struct cx231xx *dev); | 691 | void cx231xx_add_into_devlist(struct cx231xx *dev); |
692 | struct cx231xx *cx231xx_get_device(int minor, | ||
693 | enum v4l2_buf_type *fh_type, int *has_radio); | ||
694 | void cx231xx_init_extension(struct cx231xx *dev); | 692 | void cx231xx_init_extension(struct cx231xx *dev); |
695 | void cx231xx_close_extension(struct cx231xx *dev); | 693 | void cx231xx_close_extension(struct cx231xx *dev); |
696 | 694 | ||
diff --git a/drivers/media/video/cx23885/cimax2.c b/drivers/media/video/cx23885/cimax2.c index c04222ffb286..d4a9d2c5947c 100644 --- a/drivers/media/video/cx23885/cimax2.c +++ b/drivers/media/video/cx23885/cimax2.c | |||
@@ -53,6 +53,8 @@ | |||
53 | #define NETUP_CI_CTL 0x04 | 53 | #define NETUP_CI_CTL 0x04 |
54 | #define NETUP_CI_RD 1 | 54 | #define NETUP_CI_RD 1 |
55 | 55 | ||
56 | #define NETUP_IRQ_DETAM 0x1 | ||
57 | #define NETUP_IRQ_IRQAM 0x4 | ||
56 | 58 | ||
57 | static unsigned int ci_dbg; | 59 | static unsigned int ci_dbg; |
58 | module_param(ci_dbg, int, 0644); | 60 | module_param(ci_dbg, int, 0644); |
@@ -73,6 +75,9 @@ struct netup_ci_state { | |||
73 | int status; | 75 | int status; |
74 | struct work_struct work; | 76 | struct work_struct work; |
75 | void *priv; | 77 | void *priv; |
78 | u8 current_irq_mode; | ||
79 | int current_ci_flag; | ||
80 | unsigned long next_status_checked_time; | ||
76 | }; | 81 | }; |
77 | 82 | ||
78 | 83 | ||
@@ -169,24 +174,26 @@ int netup_ci_op_cam(struct dvb_ca_en50221 *en50221, int slot, | |||
169 | if (0 != slot) | 174 | if (0 != slot) |
170 | return -EINVAL; | 175 | return -EINVAL; |
171 | 176 | ||
172 | ret = netup_read_i2c(state->i2c_adap, state->ci_i2c_addr, | 177 | if (state->current_ci_flag != flag) { |
173 | 0, &store, 1); | 178 | ret = netup_read_i2c(state->i2c_adap, state->ci_i2c_addr, |
174 | if (ret != 0) | 179 | 0, &store, 1); |
175 | return ret; | 180 | if (ret != 0) |
181 | return ret; | ||
176 | 182 | ||
177 | store &= ~0x0c; | 183 | store &= ~0x0c; |
178 | store |= flag; | 184 | store |= flag; |
179 | 185 | ||
180 | ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr, | 186 | ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr, |
181 | 0, &store, 1); | 187 | 0, &store, 1); |
182 | if (ret != 0) | 188 | if (ret != 0) |
183 | return ret; | 189 | return ret; |
190 | }; | ||
191 | state->current_ci_flag = flag; | ||
184 | 192 | ||
185 | mutex_lock(&dev->gpio_lock); | 193 | mutex_lock(&dev->gpio_lock); |
186 | 194 | ||
187 | /* write addr */ | 195 | /* write addr */ |
188 | cx_write(MC417_OEN, NETUP_EN_ALL); | 196 | cx_write(MC417_OEN, NETUP_EN_ALL); |
189 | msleep(2); | ||
190 | cx_write(MC417_RWD, NETUP_CTRL_OFF | | 197 | cx_write(MC417_RWD, NETUP_CTRL_OFF | |
191 | NETUP_ADLO | (0xff & addr)); | 198 | NETUP_ADLO | (0xff & addr)); |
192 | cx_clear(MC417_RWD, NETUP_ADLO); | 199 | cx_clear(MC417_RWD, NETUP_ADLO); |
@@ -196,7 +203,6 @@ int netup_ci_op_cam(struct dvb_ca_en50221 *en50221, int slot, | |||
196 | 203 | ||
197 | if (read) { /* data in */ | 204 | if (read) { /* data in */ |
198 | cx_write(MC417_OEN, NETUP_EN_ALL | NETUP_DATA); | 205 | cx_write(MC417_OEN, NETUP_EN_ALL | NETUP_DATA); |
199 | msleep(2); | ||
200 | } else /* data out */ | 206 | } else /* data out */ |
201 | cx_write(MC417_RWD, NETUP_CTRL_OFF | data); | 207 | cx_write(MC417_RWD, NETUP_CTRL_OFF | data); |
202 | 208 | ||
@@ -213,8 +219,8 @@ int netup_ci_op_cam(struct dvb_ca_en50221 *en50221, int slot, | |||
213 | if (mem < 0) | 219 | if (mem < 0) |
214 | return -EREMOTEIO; | 220 | return -EREMOTEIO; |
215 | 221 | ||
216 | ci_dbg_print("%s: %s: addr=[0x%02x], %s=%x\n", __func__, | 222 | ci_dbg_print("%s: %s: chipaddr=[0x%x] addr=[0x%02x], %s=%x\n", __func__, |
217 | (read) ? "read" : "write", addr, | 223 | (read) ? "read" : "write", state->ci_i2c_addr, addr, |
218 | (flag == NETUP_CI_CTL) ? "ctl" : "mem", | 224 | (flag == NETUP_CI_CTL) ? "ctl" : "mem", |
219 | (read) ? mem : data); | 225 | (read) ? mem : data); |
220 | 226 | ||
@@ -283,14 +289,39 @@ int netup_ci_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot) | |||
283 | return 0; | 289 | return 0; |
284 | } | 290 | } |
285 | 291 | ||
292 | int netup_ci_set_irq(struct dvb_ca_en50221 *en50221, u8 irq_mode) | ||
293 | { | ||
294 | struct netup_ci_state *state = en50221->data; | ||
295 | int ret; | ||
296 | |||
297 | if (irq_mode == state->current_irq_mode) | ||
298 | return 0; | ||
299 | |||
300 | ci_dbg_print("%s: chipaddr=[0x%x] setting ci IRQ to [0x%x] \n", | ||
301 | __func__, state->ci_i2c_addr, irq_mode); | ||
302 | ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr, | ||
303 | 0x1b, &irq_mode, 1); | ||
304 | |||
305 | if (ret != 0) | ||
306 | return ret; | ||
307 | |||
308 | state->current_irq_mode = irq_mode; | ||
309 | |||
310 | return 0; | ||
311 | } | ||
312 | |||
286 | int netup_ci_slot_ts_ctl(struct dvb_ca_en50221 *en50221, int slot) | 313 | int netup_ci_slot_ts_ctl(struct dvb_ca_en50221 *en50221, int slot) |
287 | { | 314 | { |
288 | struct netup_ci_state *state = en50221->data; | 315 | struct netup_ci_state *state = en50221->data; |
289 | u8 buf = 0x60; | 316 | u8 buf; |
290 | 317 | ||
291 | if (0 != slot) | 318 | if (0 != slot) |
292 | return -EINVAL; | 319 | return -EINVAL; |
293 | 320 | ||
321 | netup_read_i2c(state->i2c_adap, state->ci_i2c_addr, | ||
322 | 0, &buf, 1); | ||
323 | buf |= 0x60; | ||
324 | |||
294 | return netup_write_i2c(state->i2c_adap, state->ci_i2c_addr, | 325 | return netup_write_i2c(state->i2c_adap, state->ci_i2c_addr, |
295 | 0, &buf, 1); | 326 | 0, &buf, 1); |
296 | } | 327 | } |
@@ -303,21 +334,35 @@ static void netup_read_ci_status(struct work_struct *work) | |||
303 | u8 buf[33]; | 334 | u8 buf[33]; |
304 | int ret; | 335 | int ret; |
305 | 336 | ||
306 | ret = netup_read_i2c(state->i2c_adap, state->ci_i2c_addr, | 337 | /* CAM module IRQ processing. fast operation */ |
307 | 0, &buf[0], 33); | 338 | dvb_ca_en50221_frda_irq(&state->ca, 0); |
308 | 339 | ||
309 | if (ret != 0) | 340 | /* CAM module INSERT/REMOVE processing. slow operation because of i2c |
310 | return; | 341 | * transfers */ |
342 | if (time_after(jiffies, state->next_status_checked_time) | ||
343 | || !state->status) { | ||
344 | ret = netup_read_i2c(state->i2c_adap, state->ci_i2c_addr, | ||
345 | 0, &buf[0], 33); | ||
346 | |||
347 | state->next_status_checked_time = jiffies | ||
348 | + msecs_to_jiffies(1000); | ||
349 | |||
350 | if (ret != 0) | ||
351 | return; | ||
311 | 352 | ||
312 | ci_dbg_print("%s: Slot Status Addr=[0x%04x], Reg=[0x%02x], data=%02x, " | 353 | ci_dbg_print("%s: Slot Status Addr=[0x%04x], " |
313 | "TS config = %02x\n", __func__, state->ci_i2c_addr, 0, buf[0], | 354 | "Reg=[0x%02x], data=%02x, " |
314 | buf[32]); | 355 | "TS config = %02x\n", __func__, |
356 | state->ci_i2c_addr, 0, buf[0], | ||
357 | buf[0]); | ||
315 | 358 | ||
316 | if (buf[0] & 1) | 359 | |
317 | state->status = DVB_CA_EN50221_POLL_CAM_PRESENT | | 360 | if (buf[0] & 1) |
318 | DVB_CA_EN50221_POLL_CAM_READY; | 361 | state->status = DVB_CA_EN50221_POLL_CAM_PRESENT | |
319 | else | 362 | DVB_CA_EN50221_POLL_CAM_READY; |
320 | state->status = 0; | 363 | else |
364 | state->status = 0; | ||
365 | }; | ||
321 | } | 366 | } |
322 | 367 | ||
323 | /* CI irq handler */ | 368 | /* CI irq handler */ |
@@ -347,6 +392,9 @@ int netup_poll_ci_slot_status(struct dvb_ca_en50221 *en50221, int slot, int open | |||
347 | if (0 != slot) | 392 | if (0 != slot) |
348 | return -EINVAL; | 393 | return -EINVAL; |
349 | 394 | ||
395 | netup_ci_set_irq(en50221, open ? (NETUP_IRQ_DETAM | NETUP_IRQ_IRQAM) | ||
396 | : NETUP_IRQ_DETAM); | ||
397 | |||
350 | return state->status; | 398 | return state->status; |
351 | } | 399 | } |
352 | 400 | ||
@@ -381,8 +429,8 @@ int netup_ci_init(struct cx23885_tsport *port) | |||
381 | 0x01, /* power on (use it like store place) */ | 429 | 0x01, /* power on (use it like store place) */ |
382 | 0x00, /* RFU */ | 430 | 0x00, /* RFU */ |
383 | 0x00, /* int status read only */ | 431 | 0x00, /* int status read only */ |
384 | 0x01, /* all int unmasked */ | 432 | NETUP_IRQ_IRQAM | NETUP_IRQ_DETAM, /* DETAM, IRQAM unmasked */ |
385 | 0x04, /* int config */ | 433 | 0x05, /* EXTINT=active-high, INT=push-pull */ |
386 | 0x00, /* USCG1 */ | 434 | 0x00, /* USCG1 */ |
387 | 0x04, /* ack active low */ | 435 | 0x04, /* ack active low */ |
388 | 0x00, /* LOCK = 0 */ | 436 | 0x00, /* LOCK = 0 */ |
@@ -422,6 +470,7 @@ int netup_ci_init(struct cx23885_tsport *port) | |||
422 | state->ca.poll_slot_status = netup_poll_ci_slot_status; | 470 | state->ca.poll_slot_status = netup_poll_ci_slot_status; |
423 | state->ca.data = state; | 471 | state->ca.data = state; |
424 | state->priv = port; | 472 | state->priv = port; |
473 | state->current_irq_mode = NETUP_IRQ_IRQAM | NETUP_IRQ_DETAM; | ||
425 | 474 | ||
426 | ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr, | 475 | ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr, |
427 | 0, &cimax_init[0], 34); | 476 | 0, &cimax_init[0], 34); |
diff --git a/drivers/media/video/cx23885/cx23885-417.c b/drivers/media/video/cx23885/cx23885-417.c index 0eed852c61e9..88c0d2481118 100644 --- a/drivers/media/video/cx23885/cx23885-417.c +++ b/drivers/media/video/cx23885/cx23885-417.c | |||
@@ -1568,28 +1568,11 @@ static int vidioc_queryctrl(struct file *file, void *priv, | |||
1568 | 1568 | ||
1569 | static int mpeg_open(struct file *file) | 1569 | static int mpeg_open(struct file *file) |
1570 | { | 1570 | { |
1571 | int minor = video_devdata(file)->minor; | 1571 | struct cx23885_dev *dev = video_drvdata(file); |
1572 | struct cx23885_dev *h, *dev = NULL; | ||
1573 | struct list_head *list; | ||
1574 | struct cx23885_fh *fh; | 1572 | struct cx23885_fh *fh; |
1575 | 1573 | ||
1576 | dprintk(2, "%s()\n", __func__); | 1574 | dprintk(2, "%s()\n", __func__); |
1577 | 1575 | ||
1578 | lock_kernel(); | ||
1579 | list_for_each(list, &cx23885_devlist) { | ||
1580 | h = list_entry(list, struct cx23885_dev, devlist); | ||
1581 | if (h->v4l_device && | ||
1582 | h->v4l_device->minor == minor) { | ||
1583 | dev = h; | ||
1584 | break; | ||
1585 | } | ||
1586 | } | ||
1587 | |||
1588 | if (dev == NULL) { | ||
1589 | unlock_kernel(); | ||
1590 | return -ENODEV; | ||
1591 | } | ||
1592 | |||
1593 | /* allocate + initialize per filehandle data */ | 1576 | /* allocate + initialize per filehandle data */ |
1594 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); | 1577 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); |
1595 | if (NULL == fh) { | 1578 | if (NULL == fh) { |
@@ -1597,6 +1580,8 @@ static int mpeg_open(struct file *file) | |||
1597 | return -ENOMEM; | 1580 | return -ENOMEM; |
1598 | } | 1581 | } |
1599 | 1582 | ||
1583 | lock_kernel(); | ||
1584 | |||
1600 | file->private_data = fh; | 1585 | file->private_data = fh; |
1601 | fh->dev = dev; | 1586 | fh->dev = dev; |
1602 | 1587 | ||
@@ -1736,7 +1721,6 @@ static struct video_device cx23885_mpeg_template = { | |||
1736 | .name = "cx23885", | 1721 | .name = "cx23885", |
1737 | .fops = &mpeg_fops, | 1722 | .fops = &mpeg_fops, |
1738 | .ioctl_ops = &mpeg_ioctl_ops, | 1723 | .ioctl_ops = &mpeg_ioctl_ops, |
1739 | .minor = -1, | ||
1740 | .tvnorms = CX23885_NORMS, | 1724 | .tvnorms = CX23885_NORMS, |
1741 | .current_norm = V4L2_STD_NTSC_M, | 1725 | .current_norm = V4L2_STD_NTSC_M, |
1742 | }; | 1726 | }; |
@@ -1746,7 +1730,7 @@ void cx23885_417_unregister(struct cx23885_dev *dev) | |||
1746 | dprintk(1, "%s()\n", __func__); | 1730 | dprintk(1, "%s()\n", __func__); |
1747 | 1731 | ||
1748 | if (dev->v4l_device) { | 1732 | if (dev->v4l_device) { |
1749 | if (-1 != dev->v4l_device->minor) | 1733 | if (video_is_registered(dev->v4l_device)) |
1750 | video_unregister_device(dev->v4l_device); | 1734 | video_unregister_device(dev->v4l_device); |
1751 | else | 1735 | else |
1752 | video_device_release(dev->v4l_device); | 1736 | video_device_release(dev->v4l_device); |
@@ -1803,6 +1787,7 @@ int cx23885_417_register(struct cx23885_dev *dev) | |||
1803 | /* Allocate and initialize V4L video device */ | 1787 | /* Allocate and initialize V4L video device */ |
1804 | dev->v4l_device = cx23885_video_dev_alloc(tsport, | 1788 | dev->v4l_device = cx23885_video_dev_alloc(tsport, |
1805 | dev->pci, &cx23885_mpeg_template, "mpeg"); | 1789 | dev->pci, &cx23885_mpeg_template, "mpeg"); |
1790 | video_set_drvdata(dev->v4l_device, dev); | ||
1806 | err = video_register_device(dev->v4l_device, | 1791 | err = video_register_device(dev->v4l_device, |
1807 | VFL_TYPE_GRABBER, -1); | 1792 | VFL_TYPE_GRABBER, -1); |
1808 | if (err < 0) { | 1793 | if (err < 0) { |
@@ -1810,8 +1795,8 @@ int cx23885_417_register(struct cx23885_dev *dev) | |||
1810 | return err; | 1795 | return err; |
1811 | } | 1796 | } |
1812 | 1797 | ||
1813 | printk(KERN_INFO "%s: registered device video%d [mpeg]\n", | 1798 | printk(KERN_INFO "%s: registered device %s [mpeg]\n", |
1814 | dev->name, dev->v4l_device->num); | 1799 | dev->name, video_device_node_name(dev->v4l_device)); |
1815 | 1800 | ||
1816 | return 0; | 1801 | return 0; |
1817 | } | 1802 | } |
diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c index 04b12d27bc13..0dde57e96d30 100644 --- a/drivers/media/video/cx23885/cx23885-core.c +++ b/drivers/media/video/cx23885/cx23885-core.c | |||
@@ -55,9 +55,6 @@ MODULE_PARM_DESC(card, "card type"); | |||
55 | 55 | ||
56 | static unsigned int cx23885_devcount; | 56 | static unsigned int cx23885_devcount; |
57 | 57 | ||
58 | static DEFINE_MUTEX(devlist); | ||
59 | LIST_HEAD(cx23885_devlist); | ||
60 | |||
61 | #define NO_SYNC_LINE (-1U) | 58 | #define NO_SYNC_LINE (-1U) |
62 | 59 | ||
63 | /* FIXME, these allocations will change when | 60 | /* FIXME, these allocations will change when |
@@ -785,10 +782,6 @@ static int cx23885_dev_setup(struct cx23885_dev *dev) | |||
785 | dev->nr = cx23885_devcount++; | 782 | dev->nr = cx23885_devcount++; |
786 | sprintf(dev->name, "cx23885[%d]", dev->nr); | 783 | sprintf(dev->name, "cx23885[%d]", dev->nr); |
787 | 784 | ||
788 | mutex_lock(&devlist); | ||
789 | list_add_tail(&dev->devlist, &cx23885_devlist); | ||
790 | mutex_unlock(&devlist); | ||
791 | |||
792 | /* Configure the internal memory */ | 785 | /* Configure the internal memory */ |
793 | if (dev->pci->device == 0x8880) { | 786 | if (dev->pci->device == 0x8880) { |
794 | /* Could be 887 or 888, assume a default */ | 787 | /* Could be 887 or 888, assume a default */ |
@@ -2008,10 +2001,6 @@ static void __devexit cx23885_finidev(struct pci_dev *pci_dev) | |||
2008 | /* unregister stuff */ | 2001 | /* unregister stuff */ |
2009 | free_irq(pci_dev->irq, dev); | 2002 | free_irq(pci_dev->irq, dev); |
2010 | 2003 | ||
2011 | mutex_lock(&devlist); | ||
2012 | list_del(&dev->devlist); | ||
2013 | mutex_unlock(&devlist); | ||
2014 | |||
2015 | cx23885_dev_unregister(dev); | 2004 | cx23885_dev_unregister(dev); |
2016 | v4l2_device_unregister(v4l2_dev); | 2005 | v4l2_device_unregister(v4l2_dev); |
2017 | kfree(dev); | 2006 | kfree(dev); |
diff --git a/drivers/media/video/cx23885/cx23885-input.c b/drivers/media/video/cx23885/cx23885-input.c index 469e083dd5f8..768eec92ccf9 100644 --- a/drivers/media/video/cx23885/cx23885-input.c +++ b/drivers/media/video/cx23885/cx23885-input.c | |||
@@ -377,7 +377,7 @@ int cx23885_input_init(struct cx23885_dev *dev) | |||
377 | cx23885_boards[dev->board].name); | 377 | cx23885_boards[dev->board].name); |
378 | snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(dev->pci)); | 378 | snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(dev->pci)); |
379 | 379 | ||
380 | ret = ir_input_init(input_dev, &ir->ir, ir_type, ir_codes); | 380 | ret = ir_input_init(input_dev, &ir->ir, ir_type); |
381 | if (ret < 0) | 381 | if (ret < 0) |
382 | goto err_out_free; | 382 | goto err_out_free; |
383 | 383 | ||
@@ -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 = input_register_device(ir->dev); | 400 | ret = ir_input_register(ir->dev, ir_codes); |
401 | if (ret) | 401 | if (ret) |
402 | goto err_out_stop; | 402 | goto err_out_stop; |
403 | 403 | ||
@@ -407,8 +407,6 @@ err_out_stop: | |||
407 | cx23885_input_ir_stop(dev); | 407 | cx23885_input_ir_stop(dev); |
408 | dev->ir_input = NULL; | 408 | dev->ir_input = NULL; |
409 | err_out_free: | 409 | err_out_free: |
410 | ir_input_free(input_dev); | ||
411 | input_free_device(input_dev); | ||
412 | kfree(ir); | 410 | kfree(ir); |
413 | return ret; | 411 | return ret; |
414 | } | 412 | } |
@@ -420,8 +418,7 @@ void cx23885_input_fini(struct cx23885_dev *dev) | |||
420 | 418 | ||
421 | if (dev->ir_input == NULL) | 419 | if (dev->ir_input == NULL) |
422 | return; | 420 | return; |
423 | ir_input_free(dev->ir_input->dev); | 421 | ir_input_unregister(dev->ir_input->dev); |
424 | input_unregister_device(dev->ir_input->dev); | ||
425 | kfree(dev->ir_input); | 422 | kfree(dev->ir_input); |
426 | dev->ir_input = NULL; | 423 | dev->ir_input = NULL; |
427 | } | 424 | } |
diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c index 8b372b4f0de2..8934d61cf660 100644 --- a/drivers/media/video/cx23885/cx23885-video.c +++ b/drivers/media/video/cx23885/cx23885-video.c | |||
@@ -318,11 +318,11 @@ static struct video_device *cx23885_vdev_init(struct cx23885_dev *dev, | |||
318 | if (NULL == vfd) | 318 | if (NULL == vfd) |
319 | return NULL; | 319 | return NULL; |
320 | *vfd = *template; | 320 | *vfd = *template; |
321 | vfd->minor = -1; | ||
322 | vfd->v4l2_dev = &dev->v4l2_dev; | 321 | vfd->v4l2_dev = &dev->v4l2_dev; |
323 | vfd->release = video_device_release; | 322 | vfd->release = video_device_release; |
324 | snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", | 323 | snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", |
325 | dev->name, type, cx23885_boards[dev->board].name); | 324 | dev->name, type, cx23885_boards[dev->board].name); |
325 | video_set_drvdata(vfd, dev); | ||
326 | return vfd; | 326 | return vfd; |
327 | } | 327 | } |
328 | 328 | ||
@@ -716,46 +716,34 @@ static int get_resource(struct cx23885_fh *fh) | |||
716 | 716 | ||
717 | static int video_open(struct file *file) | 717 | static int video_open(struct file *file) |
718 | { | 718 | { |
719 | int minor = video_devdata(file)->minor; | 719 | struct video_device *vdev = video_devdata(file); |
720 | struct cx23885_dev *h, *dev = NULL; | 720 | struct cx23885_dev *dev = video_drvdata(file); |
721 | struct cx23885_fh *fh; | 721 | struct cx23885_fh *fh; |
722 | struct list_head *list; | ||
723 | enum v4l2_buf_type type = 0; | 722 | enum v4l2_buf_type type = 0; |
724 | int radio = 0; | 723 | int radio = 0; |
725 | 724 | ||
726 | lock_kernel(); | 725 | switch (vdev->vfl_type) { |
727 | list_for_each(list, &cx23885_devlist) { | 726 | case VFL_TYPE_GRABBER: |
728 | h = list_entry(list, struct cx23885_dev, devlist); | 727 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
729 | if (h->video_dev && | 728 | break; |
730 | h->video_dev->minor == minor) { | 729 | case VFL_TYPE_VBI: |
731 | dev = h; | 730 | type = V4L2_BUF_TYPE_VBI_CAPTURE; |
732 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 731 | break; |
733 | } | 732 | case VFL_TYPE_RADIO: |
734 | if (h->vbi_dev && | 733 | radio = 1; |
735 | h->vbi_dev->minor == minor) { | 734 | break; |
736 | dev = h; | ||
737 | type = V4L2_BUF_TYPE_VBI_CAPTURE; | ||
738 | } | ||
739 | if (h->radio_dev && | ||
740 | h->radio_dev->minor == minor) { | ||
741 | radio = 1; | ||
742 | dev = h; | ||
743 | } | ||
744 | } | ||
745 | if (NULL == dev) { | ||
746 | unlock_kernel(); | ||
747 | return -ENODEV; | ||
748 | } | 735 | } |
749 | 736 | ||
750 | dprintk(1, "open minor=%d radio=%d type=%s\n", | 737 | dprintk(1, "open dev=%s radio=%d type=%s\n", |
751 | minor, radio, v4l2_type_names[type]); | 738 | video_device_node_name(vdev), radio, v4l2_type_names[type]); |
752 | 739 | ||
753 | /* allocate + initialize per filehandle data */ | 740 | /* allocate + initialize per filehandle data */ |
754 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); | 741 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); |
755 | if (NULL == fh) { | 742 | if (NULL == fh) |
756 | unlock_kernel(); | ||
757 | return -ENOMEM; | 743 | return -ENOMEM; |
758 | } | 744 | |
745 | lock_kernel(); | ||
746 | |||
759 | file->private_data = fh; | 747 | file->private_data = fh; |
760 | fh->dev = dev; | 748 | fh->dev = dev; |
761 | fh->radio = radio; | 749 | fh->radio = radio; |
@@ -1441,7 +1429,6 @@ static struct video_device cx23885_vbi_template; | |||
1441 | static struct video_device cx23885_video_template = { | 1429 | static struct video_device cx23885_video_template = { |
1442 | .name = "cx23885-video", | 1430 | .name = "cx23885-video", |
1443 | .fops = &video_fops, | 1431 | .fops = &video_fops, |
1444 | .minor = -1, | ||
1445 | .ioctl_ops = &video_ioctl_ops, | 1432 | .ioctl_ops = &video_ioctl_ops, |
1446 | .tvnorms = CX23885_NORMS, | 1433 | .tvnorms = CX23885_NORMS, |
1447 | .current_norm = V4L2_STD_NTSC_M, | 1434 | .current_norm = V4L2_STD_NTSC_M, |
@@ -1461,7 +1448,7 @@ void cx23885_video_unregister(struct cx23885_dev *dev) | |||
1461 | cx_clear(PCI_INT_MSK, 1); | 1448 | cx_clear(PCI_INT_MSK, 1); |
1462 | 1449 | ||
1463 | if (dev->video_dev) { | 1450 | if (dev->video_dev) { |
1464 | if (-1 != dev->video_dev->minor) | 1451 | if (video_is_registered(dev->video_dev)) |
1465 | video_unregister_device(dev->video_dev); | 1452 | video_unregister_device(dev->video_dev); |
1466 | else | 1453 | else |
1467 | video_device_release(dev->video_dev); | 1454 | video_device_release(dev->video_dev); |
@@ -1532,8 +1519,8 @@ int cx23885_video_register(struct cx23885_dev *dev) | |||
1532 | dev->name); | 1519 | dev->name); |
1533 | goto fail_unreg; | 1520 | goto fail_unreg; |
1534 | } | 1521 | } |
1535 | printk(KERN_INFO "%s/0: registered device video%d [v4l2]\n", | 1522 | printk(KERN_INFO "%s/0: registered device %s [v4l2]\n", |
1536 | dev->name, dev->video_dev->num); | 1523 | dev->name, video_device_node_name(dev->video_dev)); |
1537 | /* initial device configuration */ | 1524 | /* initial device configuration */ |
1538 | mutex_lock(&dev->lock); | 1525 | mutex_lock(&dev->lock); |
1539 | cx23885_set_tvnorm(dev, dev->tvnorm); | 1526 | cx23885_set_tvnorm(dev, dev->tvnorm); |
diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index fa744764dc8b..08b3f6b136a0 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h | |||
@@ -303,7 +303,6 @@ struct cx23885_tsport { | |||
303 | }; | 303 | }; |
304 | 304 | ||
305 | struct cx23885_dev { | 305 | struct cx23885_dev { |
306 | struct list_head devlist; | ||
307 | atomic_t refcount; | 306 | atomic_t refcount; |
308 | struct v4l2_device v4l2_dev; | 307 | struct v4l2_device v4l2_dev; |
309 | 308 | ||
@@ -399,8 +398,6 @@ static inline struct cx23885_dev *to_cx23885(struct v4l2_device *v4l2_dev) | |||
399 | 398 | ||
400 | extern struct v4l2_subdev *cx23885_find_hw(struct cx23885_dev *dev, u32 hw); | 399 | extern struct v4l2_subdev *cx23885_find_hw(struct cx23885_dev *dev, u32 hw); |
401 | 400 | ||
402 | extern struct list_head cx23885_devlist; | ||
403 | |||
404 | #define SRAM_CH01 0 /* Video A */ | 401 | #define SRAM_CH01 0 /* Video A */ |
405 | #define SRAM_CH02 1 /* VBI A */ | 402 | #define SRAM_CH02 1 /* VBI A */ |
406 | #define SRAM_CH03 2 /* Video B */ | 403 | #define SRAM_CH03 2 /* Video B */ |
diff --git a/drivers/media/video/cx23885/cx23888-ir.c b/drivers/media/video/cx23885/cx23888-ir.c index 3ccc8afeccf3..2bf57a4527d3 100644 --- a/drivers/media/video/cx23885/cx23888-ir.c +++ b/drivers/media/video/cx23885/cx23888-ir.c | |||
@@ -124,15 +124,12 @@ struct cx23888_ir_state { | |||
124 | atomic_t rxclk_divider; | 124 | atomic_t rxclk_divider; |
125 | atomic_t rx_invert; | 125 | atomic_t rx_invert; |
126 | 126 | ||
127 | struct kfifo *rx_kfifo; | 127 | struct kfifo rx_kfifo; |
128 | spinlock_t rx_kfifo_lock; | 128 | spinlock_t rx_kfifo_lock; |
129 | 129 | ||
130 | struct v4l2_subdev_ir_parameters tx_params; | 130 | struct v4l2_subdev_ir_parameters tx_params; |
131 | struct mutex tx_params_lock; | 131 | struct mutex tx_params_lock; |
132 | atomic_t txclk_divider; | 132 | atomic_t txclk_divider; |
133 | |||
134 | struct kfifo *tx_kfifo; | ||
135 | spinlock_t tx_kfifo_lock; | ||
136 | }; | 133 | }; |
137 | 134 | ||
138 | static inline struct cx23888_ir_state *to_state(struct v4l2_subdev *sd) | 135 | static inline struct cx23888_ir_state *to_state(struct v4l2_subdev *sd) |
@@ -522,6 +519,7 @@ static int cx23888_ir_irq_handler(struct v4l2_subdev *sd, u32 status, | |||
522 | { | 519 | { |
523 | struct cx23888_ir_state *state = to_state(sd); | 520 | struct cx23888_ir_state *state = to_state(sd); |
524 | struct cx23885_dev *dev = state->dev; | 521 | struct cx23885_dev *dev = state->dev; |
522 | unsigned long flags; | ||
525 | 523 | ||
526 | u32 cntrl = cx23888_ir_read4(dev, CX23888_IR_CNTRL_REG); | 524 | u32 cntrl = cx23888_ir_read4(dev, CX23888_IR_CNTRL_REG); |
527 | u32 irqen = cx23888_ir_read4(dev, CX23888_IR_IRQEN_REG); | 525 | u32 irqen = cx23888_ir_read4(dev, CX23888_IR_IRQEN_REG); |
@@ -594,8 +592,9 @@ static int cx23888_ir_irq_handler(struct v4l2_subdev *sd, u32 status, | |||
594 | if (i == 0) | 592 | if (i == 0) |
595 | break; | 593 | break; |
596 | j = i * sizeof(u32); | 594 | j = i * sizeof(u32); |
597 | k = kfifo_put(state->rx_kfifo, | 595 | k = kfifo_in_locked(&state->rx_kfifo, |
598 | (unsigned char *) rx_data, j); | 596 | (unsigned char *) rx_data, j, |
597 | &state->rx_kfifo_lock); | ||
599 | if (k != j) | 598 | if (k != j) |
600 | kror++; /* rx_kfifo over run */ | 599 | kror++; /* rx_kfifo over run */ |
601 | } | 600 | } |
@@ -631,8 +630,11 @@ static int cx23888_ir_irq_handler(struct v4l2_subdev *sd, u32 status, | |||
631 | cx23888_ir_write4(dev, CX23888_IR_CNTRL_REG, cntrl); | 630 | cx23888_ir_write4(dev, CX23888_IR_CNTRL_REG, cntrl); |
632 | *handled = true; | 631 | *handled = true; |
633 | } | 632 | } |
634 | if (kfifo_len(state->rx_kfifo) >= CX23888_IR_RX_KFIFO_SIZE / 2) | 633 | |
634 | spin_lock_irqsave(&state->rx_kfifo_lock, flags); | ||
635 | if (kfifo_len(&state->rx_kfifo) >= CX23888_IR_RX_KFIFO_SIZE / 2) | ||
635 | events |= V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ; | 636 | events |= V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ; |
637 | spin_unlock_irqrestore(&state->rx_kfifo_lock, flags); | ||
636 | 638 | ||
637 | if (events) | 639 | if (events) |
638 | v4l2_subdev_notify(sd, V4L2_SUBDEV_IR_RX_NOTIFY, &events); | 640 | v4l2_subdev_notify(sd, V4L2_SUBDEV_IR_RX_NOTIFY, &events); |
@@ -657,7 +659,7 @@ static int cx23888_ir_rx_read(struct v4l2_subdev *sd, u8 *buf, size_t count, | |||
657 | return 0; | 659 | return 0; |
658 | } | 660 | } |
659 | 661 | ||
660 | n = kfifo_get(state->rx_kfifo, buf, n); | 662 | n = kfifo_out_locked(&state->rx_kfifo, buf, n, &state->rx_kfifo_lock); |
661 | 663 | ||
662 | n /= sizeof(u32); | 664 | n /= sizeof(u32); |
663 | *num = n * sizeof(u32); | 665 | *num = n * sizeof(u32); |
@@ -785,7 +787,12 @@ static int cx23888_ir_rx_s_parameters(struct v4l2_subdev *sd, | |||
785 | o->interrupt_enable = p->interrupt_enable; | 787 | o->interrupt_enable = p->interrupt_enable; |
786 | o->enable = p->enable; | 788 | o->enable = p->enable; |
787 | if (p->enable) { | 789 | if (p->enable) { |
788 | kfifo_reset(state->rx_kfifo); | 790 | unsigned long flags; |
791 | |||
792 | spin_lock_irqsave(&state->rx_kfifo_lock, flags); | ||
793 | kfifo_reset(&state->rx_kfifo); | ||
794 | /* reset tx_fifo too if there is one... */ | ||
795 | spin_unlock_irqrestore(&state->rx_kfifo_lock, flags); | ||
789 | if (p->interrupt_enable) | 796 | if (p->interrupt_enable) |
790 | irqenable_rx(dev, IRQEN_RSE | IRQEN_RTE | IRQEN_ROE); | 797 | irqenable_rx(dev, IRQEN_RSE | IRQEN_RTE | IRQEN_ROE); |
791 | control_rx_enable(dev, p->enable); | 798 | control_rx_enable(dev, p->enable); |
@@ -892,7 +899,6 @@ static int cx23888_ir_tx_s_parameters(struct v4l2_subdev *sd, | |||
892 | o->interrupt_enable = p->interrupt_enable; | 899 | o->interrupt_enable = p->interrupt_enable; |
893 | o->enable = p->enable; | 900 | o->enable = p->enable; |
894 | if (p->enable) { | 901 | if (p->enable) { |
895 | kfifo_reset(state->tx_kfifo); | ||
896 | if (p->interrupt_enable) | 902 | if (p->interrupt_enable) |
897 | irqenable_tx(dev, IRQEN_TSE); | 903 | irqenable_tx(dev, IRQEN_TSE); |
898 | control_tx_enable(dev, p->enable); | 904 | control_tx_enable(dev, p->enable); |
@@ -1168,18 +1174,8 @@ int cx23888_ir_probe(struct cx23885_dev *dev) | |||
1168 | return -ENOMEM; | 1174 | return -ENOMEM; |
1169 | 1175 | ||
1170 | spin_lock_init(&state->rx_kfifo_lock); | 1176 | spin_lock_init(&state->rx_kfifo_lock); |
1171 | state->rx_kfifo = kfifo_alloc(CX23888_IR_RX_KFIFO_SIZE, GFP_KERNEL, | 1177 | if (kfifo_alloc(&state->rx_kfifo, CX23888_IR_RX_KFIFO_SIZE, GFP_KERNEL)) |
1172 | &state->rx_kfifo_lock); | ||
1173 | if (state->rx_kfifo == NULL) | ||
1174 | return -ENOMEM; | ||
1175 | |||
1176 | spin_lock_init(&state->tx_kfifo_lock); | ||
1177 | state->tx_kfifo = kfifo_alloc(CX23888_IR_TX_KFIFO_SIZE, GFP_KERNEL, | ||
1178 | &state->tx_kfifo_lock); | ||
1179 | if (state->tx_kfifo == NULL) { | ||
1180 | kfifo_free(state->rx_kfifo); | ||
1181 | return -ENOMEM; | 1178 | return -ENOMEM; |
1182 | } | ||
1183 | 1179 | ||
1184 | state->dev = dev; | 1180 | state->dev = dev; |
1185 | state->id = V4L2_IDENT_CX23888_IR; | 1181 | state->id = V4L2_IDENT_CX23888_IR; |
@@ -1211,8 +1207,7 @@ int cx23888_ir_probe(struct cx23885_dev *dev) | |||
1211 | sizeof(struct v4l2_subdev_ir_parameters)); | 1207 | sizeof(struct v4l2_subdev_ir_parameters)); |
1212 | v4l2_subdev_call(sd, ir, tx_s_parameters, &default_params); | 1208 | v4l2_subdev_call(sd, ir, tx_s_parameters, &default_params); |
1213 | } else { | 1209 | } else { |
1214 | kfifo_free(state->rx_kfifo); | 1210 | kfifo_free(&state->rx_kfifo); |
1215 | kfifo_free(state->tx_kfifo); | ||
1216 | } | 1211 | } |
1217 | return ret; | 1212 | return ret; |
1218 | } | 1213 | } |
@@ -1231,8 +1226,7 @@ int cx23888_ir_remove(struct cx23885_dev *dev) | |||
1231 | 1226 | ||
1232 | state = to_state(sd); | 1227 | state = to_state(sd); |
1233 | v4l2_device_unregister_subdev(sd); | 1228 | v4l2_device_unregister_subdev(sd); |
1234 | kfifo_free(state->rx_kfifo); | 1229 | kfifo_free(&state->rx_kfifo); |
1235 | kfifo_free(state->tx_kfifo); | ||
1236 | kfree(state); | 1230 | kfree(state); |
1237 | /* Nothing more to free() as state held the actual v4l2_subdev object */ | 1231 | /* Nothing more to free() as state held the actual v4l2_subdev object */ |
1238 | return 0; | 1232 | return 0; |
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index fbdc1cde56a6..6fe30e6c4262 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c | |||
@@ -1048,21 +1048,15 @@ static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id) | |||
1048 | 1048 | ||
1049 | static int mpeg_open(struct file *file) | 1049 | static int mpeg_open(struct file *file) |
1050 | { | 1050 | { |
1051 | int minor = video_devdata(file)->minor; | 1051 | struct video_device *vdev = video_devdata(file); |
1052 | struct cx8802_dev *dev = NULL; | 1052 | struct cx8802_dev *dev = video_drvdata(file); |
1053 | struct cx8802_fh *fh; | 1053 | struct cx8802_fh *fh; |
1054 | struct cx8802_driver *drv = NULL; | 1054 | struct cx8802_driver *drv = NULL; |
1055 | int err; | 1055 | int err; |
1056 | 1056 | ||
1057 | lock_kernel(); | ||
1058 | dev = cx8802_get_device(minor); | ||
1059 | |||
1060 | dprintk( 1, "%s\n", __func__); | 1057 | dprintk( 1, "%s\n", __func__); |
1061 | 1058 | ||
1062 | if (dev == NULL) { | 1059 | lock_kernel(); |
1063 | unlock_kernel(); | ||
1064 | return -ENODEV; | ||
1065 | } | ||
1066 | 1060 | ||
1067 | /* Make sure we can acquire the hardware */ | 1061 | /* Make sure we can acquire the hardware */ |
1068 | drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD); | 1062 | drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD); |
@@ -1081,7 +1075,7 @@ static int mpeg_open(struct file *file) | |||
1081 | unlock_kernel(); | 1075 | unlock_kernel(); |
1082 | return -EINVAL; | 1076 | return -EINVAL; |
1083 | } | 1077 | } |
1084 | dprintk(1,"open minor=%d\n",minor); | 1078 | dprintk(1, "open dev=%s\n", video_device_node_name(vdev)); |
1085 | 1079 | ||
1086 | /* allocate + initialize per filehandle data */ | 1080 | /* allocate + initialize per filehandle data */ |
1087 | fh = kzalloc(sizeof(*fh),GFP_KERNEL); | 1081 | fh = kzalloc(sizeof(*fh),GFP_KERNEL); |
@@ -1129,10 +1123,6 @@ static int mpeg_release(struct file *file) | |||
1129 | kfree(fh); | 1123 | kfree(fh); |
1130 | 1124 | ||
1131 | /* Make sure we release the hardware */ | 1125 | /* Make sure we release the hardware */ |
1132 | dev = cx8802_get_device(video_devdata(file)->minor); | ||
1133 | if (dev == NULL) | ||
1134 | return -ENODEV; | ||
1135 | |||
1136 | drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD); | 1126 | drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD); |
1137 | if (drv) | 1127 | if (drv) |
1138 | drv->request_release(drv); | 1128 | drv->request_release(drv); |
@@ -1220,7 +1210,6 @@ static struct video_device cx8802_mpeg_template = { | |||
1220 | .name = "cx8802", | 1210 | .name = "cx8802", |
1221 | .fops = &mpeg_fops, | 1211 | .fops = &mpeg_fops, |
1222 | .ioctl_ops = &mpeg_ioctl_ops, | 1212 | .ioctl_ops = &mpeg_ioctl_ops, |
1223 | .minor = -1, | ||
1224 | .tvnorms = CX88_NORMS, | 1213 | .tvnorms = CX88_NORMS, |
1225 | .current_norm = V4L2_STD_NTSC_M, | 1214 | .current_norm = V4L2_STD_NTSC_M, |
1226 | }; | 1215 | }; |
@@ -1276,7 +1265,7 @@ static int cx8802_blackbird_advise_release(struct cx8802_driver *drv) | |||
1276 | static void blackbird_unregister_video(struct cx8802_dev *dev) | 1265 | static void blackbird_unregister_video(struct cx8802_dev *dev) |
1277 | { | 1266 | { |
1278 | if (dev->mpeg_dev) { | 1267 | if (dev->mpeg_dev) { |
1279 | if (-1 != dev->mpeg_dev->minor) | 1268 | if (video_is_registered(dev->mpeg_dev)) |
1280 | video_unregister_device(dev->mpeg_dev); | 1269 | video_unregister_device(dev->mpeg_dev); |
1281 | else | 1270 | else |
1282 | video_device_release(dev->mpeg_dev); | 1271 | video_device_release(dev->mpeg_dev); |
@@ -1290,14 +1279,15 @@ static int blackbird_register_video(struct cx8802_dev *dev) | |||
1290 | 1279 | ||
1291 | dev->mpeg_dev = cx88_vdev_init(dev->core,dev->pci, | 1280 | dev->mpeg_dev = cx88_vdev_init(dev->core,dev->pci, |
1292 | &cx8802_mpeg_template,"mpeg"); | 1281 | &cx8802_mpeg_template,"mpeg"); |
1282 | video_set_drvdata(dev->mpeg_dev, dev); | ||
1293 | err = video_register_device(dev->mpeg_dev,VFL_TYPE_GRABBER, -1); | 1283 | err = video_register_device(dev->mpeg_dev,VFL_TYPE_GRABBER, -1); |
1294 | if (err < 0) { | 1284 | if (err < 0) { |
1295 | printk(KERN_INFO "%s/2: can't register mpeg device\n", | 1285 | printk(KERN_INFO "%s/2: can't register mpeg device\n", |
1296 | dev->core->name); | 1286 | dev->core->name); |
1297 | return err; | 1287 | return err; |
1298 | } | 1288 | } |
1299 | printk(KERN_INFO "%s/2: registered device video%d [mpeg]\n", | 1289 | printk(KERN_INFO "%s/2: registered device %s [mpeg]\n", |
1300 | dev->core->name, dev->mpeg_dev->num); | 1290 | dev->core->name, video_device_node_name(dev->mpeg_dev)); |
1301 | return 0; | 1291 | return 0; |
1302 | } | 1292 | } |
1303 | 1293 | ||
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index 92b8cdf9fb81..f9fda18b410c 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c | |||
@@ -360,7 +360,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | |||
360 | snprintf(ir->name, sizeof(ir->name), "cx88 IR (%s)", core->board.name); | 360 | snprintf(ir->name, sizeof(ir->name), "cx88 IR (%s)", core->board.name); |
361 | snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(pci)); | 361 | snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(pci)); |
362 | 362 | ||
363 | err = ir_input_init(input_dev, &ir->ir, ir_type, ir_codes); | 363 | err = ir_input_init(input_dev, &ir->ir, ir_type); |
364 | if (err < 0) | 364 | if (err < 0) |
365 | goto err_out_free; | 365 | goto err_out_free; |
366 | 366 | ||
@@ -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 = input_register_device(ir->input); | 386 | err = ir_input_register(ir->input, ir_codes); |
387 | if (err) | 387 | if (err) |
388 | goto err_out_stop; | 388 | goto err_out_stop; |
389 | 389 | ||
@@ -393,8 +393,6 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | |||
393 | cx88_ir_stop(core, ir); | 393 | cx88_ir_stop(core, ir); |
394 | core->ir = NULL; | 394 | core->ir = NULL; |
395 | err_out_free: | 395 | err_out_free: |
396 | ir_input_free(input_dev); | ||
397 | input_free_device(input_dev); | ||
398 | kfree(ir); | 396 | kfree(ir); |
399 | return err; | 397 | return err; |
400 | } | 398 | } |
@@ -408,8 +406,7 @@ int cx88_ir_fini(struct cx88_core *core) | |||
408 | return 0; | 406 | return 0; |
409 | 407 | ||
410 | cx88_ir_stop(core, ir); | 408 | cx88_ir_stop(core, ir); |
411 | ir_input_free(ir->input); | 409 | ir_input_unregister(ir->input); |
412 | input_unregister_device(ir->input); | ||
413 | kfree(ir); | 410 | kfree(ir); |
414 | 411 | ||
415 | /* done */ | 412 | /* done */ |
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index de9ff0fc741f..bb5104893411 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/video/cx88/cx88-mpeg.c | |||
@@ -580,21 +580,6 @@ static int cx8802_resume_common(struct pci_dev *pci_dev) | |||
580 | return 0; | 580 | return 0; |
581 | } | 581 | } |
582 | 582 | ||
583 | #if defined(CONFIG_VIDEO_CX88_BLACKBIRD) || \ | ||
584 | defined(CONFIG_VIDEO_CX88_BLACKBIRD_MODULE) | ||
585 | struct cx8802_dev *cx8802_get_device(int minor) | ||
586 | { | ||
587 | struct cx8802_dev *dev; | ||
588 | |||
589 | list_for_each_entry(dev, &cx8802_devlist, devlist) | ||
590 | if (dev->mpeg_dev && dev->mpeg_dev->minor == minor) | ||
591 | return dev; | ||
592 | |||
593 | return NULL; | ||
594 | } | ||
595 | EXPORT_SYMBOL(cx8802_get_device); | ||
596 | #endif | ||
597 | |||
598 | struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype) | 583 | struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype) |
599 | { | 584 | { |
600 | struct cx8802_driver *d; | 585 | struct cx8802_driver *d; |
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index d7e8fcee559c..48c450f4a85a 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c | |||
@@ -75,10 +75,6 @@ MODULE_PARM_DESC(vid_limit,"capture memory limit in megabytes"); | |||
75 | #define dprintk(level,fmt, arg...) if (video_debug >= level) \ | 75 | #define dprintk(level,fmt, arg...) if (video_debug >= level) \ |
76 | printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg) | 76 | printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg) |
77 | 77 | ||
78 | /* ------------------------------------------------------------------ */ | ||
79 | |||
80 | static LIST_HEAD(cx8800_devlist); | ||
81 | |||
82 | /* ------------------------------------------------------------------- */ | 78 | /* ------------------------------------------------------------------- */ |
83 | /* static data */ | 79 | /* static data */ |
84 | 80 | ||
@@ -753,38 +749,31 @@ static int get_ressource(struct cx8800_fh *fh) | |||
753 | 749 | ||
754 | static int video_open(struct file *file) | 750 | static int video_open(struct file *file) |
755 | { | 751 | { |
756 | int minor = video_devdata(file)->minor; | 752 | struct video_device *vdev = video_devdata(file); |
757 | struct cx8800_dev *h,*dev = NULL; | 753 | struct cx8800_dev *dev = video_drvdata(file); |
758 | struct cx88_core *core; | 754 | struct cx88_core *core; |
759 | struct cx8800_fh *fh; | 755 | struct cx8800_fh *fh; |
760 | enum v4l2_buf_type type = 0; | 756 | enum v4l2_buf_type type = 0; |
761 | int radio = 0; | 757 | int radio = 0; |
762 | 758 | ||
763 | lock_kernel(); | 759 | switch (vdev->vfl_type) { |
764 | list_for_each_entry(h, &cx8800_devlist, devlist) { | 760 | case VFL_TYPE_GRABBER: |
765 | if (h->video_dev->minor == minor) { | 761 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
766 | dev = h; | 762 | break; |
767 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 763 | case VFL_TYPE_VBI: |
768 | } | 764 | type = V4L2_BUF_TYPE_VBI_CAPTURE; |
769 | if (h->vbi_dev->minor == minor) { | 765 | break; |
770 | dev = h; | 766 | case VFL_TYPE_RADIO: |
771 | type = V4L2_BUF_TYPE_VBI_CAPTURE; | 767 | radio = 1; |
772 | } | 768 | break; |
773 | if (h->radio_dev && | ||
774 | h->radio_dev->minor == minor) { | ||
775 | radio = 1; | ||
776 | dev = h; | ||
777 | } | ||
778 | } | ||
779 | if (NULL == dev) { | ||
780 | unlock_kernel(); | ||
781 | return -ENODEV; | ||
782 | } | 769 | } |
783 | 770 | ||
771 | lock_kernel(); | ||
772 | |||
784 | core = dev->core; | 773 | core = dev->core; |
785 | 774 | ||
786 | dprintk(1,"open minor=%d radio=%d type=%s\n", | 775 | dprintk(1, "open dev=%s radio=%d type=%s\n", |
787 | minor,radio,v4l2_type_names[type]); | 776 | video_device_node_name(vdev), radio, v4l2_type_names[type]); |
788 | 777 | ||
789 | /* allocate + initialize per filehandle data */ | 778 | /* allocate + initialize per filehandle data */ |
790 | fh = kzalloc(sizeof(*fh),GFP_KERNEL); | 779 | fh = kzalloc(sizeof(*fh),GFP_KERNEL); |
@@ -1733,7 +1722,6 @@ static struct video_device cx8800_vbi_template; | |||
1733 | static struct video_device cx8800_video_template = { | 1722 | static struct video_device cx8800_video_template = { |
1734 | .name = "cx8800-video", | 1723 | .name = "cx8800-video", |
1735 | .fops = &video_fops, | 1724 | .fops = &video_fops, |
1736 | .minor = -1, | ||
1737 | .ioctl_ops = &video_ioctl_ops, | 1725 | .ioctl_ops = &video_ioctl_ops, |
1738 | .tvnorms = CX88_NORMS, | 1726 | .tvnorms = CX88_NORMS, |
1739 | .current_norm = V4L2_STD_NTSC_M, | 1727 | .current_norm = V4L2_STD_NTSC_M, |
@@ -1769,7 +1757,6 @@ static const struct v4l2_ioctl_ops radio_ioctl_ops = { | |||
1769 | static struct video_device cx8800_radio_template = { | 1757 | static struct video_device cx8800_radio_template = { |
1770 | .name = "cx8800-radio", | 1758 | .name = "cx8800-radio", |
1771 | .fops = &radio_fops, | 1759 | .fops = &radio_fops, |
1772 | .minor = -1, | ||
1773 | .ioctl_ops = &radio_ioctl_ops, | 1760 | .ioctl_ops = &radio_ioctl_ops, |
1774 | }; | 1761 | }; |
1775 | 1762 | ||
@@ -1778,21 +1765,21 @@ static struct video_device cx8800_radio_template = { | |||
1778 | static void cx8800_unregister_video(struct cx8800_dev *dev) | 1765 | static void cx8800_unregister_video(struct cx8800_dev *dev) |
1779 | { | 1766 | { |
1780 | if (dev->radio_dev) { | 1767 | if (dev->radio_dev) { |
1781 | if (-1 != dev->radio_dev->minor) | 1768 | if (video_is_registered(dev->radio_dev)) |
1782 | video_unregister_device(dev->radio_dev); | 1769 | video_unregister_device(dev->radio_dev); |
1783 | else | 1770 | else |
1784 | video_device_release(dev->radio_dev); | 1771 | video_device_release(dev->radio_dev); |
1785 | dev->radio_dev = NULL; | 1772 | dev->radio_dev = NULL; |
1786 | } | 1773 | } |
1787 | if (dev->vbi_dev) { | 1774 | if (dev->vbi_dev) { |
1788 | if (-1 != dev->vbi_dev->minor) | 1775 | if (video_is_registered(dev->vbi_dev)) |
1789 | video_unregister_device(dev->vbi_dev); | 1776 | video_unregister_device(dev->vbi_dev); |
1790 | else | 1777 | else |
1791 | video_device_release(dev->vbi_dev); | 1778 | video_device_release(dev->vbi_dev); |
1792 | dev->vbi_dev = NULL; | 1779 | dev->vbi_dev = NULL; |
1793 | } | 1780 | } |
1794 | if (dev->video_dev) { | 1781 | if (dev->video_dev) { |
1795 | if (-1 != dev->video_dev->minor) | 1782 | if (video_is_registered(dev->video_dev)) |
1796 | video_unregister_device(dev->video_dev); | 1783 | video_unregister_device(dev->video_dev); |
1797 | else | 1784 | else |
1798 | video_device_release(dev->video_dev); | 1785 | video_device_release(dev->video_dev); |
@@ -1909,6 +1896,7 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, | |||
1909 | /* register v4l devices */ | 1896 | /* register v4l devices */ |
1910 | dev->video_dev = cx88_vdev_init(core,dev->pci, | 1897 | dev->video_dev = cx88_vdev_init(core,dev->pci, |
1911 | &cx8800_video_template,"video"); | 1898 | &cx8800_video_template,"video"); |
1899 | video_set_drvdata(dev->video_dev, dev); | ||
1912 | err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER, | 1900 | err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER, |
1913 | video_nr[core->nr]); | 1901 | video_nr[core->nr]); |
1914 | if (err < 0) { | 1902 | if (err < 0) { |
@@ -1916,10 +1904,11 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, | |||
1916 | core->name); | 1904 | core->name); |
1917 | goto fail_unreg; | 1905 | goto fail_unreg; |
1918 | } | 1906 | } |
1919 | printk(KERN_INFO "%s/0: registered device video%d [v4l2]\n", | 1907 | printk(KERN_INFO "%s/0: registered device %s [v4l2]\n", |
1920 | core->name, dev->video_dev->num); | 1908 | core->name, video_device_node_name(dev->video_dev)); |
1921 | 1909 | ||
1922 | dev->vbi_dev = cx88_vdev_init(core,dev->pci,&cx8800_vbi_template,"vbi"); | 1910 | dev->vbi_dev = cx88_vdev_init(core,dev->pci,&cx8800_vbi_template,"vbi"); |
1911 | video_set_drvdata(dev->vbi_dev, dev); | ||
1923 | err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI, | 1912 | err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI, |
1924 | vbi_nr[core->nr]); | 1913 | vbi_nr[core->nr]); |
1925 | if (err < 0) { | 1914 | if (err < 0) { |
@@ -1927,12 +1916,13 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, | |||
1927 | core->name); | 1916 | core->name); |
1928 | goto fail_unreg; | 1917 | goto fail_unreg; |
1929 | } | 1918 | } |
1930 | printk(KERN_INFO "%s/0: registered device vbi%d\n", | 1919 | printk(KERN_INFO "%s/0: registered device %s\n", |
1931 | core->name, dev->vbi_dev->num); | 1920 | core->name, video_device_node_name(dev->vbi_dev)); |
1932 | 1921 | ||
1933 | if (core->board.radio.type == CX88_RADIO) { | 1922 | if (core->board.radio.type == CX88_RADIO) { |
1934 | dev->radio_dev = cx88_vdev_init(core,dev->pci, | 1923 | dev->radio_dev = cx88_vdev_init(core,dev->pci, |
1935 | &cx8800_radio_template,"radio"); | 1924 | &cx8800_radio_template,"radio"); |
1925 | video_set_drvdata(dev->radio_dev, dev); | ||
1936 | err = video_register_device(dev->radio_dev,VFL_TYPE_RADIO, | 1926 | err = video_register_device(dev->radio_dev,VFL_TYPE_RADIO, |
1937 | radio_nr[core->nr]); | 1927 | radio_nr[core->nr]); |
1938 | if (err < 0) { | 1928 | if (err < 0) { |
@@ -1940,12 +1930,11 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, | |||
1940 | core->name); | 1930 | core->name); |
1941 | goto fail_unreg; | 1931 | goto fail_unreg; |
1942 | } | 1932 | } |
1943 | printk(KERN_INFO "%s/0: registered device radio%d\n", | 1933 | printk(KERN_INFO "%s/0: registered device %s\n", |
1944 | core->name, dev->radio_dev->num); | 1934 | core->name, video_device_node_name(dev->radio_dev)); |
1945 | } | 1935 | } |
1946 | 1936 | ||
1947 | /* everything worked */ | 1937 | /* everything worked */ |
1948 | list_add_tail(&dev->devlist,&cx8800_devlist); | ||
1949 | pci_set_drvdata(pci_dev,dev); | 1938 | pci_set_drvdata(pci_dev,dev); |
1950 | 1939 | ||
1951 | /* initial device configuration */ | 1940 | /* initial device configuration */ |
@@ -2001,7 +1990,6 @@ static void __devexit cx8800_finidev(struct pci_dev *pci_dev) | |||
2001 | 1990 | ||
2002 | /* free memory */ | 1991 | /* free memory */ |
2003 | btcx_riscmem_free(dev->pci,&dev->vidq.stopper); | 1992 | btcx_riscmem_free(dev->pci,&dev->vidq.stopper); |
2004 | list_del(&dev->devlist); | ||
2005 | cx88_core_put(core,dev->pci); | 1993 | cx88_core_put(core,dev->pci); |
2006 | kfree(dev); | 1994 | kfree(dev); |
2007 | } | 1995 | } |
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index e1c521710103..b1499bf604ea 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h | |||
@@ -423,7 +423,6 @@ struct cx8800_suspend_state { | |||
423 | 423 | ||
424 | struct cx8800_dev { | 424 | struct cx8800_dev { |
425 | struct cx88_core *core; | 425 | struct cx88_core *core; |
426 | struct list_head devlist; | ||
427 | spinlock_t slock; | 426 | spinlock_t slock; |
428 | 427 | ||
429 | /* various device info */ | 428 | /* various device info */ |
@@ -670,7 +669,6 @@ int cx88_audio_thread(void *data); | |||
670 | 669 | ||
671 | int cx8802_register_driver(struct cx8802_driver *drv); | 670 | int cx8802_register_driver(struct cx8802_driver *drv); |
672 | int cx8802_unregister_driver(struct cx8802_driver *drv); | 671 | int cx8802_unregister_driver(struct cx8802_driver *drv); |
673 | struct cx8802_dev *cx8802_get_device(int minor); | ||
674 | struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype); | 672 | struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype); |
675 | 673 | ||
676 | /* ----------------------------------------------------------- */ | 674 | /* ----------------------------------------------------------- */ |
diff --git a/drivers/media/video/davinci/vpfe_capture.c b/drivers/media/video/davinci/vpfe_capture.c index 12a1b3d7132d..de22bc9faf21 100644 --- a/drivers/media/video/davinci/vpfe_capture.c +++ b/drivers/media/video/davinci/vpfe_capture.c | |||
@@ -70,7 +70,6 @@ | |||
70 | #include <linux/init.h> | 70 | #include <linux/init.h> |
71 | #include <linux/platform_device.h> | 71 | #include <linux/platform_device.h> |
72 | #include <linux/interrupt.h> | 72 | #include <linux/interrupt.h> |
73 | #include <linux/version.h> | ||
74 | #include <media/v4l2-common.h> | 73 | #include <media/v4l2-common.h> |
75 | #include <linux/io.h> | 74 | #include <linux/io.h> |
76 | #include <media/davinci/vpfe_capture.h> | 75 | #include <media/davinci/vpfe_capture.h> |
@@ -1967,7 +1966,6 @@ static __init int vpfe_probe(struct platform_device *pdev) | |||
1967 | vfd->release = video_device_release; | 1966 | vfd->release = video_device_release; |
1968 | vfd->fops = &vpfe_fops; | 1967 | vfd->fops = &vpfe_fops; |
1969 | vfd->ioctl_ops = &vpfe_ioctl_ops; | 1968 | vfd->ioctl_ops = &vpfe_ioctl_ops; |
1970 | vfd->minor = -1; | ||
1971 | vfd->tvnorms = 0; | 1969 | vfd->tvnorms = 0; |
1972 | vfd->current_norm = V4L2_STD_PAL; | 1970 | vfd->current_norm = V4L2_STD_PAL; |
1973 | vfd->v4l2_dev = &vpfe_dev->v4l2_dev; | 1971 | vfd->v4l2_dev = &vpfe_dev->v4l2_dev; |
@@ -2071,7 +2069,7 @@ probe_out_video_unregister: | |||
2071 | probe_out_v4l2_unregister: | 2069 | probe_out_v4l2_unregister: |
2072 | v4l2_device_unregister(&vpfe_dev->v4l2_dev); | 2070 | v4l2_device_unregister(&vpfe_dev->v4l2_dev); |
2073 | probe_out_video_release: | 2071 | probe_out_video_release: |
2074 | if (vpfe_dev->video_dev->minor == -1) | 2072 | if (!video_is_registered(vpfe_dev->video_dev)) |
2075 | video_device_release(vpfe_dev->video_dev); | 2073 | video_device_release(vpfe_dev->video_dev); |
2076 | probe_out_release_irq: | 2074 | probe_out_release_irq: |
2077 | free_irq(vpfe_dev->ccdc_irq0, vpfe_dev); | 2075 | free_irq(vpfe_dev->ccdc_irq0, vpfe_dev); |
@@ -2091,7 +2089,7 @@ probe_free_dev_mem: | |||
2091 | /* | 2089 | /* |
2092 | * vpfe_remove : It un-register device from V4L2 driver | 2090 | * vpfe_remove : It un-register device from V4L2 driver |
2093 | */ | 2091 | */ |
2094 | static int vpfe_remove(struct platform_device *pdev) | 2092 | static int __devexit vpfe_remove(struct platform_device *pdev) |
2095 | { | 2093 | { |
2096 | struct vpfe_device *vpfe_dev = platform_get_drvdata(pdev); | 2094 | struct vpfe_device *vpfe_dev = platform_get_drvdata(pdev); |
2097 | struct resource *res; | 2095 | struct resource *res; |
@@ -2127,7 +2125,7 @@ vpfe_resume(struct device *dev) | |||
2127 | return -1; | 2125 | return -1; |
2128 | } | 2126 | } |
2129 | 2127 | ||
2130 | static struct dev_pm_ops vpfe_dev_pm_ops = { | 2128 | static const struct dev_pm_ops vpfe_dev_pm_ops = { |
2131 | .suspend = vpfe_suspend, | 2129 | .suspend = vpfe_suspend, |
2132 | .resume = vpfe_resume, | 2130 | .resume = vpfe_resume, |
2133 | }; | 2131 | }; |
diff --git a/drivers/media/video/davinci/vpif.c b/drivers/media/video/davinci/vpif.c index 3b8eac31ecae..1f532e31cd49 100644 --- a/drivers/media/video/davinci/vpif.c +++ b/drivers/media/video/davinci/vpif.c | |||
@@ -266,7 +266,7 @@ fail: | |||
266 | return status; | 266 | return status; |
267 | } | 267 | } |
268 | 268 | ||
269 | static int vpif_remove(struct platform_device *pdev) | 269 | static int __devexit vpif_remove(struct platform_device *pdev) |
270 | { | 270 | { |
271 | iounmap(vpif_base); | 271 | iounmap(vpif_base); |
272 | release_mem_region(res->start, res_len); | 272 | release_mem_region(res->start, res_len); |
diff --git a/drivers/media/video/davinci/vpif_capture.c b/drivers/media/video/davinci/vpif_capture.c index d947ee5e4eb4..78130721f578 100644 --- a/drivers/media/video/davinci/vpif_capture.c +++ b/drivers/media/video/davinci/vpif_capture.c | |||
@@ -2107,7 +2107,7 @@ vpif_resume(struct device *dev) | |||
2107 | return -1; | 2107 | return -1; |
2108 | } | 2108 | } |
2109 | 2109 | ||
2110 | static struct dev_pm_ops vpif_dev_pm_ops = { | 2110 | static const struct dev_pm_ops vpif_dev_pm_ops = { |
2111 | .suspend = vpif_suspend, | 2111 | .suspend = vpif_suspend, |
2112 | .resume = vpif_resume, | 2112 | .resume = vpif_resume, |
2113 | }; | 2113 | }; |
diff --git a/drivers/media/video/davinci/vpif_display.c b/drivers/media/video/davinci/vpif_display.c index d14cfb200ed0..dfddef7228dd 100644 --- a/drivers/media/video/davinci/vpif_display.c +++ b/drivers/media/video/davinci/vpif_display.c | |||
@@ -1347,7 +1347,6 @@ static const struct v4l2_file_operations vpif_fops = { | |||
1347 | static struct video_device vpif_video_template = { | 1347 | static struct video_device vpif_video_template = { |
1348 | .name = "vpif", | 1348 | .name = "vpif", |
1349 | .fops = &vpif_fops, | 1349 | .fops = &vpif_fops, |
1350 | .minor = -1, | ||
1351 | .ioctl_ops = &vpif_ioctl_ops, | 1350 | .ioctl_ops = &vpif_ioctl_ops, |
1352 | .tvnorms = DM646X_V4L2_STD, | 1351 | .tvnorms = DM646X_V4L2_STD, |
1353 | .current_norm = V4L2_STD_625_50, | 1352 | .current_norm = V4L2_STD_625_50, |
diff --git a/drivers/media/video/davinci/vpss.c b/drivers/media/video/davinci/vpss.c index 453236bd7559..7ee72ecd3d81 100644 --- a/drivers/media/video/davinci/vpss.c +++ b/drivers/media/video/davinci/vpss.c | |||
@@ -268,7 +268,7 @@ fail1: | |||
268 | return status; | 268 | return status; |
269 | } | 269 | } |
270 | 270 | ||
271 | static int vpss_remove(struct platform_device *pdev) | 271 | static int __devexit vpss_remove(struct platform_device *pdev) |
272 | { | 272 | { |
273 | iounmap(oper_cfg.vpss_bl_regs_base); | 273 | iounmap(oper_cfg.vpss_bl_regs_base); |
274 | release_mem_region(oper_cfg.r1->start, oper_cfg.len1); | 274 | release_mem_region(oper_cfg.r1->start, oper_cfg.len1); |
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 82da205047be..25100001ffff 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c | |||
@@ -2285,7 +2285,7 @@ void em28xx_register_i2c_ir(struct em28xx *dev) | |||
2285 | dev->init_data.name = "i2c IR (EM28XX Pinnacle PCTV)"; | 2285 | dev->init_data.name = "i2c IR (EM28XX Pinnacle PCTV)"; |
2286 | break; | 2286 | break; |
2287 | case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2: | 2287 | case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2: |
2288 | dev->init_data.ir_codes = &ir_codes_hauppauge_new_table; | 2288 | dev->init_data.ir_codes = &ir_codes_rc5_hauppauge_new_table; |
2289 | dev->init_data.get_key = em28xx_get_key_em_haup; | 2289 | dev->init_data.get_key = em28xx_get_key_em_haup; |
2290 | dev->init_data.name = "i2c IR (EM2840 Hauppauge)"; | 2290 | dev->init_data.name = "i2c IR (EM2840 Hauppauge)"; |
2291 | break; | 2291 | break; |
@@ -2653,7 +2653,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | |||
2653 | INIT_LIST_HEAD(&dev->vbiq.active); | 2653 | INIT_LIST_HEAD(&dev->vbiq.active); |
2654 | INIT_LIST_HEAD(&dev->vbiq.queued); | 2654 | INIT_LIST_HEAD(&dev->vbiq.queued); |
2655 | 2655 | ||
2656 | |||
2657 | if (dev->board.has_msp34xx) { | 2656 | if (dev->board.has_msp34xx) { |
2658 | /* Send a reset to other chips via gpio */ | 2657 | /* Send a reset to other chips via gpio */ |
2659 | errCode = em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xf7); | 2658 | errCode = em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xf7); |
@@ -2923,9 +2922,9 @@ static void em28xx_usb_disconnect(struct usb_interface *interface) | |||
2923 | 2922 | ||
2924 | if (dev->users) { | 2923 | if (dev->users) { |
2925 | em28xx_warn | 2924 | em28xx_warn |
2926 | ("device /dev/video%d is open! Deregistration and memory " | 2925 | ("device %s is open! Deregistration and memory " |
2927 | "deallocation are deferred on close.\n", | 2926 | "deallocation are deferred on close.\n", |
2928 | dev->vdev->num); | 2927 | video_device_node_name(dev->vdev)); |
2929 | 2928 | ||
2930 | dev->state |= DEV_MISCONFIGURED; | 2929 | dev->state |= DEV_MISCONFIGURED; |
2931 | em28xx_uninit_isoc(dev); | 2930 | em28xx_uninit_isoc(dev); |
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 3f86d36dff2b..b311d4514bdf 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c | |||
@@ -216,7 +216,7 @@ int em28xx_write_reg(struct em28xx *dev, u16 reg, u8 val) | |||
216 | * sets only some bits (specified by bitmask) of a register, by first reading | 216 | * sets only some bits (specified by bitmask) of a register, by first reading |
217 | * the actual value | 217 | * the actual value |
218 | */ | 218 | */ |
219 | static int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val, | 219 | int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val, |
220 | u8 bitmask) | 220 | u8 bitmask) |
221 | { | 221 | { |
222 | int oldval; | 222 | int oldval; |
@@ -1136,34 +1136,6 @@ void em28xx_wake_i2c(struct em28xx *dev) | |||
1136 | static LIST_HEAD(em28xx_devlist); | 1136 | static LIST_HEAD(em28xx_devlist); |
1137 | static DEFINE_MUTEX(em28xx_devlist_mutex); | 1137 | static DEFINE_MUTEX(em28xx_devlist_mutex); |
1138 | 1138 | ||
1139 | struct em28xx *em28xx_get_device(int minor, | ||
1140 | enum v4l2_buf_type *fh_type, | ||
1141 | int *has_radio) | ||
1142 | { | ||
1143 | struct em28xx *h, *dev = NULL; | ||
1144 | |||
1145 | *fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
1146 | *has_radio = 0; | ||
1147 | |||
1148 | mutex_lock(&em28xx_devlist_mutex); | ||
1149 | list_for_each_entry(h, &em28xx_devlist, devlist) { | ||
1150 | if (h->vdev->minor == minor) | ||
1151 | dev = h; | ||
1152 | if (h->vbi_dev && h->vbi_dev->minor == minor) { | ||
1153 | dev = h; | ||
1154 | *fh_type = V4L2_BUF_TYPE_VBI_CAPTURE; | ||
1155 | } | ||
1156 | if (h->radio_dev && | ||
1157 | h->radio_dev->minor == minor) { | ||
1158 | dev = h; | ||
1159 | *has_radio = 1; | ||
1160 | } | ||
1161 | } | ||
1162 | mutex_unlock(&em28xx_devlist_mutex); | ||
1163 | |||
1164 | return dev; | ||
1165 | } | ||
1166 | |||
1167 | /* | 1139 | /* |
1168 | * em28xx_realease_resources() | 1140 | * em28xx_realease_resources() |
1169 | * unregisters the v4l2,i2c and usb devices | 1141 | * unregisters the v4l2,i2c and usb devices |
diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index d96ec7c09dca..af0d935c29be 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c | |||
@@ -112,10 +112,13 @@ int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | |||
112 | int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | 112 | int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) |
113 | { | 113 | { |
114 | unsigned char buf[2]; | 114 | unsigned char buf[2]; |
115 | unsigned char code; | 115 | u16 code; |
116 | int size; | ||
116 | 117 | ||
117 | /* poll IR chip */ | 118 | /* poll IR chip */ |
118 | if (2 != i2c_master_recv(ir->c, buf, 2)) | 119 | size = i2c_master_recv(ir->c, buf, sizeof(buf)); |
120 | |||
121 | if (size != 2) | ||
119 | return -EIO; | 122 | return -EIO; |
120 | 123 | ||
121 | /* Does eliminate repeated parity code */ | 124 | /* Does eliminate repeated parity code */ |
@@ -124,16 +127,30 @@ int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | |||
124 | 127 | ||
125 | ir->old = buf[1]; | 128 | ir->old = buf[1]; |
126 | 129 | ||
127 | /* Rearranges bits to the right order */ | 130 | /* |
128 | code = ((buf[0]&0x01)<<5) | /* 0010 0000 */ | 131 | * Rearranges bits to the right order. |
129 | ((buf[0]&0x02)<<3) | /* 0001 0000 */ | 132 | * The bit order were determined experimentally by using |
130 | ((buf[0]&0x04)<<1) | /* 0000 1000 */ | 133 | * The original Hauppauge Grey IR and another RC5 that uses addr=0x08 |
131 | ((buf[0]&0x08)>>1) | /* 0000 0100 */ | 134 | * The RC5 code has 14 bits, but we've experimentally determined |
132 | ((buf[0]&0x10)>>3) | /* 0000 0010 */ | 135 | * the meaning for only 11 bits. |
133 | ((buf[0]&0x20)>>5); /* 0000 0001 */ | 136 | * So, the code translation is not complete. Yet, it is enough to |
134 | 137 | * work with the provided RC5 IR. | |
135 | i2cdprintk("ir hauppauge (em2840): code=0x%02x (rcv=0x%02x)\n", | 138 | */ |
136 | code, buf[0]); | 139 | code = |
140 | ((buf[0] & 0x01) ? 0x0020 : 0) | /* 0010 0000 */ | ||
141 | ((buf[0] & 0x02) ? 0x0010 : 0) | /* 0001 0000 */ | ||
142 | ((buf[0] & 0x04) ? 0x0008 : 0) | /* 0000 1000 */ | ||
143 | ((buf[0] & 0x08) ? 0x0004 : 0) | /* 0000 0100 */ | ||
144 | ((buf[0] & 0x10) ? 0x0002 : 0) | /* 0000 0010 */ | ||
145 | ((buf[0] & 0x20) ? 0x0001 : 0) | /* 0000 0001 */ | ||
146 | ((buf[1] & 0x08) ? 0x1000 : 0) | /* 0001 0000 */ | ||
147 | ((buf[1] & 0x10) ? 0x0800 : 0) | /* 0000 1000 */ | ||
148 | ((buf[1] & 0x20) ? 0x0400 : 0) | /* 0000 0100 */ | ||
149 | ((buf[1] & 0x40) ? 0x0200 : 0) | /* 0000 0010 */ | ||
150 | ((buf[1] & 0x80) ? 0x0100 : 0); /* 0000 0001 */ | ||
151 | |||
152 | i2cdprintk("ir hauppauge (em2840): code=0x%02x (rcv=0x%02x%02x)\n", | ||
153 | code, buf[1], buf[0]); | ||
137 | 154 | ||
138 | /* return key */ | 155 | /* return key */ |
139 | *ir_key = code; | 156 | *ir_key = code; |
@@ -337,19 +354,28 @@ int em28xx_ir_init(struct em28xx *dev) | |||
337 | goto err_out_free; | 354 | goto err_out_free; |
338 | 355 | ||
339 | ir->input = input_dev; | 356 | ir->input = input_dev; |
357 | ir_config = EM2874_IR_RC5; | ||
358 | |||
359 | /* Adjust xclk based o IR table for RC5/NEC tables */ | ||
360 | if (dev->board.ir_codes->ir_type == IR_TYPE_RC5) { | ||
361 | dev->board.xclk |= EM28XX_XCLK_IR_RC5_MODE; | ||
362 | ir->full_code = 1; | ||
363 | } else if (dev->board.ir_codes->ir_type == IR_TYPE_NEC) { | ||
364 | dev->board.xclk &= ~EM28XX_XCLK_IR_RC5_MODE; | ||
365 | ir_config = EM2874_IR_NEC; | ||
366 | ir->full_code = 1; | ||
367 | } | ||
368 | em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, dev->board.xclk, | ||
369 | EM28XX_XCLK_IR_RC5_MODE); | ||
340 | 370 | ||
341 | /* Setup the proper handler based on the chip */ | 371 | /* Setup the proper handler based on the chip */ |
342 | switch (dev->chip_id) { | 372 | switch (dev->chip_id) { |
343 | case CHIP_ID_EM2860: | 373 | case CHIP_ID_EM2860: |
344 | case CHIP_ID_EM2883: | 374 | case CHIP_ID_EM2883: |
345 | if (dev->model == EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950) | ||
346 | ir->full_code = 1; | ||
347 | ir->get_key = default_polling_getkey; | 375 | ir->get_key = default_polling_getkey; |
348 | break; | 376 | break; |
349 | case CHIP_ID_EM2874: | 377 | case CHIP_ID_EM2874: |
350 | ir->get_key = em2874_polling_getkey; | 378 | ir->get_key = em2874_polling_getkey; |
351 | /* For now we only support RC5, so enable it */ | ||
352 | ir_config = EM2874_IR_RC5; | ||
353 | em28xx_write_regs(dev, EM2874_R50_IR_CONFIG, &ir_config, 1); | 379 | em28xx_write_regs(dev, EM2874_R50_IR_CONFIG, &ir_config, 1); |
354 | break; | 380 | break; |
355 | default: | 381 | default: |
@@ -367,8 +393,7 @@ int em28xx_ir_init(struct em28xx *dev) | |||
367 | usb_make_path(dev->udev, ir->phys, sizeof(ir->phys)); | 393 | usb_make_path(dev->udev, ir->phys, sizeof(ir->phys)); |
368 | strlcat(ir->phys, "/input0", sizeof(ir->phys)); | 394 | strlcat(ir->phys, "/input0", sizeof(ir->phys)); |
369 | 395 | ||
370 | err = ir_input_init(input_dev, &ir->ir, IR_TYPE_OTHER, | 396 | err = ir_input_init(input_dev, &ir->ir, IR_TYPE_OTHER); |
371 | dev->board.ir_codes); | ||
372 | if (err < 0) | 397 | if (err < 0) |
373 | goto err_out_free; | 398 | goto err_out_free; |
374 | 399 | ||
@@ -387,7 +412,7 @@ int em28xx_ir_init(struct em28xx *dev) | |||
387 | em28xx_ir_start(ir); | 412 | em28xx_ir_start(ir); |
388 | 413 | ||
389 | /* all done */ | 414 | /* all done */ |
390 | err = input_register_device(ir->input); | 415 | err = ir_input_register(ir->input, dev->board.ir_codes); |
391 | if (err) | 416 | if (err) |
392 | goto err_out_stop; | 417 | goto err_out_stop; |
393 | 418 | ||
@@ -396,8 +421,6 @@ int em28xx_ir_init(struct em28xx *dev) | |||
396 | em28xx_ir_stop(ir); | 421 | em28xx_ir_stop(ir); |
397 | dev->ir = NULL; | 422 | dev->ir = NULL; |
398 | err_out_free: | 423 | err_out_free: |
399 | ir_input_free(input_dev); | ||
400 | input_free_device(input_dev); | ||
401 | kfree(ir); | 424 | kfree(ir); |
402 | return err; | 425 | return err; |
403 | } | 426 | } |
@@ -411,8 +434,7 @@ int em28xx_ir_fini(struct em28xx *dev) | |||
411 | return 0; | 434 | return 0; |
412 | 435 | ||
413 | em28xx_ir_stop(ir); | 436 | em28xx_ir_stop(ir); |
414 | ir_input_free(ir->input); | 437 | ir_input_unregister(ir->input); |
415 | input_unregister_device(ir->input); | ||
416 | kfree(ir); | 438 | kfree(ir); |
417 | 439 | ||
418 | /* done */ | 440 | /* done */ |
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 7ad65370f274..849b18c94037 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c | |||
@@ -2081,22 +2081,30 @@ static int radio_queryctrl(struct file *file, void *priv, | |||
2081 | */ | 2081 | */ |
2082 | static int em28xx_v4l2_open(struct file *filp) | 2082 | static int em28xx_v4l2_open(struct file *filp) |
2083 | { | 2083 | { |
2084 | int minor = video_devdata(filp)->minor; | 2084 | int errCode = 0, radio = 0; |
2085 | int errCode = 0, radio; | 2085 | struct video_device *vdev = video_devdata(filp); |
2086 | struct em28xx *dev; | 2086 | struct em28xx *dev = video_drvdata(filp); |
2087 | enum v4l2_buf_type fh_type; | 2087 | enum v4l2_buf_type fh_type = 0; |
2088 | struct em28xx_fh *fh; | 2088 | struct em28xx_fh *fh; |
2089 | enum v4l2_field field; | 2089 | enum v4l2_field field; |
2090 | 2090 | ||
2091 | dev = em28xx_get_device(minor, &fh_type, &radio); | 2091 | switch (vdev->vfl_type) { |
2092 | 2092 | case VFL_TYPE_GRABBER: | |
2093 | if (NULL == dev) | 2093 | fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
2094 | return -ENODEV; | 2094 | break; |
2095 | case VFL_TYPE_VBI: | ||
2096 | fh_type = V4L2_BUF_TYPE_VBI_CAPTURE; | ||
2097 | break; | ||
2098 | case VFL_TYPE_RADIO: | ||
2099 | radio = 1; | ||
2100 | break; | ||
2101 | } | ||
2095 | 2102 | ||
2096 | mutex_lock(&dev->lock); | 2103 | mutex_lock(&dev->lock); |
2097 | 2104 | ||
2098 | em28xx_videodbg("open minor=%d type=%s users=%d\n", | 2105 | em28xx_videodbg("open dev=%s type=%s users=%d\n", |
2099 | minor, v4l2_type_names[fh_type], dev->users); | 2106 | video_device_node_name(vdev), v4l2_type_names[fh_type], |
2107 | dev->users); | ||
2100 | 2108 | ||
2101 | 2109 | ||
2102 | fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL); | 2110 | fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL); |
@@ -2160,25 +2168,25 @@ void em28xx_release_analog_resources(struct em28xx *dev) | |||
2160 | /*FIXME: I2C IR should be disconnected */ | 2168 | /*FIXME: I2C IR should be disconnected */ |
2161 | 2169 | ||
2162 | if (dev->radio_dev) { | 2170 | if (dev->radio_dev) { |
2163 | if (-1 != dev->radio_dev->minor) | 2171 | if (video_is_registered(dev->radio_dev)) |
2164 | video_unregister_device(dev->radio_dev); | 2172 | video_unregister_device(dev->radio_dev); |
2165 | else | 2173 | else |
2166 | video_device_release(dev->radio_dev); | 2174 | video_device_release(dev->radio_dev); |
2167 | dev->radio_dev = NULL; | 2175 | dev->radio_dev = NULL; |
2168 | } | 2176 | } |
2169 | if (dev->vbi_dev) { | 2177 | if (dev->vbi_dev) { |
2170 | em28xx_info("V4L2 device /dev/vbi%d deregistered\n", | 2178 | em28xx_info("V4L2 device %s deregistered\n", |
2171 | dev->vbi_dev->num); | 2179 | video_device_node_name(dev->vbi_dev)); |
2172 | if (-1 != dev->vbi_dev->minor) | 2180 | if (video_is_registered(dev->vbi_dev)) |
2173 | video_unregister_device(dev->vbi_dev); | 2181 | video_unregister_device(dev->vbi_dev); |
2174 | else | 2182 | else |
2175 | video_device_release(dev->vbi_dev); | 2183 | video_device_release(dev->vbi_dev); |
2176 | dev->vbi_dev = NULL; | 2184 | dev->vbi_dev = NULL; |
2177 | } | 2185 | } |
2178 | if (dev->vdev) { | 2186 | if (dev->vdev) { |
2179 | em28xx_info("V4L2 device /dev/video%d deregistered\n", | 2187 | em28xx_info("V4L2 device %s deregistered\n", |
2180 | dev->vdev->num); | 2188 | video_device_node_name(dev->vdev)); |
2181 | if (-1 != dev->vdev->minor) | 2189 | if (video_is_registered(dev->vdev)) |
2182 | video_unregister_device(dev->vdev); | 2190 | video_unregister_device(dev->vdev); |
2183 | else | 2191 | else |
2184 | video_device_release(dev->vdev); | 2192 | video_device_release(dev->vdev); |
@@ -2397,8 +2405,6 @@ static const struct video_device em28xx_video_template = { | |||
2397 | .release = video_device_release, | 2405 | .release = video_device_release, |
2398 | .ioctl_ops = &video_ioctl_ops, | 2406 | .ioctl_ops = &video_ioctl_ops, |
2399 | 2407 | ||
2400 | .minor = -1, | ||
2401 | |||
2402 | .tvnorms = V4L2_STD_ALL, | 2408 | .tvnorms = V4L2_STD_ALL, |
2403 | .current_norm = V4L2_STD_PAL, | 2409 | .current_norm = V4L2_STD_PAL, |
2404 | }; | 2410 | }; |
@@ -2433,7 +2439,6 @@ static struct video_device em28xx_radio_template = { | |||
2433 | .name = "em28xx-radio", | 2439 | .name = "em28xx-radio", |
2434 | .fops = &radio_fops, | 2440 | .fops = &radio_fops, |
2435 | .ioctl_ops = &radio_ioctl_ops, | 2441 | .ioctl_ops = &radio_ioctl_ops, |
2436 | .minor = -1, | ||
2437 | }; | 2442 | }; |
2438 | 2443 | ||
2439 | /******************************** usb interface ******************************/ | 2444 | /******************************** usb interface ******************************/ |
@@ -2451,7 +2456,6 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev, | |||
2451 | return NULL; | 2456 | return NULL; |
2452 | 2457 | ||
2453 | *vfd = *template; | 2458 | *vfd = *template; |
2454 | vfd->minor = -1; | ||
2455 | vfd->v4l2_dev = &dev->v4l2_dev; | 2459 | vfd->v4l2_dev = &dev->v4l2_dev; |
2456 | vfd->release = video_device_release; | 2460 | vfd->release = video_device_release; |
2457 | vfd->debug = video_debug; | 2461 | vfd->debug = video_debug; |
@@ -2459,6 +2463,7 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev, | |||
2459 | snprintf(vfd->name, sizeof(vfd->name), "%s %s", | 2463 | snprintf(vfd->name, sizeof(vfd->name), "%s %s", |
2460 | dev->name, type_name); | 2464 | dev->name, type_name); |
2461 | 2465 | ||
2466 | video_set_drvdata(vfd, dev); | ||
2462 | return vfd; | 2467 | return vfd; |
2463 | } | 2468 | } |
2464 | 2469 | ||
@@ -2540,16 +2545,16 @@ int em28xx_register_analog_devices(struct em28xx *dev) | |||
2540 | em28xx_errdev("can't register radio device\n"); | 2545 | em28xx_errdev("can't register radio device\n"); |
2541 | return ret; | 2546 | return ret; |
2542 | } | 2547 | } |
2543 | em28xx_info("Registered radio device as /dev/radio%d\n", | 2548 | em28xx_info("Registered radio device as %s\n", |
2544 | dev->radio_dev->num); | 2549 | video_device_node_name(dev->radio_dev)); |
2545 | } | 2550 | } |
2546 | 2551 | ||
2547 | em28xx_info("V4L2 video device registered as /dev/video%d\n", | 2552 | em28xx_info("V4L2 video device registered as %s\n", |
2548 | dev->vdev->num); | 2553 | video_device_node_name(dev->vdev)); |
2549 | 2554 | ||
2550 | if (dev->vbi_dev) | 2555 | if (dev->vbi_dev) |
2551 | em28xx_info("V4L2 VBI device registered as /dev/vbi%d\n", | 2556 | em28xx_info("V4L2 VBI device registered as %s\n", |
2552 | dev->vbi_dev->num); | 2557 | video_device_node_name(dev->vbi_dev)); |
2553 | 2558 | ||
2554 | return 0; | 2559 | return 0; |
2555 | } | 2560 | } |
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 441df644ddbe..80d9b4fa1b97 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h | |||
@@ -643,6 +643,8 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, | |||
643 | int len); | 643 | int len); |
644 | int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len); | 644 | int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len); |
645 | int em28xx_write_reg(struct em28xx *dev, u16 reg, u8 val); | 645 | int em28xx_write_reg(struct em28xx *dev, u16 reg, u8 val); |
646 | int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val, | ||
647 | u8 bitmask); | ||
646 | 648 | ||
647 | int em28xx_read_ac97(struct em28xx *dev, u8 reg); | 649 | int em28xx_read_ac97(struct em28xx *dev, u8 reg); |
648 | int em28xx_write_ac97(struct em28xx *dev, u8 reg, u16 val); | 650 | int em28xx_write_ac97(struct em28xx *dev, u8 reg, u16 val); |
@@ -666,9 +668,6 @@ int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio); | |||
666 | void em28xx_wake_i2c(struct em28xx *dev); | 668 | void em28xx_wake_i2c(struct em28xx *dev); |
667 | void em28xx_remove_from_devlist(struct em28xx *dev); | 669 | void em28xx_remove_from_devlist(struct em28xx *dev); |
668 | void em28xx_add_into_devlist(struct em28xx *dev); | 670 | void em28xx_add_into_devlist(struct em28xx *dev); |
669 | struct em28xx *em28xx_get_device(int minor, | ||
670 | enum v4l2_buf_type *fh_type, | ||
671 | int *has_radio); | ||
672 | int em28xx_register_extension(struct em28xx_ops *dev); | 671 | int em28xx_register_extension(struct em28xx_ops *dev); |
673 | void em28xx_unregister_extension(struct em28xx_ops *dev); | 672 | void em28xx_unregister_extension(struct em28xx_ops *dev); |
674 | void em28xx_init_extension(struct em28xx *dev); | 673 | void em28xx_init_extension(struct em28xx *dev); |
diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c index 88987a57cf7b..e6c23d509862 100644 --- a/drivers/media/video/et61x251/et61x251_core.c +++ b/drivers/media/video/et61x251/et61x251_core.c | |||
@@ -587,8 +587,8 @@ static int et61x251_stream_interrupt(struct et61x251_device* cam) | |||
587 | else if (cam->stream != STREAM_OFF) { | 587 | else if (cam->stream != STREAM_OFF) { |
588 | cam->state |= DEV_MISCONFIGURED; | 588 | cam->state |= DEV_MISCONFIGURED; |
589 | DBG(1, "URB timeout reached. The camera is misconfigured. To " | 589 | DBG(1, "URB timeout reached. The camera is misconfigured. To " |
590 | "use it, close and open /dev/video%d again.", | 590 | "use it, close and open %s again.", |
591 | cam->v4ldev->num); | 591 | video_device_node_name(cam->v4ldev)); |
592 | return -EIO; | 592 | return -EIO; |
593 | } | 593 | } |
594 | 594 | ||
@@ -1195,7 +1195,8 @@ static void et61x251_release_resources(struct kref *kref) | |||
1195 | 1195 | ||
1196 | cam = container_of(kref, struct et61x251_device, kref); | 1196 | cam = container_of(kref, struct et61x251_device, kref); |
1197 | 1197 | ||
1198 | DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->num); | 1198 | DBG(2, "V4L2 device %s deregistered", |
1199 | video_device_node_name(cam->v4ldev)); | ||
1199 | video_set_drvdata(cam->v4ldev, NULL); | 1200 | video_set_drvdata(cam->v4ldev, NULL); |
1200 | video_unregister_device(cam->v4ldev); | 1201 | video_unregister_device(cam->v4ldev); |
1201 | usb_put_dev(cam->usbdev); | 1202 | usb_put_dev(cam->usbdev); |
@@ -1236,8 +1237,8 @@ static int et61x251_open(struct file *filp) | |||
1236 | } | 1237 | } |
1237 | 1238 | ||
1238 | if (cam->users) { | 1239 | if (cam->users) { |
1239 | DBG(2, "Device /dev/video%d is already in use", | 1240 | DBG(2, "Device %s is already in use", |
1240 | cam->v4ldev->num); | 1241 | video_device_node_name(cam->v4ldev)); |
1241 | DBG(3, "Simultaneous opens are not supported"); | 1242 | DBG(3, "Simultaneous opens are not supported"); |
1242 | if ((filp->f_flags & O_NONBLOCK) || | 1243 | if ((filp->f_flags & O_NONBLOCK) || |
1243 | (filp->f_flags & O_NDELAY)) { | 1244 | (filp->f_flags & O_NDELAY)) { |
@@ -1280,7 +1281,8 @@ static int et61x251_open(struct file *filp) | |||
1280 | cam->frame_count = 0; | 1281 | cam->frame_count = 0; |
1281 | et61x251_empty_framequeues(cam); | 1282 | et61x251_empty_framequeues(cam); |
1282 | 1283 | ||
1283 | DBG(3, "Video device /dev/video%d is open", cam->v4ldev->num); | 1284 | DBG(3, "Video device %s is open", |
1285 | video_device_node_name(cam->v4ldev)); | ||
1284 | 1286 | ||
1285 | out: | 1287 | out: |
1286 | mutex_unlock(&cam->open_mutex); | 1288 | mutex_unlock(&cam->open_mutex); |
@@ -1304,7 +1306,8 @@ static int et61x251_release(struct file *filp) | |||
1304 | cam->users--; | 1306 | cam->users--; |
1305 | wake_up_interruptible_nr(&cam->wait_open, 1); | 1307 | wake_up_interruptible_nr(&cam->wait_open, 1); |
1306 | 1308 | ||
1307 | DBG(3, "Video device /dev/video%d closed", cam->v4ldev->num); | 1309 | DBG(3, "Video device %s closed", |
1310 | video_device_node_name(cam->v4ldev)); | ||
1308 | 1311 | ||
1309 | kref_put(&cam->kref, et61x251_release_resources); | 1312 | kref_put(&cam->kref, et61x251_release_resources); |
1310 | 1313 | ||
@@ -1846,8 +1849,8 @@ et61x251_vidioc_s_crop(struct et61x251_device* cam, void __user * arg) | |||
1846 | if (err) { /* atomic, no rollback in ioctl() */ | 1849 | if (err) { /* atomic, no rollback in ioctl() */ |
1847 | cam->state |= DEV_MISCONFIGURED; | 1850 | cam->state |= DEV_MISCONFIGURED; |
1848 | DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To " | 1851 | DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To " |
1849 | "use the camera, close and open /dev/video%d again.", | 1852 | "use the camera, close and open %s again.", |
1850 | cam->v4ldev->num); | 1853 | video_device_node_name(cam->v4ldev)); |
1851 | return -EIO; | 1854 | return -EIO; |
1852 | } | 1855 | } |
1853 | 1856 | ||
@@ -1859,8 +1862,8 @@ et61x251_vidioc_s_crop(struct et61x251_device* cam, void __user * arg) | |||
1859 | nbuffers != et61x251_request_buffers(cam, nbuffers, cam->io)) { | 1862 | nbuffers != et61x251_request_buffers(cam, nbuffers, cam->io)) { |
1860 | cam->state |= DEV_MISCONFIGURED; | 1863 | cam->state |= DEV_MISCONFIGURED; |
1861 | DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To " | 1864 | DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To " |
1862 | "use the camera, close and open /dev/video%d again.", | 1865 | "use the camera, close and open %s again.", |
1863 | cam->v4ldev->num); | 1866 | video_device_node_name(cam->v4ldev)); |
1864 | return -ENOMEM; | 1867 | return -ENOMEM; |
1865 | } | 1868 | } |
1866 | 1869 | ||
@@ -2069,8 +2072,8 @@ et61x251_vidioc_try_s_fmt(struct et61x251_device* cam, unsigned int cmd, | |||
2069 | if (err) { /* atomic, no rollback in ioctl() */ | 2072 | if (err) { /* atomic, no rollback in ioctl() */ |
2070 | cam->state |= DEV_MISCONFIGURED; | 2073 | cam->state |= DEV_MISCONFIGURED; |
2071 | DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To " | 2074 | DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To " |
2072 | "use the camera, close and open /dev/video%d again.", | 2075 | "use the camera, close and open %s again.", |
2073 | cam->v4ldev->num); | 2076 | video_device_node_name(cam->v4ldev)); |
2074 | return -EIO; | 2077 | return -EIO; |
2075 | } | 2078 | } |
2076 | 2079 | ||
@@ -2081,8 +2084,8 @@ et61x251_vidioc_try_s_fmt(struct et61x251_device* cam, unsigned int cmd, | |||
2081 | nbuffers != et61x251_request_buffers(cam, nbuffers, cam->io)) { | 2084 | nbuffers != et61x251_request_buffers(cam, nbuffers, cam->io)) { |
2082 | cam->state |= DEV_MISCONFIGURED; | 2085 | cam->state |= DEV_MISCONFIGURED; |
2083 | DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To " | 2086 | DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To " |
2084 | "use the camera, close and open /dev/video%d again.", | 2087 | "use the camera, close and open %s again.", |
2085 | cam->v4ldev->num); | 2088 | video_device_node_name(cam->v4ldev)); |
2086 | return -ENOMEM; | 2089 | return -ENOMEM; |
2087 | } | 2090 | } |
2088 | 2091 | ||
@@ -2130,7 +2133,7 @@ et61x251_vidioc_s_jpegcomp(struct et61x251_device* cam, void __user * arg) | |||
2130 | cam->state |= DEV_MISCONFIGURED; | 2133 | cam->state |= DEV_MISCONFIGURED; |
2131 | DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware " | 2134 | DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware " |
2132 | "problems. To use the camera, close and open " | 2135 | "problems. To use the camera, close and open " |
2133 | "/dev/video%d again.", cam->v4ldev->num); | 2136 | "%s again.", video_device_node_name(cam->v4ldev)); |
2134 | return -EIO; | 2137 | return -EIO; |
2135 | } | 2138 | } |
2136 | 2139 | ||
@@ -2584,7 +2587,6 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) | |||
2584 | 2587 | ||
2585 | strcpy(cam->v4ldev->name, "ET61X[12]51 PC Camera"); | 2588 | strcpy(cam->v4ldev->name, "ET61X[12]51 PC Camera"); |
2586 | cam->v4ldev->fops = &et61x251_fops; | 2589 | cam->v4ldev->fops = &et61x251_fops; |
2587 | cam->v4ldev->minor = video_nr[dev_nr]; | ||
2588 | cam->v4ldev->release = video_device_release; | 2590 | cam->v4ldev->release = video_device_release; |
2589 | cam->v4ldev->parent = &udev->dev; | 2591 | cam->v4ldev->parent = &udev->dev; |
2590 | video_set_drvdata(cam->v4ldev, cam); | 2592 | video_set_drvdata(cam->v4ldev, cam); |
@@ -2603,7 +2605,8 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) | |||
2603 | goto fail; | 2605 | goto fail; |
2604 | } | 2606 | } |
2605 | 2607 | ||
2606 | DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->num); | 2608 | DBG(2, "V4L2 device registered as %s", |
2609 | video_device_node_name(cam->v4ldev)); | ||
2607 | 2610 | ||
2608 | cam->module_param.force_munmap = force_munmap[dev_nr]; | 2611 | cam->module_param.force_munmap = force_munmap[dev_nr]; |
2609 | cam->module_param.frame_timeout = frame_timeout[dev_nr]; | 2612 | cam->module_param.frame_timeout = frame_timeout[dev_nr]; |
@@ -2654,9 +2657,9 @@ static void et61x251_usb_disconnect(struct usb_interface* intf) | |||
2654 | DBG(2, "Disconnecting %s...", cam->v4ldev->name); | 2657 | DBG(2, "Disconnecting %s...", cam->v4ldev->name); |
2655 | 2658 | ||
2656 | if (cam->users) { | 2659 | if (cam->users) { |
2657 | DBG(2, "Device /dev/video%d is open! Deregistration and " | 2660 | DBG(2, "Device %s is open! Deregistration and memory " |
2658 | "memory deallocation are deferred.", | 2661 | "deallocation are deferred.", |
2659 | cam->v4ldev->num); | 2662 | video_device_node_name(cam->v4ldev)); |
2660 | cam->state |= DEV_MISCONFIGURED; | 2663 | cam->state |= DEV_MISCONFIGURED; |
2661 | et61x251_stop_transfer(cam); | 2664 | et61x251_stop_transfer(cam); |
2662 | cam->state |= DEV_DISCONNECTED; | 2665 | cam->state |= DEV_DISCONNECTED; |
diff --git a/drivers/media/video/gspca/conex.c b/drivers/media/video/gspca/conex.c index 2f0b8d621e00..c98b5d69c438 100644 --- a/drivers/media/video/gspca/conex.c +++ b/drivers/media/video/gspca/conex.c | |||
@@ -1046,14 +1046,14 @@ static struct sd_desc sd_desc = { | |||
1046 | }; | 1046 | }; |
1047 | 1047 | ||
1048 | /* -- module initialisation -- */ | 1048 | /* -- module initialisation -- */ |
1049 | static __devinitdata struct usb_device_id device_table[] = { | 1049 | static const struct usb_device_id device_table[] __devinitconst = { |
1050 | {USB_DEVICE(0x0572, 0x0041)}, | 1050 | {USB_DEVICE(0x0572, 0x0041)}, |
1051 | {} | 1051 | {} |
1052 | }; | 1052 | }; |
1053 | MODULE_DEVICE_TABLE(usb, device_table); | 1053 | MODULE_DEVICE_TABLE(usb, device_table); |
1054 | 1054 | ||
1055 | /* -- device connect -- */ | 1055 | /* -- device connect -- */ |
1056 | static int sd_probe(struct usb_interface *intf, | 1056 | static int __devinit sd_probe(struct usb_interface *intf, |
1057 | const struct usb_device_id *id) | 1057 | const struct usb_device_id *id) |
1058 | { | 1058 | { |
1059 | return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), | 1059 | return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), |
diff --git a/drivers/media/video/gspca/etoms.c b/drivers/media/video/gspca/etoms.c index 9de86419ae1e..fdf4c0ec5e7a 100644 --- a/drivers/media/video/gspca/etoms.c +++ b/drivers/media/video/gspca/etoms.c | |||
@@ -864,7 +864,7 @@ static struct sd_desc sd_desc = { | |||
864 | }; | 864 | }; |
865 | 865 | ||
866 | /* -- module initialisation -- */ | 866 | /* -- module initialisation -- */ |
867 | static __devinitdata struct usb_device_id device_table[] = { | 867 | static const struct usb_device_id device_table[] __devinitconst = { |
868 | {USB_DEVICE(0x102c, 0x6151), .driver_info = SENSOR_PAS106}, | 868 | {USB_DEVICE(0x102c, 0x6151), .driver_info = SENSOR_PAS106}, |
869 | #if !defined CONFIG_USB_ET61X251 && !defined CONFIG_USB_ET61X251_MODULE | 869 | #if !defined CONFIG_USB_ET61X251 && !defined CONFIG_USB_ET61X251_MODULE |
870 | {USB_DEVICE(0x102c, 0x6251), .driver_info = SENSOR_TAS5130CXX}, | 870 | {USB_DEVICE(0x102c, 0x6251), .driver_info = SENSOR_TAS5130CXX}, |
@@ -875,7 +875,7 @@ static __devinitdata struct usb_device_id device_table[] = { | |||
875 | MODULE_DEVICE_TABLE(usb, device_table); | 875 | MODULE_DEVICE_TABLE(usb, device_table); |
876 | 876 | ||
877 | /* -- device connect -- */ | 877 | /* -- device connect -- */ |
878 | static int sd_probe(struct usb_interface *intf, | 878 | static int __devinit sd_probe(struct usb_interface *intf, |
879 | const struct usb_device_id *id) | 879 | const struct usb_device_id *id) |
880 | { | 880 | { |
881 | return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), | 881 | return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), |
diff --git a/drivers/media/video/gspca/gl860/gl860-mi1320.c b/drivers/media/video/gspca/gl860/gl860-mi1320.c index 1355e526ee84..c276a7debdec 100644 --- a/drivers/media/video/gspca/gl860/gl860-mi1320.c +++ b/drivers/media/video/gspca/gl860/gl860-mi1320.c | |||
@@ -345,7 +345,7 @@ static int mi1320_configure_alt(struct gspca_dev *gspca_dev) | |||
345 | return 0; | 345 | return 0; |
346 | } | 346 | } |
347 | 347 | ||
348 | int mi1320_camera_settings(struct gspca_dev *gspca_dev) | 348 | static int mi1320_camera_settings(struct gspca_dev *gspca_dev) |
349 | { | 349 | { |
350 | struct sd *sd = (struct sd *) gspca_dev; | 350 | struct sd *sd = (struct sd *) gspca_dev; |
351 | 351 | ||
diff --git a/drivers/media/video/gspca/gl860/gl860-mi2020.c b/drivers/media/video/gspca/gl860/gl860-mi2020.c index 80cb3f1b36f7..7c31b4f2abea 100644 --- a/drivers/media/video/gspca/gl860/gl860-mi2020.c +++ b/drivers/media/video/gspca/gl860/gl860-mi2020.c | |||
@@ -769,7 +769,7 @@ static int mi2020_configure_alt(struct gspca_dev *gspca_dev) | |||
769 | return 0; | 769 | return 0; |
770 | } | 770 | } |
771 | 771 | ||
772 | int mi2020_camera_settings(struct gspca_dev *gspca_dev) | 772 | static int mi2020_camera_settings(struct gspca_dev *gspca_dev) |
773 | { | 773 | { |
774 | struct sd *sd = (struct sd *) gspca_dev; | 774 | struct sd *sd = (struct sd *) gspca_dev; |
775 | 775 | ||
diff --git a/drivers/media/video/gspca/gl860/gl860.c b/drivers/media/video/gspca/gl860/gl860.c index a695e0ae13c2..4878c8f66543 100644 --- a/drivers/media/video/gspca/gl860/gl860.c +++ b/drivers/media/video/gspca/gl860/gl860.c | |||
@@ -40,7 +40,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
40 | static void sd_callback(struct gspca_dev *gspca_dev); | 40 | static void sd_callback(struct gspca_dev *gspca_dev); |
41 | 41 | ||
42 | static int gl860_guess_sensor(struct gspca_dev *gspca_dev, | 42 | static int gl860_guess_sensor(struct gspca_dev *gspca_dev, |
43 | s32 vendor_id, s32 product_id); | 43 | u16 vendor_id, u16 product_id); |
44 | 44 | ||
45 | /*============================ driver options ==============================*/ | 45 | /*============================ driver options ==============================*/ |
46 | 46 | ||
@@ -326,11 +326,11 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
326 | { | 326 | { |
327 | struct sd *sd = (struct sd *) gspca_dev; | 327 | struct sd *sd = (struct sd *) gspca_dev; |
328 | struct cam *cam; | 328 | struct cam *cam; |
329 | s32 vendor_id, product_id; | 329 | u16 vendor_id, product_id; |
330 | 330 | ||
331 | /* Get USB VendorID and ProductID */ | 331 | /* Get USB VendorID and ProductID */ |
332 | vendor_id = le16_to_cpu(id->idVendor); | 332 | vendor_id = id->idVendor; |
333 | product_id = le16_to_cpu(id->idProduct); | 333 | product_id = id->idProduct; |
334 | 334 | ||
335 | sd->nbRightUp = 1; | 335 | sd->nbRightUp = 1; |
336 | sd->nbIm = -1; | 336 | sd->nbIm = -1; |
@@ -534,8 +534,8 @@ static int sd_probe(struct usb_interface *intf, | |||
534 | gspca_dev = usb_get_intfdata(intf); | 534 | gspca_dev = usb_get_intfdata(intf); |
535 | 535 | ||
536 | PDEBUG(D_PROBE, | 536 | PDEBUG(D_PROBE, |
537 | "Camera is now controlling video device /dev/video%d", | 537 | "Camera is now controlling video device %s", |
538 | gspca_dev->vdev.minor); | 538 | video_device_node_name(&gspca_dev->vdev)); |
539 | } | 539 | } |
540 | 540 | ||
541 | return ret; | 541 | return ret; |
@@ -673,7 +673,7 @@ void fetch_idxdata(struct gspca_dev *gspca_dev, struct idxdata *tbl, int len) | |||
673 | } | 673 | } |
674 | 674 | ||
675 | static int gl860_guess_sensor(struct gspca_dev *gspca_dev, | 675 | static int gl860_guess_sensor(struct gspca_dev *gspca_dev, |
676 | s32 vendor_id, s32 product_id) | 676 | u16 vendor_id, u16 product_id) |
677 | { | 677 | { |
678 | struct sd *sd = (struct sd *) gspca_dev; | 678 | struct sd *sd = (struct sd *) gspca_dev; |
679 | u8 probe, nb26, nb96, nOV, ntry; | 679 | u8 probe, nb26, nb96, nOV, ntry; |
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 4076f8e5a6fc..bd6214d4ab3b 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c | |||
@@ -304,7 +304,6 @@ void gspca_frame_add(struct gspca_dev *gspca_dev, | |||
304 | j = gspca_dev->fr_queue[i]; | 304 | j = gspca_dev->fr_queue[i]; |
305 | gspca_dev->cur_frame = &gspca_dev->frame[j]; | 305 | gspca_dev->cur_frame = &gspca_dev->frame[j]; |
306 | } | 306 | } |
307 | return; | ||
308 | } | 307 | } |
309 | EXPORT_SYMBOL(gspca_frame_add); | 308 | EXPORT_SYMBOL(gspca_frame_add); |
310 | 309 | ||
@@ -321,7 +320,7 @@ static int gspca_is_compressed(__u32 format) | |||
321 | return 0; | 320 | return 0; |
322 | } | 321 | } |
323 | 322 | ||
324 | static void *rvmalloc(unsigned long size) | 323 | static void *rvmalloc(long size) |
325 | { | 324 | { |
326 | void *mem; | 325 | void *mem; |
327 | unsigned long adr; | 326 | unsigned long adr; |
@@ -329,7 +328,7 @@ static void *rvmalloc(unsigned long size) | |||
329 | mem = vmalloc_32(size); | 328 | mem = vmalloc_32(size); |
330 | if (mem != NULL) { | 329 | if (mem != NULL) { |
331 | adr = (unsigned long) mem; | 330 | adr = (unsigned long) mem; |
332 | while ((long) size > 0) { | 331 | while (size > 0) { |
333 | SetPageReserved(vmalloc_to_page((void *) adr)); | 332 | SetPageReserved(vmalloc_to_page((void *) adr)); |
334 | adr += PAGE_SIZE; | 333 | adr += PAGE_SIZE; |
335 | size -= PAGE_SIZE; | 334 | size -= PAGE_SIZE; |
@@ -768,6 +767,7 @@ static int vidioc_g_register(struct file *file, void *priv, | |||
768 | 767 | ||
769 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) | 768 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) |
770 | return -ERESTARTSYS; | 769 | return -ERESTARTSYS; |
770 | gspca_dev->usb_err = 0; | ||
771 | if (gspca_dev->present) | 771 | if (gspca_dev->present) |
772 | ret = gspca_dev->sd_desc->get_register(gspca_dev, reg); | 772 | ret = gspca_dev->sd_desc->get_register(gspca_dev, reg); |
773 | else | 773 | else |
@@ -791,6 +791,7 @@ static int vidioc_s_register(struct file *file, void *priv, | |||
791 | 791 | ||
792 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) | 792 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) |
793 | return -ERESTARTSYS; | 793 | return -ERESTARTSYS; |
794 | gspca_dev->usb_err = 0; | ||
794 | if (gspca_dev->present) | 795 | if (gspca_dev->present) |
795 | ret = gspca_dev->sd_desc->set_register(gspca_dev, reg); | 796 | ret = gspca_dev->sd_desc->set_register(gspca_dev, reg); |
796 | else | 797 | else |
@@ -812,6 +813,7 @@ static int vidioc_g_chip_ident(struct file *file, void *priv, | |||
812 | 813 | ||
813 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) | 814 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) |
814 | return -ERESTARTSYS; | 815 | return -ERESTARTSYS; |
816 | gspca_dev->usb_err = 0; | ||
815 | if (gspca_dev->present) | 817 | if (gspca_dev->present) |
816 | ret = gspca_dev->sd_desc->get_chip_ident(gspca_dev, chip); | 818 | ret = gspca_dev->sd_desc->get_chip_ident(gspca_dev, chip); |
817 | else | 819 | else |
@@ -983,11 +985,40 @@ static int vidioc_enum_framesizes(struct file *file, void *priv, | |||
983 | return -EINVAL; | 985 | return -EINVAL; |
984 | } | 986 | } |
985 | 987 | ||
988 | static int vidioc_enum_frameintervals(struct file *filp, void *priv, | ||
989 | struct v4l2_frmivalenum *fival) | ||
990 | { | ||
991 | struct gspca_dev *gspca_dev = priv; | ||
992 | int mode = wxh_to_mode(gspca_dev, fival->width, fival->height); | ||
993 | __u32 i; | ||
994 | |||
995 | if (gspca_dev->cam.mode_framerates == NULL || | ||
996 | gspca_dev->cam.mode_framerates[mode].nrates == 0) | ||
997 | return -EINVAL; | ||
998 | |||
999 | if (fival->pixel_format != | ||
1000 | gspca_dev->cam.cam_mode[mode].pixelformat) | ||
1001 | return -EINVAL; | ||
1002 | |||
1003 | for (i = 0; i < gspca_dev->cam.mode_framerates[mode].nrates; i++) { | ||
1004 | if (fival->index == i) { | ||
1005 | fival->type = V4L2_FRMSIZE_TYPE_DISCRETE; | ||
1006 | fival->discrete.numerator = 1; | ||
1007 | fival->discrete.denominator = | ||
1008 | gspca_dev->cam.mode_framerates[mode].rates[i]; | ||
1009 | return 0; | ||
1010 | } | ||
1011 | } | ||
1012 | |||
1013 | return -EINVAL; | ||
1014 | } | ||
1015 | |||
986 | static void gspca_release(struct video_device *vfd) | 1016 | static void gspca_release(struct video_device *vfd) |
987 | { | 1017 | { |
988 | struct gspca_dev *gspca_dev = container_of(vfd, struct gspca_dev, vdev); | 1018 | struct gspca_dev *gspca_dev = container_of(vfd, struct gspca_dev, vdev); |
989 | 1019 | ||
990 | PDEBUG(D_PROBE, "/dev/video%d released", gspca_dev->vdev.num); | 1020 | PDEBUG(D_PROBE, "%s released", |
1021 | video_device_node_name(&gspca_dev->vdev)); | ||
991 | 1022 | ||
992 | kfree(gspca_dev->usb_buf); | 1023 | kfree(gspca_dev->usb_buf); |
993 | kfree(gspca_dev); | 1024 | kfree(gspca_dev); |
@@ -1053,6 +1084,7 @@ static int dev_close(struct file *file) | |||
1053 | if (gspca_dev->capt_file == file) { | 1084 | if (gspca_dev->capt_file == file) { |
1054 | if (gspca_dev->streaming) { | 1085 | if (gspca_dev->streaming) { |
1055 | mutex_lock(&gspca_dev->usb_lock); | 1086 | mutex_lock(&gspca_dev->usb_lock); |
1087 | gspca_dev->usb_err = 0; | ||
1056 | gspca_stream_off(gspca_dev); | 1088 | gspca_stream_off(gspca_dev); |
1057 | mutex_unlock(&gspca_dev->usb_lock); | 1089 | mutex_unlock(&gspca_dev->usb_lock); |
1058 | } | 1090 | } |
@@ -1143,12 +1175,14 @@ static int vidioc_queryctrl(struct file *file, void *priv, | |||
1143 | continue; | 1175 | continue; |
1144 | ctrls = &gspca_dev->sd_desc->ctrls[i]; | 1176 | ctrls = &gspca_dev->sd_desc->ctrls[i]; |
1145 | } | 1177 | } |
1178 | if (ctrls == NULL) | ||
1179 | return -EINVAL; | ||
1146 | } else { | 1180 | } else { |
1147 | ctrls = get_ctrl(gspca_dev, id); | 1181 | ctrls = get_ctrl(gspca_dev, id); |
1182 | if (ctrls == NULL) | ||
1183 | return -EINVAL; | ||
1148 | i = ctrls - gspca_dev->sd_desc->ctrls; | 1184 | i = ctrls - gspca_dev->sd_desc->ctrls; |
1149 | } | 1185 | } |
1150 | if (ctrls == NULL) | ||
1151 | return -EINVAL; | ||
1152 | memcpy(q_ctrl, ctrls, sizeof *q_ctrl); | 1186 | memcpy(q_ctrl, ctrls, sizeof *q_ctrl); |
1153 | if (gspca_dev->ctrl_inac & (1 << i)) | 1187 | if (gspca_dev->ctrl_inac & (1 << i)) |
1154 | q_ctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; | 1188 | q_ctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; |
@@ -1172,6 +1206,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, | |||
1172 | PDEBUG(D_CONF, "set ctrl [%08x] = %d", ctrl->id, ctrl->value); | 1206 | PDEBUG(D_CONF, "set ctrl [%08x] = %d", ctrl->id, ctrl->value); |
1173 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) | 1207 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) |
1174 | return -ERESTARTSYS; | 1208 | return -ERESTARTSYS; |
1209 | gspca_dev->usb_err = 0; | ||
1175 | if (gspca_dev->present) | 1210 | if (gspca_dev->present) |
1176 | ret = ctrls->set(gspca_dev, ctrl->value); | 1211 | ret = ctrls->set(gspca_dev, ctrl->value); |
1177 | else | 1212 | else |
@@ -1193,6 +1228,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, | |||
1193 | 1228 | ||
1194 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) | 1229 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) |
1195 | return -ERESTARTSYS; | 1230 | return -ERESTARTSYS; |
1231 | gspca_dev->usb_err = 0; | ||
1196 | if (gspca_dev->present) | 1232 | if (gspca_dev->present) |
1197 | ret = ctrls->get(gspca_dev, &ctrl->value); | 1233 | ret = ctrls->get(gspca_dev, &ctrl->value); |
1198 | else | 1234 | else |
@@ -1307,6 +1343,7 @@ static int vidioc_reqbufs(struct file *file, void *priv, | |||
1307 | /* stop streaming */ | 1343 | /* stop streaming */ |
1308 | if (gspca_dev->streaming) { | 1344 | if (gspca_dev->streaming) { |
1309 | mutex_lock(&gspca_dev->usb_lock); | 1345 | mutex_lock(&gspca_dev->usb_lock); |
1346 | gspca_dev->usb_err = 0; | ||
1310 | gspca_stream_off(gspca_dev); | 1347 | gspca_stream_off(gspca_dev); |
1311 | mutex_unlock(&gspca_dev->usb_lock); | 1348 | mutex_unlock(&gspca_dev->usb_lock); |
1312 | } | 1349 | } |
@@ -1398,6 +1435,7 @@ static int vidioc_streamoff(struct file *file, void *priv, | |||
1398 | ret = -ERESTARTSYS; | 1435 | ret = -ERESTARTSYS; |
1399 | goto out; | 1436 | goto out; |
1400 | } | 1437 | } |
1438 | gspca_dev->usb_err = 0; | ||
1401 | gspca_stream_off(gspca_dev); | 1439 | gspca_stream_off(gspca_dev); |
1402 | mutex_unlock(&gspca_dev->usb_lock); | 1440 | mutex_unlock(&gspca_dev->usb_lock); |
1403 | 1441 | ||
@@ -1423,6 +1461,7 @@ static int vidioc_g_jpegcomp(struct file *file, void *priv, | |||
1423 | return -EINVAL; | 1461 | return -EINVAL; |
1424 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) | 1462 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) |
1425 | return -ERESTARTSYS; | 1463 | return -ERESTARTSYS; |
1464 | gspca_dev->usb_err = 0; | ||
1426 | if (gspca_dev->present) | 1465 | if (gspca_dev->present) |
1427 | ret = gspca_dev->sd_desc->get_jcomp(gspca_dev, jpegcomp); | 1466 | ret = gspca_dev->sd_desc->get_jcomp(gspca_dev, jpegcomp); |
1428 | else | 1467 | else |
@@ -1441,6 +1480,7 @@ static int vidioc_s_jpegcomp(struct file *file, void *priv, | |||
1441 | return -EINVAL; | 1480 | return -EINVAL; |
1442 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) | 1481 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) |
1443 | return -ERESTARTSYS; | 1482 | return -ERESTARTSYS; |
1483 | gspca_dev->usb_err = 0; | ||
1444 | if (gspca_dev->present) | 1484 | if (gspca_dev->present) |
1445 | ret = gspca_dev->sd_desc->set_jcomp(gspca_dev, jpegcomp); | 1485 | ret = gspca_dev->sd_desc->set_jcomp(gspca_dev, jpegcomp); |
1446 | else | 1486 | else |
@@ -1461,6 +1501,7 @@ static int vidioc_g_parm(struct file *filp, void *priv, | |||
1461 | 1501 | ||
1462 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) | 1502 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) |
1463 | return -ERESTARTSYS; | 1503 | return -ERESTARTSYS; |
1504 | gspca_dev->usb_err = 0; | ||
1464 | if (gspca_dev->present) | 1505 | if (gspca_dev->present) |
1465 | ret = gspca_dev->sd_desc->get_streamparm(gspca_dev, | 1506 | ret = gspca_dev->sd_desc->get_streamparm(gspca_dev, |
1466 | parm); | 1507 | parm); |
@@ -1490,6 +1531,7 @@ static int vidioc_s_parm(struct file *filp, void *priv, | |||
1490 | 1531 | ||
1491 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) | 1532 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) |
1492 | return -ERESTARTSYS; | 1533 | return -ERESTARTSYS; |
1534 | gspca_dev->usb_err = 0; | ||
1493 | if (gspca_dev->present) | 1535 | if (gspca_dev->present) |
1494 | ret = gspca_dev->sd_desc->set_streamparm(gspca_dev, | 1536 | ret = gspca_dev->sd_desc->set_streamparm(gspca_dev, |
1495 | parm); | 1537 | parm); |
@@ -1613,7 +1655,7 @@ static int dev_mmap(struct file *file, struct vm_area_struct *vma) | |||
1613 | size -= PAGE_SIZE; | 1655 | size -= PAGE_SIZE; |
1614 | } | 1656 | } |
1615 | 1657 | ||
1616 | vma->vm_ops = (struct vm_operations_struct *) &gspca_vm_ops; | 1658 | vma->vm_ops = &gspca_vm_ops; |
1617 | vma->vm_private_data = frame; | 1659 | vma->vm_private_data = frame; |
1618 | gspca_vm_open(vma); | 1660 | gspca_vm_open(vma); |
1619 | ret = 0; | 1661 | ret = 0; |
@@ -1661,6 +1703,7 @@ static int frame_wait(struct gspca_dev *gspca_dev, | |||
1661 | 1703 | ||
1662 | if (gspca_dev->sd_desc->dq_callback) { | 1704 | if (gspca_dev->sd_desc->dq_callback) { |
1663 | mutex_lock(&gspca_dev->usb_lock); | 1705 | mutex_lock(&gspca_dev->usb_lock); |
1706 | gspca_dev->usb_err = 0; | ||
1664 | if (gspca_dev->present) | 1707 | if (gspca_dev->present) |
1665 | gspca_dev->sd_desc->dq_callback(gspca_dev); | 1708 | gspca_dev->sd_desc->dq_callback(gspca_dev); |
1666 | mutex_unlock(&gspca_dev->usb_lock); | 1709 | mutex_unlock(&gspca_dev->usb_lock); |
@@ -1772,6 +1815,8 @@ static int vidioc_qbuf(struct file *file, void *priv, | |||
1772 | /* put the buffer in the 'queued' queue */ | 1815 | /* put the buffer in the 'queued' queue */ |
1773 | i = gspca_dev->fr_q; | 1816 | i = gspca_dev->fr_q; |
1774 | gspca_dev->fr_queue[i] = index; | 1817 | gspca_dev->fr_queue[i] = index; |
1818 | if (gspca_dev->fr_i == i) | ||
1819 | gspca_dev->cur_frame = frame; | ||
1775 | gspca_dev->fr_q = (i + 1) % gspca_dev->nframes; | 1820 | gspca_dev->fr_q = (i + 1) % gspca_dev->nframes; |
1776 | PDEBUG(D_FRAM, "qbuf q:%d i:%d o:%d", | 1821 | PDEBUG(D_FRAM, "qbuf q:%d i:%d o:%d", |
1777 | gspca_dev->fr_q, | 1822 | gspca_dev->fr_q, |
@@ -1973,6 +2018,7 @@ static const struct v4l2_ioctl_ops dev_ioctl_ops = { | |||
1973 | .vidioc_g_parm = vidioc_g_parm, | 2018 | .vidioc_g_parm = vidioc_g_parm, |
1974 | .vidioc_s_parm = vidioc_s_parm, | 2019 | .vidioc_s_parm = vidioc_s_parm, |
1975 | .vidioc_enum_framesizes = vidioc_enum_framesizes, | 2020 | .vidioc_enum_framesizes = vidioc_enum_framesizes, |
2021 | .vidioc_enum_frameintervals = vidioc_enum_frameintervals, | ||
1976 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 2022 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
1977 | .vidioc_g_register = vidioc_g_register, | 2023 | .vidioc_g_register = vidioc_g_register, |
1978 | .vidioc_s_register = vidioc_s_register, | 2024 | .vidioc_s_register = vidioc_s_register, |
@@ -1988,7 +2034,6 @@ static struct video_device gspca_template = { | |||
1988 | .fops = &dev_fops, | 2034 | .fops = &dev_fops, |
1989 | .ioctl_ops = &dev_ioctl_ops, | 2035 | .ioctl_ops = &dev_ioctl_ops, |
1990 | .release = gspca_release, | 2036 | .release = gspca_release, |
1991 | .minor = -1, | ||
1992 | }; | 2037 | }; |
1993 | 2038 | ||
1994 | /* | 2039 | /* |
@@ -2049,9 +2094,6 @@ int gspca_dev_probe(struct usb_interface *intf, | |||
2049 | ret = sd_desc->init(gspca_dev); | 2094 | ret = sd_desc->init(gspca_dev); |
2050 | if (ret < 0) | 2095 | if (ret < 0) |
2051 | goto out; | 2096 | goto out; |
2052 | ret = gspca_set_alt0(gspca_dev); | ||
2053 | if (ret < 0) | ||
2054 | goto out; | ||
2055 | gspca_set_default_mode(gspca_dev); | 2097 | gspca_set_default_mode(gspca_dev); |
2056 | 2098 | ||
2057 | mutex_init(&gspca_dev->usb_lock); | 2099 | mutex_init(&gspca_dev->usb_lock); |
@@ -2073,7 +2115,7 @@ int gspca_dev_probe(struct usb_interface *intf, | |||
2073 | } | 2115 | } |
2074 | 2116 | ||
2075 | usb_set_intfdata(intf, gspca_dev); | 2117 | usb_set_intfdata(intf, gspca_dev); |
2076 | PDEBUG(D_PROBE, "/dev/video%d created", gspca_dev->vdev.num); | 2118 | PDEBUG(D_PROBE, "%s created", video_device_node_name(&gspca_dev->vdev)); |
2077 | return 0; | 2119 | return 0; |
2078 | out: | 2120 | out: |
2079 | kfree(gspca_dev->usb_buf); | 2121 | kfree(gspca_dev->usb_buf); |
@@ -2092,7 +2134,8 @@ void gspca_disconnect(struct usb_interface *intf) | |||
2092 | { | 2134 | { |
2093 | struct gspca_dev *gspca_dev = usb_get_intfdata(intf); | 2135 | struct gspca_dev *gspca_dev = usb_get_intfdata(intf); |
2094 | 2136 | ||
2095 | PDEBUG(D_PROBE, "/dev/video%d disconnect", gspca_dev->vdev.num); | 2137 | PDEBUG(D_PROBE, "%s disconnect", |
2138 | video_device_node_name(&gspca_dev->vdev)); | ||
2096 | mutex_lock(&gspca_dev->usb_lock); | 2139 | mutex_lock(&gspca_dev->usb_lock); |
2097 | gspca_dev->present = 0; | 2140 | gspca_dev->present = 0; |
2098 | 2141 | ||
diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index 181617355ec3..59c7941da999 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h | |||
@@ -45,11 +45,20 @@ extern int gspca_debug; | |||
45 | /* image transfers */ | 45 | /* image transfers */ |
46 | #define MAX_NURBS 4 /* max number of URBs */ | 46 | #define MAX_NURBS 4 /* max number of URBs */ |
47 | 47 | ||
48 | |||
49 | /* used to list framerates supported by a camera mode (resolution) */ | ||
50 | struct framerates { | ||
51 | int *rates; | ||
52 | int nrates; | ||
53 | }; | ||
54 | |||
48 | /* device information - set at probe time */ | 55 | /* device information - set at probe time */ |
49 | struct cam { | 56 | struct cam { |
50 | int bulk_size; /* buffer size when image transfer by bulk */ | 57 | int bulk_size; /* buffer size when image transfer by bulk */ |
51 | const struct v4l2_pix_format *cam_mode; /* size nmodes */ | 58 | const struct v4l2_pix_format *cam_mode; /* size nmodes */ |
52 | char nmodes; | 59 | char nmodes; |
60 | const struct framerates *mode_framerates; /* must have size nmode, | ||
61 | * just like cam_mode */ | ||
53 | __u8 bulk_nurbs; /* number of URBs in bulk mode | 62 | __u8 bulk_nurbs; /* number of URBs in bulk mode |
54 | * - cannot be > MAX_NURBS | 63 | * - cannot be > MAX_NURBS |
55 | * - when 0 and bulk_size != 0 means | 64 | * - when 0 and bulk_size != 0 means |
@@ -171,6 +180,7 @@ struct gspca_dev { | |||
171 | struct mutex usb_lock; /* usb exchange protection */ | 180 | struct mutex usb_lock; /* usb exchange protection */ |
172 | struct mutex read_lock; /* read protection */ | 181 | struct mutex read_lock; /* read protection */ |
173 | struct mutex queue_lock; /* ISOC queue protection */ | 182 | struct mutex queue_lock; /* ISOC queue protection */ |
183 | int usb_err; /* USB error - protected by usb_lock */ | ||
174 | #ifdef CONFIG_PM | 184 | #ifdef CONFIG_PM |
175 | char frozen; /* suspend - resume */ | 185 | char frozen; /* suspend - resume */ |
176 | #endif | 186 | #endif |
diff --git a/drivers/media/video/gspca/m5602/m5602_core.c b/drivers/media/video/gspca/m5602/m5602_core.c index 844fc1d886d1..4294c75e3b11 100644 --- a/drivers/media/video/gspca/m5602/m5602_core.c +++ b/drivers/media/video/gspca/m5602/m5602_core.c | |||
@@ -81,7 +81,7 @@ int m5602_write_bridge(struct sd *sd, const u8 address, const u8 i2c_data) | |||
81 | return (err < 0) ? err : 0; | 81 | return (err < 0) ? err : 0; |
82 | } | 82 | } |
83 | 83 | ||
84 | int m5602_wait_for_i2c(struct sd *sd) | 84 | static int m5602_wait_for_i2c(struct sd *sd) |
85 | { | 85 | { |
86 | int err; | 86 | int err; |
87 | u8 data; | 87 | u8 data; |
@@ -388,7 +388,7 @@ static int m5602_probe(struct usb_interface *intf, | |||
388 | THIS_MODULE); | 388 | THIS_MODULE); |
389 | } | 389 | } |
390 | 390 | ||
391 | void m5602_disconnect(struct usb_interface *intf) | 391 | static void m5602_disconnect(struct usb_interface *intf) |
392 | { | 392 | { |
393 | struct gspca_dev *gspca_dev = usb_get_intfdata(intf); | 393 | struct gspca_dev *gspca_dev = usb_get_intfdata(intf); |
394 | struct sd *sd = (struct sd *) gspca_dev; | 394 | struct sd *sd = (struct sd *) gspca_dev; |
diff --git a/drivers/media/video/gspca/m5602/m5602_ov9650.c b/drivers/media/video/gspca/m5602/m5602_ov9650.c index c2739d6605a1..923cdd5f7a6b 100644 --- a/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/drivers/media/video/gspca/m5602/m5602_ov9650.c | |||
@@ -439,7 +439,7 @@ int ov9650_start(struct sd *sd) | |||
439 | err = m5602_write_bridge(sd, res_init_ov9650[i][1], | 439 | err = m5602_write_bridge(sd, res_init_ov9650[i][1], |
440 | res_init_ov9650[i][2]); | 440 | res_init_ov9650[i][2]); |
441 | else if (res_init_ov9650[i][0] == SENSOR) { | 441 | else if (res_init_ov9650[i][0] == SENSOR) { |
442 | u8 data = res_init_ov9650[i][2]; | 442 | data = res_init_ov9650[i][2]; |
443 | err = m5602_write_sensor(sd, | 443 | err = m5602_write_sensor(sd, |
444 | res_init_ov9650[i][1], &data, 1); | 444 | res_init_ov9650[i][1], &data, 1); |
445 | } | 445 | } |
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index a27afeb6f39b..1b536f7d30cf 100644 --- a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c | |||
@@ -48,6 +48,12 @@ static | |||
48 | DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xa 2528") | 48 | DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xa 2528") |
49 | } | 49 | } |
50 | }, { | 50 | }, { |
51 | .ident = "Fujitsu-Siemens Amilo Xi 2428", | ||
52 | .matches = { | ||
53 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), | ||
54 | DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 2428") | ||
55 | } | ||
56 | }, { | ||
51 | .ident = "Fujitsu-Siemens Amilo Xi 2528", | 57 | .ident = "Fujitsu-Siemens Amilo Xi 2528", |
52 | .matches = { | 58 | .matches = { |
53 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), | 59 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), |
@@ -525,7 +531,10 @@ static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val) | |||
525 | err = m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); | 531 | err = m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); |
526 | if (err < 0) | 532 | if (err < 0) |
527 | return err; | 533 | return err; |
528 | data = (data & 0xfe) | !val; | 534 | if (val) |
535 | data &= 0xfe; | ||
536 | else | ||
537 | data |= 0x01; | ||
529 | err = m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); | 538 | err = m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1); |
530 | return err; | 539 | return err; |
531 | } | 540 | } |
@@ -570,7 +579,10 @@ static int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val) | |||
570 | err = m5602_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); | 579 | err = m5602_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); |
571 | if (err < 0) | 580 | if (err < 0) |
572 | return err; | 581 | return err; |
573 | data = (data & 0xfe) | !val; | 582 | if (val) |
583 | data &= 0xfe; | ||
584 | else | ||
585 | data |= 0x01; | ||
574 | err = m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); | 586 | err = m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1); |
575 | return err; | 587 | return err; |
576 | } | 588 | } |
diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c index 126d968dd9e0..9154870e07d2 100644 --- a/drivers/media/video/gspca/mr97310a.c +++ b/drivers/media/video/gspca/mr97310a.c | |||
@@ -67,7 +67,7 @@ MODULE_DESCRIPTION("GSPCA/Mars-Semi MR97310A USB Camera Driver"); | |||
67 | MODULE_LICENSE("GPL"); | 67 | MODULE_LICENSE("GPL"); |
68 | 68 | ||
69 | /* global parameters */ | 69 | /* global parameters */ |
70 | int force_sensor_type = -1; | 70 | static int force_sensor_type = -1; |
71 | module_param(force_sensor_type, int, 0644); | 71 | module_param(force_sensor_type, int, 0644); |
72 | MODULE_PARM_DESC(force_sensor_type, "Force sensor type (-1 (auto), 0 or 1)"); | 72 | MODULE_PARM_DESC(force_sensor_type, "Force sensor type (-1 (auto), 0 or 1)"); |
73 | 73 | ||
diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index ad9ec339981d..b4f965731244 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c | |||
@@ -1982,7 +1982,7 @@ static int ov518_reg_w32(struct sd *sd, __u16 index, u32 value, int n) | |||
1982 | { | 1982 | { |
1983 | int ret; | 1983 | int ret; |
1984 | 1984 | ||
1985 | *((u32 *)sd->gspca_dev.usb_buf) = __cpu_to_le32(value); | 1985 | *((__le32 *) sd->gspca_dev.usb_buf) = __cpu_to_le32(value); |
1986 | 1986 | ||
1987 | ret = usb_control_msg(sd->gspca_dev.dev, | 1987 | ret = usb_control_msg(sd->gspca_dev.dev, |
1988 | usb_sndctrlpipe(sd->gspca_dev.dev, 0), | 1988 | usb_sndctrlpipe(sd->gspca_dev.dev, 0), |
@@ -2021,9 +2021,9 @@ static int ov511_i2c_w(struct sd *sd, __u8 reg, __u8 value) | |||
2021 | if (rc < 0) | 2021 | if (rc < 0) |
2022 | return rc; | 2022 | return rc; |
2023 | 2023 | ||
2024 | do | 2024 | do { |
2025 | rc = reg_r(sd, R511_I2C_CTL); | 2025 | rc = reg_r(sd, R511_I2C_CTL); |
2026 | while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */ | 2026 | } while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */ |
2027 | 2027 | ||
2028 | if (rc < 0) | 2028 | if (rc < 0) |
2029 | return rc; | 2029 | return rc; |
@@ -2055,9 +2055,9 @@ static int ov511_i2c_r(struct sd *sd, __u8 reg) | |||
2055 | if (rc < 0) | 2055 | if (rc < 0) |
2056 | return rc; | 2056 | return rc; |
2057 | 2057 | ||
2058 | do | 2058 | do { |
2059 | rc = reg_r(sd, R511_I2C_CTL); | 2059 | rc = reg_r(sd, R511_I2C_CTL); |
2060 | while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */ | 2060 | } while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */ |
2061 | 2061 | ||
2062 | if (rc < 0) | 2062 | if (rc < 0) |
2063 | return rc; | 2063 | return rc; |
@@ -2081,9 +2081,9 @@ static int ov511_i2c_r(struct sd *sd, __u8 reg) | |||
2081 | if (rc < 0) | 2081 | if (rc < 0) |
2082 | return rc; | 2082 | return rc; |
2083 | 2083 | ||
2084 | do | 2084 | do { |
2085 | rc = reg_r(sd, R511_I2C_CTL); | 2085 | rc = reg_r(sd, R511_I2C_CTL); |
2086 | while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */ | 2086 | } while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */ |
2087 | 2087 | ||
2088 | if (rc < 0) | 2088 | if (rc < 0) |
2089 | return rc; | 2089 | return rc; |
diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index 4dbb882c83dc..0a6b8f07a69d 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c | |||
@@ -1533,7 +1533,7 @@ static void setexposure_96(struct gspca_dev *gspca_dev) | |||
1533 | static void setsharpness_96(struct gspca_dev *gspca_dev) | 1533 | static void setsharpness_96(struct gspca_dev *gspca_dev) |
1534 | { | 1534 | { |
1535 | struct sd *sd = (struct sd *) gspca_dev; | 1535 | struct sd *sd = (struct sd *) gspca_dev; |
1536 | u8 val; | 1536 | s8 val; |
1537 | 1537 | ||
1538 | val = sd->sharpness; | 1538 | val = sd->sharpness; |
1539 | if (val < 0) { /* auto */ | 1539 | if (val < 0) { /* auto */ |
diff --git a/drivers/media/video/gspca/pac7302.c b/drivers/media/video/gspca/pac7302.c index 74acceea8094..de0b66c4b56e 100644 --- a/drivers/media/video/gspca/pac7302.c +++ b/drivers/media/video/gspca/pac7302.c | |||
@@ -90,6 +90,9 @@ struct sd { | |||
90 | unsigned char autogain; | 90 | unsigned char autogain; |
91 | __u8 hflip; | 91 | __u8 hflip; |
92 | __u8 vflip; | 92 | __u8 vflip; |
93 | u8 flags; | ||
94 | #define FL_HFLIP 0x01 /* mirrored by default */ | ||
95 | #define FL_VFLIP 0x02 /* vertical flipped by default */ | ||
93 | 96 | ||
94 | u8 sof_read; | 97 | u8 sof_read; |
95 | u8 autogain_ignore_frames; | 98 | u8 autogain_ignore_frames; |
@@ -552,6 +555,7 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
552 | sd->autogain = AUTOGAIN_DEF; | 555 | sd->autogain = AUTOGAIN_DEF; |
553 | sd->hflip = HFLIP_DEF; | 556 | sd->hflip = HFLIP_DEF; |
554 | sd->vflip = VFLIP_DEF; | 557 | sd->vflip = VFLIP_DEF; |
558 | sd->flags = id->driver_info; | ||
555 | return 0; | 559 | return 0; |
556 | } | 560 | } |
557 | 561 | ||
@@ -708,10 +712,17 @@ static int sethvflip(struct gspca_dev *gspca_dev) | |||
708 | { | 712 | { |
709 | struct sd *sd = (struct sd *) gspca_dev; | 713 | struct sd *sd = (struct sd *) gspca_dev; |
710 | int ret; | 714 | int ret; |
711 | __u8 data; | 715 | u8 data, hflip, vflip; |
716 | |||
717 | hflip = sd->hflip; | ||
718 | if (sd->flags & FL_HFLIP) | ||
719 | hflip = !hflip; | ||
720 | vflip = sd->vflip; | ||
721 | if (sd->flags & FL_VFLIP) | ||
722 | vflip = !vflip; | ||
712 | 723 | ||
713 | ret = reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ | 724 | ret = reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ |
714 | data = (sd->hflip ? 0x08 : 0x00) | (sd->vflip ? 0x04 : 0x00); | 725 | data = (hflip ? 0x08 : 0x00) | (vflip ? 0x04 : 0x00); |
715 | if (0 <= ret) | 726 | if (0 <= ret) |
716 | ret = reg_w(gspca_dev, 0x21, data); | 727 | ret = reg_w(gspca_dev, 0x21, data); |
717 | /* load registers to sensor (Bit 0, auto clear) */ | 728 | /* load registers to sensor (Bit 0, auto clear) */ |
@@ -1218,15 +1229,15 @@ static struct sd_desc sd_desc = { | |||
1218 | }; | 1229 | }; |
1219 | 1230 | ||
1220 | /* -- module initialisation -- */ | 1231 | /* -- module initialisation -- */ |
1221 | static __devinitdata struct usb_device_id device_table[] = { | 1232 | static const struct usb_device_id device_table[] __devinitconst = { |
1222 | {USB_DEVICE(0x06f8, 0x3009)}, | 1233 | {USB_DEVICE(0x06f8, 0x3009)}, |
1223 | {USB_DEVICE(0x093a, 0x2620)}, | 1234 | {USB_DEVICE(0x093a, 0x2620)}, |
1224 | {USB_DEVICE(0x093a, 0x2621)}, | 1235 | {USB_DEVICE(0x093a, 0x2621)}, |
1225 | {USB_DEVICE(0x093a, 0x2622)}, | 1236 | {USB_DEVICE(0x093a, 0x2622), .driver_info = FL_VFLIP}, |
1226 | {USB_DEVICE(0x093a, 0x2624)}, | 1237 | {USB_DEVICE(0x093a, 0x2624), .driver_info = FL_VFLIP}, |
1227 | {USB_DEVICE(0x093a, 0x2626)}, | 1238 | {USB_DEVICE(0x093a, 0x2626)}, |
1228 | {USB_DEVICE(0x093a, 0x2628)}, | 1239 | {USB_DEVICE(0x093a, 0x2628)}, |
1229 | {USB_DEVICE(0x093a, 0x2629)}, | 1240 | {USB_DEVICE(0x093a, 0x2629), .driver_info = FL_VFLIP}, |
1230 | {USB_DEVICE(0x093a, 0x262a)}, | 1241 | {USB_DEVICE(0x093a, 0x262a)}, |
1231 | {USB_DEVICE(0x093a, 0x262c)}, | 1242 | {USB_DEVICE(0x093a, 0x262c)}, |
1232 | {} | 1243 | {} |
@@ -1234,7 +1245,7 @@ static __devinitdata struct usb_device_id device_table[] = { | |||
1234 | MODULE_DEVICE_TABLE(usb, device_table); | 1245 | MODULE_DEVICE_TABLE(usb, device_table); |
1235 | 1246 | ||
1236 | /* -- device connect -- */ | 1247 | /* -- device connect -- */ |
1237 | static int sd_probe(struct usb_interface *intf, | 1248 | static int __devinit sd_probe(struct usb_interface *intf, |
1238 | const struct usb_device_id *id) | 1249 | const struct usb_device_id *id) |
1239 | { | 1250 | { |
1240 | return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), | 1251 | return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), |
diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index e5697a6345e8..42cfcdfd8f4f 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c | |||
@@ -863,7 +863,7 @@ static struct sd_desc sd_desc = { | |||
863 | }; | 863 | }; |
864 | 864 | ||
865 | /* -- module initialisation -- */ | 865 | /* -- module initialisation -- */ |
866 | static __devinitdata struct usb_device_id device_table[] = { | 866 | static const struct usb_device_id device_table[] __devinitconst = { |
867 | {USB_DEVICE(0x093a, 0x2600)}, | 867 | {USB_DEVICE(0x093a, 0x2600)}, |
868 | {USB_DEVICE(0x093a, 0x2601)}, | 868 | {USB_DEVICE(0x093a, 0x2601)}, |
869 | {USB_DEVICE(0x093a, 0x2603)}, | 869 | {USB_DEVICE(0x093a, 0x2603)}, |
@@ -875,7 +875,7 @@ static __devinitdata struct usb_device_id device_table[] = { | |||
875 | MODULE_DEVICE_TABLE(usb, device_table); | 875 | MODULE_DEVICE_TABLE(usb, device_table); |
876 | 876 | ||
877 | /* -- device connect -- */ | 877 | /* -- device connect -- */ |
878 | static int sd_probe(struct usb_interface *intf, | 878 | static int __devinit sd_probe(struct usb_interface *intf, |
879 | const struct usb_device_id *id) | 879 | const struct usb_device_id *id) |
880 | { | 880 | { |
881 | return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), | 881 | return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), |
diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c index b1944a7cbb0f..0ca1c06652b1 100644 --- a/drivers/media/video/gspca/sn9c20x.c +++ b/drivers/media/video/gspca/sn9c20x.c | |||
@@ -1158,7 +1158,7 @@ static int i2c_w2(struct gspca_dev *gspca_dev, u8 reg, u16 val) | |||
1158 | return i2c_w(gspca_dev, row); | 1158 | return i2c_w(gspca_dev, row); |
1159 | } | 1159 | } |
1160 | 1160 | ||
1161 | int i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val) | 1161 | static int i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val) |
1162 | { | 1162 | { |
1163 | struct sd *sd = (struct sd *) gspca_dev; | 1163 | struct sd *sd = (struct sd *) gspca_dev; |
1164 | u8 row[8]; | 1164 | u8 row[8]; |
@@ -1183,7 +1183,7 @@ int i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val) | |||
1183 | return 0; | 1183 | return 0; |
1184 | } | 1184 | } |
1185 | 1185 | ||
1186 | int i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val) | 1186 | static int i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val) |
1187 | { | 1187 | { |
1188 | struct sd *sd = (struct sd *) gspca_dev; | 1188 | struct sd *sd = (struct sd *) gspca_dev; |
1189 | u8 row[8]; | 1189 | u8 row[8]; |
@@ -1476,8 +1476,9 @@ static int sn9c20x_input_init(struct gspca_dev *gspca_dev) | |||
1476 | if (input_register_device(sd->input_dev)) | 1476 | if (input_register_device(sd->input_dev)) |
1477 | return -EINVAL; | 1477 | return -EINVAL; |
1478 | 1478 | ||
1479 | sd->input_task = kthread_run(input_kthread, gspca_dev, "sn9c20x/%d", | 1479 | sd->input_task = kthread_run(input_kthread, gspca_dev, "sn9c20x/%s-%s", |
1480 | gspca_dev->vdev.minor); | 1480 | gspca_dev->dev->bus->bus_name, |
1481 | gspca_dev->dev->devpath); | ||
1481 | 1482 | ||
1482 | if (IS_ERR(sd->input_task)) | 1483 | if (IS_ERR(sd->input_task)) |
1483 | return -EINVAL; | 1484 | return -EINVAL; |
@@ -2174,8 +2175,7 @@ static void configure_sensor_output(struct gspca_dev *gspca_dev, int mode) | |||
2174 | } | 2175 | } |
2175 | 2176 | ||
2176 | #define HW_WIN(mode, hstart, vstart) \ | 2177 | #define HW_WIN(mode, hstart, vstart) \ |
2177 | ((const u8 []){hstart & 0xff, hstart >> 8, \ | 2178 | ((const u8 []){hstart, 0, vstart, 0, \ |
2178 | vstart & 0xff, vstart >> 8, \ | ||
2179 | (mode & MODE_SXGA ? 1280 >> 4 : 640 >> 4), \ | 2179 | (mode & MODE_SXGA ? 1280 >> 4 : 640 >> 4), \ |
2180 | (mode & MODE_SXGA ? 1024 >> 3 : 480 >> 3)}) | 2180 | (mode & MODE_SXGA ? 1024 >> 3 : 480 >> 3)}) |
2181 | 2181 | ||
@@ -2319,7 +2319,7 @@ static void do_autogain(struct gspca_dev *gspca_dev, u16 avg_lum) | |||
2319 | } | 2319 | } |
2320 | } | 2320 | } |
2321 | if (avg_lum > MAX_AVG_LUM) { | 2321 | if (avg_lum > MAX_AVG_LUM) { |
2322 | if (sd->gain - 1 >= 0) { | 2322 | if (sd->gain >= 1) { |
2323 | sd->gain--; | 2323 | sd->gain--; |
2324 | set_gain(gspca_dev); | 2324 | set_gain(gspca_dev); |
2325 | } | 2325 | } |
diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index 5be95bc65138..ddff2b5ee5c2 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c | |||
@@ -1226,7 +1226,7 @@ static const struct sd_desc sd_desc = { | |||
1226 | .driver_info = (SENSOR_ ## sensor << 8) | BRIDGE_ ## bridge | 1226 | .driver_info = (SENSOR_ ## sensor << 8) | BRIDGE_ ## bridge |
1227 | 1227 | ||
1228 | 1228 | ||
1229 | static __devinitdata struct usb_device_id device_table[] = { | 1229 | static const struct usb_device_id device_table[] __devinitconst = { |
1230 | {USB_DEVICE(0x0c45, 0x6001), SB(TAS5110, 102)}, /* TAS5110C1B */ | 1230 | {USB_DEVICE(0x0c45, 0x6001), SB(TAS5110, 102)}, /* TAS5110C1B */ |
1231 | {USB_DEVICE(0x0c45, 0x6005), SB(TAS5110, 101)}, /* TAS5110C1B */ | 1231 | {USB_DEVICE(0x0c45, 0x6005), SB(TAS5110, 101)}, /* TAS5110C1B */ |
1232 | #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE | 1232 | #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE |
@@ -1257,7 +1257,7 @@ static __devinitdata struct usb_device_id device_table[] = { | |||
1257 | MODULE_DEVICE_TABLE(usb, device_table); | 1257 | MODULE_DEVICE_TABLE(usb, device_table); |
1258 | 1258 | ||
1259 | /* -- device connect -- */ | 1259 | /* -- device connect -- */ |
1260 | static int sd_probe(struct usb_interface *intf, | 1260 | static int __devinit sd_probe(struct usb_interface *intf, |
1261 | const struct usb_device_id *id) | 1261 | const struct usb_device_id *id) |
1262 | { | 1262 | { |
1263 | return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), | 1263 | return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), |
diff --git a/drivers/media/video/gspca/spca506.c b/drivers/media/video/gspca/spca506.c index ab28cc23e415..39257e4e074f 100644 --- a/drivers/media/video/gspca/spca506.c +++ b/drivers/media/video/gspca/spca506.c | |||
@@ -685,7 +685,7 @@ static struct sd_desc sd_desc = { | |||
685 | }; | 685 | }; |
686 | 686 | ||
687 | /* -- module initialisation -- */ | 687 | /* -- module initialisation -- */ |
688 | static __devinitdata struct usb_device_id device_table[] = { | 688 | static const struct usb_device_id device_table[] __devinitconst = { |
689 | {USB_DEVICE(0x06e1, 0xa190)}, | 689 | {USB_DEVICE(0x06e1, 0xa190)}, |
690 | /*fixme: may be IntelPCCameraPro BRIDGE_SPCA505 | 690 | /*fixme: may be IntelPCCameraPro BRIDGE_SPCA505 |
691 | {USB_DEVICE(0x0733, 0x0430)}, */ | 691 | {USB_DEVICE(0x0733, 0x0430)}, */ |
@@ -696,7 +696,7 @@ static __devinitdata struct usb_device_id device_table[] = { | |||
696 | MODULE_DEVICE_TABLE(usb, device_table); | 696 | MODULE_DEVICE_TABLE(usb, device_table); |
697 | 697 | ||
698 | /* -- device connect -- */ | 698 | /* -- device connect -- */ |
699 | static int sd_probe(struct usb_interface *intf, | 699 | static int __devinit sd_probe(struct usb_interface *intf, |
700 | const struct usb_device_id *id) | 700 | const struct usb_device_id *id) |
701 | { | 701 | { |
702 | return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), | 702 | return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), |
diff --git a/drivers/media/video/gspca/stk014.c b/drivers/media/video/gspca/stk014.c index 8e23320d7ab7..2e2935532d99 100644 --- a/drivers/media/video/gspca/stk014.c +++ b/drivers/media/video/gspca/stk014.c | |||
@@ -126,12 +126,14 @@ static const struct v4l2_pix_format vga_mode[] = { | |||
126 | }; | 126 | }; |
127 | 127 | ||
128 | /* -- read a register -- */ | 128 | /* -- read a register -- */ |
129 | static int reg_r(struct gspca_dev *gspca_dev, | 129 | static u8 reg_r(struct gspca_dev *gspca_dev, |
130 | __u16 index) | 130 | __u16 index) |
131 | { | 131 | { |
132 | struct usb_device *dev = gspca_dev->dev; | 132 | struct usb_device *dev = gspca_dev->dev; |
133 | int ret; | 133 | int ret; |
134 | 134 | ||
135 | if (gspca_dev->usb_err < 0) | ||
136 | return 0; | ||
135 | ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | 137 | ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), |
136 | 0x00, | 138 | 0x00, |
137 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 139 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
@@ -141,18 +143,21 @@ static int reg_r(struct gspca_dev *gspca_dev, | |||
141 | 500); | 143 | 500); |
142 | if (ret < 0) { | 144 | if (ret < 0) { |
143 | PDEBUG(D_ERR, "reg_r err %d", ret); | 145 | PDEBUG(D_ERR, "reg_r err %d", ret); |
144 | return ret; | 146 | gspca_dev->usb_err = ret; |
147 | return 0; | ||
145 | } | 148 | } |
146 | return gspca_dev->usb_buf[0]; | 149 | return gspca_dev->usb_buf[0]; |
147 | } | 150 | } |
148 | 151 | ||
149 | /* -- write a register -- */ | 152 | /* -- write a register -- */ |
150 | static int reg_w(struct gspca_dev *gspca_dev, | 153 | static void reg_w(struct gspca_dev *gspca_dev, |
151 | __u16 index, __u16 value) | 154 | __u16 index, __u16 value) |
152 | { | 155 | { |
153 | struct usb_device *dev = gspca_dev->dev; | 156 | struct usb_device *dev = gspca_dev->dev; |
154 | int ret; | 157 | int ret; |
155 | 158 | ||
159 | if (gspca_dev->usb_err < 0) | ||
160 | return; | ||
156 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | 161 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), |
157 | 0x01, | 162 | 0x01, |
158 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 163 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
@@ -161,13 +166,14 @@ static int reg_w(struct gspca_dev *gspca_dev, | |||
161 | NULL, | 166 | NULL, |
162 | 0, | 167 | 0, |
163 | 500); | 168 | 500); |
164 | if (ret < 0) | 169 | if (ret < 0) { |
165 | PDEBUG(D_ERR, "reg_w err %d", ret); | 170 | PDEBUG(D_ERR, "reg_w err %d", ret); |
166 | return ret; | 171 | gspca_dev->usb_err = ret; |
172 | } | ||
167 | } | 173 | } |
168 | 174 | ||
169 | /* -- get a bulk value (4 bytes) -- */ | 175 | /* -- get a bulk value (4 bytes) -- */ |
170 | static int rcv_val(struct gspca_dev *gspca_dev, | 176 | static void rcv_val(struct gspca_dev *gspca_dev, |
171 | int ads) | 177 | int ads) |
172 | { | 178 | { |
173 | struct usb_device *dev = gspca_dev->dev; | 179 | struct usb_device *dev = gspca_dev->dev; |
@@ -182,17 +188,22 @@ static int rcv_val(struct gspca_dev *gspca_dev, | |||
182 | reg_w(gspca_dev, 0x63a, 0); | 188 | reg_w(gspca_dev, 0x63a, 0); |
183 | reg_w(gspca_dev, 0x63b, 0); | 189 | reg_w(gspca_dev, 0x63b, 0); |
184 | reg_w(gspca_dev, 0x630, 5); | 190 | reg_w(gspca_dev, 0x630, 5); |
191 | if (gspca_dev->usb_err < 0) | ||
192 | return; | ||
185 | ret = usb_bulk_msg(dev, | 193 | ret = usb_bulk_msg(dev, |
186 | usb_rcvbulkpipe(dev, 0x05), | 194 | usb_rcvbulkpipe(dev, 0x05), |
187 | gspca_dev->usb_buf, | 195 | gspca_dev->usb_buf, |
188 | 4, /* length */ | 196 | 4, /* length */ |
189 | &alen, | 197 | &alen, |
190 | 500); /* timeout in milliseconds */ | 198 | 500); /* timeout in milliseconds */ |
191 | return ret; | 199 | if (ret < 0) { |
200 | PDEBUG(D_ERR, "rcv_val err %d", ret); | ||
201 | gspca_dev->usb_err = ret; | ||
202 | } | ||
192 | } | 203 | } |
193 | 204 | ||
194 | /* -- send a bulk value -- */ | 205 | /* -- send a bulk value -- */ |
195 | static int snd_val(struct gspca_dev *gspca_dev, | 206 | static void snd_val(struct gspca_dev *gspca_dev, |
196 | int ads, | 207 | int ads, |
197 | unsigned int val) | 208 | unsigned int val) |
198 | { | 209 | { |
@@ -201,16 +212,9 @@ static int snd_val(struct gspca_dev *gspca_dev, | |||
201 | __u8 seq = 0; | 212 | __u8 seq = 0; |
202 | 213 | ||
203 | if (ads == 0x003f08) { | 214 | if (ads == 0x003f08) { |
204 | ret = reg_r(gspca_dev, 0x0704); | 215 | reg_r(gspca_dev, 0x0704); |
205 | if (ret < 0) | 216 | seq = reg_r(gspca_dev, 0x0705); |
206 | goto ko; | 217 | reg_r(gspca_dev, 0x0650); |
207 | ret = reg_r(gspca_dev, 0x0705); | ||
208 | if (ret < 0) | ||
209 | goto ko; | ||
210 | seq = ret; /* keep the sequence number */ | ||
211 | ret = reg_r(gspca_dev, 0x0650); | ||
212 | if (ret < 0) | ||
213 | goto ko; | ||
214 | reg_w(gspca_dev, 0x654, seq); | 218 | reg_w(gspca_dev, 0x654, seq); |
215 | } else { | 219 | } else { |
216 | reg_w(gspca_dev, 0x654, (ads >> 16) & 0xff); | 220 | reg_w(gspca_dev, 0x654, (ads >> 16) & 0xff); |
@@ -223,6 +227,8 @@ static int snd_val(struct gspca_dev *gspca_dev, | |||
223 | reg_w(gspca_dev, 0x65a, 0); | 227 | reg_w(gspca_dev, 0x65a, 0); |
224 | reg_w(gspca_dev, 0x65b, 0); | 228 | reg_w(gspca_dev, 0x65b, 0); |
225 | reg_w(gspca_dev, 0x650, 5); | 229 | reg_w(gspca_dev, 0x650, 5); |
230 | if (gspca_dev->usb_err < 0) | ||
231 | return; | ||
226 | gspca_dev->usb_buf[0] = val >> 24; | 232 | gspca_dev->usb_buf[0] = val >> 24; |
227 | gspca_dev->usb_buf[1] = val >> 16; | 233 | gspca_dev->usb_buf[1] = val >> 16; |
228 | gspca_dev->usb_buf[2] = val >> 8; | 234 | gspca_dev->usb_buf[2] = val >> 8; |
@@ -233,24 +239,23 @@ static int snd_val(struct gspca_dev *gspca_dev, | |||
233 | 4, | 239 | 4, |
234 | &alen, | 240 | &alen, |
235 | 500); /* timeout in milliseconds */ | 241 | 500); /* timeout in milliseconds */ |
236 | if (ret < 0) | 242 | if (ret < 0) { |
237 | goto ko; | 243 | PDEBUG(D_ERR, "snd_val err %d", ret); |
238 | if (ads == 0x003f08) { | 244 | gspca_dev->usb_err = ret; |
239 | seq += 4; | 245 | } else { |
240 | seq &= 0x3f; | 246 | if (ads == 0x003f08) { |
241 | reg_w(gspca_dev, 0x705, seq); | 247 | seq += 4; |
248 | seq &= 0x3f; | ||
249 | reg_w(gspca_dev, 0x705, seq); | ||
250 | } | ||
242 | } | 251 | } |
243 | return ret; | ||
244 | ko: | ||
245 | PDEBUG(D_ERR, "snd_val err %d", ret); | ||
246 | return ret; | ||
247 | } | 252 | } |
248 | 253 | ||
249 | /* set a camera parameter */ | 254 | /* set a camera parameter */ |
250 | static int set_par(struct gspca_dev *gspca_dev, | 255 | static void set_par(struct gspca_dev *gspca_dev, |
251 | int parval) | 256 | int parval) |
252 | { | 257 | { |
253 | return snd_val(gspca_dev, 0x003f08, parval); | 258 | snd_val(gspca_dev, 0x003f08, parval); |
254 | } | 259 | } |
255 | 260 | ||
256 | static void setbrightness(struct gspca_dev *gspca_dev) | 261 | static void setbrightness(struct gspca_dev *gspca_dev) |
@@ -311,18 +316,18 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
311 | /* this function is called at probe and resume time */ | 316 | /* this function is called at probe and resume time */ |
312 | static int sd_init(struct gspca_dev *gspca_dev) | 317 | static int sd_init(struct gspca_dev *gspca_dev) |
313 | { | 318 | { |
314 | int ret; | 319 | u8 ret; |
315 | 320 | ||
316 | /* check if the device responds */ | 321 | /* check if the device responds */ |
317 | usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1); | 322 | usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1); |
318 | ret = reg_r(gspca_dev, 0x0740); | 323 | ret = reg_r(gspca_dev, 0x0740); |
319 | if (ret < 0) | 324 | if (gspca_dev->usb_err >= 0) { |
320 | return ret; | 325 | if (ret != 0xff) { |
321 | if (ret != 0xff) { | 326 | PDEBUG(D_ERR|D_STREAM, "init reg: 0x%02x", ret); |
322 | PDEBUG(D_ERR|D_STREAM, "init reg: 0x%02x", ret); | 327 | gspca_dev->usb_err = -EIO; |
323 | return -1; | 328 | } |
324 | } | 329 | } |
325 | return 0; | 330 | return gspca_dev->usb_err; |
326 | } | 331 | } |
327 | 332 | ||
328 | /* -- start the camera -- */ | 333 | /* -- start the camera -- */ |
@@ -357,15 +362,12 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
357 | if (ret < 0) { | 362 | if (ret < 0) { |
358 | PDEBUG(D_ERR|D_STREAM, "set intf %d %d failed", | 363 | PDEBUG(D_ERR|D_STREAM, "set intf %d %d failed", |
359 | gspca_dev->iface, gspca_dev->alt); | 364 | gspca_dev->iface, gspca_dev->alt); |
365 | gspca_dev->usb_err = ret; | ||
360 | goto out; | 366 | goto out; |
361 | } | 367 | } |
362 | ret = reg_r(gspca_dev, 0x0630); | 368 | reg_r(gspca_dev, 0x0630); |
363 | if (ret < 0) | ||
364 | goto out; | ||
365 | rcv_val(gspca_dev, 0x000020); /* << (value ff ff ff ff) */ | 369 | rcv_val(gspca_dev, 0x000020); /* << (value ff ff ff ff) */ |
366 | ret = reg_r(gspca_dev, 0x0650); | 370 | reg_r(gspca_dev, 0x0650); |
367 | if (ret < 0) | ||
368 | goto out; | ||
369 | snd_val(gspca_dev, 0x000020, 0xffffffff); | 371 | snd_val(gspca_dev, 0x000020, 0xffffffff); |
370 | reg_w(gspca_dev, 0x0620, 0); | 372 | reg_w(gspca_dev, 0x0620, 0); |
371 | reg_w(gspca_dev, 0x0630, 0); | 373 | reg_w(gspca_dev, 0x0630, 0); |
@@ -384,11 +386,11 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
384 | /* start the video flow */ | 386 | /* start the video flow */ |
385 | set_par(gspca_dev, 0x01000000); | 387 | set_par(gspca_dev, 0x01000000); |
386 | set_par(gspca_dev, 0x01000000); | 388 | set_par(gspca_dev, 0x01000000); |
387 | PDEBUG(D_STREAM, "camera started alt: 0x%02x", gspca_dev->alt); | 389 | if (gspca_dev->usb_err >= 0) |
388 | return 0; | 390 | PDEBUG(D_STREAM, "camera started alt: 0x%02x", |
391 | gspca_dev->alt); | ||
389 | out: | 392 | out: |
390 | PDEBUG(D_ERR|D_STREAM, "camera start err %d", ret); | 393 | return gspca_dev->usb_err; |
391 | return ret; | ||
392 | } | 394 | } |
393 | 395 | ||
394 | static void sd_stopN(struct gspca_dev *gspca_dev) | 396 | static void sd_stopN(struct gspca_dev *gspca_dev) |
@@ -456,7 +458,7 @@ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | |||
456 | sd->brightness = val; | 458 | sd->brightness = val; |
457 | if (gspca_dev->streaming) | 459 | if (gspca_dev->streaming) |
458 | setbrightness(gspca_dev); | 460 | setbrightness(gspca_dev); |
459 | return 0; | 461 | return gspca_dev->usb_err; |
460 | } | 462 | } |
461 | 463 | ||
462 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) | 464 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -474,7 +476,7 @@ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) | |||
474 | sd->contrast = val; | 476 | sd->contrast = val; |
475 | if (gspca_dev->streaming) | 477 | if (gspca_dev->streaming) |
476 | setcontrast(gspca_dev); | 478 | setcontrast(gspca_dev); |
477 | return 0; | 479 | return gspca_dev->usb_err; |
478 | } | 480 | } |
479 | 481 | ||
480 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) | 482 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -492,7 +494,7 @@ static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val) | |||
492 | sd->colors = val; | 494 | sd->colors = val; |
493 | if (gspca_dev->streaming) | 495 | if (gspca_dev->streaming) |
494 | setcolors(gspca_dev); | 496 | setcolors(gspca_dev); |
495 | return 0; | 497 | return gspca_dev->usb_err; |
496 | } | 498 | } |
497 | 499 | ||
498 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) | 500 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -510,7 +512,7 @@ static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val) | |||
510 | sd->lightfreq = val; | 512 | sd->lightfreq = val; |
511 | if (gspca_dev->streaming) | 513 | if (gspca_dev->streaming) |
512 | setfreq(gspca_dev); | 514 | setfreq(gspca_dev); |
513 | return 0; | 515 | return gspca_dev->usb_err; |
514 | } | 516 | } |
515 | 517 | ||
516 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val) | 518 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -552,7 +554,7 @@ static int sd_set_jcomp(struct gspca_dev *gspca_dev, | |||
552 | sd->quality = jcomp->quality; | 554 | sd->quality = jcomp->quality; |
553 | if (gspca_dev->streaming) | 555 | if (gspca_dev->streaming) |
554 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); | 556 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); |
555 | return 0; | 557 | return gspca_dev->usb_err; |
556 | } | 558 | } |
557 | 559 | ||
558 | static int sd_get_jcomp(struct gspca_dev *gspca_dev, | 560 | static int sd_get_jcomp(struct gspca_dev *gspca_dev, |
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h index 487d40555343..96c61926d372 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h +++ b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h | |||
@@ -228,6 +228,7 @@ static const struct stv_init stv_bridge_init[] = { | |||
228 | /* This reg is written twice. Some kind of reset? */ | 228 | /* This reg is written twice. Some kind of reset? */ |
229 | {NULL, 0x1620, 0x80}, | 229 | {NULL, 0x1620, 0x80}, |
230 | {NULL, 0x1620, 0x00}, | 230 | {NULL, 0x1620, 0x00}, |
231 | {NULL, 0x1443, 0x00}, | ||
231 | {NULL, 0x1423, 0x04}, | 232 | {NULL, 0x1423, 0x04}, |
232 | {x1500, 0x1500, ARRAY_SIZE(x1500)}, | 233 | {x1500, 0x1500, ARRAY_SIZE(x1500)}, |
233 | {x1536, 0x1536, ARRAY_SIZE(x1536)}, | 234 | {x1536, 0x1536, ARRAY_SIZE(x1536)}, |
diff --git a/drivers/media/video/gspca/sunplus.c b/drivers/media/video/gspca/sunplus.c index 72bf3b4f0a31..306b7d75b4aa 100644 --- a/drivers/media/video/gspca/sunplus.c +++ b/drivers/media/video/gspca/sunplus.c | |||
@@ -460,13 +460,17 @@ static void reg_r(struct gspca_dev *gspca_dev, | |||
460 | u16 index, | 460 | u16 index, |
461 | u16 len) | 461 | u16 len) |
462 | { | 462 | { |
463 | int ret; | ||
464 | |||
463 | #ifdef GSPCA_DEBUG | 465 | #ifdef GSPCA_DEBUG |
464 | if (len > USB_BUF_SZ) { | 466 | if (len > USB_BUF_SZ) { |
465 | err("reg_r: buffer overflow"); | 467 | err("reg_r: buffer overflow"); |
466 | return; | 468 | return; |
467 | } | 469 | } |
468 | #endif | 470 | #endif |
469 | usb_control_msg(gspca_dev->dev, | 471 | if (gspca_dev->usb_err < 0) |
472 | return; | ||
473 | ret = usb_control_msg(gspca_dev->dev, | ||
470 | usb_rcvctrlpipe(gspca_dev->dev, 0), | 474 | usb_rcvctrlpipe(gspca_dev->dev, 0), |
471 | req, | 475 | req, |
472 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 476 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
@@ -474,6 +478,10 @@ static void reg_r(struct gspca_dev *gspca_dev, | |||
474 | index, | 478 | index, |
475 | len ? gspca_dev->usb_buf : NULL, len, | 479 | len ? gspca_dev->usb_buf : NULL, len, |
476 | 500); | 480 | 500); |
481 | if (ret < 0) { | ||
482 | PDEBUG(D_ERR, "reg_r err %d", ret); | ||
483 | gspca_dev->usb_err = ret; | ||
484 | } | ||
477 | } | 485 | } |
478 | 486 | ||
479 | /* write one byte */ | 487 | /* write one byte */ |
@@ -483,40 +491,55 @@ static void reg_w_1(struct gspca_dev *gspca_dev, | |||
483 | u16 index, | 491 | u16 index, |
484 | u16 byte) | 492 | u16 byte) |
485 | { | 493 | { |
494 | int ret; | ||
495 | |||
496 | if (gspca_dev->usb_err < 0) | ||
497 | return; | ||
486 | gspca_dev->usb_buf[0] = byte; | 498 | gspca_dev->usb_buf[0] = byte; |
487 | usb_control_msg(gspca_dev->dev, | 499 | ret = usb_control_msg(gspca_dev->dev, |
488 | usb_sndctrlpipe(gspca_dev->dev, 0), | 500 | usb_sndctrlpipe(gspca_dev->dev, 0), |
489 | req, | 501 | req, |
490 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 502 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
491 | value, index, | 503 | value, index, |
492 | gspca_dev->usb_buf, 1, | 504 | gspca_dev->usb_buf, 1, |
493 | 500); | 505 | 500); |
506 | if (ret < 0) { | ||
507 | PDEBUG(D_ERR, "reg_w_1 err %d", ret); | ||
508 | gspca_dev->usb_err = ret; | ||
509 | } | ||
494 | } | 510 | } |
495 | 511 | ||
496 | /* write req / index / value */ | 512 | /* write req / index / value */ |
497 | static int reg_w_riv(struct usb_device *dev, | 513 | static void reg_w_riv(struct gspca_dev *gspca_dev, |
498 | u8 req, u16 index, u16 value) | 514 | u8 req, u16 index, u16 value) |
499 | { | 515 | { |
516 | struct usb_device *dev = gspca_dev->dev; | ||
500 | int ret; | 517 | int ret; |
501 | 518 | ||
519 | if (gspca_dev->usb_err < 0) | ||
520 | return; | ||
502 | ret = usb_control_msg(dev, | 521 | ret = usb_control_msg(dev, |
503 | usb_sndctrlpipe(dev, 0), | 522 | usb_sndctrlpipe(dev, 0), |
504 | req, | 523 | req, |
505 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 524 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
506 | value, index, NULL, 0, 500); | 525 | value, index, NULL, 0, 500); |
507 | PDEBUG(D_USBO, "reg write: 0x%02x,0x%02x:0x%02x, %d", | 526 | if (ret < 0) { |
508 | req, index, value, ret); | 527 | PDEBUG(D_ERR, "reg_w_riv err %d", ret); |
509 | if (ret < 0) | 528 | gspca_dev->usb_err = ret; |
510 | PDEBUG(D_ERR, "reg write: error %d", ret); | 529 | return; |
511 | return ret; | 530 | } |
531 | PDEBUG(D_USBO, "reg_w_riv: 0x%02x,0x%04x:0x%04x", | ||
532 | req, index, value); | ||
512 | } | 533 | } |
513 | 534 | ||
514 | /* read 1 byte */ | 535 | /* read 1 byte */ |
515 | static int reg_r_1(struct gspca_dev *gspca_dev, | 536 | static u8 reg_r_1(struct gspca_dev *gspca_dev, |
516 | u16 value) /* wValue */ | 537 | u16 value) /* wValue */ |
517 | { | 538 | { |
518 | int ret; | 539 | int ret; |
519 | 540 | ||
541 | if (gspca_dev->usb_err < 0) | ||
542 | return 0; | ||
520 | ret = usb_control_msg(gspca_dev->dev, | 543 | ret = usb_control_msg(gspca_dev->dev, |
521 | usb_rcvctrlpipe(gspca_dev->dev, 0), | 544 | usb_rcvctrlpipe(gspca_dev->dev, 0), |
522 | 0x20, /* request */ | 545 | 0x20, /* request */ |
@@ -527,19 +550,22 @@ static int reg_r_1(struct gspca_dev *gspca_dev, | |||
527 | 500); /* timeout */ | 550 | 500); /* timeout */ |
528 | if (ret < 0) { | 551 | if (ret < 0) { |
529 | PDEBUG(D_ERR, "reg_r_1 err %d", ret); | 552 | PDEBUG(D_ERR, "reg_r_1 err %d", ret); |
553 | gspca_dev->usb_err = ret; | ||
530 | return 0; | 554 | return 0; |
531 | } | 555 | } |
532 | return gspca_dev->usb_buf[0]; | 556 | return gspca_dev->usb_buf[0]; |
533 | } | 557 | } |
534 | 558 | ||
535 | /* read 1 or 2 bytes - returns < 0 if error */ | 559 | /* read 1 or 2 bytes */ |
536 | static int reg_r_12(struct gspca_dev *gspca_dev, | 560 | static u16 reg_r_12(struct gspca_dev *gspca_dev, |
537 | u8 req, /* bRequest */ | 561 | u8 req, /* bRequest */ |
538 | u16 index, /* wIndex */ | 562 | u16 index, /* wIndex */ |
539 | u16 length) /* wLength (1 or 2 only) */ | 563 | u16 length) /* wLength (1 or 2 only) */ |
540 | { | 564 | { |
541 | int ret; | 565 | int ret; |
542 | 566 | ||
567 | if (gspca_dev->usb_err < 0) | ||
568 | return 0; | ||
543 | gspca_dev->usb_buf[1] = 0; | 569 | gspca_dev->usb_buf[1] = 0; |
544 | ret = usb_control_msg(gspca_dev->dev, | 570 | ret = usb_control_msg(gspca_dev->dev, |
545 | usb_rcvctrlpipe(gspca_dev->dev, 0), | 571 | usb_rcvctrlpipe(gspca_dev->dev, 0), |
@@ -550,62 +576,44 @@ static int reg_r_12(struct gspca_dev *gspca_dev, | |||
550 | gspca_dev->usb_buf, length, | 576 | gspca_dev->usb_buf, length, |
551 | 500); | 577 | 500); |
552 | if (ret < 0) { | 578 | if (ret < 0) { |
553 | PDEBUG(D_ERR, "reg_read err %d", ret); | 579 | PDEBUG(D_ERR, "reg_r_12 err %d", ret); |
554 | return -1; | 580 | gspca_dev->usb_err = ret; |
581 | return 0; | ||
555 | } | 582 | } |
556 | return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0]; | 583 | return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0]; |
557 | } | 584 | } |
558 | 585 | ||
559 | static int write_vector(struct gspca_dev *gspca_dev, | 586 | static void write_vector(struct gspca_dev *gspca_dev, |
560 | const struct cmd *data, int ncmds) | 587 | const struct cmd *data, int ncmds) |
561 | { | 588 | { |
562 | struct usb_device *dev = gspca_dev->dev; | ||
563 | int ret; | ||
564 | |||
565 | while (--ncmds >= 0) { | 589 | while (--ncmds >= 0) { |
566 | ret = reg_w_riv(dev, data->req, data->idx, data->val); | 590 | reg_w_riv(gspca_dev, data->req, data->idx, data->val); |
567 | if (ret < 0) { | ||
568 | PDEBUG(D_ERR, | ||
569 | "Register write failed for 0x%02x, 0x%04x, 0x%04x", | ||
570 | data->req, data->val, data->idx); | ||
571 | return ret; | ||
572 | } | ||
573 | data++; | 591 | data++; |
574 | } | 592 | } |
575 | return 0; | ||
576 | } | 593 | } |
577 | 594 | ||
578 | static int spca50x_setup_qtable(struct gspca_dev *gspca_dev, | 595 | static void setup_qtable(struct gspca_dev *gspca_dev, |
579 | const u8 qtable[2][64]) | 596 | const u8 qtable[2][64]) |
580 | { | 597 | { |
581 | struct usb_device *dev = gspca_dev->dev; | 598 | int i; |
582 | int i, err; | ||
583 | 599 | ||
584 | /* loop over y components */ | 600 | /* loop over y components */ |
585 | for (i = 0; i < 64; i++) { | 601 | for (i = 0; i < 64; i++) |
586 | err = reg_w_riv(dev, 0x00, 0x2800 + i, qtable[0][i]); | 602 | reg_w_riv(gspca_dev, 0x00, 0x2800 + i, qtable[0][i]); |
587 | if (err < 0) | ||
588 | return err; | ||
589 | } | ||
590 | 603 | ||
591 | /* loop over c components */ | 604 | /* loop over c components */ |
592 | for (i = 0; i < 64; i++) { | 605 | for (i = 0; i < 64; i++) |
593 | err = reg_w_riv(dev, 0x00, 0x2840 + i, qtable[1][i]); | 606 | reg_w_riv(gspca_dev, 0x00, 0x2840 + i, qtable[1][i]); |
594 | if (err < 0) | ||
595 | return err; | ||
596 | } | ||
597 | return 0; | ||
598 | } | 607 | } |
599 | 608 | ||
600 | static void spca504_acknowledged_command(struct gspca_dev *gspca_dev, | 609 | static void spca504_acknowledged_command(struct gspca_dev *gspca_dev, |
601 | u8 req, u16 idx, u16 val) | 610 | u8 req, u16 idx, u16 val) |
602 | { | 611 | { |
603 | struct usb_device *dev = gspca_dev->dev; | 612 | u16 notdone; |
604 | int notdone; | ||
605 | 613 | ||
606 | reg_w_riv(dev, req, idx, val); | 614 | reg_w_riv(gspca_dev, req, idx, val); |
607 | notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1); | 615 | notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1); |
608 | reg_w_riv(dev, req, idx, val); | 616 | reg_w_riv(gspca_dev, req, idx, val); |
609 | 617 | ||
610 | PDEBUG(D_FRAM, "before wait 0x%04x", notdone); | 618 | PDEBUG(D_FRAM, "before wait 0x%04x", notdone); |
611 | 619 | ||
@@ -616,23 +624,22 @@ static void spca504_acknowledged_command(struct gspca_dev *gspca_dev, | |||
616 | 624 | ||
617 | static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev, | 625 | static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev, |
618 | u8 req, | 626 | u8 req, |
619 | u16 idx, u16 val, u8 stat, u8 count) | 627 | u16 idx, u16 val, u16 endcode, u8 count) |
620 | { | 628 | { |
621 | struct usb_device *dev = gspca_dev->dev; | 629 | u16 status; |
622 | int status; | ||
623 | u8 endcode; | ||
624 | 630 | ||
625 | reg_w_riv(dev, req, idx, val); | 631 | reg_w_riv(gspca_dev, req, idx, val); |
626 | status = reg_r_12(gspca_dev, 0x01, 0x0001, 1); | 632 | status = reg_r_12(gspca_dev, 0x01, 0x0001, 1); |
627 | endcode = stat; | 633 | if (gspca_dev->usb_err < 0) |
628 | PDEBUG(D_FRAM, "Status 0x%x Need 0x%04x", status, stat); | 634 | return; |
635 | PDEBUG(D_FRAM, "Status 0x%04x Need 0x%04x", status, endcode); | ||
629 | if (!count) | 636 | if (!count) |
630 | return; | 637 | return; |
631 | count = 200; | 638 | count = 200; |
632 | while (--count > 0) { | 639 | while (--count > 0) { |
633 | msleep(10); | 640 | msleep(10); |
634 | /* gsmart mini2 write a each wait setting 1 ms is enough */ | 641 | /* gsmart mini2 write a each wait setting 1 ms is enough */ |
635 | /* reg_w_riv(dev, req, idx, val); */ | 642 | /* reg_w_riv(gspca_dev, req, idx, val); */ |
636 | status = reg_r_12(gspca_dev, 0x01, 0x0001, 1); | 643 | status = reg_r_12(gspca_dev, 0x01, 0x0001, 1); |
637 | if (status == endcode) { | 644 | if (status == endcode) { |
638 | PDEBUG(D_FRAM, "status 0x%04x after wait %d", | 645 | PDEBUG(D_FRAM, "status 0x%04x after wait %d", |
@@ -642,7 +649,7 @@ static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev, | |||
642 | } | 649 | } |
643 | } | 650 | } |
644 | 651 | ||
645 | static int spca504B_PollingDataReady(struct gspca_dev *gspca_dev) | 652 | static void spca504B_PollingDataReady(struct gspca_dev *gspca_dev) |
646 | { | 653 | { |
647 | int count = 10; | 654 | int count = 10; |
648 | 655 | ||
@@ -652,7 +659,6 @@ static int spca504B_PollingDataReady(struct gspca_dev *gspca_dev) | |||
652 | break; | 659 | break; |
653 | msleep(10); | 660 | msleep(10); |
654 | } | 661 | } |
655 | return gspca_dev->usb_buf[0]; | ||
656 | } | 662 | } |
657 | 663 | ||
658 | static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev) | 664 | static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev) |
@@ -686,28 +692,26 @@ static void spca50x_GetFirmware(struct gspca_dev *gspca_dev) | |||
686 | static void spca504B_SetSizeType(struct gspca_dev *gspca_dev) | 692 | static void spca504B_SetSizeType(struct gspca_dev *gspca_dev) |
687 | { | 693 | { |
688 | struct sd *sd = (struct sd *) gspca_dev; | 694 | struct sd *sd = (struct sd *) gspca_dev; |
689 | struct usb_device *dev = gspca_dev->dev; | ||
690 | u8 Size; | 695 | u8 Size; |
691 | int rc; | ||
692 | 696 | ||
693 | Size = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; | 697 | Size = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; |
694 | switch (sd->bridge) { | 698 | switch (sd->bridge) { |
695 | case BRIDGE_SPCA533: | 699 | case BRIDGE_SPCA533: |
696 | reg_w_riv(dev, 0x31, 0, 0); | 700 | reg_w_riv(gspca_dev, 0x31, 0, 0); |
697 | spca504B_WaitCmdStatus(gspca_dev); | 701 | spca504B_WaitCmdStatus(gspca_dev); |
698 | rc = spca504B_PollingDataReady(gspca_dev); | 702 | spca504B_PollingDataReady(gspca_dev); |
699 | spca50x_GetFirmware(gspca_dev); | 703 | spca50x_GetFirmware(gspca_dev); |
700 | reg_w_1(gspca_dev, 0x24, 0, 8, 2); /* type */ | 704 | reg_w_1(gspca_dev, 0x24, 0, 8, 2); /* type */ |
701 | reg_r(gspca_dev, 0x24, 8, 1); | 705 | reg_r(gspca_dev, 0x24, 8, 1); |
702 | 706 | ||
703 | reg_w_1(gspca_dev, 0x25, 0, 4, Size); | 707 | reg_w_1(gspca_dev, 0x25, 0, 4, Size); |
704 | reg_r(gspca_dev, 0x25, 4, 1); /* size */ | 708 | reg_r(gspca_dev, 0x25, 4, 1); /* size */ |
705 | rc = spca504B_PollingDataReady(gspca_dev); | 709 | spca504B_PollingDataReady(gspca_dev); |
706 | 710 | ||
707 | /* Init the cam width height with some values get on init ? */ | 711 | /* Init the cam width height with some values get on init ? */ |
708 | reg_w_riv(dev, 0x31, 0, 0x04); | 712 | reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00); |
709 | spca504B_WaitCmdStatus(gspca_dev); | 713 | spca504B_WaitCmdStatus(gspca_dev); |
710 | rc = spca504B_PollingDataReady(gspca_dev); | 714 | spca504B_PollingDataReady(gspca_dev); |
711 | break; | 715 | break; |
712 | default: | 716 | default: |
713 | /* case BRIDGE_SPCA504B: */ | 717 | /* case BRIDGE_SPCA504B: */ |
@@ -716,7 +720,7 @@ static void spca504B_SetSizeType(struct gspca_dev *gspca_dev) | |||
716 | reg_r(gspca_dev, 0x25, 4, 1); /* size */ | 720 | reg_r(gspca_dev, 0x25, 4, 1); /* size */ |
717 | reg_w_1(gspca_dev, 0x27, 0, 0, 6); | 721 | reg_w_1(gspca_dev, 0x27, 0, 0, 6); |
718 | reg_r(gspca_dev, 0x27, 0, 1); /* type */ | 722 | reg_r(gspca_dev, 0x27, 0, 1); /* type */ |
719 | rc = spca504B_PollingDataReady(gspca_dev); | 723 | spca504B_PollingDataReady(gspca_dev); |
720 | break; | 724 | break; |
721 | case BRIDGE_SPCA504: | 725 | case BRIDGE_SPCA504: |
722 | Size += 3; | 726 | Size += 3; |
@@ -733,8 +737,8 @@ static void spca504B_SetSizeType(struct gspca_dev *gspca_dev) | |||
733 | break; | 737 | break; |
734 | case BRIDGE_SPCA504C: | 738 | case BRIDGE_SPCA504C: |
735 | /* capture mode */ | 739 | /* capture mode */ |
736 | reg_w_riv(dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00); | 740 | reg_w_riv(gspca_dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00); |
737 | reg_w_riv(dev, 0x20, 0x01, 0x0500 | (Size & 0x0f)); | 741 | reg_w_riv(gspca_dev, 0x20, 0x01, 0x0500 | (Size & 0x0f)); |
738 | break; | 742 | break; |
739 | } | 743 | } |
740 | } | 744 | } |
@@ -762,37 +766,33 @@ static void spca504B_setQtable(struct gspca_dev *gspca_dev) | |||
762 | static void setbrightness(struct gspca_dev *gspca_dev) | 766 | static void setbrightness(struct gspca_dev *gspca_dev) |
763 | { | 767 | { |
764 | struct sd *sd = (struct sd *) gspca_dev; | 768 | struct sd *sd = (struct sd *) gspca_dev; |
765 | struct usb_device *dev = gspca_dev->dev; | ||
766 | u16 reg; | 769 | u16 reg; |
767 | 770 | ||
768 | reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f0 : 0x21a7; | 771 | reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f0 : 0x21a7; |
769 | reg_w_riv(dev, 0x00, reg, sd->brightness); | 772 | reg_w_riv(gspca_dev, 0x00, reg, sd->brightness); |
770 | } | 773 | } |
771 | 774 | ||
772 | static void setcontrast(struct gspca_dev *gspca_dev) | 775 | static void setcontrast(struct gspca_dev *gspca_dev) |
773 | { | 776 | { |
774 | struct sd *sd = (struct sd *) gspca_dev; | 777 | struct sd *sd = (struct sd *) gspca_dev; |
775 | struct usb_device *dev = gspca_dev->dev; | ||
776 | u16 reg; | 778 | u16 reg; |
777 | 779 | ||
778 | reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f1 : 0x21a8; | 780 | reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f1 : 0x21a8; |
779 | reg_w_riv(dev, 0x00, reg, sd->contrast); | 781 | reg_w_riv(gspca_dev, 0x00, reg, sd->contrast); |
780 | } | 782 | } |
781 | 783 | ||
782 | static void setcolors(struct gspca_dev *gspca_dev) | 784 | static void setcolors(struct gspca_dev *gspca_dev) |
783 | { | 785 | { |
784 | struct sd *sd = (struct sd *) gspca_dev; | 786 | struct sd *sd = (struct sd *) gspca_dev; |
785 | struct usb_device *dev = gspca_dev->dev; | ||
786 | u16 reg; | 787 | u16 reg; |
787 | 788 | ||
788 | reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f6 : 0x21ae; | 789 | reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f6 : 0x21ae; |
789 | reg_w_riv(dev, 0x00, reg, sd->colors); | 790 | reg_w_riv(gspca_dev, 0x00, reg, sd->colors); |
790 | } | 791 | } |
791 | 792 | ||
792 | static void init_ctl_reg(struct gspca_dev *gspca_dev) | 793 | static void init_ctl_reg(struct gspca_dev *gspca_dev) |
793 | { | 794 | { |
794 | struct sd *sd = (struct sd *) gspca_dev; | 795 | struct sd *sd = (struct sd *) gspca_dev; |
795 | struct usb_device *dev = gspca_dev->dev; | ||
796 | int pollreg = 1; | 796 | int pollreg = 1; |
797 | 797 | ||
798 | setbrightness(gspca_dev); | 798 | setbrightness(gspca_dev); |
@@ -807,14 +807,14 @@ static void init_ctl_reg(struct gspca_dev *gspca_dev) | |||
807 | default: | 807 | default: |
808 | /* case BRIDGE_SPCA533: */ | 808 | /* case BRIDGE_SPCA533: */ |
809 | /* case BRIDGE_SPCA504B: */ | 809 | /* case BRIDGE_SPCA504B: */ |
810 | reg_w_riv(dev, 0, 0x00, 0x21ad); /* hue */ | 810 | reg_w_riv(gspca_dev, 0, 0x21ad, 0x00); /* hue */ |
811 | reg_w_riv(dev, 0, 0x01, 0x21ac); /* sat/hue */ | 811 | reg_w_riv(gspca_dev, 0, 0x21ac, 0x01); /* sat/hue */ |
812 | reg_w_riv(dev, 0, 0x00, 0x21a3); /* gamma */ | 812 | reg_w_riv(gspca_dev, 0, 0x21a3, 0x00); /* gamma */ |
813 | break; | 813 | break; |
814 | case BRIDGE_SPCA536: | 814 | case BRIDGE_SPCA536: |
815 | reg_w_riv(dev, 0, 0x40, 0x20f5); | 815 | reg_w_riv(gspca_dev, 0, 0x20f5, 0x40); |
816 | reg_w_riv(dev, 0, 0x01, 0x20f4); | 816 | reg_w_riv(gspca_dev, 0, 0x20f4, 0x01); |
817 | reg_w_riv(dev, 0, 0x00, 0x2089); | 817 | reg_w_riv(gspca_dev, 0, 0x2089, 0x00); |
818 | break; | 818 | break; |
819 | } | 819 | } |
820 | if (pollreg) | 820 | if (pollreg) |
@@ -881,18 +881,17 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
881 | static int sd_init(struct gspca_dev *gspca_dev) | 881 | static int sd_init(struct gspca_dev *gspca_dev) |
882 | { | 882 | { |
883 | struct sd *sd = (struct sd *) gspca_dev; | 883 | struct sd *sd = (struct sd *) gspca_dev; |
884 | struct usb_device *dev = gspca_dev->dev; | 884 | int i; |
885 | int i, err_code; | ||
886 | u8 info[6]; | 885 | u8 info[6]; |
887 | 886 | ||
888 | switch (sd->bridge) { | 887 | switch (sd->bridge) { |
889 | case BRIDGE_SPCA504B: | 888 | case BRIDGE_SPCA504B: |
890 | reg_w_riv(dev, 0x1d, 0x00, 0); | 889 | reg_w_riv(gspca_dev, 0x1d, 0x00, 0); |
891 | reg_w_riv(dev, 0, 0x01, 0x2306); | 890 | reg_w_riv(gspca_dev, 0x00, 0x2306, 0x01); |
892 | reg_w_riv(dev, 0, 0x00, 0x0d04); | 891 | reg_w_riv(gspca_dev, 0x00, 0x0d04, 0x00); |
893 | reg_w_riv(dev, 0, 0x00, 0x2000); | 892 | reg_w_riv(gspca_dev, 0x00, 0x2000, 0x00); |
894 | reg_w_riv(dev, 0, 0x13, 0x2301); | 893 | reg_w_riv(gspca_dev, 0x00, 0x2301, 0x13); |
895 | reg_w_riv(dev, 0, 0x00, 0x2306); | 894 | reg_w_riv(gspca_dev, 0x00, 0x2306, 0x00); |
896 | /* fall thru */ | 895 | /* fall thru */ |
897 | case BRIDGE_SPCA533: | 896 | case BRIDGE_SPCA533: |
898 | spca504B_PollingDataReady(gspca_dev); | 897 | spca504B_PollingDataReady(gspca_dev); |
@@ -904,13 +903,13 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
904 | reg_w_1(gspca_dev, 0x24, 0, 0, 0); | 903 | reg_w_1(gspca_dev, 0x24, 0, 0, 0); |
905 | reg_r(gspca_dev, 0x24, 0, 1); | 904 | reg_r(gspca_dev, 0x24, 0, 1); |
906 | spca504B_PollingDataReady(gspca_dev); | 905 | spca504B_PollingDataReady(gspca_dev); |
907 | reg_w_riv(dev, 0x34, 0, 0); | 906 | reg_w_riv(gspca_dev, 0x34, 0, 0); |
908 | spca504B_WaitCmdStatus(gspca_dev); | 907 | spca504B_WaitCmdStatus(gspca_dev); |
909 | break; | 908 | break; |
910 | case BRIDGE_SPCA504C: /* pccam600 */ | 909 | case BRIDGE_SPCA504C: /* pccam600 */ |
911 | PDEBUG(D_STREAM, "Opening SPCA504 (PC-CAM 600)"); | 910 | PDEBUG(D_STREAM, "Opening SPCA504 (PC-CAM 600)"); |
912 | reg_w_riv(dev, 0xe0, 0x0000, 0x0000); | 911 | reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0000); |
913 | reg_w_riv(dev, 0xe0, 0x0000, 0x0001); /* reset */ | 912 | reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0001); /* reset */ |
914 | spca504_wait_status(gspca_dev); | 913 | spca504_wait_status(gspca_dev); |
915 | if (sd->subtype == LogitechClickSmart420) | 914 | if (sd->subtype == LogitechClickSmart420) |
916 | write_vector(gspca_dev, | 915 | write_vector(gspca_dev, |
@@ -919,12 +918,7 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
919 | else | 918 | else |
920 | write_vector(gspca_dev, spca504_pccam600_open_data, | 919 | write_vector(gspca_dev, spca504_pccam600_open_data, |
921 | ARRAY_SIZE(spca504_pccam600_open_data)); | 920 | ARRAY_SIZE(spca504_pccam600_open_data)); |
922 | err_code = spca50x_setup_qtable(gspca_dev, | 921 | setup_qtable(gspca_dev, qtable_creative_pccam); |
923 | qtable_creative_pccam); | ||
924 | if (err_code < 0) { | ||
925 | PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed"); | ||
926 | return err_code; | ||
927 | } | ||
928 | break; | 922 | break; |
929 | default: | 923 | default: |
930 | /* case BRIDGE_SPCA504: */ | 924 | /* case BRIDGE_SPCA504: */ |
@@ -958,29 +952,24 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
958 | 6, 0, 0x86, 1); */ | 952 | 6, 0, 0x86, 1); */ |
959 | /* spca504A_acknowledged_command (gspca_dev, 0x24, | 953 | /* spca504A_acknowledged_command (gspca_dev, 0x24, |
960 | 0, 0, 0x9D, 1); */ | 954 | 0, 0, 0x9D, 1); */ |
961 | reg_w_riv(dev, 0x00, 0x270c, 0x05); /* L92 sno1t.txt */ | 955 | reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05); |
962 | reg_w_riv(dev, 0x00, 0x2310, 0x05); | 956 | /* L92 sno1t.txt */ |
957 | reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05); | ||
963 | spca504A_acknowledged_command(gspca_dev, 0x01, | 958 | spca504A_acknowledged_command(gspca_dev, 0x01, |
964 | 0x0f, 0, 0xff, 0); | 959 | 0x0f, 0, 0xff, 0); |
965 | } | 960 | } |
966 | /* setup qtable */ | 961 | /* setup qtable */ |
967 | reg_w_riv(dev, 0, 0x2000, 0); | 962 | reg_w_riv(gspca_dev, 0, 0x2000, 0); |
968 | reg_w_riv(dev, 0, 0x2883, 1); | 963 | reg_w_riv(gspca_dev, 0, 0x2883, 1); |
969 | err_code = spca50x_setup_qtable(gspca_dev, | 964 | setup_qtable(gspca_dev, qtable_spca504_default); |
970 | qtable_spca504_default); | ||
971 | if (err_code < 0) { | ||
972 | PDEBUG(D_ERR, "spca50x_setup_qtable failed"); | ||
973 | return err_code; | ||
974 | } | ||
975 | break; | 965 | break; |
976 | } | 966 | } |
977 | return 0; | 967 | return gspca_dev->usb_err; |
978 | } | 968 | } |
979 | 969 | ||
980 | static int sd_start(struct gspca_dev *gspca_dev) | 970 | static int sd_start(struct gspca_dev *gspca_dev) |
981 | { | 971 | { |
982 | struct sd *sd = (struct sd *) gspca_dev; | 972 | struct sd *sd = (struct sd *) gspca_dev; |
983 | struct usb_device *dev = gspca_dev->dev; | ||
984 | int enable; | 973 | int enable; |
985 | int i; | 974 | int i; |
986 | u8 info[6]; | 975 | u8 info[6]; |
@@ -1005,13 +994,13 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
1005 | case MegapixV4: | 994 | case MegapixV4: |
1006 | case LogitechClickSmart820: | 995 | case LogitechClickSmart820: |
1007 | case MegaImageVI: | 996 | case MegaImageVI: |
1008 | reg_w_riv(dev, 0xf0, 0, 0); | 997 | reg_w_riv(gspca_dev, 0xf0, 0, 0); |
1009 | spca504B_WaitCmdStatus(gspca_dev); | 998 | spca504B_WaitCmdStatus(gspca_dev); |
1010 | reg_r(gspca_dev, 0xf0, 4, 0); | 999 | reg_r(gspca_dev, 0xf0, 4, 0); |
1011 | spca504B_WaitCmdStatus(gspca_dev); | 1000 | spca504B_WaitCmdStatus(gspca_dev); |
1012 | break; | 1001 | break; |
1013 | default: | 1002 | default: |
1014 | reg_w_riv(dev, 0x31, 0, 0x04); | 1003 | reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00); |
1015 | spca504B_WaitCmdStatus(gspca_dev); | 1004 | spca504B_WaitCmdStatus(gspca_dev); |
1016 | spca504B_PollingDataReady(gspca_dev); | 1005 | spca504B_PollingDataReady(gspca_dev); |
1017 | break; | 1006 | break; |
@@ -1048,8 +1037,9 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
1048 | spca504_acknowledged_command(gspca_dev, 0x24, 0, 0); | 1037 | spca504_acknowledged_command(gspca_dev, 0x24, 0, 0); |
1049 | } | 1038 | } |
1050 | spca504B_SetSizeType(gspca_dev); | 1039 | spca504B_SetSizeType(gspca_dev); |
1051 | reg_w_riv(dev, 0x00, 0x270c, 0x05); /* L92 sno1t.txt */ | 1040 | reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05); |
1052 | reg_w_riv(dev, 0x00, 0x2310, 0x05); | 1041 | /* L92 sno1t.txt */ |
1042 | reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05); | ||
1053 | break; | 1043 | break; |
1054 | case BRIDGE_SPCA504C: | 1044 | case BRIDGE_SPCA504C: |
1055 | if (sd->subtype == LogitechClickSmart420) { | 1045 | if (sd->subtype == LogitechClickSmart420) { |
@@ -1061,36 +1051,37 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
1061 | ARRAY_SIZE(spca504_pccam600_init_data)); | 1051 | ARRAY_SIZE(spca504_pccam600_init_data)); |
1062 | } | 1052 | } |
1063 | enable = (sd->autogain ? 0x04 : 0x01); | 1053 | enable = (sd->autogain ? 0x04 : 0x01); |
1064 | reg_w_riv(dev, 0x0c, 0x0000, enable); /* auto exposure */ | 1054 | reg_w_riv(gspca_dev, 0x0c, 0x0000, enable); |
1065 | reg_w_riv(dev, 0xb0, 0x0000, enable); /* auto whiteness */ | 1055 | /* auto exposure */ |
1056 | reg_w_riv(gspca_dev, 0xb0, 0x0000, enable); | ||
1057 | /* auto whiteness */ | ||
1066 | 1058 | ||
1067 | /* set default exposure compensation and whiteness balance */ | 1059 | /* set default exposure compensation and whiteness balance */ |
1068 | reg_w_riv(dev, 0x30, 0x0001, 800); /* ~ 20 fps */ | 1060 | reg_w_riv(gspca_dev, 0x30, 0x0001, 800); /* ~ 20 fps */ |
1069 | reg_w_riv(dev, 0x30, 0x0002, 1600); | 1061 | reg_w_riv(gspca_dev, 0x30, 0x0002, 1600); |
1070 | spca504B_SetSizeType(gspca_dev); | 1062 | spca504B_SetSizeType(gspca_dev); |
1071 | break; | 1063 | break; |
1072 | } | 1064 | } |
1073 | init_ctl_reg(gspca_dev); | 1065 | init_ctl_reg(gspca_dev); |
1074 | return 0; | 1066 | return gspca_dev->usb_err; |
1075 | } | 1067 | } |
1076 | 1068 | ||
1077 | static void sd_stopN(struct gspca_dev *gspca_dev) | 1069 | static void sd_stopN(struct gspca_dev *gspca_dev) |
1078 | { | 1070 | { |
1079 | struct sd *sd = (struct sd *) gspca_dev; | 1071 | struct sd *sd = (struct sd *) gspca_dev; |
1080 | struct usb_device *dev = gspca_dev->dev; | ||
1081 | 1072 | ||
1082 | switch (sd->bridge) { | 1073 | switch (sd->bridge) { |
1083 | default: | 1074 | default: |
1084 | /* case BRIDGE_SPCA533: */ | 1075 | /* case BRIDGE_SPCA533: */ |
1085 | /* case BRIDGE_SPCA536: */ | 1076 | /* case BRIDGE_SPCA536: */ |
1086 | /* case BRIDGE_SPCA504B: */ | 1077 | /* case BRIDGE_SPCA504B: */ |
1087 | reg_w_riv(dev, 0x31, 0, 0); | 1078 | reg_w_riv(gspca_dev, 0x31, 0, 0); |
1088 | spca504B_WaitCmdStatus(gspca_dev); | 1079 | spca504B_WaitCmdStatus(gspca_dev); |
1089 | spca504B_PollingDataReady(gspca_dev); | 1080 | spca504B_PollingDataReady(gspca_dev); |
1090 | break; | 1081 | break; |
1091 | case BRIDGE_SPCA504: | 1082 | case BRIDGE_SPCA504: |
1092 | case BRIDGE_SPCA504C: | 1083 | case BRIDGE_SPCA504C: |
1093 | reg_w_riv(dev, 0x00, 0x2000, 0x0000); | 1084 | reg_w_riv(gspca_dev, 0x00, 0x2000, 0x0000); |
1094 | 1085 | ||
1095 | if (sd->subtype == AiptekMiniPenCam13) { | 1086 | if (sd->subtype == AiptekMiniPenCam13) { |
1096 | /* spca504a aiptek */ | 1087 | /* spca504a aiptek */ |
@@ -1102,7 +1093,7 @@ static void sd_stopN(struct gspca_dev *gspca_dev) | |||
1102 | 0x0f, 0x00, 0xff, 1); | 1093 | 0x0f, 0x00, 0xff, 1); |
1103 | } else { | 1094 | } else { |
1104 | spca504_acknowledged_command(gspca_dev, 0x24, 0, 0); | 1095 | spca504_acknowledged_command(gspca_dev, 0x24, 0, 0); |
1105 | reg_w_riv(dev, 0x01, 0x000f, 0x0000); | 1096 | reg_w_riv(gspca_dev, 0x01, 0x000f, 0x0000); |
1106 | } | 1097 | } |
1107 | break; | 1098 | break; |
1108 | } | 1099 | } |
@@ -1216,7 +1207,7 @@ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | |||
1216 | sd->brightness = val; | 1207 | sd->brightness = val; |
1217 | if (gspca_dev->streaming) | 1208 | if (gspca_dev->streaming) |
1218 | setbrightness(gspca_dev); | 1209 | setbrightness(gspca_dev); |
1219 | return 0; | 1210 | return gspca_dev->usb_err; |
1220 | } | 1211 | } |
1221 | 1212 | ||
1222 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) | 1213 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -1234,7 +1225,7 @@ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) | |||
1234 | sd->contrast = val; | 1225 | sd->contrast = val; |
1235 | if (gspca_dev->streaming) | 1226 | if (gspca_dev->streaming) |
1236 | setcontrast(gspca_dev); | 1227 | setcontrast(gspca_dev); |
1237 | return 0; | 1228 | return gspca_dev->usb_err; |
1238 | } | 1229 | } |
1239 | 1230 | ||
1240 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) | 1231 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -1252,7 +1243,7 @@ static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val) | |||
1252 | sd->colors = val; | 1243 | sd->colors = val; |
1253 | if (gspca_dev->streaming) | 1244 | if (gspca_dev->streaming) |
1254 | setcolors(gspca_dev); | 1245 | setcolors(gspca_dev); |
1255 | return 0; | 1246 | return gspca_dev->usb_err; |
1256 | } | 1247 | } |
1257 | 1248 | ||
1258 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) | 1249 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -1292,7 +1283,7 @@ static int sd_set_jcomp(struct gspca_dev *gspca_dev, | |||
1292 | sd->quality = jcomp->quality; | 1283 | sd->quality = jcomp->quality; |
1293 | if (gspca_dev->streaming) | 1284 | if (gspca_dev->streaming) |
1294 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); | 1285 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); |
1295 | return 0; | 1286 | return gspca_dev->usb_err; |
1296 | } | 1287 | } |
1297 | 1288 | ||
1298 | static int sd_get_jcomp(struct gspca_dev *gspca_dev, | 1289 | static int sd_get_jcomp(struct gspca_dev *gspca_dev, |
diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c index c090efcd8045..71921c878424 100644 --- a/drivers/media/video/gspca/vc032x.c +++ b/drivers/media/video/gspca/vc032x.c | |||
@@ -3009,6 +3009,10 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
3009 | int l; | 3009 | int l; |
3010 | 3010 | ||
3011 | frame = gspca_get_i_frame(gspca_dev); | 3011 | frame = gspca_get_i_frame(gspca_dev); |
3012 | if (frame == NULL) { | ||
3013 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
3014 | return; | ||
3015 | } | ||
3012 | l = frame->data_end - frame->data; | 3016 | l = frame->data_end - frame->data; |
3013 | if (len > frame->v4l2_buf.length - l) | 3017 | if (len > frame->v4l2_buf.length - l) |
3014 | len = frame->v4l2_buf.length - l; | 3018 | len = frame->v4l2_buf.length - l; |
diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index 69e5dc4fc9de..1a800fc1c00e 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c | |||
@@ -5345,9 +5345,6 @@ static const struct usb_action tas5130cxx_InitialScale[] = { /* 320x240 */ | |||
5345 | {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, | 5345 | {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, |
5346 | {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, | 5346 | {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, |
5347 | {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, | 5347 | {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, |
5348 | {0xa0, 0x07, ZC3XX_R0A5_EXPOSUREGAIN}, | ||
5349 | {0xa0, 0x02, ZC3XX_R0A6_EXPOSUREBLACKLVL}, | ||
5350 | |||
5351 | {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, | 5348 | {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, |
5352 | {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, | 5349 | {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, |
5353 | {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, | 5350 | {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, |
@@ -5364,27 +5361,27 @@ static const struct usb_action tas5130cxx_InitialScale[] = { /* 320x240 */ | |||
5364 | {0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION}, | 5361 | {0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION}, |
5365 | {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, | 5362 | {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, |
5366 | {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, | 5363 | {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, |
5367 | {0xa0, 0x95, ZC3XX_R18D_YTARGET}, | 5364 | {0xa0, 0x70, ZC3XX_R18D_YTARGET}, |
5368 | {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN}, | 5365 | {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN}, |
5369 | {0xa0, 0x00, 0x01ad}, | 5366 | {0xa0, 0x00, 0x01ad}, |
5370 | {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, | 5367 | {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, |
5371 | {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, | 5368 | {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, |
5372 | {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, | 5369 | {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, |
5373 | {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, | 5370 | {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, |
5371 | {0xa0, 0x07, ZC3XX_R0A5_EXPOSUREGAIN}, | ||
5372 | {0xa0, 0x02, ZC3XX_R0A6_EXPOSUREBLACKLVL}, | ||
5374 | {} | 5373 | {} |
5375 | }; | 5374 | }; |
5376 | static const struct usb_action tas5130cxx_Initial[] = { /* 640x480 */ | 5375 | static const struct usb_action tas5130cxx_Initial[] = { /* 640x480 */ |
5377 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, | 5376 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, |
5378 | {0xa0, 0x40, ZC3XX_R002_CLOCKSELECT}, | 5377 | {0xa0, 0x40, ZC3XX_R002_CLOCKSELECT}, |
5379 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, | 5378 | {0xa0, 0x00, ZC3XX_R008_CLOCKSETTING}, |
5380 | {0xa0, 0x02, ZC3XX_R010_CMOSSENSORSELECT}, | 5379 | {0xa0, 0x02, ZC3XX_R010_CMOSSENSORSELECT}, |
5381 | {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, | 5380 | {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, |
5382 | {0xa0, 0x00, ZC3XX_R001_SYSTEMOPERATING}, | 5381 | {0xa0, 0x00, ZC3XX_R001_SYSTEMOPERATING}, |
5383 | {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, | 5382 | {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, |
5384 | {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, | 5383 | {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, |
5385 | {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, | 5384 | {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, |
5386 | {0xa0, 0x07, ZC3XX_R0A5_EXPOSUREGAIN}, | ||
5387 | {0xa0, 0x02, ZC3XX_R0A6_EXPOSUREBLACKLVL}, | ||
5388 | {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, | 5385 | {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, |
5389 | {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, | 5386 | {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, |
5390 | {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, | 5387 | {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, |
@@ -5400,13 +5397,15 @@ static const struct usb_action tas5130cxx_Initial[] = { /* 640x480 */ | |||
5400 | {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, | 5397 | {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, |
5401 | {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, | 5398 | {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, |
5402 | {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, | 5399 | {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, |
5403 | {0xa0, 0x95, ZC3XX_R18D_YTARGET}, | 5400 | {0xa0, 0x70, ZC3XX_R18D_YTARGET}, |
5404 | {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN}, | 5401 | {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN}, |
5405 | {0xa0, 0x00, 0x01ad}, | 5402 | {0xa0, 0x00, 0x01ad}, |
5406 | {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, | 5403 | {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, |
5407 | {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, | 5404 | {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, |
5408 | {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, | 5405 | {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, |
5409 | {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, | 5406 | {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, |
5407 | {0xa0, 0x07, ZC3XX_R0A5_EXPOSUREGAIN}, | ||
5408 | {0xa0, 0x02, ZC3XX_R0A6_EXPOSUREBLACKLVL}, | ||
5410 | {} | 5409 | {} |
5411 | }; | 5410 | }; |
5412 | static const struct usb_action tas5130cxx_50HZ[] = { | 5411 | static const struct usb_action tas5130cxx_50HZ[] = { |
@@ -6424,11 +6423,11 @@ static int vga_2wr_probe(struct gspca_dev *gspca_dev) | |||
6424 | if (retword != 0) | 6423 | if (retword != 0) |
6425 | return 0x0e; /* PAS202BCB */ | 6424 | return 0x0e; /* PAS202BCB */ |
6426 | 6425 | ||
6427 | start_2wr_probe(dev, 0x02); /* ?? */ | 6426 | start_2wr_probe(dev, 0x02); /* TAS5130C */ |
6428 | i2c_write(gspca_dev, 0x01, 0xaa, 0x00); | 6427 | i2c_write(gspca_dev, 0x01, 0xaa, 0x00); |
6429 | retword = i2c_read(gspca_dev, 0x01); | 6428 | retword = i2c_read(gspca_dev, 0x01); |
6430 | if (retword != 0) | 6429 | if (retword != 0) |
6431 | return 0x02; /* ?? */ | 6430 | return 0x02; /* TAS5130C */ |
6432 | ov_check: | 6431 | ov_check: |
6433 | reg_r(gspca_dev, 0x0010); /* ?? */ | 6432 | reg_r(gspca_dev, 0x0010); /* ?? */ |
6434 | reg_r(gspca_dev, 0x0010); | 6433 | reg_r(gspca_dev, 0x0010); |
@@ -6505,6 +6504,8 @@ static int vga_3wr_probe(struct gspca_dev *gspca_dev) | |||
6505 | reg_r(gspca_dev, 0x0010); | 6504 | reg_r(gspca_dev, 0x0010); |
6506 | /* value 0x4001 is meaningless */ | 6505 | /* value 0x4001 is meaningless */ |
6507 | if (retword != 0x4001) { | 6506 | if (retword != 0x4001) { |
6507 | if ((retword & 0xff00) == 0x6400) | ||
6508 | return 0x02; /* TAS5130C */ | ||
6508 | for (i = 0; i < ARRAY_SIZE(chipset_revision_sensor); i++) { | 6509 | for (i = 0; i < ARRAY_SIZE(chipset_revision_sensor); i++) { |
6509 | if (chipset_revision_sensor[i].revision == retword) { | 6510 | if (chipset_revision_sensor[i].revision == retword) { |
6510 | sd->chip_revision = retword; | 6511 | sd->chip_revision = retword; |
@@ -6515,7 +6516,7 @@ static int vga_3wr_probe(struct gspca_dev *gspca_dev) | |||
6515 | } | 6516 | } |
6516 | } | 6517 | } |
6517 | 6518 | ||
6518 | reg_w(dev, 0x01, 0x0000); /* check ?? */ | 6519 | reg_w(dev, 0x01, 0x0000); /* check PB0330 */ |
6519 | reg_w(dev, 0x01, 0x0001); | 6520 | reg_w(dev, 0x01, 0x0001); |
6520 | reg_w(dev, 0xdd, 0x008b); | 6521 | reg_w(dev, 0xdd, 0x008b); |
6521 | reg_w(dev, 0x0a, 0x0010); | 6522 | reg_w(dev, 0x0a, 0x0010); |
@@ -6524,7 +6525,7 @@ static int vga_3wr_probe(struct gspca_dev *gspca_dev) | |||
6524 | retword = i2c_read(gspca_dev, 0x00); | 6525 | retword = i2c_read(gspca_dev, 0x00); |
6525 | if (retword != 0) { | 6526 | if (retword != 0) { |
6526 | PDEBUG(D_PROBE, "probe 3wr vga type 0a ?"); | 6527 | PDEBUG(D_PROBE, "probe 3wr vga type 0a ?"); |
6527 | return 0x0a; /* ?? */ | 6528 | return 0x0a; /* PB0330 */ |
6528 | } | 6529 | } |
6529 | 6530 | ||
6530 | reg_w(dev, 0x01, 0x0000); | 6531 | reg_w(dev, 0x01, 0x0000); |
@@ -6673,6 +6674,10 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
6673 | PDEBUG(D_PROBE, "Find Sensor HV7131B"); | 6674 | PDEBUG(D_PROBE, "Find Sensor HV7131B"); |
6674 | sd->sensor = SENSOR_HV7131B; | 6675 | sd->sensor = SENSOR_HV7131B; |
6675 | break; | 6676 | break; |
6677 | case 0x02: | ||
6678 | PDEBUG(D_PROBE, "Sensor TAS5130C"); | ||
6679 | sd->sensor = SENSOR_TAS5130CXX; | ||
6680 | break; | ||
6676 | case 0x04: | 6681 | case 0x04: |
6677 | PDEBUG(D_PROBE, "Find Sensor CS2102"); | 6682 | PDEBUG(D_PROBE, "Find Sensor CS2102"); |
6678 | sd->sensor = SENSOR_CS2102; | 6683 | sd->sensor = SENSOR_CS2102; |
@@ -6866,11 +6871,14 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
6866 | case SENSOR_GC0305: | 6871 | case SENSOR_GC0305: |
6867 | case SENSOR_OV7620: | 6872 | case SENSOR_OV7620: |
6868 | case SENSOR_PO2030: | 6873 | case SENSOR_PO2030: |
6874 | case SENSOR_TAS5130CXX: | ||
6869 | case SENSOR_TAS5130C_VF0250: | 6875 | case SENSOR_TAS5130C_VF0250: |
6870 | /* msleep(100); * ?? */ | 6876 | /* msleep(100); * ?? */ |
6871 | reg_r(gspca_dev, 0x0002); /* --> 0x40 */ | 6877 | reg_r(gspca_dev, 0x0002); /* --> 0x40 */ |
6872 | reg_w(dev, 0x09, 0x01ad); /* (from win traces) */ | 6878 | reg_w(dev, 0x09, 0x01ad); /* (from win traces) */ |
6873 | reg_w(dev, 0x15, 0x01ae); | 6879 | reg_w(dev, 0x15, 0x01ae); |
6880 | if (sd->sensor == SENSOR_TAS5130CXX) | ||
6881 | break; | ||
6874 | reg_w(dev, 0x0d, 0x003a); | 6882 | reg_w(dev, 0x0d, 0x003a); |
6875 | reg_w(dev, 0x02, 0x003b); | 6883 | reg_w(dev, 0x02, 0x003b); |
6876 | reg_w(dev, 0x00, 0x0038); | 6884 | reg_w(dev, 0x00, 0x0038); |
@@ -6887,6 +6895,7 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
6887 | break; | 6895 | break; |
6888 | case SENSOR_PAS202B: | 6896 | case SENSOR_PAS202B: |
6889 | case SENSOR_GC0305: | 6897 | case SENSOR_GC0305: |
6898 | case SENSOR_TAS5130CXX: | ||
6890 | reg_r(gspca_dev, 0x0008); | 6899 | reg_r(gspca_dev, 0x0008); |
6891 | /* fall thru */ | 6900 | /* fall thru */ |
6892 | case SENSOR_PO2030: | 6901 | case SENSOR_PO2030: |
@@ -6928,6 +6937,7 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
6928 | reg_w(dev, 0x40, 0x0117); | 6937 | reg_w(dev, 0x40, 0x0117); |
6929 | break; | 6938 | break; |
6930 | case SENSOR_GC0305: | 6939 | case SENSOR_GC0305: |
6940 | case SENSOR_TAS5130CXX: | ||
6931 | reg_w(dev, 0x09, 0x01ad); /* (from win traces) */ | 6941 | reg_w(dev, 0x09, 0x01ad); /* (from win traces) */ |
6932 | reg_w(dev, 0x15, 0x01ae); | 6942 | reg_w(dev, 0x15, 0x01ae); |
6933 | /* fall thru */ | 6943 | /* fall thru */ |
@@ -7220,7 +7230,7 @@ static const __devinitdata struct usb_device_id device_table[] = { | |||
7220 | {USB_DEVICE(0x0ac8, 0x0302), .driver_info = SENSOR_PAS106}, | 7230 | {USB_DEVICE(0x0ac8, 0x0302), .driver_info = SENSOR_PAS106}, |
7221 | {USB_DEVICE(0x0ac8, 0x301b)}, | 7231 | {USB_DEVICE(0x0ac8, 0x301b)}, |
7222 | {USB_DEVICE(0x0ac8, 0x303b)}, | 7232 | {USB_DEVICE(0x0ac8, 0x303b)}, |
7223 | {USB_DEVICE(0x0ac8, 0x305b), .driver_info = SENSOR_TAS5130C_VF0250}, | 7233 | {USB_DEVICE(0x0ac8, 0x305b)}, |
7224 | {USB_DEVICE(0x0ac8, 0x307b)}, | 7234 | {USB_DEVICE(0x0ac8, 0x307b)}, |
7225 | {USB_DEVICE(0x10fd, 0x0128)}, | 7235 | {USB_DEVICE(0x10fd, 0x0128)}, |
7226 | {USB_DEVICE(0x10fd, 0x804d)}, | 7236 | {USB_DEVICE(0x10fd, 0x804d)}, |
diff --git a/drivers/media/video/hdpvr/hdpvr-core.c b/drivers/media/video/hdpvr/hdpvr-core.c index 1c9bc94c905c..51f393d03a46 100644 --- a/drivers/media/video/hdpvr/hdpvr-core.c +++ b/drivers/media/video/hdpvr/hdpvr-core.c | |||
@@ -145,7 +145,7 @@ static int device_authorization(struct hdpvr_device *dev) | |||
145 | #ifdef HDPVR_DEBUG | 145 | #ifdef HDPVR_DEBUG |
146 | else { | 146 | else { |
147 | hex_dump_to_buffer(dev->usbc_buf, 46, 16, 1, print_buf, | 147 | hex_dump_to_buffer(dev->usbc_buf, 46, 16, 1, print_buf, |
148 | sizeof(print_buf), 0); | 148 | 5*buf_size+1, 0); |
149 | v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, | 149 | v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, |
150 | "Status request returned, len %d: %s\n", | 150 | "Status request returned, len %d: %s\n", |
151 | ret, print_buf); | 151 | ret, print_buf); |
@@ -168,13 +168,13 @@ static int device_authorization(struct hdpvr_device *dev) | |||
168 | 168 | ||
169 | response = dev->usbc_buf+38; | 169 | response = dev->usbc_buf+38; |
170 | #ifdef HDPVR_DEBUG | 170 | #ifdef HDPVR_DEBUG |
171 | hex_dump_to_buffer(response, 8, 16, 1, print_buf, sizeof(print_buf), 0); | 171 | hex_dump_to_buffer(response, 8, 16, 1, print_buf, 5*buf_size+1, 0); |
172 | v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, "challenge: %s\n", | 172 | v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, "challenge: %s\n", |
173 | print_buf); | 173 | print_buf); |
174 | #endif | 174 | #endif |
175 | challenge(response); | 175 | challenge(response); |
176 | #ifdef HDPVR_DEBUG | 176 | #ifdef HDPVR_DEBUG |
177 | hex_dump_to_buffer(response, 8, 16, 1, print_buf, sizeof(print_buf), 0); | 177 | hex_dump_to_buffer(response, 8, 16, 1, print_buf, 5*buf_size+1, 0); |
178 | v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, " response: %s\n", | 178 | v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, " response: %s\n", |
179 | print_buf); | 179 | print_buf); |
180 | #endif | 180 | #endif |
@@ -376,8 +376,8 @@ static int hdpvr_probe(struct usb_interface *interface, | |||
376 | usb_set_intfdata(interface, dev); | 376 | usb_set_intfdata(interface, dev); |
377 | 377 | ||
378 | /* let the user know what node this device is now attached to */ | 378 | /* let the user know what node this device is now attached to */ |
379 | v4l2_info(&dev->v4l2_dev, "device now attached to /dev/video%d\n", | 379 | v4l2_info(&dev->v4l2_dev, "device now attached to %s\n", |
380 | dev->video_dev->minor); | 380 | video_device_node_name(dev->video_dev)); |
381 | return 0; | 381 | return 0; |
382 | 382 | ||
383 | error: | 383 | error: |
@@ -391,13 +391,10 @@ error: | |||
391 | static void hdpvr_disconnect(struct usb_interface *interface) | 391 | static void hdpvr_disconnect(struct usb_interface *interface) |
392 | { | 392 | { |
393 | struct hdpvr_device *dev; | 393 | struct hdpvr_device *dev; |
394 | int minor; | ||
395 | 394 | ||
396 | dev = usb_get_intfdata(interface); | 395 | dev = usb_get_intfdata(interface); |
397 | usb_set_intfdata(interface, NULL); | 396 | usb_set_intfdata(interface, NULL); |
398 | 397 | ||
399 | minor = dev->video_dev->minor; | ||
400 | |||
401 | /* prevent more I/O from starting and stop any ongoing */ | 398 | /* prevent more I/O from starting and stop any ongoing */ |
402 | mutex_lock(&dev->io_mutex); | 399 | mutex_lock(&dev->io_mutex); |
403 | dev->status = STATUS_DISCONNECTED; | 400 | dev->status = STATUS_DISCONNECTED; |
@@ -425,7 +422,8 @@ static void hdpvr_disconnect(struct usb_interface *interface) | |||
425 | 422 | ||
426 | atomic_dec(&dev_nr); | 423 | atomic_dec(&dev_nr); |
427 | 424 | ||
428 | v4l2_info(&dev->v4l2_dev, "device /dev/video%d disconnected\n", minor); | 425 | v4l2_info(&dev->v4l2_dev, "device %s disconnected\n", |
426 | video_device_node_name(dev->video_dev)); | ||
429 | 427 | ||
430 | v4l2_device_unregister(&dev->v4l2_dev); | 428 | v4l2_device_unregister(&dev->v4l2_dev); |
431 | kfree(dev->usbc_buf); | 429 | kfree(dev->usbc_buf); |
diff --git a/drivers/media/video/hdpvr/hdpvr-video.c b/drivers/media/video/hdpvr/hdpvr-video.c index b5439cabb381..fdd782039e9d 100644 --- a/drivers/media/video/hdpvr/hdpvr-video.c +++ b/drivers/media/video/hdpvr/hdpvr-video.c | |||
@@ -523,7 +523,7 @@ static unsigned int hdpvr_poll(struct file *filp, poll_table *wait) | |||
523 | 523 | ||
524 | mutex_lock(&dev->io_mutex); | 524 | mutex_lock(&dev->io_mutex); |
525 | 525 | ||
526 | if (video_is_unregistered(dev->video_dev)) { | 526 | if (!video_is_registered(dev->video_dev)) { |
527 | mutex_unlock(&dev->io_mutex); | 527 | mutex_unlock(&dev->io_mutex); |
528 | return -EIO; | 528 | return -EIO; |
529 | } | 529 | } |
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index 64360d26b32d..b86e35386cee 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c | |||
@@ -353,6 +353,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
353 | ir_type = IR_TYPE_RC5; | 353 | ir_type = IR_TYPE_RC5; |
354 | ir_codes = &ir_codes_fusionhdtv_mce_table; | 354 | ir_codes = &ir_codes_fusionhdtv_mce_table; |
355 | break; | 355 | break; |
356 | case 0x0b: | ||
356 | case 0x47: | 357 | case 0x47: |
357 | case 0x71: | 358 | case 0x71: |
358 | if (adap->id == I2C_HW_B_CX2388x || | 359 | if (adap->id == I2C_HW_B_CX2388x || |
@@ -422,7 +423,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
422 | 423 | ||
423 | /* Make sure we are all setup before going on */ | 424 | /* Make sure we are all setup before going on */ |
424 | if (!name || !ir->get_key || !ir_type || !ir_codes) { | 425 | if (!name || !ir->get_key || !ir_type || !ir_codes) { |
425 | dprintk(1, DEVNAME ": Unsupported device at address 0x%02x\n", | 426 | dprintk(1, ": Unsupported device at address 0x%02x\n", |
426 | addr); | 427 | addr); |
427 | err = -ENODEV; | 428 | err = -ENODEV; |
428 | goto err_out_free; | 429 | goto err_out_free; |
@@ -437,7 +438,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
437 | dev_name(&client->dev)); | 438 | dev_name(&client->dev)); |
438 | 439 | ||
439 | /* init + register input device */ | 440 | /* init + register input device */ |
440 | err = ir_input_init(input_dev, &ir->ir, ir_type, ir->ir_codes); | 441 | err = ir_input_init(input_dev, &ir->ir, ir_type); |
441 | if (err < 0) | 442 | if (err < 0) |
442 | goto err_out_free; | 443 | goto err_out_free; |
443 | 444 | ||
@@ -445,7 +446,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
445 | input_dev->name = ir->name; | 446 | input_dev->name = ir->name; |
446 | input_dev->phys = ir->phys; | 447 | input_dev->phys = ir->phys; |
447 | 448 | ||
448 | err = input_register_device(ir->input); | 449 | err = ir_input_register(ir->input, ir->ir_codes); |
449 | if (err) | 450 | if (err) |
450 | goto err_out_free; | 451 | goto err_out_free; |
451 | 452 | ||
@@ -459,8 +460,6 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
459 | return 0; | 460 | return 0; |
460 | 461 | ||
461 | err_out_free: | 462 | err_out_free: |
462 | ir_input_free(input_dev); | ||
463 | input_free_device(input_dev); | ||
464 | kfree(ir); | 463 | kfree(ir); |
465 | return err; | 464 | return err; |
466 | } | 465 | } |
@@ -473,8 +472,7 @@ static int ir_remove(struct i2c_client *client) | |||
473 | cancel_delayed_work_sync(&ir->work); | 472 | cancel_delayed_work_sync(&ir->work); |
474 | 473 | ||
475 | /* unregister device */ | 474 | /* unregister device */ |
476 | ir_input_free(ir->input); | 475 | ir_input_unregister(ir->input); |
477 | input_unregister_device(ir->input); | ||
478 | 476 | ||
479 | /* free memory */ | 477 | /* free memory */ |
480 | kfree(ir); | 478 | kfree(ir); |
diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c index e707ef3086b2..babcabd73c08 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ b/drivers/media/video/ivtv/ivtv-fileops.c | |||
@@ -985,8 +985,8 @@ int ivtv_v4l2_open(struct file *filp) | |||
985 | 985 | ||
986 | mutex_lock(&itv->serialize_lock); | 986 | mutex_lock(&itv->serialize_lock); |
987 | if (ivtv_init_on_first_open(itv)) { | 987 | if (ivtv_init_on_first_open(itv)) { |
988 | IVTV_ERR("Failed to initialize on minor %d\n", | 988 | IVTV_ERR("Failed to initialize on device %s\n", |
989 | vdev->minor); | 989 | video_device_node_name(vdev)); |
990 | mutex_unlock(&itv->serialize_lock); | 990 | mutex_unlock(&itv->serialize_lock); |
991 | return -ENXIO; | 991 | return -ENXIO; |
992 | } | 992 | } |
diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c index 67699e3f2aaa..e12c6022373e 100644 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ b/drivers/media/video/ivtv/ivtv-streams.c | |||
@@ -245,6 +245,7 @@ static int ivtv_reg_dev(struct ivtv *itv, int type) | |||
245 | { | 245 | { |
246 | struct ivtv_stream *s = &itv->streams[type]; | 246 | struct ivtv_stream *s = &itv->streams[type]; |
247 | int vfl_type = ivtv_stream_info[type].vfl_type; | 247 | int vfl_type = ivtv_stream_info[type].vfl_type; |
248 | const char *name; | ||
248 | int num; | 249 | int num; |
249 | 250 | ||
250 | if (s->vdev == NULL) | 251 | if (s->vdev == NULL) |
@@ -268,24 +269,24 @@ static int ivtv_reg_dev(struct ivtv *itv, int type) | |||
268 | s->vdev = NULL; | 269 | s->vdev = NULL; |
269 | return -ENOMEM; | 270 | return -ENOMEM; |
270 | } | 271 | } |
271 | num = s->vdev->num; | 272 | name = video_device_node_name(s->vdev); |
272 | 273 | ||
273 | switch (vfl_type) { | 274 | switch (vfl_type) { |
274 | case VFL_TYPE_GRABBER: | 275 | case VFL_TYPE_GRABBER: |
275 | IVTV_INFO("Registered device video%d for %s (%d kB)\n", | 276 | IVTV_INFO("Registered device %s for %s (%d kB)\n", |
276 | num, s->name, itv->options.kilobytes[type]); | 277 | name, s->name, itv->options.kilobytes[type]); |
277 | break; | 278 | break; |
278 | case VFL_TYPE_RADIO: | 279 | case VFL_TYPE_RADIO: |
279 | IVTV_INFO("Registered device radio%d for %s\n", | 280 | IVTV_INFO("Registered device %s for %s\n", |
280 | num, s->name); | 281 | name, s->name); |
281 | break; | 282 | break; |
282 | case VFL_TYPE_VBI: | 283 | case VFL_TYPE_VBI: |
283 | if (itv->options.kilobytes[type]) | 284 | if (itv->options.kilobytes[type]) |
284 | IVTV_INFO("Registered device vbi%d for %s (%d kB)\n", | 285 | IVTV_INFO("Registered device %s for %s (%d kB)\n", |
285 | num, s->name, itv->options.kilobytes[type]); | 286 | name, s->name, itv->options.kilobytes[type]); |
286 | else | 287 | else |
287 | IVTV_INFO("Registered device vbi%d for %s\n", | 288 | IVTV_INFO("Registered device %s for %s\n", |
288 | num, s->name); | 289 | name, s->name); |
289 | break; | 290 | break; |
290 | } | 291 | } |
291 | return 0; | 292 | return 0; |
diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c index 01e1eefcf1eb..b421858ccf90 100644 --- a/drivers/media/video/meye.c +++ b/drivers/media/video/meye.c | |||
@@ -800,8 +800,8 @@ again: | |||
800 | return IRQ_HANDLED; | 800 | return IRQ_HANDLED; |
801 | 801 | ||
802 | if (meye.mchip_mode == MCHIP_HIC_MODE_CONT_OUT) { | 802 | if (meye.mchip_mode == MCHIP_HIC_MODE_CONT_OUT) { |
803 | if (kfifo_get(meye.grabq, (unsigned char *)&reqnr, | 803 | if (kfifo_out_locked(&meye.grabq, (unsigned char *)&reqnr, |
804 | sizeof(int)) != sizeof(int)) { | 804 | sizeof(int), &meye.grabq_lock) != sizeof(int)) { |
805 | mchip_free_frame(); | 805 | mchip_free_frame(); |
806 | return IRQ_HANDLED; | 806 | return IRQ_HANDLED; |
807 | } | 807 | } |
@@ -811,7 +811,8 @@ again: | |||
811 | meye.grab_buffer[reqnr].state = MEYE_BUF_DONE; | 811 | meye.grab_buffer[reqnr].state = MEYE_BUF_DONE; |
812 | do_gettimeofday(&meye.grab_buffer[reqnr].timestamp); | 812 | do_gettimeofday(&meye.grab_buffer[reqnr].timestamp); |
813 | meye.grab_buffer[reqnr].sequence = sequence++; | 813 | meye.grab_buffer[reqnr].sequence = sequence++; |
814 | kfifo_put(meye.doneq, (unsigned char *)&reqnr, sizeof(int)); | 814 | kfifo_in_locked(&meye.doneq, (unsigned char *)&reqnr, |
815 | sizeof(int), &meye.doneq_lock); | ||
815 | wake_up_interruptible(&meye.proc_list); | 816 | wake_up_interruptible(&meye.proc_list); |
816 | } else { | 817 | } else { |
817 | int size; | 818 | int size; |
@@ -820,8 +821,8 @@ again: | |||
820 | mchip_free_frame(); | 821 | mchip_free_frame(); |
821 | goto again; | 822 | goto again; |
822 | } | 823 | } |
823 | if (kfifo_get(meye.grabq, (unsigned char *)&reqnr, | 824 | if (kfifo_out_locked(&meye.grabq, (unsigned char *)&reqnr, |
824 | sizeof(int)) != sizeof(int)) { | 825 | sizeof(int), &meye.grabq_lock) != sizeof(int)) { |
825 | mchip_free_frame(); | 826 | mchip_free_frame(); |
826 | goto again; | 827 | goto again; |
827 | } | 828 | } |
@@ -831,7 +832,8 @@ again: | |||
831 | meye.grab_buffer[reqnr].state = MEYE_BUF_DONE; | 832 | meye.grab_buffer[reqnr].state = MEYE_BUF_DONE; |
832 | do_gettimeofday(&meye.grab_buffer[reqnr].timestamp); | 833 | do_gettimeofday(&meye.grab_buffer[reqnr].timestamp); |
833 | meye.grab_buffer[reqnr].sequence = sequence++; | 834 | meye.grab_buffer[reqnr].sequence = sequence++; |
834 | kfifo_put(meye.doneq, (unsigned char *)&reqnr, sizeof(int)); | 835 | kfifo_in_locked(&meye.doneq, (unsigned char *)&reqnr, |
836 | sizeof(int), &meye.doneq_lock); | ||
835 | wake_up_interruptible(&meye.proc_list); | 837 | wake_up_interruptible(&meye.proc_list); |
836 | } | 838 | } |
837 | mchip_free_frame(); | 839 | mchip_free_frame(); |
@@ -859,8 +861,8 @@ static int meye_open(struct file *file) | |||
859 | 861 | ||
860 | for (i = 0; i < MEYE_MAX_BUFNBRS; i++) | 862 | for (i = 0; i < MEYE_MAX_BUFNBRS; i++) |
861 | meye.grab_buffer[i].state = MEYE_BUF_UNUSED; | 863 | meye.grab_buffer[i].state = MEYE_BUF_UNUSED; |
862 | kfifo_reset(meye.grabq); | 864 | kfifo_reset(&meye.grabq); |
863 | kfifo_reset(meye.doneq); | 865 | kfifo_reset(&meye.doneq); |
864 | return 0; | 866 | return 0; |
865 | } | 867 | } |
866 | 868 | ||
@@ -933,7 +935,8 @@ static int meyeioc_qbuf_capt(int *nb) | |||
933 | mchip_cont_compression_start(); | 935 | mchip_cont_compression_start(); |
934 | 936 | ||
935 | meye.grab_buffer[*nb].state = MEYE_BUF_USING; | 937 | meye.grab_buffer[*nb].state = MEYE_BUF_USING; |
936 | kfifo_put(meye.grabq, (unsigned char *)nb, sizeof(int)); | 938 | kfifo_in_locked(&meye.grabq, (unsigned char *)nb, sizeof(int), |
939 | &meye.grabq_lock); | ||
937 | mutex_unlock(&meye.lock); | 940 | mutex_unlock(&meye.lock); |
938 | 941 | ||
939 | return 0; | 942 | return 0; |
@@ -965,7 +968,9 @@ static int meyeioc_sync(struct file *file, void *fh, int *i) | |||
965 | /* fall through */ | 968 | /* fall through */ |
966 | case MEYE_BUF_DONE: | 969 | case MEYE_BUF_DONE: |
967 | meye.grab_buffer[*i].state = MEYE_BUF_UNUSED; | 970 | meye.grab_buffer[*i].state = MEYE_BUF_UNUSED; |
968 | kfifo_get(meye.doneq, (unsigned char *)&unused, sizeof(int)); | 971 | if (kfifo_out_locked(&meye.doneq, (unsigned char *)&unused, |
972 | sizeof(int), &meye.doneq_lock) != sizeof(int)) | ||
973 | break; | ||
969 | } | 974 | } |
970 | *i = meye.grab_buffer[*i].size; | 975 | *i = meye.grab_buffer[*i].size; |
971 | mutex_unlock(&meye.lock); | 976 | mutex_unlock(&meye.lock); |
@@ -1452,7 +1457,8 @@ static int vidioc_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf) | |||
1452 | buf->flags |= V4L2_BUF_FLAG_QUEUED; | 1457 | buf->flags |= V4L2_BUF_FLAG_QUEUED; |
1453 | buf->flags &= ~V4L2_BUF_FLAG_DONE; | 1458 | buf->flags &= ~V4L2_BUF_FLAG_DONE; |
1454 | meye.grab_buffer[buf->index].state = MEYE_BUF_USING; | 1459 | meye.grab_buffer[buf->index].state = MEYE_BUF_USING; |
1455 | kfifo_put(meye.grabq, (unsigned char *)&buf->index, sizeof(int)); | 1460 | kfifo_in_locked(&meye.grabq, (unsigned char *)&buf->index, |
1461 | sizeof(int), &meye.grabq_lock); | ||
1456 | mutex_unlock(&meye.lock); | 1462 | mutex_unlock(&meye.lock); |
1457 | 1463 | ||
1458 | return 0; | 1464 | return 0; |
@@ -1467,19 +1473,19 @@ static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf) | |||
1467 | 1473 | ||
1468 | mutex_lock(&meye.lock); | 1474 | mutex_lock(&meye.lock); |
1469 | 1475 | ||
1470 | if (kfifo_len(meye.doneq) == 0 && file->f_flags & O_NONBLOCK) { | 1476 | if (kfifo_len(&meye.doneq) == 0 && file->f_flags & O_NONBLOCK) { |
1471 | mutex_unlock(&meye.lock); | 1477 | mutex_unlock(&meye.lock); |
1472 | return -EAGAIN; | 1478 | return -EAGAIN; |
1473 | } | 1479 | } |
1474 | 1480 | ||
1475 | if (wait_event_interruptible(meye.proc_list, | 1481 | if (wait_event_interruptible(meye.proc_list, |
1476 | kfifo_len(meye.doneq) != 0) < 0) { | 1482 | kfifo_len(&meye.doneq) != 0) < 0) { |
1477 | mutex_unlock(&meye.lock); | 1483 | mutex_unlock(&meye.lock); |
1478 | return -EINTR; | 1484 | return -EINTR; |
1479 | } | 1485 | } |
1480 | 1486 | ||
1481 | if (!kfifo_get(meye.doneq, (unsigned char *)&reqnr, | 1487 | if (!kfifo_out_locked(&meye.doneq, (unsigned char *)&reqnr, |
1482 | sizeof(int))) { | 1488 | sizeof(int), &meye.doneq_lock)) { |
1483 | mutex_unlock(&meye.lock); | 1489 | mutex_unlock(&meye.lock); |
1484 | return -EBUSY; | 1490 | return -EBUSY; |
1485 | } | 1491 | } |
@@ -1529,8 +1535,8 @@ static int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i) | |||
1529 | { | 1535 | { |
1530 | mutex_lock(&meye.lock); | 1536 | mutex_lock(&meye.lock); |
1531 | mchip_hic_stop(); | 1537 | mchip_hic_stop(); |
1532 | kfifo_reset(meye.grabq); | 1538 | kfifo_reset(&meye.grabq); |
1533 | kfifo_reset(meye.doneq); | 1539 | kfifo_reset(&meye.doneq); |
1534 | 1540 | ||
1535 | for (i = 0; i < MEYE_MAX_BUFNBRS; i++) | 1541 | for (i = 0; i < MEYE_MAX_BUFNBRS; i++) |
1536 | meye.grab_buffer[i].state = MEYE_BUF_UNUSED; | 1542 | meye.grab_buffer[i].state = MEYE_BUF_UNUSED; |
@@ -1572,7 +1578,7 @@ static unsigned int meye_poll(struct file *file, poll_table *wait) | |||
1572 | 1578 | ||
1573 | mutex_lock(&meye.lock); | 1579 | mutex_lock(&meye.lock); |
1574 | poll_wait(file, &meye.proc_list, wait); | 1580 | poll_wait(file, &meye.proc_list, wait); |
1575 | if (kfifo_len(meye.doneq)) | 1581 | if (kfifo_len(&meye.doneq)) |
1576 | res = POLLIN | POLLRDNORM; | 1582 | res = POLLIN | POLLRDNORM; |
1577 | mutex_unlock(&meye.lock); | 1583 | mutex_unlock(&meye.lock); |
1578 | return res; | 1584 | return res; |
@@ -1681,7 +1687,6 @@ static struct video_device meye_template = { | |||
1681 | .fops = &meye_fops, | 1687 | .fops = &meye_fops, |
1682 | .ioctl_ops = &meye_ioctl_ops, | 1688 | .ioctl_ops = &meye_ioctl_ops, |
1683 | .release = video_device_release, | 1689 | .release = video_device_release, |
1684 | .minor = -1, | ||
1685 | }; | 1690 | }; |
1686 | 1691 | ||
1687 | #ifdef CONFIG_PM | 1692 | #ifdef CONFIG_PM |
@@ -1746,16 +1751,14 @@ static int __devinit meye_probe(struct pci_dev *pcidev, | |||
1746 | } | 1751 | } |
1747 | 1752 | ||
1748 | spin_lock_init(&meye.grabq_lock); | 1753 | spin_lock_init(&meye.grabq_lock); |
1749 | meye.grabq = kfifo_alloc(sizeof(int) * MEYE_MAX_BUFNBRS, GFP_KERNEL, | 1754 | if (kfifo_alloc(&meye.grabq, sizeof(int) * MEYE_MAX_BUFNBRS, |
1750 | &meye.grabq_lock); | 1755 | GFP_KERNEL)) { |
1751 | if (IS_ERR(meye.grabq)) { | ||
1752 | printk(KERN_ERR "meye: fifo allocation failed\n"); | 1756 | printk(KERN_ERR "meye: fifo allocation failed\n"); |
1753 | goto outkfifoalloc1; | 1757 | goto outkfifoalloc1; |
1754 | } | 1758 | } |
1755 | spin_lock_init(&meye.doneq_lock); | 1759 | spin_lock_init(&meye.doneq_lock); |
1756 | meye.doneq = kfifo_alloc(sizeof(int) * MEYE_MAX_BUFNBRS, GFP_KERNEL, | 1760 | if (kfifo_alloc(&meye.doneq, sizeof(int) * MEYE_MAX_BUFNBRS, |
1757 | &meye.doneq_lock); | 1761 | GFP_KERNEL)) { |
1758 | if (IS_ERR(meye.doneq)) { | ||
1759 | printk(KERN_ERR "meye: fifo allocation failed\n"); | 1762 | printk(KERN_ERR "meye: fifo allocation failed\n"); |
1760 | goto outkfifoalloc2; | 1763 | goto outkfifoalloc2; |
1761 | } | 1764 | } |
@@ -1869,9 +1872,9 @@ outregions: | |||
1869 | outenabledev: | 1872 | outenabledev: |
1870 | sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 0); | 1873 | sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 0); |
1871 | outsonypienable: | 1874 | outsonypienable: |
1872 | kfifo_free(meye.doneq); | 1875 | kfifo_free(&meye.doneq); |
1873 | outkfifoalloc2: | 1876 | outkfifoalloc2: |
1874 | kfifo_free(meye.grabq); | 1877 | kfifo_free(&meye.grabq); |
1875 | outkfifoalloc1: | 1878 | outkfifoalloc1: |
1876 | vfree(meye.grab_temp); | 1879 | vfree(meye.grab_temp); |
1877 | outvmalloc: | 1880 | outvmalloc: |
@@ -1902,8 +1905,8 @@ static void __devexit meye_remove(struct pci_dev *pcidev) | |||
1902 | 1905 | ||
1903 | sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 0); | 1906 | sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 0); |
1904 | 1907 | ||
1905 | kfifo_free(meye.doneq); | 1908 | kfifo_free(&meye.doneq); |
1906 | kfifo_free(meye.grabq); | 1909 | kfifo_free(&meye.grabq); |
1907 | 1910 | ||
1908 | vfree(meye.grab_temp); | 1911 | vfree(meye.grab_temp); |
1909 | 1912 | ||
diff --git a/drivers/media/video/meye.h b/drivers/media/video/meye.h index 5f70a106ba2b..1321ad5d6597 100644 --- a/drivers/media/video/meye.h +++ b/drivers/media/video/meye.h | |||
@@ -303,9 +303,9 @@ struct meye { | |||
303 | struct meye_grab_buffer grab_buffer[MEYE_MAX_BUFNBRS]; | 303 | struct meye_grab_buffer grab_buffer[MEYE_MAX_BUFNBRS]; |
304 | int vma_use_count[MEYE_MAX_BUFNBRS]; /* mmap count */ | 304 | int vma_use_count[MEYE_MAX_BUFNBRS]; /* mmap count */ |
305 | struct mutex lock; /* mutex for open/mmap... */ | 305 | struct mutex lock; /* mutex for open/mmap... */ |
306 | struct kfifo *grabq; /* queue for buffers to be grabbed */ | 306 | struct kfifo grabq; /* queue for buffers to be grabbed */ |
307 | spinlock_t grabq_lock; /* lock protecting the queue */ | 307 | spinlock_t grabq_lock; /* lock protecting the queue */ |
308 | struct kfifo *doneq; /* queue for grabbed buffers */ | 308 | struct kfifo doneq; /* queue for grabbed buffers */ |
309 | spinlock_t doneq_lock; /* lock protecting the queue */ | 309 | spinlock_t doneq_lock; /* lock protecting the queue */ |
310 | wait_queue_head_t proc_list; /* wait queue */ | 310 | wait_queue_head_t proc_list; /* wait queue */ |
311 | struct video_device *video_dev; /* video device parameters */ | 311 | struct video_device *video_dev; /* video device parameters */ |
diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c index 45388d2ce2fd..b62c0bd3f8ea 100644 --- a/drivers/media/video/mt9m001.c +++ b/drivers/media/video/mt9m001.c | |||
@@ -17,9 +17,11 @@ | |||
17 | #include <media/v4l2-chip-ident.h> | 17 | #include <media/v4l2-chip-ident.h> |
18 | #include <media/soc_camera.h> | 18 | #include <media/soc_camera.h> |
19 | 19 | ||
20 | /* mt9m001 i2c address 0x5d | 20 | /* |
21 | * mt9m001 i2c address 0x5d | ||
21 | * The platform has to define ctruct i2c_board_info objects and link to them | 22 | * The platform has to define ctruct i2c_board_info objects and link to them |
22 | * from struct soc_camera_link */ | 23 | * from struct soc_camera_link |
24 | */ | ||
23 | 25 | ||
24 | /* mt9m001 selected register addresses */ | 26 | /* mt9m001 selected register addresses */ |
25 | #define MT9M001_CHIP_VERSION 0x00 | 27 | #define MT9M001_CHIP_VERSION 0x00 |
@@ -46,42 +48,50 @@ | |||
46 | #define MT9M001_COLUMN_SKIP 20 | 48 | #define MT9M001_COLUMN_SKIP 20 |
47 | #define MT9M001_ROW_SKIP 12 | 49 | #define MT9M001_ROW_SKIP 12 |
48 | 50 | ||
49 | static const struct soc_camera_data_format mt9m001_colour_formats[] = { | 51 | /* MT9M001 has only one fixed colorspace per pixelcode */ |
50 | /* Order important: first natively supported, | 52 | struct mt9m001_datafmt { |
51 | * second supported with a GPIO extender */ | 53 | enum v4l2_mbus_pixelcode code; |
52 | { | 54 | enum v4l2_colorspace colorspace; |
53 | .name = "Bayer (sRGB) 10 bit", | 55 | }; |
54 | .depth = 10, | 56 | |
55 | .fourcc = V4L2_PIX_FMT_SBGGR16, | 57 | /* Find a data format by a pixel code in an array */ |
56 | .colorspace = V4L2_COLORSPACE_SRGB, | 58 | static const struct mt9m001_datafmt *mt9m001_find_datafmt( |
57 | }, { | 59 | enum v4l2_mbus_pixelcode code, const struct mt9m001_datafmt *fmt, |
58 | .name = "Bayer (sRGB) 8 bit", | 60 | int n) |
59 | .depth = 8, | 61 | { |
60 | .fourcc = V4L2_PIX_FMT_SBGGR8, | 62 | int i; |
61 | .colorspace = V4L2_COLORSPACE_SRGB, | 63 | for (i = 0; i < n; i++) |
62 | } | 64 | if (fmt[i].code == code) |
65 | return fmt + i; | ||
66 | |||
67 | return NULL; | ||
68 | } | ||
69 | |||
70 | static const struct mt9m001_datafmt mt9m001_colour_fmts[] = { | ||
71 | /* | ||
72 | * Order important: first natively supported, | ||
73 | * second supported with a GPIO extender | ||
74 | */ | ||
75 | {V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_COLORSPACE_SRGB}, | ||
76 | {V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB}, | ||
63 | }; | 77 | }; |
64 | 78 | ||
65 | static const struct soc_camera_data_format mt9m001_monochrome_formats[] = { | 79 | static const struct mt9m001_datafmt mt9m001_monochrome_fmts[] = { |
66 | /* Order important - see above */ | 80 | /* Order important - see above */ |
67 | { | 81 | {V4L2_MBUS_FMT_Y10_1X10, V4L2_COLORSPACE_JPEG}, |
68 | .name = "Monochrome 10 bit", | 82 | {V4L2_MBUS_FMT_GREY8_1X8, V4L2_COLORSPACE_JPEG}, |
69 | .depth = 10, | ||
70 | .fourcc = V4L2_PIX_FMT_Y16, | ||
71 | }, { | ||
72 | .name = "Monochrome 8 bit", | ||
73 | .depth = 8, | ||
74 | .fourcc = V4L2_PIX_FMT_GREY, | ||
75 | }, | ||
76 | }; | 83 | }; |
77 | 84 | ||
78 | struct mt9m001 { | 85 | struct mt9m001 { |
79 | struct v4l2_subdev subdev; | 86 | struct v4l2_subdev subdev; |
80 | struct v4l2_rect rect; /* Sensor window */ | 87 | struct v4l2_rect rect; /* Sensor window */ |
81 | __u32 fourcc; | 88 | const struct mt9m001_datafmt *fmt; |
89 | const struct mt9m001_datafmt *fmts; | ||
90 | int num_fmts; | ||
82 | int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */ | 91 | int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */ |
83 | unsigned int gain; | 92 | unsigned int gain; |
84 | unsigned int exposure; | 93 | unsigned int exposure; |
94 | unsigned short y_skip_top; /* Lines to skip at the top */ | ||
85 | unsigned char autoexposure; | 95 | unsigned char autoexposure; |
86 | }; | 96 | }; |
87 | 97 | ||
@@ -204,8 +214,7 @@ static int mt9m001_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) | |||
204 | const u16 hblank = 9, vblank = 25; | 214 | const u16 hblank = 9, vblank = 25; |
205 | unsigned int total_h; | 215 | unsigned int total_h; |
206 | 216 | ||
207 | if (mt9m001->fourcc == V4L2_PIX_FMT_SBGGR8 || | 217 | if (mt9m001->fmts == mt9m001_colour_fmts) |
208 | mt9m001->fourcc == V4L2_PIX_FMT_SBGGR16) | ||
209 | /* | 218 | /* |
210 | * Bayer format - even number of rows for simplicity, | 219 | * Bayer format - even number of rows for simplicity, |
211 | * but let the user play with the top row. | 220 | * but let the user play with the top row. |
@@ -222,15 +231,17 @@ static int mt9m001_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) | |||
222 | soc_camera_limit_side(&rect.top, &rect.height, | 231 | soc_camera_limit_side(&rect.top, &rect.height, |
223 | MT9M001_ROW_SKIP, MT9M001_MIN_HEIGHT, MT9M001_MAX_HEIGHT); | 232 | MT9M001_ROW_SKIP, MT9M001_MIN_HEIGHT, MT9M001_MAX_HEIGHT); |
224 | 233 | ||
225 | total_h = rect.height + icd->y_skip_top + vblank; | 234 | total_h = rect.height + mt9m001->y_skip_top + vblank; |
226 | 235 | ||
227 | /* Blanking and start values - default... */ | 236 | /* Blanking and start values - default... */ |
228 | ret = reg_write(client, MT9M001_HORIZONTAL_BLANKING, hblank); | 237 | ret = reg_write(client, MT9M001_HORIZONTAL_BLANKING, hblank); |
229 | if (!ret) | 238 | if (!ret) |
230 | ret = reg_write(client, MT9M001_VERTICAL_BLANKING, vblank); | 239 | ret = reg_write(client, MT9M001_VERTICAL_BLANKING, vblank); |
231 | 240 | ||
232 | /* The caller provides a supported format, as verified per | 241 | /* |
233 | * call to icd->try_fmt() */ | 242 | * The caller provides a supported format, as verified per |
243 | * call to icd->try_fmt() | ||
244 | */ | ||
234 | if (!ret) | 245 | if (!ret) |
235 | ret = reg_write(client, MT9M001_COLUMN_START, rect.left); | 246 | ret = reg_write(client, MT9M001_COLUMN_START, rect.left); |
236 | if (!ret) | 247 | if (!ret) |
@@ -239,7 +250,7 @@ static int mt9m001_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) | |||
239 | ret = reg_write(client, MT9M001_WINDOW_WIDTH, rect.width - 1); | 250 | ret = reg_write(client, MT9M001_WINDOW_WIDTH, rect.width - 1); |
240 | if (!ret) | 251 | if (!ret) |
241 | ret = reg_write(client, MT9M001_WINDOW_HEIGHT, | 252 | ret = reg_write(client, MT9M001_WINDOW_HEIGHT, |
242 | rect.height + icd->y_skip_top - 1); | 253 | rect.height + mt9m001->y_skip_top - 1); |
243 | if (!ret && mt9m001->autoexposure) { | 254 | if (!ret && mt9m001->autoexposure) { |
244 | ret = reg_write(client, MT9M001_SHUTTER_WIDTH, total_h); | 255 | ret = reg_write(client, MT9M001_SHUTTER_WIDTH, total_h); |
245 | if (!ret) { | 256 | if (!ret) { |
@@ -283,32 +294,32 @@ static int mt9m001_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) | |||
283 | return 0; | 294 | return 0; |
284 | } | 295 | } |
285 | 296 | ||
286 | static int mt9m001_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | 297 | static int mt9m001_g_fmt(struct v4l2_subdev *sd, |
298 | struct v4l2_mbus_framefmt *mf) | ||
287 | { | 299 | { |
288 | struct i2c_client *client = sd->priv; | 300 | struct i2c_client *client = sd->priv; |
289 | struct mt9m001 *mt9m001 = to_mt9m001(client); | 301 | struct mt9m001 *mt9m001 = to_mt9m001(client); |
290 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
291 | 302 | ||
292 | pix->width = mt9m001->rect.width; | 303 | mf->width = mt9m001->rect.width; |
293 | pix->height = mt9m001->rect.height; | 304 | mf->height = mt9m001->rect.height; |
294 | pix->pixelformat = mt9m001->fourcc; | 305 | mf->code = mt9m001->fmt->code; |
295 | pix->field = V4L2_FIELD_NONE; | 306 | mf->colorspace = mt9m001->fmt->colorspace; |
296 | pix->colorspace = V4L2_COLORSPACE_SRGB; | 307 | mf->field = V4L2_FIELD_NONE; |
297 | 308 | ||
298 | return 0; | 309 | return 0; |
299 | } | 310 | } |
300 | 311 | ||
301 | static int mt9m001_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | 312 | static int mt9m001_s_fmt(struct v4l2_subdev *sd, |
313 | struct v4l2_mbus_framefmt *mf) | ||
302 | { | 314 | { |
303 | struct i2c_client *client = sd->priv; | 315 | struct i2c_client *client = sd->priv; |
304 | struct mt9m001 *mt9m001 = to_mt9m001(client); | 316 | struct mt9m001 *mt9m001 = to_mt9m001(client); |
305 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
306 | struct v4l2_crop a = { | 317 | struct v4l2_crop a = { |
307 | .c = { | 318 | .c = { |
308 | .left = mt9m001->rect.left, | 319 | .left = mt9m001->rect.left, |
309 | .top = mt9m001->rect.top, | 320 | .top = mt9m001->rect.top, |
310 | .width = pix->width, | 321 | .width = mf->width, |
311 | .height = pix->height, | 322 | .height = mf->height, |
312 | }, | 323 | }, |
313 | }; | 324 | }; |
314 | int ret; | 325 | int ret; |
@@ -316,28 +327,39 @@ static int mt9m001_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | |||
316 | /* No support for scaling so far, just crop. TODO: use skipping */ | 327 | /* No support for scaling so far, just crop. TODO: use skipping */ |
317 | ret = mt9m001_s_crop(sd, &a); | 328 | ret = mt9m001_s_crop(sd, &a); |
318 | if (!ret) { | 329 | if (!ret) { |
319 | pix->width = mt9m001->rect.width; | 330 | mf->width = mt9m001->rect.width; |
320 | pix->height = mt9m001->rect.height; | 331 | mf->height = mt9m001->rect.height; |
321 | mt9m001->fourcc = pix->pixelformat; | 332 | mt9m001->fmt = mt9m001_find_datafmt(mf->code, |
333 | mt9m001->fmts, mt9m001->num_fmts); | ||
334 | mf->colorspace = mt9m001->fmt->colorspace; | ||
322 | } | 335 | } |
323 | 336 | ||
324 | return ret; | 337 | return ret; |
325 | } | 338 | } |
326 | 339 | ||
327 | static int mt9m001_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | 340 | static int mt9m001_try_fmt(struct v4l2_subdev *sd, |
341 | struct v4l2_mbus_framefmt *mf) | ||
328 | { | 342 | { |
329 | struct i2c_client *client = sd->priv; | 343 | struct i2c_client *client = sd->priv; |
330 | struct soc_camera_device *icd = client->dev.platform_data; | 344 | struct mt9m001 *mt9m001 = to_mt9m001(client); |
331 | struct v4l2_pix_format *pix = &f->fmt.pix; | 345 | const struct mt9m001_datafmt *fmt; |
332 | 346 | ||
333 | v4l_bound_align_image(&pix->width, MT9M001_MIN_WIDTH, | 347 | v4l_bound_align_image(&mf->width, MT9M001_MIN_WIDTH, |
334 | MT9M001_MAX_WIDTH, 1, | 348 | MT9M001_MAX_WIDTH, 1, |
335 | &pix->height, MT9M001_MIN_HEIGHT + icd->y_skip_top, | 349 | &mf->height, MT9M001_MIN_HEIGHT + mt9m001->y_skip_top, |
336 | MT9M001_MAX_HEIGHT + icd->y_skip_top, 0, 0); | 350 | MT9M001_MAX_HEIGHT + mt9m001->y_skip_top, 0, 0); |
351 | |||
352 | if (mt9m001->fmts == mt9m001_colour_fmts) | ||
353 | mf->height = ALIGN(mf->height - 1, 2); | ||
337 | 354 | ||
338 | if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8 || | 355 | fmt = mt9m001_find_datafmt(mf->code, mt9m001->fmts, |
339 | pix->pixelformat == V4L2_PIX_FMT_SBGGR16) | 356 | mt9m001->num_fmts); |
340 | pix->height = ALIGN(pix->height - 1, 2); | 357 | if (!fmt) { |
358 | fmt = mt9m001->fmt; | ||
359 | mf->code = fmt->code; | ||
360 | } | ||
361 | |||
362 | mf->colorspace = fmt->colorspace; | ||
341 | 363 | ||
342 | return 0; | 364 | return 0; |
343 | } | 365 | } |
@@ -552,7 +574,7 @@ static int mt9m001_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | |||
552 | if (ctrl->value) { | 574 | if (ctrl->value) { |
553 | const u16 vblank = 25; | 575 | const u16 vblank = 25; |
554 | unsigned int total_h = mt9m001->rect.height + | 576 | unsigned int total_h = mt9m001->rect.height + |
555 | icd->y_skip_top + vblank; | 577 | mt9m001->y_skip_top + vblank; |
556 | if (reg_write(client, MT9M001_SHUTTER_WIDTH, | 578 | if (reg_write(client, MT9M001_SHUTTER_WIDTH, |
557 | total_h) < 0) | 579 | total_h) < 0) |
558 | return -EIO; | 580 | return -EIO; |
@@ -568,8 +590,10 @@ static int mt9m001_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | |||
568 | return 0; | 590 | return 0; |
569 | } | 591 | } |
570 | 592 | ||
571 | /* Interface active, can use i2c. If it fails, it can indeed mean, that | 593 | /* |
572 | * this wasn't our capture interface, so, we wait for the right one */ | 594 | * Interface active, can use i2c. If it fails, it can indeed mean, that |
595 | * this wasn't our capture interface, so, we wait for the right one | ||
596 | */ | ||
573 | static int mt9m001_video_probe(struct soc_camera_device *icd, | 597 | static int mt9m001_video_probe(struct soc_camera_device *icd, |
574 | struct i2c_client *client) | 598 | struct i2c_client *client) |
575 | { | 599 | { |
@@ -579,8 +603,10 @@ static int mt9m001_video_probe(struct soc_camera_device *icd, | |||
579 | unsigned long flags; | 603 | unsigned long flags; |
580 | int ret; | 604 | int ret; |
581 | 605 | ||
582 | /* We must have a parent by now. And it cannot be a wrong one. | 606 | /* |
583 | * So this entire test is completely redundant. */ | 607 | * We must have a parent by now. And it cannot be a wrong one. |
608 | * So this entire test is completely redundant. | ||
609 | */ | ||
584 | if (!icd->dev.parent || | 610 | if (!icd->dev.parent || |
585 | to_soc_camera_host(icd->dev.parent)->nr != icd->iface) | 611 | to_soc_camera_host(icd->dev.parent)->nr != icd->iface) |
586 | return -ENODEV; | 612 | return -ENODEV; |
@@ -597,11 +623,11 @@ static int mt9m001_video_probe(struct soc_camera_device *icd, | |||
597 | case 0x8411: | 623 | case 0x8411: |
598 | case 0x8421: | 624 | case 0x8421: |
599 | mt9m001->model = V4L2_IDENT_MT9M001C12ST; | 625 | mt9m001->model = V4L2_IDENT_MT9M001C12ST; |
600 | icd->formats = mt9m001_colour_formats; | 626 | mt9m001->fmts = mt9m001_colour_fmts; |
601 | break; | 627 | break; |
602 | case 0x8431: | 628 | case 0x8431: |
603 | mt9m001->model = V4L2_IDENT_MT9M001C12STM; | 629 | mt9m001->model = V4L2_IDENT_MT9M001C12STM; |
604 | icd->formats = mt9m001_monochrome_formats; | 630 | mt9m001->fmts = mt9m001_monochrome_fmts; |
605 | break; | 631 | break; |
606 | default: | 632 | default: |
607 | dev_err(&client->dev, | 633 | dev_err(&client->dev, |
@@ -609,7 +635,7 @@ static int mt9m001_video_probe(struct soc_camera_device *icd, | |||
609 | return -ENODEV; | 635 | return -ENODEV; |
610 | } | 636 | } |
611 | 637 | ||
612 | icd->num_formats = 0; | 638 | mt9m001->num_fmts = 0; |
613 | 639 | ||
614 | /* | 640 | /* |
615 | * This is a 10bit sensor, so by default we only allow 10bit. | 641 | * This is a 10bit sensor, so by default we only allow 10bit. |
@@ -622,14 +648,14 @@ static int mt9m001_video_probe(struct soc_camera_device *icd, | |||
622 | flags = SOCAM_DATAWIDTH_10; | 648 | flags = SOCAM_DATAWIDTH_10; |
623 | 649 | ||
624 | if (flags & SOCAM_DATAWIDTH_10) | 650 | if (flags & SOCAM_DATAWIDTH_10) |
625 | icd->num_formats++; | 651 | mt9m001->num_fmts++; |
626 | else | 652 | else |
627 | icd->formats++; | 653 | mt9m001->fmts++; |
628 | 654 | ||
629 | if (flags & SOCAM_DATAWIDTH_8) | 655 | if (flags & SOCAM_DATAWIDTH_8) |
630 | icd->num_formats++; | 656 | mt9m001->num_fmts++; |
631 | 657 | ||
632 | mt9m001->fourcc = icd->formats->fourcc; | 658 | mt9m001->fmt = &mt9m001->fmts[0]; |
633 | 659 | ||
634 | dev_info(&client->dev, "Detected a MT9M001 chip ID %x (%s)\n", data, | 660 | dev_info(&client->dev, "Detected a MT9M001 chip ID %x (%s)\n", data, |
635 | data == 0x8431 ? "C12STM" : "C12ST"); | 661 | data == 0x8431 ? "C12STM" : "C12ST"); |
@@ -655,6 +681,16 @@ static void mt9m001_video_remove(struct soc_camera_device *icd) | |||
655 | icl->free_bus(icl); | 681 | icl->free_bus(icl); |
656 | } | 682 | } |
657 | 683 | ||
684 | static int mt9m001_g_skip_top_lines(struct v4l2_subdev *sd, u32 *lines) | ||
685 | { | ||
686 | struct i2c_client *client = sd->priv; | ||
687 | struct mt9m001 *mt9m001 = to_mt9m001(client); | ||
688 | |||
689 | *lines = mt9m001->y_skip_top; | ||
690 | |||
691 | return 0; | ||
692 | } | ||
693 | |||
658 | static struct v4l2_subdev_core_ops mt9m001_subdev_core_ops = { | 694 | static struct v4l2_subdev_core_ops mt9m001_subdev_core_ops = { |
659 | .g_ctrl = mt9m001_g_ctrl, | 695 | .g_ctrl = mt9m001_g_ctrl, |
660 | .s_ctrl = mt9m001_s_ctrl, | 696 | .s_ctrl = mt9m001_s_ctrl, |
@@ -665,19 +701,38 @@ static struct v4l2_subdev_core_ops mt9m001_subdev_core_ops = { | |||
665 | #endif | 701 | #endif |
666 | }; | 702 | }; |
667 | 703 | ||
704 | static int mt9m001_enum_fmt(struct v4l2_subdev *sd, int index, | ||
705 | enum v4l2_mbus_pixelcode *code) | ||
706 | { | ||
707 | struct i2c_client *client = sd->priv; | ||
708 | struct mt9m001 *mt9m001 = to_mt9m001(client); | ||
709 | |||
710 | if ((unsigned int)index >= mt9m001->num_fmts) | ||
711 | return -EINVAL; | ||
712 | |||
713 | *code = mt9m001->fmts[index].code; | ||
714 | return 0; | ||
715 | } | ||
716 | |||
668 | static struct v4l2_subdev_video_ops mt9m001_subdev_video_ops = { | 717 | static struct v4l2_subdev_video_ops mt9m001_subdev_video_ops = { |
669 | .s_stream = mt9m001_s_stream, | 718 | .s_stream = mt9m001_s_stream, |
670 | .s_fmt = mt9m001_s_fmt, | 719 | .s_mbus_fmt = mt9m001_s_fmt, |
671 | .g_fmt = mt9m001_g_fmt, | 720 | .g_mbus_fmt = mt9m001_g_fmt, |
672 | .try_fmt = mt9m001_try_fmt, | 721 | .try_mbus_fmt = mt9m001_try_fmt, |
673 | .s_crop = mt9m001_s_crop, | 722 | .s_crop = mt9m001_s_crop, |
674 | .g_crop = mt9m001_g_crop, | 723 | .g_crop = mt9m001_g_crop, |
675 | .cropcap = mt9m001_cropcap, | 724 | .cropcap = mt9m001_cropcap, |
725 | .enum_mbus_fmt = mt9m001_enum_fmt, | ||
726 | }; | ||
727 | |||
728 | static struct v4l2_subdev_sensor_ops mt9m001_subdev_sensor_ops = { | ||
729 | .g_skip_top_lines = mt9m001_g_skip_top_lines, | ||
676 | }; | 730 | }; |
677 | 731 | ||
678 | static struct v4l2_subdev_ops mt9m001_subdev_ops = { | 732 | static struct v4l2_subdev_ops mt9m001_subdev_ops = { |
679 | .core = &mt9m001_subdev_core_ops, | 733 | .core = &mt9m001_subdev_core_ops, |
680 | .video = &mt9m001_subdev_video_ops, | 734 | .video = &mt9m001_subdev_video_ops, |
735 | .sensor = &mt9m001_subdev_sensor_ops, | ||
681 | }; | 736 | }; |
682 | 737 | ||
683 | static int mt9m001_probe(struct i2c_client *client, | 738 | static int mt9m001_probe(struct i2c_client *client, |
@@ -714,15 +769,17 @@ static int mt9m001_probe(struct i2c_client *client, | |||
714 | 769 | ||
715 | /* Second stage probe - when a capture adapter is there */ | 770 | /* Second stage probe - when a capture adapter is there */ |
716 | icd->ops = &mt9m001_ops; | 771 | icd->ops = &mt9m001_ops; |
717 | icd->y_skip_top = 0; | ||
718 | 772 | ||
773 | mt9m001->y_skip_top = 0; | ||
719 | mt9m001->rect.left = MT9M001_COLUMN_SKIP; | 774 | mt9m001->rect.left = MT9M001_COLUMN_SKIP; |
720 | mt9m001->rect.top = MT9M001_ROW_SKIP; | 775 | mt9m001->rect.top = MT9M001_ROW_SKIP; |
721 | mt9m001->rect.width = MT9M001_MAX_WIDTH; | 776 | mt9m001->rect.width = MT9M001_MAX_WIDTH; |
722 | mt9m001->rect.height = MT9M001_MAX_HEIGHT; | 777 | mt9m001->rect.height = MT9M001_MAX_HEIGHT; |
723 | 778 | ||
724 | /* Simulated autoexposure. If enabled, we calculate shutter width | 779 | /* |
725 | * ourselves in the driver based on vertical blanking and frame width */ | 780 | * Simulated autoexposure. If enabled, we calculate shutter width |
781 | * ourselves in the driver based on vertical blanking and frame width | ||
782 | */ | ||
726 | mt9m001->autoexposure = 1; | 783 | mt9m001->autoexposure = 1; |
727 | 784 | ||
728 | ret = mt9m001_video_probe(icd, client); | 785 | ret = mt9m001_video_probe(icd, client); |
diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c index 90da699601ea..d35f536f9fc3 100644 --- a/drivers/media/video/mt9m111.c +++ b/drivers/media/video/mt9m111.c | |||
@@ -123,23 +123,34 @@ | |||
123 | #define MT9M111_MAX_HEIGHT 1024 | 123 | #define MT9M111_MAX_HEIGHT 1024 |
124 | #define MT9M111_MAX_WIDTH 1280 | 124 | #define MT9M111_MAX_WIDTH 1280 |
125 | 125 | ||
126 | #define COL_FMT(_name, _depth, _fourcc, _colorspace) \ | 126 | /* MT9M111 has only one fixed colorspace per pixelcode */ |
127 | { .name = _name, .depth = _depth, .fourcc = _fourcc, \ | 127 | struct mt9m111_datafmt { |
128 | .colorspace = _colorspace } | 128 | enum v4l2_mbus_pixelcode code; |
129 | #define RGB_FMT(_name, _depth, _fourcc) \ | 129 | enum v4l2_colorspace colorspace; |
130 | COL_FMT(_name, _depth, _fourcc, V4L2_COLORSPACE_SRGB) | 130 | }; |
131 | #define JPG_FMT(_name, _depth, _fourcc) \ | 131 | |
132 | COL_FMT(_name, _depth, _fourcc, V4L2_COLORSPACE_JPEG) | 132 | /* Find a data format by a pixel code in an array */ |
133 | 133 | static const struct mt9m111_datafmt *mt9m111_find_datafmt( | |
134 | static const struct soc_camera_data_format mt9m111_colour_formats[] = { | 134 | enum v4l2_mbus_pixelcode code, const struct mt9m111_datafmt *fmt, |
135 | JPG_FMT("CbYCrY 16 bit", 16, V4L2_PIX_FMT_UYVY), | 135 | int n) |
136 | JPG_FMT("CrYCbY 16 bit", 16, V4L2_PIX_FMT_VYUY), | 136 | { |
137 | JPG_FMT("YCbYCr 16 bit", 16, V4L2_PIX_FMT_YUYV), | 137 | int i; |
138 | JPG_FMT("YCrYCb 16 bit", 16, V4L2_PIX_FMT_YVYU), | 138 | for (i = 0; i < n; i++) |
139 | RGB_FMT("RGB 565", 16, V4L2_PIX_FMT_RGB565), | 139 | if (fmt[i].code == code) |
140 | RGB_FMT("RGB 555", 16, V4L2_PIX_FMT_RGB555), | 140 | return fmt + i; |
141 | RGB_FMT("Bayer (sRGB) 10 bit", 10, V4L2_PIX_FMT_SBGGR16), | 141 | |
142 | RGB_FMT("Bayer (sRGB) 8 bit", 8, V4L2_PIX_FMT_SBGGR8), | 142 | return NULL; |
143 | } | ||
144 | |||
145 | static const struct mt9m111_datafmt mt9m111_colour_fmts[] = { | ||
146 | {V4L2_MBUS_FMT_YUYV8_2X8_LE, V4L2_COLORSPACE_JPEG}, | ||
147 | {V4L2_MBUS_FMT_YVYU8_2X8_LE, V4L2_COLORSPACE_JPEG}, | ||
148 | {V4L2_MBUS_FMT_YUYV8_2X8_BE, V4L2_COLORSPACE_JPEG}, | ||
149 | {V4L2_MBUS_FMT_YVYU8_2X8_BE, V4L2_COLORSPACE_JPEG}, | ||
150 | {V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB}, | ||
151 | {V4L2_MBUS_FMT_RGB565_2X8_LE, V4L2_COLORSPACE_SRGB}, | ||
152 | {V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB}, | ||
153 | {V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB}, | ||
143 | }; | 154 | }; |
144 | 155 | ||
145 | enum mt9m111_context { | 156 | enum mt9m111_context { |
@@ -152,7 +163,7 @@ struct mt9m111 { | |||
152 | int model; /* V4L2_IDENT_MT9M11x* codes from v4l2-chip-ident.h */ | 163 | int model; /* V4L2_IDENT_MT9M11x* codes from v4l2-chip-ident.h */ |
153 | enum mt9m111_context context; | 164 | enum mt9m111_context context; |
154 | struct v4l2_rect rect; | 165 | struct v4l2_rect rect; |
155 | u32 pixfmt; | 166 | const struct mt9m111_datafmt *fmt; |
156 | unsigned int gain; | 167 | unsigned int gain; |
157 | unsigned char autoexposure; | 168 | unsigned char autoexposure; |
158 | unsigned char datawidth; | 169 | unsigned char datawidth; |
@@ -258,8 +269,8 @@ static int mt9m111_setup_rect(struct i2c_client *client, | |||
258 | int width = rect->width; | 269 | int width = rect->width; |
259 | int height = rect->height; | 270 | int height = rect->height; |
260 | 271 | ||
261 | if (mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR8 || | 272 | if (mt9m111->fmt->code == V4L2_MBUS_FMT_SBGGR8_1X8 || |
262 | mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR16) | 273 | mt9m111->fmt->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE) |
263 | is_raw_format = 1; | 274 | is_raw_format = 1; |
264 | else | 275 | else |
265 | is_raw_format = 0; | 276 | is_raw_format = 0; |
@@ -307,7 +318,8 @@ static int mt9m111_setup_pixfmt(struct i2c_client *client, u16 outfmt) | |||
307 | 318 | ||
308 | static int mt9m111_setfmt_bayer8(struct i2c_client *client) | 319 | static int mt9m111_setfmt_bayer8(struct i2c_client *client) |
309 | { | 320 | { |
310 | return mt9m111_setup_pixfmt(client, MT9M111_OUTFMT_PROCESSED_BAYER); | 321 | return mt9m111_setup_pixfmt(client, MT9M111_OUTFMT_PROCESSED_BAYER | |
322 | MT9M111_OUTFMT_RGB); | ||
311 | } | 323 | } |
312 | 324 | ||
313 | static int mt9m111_setfmt_bayer10(struct i2c_client *client) | 325 | static int mt9m111_setfmt_bayer10(struct i2c_client *client) |
@@ -401,8 +413,8 @@ static int mt9m111_make_rect(struct i2c_client *client, | |||
401 | { | 413 | { |
402 | struct mt9m111 *mt9m111 = to_mt9m111(client); | 414 | struct mt9m111 *mt9m111 = to_mt9m111(client); |
403 | 415 | ||
404 | if (mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR8 || | 416 | if (mt9m111->fmt->code == V4L2_MBUS_FMT_SBGGR8_1X8 || |
405 | mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR16) { | 417 | mt9m111->fmt->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE) { |
406 | /* Bayer format - even size lengths */ | 418 | /* Bayer format - even size lengths */ |
407 | rect->width = ALIGN(rect->width, 2); | 419 | rect->width = ALIGN(rect->width, 2); |
408 | rect->height = ALIGN(rect->height, 2); | 420 | rect->height = ALIGN(rect->height, 2); |
@@ -460,120 +472,139 @@ static int mt9m111_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) | |||
460 | return 0; | 472 | return 0; |
461 | } | 473 | } |
462 | 474 | ||
463 | static int mt9m111_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | 475 | static int mt9m111_g_fmt(struct v4l2_subdev *sd, |
476 | struct v4l2_mbus_framefmt *mf) | ||
464 | { | 477 | { |
465 | struct i2c_client *client = sd->priv; | 478 | struct i2c_client *client = sd->priv; |
466 | struct mt9m111 *mt9m111 = to_mt9m111(client); | 479 | struct mt9m111 *mt9m111 = to_mt9m111(client); |
467 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
468 | 480 | ||
469 | pix->width = mt9m111->rect.width; | 481 | mf->width = mt9m111->rect.width; |
470 | pix->height = mt9m111->rect.height; | 482 | mf->height = mt9m111->rect.height; |
471 | pix->pixelformat = mt9m111->pixfmt; | 483 | mf->code = mt9m111->fmt->code; |
472 | pix->field = V4L2_FIELD_NONE; | 484 | mf->field = V4L2_FIELD_NONE; |
473 | pix->colorspace = V4L2_COLORSPACE_SRGB; | ||
474 | 485 | ||
475 | return 0; | 486 | return 0; |
476 | } | 487 | } |
477 | 488 | ||
478 | static int mt9m111_set_pixfmt(struct i2c_client *client, u32 pixfmt) | 489 | static int mt9m111_set_pixfmt(struct i2c_client *client, |
490 | enum v4l2_mbus_pixelcode code) | ||
479 | { | 491 | { |
480 | struct mt9m111 *mt9m111 = to_mt9m111(client); | 492 | struct mt9m111 *mt9m111 = to_mt9m111(client); |
481 | int ret; | 493 | int ret; |
482 | 494 | ||
483 | switch (pixfmt) { | 495 | switch (code) { |
484 | case V4L2_PIX_FMT_SBGGR8: | 496 | case V4L2_MBUS_FMT_SBGGR8_1X8: |
485 | ret = mt9m111_setfmt_bayer8(client); | 497 | ret = mt9m111_setfmt_bayer8(client); |
486 | break; | 498 | break; |
487 | case V4L2_PIX_FMT_SBGGR16: | 499 | case V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE: |
488 | ret = mt9m111_setfmt_bayer10(client); | 500 | ret = mt9m111_setfmt_bayer10(client); |
489 | break; | 501 | break; |
490 | case V4L2_PIX_FMT_RGB555: | 502 | case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE: |
491 | ret = mt9m111_setfmt_rgb555(client); | 503 | ret = mt9m111_setfmt_rgb555(client); |
492 | break; | 504 | break; |
493 | case V4L2_PIX_FMT_RGB565: | 505 | case V4L2_MBUS_FMT_RGB565_2X8_LE: |
494 | ret = mt9m111_setfmt_rgb565(client); | 506 | ret = mt9m111_setfmt_rgb565(client); |
495 | break; | 507 | break; |
496 | case V4L2_PIX_FMT_UYVY: | 508 | case V4L2_MBUS_FMT_YUYV8_2X8_BE: |
497 | mt9m111->swap_yuv_y_chromas = 0; | 509 | mt9m111->swap_yuv_y_chromas = 0; |
498 | mt9m111->swap_yuv_cb_cr = 0; | 510 | mt9m111->swap_yuv_cb_cr = 0; |
499 | ret = mt9m111_setfmt_yuv(client); | 511 | ret = mt9m111_setfmt_yuv(client); |
500 | break; | 512 | break; |
501 | case V4L2_PIX_FMT_VYUY: | 513 | case V4L2_MBUS_FMT_YVYU8_2X8_BE: |
502 | mt9m111->swap_yuv_y_chromas = 0; | 514 | mt9m111->swap_yuv_y_chromas = 0; |
503 | mt9m111->swap_yuv_cb_cr = 1; | 515 | mt9m111->swap_yuv_cb_cr = 1; |
504 | ret = mt9m111_setfmt_yuv(client); | 516 | ret = mt9m111_setfmt_yuv(client); |
505 | break; | 517 | break; |
506 | case V4L2_PIX_FMT_YUYV: | 518 | case V4L2_MBUS_FMT_YUYV8_2X8_LE: |
507 | mt9m111->swap_yuv_y_chromas = 1; | 519 | mt9m111->swap_yuv_y_chromas = 1; |
508 | mt9m111->swap_yuv_cb_cr = 0; | 520 | mt9m111->swap_yuv_cb_cr = 0; |
509 | ret = mt9m111_setfmt_yuv(client); | 521 | ret = mt9m111_setfmt_yuv(client); |
510 | break; | 522 | break; |
511 | case V4L2_PIX_FMT_YVYU: | 523 | case V4L2_MBUS_FMT_YVYU8_2X8_LE: |
512 | mt9m111->swap_yuv_y_chromas = 1; | 524 | mt9m111->swap_yuv_y_chromas = 1; |
513 | mt9m111->swap_yuv_cb_cr = 1; | 525 | mt9m111->swap_yuv_cb_cr = 1; |
514 | ret = mt9m111_setfmt_yuv(client); | 526 | ret = mt9m111_setfmt_yuv(client); |
515 | break; | 527 | break; |
516 | default: | 528 | default: |
517 | dev_err(&client->dev, "Pixel format not handled : %x\n", | 529 | dev_err(&client->dev, "Pixel format not handled : %x\n", |
518 | pixfmt); | 530 | code); |
519 | ret = -EINVAL; | 531 | ret = -EINVAL; |
520 | } | 532 | } |
521 | 533 | ||
522 | if (!ret) | ||
523 | mt9m111->pixfmt = pixfmt; | ||
524 | |||
525 | return ret; | 534 | return ret; |
526 | } | 535 | } |
527 | 536 | ||
528 | static int mt9m111_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | 537 | static int mt9m111_s_fmt(struct v4l2_subdev *sd, |
538 | struct v4l2_mbus_framefmt *mf) | ||
529 | { | 539 | { |
530 | struct i2c_client *client = sd->priv; | 540 | struct i2c_client *client = sd->priv; |
541 | const struct mt9m111_datafmt *fmt; | ||
531 | struct mt9m111 *mt9m111 = to_mt9m111(client); | 542 | struct mt9m111 *mt9m111 = to_mt9m111(client); |
532 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
533 | struct v4l2_rect rect = { | 543 | struct v4l2_rect rect = { |
534 | .left = mt9m111->rect.left, | 544 | .left = mt9m111->rect.left, |
535 | .top = mt9m111->rect.top, | 545 | .top = mt9m111->rect.top, |
536 | .width = pix->width, | 546 | .width = mf->width, |
537 | .height = pix->height, | 547 | .height = mf->height, |
538 | }; | 548 | }; |
539 | int ret; | 549 | int ret; |
540 | 550 | ||
551 | fmt = mt9m111_find_datafmt(mf->code, mt9m111_colour_fmts, | ||
552 | ARRAY_SIZE(mt9m111_colour_fmts)); | ||
553 | if (!fmt) | ||
554 | return -EINVAL; | ||
555 | |||
541 | dev_dbg(&client->dev, | 556 | dev_dbg(&client->dev, |
542 | "%s fmt=%x left=%d, top=%d, width=%d, height=%d\n", __func__, | 557 | "%s code=%x left=%d, top=%d, width=%d, height=%d\n", __func__, |
543 | pix->pixelformat, rect.left, rect.top, rect.width, rect.height); | 558 | mf->code, rect.left, rect.top, rect.width, rect.height); |
544 | 559 | ||
545 | ret = mt9m111_make_rect(client, &rect); | 560 | ret = mt9m111_make_rect(client, &rect); |
546 | if (!ret) | 561 | if (!ret) |
547 | ret = mt9m111_set_pixfmt(client, pix->pixelformat); | 562 | ret = mt9m111_set_pixfmt(client, mf->code); |
548 | if (!ret) | 563 | if (!ret) { |
549 | mt9m111->rect = rect; | 564 | mt9m111->rect = rect; |
565 | mt9m111->fmt = fmt; | ||
566 | mf->colorspace = fmt->colorspace; | ||
567 | } | ||
568 | |||
550 | return ret; | 569 | return ret; |
551 | } | 570 | } |
552 | 571 | ||
553 | static int mt9m111_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | 572 | static int mt9m111_try_fmt(struct v4l2_subdev *sd, |
573 | struct v4l2_mbus_framefmt *mf) | ||
554 | { | 574 | { |
555 | struct v4l2_pix_format *pix = &f->fmt.pix; | 575 | struct i2c_client *client = sd->priv; |
556 | bool bayer = pix->pixelformat == V4L2_PIX_FMT_SBGGR8 || | 576 | struct mt9m111 *mt9m111 = to_mt9m111(client); |
557 | pix->pixelformat == V4L2_PIX_FMT_SBGGR16; | 577 | const struct mt9m111_datafmt *fmt; |
578 | bool bayer = mf->code == V4L2_MBUS_FMT_SBGGR8_1X8 || | ||
579 | mf->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE; | ||
580 | |||
581 | fmt = mt9m111_find_datafmt(mf->code, mt9m111_colour_fmts, | ||
582 | ARRAY_SIZE(mt9m111_colour_fmts)); | ||
583 | if (!fmt) { | ||
584 | fmt = mt9m111->fmt; | ||
585 | mf->code = fmt->code; | ||
586 | } | ||
558 | 587 | ||
559 | /* | 588 | /* |
560 | * With Bayer format enforce even side lengths, but let the user play | 589 | * With Bayer format enforce even side lengths, but let the user play |
561 | * with the starting pixel | 590 | * with the starting pixel |
562 | */ | 591 | */ |
563 | 592 | ||
564 | if (pix->height > MT9M111_MAX_HEIGHT) | 593 | if (mf->height > MT9M111_MAX_HEIGHT) |
565 | pix->height = MT9M111_MAX_HEIGHT; | 594 | mf->height = MT9M111_MAX_HEIGHT; |
566 | else if (pix->height < 2) | 595 | else if (mf->height < 2) |
567 | pix->height = 2; | 596 | mf->height = 2; |
568 | else if (bayer) | 597 | else if (bayer) |
569 | pix->height = ALIGN(pix->height, 2); | 598 | mf->height = ALIGN(mf->height, 2); |
570 | 599 | ||
571 | if (pix->width > MT9M111_MAX_WIDTH) | 600 | if (mf->width > MT9M111_MAX_WIDTH) |
572 | pix->width = MT9M111_MAX_WIDTH; | 601 | mf->width = MT9M111_MAX_WIDTH; |
573 | else if (pix->width < 2) | 602 | else if (mf->width < 2) |
574 | pix->width = 2; | 603 | mf->width = 2; |
575 | else if (bayer) | 604 | else if (bayer) |
576 | pix->width = ALIGN(pix->width, 2); | 605 | mf->width = ALIGN(mf->width, 2); |
606 | |||
607 | mf->colorspace = fmt->colorspace; | ||
577 | 608 | ||
578 | return 0; | 609 | return 0; |
579 | } | 610 | } |
@@ -863,7 +894,7 @@ static int mt9m111_restore_state(struct i2c_client *client) | |||
863 | struct mt9m111 *mt9m111 = to_mt9m111(client); | 894 | struct mt9m111 *mt9m111 = to_mt9m111(client); |
864 | 895 | ||
865 | mt9m111_set_context(client, mt9m111->context); | 896 | mt9m111_set_context(client, mt9m111->context); |
866 | mt9m111_set_pixfmt(client, mt9m111->pixfmt); | 897 | mt9m111_set_pixfmt(client, mt9m111->fmt->code); |
867 | mt9m111_setup_rect(client, &mt9m111->rect); | 898 | mt9m111_setup_rect(client, &mt9m111->rect); |
868 | mt9m111_set_flip(client, mt9m111->hflip, MT9M111_RMB_MIRROR_COLS); | 899 | mt9m111_set_flip(client, mt9m111->hflip, MT9M111_RMB_MIRROR_COLS); |
869 | mt9m111_set_flip(client, mt9m111->vflip, MT9M111_RMB_MIRROR_ROWS); | 900 | mt9m111_set_flip(client, mt9m111->vflip, MT9M111_RMB_MIRROR_ROWS); |
@@ -952,9 +983,6 @@ static int mt9m111_video_probe(struct soc_camera_device *icd, | |||
952 | goto ei2c; | 983 | goto ei2c; |
953 | } | 984 | } |
954 | 985 | ||
955 | icd->formats = mt9m111_colour_formats; | ||
956 | icd->num_formats = ARRAY_SIZE(mt9m111_colour_formats); | ||
957 | |||
958 | dev_info(&client->dev, "Detected a MT9M11x chip ID %x\n", data); | 986 | dev_info(&client->dev, "Detected a MT9M11x chip ID %x\n", data); |
959 | 987 | ||
960 | ei2c: | 988 | ei2c: |
@@ -971,13 +999,24 @@ static struct v4l2_subdev_core_ops mt9m111_subdev_core_ops = { | |||
971 | #endif | 999 | #endif |
972 | }; | 1000 | }; |
973 | 1001 | ||
1002 | static int mt9m111_enum_fmt(struct v4l2_subdev *sd, int index, | ||
1003 | enum v4l2_mbus_pixelcode *code) | ||
1004 | { | ||
1005 | if ((unsigned int)index >= ARRAY_SIZE(mt9m111_colour_fmts)) | ||
1006 | return -EINVAL; | ||
1007 | |||
1008 | *code = mt9m111_colour_fmts[index].code; | ||
1009 | return 0; | ||
1010 | } | ||
1011 | |||
974 | static struct v4l2_subdev_video_ops mt9m111_subdev_video_ops = { | 1012 | static struct v4l2_subdev_video_ops mt9m111_subdev_video_ops = { |
975 | .s_fmt = mt9m111_s_fmt, | 1013 | .s_mbus_fmt = mt9m111_s_fmt, |
976 | .g_fmt = mt9m111_g_fmt, | 1014 | .g_mbus_fmt = mt9m111_g_fmt, |
977 | .try_fmt = mt9m111_try_fmt, | 1015 | .try_mbus_fmt = mt9m111_try_fmt, |
978 | .s_crop = mt9m111_s_crop, | 1016 | .s_crop = mt9m111_s_crop, |
979 | .g_crop = mt9m111_g_crop, | 1017 | .g_crop = mt9m111_g_crop, |
980 | .cropcap = mt9m111_cropcap, | 1018 | .cropcap = mt9m111_cropcap, |
1019 | .enum_mbus_fmt = mt9m111_enum_fmt, | ||
981 | }; | 1020 | }; |
982 | 1021 | ||
983 | static struct v4l2_subdev_ops mt9m111_subdev_ops = { | 1022 | static struct v4l2_subdev_ops mt9m111_subdev_ops = { |
@@ -1019,12 +1058,12 @@ static int mt9m111_probe(struct i2c_client *client, | |||
1019 | 1058 | ||
1020 | /* Second stage probe - when a capture adapter is there */ | 1059 | /* Second stage probe - when a capture adapter is there */ |
1021 | icd->ops = &mt9m111_ops; | 1060 | icd->ops = &mt9m111_ops; |
1022 | icd->y_skip_top = 0; | ||
1023 | 1061 | ||
1024 | mt9m111->rect.left = MT9M111_MIN_DARK_COLS; | 1062 | mt9m111->rect.left = MT9M111_MIN_DARK_COLS; |
1025 | mt9m111->rect.top = MT9M111_MIN_DARK_ROWS; | 1063 | mt9m111->rect.top = MT9M111_MIN_DARK_ROWS; |
1026 | mt9m111->rect.width = MT9M111_MAX_WIDTH; | 1064 | mt9m111->rect.width = MT9M111_MAX_WIDTH; |
1027 | mt9m111->rect.height = MT9M111_MAX_HEIGHT; | 1065 | mt9m111->rect.height = MT9M111_MAX_HEIGHT; |
1066 | mt9m111->fmt = &mt9m111_colour_fmts[0]; | ||
1028 | 1067 | ||
1029 | ret = mt9m111_video_probe(icd, client); | 1068 | ret = mt9m111_video_probe(icd, client); |
1030 | if (ret) { | 1069 | if (ret) { |
diff --git a/drivers/media/video/mt9t031.c b/drivers/media/video/mt9t031.c index 6966f644977e..a9061bff79b2 100644 --- a/drivers/media/video/mt9t031.c +++ b/drivers/media/video/mt9t031.c | |||
@@ -17,9 +17,11 @@ | |||
17 | #include <media/v4l2-chip-ident.h> | 17 | #include <media/v4l2-chip-ident.h> |
18 | #include <media/soc_camera.h> | 18 | #include <media/soc_camera.h> |
19 | 19 | ||
20 | /* mt9t031 i2c address 0x5d | 20 | /* |
21 | * mt9t031 i2c address 0x5d | ||
21 | * The platform has to define i2c_board_info and link to it from | 22 | * The platform has to define i2c_board_info and link to it from |
22 | * struct soc_camera_link */ | 23 | * struct soc_camera_link |
24 | */ | ||
23 | 25 | ||
24 | /* mt9t031 selected register addresses */ | 26 | /* mt9t031 selected register addresses */ |
25 | #define MT9T031_CHIP_VERSION 0x00 | 27 | #define MT9T031_CHIP_VERSION 0x00 |
@@ -58,15 +60,6 @@ | |||
58 | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_HIGH | \ | 60 | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_HIGH | \ |
59 | SOCAM_MASTER | SOCAM_DATAWIDTH_10) | 61 | SOCAM_MASTER | SOCAM_DATAWIDTH_10) |
60 | 62 | ||
61 | static const struct soc_camera_data_format mt9t031_colour_formats[] = { | ||
62 | { | ||
63 | .name = "Bayer (sRGB) 10 bit", | ||
64 | .depth = 10, | ||
65 | .fourcc = V4L2_PIX_FMT_SGRBG10, | ||
66 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
67 | } | ||
68 | }; | ||
69 | |||
70 | struct mt9t031 { | 63 | struct mt9t031 { |
71 | struct v4l2_subdev subdev; | 64 | struct v4l2_subdev subdev; |
72 | struct v4l2_rect rect; /* Sensor window */ | 65 | struct v4l2_rect rect; /* Sensor window */ |
@@ -74,6 +67,7 @@ struct mt9t031 { | |||
74 | u16 xskip; | 67 | u16 xskip; |
75 | u16 yskip; | 68 | u16 yskip; |
76 | unsigned int gain; | 69 | unsigned int gain; |
70 | unsigned short y_skip_top; /* Lines to skip at the top */ | ||
77 | unsigned int exposure; | 71 | unsigned int exposure; |
78 | unsigned char autoexposure; | 72 | unsigned char autoexposure; |
79 | }; | 73 | }; |
@@ -207,6 +201,71 @@ static unsigned long mt9t031_query_bus_param(struct soc_camera_device *icd) | |||
207 | return soc_camera_apply_sensor_flags(icl, MT9T031_BUS_PARAM); | 201 | return soc_camera_apply_sensor_flags(icl, MT9T031_BUS_PARAM); |
208 | } | 202 | } |
209 | 203 | ||
204 | enum { | ||
205 | MT9T031_CTRL_VFLIP, | ||
206 | MT9T031_CTRL_HFLIP, | ||
207 | MT9T031_CTRL_GAIN, | ||
208 | MT9T031_CTRL_EXPOSURE, | ||
209 | MT9T031_CTRL_EXPOSURE_AUTO, | ||
210 | }; | ||
211 | |||
212 | static const struct v4l2_queryctrl mt9t031_controls[] = { | ||
213 | [MT9T031_CTRL_VFLIP] = { | ||
214 | .id = V4L2_CID_VFLIP, | ||
215 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
216 | .name = "Flip Vertically", | ||
217 | .minimum = 0, | ||
218 | .maximum = 1, | ||
219 | .step = 1, | ||
220 | .default_value = 0, | ||
221 | }, | ||
222 | [MT9T031_CTRL_HFLIP] = { | ||
223 | .id = V4L2_CID_HFLIP, | ||
224 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
225 | .name = "Flip Horizontally", | ||
226 | .minimum = 0, | ||
227 | .maximum = 1, | ||
228 | .step = 1, | ||
229 | .default_value = 0, | ||
230 | }, | ||
231 | [MT9T031_CTRL_GAIN] = { | ||
232 | .id = V4L2_CID_GAIN, | ||
233 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
234 | .name = "Gain", | ||
235 | .minimum = 0, | ||
236 | .maximum = 127, | ||
237 | .step = 1, | ||
238 | .default_value = 64, | ||
239 | .flags = V4L2_CTRL_FLAG_SLIDER, | ||
240 | }, | ||
241 | [MT9T031_CTRL_EXPOSURE] = { | ||
242 | .id = V4L2_CID_EXPOSURE, | ||
243 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
244 | .name = "Exposure", | ||
245 | .minimum = 1, | ||
246 | .maximum = 255, | ||
247 | .step = 1, | ||
248 | .default_value = 255, | ||
249 | .flags = V4L2_CTRL_FLAG_SLIDER, | ||
250 | }, | ||
251 | [MT9T031_CTRL_EXPOSURE_AUTO] = { | ||
252 | .id = V4L2_CID_EXPOSURE_AUTO, | ||
253 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
254 | .name = "Automatic Exposure", | ||
255 | .minimum = 0, | ||
256 | .maximum = 1, | ||
257 | .step = 1, | ||
258 | .default_value = 1, | ||
259 | } | ||
260 | }; | ||
261 | |||
262 | static struct soc_camera_ops mt9t031_ops = { | ||
263 | .set_bus_param = mt9t031_set_bus_param, | ||
264 | .query_bus_param = mt9t031_query_bus_param, | ||
265 | .controls = mt9t031_controls, | ||
266 | .num_controls = ARRAY_SIZE(mt9t031_controls), | ||
267 | }; | ||
268 | |||
210 | /* target must be _even_ */ | 269 | /* target must be _even_ */ |
211 | static u16 mt9t031_skip(s32 *source, s32 target, s32 max) | 270 | static u16 mt9t031_skip(s32 *source, s32 target, s32 max) |
212 | { | 271 | { |
@@ -226,10 +285,9 @@ static u16 mt9t031_skip(s32 *source, s32 target, s32 max) | |||
226 | } | 285 | } |
227 | 286 | ||
228 | /* rect is the sensor rectangle, the caller guarantees parameter validity */ | 287 | /* rect is the sensor rectangle, the caller guarantees parameter validity */ |
229 | static int mt9t031_set_params(struct soc_camera_device *icd, | 288 | static int mt9t031_set_params(struct i2c_client *client, |
230 | struct v4l2_rect *rect, u16 xskip, u16 yskip) | 289 | struct v4l2_rect *rect, u16 xskip, u16 yskip) |
231 | { | 290 | { |
232 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | ||
233 | struct mt9t031 *mt9t031 = to_mt9t031(client); | 291 | struct mt9t031 *mt9t031 = to_mt9t031(client); |
234 | int ret; | 292 | int ret; |
235 | u16 xbin, ybin; | 293 | u16 xbin, ybin; |
@@ -291,8 +349,10 @@ static int mt9t031_set_params(struct soc_camera_device *icd, | |||
291 | dev_dbg(&client->dev, "new physical left %u, top %u\n", | 349 | dev_dbg(&client->dev, "new physical left %u, top %u\n", |
292 | rect->left, rect->top); | 350 | rect->left, rect->top); |
293 | 351 | ||
294 | /* The caller provides a supported format, as guaranteed by | 352 | /* |
295 | * icd->try_fmt_cap(), soc_camera_s_crop() and soc_camera_cropcap() */ | 353 | * The caller provides a supported format, as guaranteed by |
354 | * icd->try_fmt_cap(), soc_camera_s_crop() and soc_camera_cropcap() | ||
355 | */ | ||
296 | if (ret >= 0) | 356 | if (ret >= 0) |
297 | ret = reg_write(client, MT9T031_COLUMN_START, rect->left); | 357 | ret = reg_write(client, MT9T031_COLUMN_START, rect->left); |
298 | if (ret >= 0) | 358 | if (ret >= 0) |
@@ -301,15 +361,14 @@ static int mt9t031_set_params(struct soc_camera_device *icd, | |||
301 | ret = reg_write(client, MT9T031_WINDOW_WIDTH, rect->width - 1); | 361 | ret = reg_write(client, MT9T031_WINDOW_WIDTH, rect->width - 1); |
302 | if (ret >= 0) | 362 | if (ret >= 0) |
303 | ret = reg_write(client, MT9T031_WINDOW_HEIGHT, | 363 | ret = reg_write(client, MT9T031_WINDOW_HEIGHT, |
304 | rect->height + icd->y_skip_top - 1); | 364 | rect->height + mt9t031->y_skip_top - 1); |
305 | if (ret >= 0 && mt9t031->autoexposure) { | 365 | if (ret >= 0 && mt9t031->autoexposure) { |
306 | unsigned int total_h = rect->height + icd->y_skip_top + vblank; | 366 | unsigned int total_h = rect->height + mt9t031->y_skip_top + vblank; |
307 | ret = set_shutter(client, total_h); | 367 | ret = set_shutter(client, total_h); |
308 | if (ret >= 0) { | 368 | if (ret >= 0) { |
309 | const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank; | 369 | const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank; |
310 | const struct v4l2_queryctrl *qctrl = | 370 | const struct v4l2_queryctrl *qctrl = |
311 | soc_camera_find_qctrl(icd->ops, | 371 | &mt9t031_controls[MT9T031_CTRL_EXPOSURE]; |
312 | V4L2_CID_EXPOSURE); | ||
313 | mt9t031->exposure = (shutter_max / 2 + (total_h - 1) * | 372 | mt9t031->exposure = (shutter_max / 2 + (total_h - 1) * |
314 | (qctrl->maximum - qctrl->minimum)) / | 373 | (qctrl->maximum - qctrl->minimum)) / |
315 | shutter_max + qctrl->minimum; | 374 | shutter_max + qctrl->minimum; |
@@ -334,7 +393,6 @@ static int mt9t031_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) | |||
334 | struct v4l2_rect rect = a->c; | 393 | struct v4l2_rect rect = a->c; |
335 | struct i2c_client *client = sd->priv; | 394 | struct i2c_client *client = sd->priv; |
336 | struct mt9t031 *mt9t031 = to_mt9t031(client); | 395 | struct mt9t031 *mt9t031 = to_mt9t031(client); |
337 | struct soc_camera_device *icd = client->dev.platform_data; | ||
338 | 396 | ||
339 | rect.width = ALIGN(rect.width, 2); | 397 | rect.width = ALIGN(rect.width, 2); |
340 | rect.height = ALIGN(rect.height, 2); | 398 | rect.height = ALIGN(rect.height, 2); |
@@ -345,7 +403,7 @@ static int mt9t031_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) | |||
345 | soc_camera_limit_side(&rect.top, &rect.height, | 403 | soc_camera_limit_side(&rect.top, &rect.height, |
346 | MT9T031_ROW_SKIP, MT9T031_MIN_HEIGHT, MT9T031_MAX_HEIGHT); | 404 | MT9T031_ROW_SKIP, MT9T031_MIN_HEIGHT, MT9T031_MAX_HEIGHT); |
347 | 405 | ||
348 | return mt9t031_set_params(icd, &rect, mt9t031->xskip, mt9t031->yskip); | 406 | return mt9t031_set_params(client, &rect, mt9t031->xskip, mt9t031->yskip); |
349 | } | 407 | } |
350 | 408 | ||
351 | static int mt9t031_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) | 409 | static int mt9t031_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) |
@@ -373,27 +431,26 @@ static int mt9t031_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) | |||
373 | return 0; | 431 | return 0; |
374 | } | 432 | } |
375 | 433 | ||
376 | static int mt9t031_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | 434 | static int mt9t031_g_fmt(struct v4l2_subdev *sd, |
435 | struct v4l2_mbus_framefmt *mf) | ||
377 | { | 436 | { |
378 | struct i2c_client *client = sd->priv; | 437 | struct i2c_client *client = sd->priv; |
379 | struct mt9t031 *mt9t031 = to_mt9t031(client); | 438 | struct mt9t031 *mt9t031 = to_mt9t031(client); |
380 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
381 | 439 | ||
382 | pix->width = mt9t031->rect.width / mt9t031->xskip; | 440 | mf->width = mt9t031->rect.width / mt9t031->xskip; |
383 | pix->height = mt9t031->rect.height / mt9t031->yskip; | 441 | mf->height = mt9t031->rect.height / mt9t031->yskip; |
384 | pix->pixelformat = V4L2_PIX_FMT_SGRBG10; | 442 | mf->code = V4L2_MBUS_FMT_SBGGR10_1X10; |
385 | pix->field = V4L2_FIELD_NONE; | 443 | mf->colorspace = V4L2_COLORSPACE_SRGB; |
386 | pix->colorspace = V4L2_COLORSPACE_SRGB; | 444 | mf->field = V4L2_FIELD_NONE; |
387 | 445 | ||
388 | return 0; | 446 | return 0; |
389 | } | 447 | } |
390 | 448 | ||
391 | static int mt9t031_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | 449 | static int mt9t031_s_fmt(struct v4l2_subdev *sd, |
450 | struct v4l2_mbus_framefmt *mf) | ||
392 | { | 451 | { |
393 | struct i2c_client *client = sd->priv; | 452 | struct i2c_client *client = sd->priv; |
394 | struct mt9t031 *mt9t031 = to_mt9t031(client); | 453 | struct mt9t031 *mt9t031 = to_mt9t031(client); |
395 | struct soc_camera_device *icd = client->dev.platform_data; | ||
396 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
397 | u16 xskip, yskip; | 454 | u16 xskip, yskip; |
398 | struct v4l2_rect rect = mt9t031->rect; | 455 | struct v4l2_rect rect = mt9t031->rect; |
399 | 456 | ||
@@ -401,24 +458,29 @@ static int mt9t031_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | |||
401 | * try_fmt has put width and height within limits. | 458 | * try_fmt has put width and height within limits. |
402 | * S_FMT: use binning and skipping for scaling | 459 | * S_FMT: use binning and skipping for scaling |
403 | */ | 460 | */ |
404 | xskip = mt9t031_skip(&rect.width, pix->width, MT9T031_MAX_WIDTH); | 461 | xskip = mt9t031_skip(&rect.width, mf->width, MT9T031_MAX_WIDTH); |
405 | yskip = mt9t031_skip(&rect.height, pix->height, MT9T031_MAX_HEIGHT); | 462 | yskip = mt9t031_skip(&rect.height, mf->height, MT9T031_MAX_HEIGHT); |
463 | |||
464 | mf->code = V4L2_MBUS_FMT_SBGGR10_1X10; | ||
465 | mf->colorspace = V4L2_COLORSPACE_SRGB; | ||
406 | 466 | ||
407 | /* mt9t031_set_params() doesn't change width and height */ | 467 | /* mt9t031_set_params() doesn't change width and height */ |
408 | return mt9t031_set_params(icd, &rect, xskip, yskip); | 468 | return mt9t031_set_params(client, &rect, xskip, yskip); |
409 | } | 469 | } |
410 | 470 | ||
411 | /* | 471 | /* |
412 | * If a user window larger than sensor window is requested, we'll increase the | 472 | * If a user window larger than sensor window is requested, we'll increase the |
413 | * sensor window. | 473 | * sensor window. |
414 | */ | 474 | */ |
415 | static int mt9t031_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | 475 | static int mt9t031_try_fmt(struct v4l2_subdev *sd, |
476 | struct v4l2_mbus_framefmt *mf) | ||
416 | { | 477 | { |
417 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
418 | |||
419 | v4l_bound_align_image( | 478 | v4l_bound_align_image( |
420 | &pix->width, MT9T031_MIN_WIDTH, MT9T031_MAX_WIDTH, 1, | 479 | &mf->width, MT9T031_MIN_WIDTH, MT9T031_MAX_WIDTH, 1, |
421 | &pix->height, MT9T031_MIN_HEIGHT, MT9T031_MAX_HEIGHT, 1, 0); | 480 | &mf->height, MT9T031_MIN_HEIGHT, MT9T031_MAX_HEIGHT, 1, 0); |
481 | |||
482 | mf->code = V4L2_MBUS_FMT_SBGGR10_1X10; | ||
483 | mf->colorspace = V4L2_COLORSPACE_SRGB; | ||
422 | 484 | ||
423 | return 0; | 485 | return 0; |
424 | } | 486 | } |
@@ -479,59 +541,6 @@ static int mt9t031_s_register(struct v4l2_subdev *sd, | |||
479 | } | 541 | } |
480 | #endif | 542 | #endif |
481 | 543 | ||
482 | static const struct v4l2_queryctrl mt9t031_controls[] = { | ||
483 | { | ||
484 | .id = V4L2_CID_VFLIP, | ||
485 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
486 | .name = "Flip Vertically", | ||
487 | .minimum = 0, | ||
488 | .maximum = 1, | ||
489 | .step = 1, | ||
490 | .default_value = 0, | ||
491 | }, { | ||
492 | .id = V4L2_CID_HFLIP, | ||
493 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
494 | .name = "Flip Horizontally", | ||
495 | .minimum = 0, | ||
496 | .maximum = 1, | ||
497 | .step = 1, | ||
498 | .default_value = 0, | ||
499 | }, { | ||
500 | .id = V4L2_CID_GAIN, | ||
501 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
502 | .name = "Gain", | ||
503 | .minimum = 0, | ||
504 | .maximum = 127, | ||
505 | .step = 1, | ||
506 | .default_value = 64, | ||
507 | .flags = V4L2_CTRL_FLAG_SLIDER, | ||
508 | }, { | ||
509 | .id = V4L2_CID_EXPOSURE, | ||
510 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
511 | .name = "Exposure", | ||
512 | .minimum = 1, | ||
513 | .maximum = 255, | ||
514 | .step = 1, | ||
515 | .default_value = 255, | ||
516 | .flags = V4L2_CTRL_FLAG_SLIDER, | ||
517 | }, { | ||
518 | .id = V4L2_CID_EXPOSURE_AUTO, | ||
519 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
520 | .name = "Automatic Exposure", | ||
521 | .minimum = 0, | ||
522 | .maximum = 1, | ||
523 | .step = 1, | ||
524 | .default_value = 1, | ||
525 | } | ||
526 | }; | ||
527 | |||
528 | static struct soc_camera_ops mt9t031_ops = { | ||
529 | .set_bus_param = mt9t031_set_bus_param, | ||
530 | .query_bus_param = mt9t031_query_bus_param, | ||
531 | .controls = mt9t031_controls, | ||
532 | .num_controls = ARRAY_SIZE(mt9t031_controls), | ||
533 | }; | ||
534 | |||
535 | static int mt9t031_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | 544 | static int mt9t031_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) |
536 | { | 545 | { |
537 | struct i2c_client *client = sd->priv; | 546 | struct i2c_client *client = sd->priv; |
@@ -568,15 +577,9 @@ static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | |||
568 | { | 577 | { |
569 | struct i2c_client *client = sd->priv; | 578 | struct i2c_client *client = sd->priv; |
570 | struct mt9t031 *mt9t031 = to_mt9t031(client); | 579 | struct mt9t031 *mt9t031 = to_mt9t031(client); |
571 | struct soc_camera_device *icd = client->dev.platform_data; | ||
572 | const struct v4l2_queryctrl *qctrl; | 580 | const struct v4l2_queryctrl *qctrl; |
573 | int data; | 581 | int data; |
574 | 582 | ||
575 | qctrl = soc_camera_find_qctrl(&mt9t031_ops, ctrl->id); | ||
576 | |||
577 | if (!qctrl) | ||
578 | return -EINVAL; | ||
579 | |||
580 | switch (ctrl->id) { | 583 | switch (ctrl->id) { |
581 | case V4L2_CID_VFLIP: | 584 | case V4L2_CID_VFLIP: |
582 | if (ctrl->value) | 585 | if (ctrl->value) |
@@ -595,6 +598,7 @@ static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | |||
595 | return -EIO; | 598 | return -EIO; |
596 | break; | 599 | break; |
597 | case V4L2_CID_GAIN: | 600 | case V4L2_CID_GAIN: |
601 | qctrl = &mt9t031_controls[MT9T031_CTRL_GAIN]; | ||
598 | if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum) | 602 | if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum) |
599 | return -EINVAL; | 603 | return -EINVAL; |
600 | /* See Datasheet Table 7, Gain settings. */ | 604 | /* See Datasheet Table 7, Gain settings. */ |
@@ -634,6 +638,7 @@ static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | |||
634 | mt9t031->gain = ctrl->value; | 638 | mt9t031->gain = ctrl->value; |
635 | break; | 639 | break; |
636 | case V4L2_CID_EXPOSURE: | 640 | case V4L2_CID_EXPOSURE: |
641 | qctrl = &mt9t031_controls[MT9T031_CTRL_EXPOSURE]; | ||
637 | /* mt9t031 has maximum == default */ | 642 | /* mt9t031 has maximum == default */ |
638 | if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum) | 643 | if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum) |
639 | return -EINVAL; | 644 | return -EINVAL; |
@@ -657,11 +662,11 @@ static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | |||
657 | const u16 vblank = MT9T031_VERTICAL_BLANK; | 662 | const u16 vblank = MT9T031_VERTICAL_BLANK; |
658 | const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank; | 663 | const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank; |
659 | unsigned int total_h = mt9t031->rect.height + | 664 | unsigned int total_h = mt9t031->rect.height + |
660 | icd->y_skip_top + vblank; | 665 | mt9t031->y_skip_top + vblank; |
661 | 666 | ||
662 | if (set_shutter(client, total_h) < 0) | 667 | if (set_shutter(client, total_h) < 0) |
663 | return -EIO; | 668 | return -EIO; |
664 | qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); | 669 | qctrl = &mt9t031_controls[MT9T031_CTRL_EXPOSURE]; |
665 | mt9t031->exposure = (shutter_max / 2 + (total_h - 1) * | 670 | mt9t031->exposure = (shutter_max / 2 + (total_h - 1) * |
666 | (qctrl->maximum - qctrl->minimum)) / | 671 | (qctrl->maximum - qctrl->minimum)) / |
667 | shutter_max + qctrl->minimum; | 672 | shutter_max + qctrl->minimum; |
@@ -669,15 +674,18 @@ static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | |||
669 | } else | 674 | } else |
670 | mt9t031->autoexposure = 0; | 675 | mt9t031->autoexposure = 0; |
671 | break; | 676 | break; |
677 | default: | ||
678 | return -EINVAL; | ||
672 | } | 679 | } |
673 | return 0; | 680 | return 0; |
674 | } | 681 | } |
675 | 682 | ||
676 | /* Interface active, can use i2c. If it fails, it can indeed mean, that | 683 | /* |
677 | * this wasn't our capture interface, so, we wait for the right one */ | 684 | * Interface active, can use i2c. If it fails, it can indeed mean, that |
685 | * this wasn't our capture interface, so, we wait for the right one | ||
686 | */ | ||
678 | static int mt9t031_video_probe(struct i2c_client *client) | 687 | static int mt9t031_video_probe(struct i2c_client *client) |
679 | { | 688 | { |
680 | struct soc_camera_device *icd = client->dev.platform_data; | ||
681 | struct mt9t031 *mt9t031 = to_mt9t031(client); | 689 | struct mt9t031 *mt9t031 = to_mt9t031(client); |
682 | s32 data; | 690 | s32 data; |
683 | int ret; | 691 | int ret; |
@@ -692,8 +700,6 @@ static int mt9t031_video_probe(struct i2c_client *client) | |||
692 | switch (data) { | 700 | switch (data) { |
693 | case 0x1621: | 701 | case 0x1621: |
694 | mt9t031->model = V4L2_IDENT_MT9T031; | 702 | mt9t031->model = V4L2_IDENT_MT9T031; |
695 | icd->formats = mt9t031_colour_formats; | ||
696 | icd->num_formats = ARRAY_SIZE(mt9t031_colour_formats); | ||
697 | break; | 703 | break; |
698 | default: | 704 | default: |
699 | dev_err(&client->dev, | 705 | dev_err(&client->dev, |
@@ -714,6 +720,16 @@ static int mt9t031_video_probe(struct i2c_client *client) | |||
714 | return ret; | 720 | return ret; |
715 | } | 721 | } |
716 | 722 | ||
723 | static int mt9t031_g_skip_top_lines(struct v4l2_subdev *sd, u32 *lines) | ||
724 | { | ||
725 | struct i2c_client *client = sd->priv; | ||
726 | struct mt9t031 *mt9t031 = to_mt9t031(client); | ||
727 | |||
728 | *lines = mt9t031->y_skip_top; | ||
729 | |||
730 | return 0; | ||
731 | } | ||
732 | |||
717 | static struct v4l2_subdev_core_ops mt9t031_subdev_core_ops = { | 733 | static struct v4l2_subdev_core_ops mt9t031_subdev_core_ops = { |
718 | .g_ctrl = mt9t031_g_ctrl, | 734 | .g_ctrl = mt9t031_g_ctrl, |
719 | .s_ctrl = mt9t031_s_ctrl, | 735 | .s_ctrl = mt9t031_s_ctrl, |
@@ -724,19 +740,35 @@ static struct v4l2_subdev_core_ops mt9t031_subdev_core_ops = { | |||
724 | #endif | 740 | #endif |
725 | }; | 741 | }; |
726 | 742 | ||
743 | static int mt9t031_enum_fmt(struct v4l2_subdev *sd, int index, | ||
744 | enum v4l2_mbus_pixelcode *code) | ||
745 | { | ||
746 | if (index) | ||
747 | return -EINVAL; | ||
748 | |||
749 | *code = V4L2_MBUS_FMT_SBGGR10_1X10; | ||
750 | return 0; | ||
751 | } | ||
752 | |||
727 | static struct v4l2_subdev_video_ops mt9t031_subdev_video_ops = { | 753 | static struct v4l2_subdev_video_ops mt9t031_subdev_video_ops = { |
728 | .s_stream = mt9t031_s_stream, | 754 | .s_stream = mt9t031_s_stream, |
729 | .s_fmt = mt9t031_s_fmt, | 755 | .s_mbus_fmt = mt9t031_s_fmt, |
730 | .g_fmt = mt9t031_g_fmt, | 756 | .g_mbus_fmt = mt9t031_g_fmt, |
731 | .try_fmt = mt9t031_try_fmt, | 757 | .try_mbus_fmt = mt9t031_try_fmt, |
732 | .s_crop = mt9t031_s_crop, | 758 | .s_crop = mt9t031_s_crop, |
733 | .g_crop = mt9t031_g_crop, | 759 | .g_crop = mt9t031_g_crop, |
734 | .cropcap = mt9t031_cropcap, | 760 | .cropcap = mt9t031_cropcap, |
761 | .enum_mbus_fmt = mt9t031_enum_fmt, | ||
762 | }; | ||
763 | |||
764 | static struct v4l2_subdev_sensor_ops mt9t031_subdev_sensor_ops = { | ||
765 | .g_skip_top_lines = mt9t031_g_skip_top_lines, | ||
735 | }; | 766 | }; |
736 | 767 | ||
737 | static struct v4l2_subdev_ops mt9t031_subdev_ops = { | 768 | static struct v4l2_subdev_ops mt9t031_subdev_ops = { |
738 | .core = &mt9t031_subdev_core_ops, | 769 | .core = &mt9t031_subdev_core_ops, |
739 | .video = &mt9t031_subdev_video_ops, | 770 | .video = &mt9t031_subdev_video_ops, |
771 | .sensor = &mt9t031_subdev_sensor_ops, | ||
740 | }; | 772 | }; |
741 | 773 | ||
742 | static int mt9t031_probe(struct i2c_client *client, | 774 | static int mt9t031_probe(struct i2c_client *client, |
@@ -745,18 +777,16 @@ static int mt9t031_probe(struct i2c_client *client, | |||
745 | struct mt9t031 *mt9t031; | 777 | struct mt9t031 *mt9t031; |
746 | struct soc_camera_device *icd = client->dev.platform_data; | 778 | struct soc_camera_device *icd = client->dev.platform_data; |
747 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); | 779 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); |
748 | struct soc_camera_link *icl; | ||
749 | int ret; | 780 | int ret; |
750 | 781 | ||
751 | if (!icd) { | 782 | if (icd) { |
752 | dev_err(&client->dev, "MT9T031: missing soc-camera data!\n"); | 783 | struct soc_camera_link *icl = to_soc_camera_link(icd); |
753 | return -EINVAL; | 784 | if (!icl) { |
754 | } | 785 | dev_err(&client->dev, "MT9T031 driver needs platform data\n"); |
786 | return -EINVAL; | ||
787 | } | ||
755 | 788 | ||
756 | icl = to_soc_camera_link(icd); | 789 | icd->ops = &mt9t031_ops; |
757 | if (!icl) { | ||
758 | dev_err(&client->dev, "MT9T031 driver needs platform data\n"); | ||
759 | return -EINVAL; | ||
760 | } | 790 | } |
761 | 791 | ||
762 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) { | 792 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) { |
@@ -771,17 +801,16 @@ static int mt9t031_probe(struct i2c_client *client, | |||
771 | 801 | ||
772 | v4l2_i2c_subdev_init(&mt9t031->subdev, client, &mt9t031_subdev_ops); | 802 | v4l2_i2c_subdev_init(&mt9t031->subdev, client, &mt9t031_subdev_ops); |
773 | 803 | ||
774 | /* Second stage probe - when a capture adapter is there */ | 804 | mt9t031->y_skip_top = 0; |
775 | icd->ops = &mt9t031_ops; | ||
776 | icd->y_skip_top = 0; | ||
777 | |||
778 | mt9t031->rect.left = MT9T031_COLUMN_SKIP; | 805 | mt9t031->rect.left = MT9T031_COLUMN_SKIP; |
779 | mt9t031->rect.top = MT9T031_ROW_SKIP; | 806 | mt9t031->rect.top = MT9T031_ROW_SKIP; |
780 | mt9t031->rect.width = MT9T031_MAX_WIDTH; | 807 | mt9t031->rect.width = MT9T031_MAX_WIDTH; |
781 | mt9t031->rect.height = MT9T031_MAX_HEIGHT; | 808 | mt9t031->rect.height = MT9T031_MAX_HEIGHT; |
782 | 809 | ||
783 | /* Simulated autoexposure. If enabled, we calculate shutter width | 810 | /* |
784 | * ourselves in the driver based on vertical blanking and frame width */ | 811 | * Simulated autoexposure. If enabled, we calculate shutter width |
812 | * ourselves in the driver based on vertical blanking and frame width | ||
813 | */ | ||
785 | mt9t031->autoexposure = 1; | 814 | mt9t031->autoexposure = 1; |
786 | 815 | ||
787 | mt9t031->xskip = 1; | 816 | mt9t031->xskip = 1; |
@@ -794,7 +823,8 @@ static int mt9t031_probe(struct i2c_client *client, | |||
794 | mt9t031_disable(client); | 823 | mt9t031_disable(client); |
795 | 824 | ||
796 | if (ret) { | 825 | if (ret) { |
797 | icd->ops = NULL; | 826 | if (icd) |
827 | icd->ops = NULL; | ||
798 | i2c_set_clientdata(client, NULL); | 828 | i2c_set_clientdata(client, NULL); |
799 | kfree(mt9t031); | 829 | kfree(mt9t031); |
800 | } | 830 | } |
@@ -807,7 +837,8 @@ static int mt9t031_remove(struct i2c_client *client) | |||
807 | struct mt9t031 *mt9t031 = to_mt9t031(client); | 837 | struct mt9t031 *mt9t031 = to_mt9t031(client); |
808 | struct soc_camera_device *icd = client->dev.platform_data; | 838 | struct soc_camera_device *icd = client->dev.platform_data; |
809 | 839 | ||
810 | icd->ops = NULL; | 840 | if (icd) |
841 | icd->ops = NULL; | ||
811 | i2c_set_clientdata(client, NULL); | 842 | i2c_set_clientdata(client, NULL); |
812 | client->driver = NULL; | 843 | client->driver = NULL; |
813 | kfree(mt9t031); | 844 | kfree(mt9t031); |
diff --git a/drivers/media/video/mt9t112.c b/drivers/media/video/mt9t112.c new file mode 100644 index 000000000000..fc4dd6045720 --- /dev/null +++ b/drivers/media/video/mt9t112.c | |||
@@ -0,0 +1,1177 @@ | |||
1 | /* | ||
2 | * mt9t112 Camera Driver | ||
3 | * | ||
4 | * Copyright (C) 2009 Renesas Solutions Corp. | ||
5 | * Kuninori Morimoto <morimoto.kuninori@renesas.com> | ||
6 | * | ||
7 | * Based on ov772x driver, mt9m111 driver, | ||
8 | * | ||
9 | * Copyright (C) 2008 Kuninori Morimoto <morimoto.kuninori@renesas.com> | ||
10 | * Copyright (C) 2008, Robert Jarzmik <robert.jarzmik@free.fr> | ||
11 | * Copyright 2006-7 Jonathan Corbet <corbet@lwn.net> | ||
12 | * Copyright (C) 2008 Magnus Damm | ||
13 | * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de> | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or modify | ||
16 | * it under the terms of the GNU General Public License version 2 as | ||
17 | * published by the Free Software Foundation. | ||
18 | */ | ||
19 | |||
20 | #include <linux/delay.h> | ||
21 | #include <linux/i2c.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include <linux/videodev2.h> | ||
26 | |||
27 | #include <media/mt9t112.h> | ||
28 | #include <media/soc_camera.h> | ||
29 | #include <media/soc_mediabus.h> | ||
30 | #include <media/v4l2-chip-ident.h> | ||
31 | #include <media/v4l2-common.h> | ||
32 | |||
33 | /* you can check PLL/clock info */ | ||
34 | /* #define EXT_CLOCK 24000000 */ | ||
35 | |||
36 | /************************************************************************ | ||
37 | |||
38 | |||
39 | macro | ||
40 | |||
41 | |||
42 | ************************************************************************/ | ||
43 | /* | ||
44 | * frame size | ||
45 | */ | ||
46 | #define MAX_WIDTH 2048 | ||
47 | #define MAX_HEIGHT 1536 | ||
48 | |||
49 | #define VGA_WIDTH 640 | ||
50 | #define VGA_HEIGHT 480 | ||
51 | |||
52 | /* | ||
53 | * macro of read/write | ||
54 | */ | ||
55 | #define ECHECKER(ret, x) \ | ||
56 | do { \ | ||
57 | (ret) = (x); \ | ||
58 | if ((ret) < 0) \ | ||
59 | return (ret); \ | ||
60 | } while (0) | ||
61 | |||
62 | #define mt9t112_reg_write(ret, client, a, b) \ | ||
63 | ECHECKER(ret, __mt9t112_reg_write(client, a, b)) | ||
64 | #define mt9t112_mcu_write(ret, client, a, b) \ | ||
65 | ECHECKER(ret, __mt9t112_mcu_write(client, a, b)) | ||
66 | |||
67 | #define mt9t112_reg_mask_set(ret, client, a, b, c) \ | ||
68 | ECHECKER(ret, __mt9t112_reg_mask_set(client, a, b, c)) | ||
69 | #define mt9t112_mcu_mask_set(ret, client, a, b, c) \ | ||
70 | ECHECKER(ret, __mt9t112_mcu_mask_set(client, a, b, c)) | ||
71 | |||
72 | #define mt9t112_reg_read(ret, client, a) \ | ||
73 | ECHECKER(ret, __mt9t112_reg_read(client, a)) | ||
74 | |||
75 | /* | ||
76 | * Logical address | ||
77 | */ | ||
78 | #define _VAR(id, offset, base) (base | (id & 0x1f) << 10 | (offset & 0x3ff)) | ||
79 | #define VAR(id, offset) _VAR(id, offset, 0x0000) | ||
80 | #define VAR8(id, offset) _VAR(id, offset, 0x8000) | ||
81 | |||
82 | /************************************************************************ | ||
83 | |||
84 | |||
85 | struct | ||
86 | |||
87 | |||
88 | ************************************************************************/ | ||
89 | struct mt9t112_frame_size { | ||
90 | u16 width; | ||
91 | u16 height; | ||
92 | }; | ||
93 | |||
94 | struct mt9t112_format { | ||
95 | enum v4l2_mbus_pixelcode code; | ||
96 | enum v4l2_colorspace colorspace; | ||
97 | u16 fmt; | ||
98 | u16 order; | ||
99 | }; | ||
100 | |||
101 | struct mt9t112_priv { | ||
102 | struct v4l2_subdev subdev; | ||
103 | struct mt9t112_camera_info *info; | ||
104 | struct i2c_client *client; | ||
105 | struct soc_camera_device icd; | ||
106 | struct mt9t112_frame_size frame; | ||
107 | const struct mt9t112_format *format; | ||
108 | int model; | ||
109 | u32 flags; | ||
110 | /* for flags */ | ||
111 | #define INIT_DONE (1<<0) | ||
112 | }; | ||
113 | |||
114 | /************************************************************************ | ||
115 | |||
116 | |||
117 | supported format | ||
118 | |||
119 | |||
120 | ************************************************************************/ | ||
121 | |||
122 | static const struct mt9t112_format mt9t112_cfmts[] = { | ||
123 | { | ||
124 | .code = V4L2_MBUS_FMT_YUYV8_2X8_BE, | ||
125 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
126 | .fmt = 1, | ||
127 | .order = 0, | ||
128 | }, { | ||
129 | .code = V4L2_MBUS_FMT_YVYU8_2X8_BE, | ||
130 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
131 | .fmt = 1, | ||
132 | .order = 1, | ||
133 | }, { | ||
134 | .code = V4L2_MBUS_FMT_YUYV8_2X8_LE, | ||
135 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
136 | .fmt = 1, | ||
137 | .order = 2, | ||
138 | }, { | ||
139 | .code = V4L2_MBUS_FMT_YVYU8_2X8_LE, | ||
140 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
141 | .fmt = 1, | ||
142 | .order = 3, | ||
143 | }, { | ||
144 | .code = V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE, | ||
145 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
146 | .fmt = 8, | ||
147 | .order = 2, | ||
148 | }, { | ||
149 | .code = V4L2_MBUS_FMT_RGB565_2X8_LE, | ||
150 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
151 | .fmt = 4, | ||
152 | .order = 2, | ||
153 | }, | ||
154 | }; | ||
155 | |||
156 | /************************************************************************ | ||
157 | |||
158 | |||
159 | general function | ||
160 | |||
161 | |||
162 | ************************************************************************/ | ||
163 | static struct mt9t112_priv *to_mt9t112(const struct i2c_client *client) | ||
164 | { | ||
165 | return container_of(i2c_get_clientdata(client), | ||
166 | struct mt9t112_priv, | ||
167 | subdev); | ||
168 | } | ||
169 | |||
170 | static int __mt9t112_reg_read(const struct i2c_client *client, u16 command) | ||
171 | { | ||
172 | struct i2c_msg msg[2]; | ||
173 | u8 buf[2]; | ||
174 | int ret; | ||
175 | |||
176 | command = swab16(command); | ||
177 | |||
178 | msg[0].addr = client->addr; | ||
179 | msg[0].flags = 0; | ||
180 | msg[0].len = 2; | ||
181 | msg[0].buf = (u8 *)&command; | ||
182 | |||
183 | msg[1].addr = client->addr; | ||
184 | msg[1].flags = I2C_M_RD; | ||
185 | msg[1].len = 2; | ||
186 | msg[1].buf = buf; | ||
187 | |||
188 | /* | ||
189 | * if return value of this function is < 0, | ||
190 | * it mean error. | ||
191 | * else, under 16bit is valid data. | ||
192 | */ | ||
193 | ret = i2c_transfer(client->adapter, msg, 2); | ||
194 | if (ret < 0) | ||
195 | return ret; | ||
196 | |||
197 | memcpy(&ret, buf, 2); | ||
198 | return swab16(ret); | ||
199 | } | ||
200 | |||
201 | static int __mt9t112_reg_write(const struct i2c_client *client, | ||
202 | u16 command, u16 data) | ||
203 | { | ||
204 | struct i2c_msg msg; | ||
205 | u8 buf[4]; | ||
206 | int ret; | ||
207 | |||
208 | command = swab16(command); | ||
209 | data = swab16(data); | ||
210 | |||
211 | memcpy(buf + 0, &command, 2); | ||
212 | memcpy(buf + 2, &data, 2); | ||
213 | |||
214 | msg.addr = client->addr; | ||
215 | msg.flags = 0; | ||
216 | msg.len = 4; | ||
217 | msg.buf = buf; | ||
218 | |||
219 | /* | ||
220 | * i2c_transfer return message length, | ||
221 | * but this function should return 0 if correct case | ||
222 | */ | ||
223 | ret = i2c_transfer(client->adapter, &msg, 1); | ||
224 | if (ret >= 0) | ||
225 | ret = 0; | ||
226 | |||
227 | return ret; | ||
228 | } | ||
229 | |||
230 | static int __mt9t112_reg_mask_set(const struct i2c_client *client, | ||
231 | u16 command, | ||
232 | u16 mask, | ||
233 | u16 set) | ||
234 | { | ||
235 | int val = __mt9t112_reg_read(client, command); | ||
236 | if (val < 0) | ||
237 | return val; | ||
238 | |||
239 | val &= ~mask; | ||
240 | val |= set & mask; | ||
241 | |||
242 | return __mt9t112_reg_write(client, command, val); | ||
243 | } | ||
244 | |||
245 | /* mcu access */ | ||
246 | static int __mt9t112_mcu_read(const struct i2c_client *client, u16 command) | ||
247 | { | ||
248 | int ret; | ||
249 | |||
250 | ret = __mt9t112_reg_write(client, 0x098E, command); | ||
251 | if (ret < 0) | ||
252 | return ret; | ||
253 | |||
254 | return __mt9t112_reg_read(client, 0x0990); | ||
255 | } | ||
256 | |||
257 | static int __mt9t112_mcu_write(const struct i2c_client *client, | ||
258 | u16 command, u16 data) | ||
259 | { | ||
260 | int ret; | ||
261 | |||
262 | ret = __mt9t112_reg_write(client, 0x098E, command); | ||
263 | if (ret < 0) | ||
264 | return ret; | ||
265 | |||
266 | return __mt9t112_reg_write(client, 0x0990, data); | ||
267 | } | ||
268 | |||
269 | static int __mt9t112_mcu_mask_set(const struct i2c_client *client, | ||
270 | u16 command, | ||
271 | u16 mask, | ||
272 | u16 set) | ||
273 | { | ||
274 | int val = __mt9t112_mcu_read(client, command); | ||
275 | if (val < 0) | ||
276 | return val; | ||
277 | |||
278 | val &= ~mask; | ||
279 | val |= set & mask; | ||
280 | |||
281 | return __mt9t112_mcu_write(client, command, val); | ||
282 | } | ||
283 | |||
284 | static int mt9t112_reset(const struct i2c_client *client) | ||
285 | { | ||
286 | int ret; | ||
287 | |||
288 | mt9t112_reg_mask_set(ret, client, 0x001a, 0x0001, 0x0001); | ||
289 | msleep(1); | ||
290 | mt9t112_reg_mask_set(ret, client, 0x001a, 0x0001, 0x0000); | ||
291 | |||
292 | return ret; | ||
293 | } | ||
294 | |||
295 | #ifndef EXT_CLOCK | ||
296 | #define CLOCK_INFO(a, b) | ||
297 | #else | ||
298 | #define CLOCK_INFO(a, b) mt9t112_clock_info(a, b) | ||
299 | static int mt9t112_clock_info(const struct i2c_client *client, u32 ext) | ||
300 | { | ||
301 | int m, n, p1, p2, p3, p4, p5, p6, p7; | ||
302 | u32 vco, clk; | ||
303 | char *enable; | ||
304 | |||
305 | ext /= 1000; /* kbyte order */ | ||
306 | |||
307 | mt9t112_reg_read(n, client, 0x0012); | ||
308 | p1 = n & 0x000f; | ||
309 | n = n >> 4; | ||
310 | p2 = n & 0x000f; | ||
311 | n = n >> 4; | ||
312 | p3 = n & 0x000f; | ||
313 | |||
314 | mt9t112_reg_read(n, client, 0x002a); | ||
315 | p4 = n & 0x000f; | ||
316 | n = n >> 4; | ||
317 | p5 = n & 0x000f; | ||
318 | n = n >> 4; | ||
319 | p6 = n & 0x000f; | ||
320 | |||
321 | mt9t112_reg_read(n, client, 0x002c); | ||
322 | p7 = n & 0x000f; | ||
323 | |||
324 | mt9t112_reg_read(n, client, 0x0010); | ||
325 | m = n & 0x00ff; | ||
326 | n = (n >> 8) & 0x003f; | ||
327 | |||
328 | enable = ((6000 > ext) || (54000 < ext)) ? "X" : ""; | ||
329 | dev_info(&client->dev, "EXTCLK : %10u K %s\n", ext, enable); | ||
330 | |||
331 | vco = 2 * m * ext / (n+1); | ||
332 | enable = ((384000 > vco) || (768000 < vco)) ? "X" : ""; | ||
333 | dev_info(&client->dev, "VCO : %10u K %s\n", vco, enable); | ||
334 | |||
335 | clk = vco / (p1+1) / (p2+1); | ||
336 | enable = (96000 < clk) ? "X" : ""; | ||
337 | dev_info(&client->dev, "PIXCLK : %10u K %s\n", clk, enable); | ||
338 | |||
339 | clk = vco / (p3+1); | ||
340 | enable = (768000 < clk) ? "X" : ""; | ||
341 | dev_info(&client->dev, "MIPICLK : %10u K %s\n", clk, enable); | ||
342 | |||
343 | clk = vco / (p6+1); | ||
344 | enable = (96000 < clk) ? "X" : ""; | ||
345 | dev_info(&client->dev, "MCU CLK : %10u K %s\n", clk, enable); | ||
346 | |||
347 | clk = vco / (p5+1); | ||
348 | enable = (54000 < clk) ? "X" : ""; | ||
349 | dev_info(&client->dev, "SOC CLK : %10u K %s\n", clk, enable); | ||
350 | |||
351 | clk = vco / (p4+1); | ||
352 | enable = (70000 < clk) ? "X" : ""; | ||
353 | dev_info(&client->dev, "Sensor CLK : %10u K %s\n", clk, enable); | ||
354 | |||
355 | clk = vco / (p7+1); | ||
356 | dev_info(&client->dev, "External sensor : %10u K\n", clk); | ||
357 | |||
358 | clk = ext / (n+1); | ||
359 | enable = ((2000 > clk) || (24000 < clk)) ? "X" : ""; | ||
360 | dev_info(&client->dev, "PFD : %10u K %s\n", clk, enable); | ||
361 | |||
362 | return 0; | ||
363 | } | ||
364 | #endif | ||
365 | |||
366 | static void mt9t112_frame_check(u32 *width, u32 *height) | ||
367 | { | ||
368 | if (*width > MAX_WIDTH) | ||
369 | *width = MAX_WIDTH; | ||
370 | |||
371 | if (*height > MAX_HEIGHT) | ||
372 | *height = MAX_HEIGHT; | ||
373 | } | ||
374 | |||
375 | static int mt9t112_set_a_frame_size(const struct i2c_client *client, | ||
376 | u16 width, | ||
377 | u16 height) | ||
378 | { | ||
379 | int ret; | ||
380 | u16 wstart = (MAX_WIDTH - width) / 2; | ||
381 | u16 hstart = (MAX_HEIGHT - height) / 2; | ||
382 | |||
383 | /* (Context A) Image Width/Height */ | ||
384 | mt9t112_mcu_write(ret, client, VAR(26, 0), width); | ||
385 | mt9t112_mcu_write(ret, client, VAR(26, 2), height); | ||
386 | |||
387 | /* (Context A) Output Width/Height */ | ||
388 | mt9t112_mcu_write(ret, client, VAR(18, 43), 8 + width); | ||
389 | mt9t112_mcu_write(ret, client, VAR(18, 45), 8 + height); | ||
390 | |||
391 | /* (Context A) Start Row/Column */ | ||
392 | mt9t112_mcu_write(ret, client, VAR(18, 2), 4 + hstart); | ||
393 | mt9t112_mcu_write(ret, client, VAR(18, 4), 4 + wstart); | ||
394 | |||
395 | /* (Context A) End Row/Column */ | ||
396 | mt9t112_mcu_write(ret, client, VAR(18, 6), 11 + height + hstart); | ||
397 | mt9t112_mcu_write(ret, client, VAR(18, 8), 11 + width + wstart); | ||
398 | |||
399 | mt9t112_mcu_write(ret, client, VAR8(1, 0), 0x06); | ||
400 | |||
401 | return ret; | ||
402 | } | ||
403 | |||
404 | static int mt9t112_set_pll_dividers(const struct i2c_client *client, | ||
405 | u8 m, u8 n, | ||
406 | u8 p1, u8 p2, u8 p3, | ||
407 | u8 p4, u8 p5, u8 p6, | ||
408 | u8 p7) | ||
409 | { | ||
410 | int ret; | ||
411 | u16 val; | ||
412 | |||
413 | /* N/M */ | ||
414 | val = (n << 8) | | ||
415 | (m << 0); | ||
416 | mt9t112_reg_mask_set(ret, client, 0x0010, 0x3fff, val); | ||
417 | |||
418 | /* P1/P2/P3 */ | ||
419 | val = ((p3 & 0x0F) << 8) | | ||
420 | ((p2 & 0x0F) << 4) | | ||
421 | ((p1 & 0x0F) << 0); | ||
422 | mt9t112_reg_mask_set(ret, client, 0x0012, 0x0fff, val); | ||
423 | |||
424 | /* P4/P5/P6 */ | ||
425 | val = (0x7 << 12) | | ||
426 | ((p6 & 0x0F) << 8) | | ||
427 | ((p5 & 0x0F) << 4) | | ||
428 | ((p4 & 0x0F) << 0); | ||
429 | mt9t112_reg_mask_set(ret, client, 0x002A, 0x7fff, val); | ||
430 | |||
431 | /* P7 */ | ||
432 | val = (0x1 << 12) | | ||
433 | ((p7 & 0x0F) << 0); | ||
434 | mt9t112_reg_mask_set(ret, client, 0x002C, 0x100f, val); | ||
435 | |||
436 | return ret; | ||
437 | } | ||
438 | |||
439 | static int mt9t112_init_pll(const struct i2c_client *client) | ||
440 | { | ||
441 | struct mt9t112_priv *priv = to_mt9t112(client); | ||
442 | int data, i, ret; | ||
443 | |||
444 | mt9t112_reg_mask_set(ret, client, 0x0014, 0x003, 0x0001); | ||
445 | |||
446 | /* PLL control: BYPASS PLL = 8517 */ | ||
447 | mt9t112_reg_write(ret, client, 0x0014, 0x2145); | ||
448 | |||
449 | /* Replace these registers when new timing parameters are generated */ | ||
450 | mt9t112_set_pll_dividers(client, | ||
451 | priv->info->divider.m, | ||
452 | priv->info->divider.n, | ||
453 | priv->info->divider.p1, | ||
454 | priv->info->divider.p2, | ||
455 | priv->info->divider.p3, | ||
456 | priv->info->divider.p4, | ||
457 | priv->info->divider.p5, | ||
458 | priv->info->divider.p6, | ||
459 | priv->info->divider.p7); | ||
460 | |||
461 | /* | ||
462 | * TEST_BYPASS on | ||
463 | * PLL_ENABLE on | ||
464 | * SEL_LOCK_DET on | ||
465 | * TEST_BYPASS off | ||
466 | */ | ||
467 | mt9t112_reg_write(ret, client, 0x0014, 0x2525); | ||
468 | mt9t112_reg_write(ret, client, 0x0014, 0x2527); | ||
469 | mt9t112_reg_write(ret, client, 0x0014, 0x3427); | ||
470 | mt9t112_reg_write(ret, client, 0x0014, 0x3027); | ||
471 | |||
472 | mdelay(10); | ||
473 | |||
474 | /* | ||
475 | * PLL_BYPASS off | ||
476 | * Reference clock count | ||
477 | * I2C Master Clock Divider | ||
478 | */ | ||
479 | mt9t112_reg_write(ret, client, 0x0014, 0x3046); | ||
480 | mt9t112_reg_write(ret, client, 0x0022, 0x0190); | ||
481 | mt9t112_reg_write(ret, client, 0x3B84, 0x0212); | ||
482 | |||
483 | /* External sensor clock is PLL bypass */ | ||
484 | mt9t112_reg_write(ret, client, 0x002E, 0x0500); | ||
485 | |||
486 | mt9t112_reg_mask_set(ret, client, 0x0018, 0x0002, 0x0002); | ||
487 | mt9t112_reg_mask_set(ret, client, 0x3B82, 0x0004, 0x0004); | ||
488 | |||
489 | /* MCU disabled */ | ||
490 | mt9t112_reg_mask_set(ret, client, 0x0018, 0x0004, 0x0004); | ||
491 | |||
492 | /* out of standby */ | ||
493 | mt9t112_reg_mask_set(ret, client, 0x0018, 0x0001, 0); | ||
494 | |||
495 | mdelay(50); | ||
496 | |||
497 | /* | ||
498 | * Standby Workaround | ||
499 | * Disable Secondary I2C Pads | ||
500 | */ | ||
501 | mt9t112_reg_write(ret, client, 0x0614, 0x0001); | ||
502 | mdelay(1); | ||
503 | mt9t112_reg_write(ret, client, 0x0614, 0x0001); | ||
504 | mdelay(1); | ||
505 | mt9t112_reg_write(ret, client, 0x0614, 0x0001); | ||
506 | mdelay(1); | ||
507 | mt9t112_reg_write(ret, client, 0x0614, 0x0001); | ||
508 | mdelay(1); | ||
509 | mt9t112_reg_write(ret, client, 0x0614, 0x0001); | ||
510 | mdelay(1); | ||
511 | mt9t112_reg_write(ret, client, 0x0614, 0x0001); | ||
512 | mdelay(1); | ||
513 | |||
514 | /* poll to verify out of standby. Must Poll this bit */ | ||
515 | for (i = 0; i < 100; i++) { | ||
516 | mt9t112_reg_read(data, client, 0x0018); | ||
517 | if (0x4000 & data) | ||
518 | break; | ||
519 | |||
520 | mdelay(10); | ||
521 | } | ||
522 | |||
523 | return ret; | ||
524 | } | ||
525 | |||
526 | static int mt9t112_init_setting(const struct i2c_client *client) | ||
527 | { | ||
528 | |||
529 | int ret; | ||
530 | |||
531 | /* Adaptive Output Clock (A) */ | ||
532 | mt9t112_mcu_mask_set(ret, client, VAR(26, 160), 0x0040, 0x0000); | ||
533 | |||
534 | /* Read Mode (A) */ | ||
535 | mt9t112_mcu_write(ret, client, VAR(18, 12), 0x0024); | ||
536 | |||
537 | /* Fine Correction (A) */ | ||
538 | mt9t112_mcu_write(ret, client, VAR(18, 15), 0x00CC); | ||
539 | |||
540 | /* Fine IT Min (A) */ | ||
541 | mt9t112_mcu_write(ret, client, VAR(18, 17), 0x01f1); | ||
542 | |||
543 | /* Fine IT Max Margin (A) */ | ||
544 | mt9t112_mcu_write(ret, client, VAR(18, 19), 0x00fF); | ||
545 | |||
546 | /* Base Frame Lines (A) */ | ||
547 | mt9t112_mcu_write(ret, client, VAR(18, 29), 0x032D); | ||
548 | |||
549 | /* Min Line Length (A) */ | ||
550 | mt9t112_mcu_write(ret, client, VAR(18, 31), 0x073a); | ||
551 | |||
552 | /* Line Length (A) */ | ||
553 | mt9t112_mcu_write(ret, client, VAR(18, 37), 0x07d0); | ||
554 | |||
555 | /* Adaptive Output Clock (B) */ | ||
556 | mt9t112_mcu_mask_set(ret, client, VAR(27, 160), 0x0040, 0x0000); | ||
557 | |||
558 | /* Row Start (B) */ | ||
559 | mt9t112_mcu_write(ret, client, VAR(18, 74), 0x004); | ||
560 | |||
561 | /* Column Start (B) */ | ||
562 | mt9t112_mcu_write(ret, client, VAR(18, 76), 0x004); | ||
563 | |||
564 | /* Row End (B) */ | ||
565 | mt9t112_mcu_write(ret, client, VAR(18, 78), 0x60B); | ||
566 | |||
567 | /* Column End (B) */ | ||
568 | mt9t112_mcu_write(ret, client, VAR(18, 80), 0x80B); | ||
569 | |||
570 | /* Fine Correction (B) */ | ||
571 | mt9t112_mcu_write(ret, client, VAR(18, 87), 0x008C); | ||
572 | |||
573 | /* Fine IT Min (B) */ | ||
574 | mt9t112_mcu_write(ret, client, VAR(18, 89), 0x01F1); | ||
575 | |||
576 | /* Fine IT Max Margin (B) */ | ||
577 | mt9t112_mcu_write(ret, client, VAR(18, 91), 0x00FF); | ||
578 | |||
579 | /* Base Frame Lines (B) */ | ||
580 | mt9t112_mcu_write(ret, client, VAR(18, 101), 0x0668); | ||
581 | |||
582 | /* Min Line Length (B) */ | ||
583 | mt9t112_mcu_write(ret, client, VAR(18, 103), 0x0AF0); | ||
584 | |||
585 | /* Line Length (B) */ | ||
586 | mt9t112_mcu_write(ret, client, VAR(18, 109), 0x0AF0); | ||
587 | |||
588 | /* | ||
589 | * Flicker Dectection registers | ||
590 | * This section should be replaced whenever new Timing file is generated | ||
591 | * All the following registers need to be replaced | ||
592 | * Following registers are generated from Register Wizard but user can | ||
593 | * modify them. For detail see auto flicker detection tuning | ||
594 | */ | ||
595 | |||
596 | /* FD_FDPERIOD_SELECT */ | ||
597 | mt9t112_mcu_write(ret, client, VAR8(8, 5), 0x01); | ||
598 | |||
599 | /* PRI_B_CONFIG_FD_ALGO_RUN */ | ||
600 | mt9t112_mcu_write(ret, client, VAR(27, 17), 0x0003); | ||
601 | |||
602 | /* PRI_A_CONFIG_FD_ALGO_RUN */ | ||
603 | mt9t112_mcu_write(ret, client, VAR(26, 17), 0x0003); | ||
604 | |||
605 | /* | ||
606 | * AFD range detection tuning registers | ||
607 | */ | ||
608 | |||
609 | /* search_f1_50 */ | ||
610 | mt9t112_mcu_write(ret, client, VAR8(18, 165), 0x25); | ||
611 | |||
612 | /* search_f2_50 */ | ||
613 | mt9t112_mcu_write(ret, client, VAR8(18, 166), 0x28); | ||
614 | |||
615 | /* search_f1_60 */ | ||
616 | mt9t112_mcu_write(ret, client, VAR8(18, 167), 0x2C); | ||
617 | |||
618 | /* search_f2_60 */ | ||
619 | mt9t112_mcu_write(ret, client, VAR8(18, 168), 0x2F); | ||
620 | |||
621 | /* period_50Hz (A) */ | ||
622 | mt9t112_mcu_write(ret, client, VAR8(18, 68), 0xBA); | ||
623 | |||
624 | /* secret register by aptina */ | ||
625 | /* period_50Hz (A MSB) */ | ||
626 | mt9t112_mcu_write(ret, client, VAR8(18, 303), 0x00); | ||
627 | |||
628 | /* period_60Hz (A) */ | ||
629 | mt9t112_mcu_write(ret, client, VAR8(18, 69), 0x9B); | ||
630 | |||
631 | /* secret register by aptina */ | ||
632 | /* period_60Hz (A MSB) */ | ||
633 | mt9t112_mcu_write(ret, client, VAR8(18, 301), 0x00); | ||
634 | |||
635 | /* period_50Hz (B) */ | ||
636 | mt9t112_mcu_write(ret, client, VAR8(18, 140), 0x82); | ||
637 | |||
638 | /* secret register by aptina */ | ||
639 | /* period_50Hz (B) MSB */ | ||
640 | mt9t112_mcu_write(ret, client, VAR8(18, 304), 0x00); | ||
641 | |||
642 | /* period_60Hz (B) */ | ||
643 | mt9t112_mcu_write(ret, client, VAR8(18, 141), 0x6D); | ||
644 | |||
645 | /* secret register by aptina */ | ||
646 | /* period_60Hz (B) MSB */ | ||
647 | mt9t112_mcu_write(ret, client, VAR8(18, 302), 0x00); | ||
648 | |||
649 | /* FD Mode */ | ||
650 | mt9t112_mcu_write(ret, client, VAR8(8, 2), 0x10); | ||
651 | |||
652 | /* Stat_min */ | ||
653 | mt9t112_mcu_write(ret, client, VAR8(8, 9), 0x02); | ||
654 | |||
655 | /* Stat_max */ | ||
656 | mt9t112_mcu_write(ret, client, VAR8(8, 10), 0x03); | ||
657 | |||
658 | /* Min_amplitude */ | ||
659 | mt9t112_mcu_write(ret, client, VAR8(8, 12), 0x0A); | ||
660 | |||
661 | /* RX FIFO Watermark (A) */ | ||
662 | mt9t112_mcu_write(ret, client, VAR(18, 70), 0x0014); | ||
663 | |||
664 | /* RX FIFO Watermark (B) */ | ||
665 | mt9t112_mcu_write(ret, client, VAR(18, 142), 0x0014); | ||
666 | |||
667 | /* MCLK: 16MHz | ||
668 | * PCLK: 73MHz | ||
669 | * CorePixCLK: 36.5 MHz | ||
670 | */ | ||
671 | mt9t112_mcu_write(ret, client, VAR8(18, 0x0044), 133); | ||
672 | mt9t112_mcu_write(ret, client, VAR8(18, 0x0045), 110); | ||
673 | mt9t112_mcu_write(ret, client, VAR8(18, 0x008c), 130); | ||
674 | mt9t112_mcu_write(ret, client, VAR8(18, 0x008d), 108); | ||
675 | |||
676 | mt9t112_mcu_write(ret, client, VAR8(18, 0x00A5), 27); | ||
677 | mt9t112_mcu_write(ret, client, VAR8(18, 0x00a6), 30); | ||
678 | mt9t112_mcu_write(ret, client, VAR8(18, 0x00a7), 32); | ||
679 | mt9t112_mcu_write(ret, client, VAR8(18, 0x00a8), 35); | ||
680 | |||
681 | return ret; | ||
682 | } | ||
683 | |||
684 | static int mt9t112_auto_focus_setting(const struct i2c_client *client) | ||
685 | { | ||
686 | int ret; | ||
687 | |||
688 | mt9t112_mcu_write(ret, client, VAR(12, 13), 0x000F); | ||
689 | mt9t112_mcu_write(ret, client, VAR(12, 23), 0x0F0F); | ||
690 | mt9t112_mcu_write(ret, client, VAR8(1, 0), 0x06); | ||
691 | |||
692 | mt9t112_reg_write(ret, client, 0x0614, 0x0000); | ||
693 | |||
694 | mt9t112_mcu_write(ret, client, VAR8(1, 0), 0x05); | ||
695 | mt9t112_mcu_write(ret, client, VAR8(12, 2), 0x02); | ||
696 | mt9t112_mcu_write(ret, client, VAR(12, 3), 0x0002); | ||
697 | mt9t112_mcu_write(ret, client, VAR(17, 3), 0x8001); | ||
698 | mt9t112_mcu_write(ret, client, VAR(17, 11), 0x0025); | ||
699 | mt9t112_mcu_write(ret, client, VAR(17, 13), 0x0193); | ||
700 | mt9t112_mcu_write(ret, client, VAR8(17, 33), 0x18); | ||
701 | mt9t112_mcu_write(ret, client, VAR8(1, 0), 0x05); | ||
702 | |||
703 | return ret; | ||
704 | } | ||
705 | |||
706 | static int mt9t112_auto_focus_trigger(const struct i2c_client *client) | ||
707 | { | ||
708 | int ret; | ||
709 | |||
710 | mt9t112_mcu_write(ret, client, VAR8(12, 25), 0x01); | ||
711 | |||
712 | return ret; | ||
713 | } | ||
714 | |||
715 | static int mt9t112_init_camera(const struct i2c_client *client) | ||
716 | { | ||
717 | int ret; | ||
718 | |||
719 | ECHECKER(ret, mt9t112_reset(client)); | ||
720 | |||
721 | ECHECKER(ret, mt9t112_init_pll(client)); | ||
722 | |||
723 | ECHECKER(ret, mt9t112_init_setting(client)); | ||
724 | |||
725 | ECHECKER(ret, mt9t112_auto_focus_setting(client)); | ||
726 | |||
727 | mt9t112_reg_mask_set(ret, client, 0x0018, 0x0004, 0); | ||
728 | |||
729 | /* Analog setting B */ | ||
730 | mt9t112_reg_write(ret, client, 0x3084, 0x2409); | ||
731 | mt9t112_reg_write(ret, client, 0x3092, 0x0A49); | ||
732 | mt9t112_reg_write(ret, client, 0x3094, 0x4949); | ||
733 | mt9t112_reg_write(ret, client, 0x3096, 0x4950); | ||
734 | |||
735 | /* | ||
736 | * Disable adaptive clock | ||
737 | * PRI_A_CONFIG_JPEG_OB_TX_CONTROL_VAR | ||
738 | * PRI_B_CONFIG_JPEG_OB_TX_CONTROL_VAR | ||
739 | */ | ||
740 | mt9t112_mcu_write(ret, client, VAR(26, 160), 0x0A2E); | ||
741 | mt9t112_mcu_write(ret, client, VAR(27, 160), 0x0A2E); | ||
742 | |||
743 | /* Configure STatus in Status_before_length Format and enable header */ | ||
744 | /* PRI_B_CONFIG_JPEG_OB_TX_CONTROL_VAR */ | ||
745 | mt9t112_mcu_write(ret, client, VAR(27, 144), 0x0CB4); | ||
746 | |||
747 | /* Enable JPEG in context B */ | ||
748 | /* PRI_B_CONFIG_JPEG_OB_TX_CONTROL_VAR */ | ||
749 | mt9t112_mcu_write(ret, client, VAR8(27, 142), 0x01); | ||
750 | |||
751 | /* Disable Dac_TXLO */ | ||
752 | mt9t112_reg_write(ret, client, 0x316C, 0x350F); | ||
753 | |||
754 | /* Set max slew rates */ | ||
755 | mt9t112_reg_write(ret, client, 0x1E, 0x777); | ||
756 | |||
757 | return ret; | ||
758 | } | ||
759 | |||
760 | /************************************************************************ | ||
761 | |||
762 | |||
763 | soc_camera_ops | ||
764 | |||
765 | |||
766 | ************************************************************************/ | ||
767 | static int mt9t112_set_bus_param(struct soc_camera_device *icd, | ||
768 | unsigned long flags) | ||
769 | { | ||
770 | return 0; | ||
771 | } | ||
772 | |||
773 | static unsigned long mt9t112_query_bus_param(struct soc_camera_device *icd) | ||
774 | { | ||
775 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | ||
776 | struct mt9t112_priv *priv = to_mt9t112(client); | ||
777 | struct soc_camera_link *icl = to_soc_camera_link(icd); | ||
778 | unsigned long flags = SOCAM_MASTER | SOCAM_VSYNC_ACTIVE_HIGH | | ||
779 | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_HIGH; | ||
780 | |||
781 | flags |= (priv->info->flags & MT9T112_FLAG_PCLK_RISING_EDGE) ? | ||
782 | SOCAM_PCLK_SAMPLE_RISING : SOCAM_PCLK_SAMPLE_FALLING; | ||
783 | |||
784 | if (priv->info->flags & MT9T112_FLAG_DATAWIDTH_8) | ||
785 | flags |= SOCAM_DATAWIDTH_8; | ||
786 | else | ||
787 | flags |= SOCAM_DATAWIDTH_10; | ||
788 | |||
789 | return soc_camera_apply_sensor_flags(icl, flags); | ||
790 | } | ||
791 | |||
792 | static struct soc_camera_ops mt9t112_ops = { | ||
793 | .set_bus_param = mt9t112_set_bus_param, | ||
794 | .query_bus_param = mt9t112_query_bus_param, | ||
795 | }; | ||
796 | |||
797 | /************************************************************************ | ||
798 | |||
799 | |||
800 | v4l2_subdev_core_ops | ||
801 | |||
802 | |||
803 | ************************************************************************/ | ||
804 | static int mt9t112_g_chip_ident(struct v4l2_subdev *sd, | ||
805 | struct v4l2_dbg_chip_ident *id) | ||
806 | { | ||
807 | struct i2c_client *client = sd->priv; | ||
808 | struct mt9t112_priv *priv = to_mt9t112(client); | ||
809 | |||
810 | id->ident = priv->model; | ||
811 | id->revision = 0; | ||
812 | |||
813 | return 0; | ||
814 | } | ||
815 | |||
816 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
817 | static int mt9t112_g_register(struct v4l2_subdev *sd, | ||
818 | struct v4l2_dbg_register *reg) | ||
819 | { | ||
820 | struct i2c_client *client = sd->priv; | ||
821 | int ret; | ||
822 | |||
823 | reg->size = 2; | ||
824 | mt9t112_reg_read(ret, client, reg->reg); | ||
825 | |||
826 | reg->val = (__u64)ret; | ||
827 | |||
828 | return 0; | ||
829 | } | ||
830 | |||
831 | static int mt9t112_s_register(struct v4l2_subdev *sd, | ||
832 | struct v4l2_dbg_register *reg) | ||
833 | { | ||
834 | struct i2c_client *client = sd->priv; | ||
835 | int ret; | ||
836 | |||
837 | mt9t112_reg_write(ret, client, reg->reg, reg->val); | ||
838 | |||
839 | return ret; | ||
840 | } | ||
841 | #endif | ||
842 | |||
843 | static struct v4l2_subdev_core_ops mt9t112_subdev_core_ops = { | ||
844 | .g_chip_ident = mt9t112_g_chip_ident, | ||
845 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
846 | .g_register = mt9t112_g_register, | ||
847 | .s_register = mt9t112_s_register, | ||
848 | #endif | ||
849 | }; | ||
850 | |||
851 | |||
852 | /************************************************************************ | ||
853 | |||
854 | |||
855 | v4l2_subdev_video_ops | ||
856 | |||
857 | |||
858 | ************************************************************************/ | ||
859 | static int mt9t112_s_stream(struct v4l2_subdev *sd, int enable) | ||
860 | { | ||
861 | struct i2c_client *client = sd->priv; | ||
862 | struct mt9t112_priv *priv = to_mt9t112(client); | ||
863 | int ret = 0; | ||
864 | |||
865 | if (!enable) { | ||
866 | /* FIXME | ||
867 | * | ||
868 | * If user selected large output size, | ||
869 | * and used it long time, | ||
870 | * mt9t112 camera will be very warm. | ||
871 | * | ||
872 | * But current driver can not stop mt9t112 camera. | ||
873 | * So, set small size here to solve this problem. | ||
874 | */ | ||
875 | mt9t112_set_a_frame_size(client, VGA_WIDTH, VGA_HEIGHT); | ||
876 | return ret; | ||
877 | } | ||
878 | |||
879 | if (!(priv->flags & INIT_DONE)) { | ||
880 | u16 param = (MT9T112_FLAG_PCLK_RISING_EDGE & | ||
881 | priv->info->flags) ? 0x0001 : 0x0000; | ||
882 | |||
883 | ECHECKER(ret, mt9t112_init_camera(client)); | ||
884 | |||
885 | /* Invert PCLK (Data sampled on falling edge of pixclk) */ | ||
886 | mt9t112_reg_write(ret, client, 0x3C20, param); | ||
887 | |||
888 | mdelay(5); | ||
889 | |||
890 | priv->flags |= INIT_DONE; | ||
891 | } | ||
892 | |||
893 | mt9t112_mcu_write(ret, client, VAR(26, 7), priv->format->fmt); | ||
894 | mt9t112_mcu_write(ret, client, VAR(26, 9), priv->format->order); | ||
895 | mt9t112_mcu_write(ret, client, VAR8(1, 0), 0x06); | ||
896 | |||
897 | mt9t112_set_a_frame_size(client, | ||
898 | priv->frame.width, | ||
899 | priv->frame.height); | ||
900 | |||
901 | ECHECKER(ret, mt9t112_auto_focus_trigger(client)); | ||
902 | |||
903 | dev_dbg(&client->dev, "format : %d\n", priv->format->code); | ||
904 | dev_dbg(&client->dev, "size : %d x %d\n", | ||
905 | priv->frame.width, | ||
906 | priv->frame.height); | ||
907 | |||
908 | CLOCK_INFO(client, EXT_CLOCK); | ||
909 | |||
910 | return ret; | ||
911 | } | ||
912 | |||
913 | static int mt9t112_set_params(struct i2c_client *client, u32 width, u32 height, | ||
914 | enum v4l2_mbus_pixelcode code) | ||
915 | { | ||
916 | struct mt9t112_priv *priv = to_mt9t112(client); | ||
917 | int i; | ||
918 | |||
919 | priv->format = NULL; | ||
920 | |||
921 | /* | ||
922 | * frame size check | ||
923 | */ | ||
924 | mt9t112_frame_check(&width, &height); | ||
925 | |||
926 | /* | ||
927 | * get color format | ||
928 | */ | ||
929 | for (i = 0; i < ARRAY_SIZE(mt9t112_cfmts); i++) | ||
930 | if (mt9t112_cfmts[i].code == code) | ||
931 | break; | ||
932 | |||
933 | if (i == ARRAY_SIZE(mt9t112_cfmts)) | ||
934 | return -EINVAL; | ||
935 | |||
936 | priv->frame.width = (u16)width; | ||
937 | priv->frame.height = (u16)height; | ||
938 | |||
939 | priv->format = mt9t112_cfmts + i; | ||
940 | |||
941 | return 0; | ||
942 | } | ||
943 | |||
944 | static int mt9t112_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) | ||
945 | { | ||
946 | a->bounds.left = 0; | ||
947 | a->bounds.top = 0; | ||
948 | a->bounds.width = VGA_WIDTH; | ||
949 | a->bounds.height = VGA_HEIGHT; | ||
950 | a->defrect = a->bounds; | ||
951 | a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
952 | a->pixelaspect.numerator = 1; | ||
953 | a->pixelaspect.denominator = 1; | ||
954 | |||
955 | return 0; | ||
956 | } | ||
957 | |||
958 | static int mt9t112_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) | ||
959 | { | ||
960 | a->c.left = 0; | ||
961 | a->c.top = 0; | ||
962 | a->c.width = VGA_WIDTH; | ||
963 | a->c.height = VGA_HEIGHT; | ||
964 | a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
965 | |||
966 | return 0; | ||
967 | } | ||
968 | |||
969 | static int mt9t112_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) | ||
970 | { | ||
971 | struct i2c_client *client = sd->priv; | ||
972 | struct v4l2_rect *rect = &a->c; | ||
973 | |||
974 | return mt9t112_set_params(client, rect->width, rect->height, | ||
975 | V4L2_MBUS_FMT_YUYV8_2X8_BE); | ||
976 | } | ||
977 | |||
978 | static int mt9t112_g_fmt(struct v4l2_subdev *sd, | ||
979 | struct v4l2_mbus_framefmt *mf) | ||
980 | { | ||
981 | struct i2c_client *client = sd->priv; | ||
982 | struct mt9t112_priv *priv = to_mt9t112(client); | ||
983 | |||
984 | if (!priv->format) { | ||
985 | int ret = mt9t112_set_params(client, VGA_WIDTH, VGA_HEIGHT, | ||
986 | V4L2_MBUS_FMT_YUYV8_2X8_BE); | ||
987 | if (ret < 0) | ||
988 | return ret; | ||
989 | } | ||
990 | |||
991 | mf->width = priv->frame.width; | ||
992 | mf->height = priv->frame.height; | ||
993 | /* TODO: set colorspace */ | ||
994 | mf->code = priv->format->code; | ||
995 | mf->field = V4L2_FIELD_NONE; | ||
996 | |||
997 | return 0; | ||
998 | } | ||
999 | |||
1000 | static int mt9t112_s_fmt(struct v4l2_subdev *sd, | ||
1001 | struct v4l2_mbus_framefmt *mf) | ||
1002 | { | ||
1003 | struct i2c_client *client = sd->priv; | ||
1004 | |||
1005 | /* TODO: set colorspace */ | ||
1006 | return mt9t112_set_params(client, mf->width, mf->height, mf->code); | ||
1007 | } | ||
1008 | |||
1009 | static int mt9t112_try_fmt(struct v4l2_subdev *sd, | ||
1010 | struct v4l2_mbus_framefmt *mf) | ||
1011 | { | ||
1012 | mt9t112_frame_check(&mf->width, &mf->height); | ||
1013 | |||
1014 | /* TODO: set colorspace */ | ||
1015 | mf->field = V4L2_FIELD_NONE; | ||
1016 | |||
1017 | return 0; | ||
1018 | } | ||
1019 | |||
1020 | static int mt9t112_enum_fmt(struct v4l2_subdev *sd, int index, | ||
1021 | enum v4l2_mbus_pixelcode *code) | ||
1022 | { | ||
1023 | if ((unsigned int)index >= ARRAY_SIZE(mt9t112_cfmts)) | ||
1024 | return -EINVAL; | ||
1025 | |||
1026 | *code = mt9t112_cfmts[index].code; | ||
1027 | return 0; | ||
1028 | } | ||
1029 | |||
1030 | static struct v4l2_subdev_video_ops mt9t112_subdev_video_ops = { | ||
1031 | .s_stream = mt9t112_s_stream, | ||
1032 | .g_mbus_fmt = mt9t112_g_fmt, | ||
1033 | .s_mbus_fmt = mt9t112_s_fmt, | ||
1034 | .try_mbus_fmt = mt9t112_try_fmt, | ||
1035 | .cropcap = mt9t112_cropcap, | ||
1036 | .g_crop = mt9t112_g_crop, | ||
1037 | .s_crop = mt9t112_s_crop, | ||
1038 | .enum_mbus_fmt = mt9t112_enum_fmt, | ||
1039 | }; | ||
1040 | |||
1041 | /************************************************************************ | ||
1042 | |||
1043 | |||
1044 | i2c driver | ||
1045 | |||
1046 | |||
1047 | ************************************************************************/ | ||
1048 | static struct v4l2_subdev_ops mt9t112_subdev_ops = { | ||
1049 | .core = &mt9t112_subdev_core_ops, | ||
1050 | .video = &mt9t112_subdev_video_ops, | ||
1051 | }; | ||
1052 | |||
1053 | static int mt9t112_camera_probe(struct soc_camera_device *icd, | ||
1054 | struct i2c_client *client) | ||
1055 | { | ||
1056 | struct mt9t112_priv *priv = to_mt9t112(client); | ||
1057 | const char *devname; | ||
1058 | int chipid; | ||
1059 | |||
1060 | /* | ||
1061 | * We must have a parent by now. And it cannot be a wrong one. | ||
1062 | * So this entire test is completely redundant. | ||
1063 | */ | ||
1064 | if (!icd->dev.parent || | ||
1065 | to_soc_camera_host(icd->dev.parent)->nr != icd->iface) | ||
1066 | return -ENODEV; | ||
1067 | |||
1068 | /* | ||
1069 | * check and show chip ID | ||
1070 | */ | ||
1071 | mt9t112_reg_read(chipid, client, 0x0000); | ||
1072 | |||
1073 | switch (chipid) { | ||
1074 | case 0x2680: | ||
1075 | devname = "mt9t111"; | ||
1076 | priv->model = V4L2_IDENT_MT9T111; | ||
1077 | break; | ||
1078 | case 0x2682: | ||
1079 | devname = "mt9t112"; | ||
1080 | priv->model = V4L2_IDENT_MT9T112; | ||
1081 | break; | ||
1082 | default: | ||
1083 | dev_err(&client->dev, "Product ID error %04x\n", chipid); | ||
1084 | return -ENODEV; | ||
1085 | } | ||
1086 | |||
1087 | dev_info(&client->dev, "%s chip ID %04x\n", devname, chipid); | ||
1088 | |||
1089 | return 0; | ||
1090 | } | ||
1091 | |||
1092 | static int mt9t112_probe(struct i2c_client *client, | ||
1093 | const struct i2c_device_id *did) | ||
1094 | { | ||
1095 | struct mt9t112_priv *priv; | ||
1096 | struct soc_camera_device *icd = client->dev.platform_data; | ||
1097 | struct soc_camera_link *icl; | ||
1098 | int ret; | ||
1099 | |||
1100 | if (!icd) { | ||
1101 | dev_err(&client->dev, "mt9t112: missing soc-camera data!\n"); | ||
1102 | return -EINVAL; | ||
1103 | } | ||
1104 | |||
1105 | icl = to_soc_camera_link(icd); | ||
1106 | if (!icl || !icl->priv) | ||
1107 | return -EINVAL; | ||
1108 | |||
1109 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
1110 | if (!priv) | ||
1111 | return -ENOMEM; | ||
1112 | |||
1113 | priv->info = icl->priv; | ||
1114 | |||
1115 | v4l2_i2c_subdev_init(&priv->subdev, client, &mt9t112_subdev_ops); | ||
1116 | |||
1117 | icd->ops = &mt9t112_ops; | ||
1118 | |||
1119 | ret = mt9t112_camera_probe(icd, client); | ||
1120 | if (ret) { | ||
1121 | icd->ops = NULL; | ||
1122 | i2c_set_clientdata(client, NULL); | ||
1123 | kfree(priv); | ||
1124 | } | ||
1125 | |||
1126 | return ret; | ||
1127 | } | ||
1128 | |||
1129 | static int mt9t112_remove(struct i2c_client *client) | ||
1130 | { | ||
1131 | struct mt9t112_priv *priv = to_mt9t112(client); | ||
1132 | struct soc_camera_device *icd = client->dev.platform_data; | ||
1133 | |||
1134 | icd->ops = NULL; | ||
1135 | i2c_set_clientdata(client, NULL); | ||
1136 | kfree(priv); | ||
1137 | return 0; | ||
1138 | } | ||
1139 | |||
1140 | static const struct i2c_device_id mt9t112_id[] = { | ||
1141 | { "mt9t112", 0 }, | ||
1142 | { } | ||
1143 | }; | ||
1144 | MODULE_DEVICE_TABLE(i2c, mt9t112_id); | ||
1145 | |||
1146 | static struct i2c_driver mt9t112_i2c_driver = { | ||
1147 | .driver = { | ||
1148 | .name = "mt9t112", | ||
1149 | }, | ||
1150 | .probe = mt9t112_probe, | ||
1151 | .remove = mt9t112_remove, | ||
1152 | .id_table = mt9t112_id, | ||
1153 | }; | ||
1154 | |||
1155 | /************************************************************************ | ||
1156 | |||
1157 | |||
1158 | module function | ||
1159 | |||
1160 | |||
1161 | ************************************************************************/ | ||
1162 | static int __init mt9t112_module_init(void) | ||
1163 | { | ||
1164 | return i2c_add_driver(&mt9t112_i2c_driver); | ||
1165 | } | ||
1166 | |||
1167 | static void __exit mt9t112_module_exit(void) | ||
1168 | { | ||
1169 | i2c_del_driver(&mt9t112_i2c_driver); | ||
1170 | } | ||
1171 | |||
1172 | module_init(mt9t112_module_init); | ||
1173 | module_exit(mt9t112_module_exit); | ||
1174 | |||
1175 | MODULE_DESCRIPTION("SoC Camera driver for mt9t112"); | ||
1176 | MODULE_AUTHOR("Kuninori Morimoto"); | ||
1177 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c index 995607f9d3ba..91df7ec91fb6 100644 --- a/drivers/media/video/mt9v022.c +++ b/drivers/media/video/mt9v022.c | |||
@@ -18,9 +18,11 @@ | |||
18 | #include <media/v4l2-chip-ident.h> | 18 | #include <media/v4l2-chip-ident.h> |
19 | #include <media/soc_camera.h> | 19 | #include <media/soc_camera.h> |
20 | 20 | ||
21 | /* mt9v022 i2c address 0x48, 0x4c, 0x58, 0x5c | 21 | /* |
22 | * mt9v022 i2c address 0x48, 0x4c, 0x58, 0x5c | ||
22 | * The platform has to define ctruct i2c_board_info objects and link to them | 23 | * The platform has to define ctruct i2c_board_info objects and link to them |
23 | * from struct soc_camera_link */ | 24 | * from struct soc_camera_link |
25 | */ | ||
24 | 26 | ||
25 | static char *sensor_type; | 27 | static char *sensor_type; |
26 | module_param(sensor_type, charp, S_IRUGO); | 28 | module_param(sensor_type, charp, S_IRUGO); |
@@ -62,41 +64,49 @@ MODULE_PARM_DESC(sensor_type, "Sensor type: \"colour\" or \"monochrome\""); | |||
62 | #define MT9V022_COLUMN_SKIP 1 | 64 | #define MT9V022_COLUMN_SKIP 1 |
63 | #define MT9V022_ROW_SKIP 4 | 65 | #define MT9V022_ROW_SKIP 4 |
64 | 66 | ||
65 | static const struct soc_camera_data_format mt9v022_colour_formats[] = { | 67 | /* MT9V022 has only one fixed colorspace per pixelcode */ |
66 | /* Order important: first natively supported, | 68 | struct mt9v022_datafmt { |
67 | * second supported with a GPIO extender */ | 69 | enum v4l2_mbus_pixelcode code; |
68 | { | 70 | enum v4l2_colorspace colorspace; |
69 | .name = "Bayer (sRGB) 10 bit", | 71 | }; |
70 | .depth = 10, | 72 | |
71 | .fourcc = V4L2_PIX_FMT_SBGGR16, | 73 | /* Find a data format by a pixel code in an array */ |
72 | .colorspace = V4L2_COLORSPACE_SRGB, | 74 | static const struct mt9v022_datafmt *mt9v022_find_datafmt( |
73 | }, { | 75 | enum v4l2_mbus_pixelcode code, const struct mt9v022_datafmt *fmt, |
74 | .name = "Bayer (sRGB) 8 bit", | 76 | int n) |
75 | .depth = 8, | 77 | { |
76 | .fourcc = V4L2_PIX_FMT_SBGGR8, | 78 | int i; |
77 | .colorspace = V4L2_COLORSPACE_SRGB, | 79 | for (i = 0; i < n; i++) |
78 | } | 80 | if (fmt[i].code == code) |
81 | return fmt + i; | ||
82 | |||
83 | return NULL; | ||
84 | } | ||
85 | |||
86 | static const struct mt9v022_datafmt mt9v022_colour_fmts[] = { | ||
87 | /* | ||
88 | * Order important: first natively supported, | ||
89 | * second supported with a GPIO extender | ||
90 | */ | ||
91 | {V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_COLORSPACE_SRGB}, | ||
92 | {V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB}, | ||
79 | }; | 93 | }; |
80 | 94 | ||
81 | static const struct soc_camera_data_format mt9v022_monochrome_formats[] = { | 95 | static const struct mt9v022_datafmt mt9v022_monochrome_fmts[] = { |
82 | /* Order important - see above */ | 96 | /* Order important - see above */ |
83 | { | 97 | {V4L2_MBUS_FMT_Y10_1X10, V4L2_COLORSPACE_JPEG}, |
84 | .name = "Monochrome 10 bit", | 98 | {V4L2_MBUS_FMT_GREY8_1X8, V4L2_COLORSPACE_JPEG}, |
85 | .depth = 10, | ||
86 | .fourcc = V4L2_PIX_FMT_Y16, | ||
87 | }, { | ||
88 | .name = "Monochrome 8 bit", | ||
89 | .depth = 8, | ||
90 | .fourcc = V4L2_PIX_FMT_GREY, | ||
91 | }, | ||
92 | }; | 99 | }; |
93 | 100 | ||
94 | struct mt9v022 { | 101 | struct mt9v022 { |
95 | struct v4l2_subdev subdev; | 102 | struct v4l2_subdev subdev; |
96 | struct v4l2_rect rect; /* Sensor window */ | 103 | struct v4l2_rect rect; /* Sensor window */ |
97 | __u32 fourcc; | 104 | const struct mt9v022_datafmt *fmt; |
105 | const struct mt9v022_datafmt *fmts; | ||
106 | int num_fmts; | ||
98 | int model; /* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */ | 107 | int model; /* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */ |
99 | u16 chip_control; | 108 | u16 chip_control; |
109 | unsigned short y_skip_top; /* Lines to skip at the top */ | ||
100 | }; | 110 | }; |
101 | 111 | ||
102 | static struct mt9v022 *to_mt9v022(const struct i2c_client *client) | 112 | static struct mt9v022 *to_mt9v022(const struct i2c_client *client) |
@@ -143,9 +153,11 @@ static int mt9v022_init(struct i2c_client *client) | |||
143 | struct mt9v022 *mt9v022 = to_mt9v022(client); | 153 | struct mt9v022 *mt9v022 = to_mt9v022(client); |
144 | int ret; | 154 | int ret; |
145 | 155 | ||
146 | /* Almost the default mode: master, parallel, simultaneous, and an | 156 | /* |
157 | * Almost the default mode: master, parallel, simultaneous, and an | ||
147 | * undocumented bit 0x200, which is present in table 7, but not in 8, | 158 | * undocumented bit 0x200, which is present in table 7, but not in 8, |
148 | * plus snapshot mode to disable scan for now */ | 159 | * plus snapshot mode to disable scan for now |
160 | */ | ||
149 | mt9v022->chip_control |= 0x10; | 161 | mt9v022->chip_control |= 0x10; |
150 | ret = reg_write(client, MT9V022_CHIP_CONTROL, mt9v022->chip_control); | 162 | ret = reg_write(client, MT9V022_CHIP_CONTROL, mt9v022->chip_control); |
151 | if (!ret) | 163 | if (!ret) |
@@ -265,12 +277,10 @@ static int mt9v022_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) | |||
265 | struct i2c_client *client = sd->priv; | 277 | struct i2c_client *client = sd->priv; |
266 | struct mt9v022 *mt9v022 = to_mt9v022(client); | 278 | struct mt9v022 *mt9v022 = to_mt9v022(client); |
267 | struct v4l2_rect rect = a->c; | 279 | struct v4l2_rect rect = a->c; |
268 | struct soc_camera_device *icd = client->dev.platform_data; | ||
269 | int ret; | 280 | int ret; |
270 | 281 | ||
271 | /* Bayer format - even size lengths */ | 282 | /* Bayer format - even size lengths */ |
272 | if (mt9v022->fourcc == V4L2_PIX_FMT_SBGGR8 || | 283 | if (mt9v022->fmts == mt9v022_colour_fmts) { |
273 | mt9v022->fourcc == V4L2_PIX_FMT_SBGGR16) { | ||
274 | rect.width = ALIGN(rect.width, 2); | 284 | rect.width = ALIGN(rect.width, 2); |
275 | rect.height = ALIGN(rect.height, 2); | 285 | rect.height = ALIGN(rect.height, 2); |
276 | /* Let the user play with the starting pixel */ | 286 | /* Let the user play with the starting pixel */ |
@@ -287,10 +297,10 @@ static int mt9v022_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) | |||
287 | if (ret >= 0) { | 297 | if (ret >= 0) { |
288 | if (ret & 1) /* Autoexposure */ | 298 | if (ret & 1) /* Autoexposure */ |
289 | ret = reg_write(client, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, | 299 | ret = reg_write(client, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, |
290 | rect.height + icd->y_skip_top + 43); | 300 | rect.height + mt9v022->y_skip_top + 43); |
291 | else | 301 | else |
292 | ret = reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH, | 302 | ret = reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH, |
293 | rect.height + icd->y_skip_top + 43); | 303 | rect.height + mt9v022->y_skip_top + 43); |
294 | } | 304 | } |
295 | /* Setup frame format: defaults apart from width and height */ | 305 | /* Setup frame format: defaults apart from width and height */ |
296 | if (!ret) | 306 | if (!ret) |
@@ -298,8 +308,10 @@ static int mt9v022_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) | |||
298 | if (!ret) | 308 | if (!ret) |
299 | ret = reg_write(client, MT9V022_ROW_START, rect.top); | 309 | ret = reg_write(client, MT9V022_ROW_START, rect.top); |
300 | if (!ret) | 310 | if (!ret) |
301 | /* Default 94, Phytec driver says: | 311 | /* |
302 | * "width + horizontal blank >= 660" */ | 312 | * Default 94, Phytec driver says: |
313 | * "width + horizontal blank >= 660" | ||
314 | */ | ||
303 | ret = reg_write(client, MT9V022_HORIZONTAL_BLANKING, | 315 | ret = reg_write(client, MT9V022_HORIZONTAL_BLANKING, |
304 | rect.width > 660 - 43 ? 43 : | 316 | rect.width > 660 - 43 ? 43 : |
305 | 660 - rect.width); | 317 | 660 - rect.width); |
@@ -309,7 +321,7 @@ static int mt9v022_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) | |||
309 | ret = reg_write(client, MT9V022_WINDOW_WIDTH, rect.width); | 321 | ret = reg_write(client, MT9V022_WINDOW_WIDTH, rect.width); |
310 | if (!ret) | 322 | if (!ret) |
311 | ret = reg_write(client, MT9V022_WINDOW_HEIGHT, | 323 | ret = reg_write(client, MT9V022_WINDOW_HEIGHT, |
312 | rect.height + icd->y_skip_top); | 324 | rect.height + mt9v022->y_skip_top); |
313 | 325 | ||
314 | if (ret < 0) | 326 | if (ret < 0) |
315 | return ret; | 327 | return ret; |
@@ -346,46 +358,48 @@ static int mt9v022_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) | |||
346 | return 0; | 358 | return 0; |
347 | } | 359 | } |
348 | 360 | ||
349 | static int mt9v022_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | 361 | static int mt9v022_g_fmt(struct v4l2_subdev *sd, |
362 | struct v4l2_mbus_framefmt *mf) | ||
350 | { | 363 | { |
351 | struct i2c_client *client = sd->priv; | 364 | struct i2c_client *client = sd->priv; |
352 | struct mt9v022 *mt9v022 = to_mt9v022(client); | 365 | struct mt9v022 *mt9v022 = to_mt9v022(client); |
353 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
354 | 366 | ||
355 | pix->width = mt9v022->rect.width; | 367 | mf->width = mt9v022->rect.width; |
356 | pix->height = mt9v022->rect.height; | 368 | mf->height = mt9v022->rect.height; |
357 | pix->pixelformat = mt9v022->fourcc; | 369 | mf->code = mt9v022->fmt->code; |
358 | pix->field = V4L2_FIELD_NONE; | 370 | mf->colorspace = mt9v022->fmt->colorspace; |
359 | pix->colorspace = V4L2_COLORSPACE_SRGB; | 371 | mf->field = V4L2_FIELD_NONE; |
360 | 372 | ||
361 | return 0; | 373 | return 0; |
362 | } | 374 | } |
363 | 375 | ||
364 | static int mt9v022_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | 376 | static int mt9v022_s_fmt(struct v4l2_subdev *sd, |
377 | struct v4l2_mbus_framefmt *mf) | ||
365 | { | 378 | { |
366 | struct i2c_client *client = sd->priv; | 379 | struct i2c_client *client = sd->priv; |
367 | struct mt9v022 *mt9v022 = to_mt9v022(client); | 380 | struct mt9v022 *mt9v022 = to_mt9v022(client); |
368 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
369 | struct v4l2_crop a = { | 381 | struct v4l2_crop a = { |
370 | .c = { | 382 | .c = { |
371 | .left = mt9v022->rect.left, | 383 | .left = mt9v022->rect.left, |
372 | .top = mt9v022->rect.top, | 384 | .top = mt9v022->rect.top, |
373 | .width = pix->width, | 385 | .width = mf->width, |
374 | .height = pix->height, | 386 | .height = mf->height, |
375 | }, | 387 | }, |
376 | }; | 388 | }; |
377 | int ret; | 389 | int ret; |
378 | 390 | ||
379 | /* The caller provides a supported format, as verified per call to | 391 | /* |
380 | * icd->try_fmt(), datawidth is from our supported format list */ | 392 | * The caller provides a supported format, as verified per call to |
381 | switch (pix->pixelformat) { | 393 | * icd->try_fmt(), datawidth is from our supported format list |
382 | case V4L2_PIX_FMT_GREY: | 394 | */ |
383 | case V4L2_PIX_FMT_Y16: | 395 | switch (mf->code) { |
396 | case V4L2_MBUS_FMT_GREY8_1X8: | ||
397 | case V4L2_MBUS_FMT_Y10_1X10: | ||
384 | if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATM) | 398 | if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATM) |
385 | return -EINVAL; | 399 | return -EINVAL; |
386 | break; | 400 | break; |
387 | case V4L2_PIX_FMT_SBGGR8: | 401 | case V4L2_MBUS_FMT_SBGGR8_1X8: |
388 | case V4L2_PIX_FMT_SBGGR16: | 402 | case V4L2_MBUS_FMT_SBGGR10_1X10: |
389 | if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATC) | 403 | if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATC) |
390 | return -EINVAL; | 404 | return -EINVAL; |
391 | break; | 405 | break; |
@@ -399,26 +413,38 @@ static int mt9v022_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | |||
399 | /* No support for scaling on this camera, just crop. */ | 413 | /* No support for scaling on this camera, just crop. */ |
400 | ret = mt9v022_s_crop(sd, &a); | 414 | ret = mt9v022_s_crop(sd, &a); |
401 | if (!ret) { | 415 | if (!ret) { |
402 | pix->width = mt9v022->rect.width; | 416 | mf->width = mt9v022->rect.width; |
403 | pix->height = mt9v022->rect.height; | 417 | mf->height = mt9v022->rect.height; |
404 | mt9v022->fourcc = pix->pixelformat; | 418 | mt9v022->fmt = mt9v022_find_datafmt(mf->code, |
419 | mt9v022->fmts, mt9v022->num_fmts); | ||
420 | mf->colorspace = mt9v022->fmt->colorspace; | ||
405 | } | 421 | } |
406 | 422 | ||
407 | return ret; | 423 | return ret; |
408 | } | 424 | } |
409 | 425 | ||
410 | static int mt9v022_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | 426 | static int mt9v022_try_fmt(struct v4l2_subdev *sd, |
427 | struct v4l2_mbus_framefmt *mf) | ||
411 | { | 428 | { |
412 | struct i2c_client *client = sd->priv; | 429 | struct i2c_client *client = sd->priv; |
413 | struct soc_camera_device *icd = client->dev.platform_data; | 430 | struct mt9v022 *mt9v022 = to_mt9v022(client); |
414 | struct v4l2_pix_format *pix = &f->fmt.pix; | 431 | const struct mt9v022_datafmt *fmt; |
415 | int align = pix->pixelformat == V4L2_PIX_FMT_SBGGR8 || | 432 | int align = mf->code == V4L2_MBUS_FMT_SBGGR8_1X8 || |
416 | pix->pixelformat == V4L2_PIX_FMT_SBGGR16; | 433 | mf->code == V4L2_MBUS_FMT_SBGGR10_1X10; |
417 | 434 | ||
418 | v4l_bound_align_image(&pix->width, MT9V022_MIN_WIDTH, | 435 | v4l_bound_align_image(&mf->width, MT9V022_MIN_WIDTH, |
419 | MT9V022_MAX_WIDTH, align, | 436 | MT9V022_MAX_WIDTH, align, |
420 | &pix->height, MT9V022_MIN_HEIGHT + icd->y_skip_top, | 437 | &mf->height, MT9V022_MIN_HEIGHT + mt9v022->y_skip_top, |
421 | MT9V022_MAX_HEIGHT + icd->y_skip_top, align, 0); | 438 | MT9V022_MAX_HEIGHT + mt9v022->y_skip_top, align, 0); |
439 | |||
440 | fmt = mt9v022_find_datafmt(mf->code, mt9v022->fmts, | ||
441 | mt9v022->num_fmts); | ||
442 | if (!fmt) { | ||
443 | fmt = mt9v022->fmt; | ||
444 | mf->code = fmt->code; | ||
445 | } | ||
446 | |||
447 | mf->colorspace = fmt->colorspace; | ||
422 | 448 | ||
423 | return 0; | 449 | return 0; |
424 | } | 450 | } |
@@ -635,8 +661,10 @@ static int mt9v022_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | |||
635 | 48 + range / 2) / range + 16; | 661 | 48 + range / 2) / range + 16; |
636 | if (gain >= 32) | 662 | if (gain >= 32) |
637 | gain &= ~1; | 663 | gain &= ~1; |
638 | /* The user wants to set gain manually, hope, she | 664 | /* |
639 | * knows, what she's doing... Switch AGC off. */ | 665 | * The user wants to set gain manually, hope, she |
666 | * knows, what she's doing... Switch AGC off. | ||
667 | */ | ||
640 | 668 | ||
641 | if (reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x2) < 0) | 669 | if (reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x2) < 0) |
642 | return -EIO; | 670 | return -EIO; |
@@ -655,8 +683,10 @@ static int mt9v022_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | |||
655 | unsigned long range = qctrl->maximum - qctrl->minimum; | 683 | unsigned long range = qctrl->maximum - qctrl->minimum; |
656 | unsigned long shutter = ((ctrl->value - qctrl->minimum) * | 684 | unsigned long shutter = ((ctrl->value - qctrl->minimum) * |
657 | 479 + range / 2) / range + 1; | 685 | 479 + range / 2) / range + 1; |
658 | /* The user wants to set shutter width manually, hope, | 686 | /* |
659 | * she knows, what she's doing... Switch AEC off. */ | 687 | * The user wants to set shutter width manually, hope, |
688 | * she knows, what she's doing... Switch AEC off. | ||
689 | */ | ||
660 | 690 | ||
661 | if (reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x1) < 0) | 691 | if (reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x1) < 0) |
662 | return -EIO; | 692 | return -EIO; |
@@ -689,8 +719,10 @@ static int mt9v022_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | |||
689 | return 0; | 719 | return 0; |
690 | } | 720 | } |
691 | 721 | ||
692 | /* Interface active, can use i2c. If it fails, it can indeed mean, that | 722 | /* |
693 | * this wasn't our capture interface, so, we wait for the right one */ | 723 | * Interface active, can use i2c. If it fails, it can indeed mean, that |
724 | * this wasn't our capture interface, so, we wait for the right one | ||
725 | */ | ||
694 | static int mt9v022_video_probe(struct soc_camera_device *icd, | 726 | static int mt9v022_video_probe(struct soc_camera_device *icd, |
695 | struct i2c_client *client) | 727 | struct i2c_client *client) |
696 | { | 728 | { |
@@ -733,17 +765,17 @@ static int mt9v022_video_probe(struct soc_camera_device *icd, | |||
733 | !strcmp("color", sensor_type))) { | 765 | !strcmp("color", sensor_type))) { |
734 | ret = reg_write(client, MT9V022_PIXEL_OPERATION_MODE, 4 | 0x11); | 766 | ret = reg_write(client, MT9V022_PIXEL_OPERATION_MODE, 4 | 0x11); |
735 | mt9v022->model = V4L2_IDENT_MT9V022IX7ATC; | 767 | mt9v022->model = V4L2_IDENT_MT9V022IX7ATC; |
736 | icd->formats = mt9v022_colour_formats; | 768 | mt9v022->fmts = mt9v022_colour_fmts; |
737 | } else { | 769 | } else { |
738 | ret = reg_write(client, MT9V022_PIXEL_OPERATION_MODE, 0x11); | 770 | ret = reg_write(client, MT9V022_PIXEL_OPERATION_MODE, 0x11); |
739 | mt9v022->model = V4L2_IDENT_MT9V022IX7ATM; | 771 | mt9v022->model = V4L2_IDENT_MT9V022IX7ATM; |
740 | icd->formats = mt9v022_monochrome_formats; | 772 | mt9v022->fmts = mt9v022_monochrome_fmts; |
741 | } | 773 | } |
742 | 774 | ||
743 | if (ret < 0) | 775 | if (ret < 0) |
744 | goto ei2c; | 776 | goto ei2c; |
745 | 777 | ||
746 | icd->num_formats = 0; | 778 | mt9v022->num_fmts = 0; |
747 | 779 | ||
748 | /* | 780 | /* |
749 | * This is a 10bit sensor, so by default we only allow 10bit. | 781 | * This is a 10bit sensor, so by default we only allow 10bit. |
@@ -756,14 +788,14 @@ static int mt9v022_video_probe(struct soc_camera_device *icd, | |||
756 | flags = SOCAM_DATAWIDTH_10; | 788 | flags = SOCAM_DATAWIDTH_10; |
757 | 789 | ||
758 | if (flags & SOCAM_DATAWIDTH_10) | 790 | if (flags & SOCAM_DATAWIDTH_10) |
759 | icd->num_formats++; | 791 | mt9v022->num_fmts++; |
760 | else | 792 | else |
761 | icd->formats++; | 793 | mt9v022->fmts++; |
762 | 794 | ||
763 | if (flags & SOCAM_DATAWIDTH_8) | 795 | if (flags & SOCAM_DATAWIDTH_8) |
764 | icd->num_formats++; | 796 | mt9v022->num_fmts++; |
765 | 797 | ||
766 | mt9v022->fourcc = icd->formats->fourcc; | 798 | mt9v022->fmt = &mt9v022->fmts[0]; |
767 | 799 | ||
768 | dev_info(&client->dev, "Detected a MT9V022 chip ID %x, %s sensor\n", | 800 | dev_info(&client->dev, "Detected a MT9V022 chip ID %x, %s sensor\n", |
769 | data, mt9v022->model == V4L2_IDENT_MT9V022IX7ATM ? | 801 | data, mt9v022->model == V4L2_IDENT_MT9V022IX7ATM ? |
@@ -787,6 +819,16 @@ static void mt9v022_video_remove(struct soc_camera_device *icd) | |||
787 | icl->free_bus(icl); | 819 | icl->free_bus(icl); |
788 | } | 820 | } |
789 | 821 | ||
822 | static int mt9v022_g_skip_top_lines(struct v4l2_subdev *sd, u32 *lines) | ||
823 | { | ||
824 | struct i2c_client *client = sd->priv; | ||
825 | struct mt9v022 *mt9v022 = to_mt9v022(client); | ||
826 | |||
827 | *lines = mt9v022->y_skip_top; | ||
828 | |||
829 | return 0; | ||
830 | } | ||
831 | |||
790 | static struct v4l2_subdev_core_ops mt9v022_subdev_core_ops = { | 832 | static struct v4l2_subdev_core_ops mt9v022_subdev_core_ops = { |
791 | .g_ctrl = mt9v022_g_ctrl, | 833 | .g_ctrl = mt9v022_g_ctrl, |
792 | .s_ctrl = mt9v022_s_ctrl, | 834 | .s_ctrl = mt9v022_s_ctrl, |
@@ -797,19 +839,38 @@ static struct v4l2_subdev_core_ops mt9v022_subdev_core_ops = { | |||
797 | #endif | 839 | #endif |
798 | }; | 840 | }; |
799 | 841 | ||
842 | static int mt9v022_enum_fmt(struct v4l2_subdev *sd, int index, | ||
843 | enum v4l2_mbus_pixelcode *code) | ||
844 | { | ||
845 | struct i2c_client *client = sd->priv; | ||
846 | struct mt9v022 *mt9v022 = to_mt9v022(client); | ||
847 | |||
848 | if ((unsigned int)index >= mt9v022->num_fmts) | ||
849 | return -EINVAL; | ||
850 | |||
851 | *code = mt9v022->fmts[index].code; | ||
852 | return 0; | ||
853 | } | ||
854 | |||
800 | static struct v4l2_subdev_video_ops mt9v022_subdev_video_ops = { | 855 | static struct v4l2_subdev_video_ops mt9v022_subdev_video_ops = { |
801 | .s_stream = mt9v022_s_stream, | 856 | .s_stream = mt9v022_s_stream, |
802 | .s_fmt = mt9v022_s_fmt, | 857 | .s_mbus_fmt = mt9v022_s_fmt, |
803 | .g_fmt = mt9v022_g_fmt, | 858 | .g_mbus_fmt = mt9v022_g_fmt, |
804 | .try_fmt = mt9v022_try_fmt, | 859 | .try_mbus_fmt = mt9v022_try_fmt, |
805 | .s_crop = mt9v022_s_crop, | 860 | .s_crop = mt9v022_s_crop, |
806 | .g_crop = mt9v022_g_crop, | 861 | .g_crop = mt9v022_g_crop, |
807 | .cropcap = mt9v022_cropcap, | 862 | .cropcap = mt9v022_cropcap, |
863 | .enum_mbus_fmt = mt9v022_enum_fmt, | ||
864 | }; | ||
865 | |||
866 | static struct v4l2_subdev_sensor_ops mt9v022_subdev_sensor_ops = { | ||
867 | .g_skip_top_lines = mt9v022_g_skip_top_lines, | ||
808 | }; | 868 | }; |
809 | 869 | ||
810 | static struct v4l2_subdev_ops mt9v022_subdev_ops = { | 870 | static struct v4l2_subdev_ops mt9v022_subdev_ops = { |
811 | .core = &mt9v022_subdev_core_ops, | 871 | .core = &mt9v022_subdev_core_ops, |
812 | .video = &mt9v022_subdev_video_ops, | 872 | .video = &mt9v022_subdev_video_ops, |
873 | .sensor = &mt9v022_subdev_sensor_ops, | ||
813 | }; | 874 | }; |
814 | 875 | ||
815 | static int mt9v022_probe(struct i2c_client *client, | 876 | static int mt9v022_probe(struct i2c_client *client, |
@@ -851,8 +912,7 @@ static int mt9v022_probe(struct i2c_client *client, | |||
851 | * MT9V022 _really_ corrupts the first read out line. | 912 | * MT9V022 _really_ corrupts the first read out line. |
852 | * TODO: verify on i.MX31 | 913 | * TODO: verify on i.MX31 |
853 | */ | 914 | */ |
854 | icd->y_skip_top = 1; | 915 | mt9v022->y_skip_top = 1; |
855 | |||
856 | mt9v022->rect.left = MT9V022_COLUMN_SKIP; | 916 | mt9v022->rect.left = MT9V022_COLUMN_SKIP; |
857 | mt9v022->rect.top = MT9V022_ROW_SKIP; | 917 | mt9v022->rect.top = MT9V022_ROW_SKIP; |
858 | mt9v022->rect.width = MT9V022_MAX_WIDTH; | 918 | mt9v022->rect.width = MT9V022_MAX_WIDTH; |
diff --git a/drivers/media/video/mx1_camera.c b/drivers/media/video/mx1_camera.c index 72802291e812..c167cc3de492 100644 --- a/drivers/media/video/mx1_camera.c +++ b/drivers/media/video/mx1_camera.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <media/v4l2-common.h> | 37 | #include <media/v4l2-common.h> |
38 | #include <media/v4l2-dev.h> | 38 | #include <media/v4l2-dev.h> |
39 | #include <media/videobuf-dma-contig.h> | 39 | #include <media/videobuf-dma-contig.h> |
40 | #include <media/soc_mediabus.h> | ||
40 | 41 | ||
41 | #include <asm/dma.h> | 42 | #include <asm/dma.h> |
42 | #include <asm/fiq.h> | 43 | #include <asm/fiq.h> |
@@ -94,14 +95,16 @@ | |||
94 | /* buffer for one video frame */ | 95 | /* buffer for one video frame */ |
95 | struct mx1_buffer { | 96 | struct mx1_buffer { |
96 | /* common v4l buffer stuff -- must be first */ | 97 | /* common v4l buffer stuff -- must be first */ |
97 | struct videobuf_buffer vb; | 98 | struct videobuf_buffer vb; |
98 | const struct soc_camera_data_format *fmt; | 99 | enum v4l2_mbus_pixelcode code; |
99 | int inwork; | 100 | int inwork; |
100 | }; | 101 | }; |
101 | 102 | ||
102 | /* i.MX1/i.MXL is only supposed to handle one camera on its Camera Sensor | 103 | /* |
104 | * i.MX1/i.MXL is only supposed to handle one camera on its Camera Sensor | ||
103 | * Interface. If anyone ever builds hardware to enable more than | 105 | * Interface. If anyone ever builds hardware to enable more than |
104 | * one camera, they will have to modify this driver too */ | 106 | * one camera, they will have to modify this driver too |
107 | */ | ||
105 | struct mx1_camera_dev { | 108 | struct mx1_camera_dev { |
106 | struct soc_camera_host soc_host; | 109 | struct soc_camera_host soc_host; |
107 | struct soc_camera_device *icd; | 110 | struct soc_camera_device *icd; |
@@ -126,9 +129,13 @@ static int mx1_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, | |||
126 | unsigned int *size) | 129 | unsigned int *size) |
127 | { | 130 | { |
128 | struct soc_camera_device *icd = vq->priv_data; | 131 | struct soc_camera_device *icd = vq->priv_data; |
132 | int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, | ||
133 | icd->current_fmt->host_fmt); | ||
134 | |||
135 | if (bytes_per_line < 0) | ||
136 | return bytes_per_line; | ||
129 | 137 | ||
130 | *size = icd->user_width * icd->user_height * | 138 | *size = bytes_per_line * icd->user_height; |
131 | ((icd->current_fmt->depth + 7) >> 3); | ||
132 | 139 | ||
133 | if (!*count) | 140 | if (!*count) |
134 | *count = 32; | 141 | *count = 32; |
@@ -151,8 +158,10 @@ static void free_buffer(struct videobuf_queue *vq, struct mx1_buffer *buf) | |||
151 | dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, | 158 | dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, |
152 | vb, vb->baddr, vb->bsize); | 159 | vb, vb->baddr, vb->bsize); |
153 | 160 | ||
154 | /* This waits until this buffer is out of danger, i.e., until it is no | 161 | /* |
155 | * longer in STATE_QUEUED or STATE_ACTIVE */ | 162 | * This waits until this buffer is out of danger, i.e., until it is no |
163 | * longer in STATE_QUEUED or STATE_ACTIVE | ||
164 | */ | ||
156 | videobuf_waiton(vb, 0, 0); | 165 | videobuf_waiton(vb, 0, 0); |
157 | videobuf_dma_contig_free(vq, vb); | 166 | videobuf_dma_contig_free(vq, vb); |
158 | 167 | ||
@@ -165,6 +174,11 @@ static int mx1_videobuf_prepare(struct videobuf_queue *vq, | |||
165 | struct soc_camera_device *icd = vq->priv_data; | 174 | struct soc_camera_device *icd = vq->priv_data; |
166 | struct mx1_buffer *buf = container_of(vb, struct mx1_buffer, vb); | 175 | struct mx1_buffer *buf = container_of(vb, struct mx1_buffer, vb); |
167 | int ret; | 176 | int ret; |
177 | int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, | ||
178 | icd->current_fmt->host_fmt); | ||
179 | |||
180 | if (bytes_per_line < 0) | ||
181 | return bytes_per_line; | ||
168 | 182 | ||
169 | dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, | 183 | dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, |
170 | vb, vb->baddr, vb->bsize); | 184 | vb, vb->baddr, vb->bsize); |
@@ -174,22 +188,24 @@ static int mx1_videobuf_prepare(struct videobuf_queue *vq, | |||
174 | 188 | ||
175 | BUG_ON(NULL == icd->current_fmt); | 189 | BUG_ON(NULL == icd->current_fmt); |
176 | 190 | ||
177 | /* I think, in buf_prepare you only have to protect global data, | 191 | /* |
178 | * the actual buffer is yours */ | 192 | * I think, in buf_prepare you only have to protect global data, |
193 | * the actual buffer is yours | ||
194 | */ | ||
179 | buf->inwork = 1; | 195 | buf->inwork = 1; |
180 | 196 | ||
181 | if (buf->fmt != icd->current_fmt || | 197 | if (buf->code != icd->current_fmt->code || |
182 | vb->width != icd->user_width || | 198 | vb->width != icd->user_width || |
183 | vb->height != icd->user_height || | 199 | vb->height != icd->user_height || |
184 | vb->field != field) { | 200 | vb->field != field) { |
185 | buf->fmt = icd->current_fmt; | 201 | buf->code = icd->current_fmt->code; |
186 | vb->width = icd->user_width; | 202 | vb->width = icd->user_width; |
187 | vb->height = icd->user_height; | 203 | vb->height = icd->user_height; |
188 | vb->field = field; | 204 | vb->field = field; |
189 | vb->state = VIDEOBUF_NEEDS_INIT; | 205 | vb->state = VIDEOBUF_NEEDS_INIT; |
190 | } | 206 | } |
191 | 207 | ||
192 | vb->size = vb->width * vb->height * ((buf->fmt->depth + 7) >> 3); | 208 | vb->size = bytes_per_line * vb->height; |
193 | if (0 != vb->baddr && vb->bsize < vb->size) { | 209 | if (0 != vb->baddr && vb->bsize < vb->size) { |
194 | ret = -EINVAL; | 210 | ret = -EINVAL; |
195 | goto out; | 211 | goto out; |
@@ -381,8 +397,10 @@ static int mclk_get_divisor(struct mx1_camera_dev *pcdev) | |||
381 | 397 | ||
382 | lcdclk = clk_get_rate(pcdev->clk); | 398 | lcdclk = clk_get_rate(pcdev->clk); |
383 | 399 | ||
384 | /* We verify platform_mclk_10khz != 0, so if anyone breaks it, here | 400 | /* |
385 | * they get a nice Oops */ | 401 | * We verify platform_mclk_10khz != 0, so if anyone breaks it, here |
402 | * they get a nice Oops | ||
403 | */ | ||
386 | div = (lcdclk + 2 * mclk - 1) / (2 * mclk) - 1; | 404 | div = (lcdclk + 2 * mclk - 1) / (2 * mclk) - 1; |
387 | 405 | ||
388 | dev_dbg(pcdev->icd->dev.parent, | 406 | dev_dbg(pcdev->icd->dev.parent, |
@@ -420,8 +438,10 @@ static void mx1_camera_deactivate(struct mx1_camera_dev *pcdev) | |||
420 | clk_disable(pcdev->clk); | 438 | clk_disable(pcdev->clk); |
421 | } | 439 | } |
422 | 440 | ||
423 | /* The following two functions absolutely depend on the fact, that | 441 | /* |
424 | * there can be only one camera on i.MX1/i.MXL camera sensor interface */ | 442 | * The following two functions absolutely depend on the fact, that |
443 | * there can be only one camera on i.MX1/i.MXL camera sensor interface | ||
444 | */ | ||
425 | static int mx1_camera_add_device(struct soc_camera_device *icd) | 445 | static int mx1_camera_add_device(struct soc_camera_device *icd) |
426 | { | 446 | { |
427 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | 447 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); |
@@ -487,12 +507,10 @@ static int mx1_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) | |||
487 | 507 | ||
488 | /* MX1 supports only 8bit buswidth */ | 508 | /* MX1 supports only 8bit buswidth */ |
489 | common_flags = soc_camera_bus_param_compatible(camera_flags, | 509 | common_flags = soc_camera_bus_param_compatible(camera_flags, |
490 | CSI_BUS_FLAGS); | 510 | CSI_BUS_FLAGS); |
491 | if (!common_flags) | 511 | if (!common_flags) |
492 | return -EINVAL; | 512 | return -EINVAL; |
493 | 513 | ||
494 | icd->buswidth = 8; | ||
495 | |||
496 | /* Make choises, based on platform choice */ | 514 | /* Make choises, based on platform choice */ |
497 | if ((common_flags & SOCAM_VSYNC_ACTIVE_HIGH) && | 515 | if ((common_flags & SOCAM_VSYNC_ACTIVE_HIGH) && |
498 | (common_flags & SOCAM_VSYNC_ACTIVE_LOW)) { | 516 | (common_flags & SOCAM_VSYNC_ACTIVE_LOW)) { |
@@ -545,7 +563,8 @@ static int mx1_camera_set_fmt(struct soc_camera_device *icd, | |||
545 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | 563 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
546 | const struct soc_camera_format_xlate *xlate; | 564 | const struct soc_camera_format_xlate *xlate; |
547 | struct v4l2_pix_format *pix = &f->fmt.pix; | 565 | struct v4l2_pix_format *pix = &f->fmt.pix; |
548 | int ret; | 566 | struct v4l2_mbus_framefmt mf; |
567 | int ret, buswidth; | ||
549 | 568 | ||
550 | xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); | 569 | xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); |
551 | if (!xlate) { | 570 | if (!xlate) { |
@@ -554,12 +573,33 @@ static int mx1_camera_set_fmt(struct soc_camera_device *icd, | |||
554 | return -EINVAL; | 573 | return -EINVAL; |
555 | } | 574 | } |
556 | 575 | ||
557 | ret = v4l2_subdev_call(sd, video, s_fmt, f); | 576 | buswidth = xlate->host_fmt->bits_per_sample; |
558 | if (!ret) { | 577 | if (buswidth > 8) { |
559 | icd->buswidth = xlate->buswidth; | 578 | dev_warn(icd->dev.parent, |
560 | icd->current_fmt = xlate->host_fmt; | 579 | "bits-per-sample %d for format %x unsupported\n", |
580 | buswidth, pix->pixelformat); | ||
581 | return -EINVAL; | ||
561 | } | 582 | } |
562 | 583 | ||
584 | mf.width = pix->width; | ||
585 | mf.height = pix->height; | ||
586 | mf.field = pix->field; | ||
587 | mf.colorspace = pix->colorspace; | ||
588 | mf.code = xlate->code; | ||
589 | |||
590 | ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf); | ||
591 | if (ret < 0) | ||
592 | return ret; | ||
593 | |||
594 | if (mf.code != xlate->code) | ||
595 | return -EINVAL; | ||
596 | |||
597 | pix->width = mf.width; | ||
598 | pix->height = mf.height; | ||
599 | pix->field = mf.field; | ||
600 | pix->colorspace = mf.colorspace; | ||
601 | icd->current_fmt = xlate; | ||
602 | |||
563 | return ret; | 603 | return ret; |
564 | } | 604 | } |
565 | 605 | ||
@@ -567,10 +607,36 @@ static int mx1_camera_try_fmt(struct soc_camera_device *icd, | |||
567 | struct v4l2_format *f) | 607 | struct v4l2_format *f) |
568 | { | 608 | { |
569 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | 609 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
610 | const struct soc_camera_format_xlate *xlate; | ||
611 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
612 | struct v4l2_mbus_framefmt mf; | ||
613 | int ret; | ||
570 | /* TODO: limit to mx1 hardware capabilities */ | 614 | /* TODO: limit to mx1 hardware capabilities */ |
571 | 615 | ||
616 | xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); | ||
617 | if (!xlate) { | ||
618 | dev_warn(icd->dev.parent, "Format %x not found\n", | ||
619 | pix->pixelformat); | ||
620 | return -EINVAL; | ||
621 | } | ||
622 | |||
623 | mf.width = pix->width; | ||
624 | mf.height = pix->height; | ||
625 | mf.field = pix->field; | ||
626 | mf.colorspace = pix->colorspace; | ||
627 | mf.code = xlate->code; | ||
628 | |||
572 | /* limit to sensor capabilities */ | 629 | /* limit to sensor capabilities */ |
573 | return v4l2_subdev_call(sd, video, try_fmt, f); | 630 | ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf); |
631 | if (ret < 0) | ||
632 | return ret; | ||
633 | |||
634 | pix->width = mf.width; | ||
635 | pix->height = mf.height; | ||
636 | pix->field = mf.field; | ||
637 | pix->colorspace = mf.colorspace; | ||
638 | |||
639 | return 0; | ||
574 | } | 640 | } |
575 | 641 | ||
576 | static int mx1_camera_reqbufs(struct soc_camera_file *icf, | 642 | static int mx1_camera_reqbufs(struct soc_camera_file *icf, |
@@ -578,10 +644,12 @@ static int mx1_camera_reqbufs(struct soc_camera_file *icf, | |||
578 | { | 644 | { |
579 | int i; | 645 | int i; |
580 | 646 | ||
581 | /* This is for locking debugging only. I removed spinlocks and now I | 647 | /* |
648 | * This is for locking debugging only. I removed spinlocks and now I | ||
582 | * check whether .prepare is ever called on a linked buffer, or whether | 649 | * check whether .prepare is ever called on a linked buffer, or whether |
583 | * a dma IRQ can occur for an in-work or unlinked buffer. Until now | 650 | * a dma IRQ can occur for an in-work or unlinked buffer. Until now |
584 | * it hadn't triggered */ | 651 | * it hadn't triggered |
652 | */ | ||
585 | for (i = 0; i < p->count; i++) { | 653 | for (i = 0; i < p->count; i++) { |
586 | struct mx1_buffer *buf = container_of(icf->vb_vidq.bufs[i], | 654 | struct mx1_buffer *buf = container_of(icf->vb_vidq.bufs[i], |
587 | struct mx1_buffer, vb); | 655 | struct mx1_buffer, vb); |
@@ -650,7 +718,7 @@ static int __init mx1_camera_probe(struct platform_device *pdev) | |||
650 | 718 | ||
651 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 719 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
652 | irq = platform_get_irq(pdev, 0); | 720 | irq = platform_get_irq(pdev, 0); |
653 | if (!res || !irq) { | 721 | if (!res || (int)irq <= 0) { |
654 | err = -ENODEV; | 722 | err = -ENODEV; |
655 | goto exit; | 723 | goto exit; |
656 | } | 724 | } |
diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c index 7db82bdf6f31..bd297f567dc7 100644 --- a/drivers/media/video/mx3_camera.c +++ b/drivers/media/video/mx3_camera.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <media/v4l2-dev.h> | 23 | #include <media/v4l2-dev.h> |
24 | #include <media/videobuf-dma-contig.h> | 24 | #include <media/videobuf-dma-contig.h> |
25 | #include <media/soc_camera.h> | 25 | #include <media/soc_camera.h> |
26 | #include <media/soc_mediabus.h> | ||
26 | 27 | ||
27 | #include <mach/ipu.h> | 28 | #include <mach/ipu.h> |
28 | #include <mach/mx3_camera.h> | 29 | #include <mach/mx3_camera.h> |
@@ -63,7 +64,7 @@ | |||
63 | struct mx3_camera_buffer { | 64 | struct mx3_camera_buffer { |
64 | /* common v4l buffer stuff -- must be first */ | 65 | /* common v4l buffer stuff -- must be first */ |
65 | struct videobuf_buffer vb; | 66 | struct videobuf_buffer vb; |
66 | const struct soc_camera_data_format *fmt; | 67 | enum v4l2_mbus_pixelcode code; |
67 | 68 | ||
68 | /* One descriptot per scatterlist (per frame) */ | 69 | /* One descriptot per scatterlist (per frame) */ |
69 | struct dma_async_tx_descriptor *txd; | 70 | struct dma_async_tx_descriptor *txd; |
@@ -118,8 +119,6 @@ struct dma_chan_request { | |||
118 | enum ipu_channel id; | 119 | enum ipu_channel id; |
119 | }; | 120 | }; |
120 | 121 | ||
121 | static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt); | ||
122 | |||
123 | static u32 csi_reg_read(struct mx3_camera_dev *mx3, off_t reg) | 122 | static u32 csi_reg_read(struct mx3_camera_dev *mx3, off_t reg) |
124 | { | 123 | { |
125 | return __raw_readl(mx3->base + reg); | 124 | return __raw_readl(mx3->base + reg); |
@@ -211,17 +210,16 @@ static int mx3_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, | |||
211 | struct soc_camera_device *icd = vq->priv_data; | 210 | struct soc_camera_device *icd = vq->priv_data; |
212 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | 211 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); |
213 | struct mx3_camera_dev *mx3_cam = ici->priv; | 212 | struct mx3_camera_dev *mx3_cam = ici->priv; |
214 | /* | 213 | int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, |
215 | * bits-per-pixel (depth) as specified in camera's pixel format does | 214 | icd->current_fmt->host_fmt); |
216 | * not necessarily match what the camera interface writes to RAM, but | 215 | |
217 | * it should be good enough for now. | 216 | if (bytes_per_line < 0) |
218 | */ | 217 | return bytes_per_line; |
219 | unsigned int bpp = DIV_ROUND_UP(icd->current_fmt->depth, 8); | ||
220 | 218 | ||
221 | if (!mx3_cam->idmac_channel[0]) | 219 | if (!mx3_cam->idmac_channel[0]) |
222 | return -EINVAL; | 220 | return -EINVAL; |
223 | 221 | ||
224 | *size = icd->user_width * icd->user_height * bpp; | 222 | *size = bytes_per_line * icd->user_height; |
225 | 223 | ||
226 | if (!*count) | 224 | if (!*count) |
227 | *count = 32; | 225 | *count = 32; |
@@ -241,21 +239,26 @@ static int mx3_videobuf_prepare(struct videobuf_queue *vq, | |||
241 | struct mx3_camera_dev *mx3_cam = ici->priv; | 239 | struct mx3_camera_dev *mx3_cam = ici->priv; |
242 | struct mx3_camera_buffer *buf = | 240 | struct mx3_camera_buffer *buf = |
243 | container_of(vb, struct mx3_camera_buffer, vb); | 241 | container_of(vb, struct mx3_camera_buffer, vb); |
244 | /* current_fmt _must_ always be set */ | 242 | size_t new_size; |
245 | size_t new_size = icd->user_width * icd->user_height * | ||
246 | ((icd->current_fmt->depth + 7) >> 3); | ||
247 | int ret; | 243 | int ret; |
244 | int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, | ||
245 | icd->current_fmt->host_fmt); | ||
246 | |||
247 | if (bytes_per_line < 0) | ||
248 | return bytes_per_line; | ||
249 | |||
250 | new_size = bytes_per_line * icd->user_height; | ||
248 | 251 | ||
249 | /* | 252 | /* |
250 | * I think, in buf_prepare you only have to protect global data, | 253 | * I think, in buf_prepare you only have to protect global data, |
251 | * the actual buffer is yours | 254 | * the actual buffer is yours |
252 | */ | 255 | */ |
253 | 256 | ||
254 | if (buf->fmt != icd->current_fmt || | 257 | if (buf->code != icd->current_fmt->code || |
255 | vb->width != icd->user_width || | 258 | vb->width != icd->user_width || |
256 | vb->height != icd->user_height || | 259 | vb->height != icd->user_height || |
257 | vb->field != field) { | 260 | vb->field != field) { |
258 | buf->fmt = icd->current_fmt; | 261 | buf->code = icd->current_fmt->code; |
259 | vb->width = icd->user_width; | 262 | vb->width = icd->user_width; |
260 | vb->height = icd->user_height; | 263 | vb->height = icd->user_height; |
261 | vb->field = field; | 264 | vb->field = field; |
@@ -348,13 +351,13 @@ static void mx3_videobuf_queue(struct videobuf_queue *vq, | |||
348 | struct dma_async_tx_descriptor *txd = buf->txd; | 351 | struct dma_async_tx_descriptor *txd = buf->txd; |
349 | struct idmac_channel *ichan = to_idmac_chan(txd->chan); | 352 | struct idmac_channel *ichan = to_idmac_chan(txd->chan); |
350 | struct idmac_video_param *video = &ichan->params.video; | 353 | struct idmac_video_param *video = &ichan->params.video; |
351 | const struct soc_camera_data_format *data_fmt = icd->current_fmt; | ||
352 | dma_cookie_t cookie; | 354 | dma_cookie_t cookie; |
355 | u32 fourcc = icd->current_fmt->host_fmt->fourcc; | ||
353 | 356 | ||
354 | BUG_ON(!irqs_disabled()); | 357 | BUG_ON(!irqs_disabled()); |
355 | 358 | ||
356 | /* This is the configuration of one sg-element */ | 359 | /* This is the configuration of one sg-element */ |
357 | video->out_pixel_fmt = fourcc_to_ipu_pix(data_fmt->fourcc); | 360 | video->out_pixel_fmt = fourcc_to_ipu_pix(fourcc); |
358 | video->out_width = icd->user_width; | 361 | video->out_width = icd->user_width; |
359 | video->out_height = icd->user_height; | 362 | video->out_height = icd->user_height; |
360 | video->out_stride = icd->user_width; | 363 | video->out_stride = icd->user_width; |
@@ -564,30 +567,37 @@ static int test_platform_param(struct mx3_camera_dev *mx3_cam, | |||
564 | SOCAM_DATA_ACTIVE_HIGH | | 567 | SOCAM_DATA_ACTIVE_HIGH | |
565 | SOCAM_DATA_ACTIVE_LOW; | 568 | SOCAM_DATA_ACTIVE_LOW; |
566 | 569 | ||
567 | /* If requested data width is supported by the platform, use it or any | 570 | /* |
568 | * possible lower value - i.MX31 is smart enough to schift bits */ | 571 | * If requested data width is supported by the platform, use it or any |
572 | * possible lower value - i.MX31 is smart enough to schift bits | ||
573 | */ | ||
574 | if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_15) | ||
575 | *flags |= SOCAM_DATAWIDTH_15 | SOCAM_DATAWIDTH_10 | | ||
576 | SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_4; | ||
577 | else if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_10) | ||
578 | *flags |= SOCAM_DATAWIDTH_10 | SOCAM_DATAWIDTH_8 | | ||
579 | SOCAM_DATAWIDTH_4; | ||
580 | else if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_8) | ||
581 | *flags |= SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_4; | ||
582 | else if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_4) | ||
583 | *flags |= SOCAM_DATAWIDTH_4; | ||
584 | |||
569 | switch (buswidth) { | 585 | switch (buswidth) { |
570 | case 15: | 586 | case 15: |
571 | if (!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_15)) | 587 | if (!(*flags & SOCAM_DATAWIDTH_15)) |
572 | return -EINVAL; | 588 | return -EINVAL; |
573 | *flags |= SOCAM_DATAWIDTH_15 | SOCAM_DATAWIDTH_10 | | ||
574 | SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_4; | ||
575 | break; | 589 | break; |
576 | case 10: | 590 | case 10: |
577 | if (!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_10)) | 591 | if (!(*flags & SOCAM_DATAWIDTH_10)) |
578 | return -EINVAL; | 592 | return -EINVAL; |
579 | *flags |= SOCAM_DATAWIDTH_10 | SOCAM_DATAWIDTH_8 | | ||
580 | SOCAM_DATAWIDTH_4; | ||
581 | break; | 593 | break; |
582 | case 8: | 594 | case 8: |
583 | if (!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_8)) | 595 | if (!(*flags & SOCAM_DATAWIDTH_8)) |
584 | return -EINVAL; | 596 | return -EINVAL; |
585 | *flags |= SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_4; | ||
586 | break; | 597 | break; |
587 | case 4: | 598 | case 4: |
588 | if (!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_4)) | 599 | if (!(*flags & SOCAM_DATAWIDTH_4)) |
589 | return -EINVAL; | 600 | return -EINVAL; |
590 | *flags |= SOCAM_DATAWIDTH_4; | ||
591 | break; | 601 | break; |
592 | default: | 602 | default: |
593 | dev_warn(mx3_cam->soc_host.v4l2_dev.dev, | 603 | dev_warn(mx3_cam->soc_host.v4l2_dev.dev, |
@@ -636,91 +646,92 @@ static bool chan_filter(struct dma_chan *chan, void *arg) | |||
636 | pdata->dma_dev == chan->device->dev; | 646 | pdata->dma_dev == chan->device->dev; |
637 | } | 647 | } |
638 | 648 | ||
639 | static const struct soc_camera_data_format mx3_camera_formats[] = { | 649 | static const struct soc_mbus_pixelfmt mx3_camera_formats[] = { |
640 | { | 650 | { |
641 | .name = "Bayer (sRGB) 8 bit", | 651 | .fourcc = V4L2_PIX_FMT_SBGGR8, |
642 | .depth = 8, | 652 | .name = "Bayer BGGR (sRGB) 8 bit", |
643 | .fourcc = V4L2_PIX_FMT_SBGGR8, | 653 | .bits_per_sample = 8, |
644 | .colorspace = V4L2_COLORSPACE_SRGB, | 654 | .packing = SOC_MBUS_PACKING_NONE, |
655 | .order = SOC_MBUS_ORDER_LE, | ||
645 | }, { | 656 | }, { |
646 | .name = "Monochrome 8 bit", | 657 | .fourcc = V4L2_PIX_FMT_GREY, |
647 | .depth = 8, | 658 | .name = "Monochrome 8 bit", |
648 | .fourcc = V4L2_PIX_FMT_GREY, | 659 | .bits_per_sample = 8, |
649 | .colorspace = V4L2_COLORSPACE_JPEG, | 660 | .packing = SOC_MBUS_PACKING_NONE, |
661 | .order = SOC_MBUS_ORDER_LE, | ||
650 | }, | 662 | }, |
651 | }; | 663 | }; |
652 | 664 | ||
653 | static bool buswidth_supported(struct soc_camera_host *ici, int depth) | 665 | /* This will be corrected as we get more formats */ |
666 | static bool mx3_camera_packing_supported(const struct soc_mbus_pixelfmt *fmt) | ||
654 | { | 667 | { |
655 | struct mx3_camera_dev *mx3_cam = ici->priv; | 668 | return fmt->packing == SOC_MBUS_PACKING_NONE || |
656 | 669 | (fmt->bits_per_sample == 8 && | |
657 | switch (depth) { | 670 | fmt->packing == SOC_MBUS_PACKING_2X8_PADHI) || |
658 | case 4: | 671 | (fmt->bits_per_sample > 8 && |
659 | return !!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_4); | 672 | fmt->packing == SOC_MBUS_PACKING_EXTEND16); |
660 | case 8: | ||
661 | return !!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_8); | ||
662 | case 10: | ||
663 | return !!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_10); | ||
664 | case 15: | ||
665 | return !!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_15); | ||
666 | } | ||
667 | return false; | ||
668 | } | 673 | } |
669 | 674 | ||
670 | static int mx3_camera_get_formats(struct soc_camera_device *icd, int idx, | 675 | static int mx3_camera_get_formats(struct soc_camera_device *icd, int idx, |
671 | struct soc_camera_format_xlate *xlate) | 676 | struct soc_camera_format_xlate *xlate) |
672 | { | 677 | { |
673 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | 678 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
674 | int formats = 0, buswidth, ret; | 679 | struct device *dev = icd->dev.parent; |
680 | int formats = 0, ret; | ||
681 | enum v4l2_mbus_pixelcode code; | ||
682 | const struct soc_mbus_pixelfmt *fmt; | ||
675 | 683 | ||
676 | buswidth = icd->formats[idx].depth; | 684 | ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code); |
685 | if (ret < 0) | ||
686 | /* No more formats */ | ||
687 | return 0; | ||
677 | 688 | ||
678 | if (!buswidth_supported(ici, buswidth)) | 689 | fmt = soc_mbus_get_fmtdesc(code); |
690 | if (!fmt) { | ||
691 | dev_err(icd->dev.parent, | ||
692 | "Invalid format code #%d: %d\n", idx, code); | ||
679 | return 0; | 693 | return 0; |
694 | } | ||
680 | 695 | ||
681 | ret = mx3_camera_try_bus_param(icd, buswidth); | 696 | /* This also checks support for the requested bits-per-sample */ |
697 | ret = mx3_camera_try_bus_param(icd, fmt->bits_per_sample); | ||
682 | if (ret < 0) | 698 | if (ret < 0) |
683 | return 0; | 699 | return 0; |
684 | 700 | ||
685 | switch (icd->formats[idx].fourcc) { | 701 | switch (code) { |
686 | case V4L2_PIX_FMT_SGRBG10: | 702 | case V4L2_MBUS_FMT_SBGGR10_1X10: |
687 | formats++; | 703 | formats++; |
688 | if (xlate) { | 704 | if (xlate) { |
689 | xlate->host_fmt = &mx3_camera_formats[0]; | 705 | xlate->host_fmt = &mx3_camera_formats[0]; |
690 | xlate->cam_fmt = icd->formats + idx; | 706 | xlate->code = code; |
691 | xlate->buswidth = buswidth; | ||
692 | xlate++; | 707 | xlate++; |
693 | dev_dbg(icd->dev.parent, | 708 | dev_dbg(dev, "Providing format %s using code %d\n", |
694 | "Providing format %s using %s\n", | 709 | mx3_camera_formats[0].name, code); |
695 | mx3_camera_formats[0].name, | ||
696 | icd->formats[idx].name); | ||
697 | } | 710 | } |
698 | goto passthrough; | 711 | break; |
699 | case V4L2_PIX_FMT_Y16: | 712 | case V4L2_MBUS_FMT_Y10_1X10: |
700 | formats++; | 713 | formats++; |
701 | if (xlate) { | 714 | if (xlate) { |
702 | xlate->host_fmt = &mx3_camera_formats[1]; | 715 | xlate->host_fmt = &mx3_camera_formats[1]; |
703 | xlate->cam_fmt = icd->formats + idx; | 716 | xlate->code = code; |
704 | xlate->buswidth = buswidth; | ||
705 | xlate++; | 717 | xlate++; |
706 | dev_dbg(icd->dev.parent, | 718 | dev_dbg(dev, "Providing format %s using code %d\n", |
707 | "Providing format %s using %s\n", | 719 | mx3_camera_formats[1].name, code); |
708 | mx3_camera_formats[0].name, | ||
709 | icd->formats[idx].name); | ||
710 | } | 720 | } |
721 | break; | ||
711 | default: | 722 | default: |
712 | passthrough: | 723 | if (!mx3_camera_packing_supported(fmt)) |
713 | /* Generic pass-through */ | 724 | return 0; |
714 | formats++; | 725 | } |
715 | if (xlate) { | 726 | |
716 | xlate->host_fmt = icd->formats + idx; | 727 | /* Generic pass-through */ |
717 | xlate->cam_fmt = icd->formats + idx; | 728 | formats++; |
718 | xlate->buswidth = buswidth; | 729 | if (xlate) { |
719 | xlate++; | 730 | xlate->host_fmt = fmt; |
720 | dev_dbg(icd->dev.parent, | 731 | xlate->code = code; |
721 | "Providing format %s in pass-through mode\n", | 732 | xlate++; |
722 | icd->formats[idx].name); | 733 | dev_dbg(dev, "Providing format %x in pass-through mode\n", |
723 | } | 734 | xlate->host_fmt->fourcc); |
724 | } | 735 | } |
725 | 736 | ||
726 | return formats; | 737 | return formats; |
@@ -804,8 +815,7 @@ static int mx3_camera_set_crop(struct soc_camera_device *icd, | |||
804 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | 815 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); |
805 | struct mx3_camera_dev *mx3_cam = ici->priv; | 816 | struct mx3_camera_dev *mx3_cam = ici->priv; |
806 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | 817 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
807 | struct v4l2_format f = {.type = V4L2_BUF_TYPE_VIDEO_CAPTURE}; | 818 | struct v4l2_mbus_framefmt mf; |
808 | struct v4l2_pix_format *pix = &f.fmt.pix; | ||
809 | int ret; | 819 | int ret; |
810 | 820 | ||
811 | soc_camera_limit_side(&rect->left, &rect->width, 0, 2, 4096); | 821 | soc_camera_limit_side(&rect->left, &rect->width, 0, 2, 4096); |
@@ -816,19 +826,19 @@ static int mx3_camera_set_crop(struct soc_camera_device *icd, | |||
816 | return ret; | 826 | return ret; |
817 | 827 | ||
818 | /* The capture device might have changed its output */ | 828 | /* The capture device might have changed its output */ |
819 | ret = v4l2_subdev_call(sd, video, g_fmt, &f); | 829 | ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf); |
820 | if (ret < 0) | 830 | if (ret < 0) |
821 | return ret; | 831 | return ret; |
822 | 832 | ||
823 | if (pix->width & 7) { | 833 | if (mf.width & 7) { |
824 | /* Ouch! We can only handle 8-byte aligned width... */ | 834 | /* Ouch! We can only handle 8-byte aligned width... */ |
825 | stride_align(&pix->width); | 835 | stride_align(&mf.width); |
826 | ret = v4l2_subdev_call(sd, video, s_fmt, &f); | 836 | ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf); |
827 | if (ret < 0) | 837 | if (ret < 0) |
828 | return ret; | 838 | return ret; |
829 | } | 839 | } |
830 | 840 | ||
831 | if (pix->width != icd->user_width || pix->height != icd->user_height) { | 841 | if (mf.width != icd->user_width || mf.height != icd->user_height) { |
832 | /* | 842 | /* |
833 | * We now know pixel formats and can decide upon DMA-channel(s) | 843 | * We now know pixel formats and can decide upon DMA-channel(s) |
834 | * So far only direct camera-to-memory is supported | 844 | * So far only direct camera-to-memory is supported |
@@ -839,14 +849,14 @@ static int mx3_camera_set_crop(struct soc_camera_device *icd, | |||
839 | return ret; | 849 | return ret; |
840 | } | 850 | } |
841 | 851 | ||
842 | configure_geometry(mx3_cam, pix->width, pix->height); | 852 | configure_geometry(mx3_cam, mf.width, mf.height); |
843 | } | 853 | } |
844 | 854 | ||
845 | dev_dbg(icd->dev.parent, "Sensor cropped %dx%d\n", | 855 | dev_dbg(icd->dev.parent, "Sensor cropped %dx%d\n", |
846 | pix->width, pix->height); | 856 | mf.width, mf.height); |
847 | 857 | ||
848 | icd->user_width = pix->width; | 858 | icd->user_width = mf.width; |
849 | icd->user_height = pix->height; | 859 | icd->user_height = mf.height; |
850 | 860 | ||
851 | return ret; | 861 | return ret; |
852 | } | 862 | } |
@@ -859,6 +869,7 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd, | |||
859 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | 869 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
860 | const struct soc_camera_format_xlate *xlate; | 870 | const struct soc_camera_format_xlate *xlate; |
861 | struct v4l2_pix_format *pix = &f->fmt.pix; | 871 | struct v4l2_pix_format *pix = &f->fmt.pix; |
872 | struct v4l2_mbus_framefmt mf; | ||
862 | int ret; | 873 | int ret; |
863 | 874 | ||
864 | xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); | 875 | xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); |
@@ -883,11 +894,24 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd, | |||
883 | 894 | ||
884 | configure_geometry(mx3_cam, pix->width, pix->height); | 895 | configure_geometry(mx3_cam, pix->width, pix->height); |
885 | 896 | ||
886 | ret = v4l2_subdev_call(sd, video, s_fmt, f); | 897 | mf.width = pix->width; |
887 | if (!ret) { | 898 | mf.height = pix->height; |
888 | icd->buswidth = xlate->buswidth; | 899 | mf.field = pix->field; |
889 | icd->current_fmt = xlate->host_fmt; | 900 | mf.colorspace = pix->colorspace; |
890 | } | 901 | mf.code = xlate->code; |
902 | |||
903 | ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf); | ||
904 | if (ret < 0) | ||
905 | return ret; | ||
906 | |||
907 | if (mf.code != xlate->code) | ||
908 | return -EINVAL; | ||
909 | |||
910 | pix->width = mf.width; | ||
911 | pix->height = mf.height; | ||
912 | pix->field = mf.field; | ||
913 | pix->colorspace = mf.colorspace; | ||
914 | icd->current_fmt = xlate; | ||
891 | 915 | ||
892 | dev_dbg(icd->dev.parent, "Sensor set %dx%d\n", pix->width, pix->height); | 916 | dev_dbg(icd->dev.parent, "Sensor set %dx%d\n", pix->width, pix->height); |
893 | 917 | ||
@@ -900,8 +924,8 @@ static int mx3_camera_try_fmt(struct soc_camera_device *icd, | |||
900 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | 924 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
901 | const struct soc_camera_format_xlate *xlate; | 925 | const struct soc_camera_format_xlate *xlate; |
902 | struct v4l2_pix_format *pix = &f->fmt.pix; | 926 | struct v4l2_pix_format *pix = &f->fmt.pix; |
927 | struct v4l2_mbus_framefmt mf; | ||
903 | __u32 pixfmt = pix->pixelformat; | 928 | __u32 pixfmt = pix->pixelformat; |
904 | enum v4l2_field field; | ||
905 | int ret; | 929 | int ret; |
906 | 930 | ||
907 | xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); | 931 | xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); |
@@ -916,23 +940,37 @@ static int mx3_camera_try_fmt(struct soc_camera_device *icd, | |||
916 | if (pix->width > 4096) | 940 | if (pix->width > 4096) |
917 | pix->width = 4096; | 941 | pix->width = 4096; |
918 | 942 | ||
919 | pix->bytesperline = pix->width * | 943 | pix->bytesperline = soc_mbus_bytes_per_line(pix->width, |
920 | DIV_ROUND_UP(xlate->host_fmt->depth, 8); | 944 | xlate->host_fmt); |
945 | if (pix->bytesperline < 0) | ||
946 | return pix->bytesperline; | ||
921 | pix->sizeimage = pix->height * pix->bytesperline; | 947 | pix->sizeimage = pix->height * pix->bytesperline; |
922 | 948 | ||
923 | /* camera has to see its format, but the user the original one */ | ||
924 | pix->pixelformat = xlate->cam_fmt->fourcc; | ||
925 | /* limit to sensor capabilities */ | 949 | /* limit to sensor capabilities */ |
926 | ret = v4l2_subdev_call(sd, video, try_fmt, f); | 950 | mf.width = pix->width; |
927 | pix->pixelformat = xlate->host_fmt->fourcc; | 951 | mf.height = pix->height; |
952 | mf.field = pix->field; | ||
953 | mf.colorspace = pix->colorspace; | ||
954 | mf.code = xlate->code; | ||
955 | |||
956 | ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf); | ||
957 | if (ret < 0) | ||
958 | return ret; | ||
928 | 959 | ||
929 | field = pix->field; | 960 | pix->width = mf.width; |
961 | pix->height = mf.height; | ||
962 | pix->colorspace = mf.colorspace; | ||
930 | 963 | ||
931 | if (field == V4L2_FIELD_ANY) { | 964 | switch (mf.field) { |
965 | case V4L2_FIELD_ANY: | ||
932 | pix->field = V4L2_FIELD_NONE; | 966 | pix->field = V4L2_FIELD_NONE; |
933 | } else if (field != V4L2_FIELD_NONE) { | 967 | break; |
934 | dev_err(icd->dev.parent, "Field type %d unsupported.\n", field); | 968 | case V4L2_FIELD_NONE: |
935 | return -EINVAL; | 969 | break; |
970 | default: | ||
971 | dev_err(icd->dev.parent, "Field type %d unsupported.\n", | ||
972 | mf.field); | ||
973 | ret = -EINVAL; | ||
936 | } | 974 | } |
937 | 975 | ||
938 | return ret; | 976 | return ret; |
@@ -968,18 +1006,26 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) | |||
968 | struct mx3_camera_dev *mx3_cam = ici->priv; | 1006 | struct mx3_camera_dev *mx3_cam = ici->priv; |
969 | unsigned long bus_flags, camera_flags, common_flags; | 1007 | unsigned long bus_flags, camera_flags, common_flags; |
970 | u32 dw, sens_conf; | 1008 | u32 dw, sens_conf; |
971 | int ret = test_platform_param(mx3_cam, icd->buswidth, &bus_flags); | 1009 | const struct soc_mbus_pixelfmt *fmt; |
1010 | int buswidth; | ||
1011 | int ret; | ||
972 | const struct soc_camera_format_xlate *xlate; | 1012 | const struct soc_camera_format_xlate *xlate; |
973 | struct device *dev = icd->dev.parent; | 1013 | struct device *dev = icd->dev.parent; |
974 | 1014 | ||
1015 | fmt = soc_mbus_get_fmtdesc(icd->current_fmt->code); | ||
1016 | if (!fmt) | ||
1017 | return -EINVAL; | ||
1018 | |||
1019 | buswidth = fmt->bits_per_sample; | ||
1020 | ret = test_platform_param(mx3_cam, buswidth, &bus_flags); | ||
1021 | |||
975 | xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); | 1022 | xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); |
976 | if (!xlate) { | 1023 | if (!xlate) { |
977 | dev_warn(dev, "Format %x not found\n", pixfmt); | 1024 | dev_warn(dev, "Format %x not found\n", pixfmt); |
978 | return -EINVAL; | 1025 | return -EINVAL; |
979 | } | 1026 | } |
980 | 1027 | ||
981 | dev_dbg(dev, "requested bus width %d bit: %d\n", | 1028 | dev_dbg(dev, "requested bus width %d bit: %d\n", buswidth, ret); |
982 | icd->buswidth, ret); | ||
983 | 1029 | ||
984 | if (ret < 0) | 1030 | if (ret < 0) |
985 | return ret; | 1031 | return ret; |
@@ -1027,8 +1073,10 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) | |||
1027 | common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING; | 1073 | common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING; |
1028 | } | 1074 | } |
1029 | 1075 | ||
1030 | /* Make the camera work in widest common mode, we'll take care of | 1076 | /* |
1031 | * the rest */ | 1077 | * Make the camera work in widest common mode, we'll take care of |
1078 | * the rest | ||
1079 | */ | ||
1032 | if (common_flags & SOCAM_DATAWIDTH_15) | 1080 | if (common_flags & SOCAM_DATAWIDTH_15) |
1033 | common_flags = (common_flags & ~SOCAM_DATAWIDTH_MASK) | | 1081 | common_flags = (common_flags & ~SOCAM_DATAWIDTH_MASK) | |
1034 | SOCAM_DATAWIDTH_15; | 1082 | SOCAM_DATAWIDTH_15; |
@@ -1078,7 +1126,7 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) | |||
1078 | sens_conf |= 1 << CSI_SENS_CONF_DATA_POL_SHIFT; | 1126 | sens_conf |= 1 << CSI_SENS_CONF_DATA_POL_SHIFT; |
1079 | 1127 | ||
1080 | /* Just do what we're asked to do */ | 1128 | /* Just do what we're asked to do */ |
1081 | switch (xlate->host_fmt->depth) { | 1129 | switch (xlate->host_fmt->bits_per_sample) { |
1082 | case 4: | 1130 | case 4: |
1083 | dw = 0 << CSI_SENS_CONF_DATA_WIDTH_SHIFT; | 1131 | dw = 0 << CSI_SENS_CONF_DATA_WIDTH_SHIFT; |
1084 | break; | 1132 | break; |
@@ -1152,8 +1200,10 @@ static int __devinit mx3_camera_probe(struct platform_device *pdev) | |||
1152 | if (!(mx3_cam->platform_flags & (MX3_CAMERA_DATAWIDTH_4 | | 1200 | if (!(mx3_cam->platform_flags & (MX3_CAMERA_DATAWIDTH_4 | |
1153 | MX3_CAMERA_DATAWIDTH_8 | MX3_CAMERA_DATAWIDTH_10 | | 1201 | MX3_CAMERA_DATAWIDTH_8 | MX3_CAMERA_DATAWIDTH_10 | |
1154 | MX3_CAMERA_DATAWIDTH_15))) { | 1202 | MX3_CAMERA_DATAWIDTH_15))) { |
1155 | /* Platform hasn't set available data widths. This is bad. | 1203 | /* |
1156 | * Warn and use a default. */ | 1204 | * Platform hasn't set available data widths. This is bad. |
1205 | * Warn and use a default. | ||
1206 | */ | ||
1157 | dev_warn(&pdev->dev, "WARNING! Platform hasn't set available " | 1207 | dev_warn(&pdev->dev, "WARNING! Platform hasn't set available " |
1158 | "data widths, using default 8 bit\n"); | 1208 | "data widths, using default 8 bit\n"); |
1159 | mx3_cam->platform_flags |= MX3_CAMERA_DATAWIDTH_8; | 1209 | mx3_cam->platform_flags |= MX3_CAMERA_DATAWIDTH_8; |
diff --git a/drivers/media/video/omap24xxcam.c b/drivers/media/video/omap24xxcam.c index 5fc4ac0d88f0..7400eacb4d64 100644 --- a/drivers/media/video/omap24xxcam.c +++ b/drivers/media/video/omap24xxcam.c | |||
@@ -1450,12 +1450,11 @@ static int omap24xxcam_mmap(struct file *file, struct vm_area_struct *vma) | |||
1450 | 1450 | ||
1451 | static int omap24xxcam_open(struct file *file) | 1451 | static int omap24xxcam_open(struct file *file) |
1452 | { | 1452 | { |
1453 | int minor = video_devdata(file)->minor; | ||
1454 | struct omap24xxcam_device *cam = omap24xxcam.priv; | 1453 | struct omap24xxcam_device *cam = omap24xxcam.priv; |
1455 | struct omap24xxcam_fh *fh; | 1454 | struct omap24xxcam_fh *fh; |
1456 | struct v4l2_format format; | 1455 | struct v4l2_format format; |
1457 | 1456 | ||
1458 | if (!cam || !cam->vfd || (cam->vfd->minor != minor)) | 1457 | if (!cam || !cam->vfd) |
1459 | return -ENODEV; | 1458 | return -ENODEV; |
1460 | 1459 | ||
1461 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); | 1460 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); |
@@ -1660,7 +1659,6 @@ static int omap24xxcam_device_register(struct v4l2_int_device *s) | |||
1660 | 1659 | ||
1661 | strlcpy(vfd->name, CAM_NAME, sizeof(vfd->name)); | 1660 | strlcpy(vfd->name, CAM_NAME, sizeof(vfd->name)); |
1662 | vfd->fops = &omap24xxcam_fops; | 1661 | vfd->fops = &omap24xxcam_fops; |
1663 | vfd->minor = -1; | ||
1664 | vfd->ioctl_ops = &omap24xxcam_ioctl_fops; | 1662 | vfd->ioctl_ops = &omap24xxcam_ioctl_fops; |
1665 | 1663 | ||
1666 | omap24xxcam_hwinit(cam); | 1664 | omap24xxcam_hwinit(cam); |
@@ -1671,14 +1669,14 @@ static int omap24xxcam_device_register(struct v4l2_int_device *s) | |||
1671 | 1669 | ||
1672 | if (video_register_device(vfd, VFL_TYPE_GRABBER, video_nr) < 0) { | 1670 | if (video_register_device(vfd, VFL_TYPE_GRABBER, video_nr) < 0) { |
1673 | dev_err(cam->dev, "could not register V4L device\n"); | 1671 | dev_err(cam->dev, "could not register V4L device\n"); |
1674 | vfd->minor = -1; | ||
1675 | rval = -EBUSY; | 1672 | rval = -EBUSY; |
1676 | goto err; | 1673 | goto err; |
1677 | } | 1674 | } |
1678 | 1675 | ||
1679 | omap24xxcam_poweron_reset(cam); | 1676 | omap24xxcam_poweron_reset(cam); |
1680 | 1677 | ||
1681 | dev_info(cam->dev, "registered device video%d\n", vfd->minor); | 1678 | dev_info(cam->dev, "registered device %s\n", |
1679 | video_device_node_name(vfd)); | ||
1682 | 1680 | ||
1683 | return 0; | 1681 | return 0; |
1684 | 1682 | ||
@@ -1695,7 +1693,7 @@ static void omap24xxcam_device_unregister(struct v4l2_int_device *s) | |||
1695 | omap24xxcam_sensor_exit(cam); | 1693 | omap24xxcam_sensor_exit(cam); |
1696 | 1694 | ||
1697 | if (cam->vfd) { | 1695 | if (cam->vfd) { |
1698 | if (cam->vfd->minor == -1) { | 1696 | if (!video_is_registered(cam->vfd)) { |
1699 | /* | 1697 | /* |
1700 | * The device was never registered, so release the | 1698 | * The device was never registered, so release the |
1701 | * video_device struct directly. | 1699 | * video_device struct directly. |
diff --git a/drivers/media/video/ov511.c b/drivers/media/video/ov511.c index 0bc2cf573c76..e0bce8dc74bf 100644 --- a/drivers/media/video/ov511.c +++ b/drivers/media/video/ov511.c | |||
@@ -4674,7 +4674,6 @@ static struct video_device vdev_template = { | |||
4674 | .name = "OV511 USB Camera", | 4674 | .name = "OV511 USB Camera", |
4675 | .fops = &ov511_fops, | 4675 | .fops = &ov511_fops, |
4676 | .release = video_device_release, | 4676 | .release = video_device_release, |
4677 | .minor = -1, | ||
4678 | }; | 4677 | }; |
4679 | 4678 | ||
4680 | /**************************************************************************** | 4679 | /**************************************************************************** |
@@ -5867,8 +5866,8 @@ ov51x_probe(struct usb_interface *intf, const struct usb_device_id *id) | |||
5867 | ov511_devused |= 1 << nr; | 5866 | ov511_devused |= 1 << nr; |
5868 | ov->nr = nr; | 5867 | ov->nr = nr; |
5869 | 5868 | ||
5870 | dev_info(&intf->dev, "Device at %s registered to minor %d\n", | 5869 | dev_info(&intf->dev, "Device at %s registered to %s\n", |
5871 | ov->usb_path, ov->vdev->minor); | 5870 | ov->usb_path, video_device_node_name(ov->vdev)); |
5872 | 5871 | ||
5873 | usb_set_intfdata(intf, ov); | 5872 | usb_set_intfdata(intf, ov); |
5874 | if (ov_create_sysfs(ov->vdev)) { | 5873 | if (ov_create_sysfs(ov->vdev)) { |
@@ -5878,13 +5877,13 @@ ov51x_probe(struct usb_interface *intf, const struct usb_device_id *id) | |||
5878 | goto error; | 5877 | goto error; |
5879 | } | 5878 | } |
5880 | 5879 | ||
5881 | mutex_lock(&ov->lock); | 5880 | mutex_unlock(&ov->lock); |
5882 | 5881 | ||
5883 | return 0; | 5882 | return 0; |
5884 | 5883 | ||
5885 | error: | 5884 | error: |
5886 | if (ov->vdev) { | 5885 | if (ov->vdev) { |
5887 | if (-1 == ov->vdev->minor) | 5886 | if (!video_is_registered(ov->vdev)) |
5888 | video_device_release(ov->vdev); | 5887 | video_device_release(ov->vdev); |
5889 | else | 5888 | else |
5890 | video_unregister_device(ov->vdev); | 5889 | video_unregister_device(ov->vdev); |
diff --git a/drivers/media/video/ov772x.c b/drivers/media/video/ov772x.c index 205229333466..3a45e945a528 100644 --- a/drivers/media/video/ov772x.c +++ b/drivers/media/video/ov772x.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <media/v4l2-chip-ident.h> | 24 | #include <media/v4l2-chip-ident.h> |
25 | #include <media/v4l2-subdev.h> | 25 | #include <media/v4l2-subdev.h> |
26 | #include <media/soc_camera.h> | 26 | #include <media/soc_camera.h> |
27 | #include <media/soc_mediabus.h> | ||
27 | #include <media/ov772x.h> | 28 | #include <media/ov772x.h> |
28 | 29 | ||
29 | /* | 30 | /* |
@@ -382,7 +383,8 @@ struct regval_list { | |||
382 | }; | 383 | }; |
383 | 384 | ||
384 | struct ov772x_color_format { | 385 | struct ov772x_color_format { |
385 | const struct soc_camera_data_format *format; | 386 | enum v4l2_mbus_pixelcode code; |
387 | enum v4l2_colorspace colorspace; | ||
386 | u8 dsp3; | 388 | u8 dsp3; |
387 | u8 com3; | 389 | u8 com3; |
388 | u8 com7; | 390 | u8 com7; |
@@ -399,7 +401,7 @@ struct ov772x_win_size { | |||
399 | struct ov772x_priv { | 401 | struct ov772x_priv { |
400 | struct v4l2_subdev subdev; | 402 | struct v4l2_subdev subdev; |
401 | struct ov772x_camera_info *info; | 403 | struct ov772x_camera_info *info; |
402 | const struct ov772x_color_format *fmt; | 404 | const struct ov772x_color_format *cfmt; |
403 | const struct ov772x_win_size *win; | 405 | const struct ov772x_win_size *win; |
404 | int model; | 406 | int model; |
405 | unsigned short flag_vflip:1; | 407 | unsigned short flag_vflip:1; |
@@ -434,93 +436,57 @@ static const struct regval_list ov772x_vga_regs[] = { | |||
434 | }; | 436 | }; |
435 | 437 | ||
436 | /* | 438 | /* |
437 | * supported format list | 439 | * supported color format list |
438 | */ | ||
439 | |||
440 | #define SETFOURCC(type) .name = (#type), .fourcc = (V4L2_PIX_FMT_ ## type) | ||
441 | static const struct soc_camera_data_format ov772x_fmt_lists[] = { | ||
442 | { | ||
443 | SETFOURCC(YUYV), | ||
444 | .depth = 16, | ||
445 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
446 | }, | ||
447 | { | ||
448 | SETFOURCC(YVYU), | ||
449 | .depth = 16, | ||
450 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
451 | }, | ||
452 | { | ||
453 | SETFOURCC(UYVY), | ||
454 | .depth = 16, | ||
455 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
456 | }, | ||
457 | { | ||
458 | SETFOURCC(RGB555), | ||
459 | .depth = 16, | ||
460 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
461 | }, | ||
462 | { | ||
463 | SETFOURCC(RGB555X), | ||
464 | .depth = 16, | ||
465 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
466 | }, | ||
467 | { | ||
468 | SETFOURCC(RGB565), | ||
469 | .depth = 16, | ||
470 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
471 | }, | ||
472 | { | ||
473 | SETFOURCC(RGB565X), | ||
474 | .depth = 16, | ||
475 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
476 | }, | ||
477 | }; | ||
478 | |||
479 | /* | ||
480 | * color format list | ||
481 | */ | 440 | */ |
482 | static const struct ov772x_color_format ov772x_cfmts[] = { | 441 | static const struct ov772x_color_format ov772x_cfmts[] = { |
483 | { | 442 | { |
484 | .format = &ov772x_fmt_lists[0], | 443 | .code = V4L2_MBUS_FMT_YUYV8_2X8_LE, |
485 | .dsp3 = 0x0, | 444 | .colorspace = V4L2_COLORSPACE_JPEG, |
486 | .com3 = SWAP_YUV, | 445 | .dsp3 = 0x0, |
487 | .com7 = OFMT_YUV, | 446 | .com3 = SWAP_YUV, |
447 | .com7 = OFMT_YUV, | ||
488 | }, | 448 | }, |
489 | { | 449 | { |
490 | .format = &ov772x_fmt_lists[1], | 450 | .code = V4L2_MBUS_FMT_YVYU8_2X8_LE, |
491 | .dsp3 = UV_ON, | 451 | .colorspace = V4L2_COLORSPACE_JPEG, |
492 | .com3 = SWAP_YUV, | 452 | .dsp3 = UV_ON, |
493 | .com7 = OFMT_YUV, | 453 | .com3 = SWAP_YUV, |
454 | .com7 = OFMT_YUV, | ||
494 | }, | 455 | }, |
495 | { | 456 | { |
496 | .format = &ov772x_fmt_lists[2], | 457 | .code = V4L2_MBUS_FMT_YUYV8_2X8_BE, |
497 | .dsp3 = 0x0, | 458 | .colorspace = V4L2_COLORSPACE_JPEG, |
498 | .com3 = 0x0, | 459 | .dsp3 = 0x0, |
499 | .com7 = OFMT_YUV, | 460 | .com3 = 0x0, |
461 | .com7 = OFMT_YUV, | ||
500 | }, | 462 | }, |
501 | { | 463 | { |
502 | .format = &ov772x_fmt_lists[3], | 464 | .code = V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE, |
503 | .dsp3 = 0x0, | 465 | .colorspace = V4L2_COLORSPACE_SRGB, |
504 | .com3 = SWAP_RGB, | 466 | .dsp3 = 0x0, |
505 | .com7 = FMT_RGB555 | OFMT_RGB, | 467 | .com3 = SWAP_RGB, |
468 | .com7 = FMT_RGB555 | OFMT_RGB, | ||
506 | }, | 469 | }, |
507 | { | 470 | { |
508 | .format = &ov772x_fmt_lists[4], | 471 | .code = V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE, |
509 | .dsp3 = 0x0, | 472 | .colorspace = V4L2_COLORSPACE_SRGB, |
510 | .com3 = 0x0, | 473 | .dsp3 = 0x0, |
511 | .com7 = FMT_RGB555 | OFMT_RGB, | 474 | .com3 = 0x0, |
475 | .com7 = FMT_RGB555 | OFMT_RGB, | ||
512 | }, | 476 | }, |
513 | { | 477 | { |
514 | .format = &ov772x_fmt_lists[5], | 478 | .code = V4L2_MBUS_FMT_RGB565_2X8_LE, |
515 | .dsp3 = 0x0, | 479 | .colorspace = V4L2_COLORSPACE_SRGB, |
516 | .com3 = SWAP_RGB, | 480 | .dsp3 = 0x0, |
517 | .com7 = FMT_RGB565 | OFMT_RGB, | 481 | .com3 = SWAP_RGB, |
482 | .com7 = FMT_RGB565 | OFMT_RGB, | ||
518 | }, | 483 | }, |
519 | { | 484 | { |
520 | .format = &ov772x_fmt_lists[6], | 485 | .code = V4L2_MBUS_FMT_RGB565_2X8_BE, |
521 | .dsp3 = 0x0, | 486 | .colorspace = V4L2_COLORSPACE_SRGB, |
522 | .com3 = 0x0, | 487 | .dsp3 = 0x0, |
523 | .com7 = FMT_RGB565 | OFMT_RGB, | 488 | .com3 = 0x0, |
489 | .com7 = FMT_RGB565 | OFMT_RGB, | ||
524 | }, | 490 | }, |
525 | }; | 491 | }; |
526 | 492 | ||
@@ -642,15 +608,15 @@ static int ov772x_s_stream(struct v4l2_subdev *sd, int enable) | |||
642 | return 0; | 608 | return 0; |
643 | } | 609 | } |
644 | 610 | ||
645 | if (!priv->win || !priv->fmt) { | 611 | if (!priv->win || !priv->cfmt) { |
646 | dev_err(&client->dev, "norm or win select error\n"); | 612 | dev_err(&client->dev, "norm or win select error\n"); |
647 | return -EPERM; | 613 | return -EPERM; |
648 | } | 614 | } |
649 | 615 | ||
650 | ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, 0); | 616 | ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, 0); |
651 | 617 | ||
652 | dev_dbg(&client->dev, "format %s, win %s\n", | 618 | dev_dbg(&client->dev, "format %d, win %s\n", |
653 | priv->fmt->format->name, priv->win->name); | 619 | priv->cfmt->code, priv->win->name); |
654 | 620 | ||
655 | return 0; | 621 | return 0; |
656 | } | 622 | } |
@@ -806,8 +772,8 @@ static const struct ov772x_win_size *ov772x_select_win(u32 width, u32 height) | |||
806 | return win; | 772 | return win; |
807 | } | 773 | } |
808 | 774 | ||
809 | static int ov772x_set_params(struct i2c_client *client, | 775 | static int ov772x_set_params(struct i2c_client *client, u32 *width, u32 *height, |
810 | u32 *width, u32 *height, u32 pixfmt) | 776 | enum v4l2_mbus_pixelcode code) |
811 | { | 777 | { |
812 | struct ov772x_priv *priv = to_ov772x(client); | 778 | struct ov772x_priv *priv = to_ov772x(client); |
813 | int ret = -EINVAL; | 779 | int ret = -EINVAL; |
@@ -817,14 +783,14 @@ static int ov772x_set_params(struct i2c_client *client, | |||
817 | /* | 783 | /* |
818 | * select format | 784 | * select format |
819 | */ | 785 | */ |
820 | priv->fmt = NULL; | 786 | priv->cfmt = NULL; |
821 | for (i = 0; i < ARRAY_SIZE(ov772x_cfmts); i++) { | 787 | for (i = 0; i < ARRAY_SIZE(ov772x_cfmts); i++) { |
822 | if (pixfmt == ov772x_cfmts[i].format->fourcc) { | 788 | if (code == ov772x_cfmts[i].code) { |
823 | priv->fmt = ov772x_cfmts + i; | 789 | priv->cfmt = ov772x_cfmts + i; |
824 | break; | 790 | break; |
825 | } | 791 | } |
826 | } | 792 | } |
827 | if (!priv->fmt) | 793 | if (!priv->cfmt) |
828 | goto ov772x_set_fmt_error; | 794 | goto ov772x_set_fmt_error; |
829 | 795 | ||
830 | /* | 796 | /* |
@@ -894,7 +860,7 @@ static int ov772x_set_params(struct i2c_client *client, | |||
894 | /* | 860 | /* |
895 | * set DSP_CTRL3 | 861 | * set DSP_CTRL3 |
896 | */ | 862 | */ |
897 | val = priv->fmt->dsp3; | 863 | val = priv->cfmt->dsp3; |
898 | if (val) { | 864 | if (val) { |
899 | ret = ov772x_mask_set(client, | 865 | ret = ov772x_mask_set(client, |
900 | DSP_CTRL3, UV_MASK, val); | 866 | DSP_CTRL3, UV_MASK, val); |
@@ -905,7 +871,7 @@ static int ov772x_set_params(struct i2c_client *client, | |||
905 | /* | 871 | /* |
906 | * set COM3 | 872 | * set COM3 |
907 | */ | 873 | */ |
908 | val = priv->fmt->com3; | 874 | val = priv->cfmt->com3; |
909 | if (priv->info->flags & OV772X_FLAG_VFLIP) | 875 | if (priv->info->flags & OV772X_FLAG_VFLIP) |
910 | val |= VFLIP_IMG; | 876 | val |= VFLIP_IMG; |
911 | if (priv->info->flags & OV772X_FLAG_HFLIP) | 877 | if (priv->info->flags & OV772X_FLAG_HFLIP) |
@@ -923,9 +889,9 @@ static int ov772x_set_params(struct i2c_client *client, | |||
923 | /* | 889 | /* |
924 | * set COM7 | 890 | * set COM7 |
925 | */ | 891 | */ |
926 | val = priv->win->com7_bit | priv->fmt->com7; | 892 | val = priv->win->com7_bit | priv->cfmt->com7; |
927 | ret = ov772x_mask_set(client, | 893 | ret = ov772x_mask_set(client, |
928 | COM7, (SLCT_MASK | FMT_MASK | OFMT_MASK), | 894 | COM7, SLCT_MASK | FMT_MASK | OFMT_MASK, |
929 | val); | 895 | val); |
930 | if (ret < 0) | 896 | if (ret < 0) |
931 | goto ov772x_set_fmt_error; | 897 | goto ov772x_set_fmt_error; |
@@ -951,7 +917,7 @@ ov772x_set_fmt_error: | |||
951 | 917 | ||
952 | ov772x_reset(client); | 918 | ov772x_reset(client); |
953 | priv->win = NULL; | 919 | priv->win = NULL; |
954 | priv->fmt = NULL; | 920 | priv->cfmt = NULL; |
955 | 921 | ||
956 | return ret; | 922 | return ret; |
957 | } | 923 | } |
@@ -981,54 +947,79 @@ static int ov772x_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) | |||
981 | return 0; | 947 | return 0; |
982 | } | 948 | } |
983 | 949 | ||
984 | static int ov772x_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | 950 | static int ov772x_g_fmt(struct v4l2_subdev *sd, |
951 | struct v4l2_mbus_framefmt *mf) | ||
985 | { | 952 | { |
986 | struct i2c_client *client = sd->priv; | 953 | struct i2c_client *client = sd->priv; |
987 | struct ov772x_priv *priv = to_ov772x(client); | 954 | struct ov772x_priv *priv = to_ov772x(client); |
988 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
989 | 955 | ||
990 | if (!priv->win || !priv->fmt) { | 956 | if (!priv->win || !priv->cfmt) { |
991 | u32 width = VGA_WIDTH, height = VGA_HEIGHT; | 957 | u32 width = VGA_WIDTH, height = VGA_HEIGHT; |
992 | int ret = ov772x_set_params(client, &width, &height, | 958 | int ret = ov772x_set_params(client, &width, &height, |
993 | V4L2_PIX_FMT_YUYV); | 959 | V4L2_MBUS_FMT_YUYV8_2X8_LE); |
994 | if (ret < 0) | 960 | if (ret < 0) |
995 | return ret; | 961 | return ret; |
996 | } | 962 | } |
997 | 963 | ||
998 | f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 964 | mf->width = priv->win->width; |
999 | 965 | mf->height = priv->win->height; | |
1000 | pix->width = priv->win->width; | 966 | mf->code = priv->cfmt->code; |
1001 | pix->height = priv->win->height; | 967 | mf->colorspace = priv->cfmt->colorspace; |
1002 | pix->pixelformat = priv->fmt->format->fourcc; | 968 | mf->field = V4L2_FIELD_NONE; |
1003 | pix->colorspace = priv->fmt->format->colorspace; | ||
1004 | pix->field = V4L2_FIELD_NONE; | ||
1005 | 969 | ||
1006 | return 0; | 970 | return 0; |
1007 | } | 971 | } |
1008 | 972 | ||
1009 | static int ov772x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | 973 | static int ov772x_s_fmt(struct v4l2_subdev *sd, |
974 | struct v4l2_mbus_framefmt *mf) | ||
1010 | { | 975 | { |
1011 | struct i2c_client *client = sd->priv; | 976 | struct i2c_client *client = sd->priv; |
1012 | struct v4l2_pix_format *pix = &f->fmt.pix; | 977 | struct ov772x_priv *priv = to_ov772x(client); |
978 | int ret = ov772x_set_params(client, &mf->width, &mf->height, | ||
979 | mf->code); | ||
980 | |||
981 | if (!ret) | ||
982 | mf->colorspace = priv->cfmt->colorspace; | ||
1013 | 983 | ||
1014 | return ov772x_set_params(client, &pix->width, &pix->height, | 984 | return ret; |
1015 | pix->pixelformat); | ||
1016 | } | 985 | } |
1017 | 986 | ||
1018 | static int ov772x_try_fmt(struct v4l2_subdev *sd, | 987 | static int ov772x_try_fmt(struct v4l2_subdev *sd, |
1019 | struct v4l2_format *f) | 988 | struct v4l2_mbus_framefmt *mf) |
1020 | { | 989 | { |
1021 | struct v4l2_pix_format *pix = &f->fmt.pix; | 990 | struct i2c_client *client = sd->priv; |
991 | struct ov772x_priv *priv = to_ov772x(client); | ||
1022 | const struct ov772x_win_size *win; | 992 | const struct ov772x_win_size *win; |
993 | int i; | ||
1023 | 994 | ||
1024 | /* | 995 | /* |
1025 | * select suitable win | 996 | * select suitable win |
1026 | */ | 997 | */ |
1027 | win = ov772x_select_win(pix->width, pix->height); | 998 | win = ov772x_select_win(mf->width, mf->height); |
999 | |||
1000 | mf->width = win->width; | ||
1001 | mf->height = win->height; | ||
1002 | mf->field = V4L2_FIELD_NONE; | ||
1028 | 1003 | ||
1029 | pix->width = win->width; | 1004 | for (i = 0; i < ARRAY_SIZE(ov772x_cfmts); i++) |
1030 | pix->height = win->height; | 1005 | if (mf->code == ov772x_cfmts[i].code) |
1031 | pix->field = V4L2_FIELD_NONE; | 1006 | break; |
1007 | |||
1008 | if (i == ARRAY_SIZE(ov772x_cfmts)) { | ||
1009 | /* Unsupported format requested. Propose either */ | ||
1010 | if (priv->cfmt) { | ||
1011 | /* the current one or */ | ||
1012 | mf->colorspace = priv->cfmt->colorspace; | ||
1013 | mf->code = priv->cfmt->code; | ||
1014 | } else { | ||
1015 | /* the default one */ | ||
1016 | mf->colorspace = ov772x_cfmts[0].colorspace; | ||
1017 | mf->code = ov772x_cfmts[0].code; | ||
1018 | } | ||
1019 | } else { | ||
1020 | /* Also return the colorspace */ | ||
1021 | mf->colorspace = ov772x_cfmts[i].colorspace; | ||
1022 | } | ||
1032 | 1023 | ||
1033 | return 0; | 1024 | return 0; |
1034 | } | 1025 | } |
@@ -1057,9 +1048,6 @@ static int ov772x_video_probe(struct soc_camera_device *icd, | |||
1057 | return -ENODEV; | 1048 | return -ENODEV; |
1058 | } | 1049 | } |
1059 | 1050 | ||
1060 | icd->formats = ov772x_fmt_lists; | ||
1061 | icd->num_formats = ARRAY_SIZE(ov772x_fmt_lists); | ||
1062 | |||
1063 | /* | 1051 | /* |
1064 | * check and show product ID and manufacturer ID | 1052 | * check and show product ID and manufacturer ID |
1065 | */ | 1053 | */ |
@@ -1109,13 +1097,24 @@ static struct v4l2_subdev_core_ops ov772x_subdev_core_ops = { | |||
1109 | #endif | 1097 | #endif |
1110 | }; | 1098 | }; |
1111 | 1099 | ||
1100 | static int ov772x_enum_fmt(struct v4l2_subdev *sd, int index, | ||
1101 | enum v4l2_mbus_pixelcode *code) | ||
1102 | { | ||
1103 | if ((unsigned int)index >= ARRAY_SIZE(ov772x_cfmts)) | ||
1104 | return -EINVAL; | ||
1105 | |||
1106 | *code = ov772x_cfmts[index].code; | ||
1107 | return 0; | ||
1108 | } | ||
1109 | |||
1112 | static struct v4l2_subdev_video_ops ov772x_subdev_video_ops = { | 1110 | static struct v4l2_subdev_video_ops ov772x_subdev_video_ops = { |
1113 | .s_stream = ov772x_s_stream, | 1111 | .s_stream = ov772x_s_stream, |
1114 | .g_fmt = ov772x_g_fmt, | 1112 | .g_mbus_fmt = ov772x_g_fmt, |
1115 | .s_fmt = ov772x_s_fmt, | 1113 | .s_mbus_fmt = ov772x_s_fmt, |
1116 | .try_fmt = ov772x_try_fmt, | 1114 | .try_mbus_fmt = ov772x_try_fmt, |
1117 | .cropcap = ov772x_cropcap, | 1115 | .cropcap = ov772x_cropcap, |
1118 | .g_crop = ov772x_g_crop, | 1116 | .g_crop = ov772x_g_crop, |
1117 | .enum_mbus_fmt = ov772x_enum_fmt, | ||
1119 | }; | 1118 | }; |
1120 | 1119 | ||
1121 | static struct v4l2_subdev_ops ov772x_subdev_ops = { | 1120 | static struct v4l2_subdev_ops ov772x_subdev_ops = { |
@@ -1143,10 +1142,10 @@ static int ov772x_probe(struct i2c_client *client, | |||
1143 | } | 1142 | } |
1144 | 1143 | ||
1145 | icl = to_soc_camera_link(icd); | 1144 | icl = to_soc_camera_link(icd); |
1146 | if (!icl) | 1145 | if (!icl || !icl->priv) |
1147 | return -EINVAL; | 1146 | return -EINVAL; |
1148 | 1147 | ||
1149 | info = container_of(icl, struct ov772x_camera_info, link); | 1148 | info = icl->priv; |
1150 | 1149 | ||
1151 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { | 1150 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { |
1152 | dev_err(&adapter->dev, | 1151 | dev_err(&adapter->dev, |
diff --git a/drivers/media/video/ov9640.c b/drivers/media/video/ov9640.c index c81ae2192887..47bf60ceb7a2 100644 --- a/drivers/media/video/ov9640.c +++ b/drivers/media/video/ov9640.c | |||
@@ -154,19 +154,10 @@ static const struct ov9640_reg ov9640_regs_rgb[] = { | |||
154 | { OV9640_MTXS, 0x65 }, | 154 | { OV9640_MTXS, 0x65 }, |
155 | }; | 155 | }; |
156 | 156 | ||
157 | /* | 157 | static enum v4l2_mbus_pixelcode ov9640_codes[] = { |
158 | * TODO: this sensor also supports RGB555 and RGB565 formats, but support for | 158 | V4L2_MBUS_FMT_YUYV8_2X8_BE, |
159 | * them has not yet been sufficiently tested and so it is not included with | 159 | V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE, |
160 | * this version of the driver. To test and debug these formats add two entries | 160 | V4L2_MBUS_FMT_RGB565_2X8_LE, |
161 | * to the below array, see ov722x.c for an example. | ||
162 | */ | ||
163 | static const struct soc_camera_data_format ov9640_fmt_lists[] = { | ||
164 | { | ||
165 | .name = "UYVY", | ||
166 | .fourcc = V4L2_PIX_FMT_UYVY, | ||
167 | .depth = 16, | ||
168 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
169 | }, | ||
170 | }; | 161 | }; |
171 | 162 | ||
172 | static const struct v4l2_queryctrl ov9640_controls[] = { | 163 | static const struct v4l2_queryctrl ov9640_controls[] = { |
@@ -434,20 +425,22 @@ static void ov9640_res_roundup(u32 *width, u32 *height) | |||
434 | } | 425 | } |
435 | 426 | ||
436 | /* Prepare necessary register changes depending on color encoding */ | 427 | /* Prepare necessary register changes depending on color encoding */ |
437 | static void ov9640_alter_regs(u32 pixfmt, struct ov9640_reg_alt *alt) | 428 | static void ov9640_alter_regs(enum v4l2_mbus_pixelcode code, |
429 | struct ov9640_reg_alt *alt) | ||
438 | { | 430 | { |
439 | switch (pixfmt) { | 431 | switch (code) { |
440 | case V4L2_PIX_FMT_UYVY: | 432 | default: |
433 | case V4L2_MBUS_FMT_YUYV8_2X8_BE: | ||
441 | alt->com12 = OV9640_COM12_YUV_AVG; | 434 | alt->com12 = OV9640_COM12_YUV_AVG; |
442 | alt->com13 = OV9640_COM13_Y_DELAY_EN | | 435 | alt->com13 = OV9640_COM13_Y_DELAY_EN | |
443 | OV9640_COM13_YUV_DLY(0x01); | 436 | OV9640_COM13_YUV_DLY(0x01); |
444 | break; | 437 | break; |
445 | case V4L2_PIX_FMT_RGB555: | 438 | case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE: |
446 | alt->com7 = OV9640_COM7_RGB; | 439 | alt->com7 = OV9640_COM7_RGB; |
447 | alt->com13 = OV9640_COM13_RGB_AVG; | 440 | alt->com13 = OV9640_COM13_RGB_AVG; |
448 | alt->com15 = OV9640_COM15_RGB_555; | 441 | alt->com15 = OV9640_COM15_RGB_555; |
449 | break; | 442 | break; |
450 | case V4L2_PIX_FMT_RGB565: | 443 | case V4L2_MBUS_FMT_RGB565_2X8_LE: |
451 | alt->com7 = OV9640_COM7_RGB; | 444 | alt->com7 = OV9640_COM7_RGB; |
452 | alt->com13 = OV9640_COM13_RGB_AVG; | 445 | alt->com13 = OV9640_COM13_RGB_AVG; |
453 | alt->com15 = OV9640_COM15_RGB_565; | 446 | alt->com15 = OV9640_COM15_RGB_565; |
@@ -456,8 +449,8 @@ static void ov9640_alter_regs(u32 pixfmt, struct ov9640_reg_alt *alt) | |||
456 | } | 449 | } |
457 | 450 | ||
458 | /* Setup registers according to resolution and color encoding */ | 451 | /* Setup registers according to resolution and color encoding */ |
459 | static int ov9640_write_regs(struct i2c_client *client, | 452 | static int ov9640_write_regs(struct i2c_client *client, u32 width, |
460 | u32 width, u32 pixfmt, struct ov9640_reg_alt *alts) | 453 | enum v4l2_mbus_pixelcode code, struct ov9640_reg_alt *alts) |
461 | { | 454 | { |
462 | const struct ov9640_reg *ov9640_regs, *matrix_regs; | 455 | const struct ov9640_reg *ov9640_regs, *matrix_regs; |
463 | int ov9640_regs_len, matrix_regs_len; | 456 | int ov9640_regs_len, matrix_regs_len; |
@@ -500,7 +493,7 @@ static int ov9640_write_regs(struct i2c_client *client, | |||
500 | } | 493 | } |
501 | 494 | ||
502 | /* select color matrix configuration for given color encoding */ | 495 | /* select color matrix configuration for given color encoding */ |
503 | if (pixfmt == V4L2_PIX_FMT_UYVY) { | 496 | if (code == V4L2_MBUS_FMT_YUYV8_2X8_BE) { |
504 | matrix_regs = ov9640_regs_yuv; | 497 | matrix_regs = ov9640_regs_yuv; |
505 | matrix_regs_len = ARRAY_SIZE(ov9640_regs_yuv); | 498 | matrix_regs_len = ARRAY_SIZE(ov9640_regs_yuv); |
506 | } else { | 499 | } else { |
@@ -562,15 +555,17 @@ static int ov9640_prog_dflt(struct i2c_client *client) | |||
562 | } | 555 | } |
563 | 556 | ||
564 | /* set the format we will capture in */ | 557 | /* set the format we will capture in */ |
565 | static int ov9640_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | 558 | static int ov9640_s_fmt(struct v4l2_subdev *sd, |
559 | struct v4l2_mbus_framefmt *mf) | ||
566 | { | 560 | { |
567 | struct i2c_client *client = sd->priv; | 561 | struct i2c_client *client = sd->priv; |
568 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
569 | struct ov9640_reg_alt alts = {0}; | 562 | struct ov9640_reg_alt alts = {0}; |
563 | enum v4l2_colorspace cspace; | ||
564 | enum v4l2_mbus_pixelcode code = mf->code; | ||
570 | int ret; | 565 | int ret; |
571 | 566 | ||
572 | ov9640_res_roundup(&pix->width, &pix->height); | 567 | ov9640_res_roundup(&mf->width, &mf->height); |
573 | ov9640_alter_regs(pix->pixelformat, &alts); | 568 | ov9640_alter_regs(mf->code, &alts); |
574 | 569 | ||
575 | ov9640_reset(client); | 570 | ov9640_reset(client); |
576 | 571 | ||
@@ -578,19 +573,57 @@ static int ov9640_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | |||
578 | if (ret) | 573 | if (ret) |
579 | return ret; | 574 | return ret; |
580 | 575 | ||
581 | return ov9640_write_regs(client, pix->width, pix->pixelformat, &alts); | 576 | switch (code) { |
577 | case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE: | ||
578 | case V4L2_MBUS_FMT_RGB565_2X8_LE: | ||
579 | cspace = V4L2_COLORSPACE_SRGB; | ||
580 | break; | ||
581 | default: | ||
582 | code = V4L2_MBUS_FMT_YUYV8_2X8_BE; | ||
583 | case V4L2_MBUS_FMT_YUYV8_2X8_BE: | ||
584 | cspace = V4L2_COLORSPACE_JPEG; | ||
585 | } | ||
586 | |||
587 | ret = ov9640_write_regs(client, mf->width, code, &alts); | ||
588 | if (!ret) { | ||
589 | mf->code = code; | ||
590 | mf->colorspace = cspace; | ||
591 | } | ||
592 | |||
593 | return ret; | ||
582 | } | 594 | } |
583 | 595 | ||
584 | static int ov9640_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | 596 | static int ov9640_try_fmt(struct v4l2_subdev *sd, |
597 | struct v4l2_mbus_framefmt *mf) | ||
585 | { | 598 | { |
586 | struct v4l2_pix_format *pix = &f->fmt.pix; | 599 | ov9640_res_roundup(&mf->width, &mf->height); |
587 | 600 | ||
588 | ov9640_res_roundup(&pix->width, &pix->height); | 601 | mf->field = V4L2_FIELD_NONE; |
589 | pix->field = V4L2_FIELD_NONE; | 602 | |
603 | switch (mf->code) { | ||
604 | case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE: | ||
605 | case V4L2_MBUS_FMT_RGB565_2X8_LE: | ||
606 | mf->colorspace = V4L2_COLORSPACE_SRGB; | ||
607 | break; | ||
608 | default: | ||
609 | mf->code = V4L2_MBUS_FMT_YUYV8_2X8_BE; | ||
610 | case V4L2_MBUS_FMT_YUYV8_2X8_BE: | ||
611 | mf->colorspace = V4L2_COLORSPACE_JPEG; | ||
612 | } | ||
590 | 613 | ||
591 | return 0; | 614 | return 0; |
592 | } | 615 | } |
593 | 616 | ||
617 | static int ov9640_enum_fmt(struct v4l2_subdev *sd, int index, | ||
618 | enum v4l2_mbus_pixelcode *code) | ||
619 | { | ||
620 | if ((unsigned int)index >= ARRAY_SIZE(ov9640_codes)) | ||
621 | return -EINVAL; | ||
622 | |||
623 | *code = ov9640_codes[index]; | ||
624 | return 0; | ||
625 | } | ||
626 | |||
594 | static int ov9640_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) | 627 | static int ov9640_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) |
595 | { | 628 | { |
596 | a->c.left = 0; | 629 | a->c.left = 0; |
@@ -637,9 +670,6 @@ static int ov9640_video_probe(struct soc_camera_device *icd, | |||
637 | goto err; | 670 | goto err; |
638 | } | 671 | } |
639 | 672 | ||
640 | icd->formats = ov9640_fmt_lists; | ||
641 | icd->num_formats = ARRAY_SIZE(ov9640_fmt_lists); | ||
642 | |||
643 | /* | 673 | /* |
644 | * check and show product ID and manufacturer ID | 674 | * check and show product ID and manufacturer ID |
645 | */ | 675 | */ |
@@ -702,11 +732,12 @@ static struct v4l2_subdev_core_ops ov9640_core_ops = { | |||
702 | }; | 732 | }; |
703 | 733 | ||
704 | static struct v4l2_subdev_video_ops ov9640_video_ops = { | 734 | static struct v4l2_subdev_video_ops ov9640_video_ops = { |
705 | .s_stream = ov9640_s_stream, | 735 | .s_stream = ov9640_s_stream, |
706 | .s_fmt = ov9640_s_fmt, | 736 | .s_mbus_fmt = ov9640_s_fmt, |
707 | .try_fmt = ov9640_try_fmt, | 737 | .try_mbus_fmt = ov9640_try_fmt, |
708 | .cropcap = ov9640_cropcap, | 738 | .enum_mbus_fmt = ov9640_enum_fmt, |
709 | .g_crop = ov9640_g_crop, | 739 | .cropcap = ov9640_cropcap, |
740 | .g_crop = ov9640_g_crop, | ||
710 | 741 | ||
711 | }; | 742 | }; |
712 | 743 | ||
diff --git a/drivers/media/video/pms.c b/drivers/media/video/pms.c index 73ec970ca5ca..11a2c26399b5 100644 --- a/drivers/media/video/pms.c +++ b/drivers/media/video/pms.c | |||
@@ -31,7 +31,7 @@ | |||
31 | #include <linux/init.h> | 31 | #include <linux/init.h> |
32 | #include <linux/version.h> | 32 | #include <linux/version.h> |
33 | #include <linux/mutex.h> | 33 | #include <linux/mutex.h> |
34 | #include <asm/uaccess.h> | 34 | #include <linux/uaccess.h> |
35 | #include <asm/io.h> | 35 | #include <asm/io.h> |
36 | 36 | ||
37 | #include <linux/videodev2.h> | 37 | #include <linux/videodev2.h> |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index 6aa48e0ae731..cc8ddb2d2382 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c | |||
@@ -151,17 +151,6 @@ static struct v4l2_format pvr_format [] = { | |||
151 | }; | 151 | }; |
152 | 152 | ||
153 | 153 | ||
154 | static const char *get_v4l_name(int v4l_type) | ||
155 | { | ||
156 | switch (v4l_type) { | ||
157 | case VFL_TYPE_GRABBER: return "video"; | ||
158 | case VFL_TYPE_RADIO: return "radio"; | ||
159 | case VFL_TYPE_VBI: return "vbi"; | ||
160 | default: return "?"; | ||
161 | } | ||
162 | } | ||
163 | |||
164 | |||
165 | /* | 154 | /* |
166 | * pvr_ioctl() | 155 | * pvr_ioctl() |
167 | * | 156 | * |
@@ -891,10 +880,8 @@ static long pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) | |||
891 | 880 | ||
892 | static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip) | 881 | static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip) |
893 | { | 882 | { |
894 | int num = dip->devbase.num; | ||
895 | struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw; | 883 | struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw; |
896 | enum pvr2_config cfg = dip->config; | 884 | enum pvr2_config cfg = dip->config; |
897 | int v4l_type = dip->v4l_type; | ||
898 | 885 | ||
899 | pvr2_hdw_v4l_store_minor_number(hdw,dip->minor_type,-1); | 886 | pvr2_hdw_v4l_store_minor_number(hdw,dip->minor_type,-1); |
900 | 887 | ||
@@ -906,8 +893,8 @@ static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip) | |||
906 | are gone. */ | 893 | are gone. */ |
907 | video_unregister_device(&dip->devbase); | 894 | video_unregister_device(&dip->devbase); |
908 | 895 | ||
909 | printk(KERN_INFO "pvrusb2: unregistered device %s%u [%s]\n", | 896 | printk(KERN_INFO "pvrusb2: unregistered device %s [%s]\n", |
910 | get_v4l_name(v4l_type), num, | 897 | video_device_node_name(&dip->devbase), |
911 | pvr2_config_get_name(cfg)); | 898 | pvr2_config_get_name(cfg)); |
912 | 899 | ||
913 | } | 900 | } |
@@ -1317,8 +1304,8 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, | |||
1317 | ": Failed to register pvrusb2 v4l device\n"); | 1304 | ": Failed to register pvrusb2 v4l device\n"); |
1318 | } | 1305 | } |
1319 | 1306 | ||
1320 | printk(KERN_INFO "pvrusb2: registered device %s%u [%s]\n", | 1307 | printk(KERN_INFO "pvrusb2: registered device %s [%s]\n", |
1321 | get_v4l_name(dip->v4l_type), dip->devbase.num, | 1308 | video_device_node_name(&dip->devbase), |
1322 | pvr2_config_get_name(dip->config)); | 1309 | pvr2_config_get_name(dip->config)); |
1323 | 1310 | ||
1324 | pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw, | 1311 | pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw, |
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index 89b620f6db7b..aea7e224cef6 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c | |||
@@ -169,7 +169,6 @@ static struct video_device pwc_template = { | |||
169 | .name = "Philips Webcam", /* Filled in later */ | 169 | .name = "Philips Webcam", /* Filled in later */ |
170 | .release = video_device_release, | 170 | .release = video_device_release, |
171 | .fops = &pwc_fops, | 171 | .fops = &pwc_fops, |
172 | .minor = -1, | ||
173 | }; | 172 | }; |
174 | 173 | ||
175 | /***************************************************************************/ | 174 | /***************************************************************************/ |
@@ -1807,7 +1806,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id | |||
1807 | goto err_video_release; | 1806 | goto err_video_release; |
1808 | } | 1807 | } |
1809 | 1808 | ||
1810 | PWC_INFO("Registered as /dev/video%d.\n", pdev->vdev->num); | 1809 | PWC_INFO("Registered as %s.\n", video_device_node_name(pdev->vdev)); |
1811 | 1810 | ||
1812 | /* occupy slot */ | 1811 | /* occupy slot */ |
1813 | if (hint < MAX_DEV_HINTS) | 1812 | if (hint < MAX_DEV_HINTS) |
@@ -1948,7 +1947,9 @@ MODULE_PARM_DESC(size, "Initial image size. One of sqcif, qsif, qcif, sif, cif, | |||
1948 | MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 5-30"); | 1947 | MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 5-30"); |
1949 | MODULE_PARM_DESC(fbufs, "Number of internal frame buffers to reserve"); | 1948 | MODULE_PARM_DESC(fbufs, "Number of internal frame buffers to reserve"); |
1950 | MODULE_PARM_DESC(mbufs, "Number of external (mmap()ed) image buffers"); | 1949 | MODULE_PARM_DESC(mbufs, "Number of external (mmap()ed) image buffers"); |
1950 | #ifdef CONFIG_USB_PWC_DEBUG | ||
1951 | MODULE_PARM_DESC(trace, "For debugging purposes"); | 1951 | MODULE_PARM_DESC(trace, "For debugging purposes"); |
1952 | #endif | ||
1952 | MODULE_PARM_DESC(power_save, "Turn power save feature in camera on or off"); | 1953 | MODULE_PARM_DESC(power_save, "Turn power save feature in camera on or off"); |
1953 | MODULE_PARM_DESC(compression, "Preferred compression quality. Range 0 (uncompressed) to 3 (high compression)"); | 1954 | MODULE_PARM_DESC(compression, "Preferred compression quality. Range 0 (uncompressed) to 3 (high compression)"); |
1954 | MODULE_PARM_DESC(leds, "LED on,off time in milliseconds"); | 1955 | MODULE_PARM_DESC(leds, "LED on,off time in milliseconds"); |
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index 51b683c63b70..294f860ce2b0 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <media/v4l2-dev.h> | 32 | #include <media/v4l2-dev.h> |
33 | #include <media/videobuf-dma-sg.h> | 33 | #include <media/videobuf-dma-sg.h> |
34 | #include <media/soc_camera.h> | 34 | #include <media/soc_camera.h> |
35 | #include <media/soc_mediabus.h> | ||
35 | 36 | ||
36 | #include <linux/videodev2.h> | 37 | #include <linux/videodev2.h> |
37 | 38 | ||
@@ -183,23 +184,21 @@ struct pxa_cam_dma { | |||
183 | /* buffer for one video frame */ | 184 | /* buffer for one video frame */ |
184 | struct pxa_buffer { | 185 | struct pxa_buffer { |
185 | /* common v4l buffer stuff -- must be first */ | 186 | /* common v4l buffer stuff -- must be first */ |
186 | struct videobuf_buffer vb; | 187 | struct videobuf_buffer vb; |
187 | 188 | enum v4l2_mbus_pixelcode code; | |
188 | const struct soc_camera_data_format *fmt; | ||
189 | |||
190 | /* our descriptor lists for Y, U and V channels */ | 189 | /* our descriptor lists for Y, U and V channels */ |
191 | struct pxa_cam_dma dmas[3]; | 190 | struct pxa_cam_dma dmas[3]; |
192 | 191 | int inwork; | |
193 | int inwork; | 192 | enum pxa_camera_active_dma active_dma; |
194 | |||
195 | enum pxa_camera_active_dma active_dma; | ||
196 | }; | 193 | }; |
197 | 194 | ||
198 | struct pxa_camera_dev { | 195 | struct pxa_camera_dev { |
199 | struct soc_camera_host soc_host; | 196 | struct soc_camera_host soc_host; |
200 | /* PXA27x is only supposed to handle one camera on its Quick Capture | 197 | /* |
198 | * PXA27x is only supposed to handle one camera on its Quick Capture | ||
201 | * interface. If anyone ever builds hardware to enable more than | 199 | * interface. If anyone ever builds hardware to enable more than |
202 | * one camera, they will have to modify this driver too */ | 200 | * one camera, they will have to modify this driver too |
201 | */ | ||
203 | struct soc_camera_device *icd; | 202 | struct soc_camera_device *icd; |
204 | struct clk *clk; | 203 | struct clk *clk; |
205 | 204 | ||
@@ -241,11 +240,15 @@ static int pxa_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, | |||
241 | unsigned int *size) | 240 | unsigned int *size) |
242 | { | 241 | { |
243 | struct soc_camera_device *icd = vq->priv_data; | 242 | struct soc_camera_device *icd = vq->priv_data; |
243 | int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, | ||
244 | icd->current_fmt->host_fmt); | ||
245 | |||
246 | if (bytes_per_line < 0) | ||
247 | return bytes_per_line; | ||
244 | 248 | ||
245 | dev_dbg(icd->dev.parent, "count=%d, size=%d\n", *count, *size); | 249 | dev_dbg(icd->dev.parent, "count=%d, size=%d\n", *count, *size); |
246 | 250 | ||
247 | *size = roundup(icd->user_width * icd->user_height * | 251 | *size = bytes_per_line * icd->user_height; |
248 | ((icd->current_fmt->depth + 7) >> 3), 8); | ||
249 | 252 | ||
250 | if (0 == *count) | 253 | if (0 == *count) |
251 | *count = 32; | 254 | *count = 32; |
@@ -267,8 +270,10 @@ static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf) | |||
267 | dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, | 270 | dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, |
268 | &buf->vb, buf->vb.baddr, buf->vb.bsize); | 271 | &buf->vb, buf->vb.baddr, buf->vb.bsize); |
269 | 272 | ||
270 | /* This waits until this buffer is out of danger, i.e., until it is no | 273 | /* |
271 | * longer in STATE_QUEUED or STATE_ACTIVE */ | 274 | * This waits until this buffer is out of danger, i.e., until it is no |
275 | * longer in STATE_QUEUED or STATE_ACTIVE | ||
276 | */ | ||
272 | videobuf_waiton(&buf->vb, 0, 0); | 277 | videobuf_waiton(&buf->vb, 0, 0); |
273 | videobuf_dma_unmap(vq, dma); | 278 | videobuf_dma_unmap(vq, dma); |
274 | videobuf_dma_free(dma); | 279 | videobuf_dma_free(dma); |
@@ -429,6 +434,11 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, | |||
429 | struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb); | 434 | struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb); |
430 | int ret; | 435 | int ret; |
431 | int size_y, size_u = 0, size_v = 0; | 436 | int size_y, size_u = 0, size_v = 0; |
437 | int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, | ||
438 | icd->current_fmt->host_fmt); | ||
439 | |||
440 | if (bytes_per_line < 0) | ||
441 | return bytes_per_line; | ||
432 | 442 | ||
433 | dev_dbg(dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, | 443 | dev_dbg(dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, |
434 | vb, vb->baddr, vb->bsize); | 444 | vb, vb->baddr, vb->bsize); |
@@ -437,29 +447,33 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, | |||
437 | WARN_ON(!list_empty(&vb->queue)); | 447 | WARN_ON(!list_empty(&vb->queue)); |
438 | 448 | ||
439 | #ifdef DEBUG | 449 | #ifdef DEBUG |
440 | /* This can be useful if you want to see if we actually fill | 450 | /* |
441 | * the buffer with something */ | 451 | * This can be useful if you want to see if we actually fill |
452 | * the buffer with something | ||
453 | */ | ||
442 | memset((void *)vb->baddr, 0xaa, vb->bsize); | 454 | memset((void *)vb->baddr, 0xaa, vb->bsize); |
443 | #endif | 455 | #endif |
444 | 456 | ||
445 | BUG_ON(NULL == icd->current_fmt); | 457 | BUG_ON(NULL == icd->current_fmt); |
446 | 458 | ||
447 | /* I think, in buf_prepare you only have to protect global data, | 459 | /* |
448 | * the actual buffer is yours */ | 460 | * I think, in buf_prepare you only have to protect global data, |
461 | * the actual buffer is yours | ||
462 | */ | ||
449 | buf->inwork = 1; | 463 | buf->inwork = 1; |
450 | 464 | ||
451 | if (buf->fmt != icd->current_fmt || | 465 | if (buf->code != icd->current_fmt->code || |
452 | vb->width != icd->user_width || | 466 | vb->width != icd->user_width || |
453 | vb->height != icd->user_height || | 467 | vb->height != icd->user_height || |
454 | vb->field != field) { | 468 | vb->field != field) { |
455 | buf->fmt = icd->current_fmt; | 469 | buf->code = icd->current_fmt->code; |
456 | vb->width = icd->user_width; | 470 | vb->width = icd->user_width; |
457 | vb->height = icd->user_height; | 471 | vb->height = icd->user_height; |
458 | vb->field = field; | 472 | vb->field = field; |
459 | vb->state = VIDEOBUF_NEEDS_INIT; | 473 | vb->state = VIDEOBUF_NEEDS_INIT; |
460 | } | 474 | } |
461 | 475 | ||
462 | vb->size = vb->width * vb->height * ((buf->fmt->depth + 7) >> 3); | 476 | vb->size = bytes_per_line * vb->height; |
463 | if (0 != vb->baddr && vb->bsize < vb->size) { | 477 | if (0 != vb->baddr && vb->bsize < vb->size) { |
464 | ret = -EINVAL; | 478 | ret = -EINVAL; |
465 | goto out; | 479 | goto out; |
@@ -834,8 +848,10 @@ static void pxa_camera_init_videobuf(struct videobuf_queue *q, | |||
834 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | 848 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); |
835 | struct pxa_camera_dev *pcdev = ici->priv; | 849 | struct pxa_camera_dev *pcdev = ici->priv; |
836 | 850 | ||
837 | /* We must pass NULL as dev pointer, then all pci_* dma operations | 851 | /* |
838 | * transform to normal dma_* ones. */ | 852 | * We must pass NULL as dev pointer, then all pci_* dma operations |
853 | * transform to normal dma_* ones. | ||
854 | */ | ||
839 | videobuf_queue_sg_init(q, &pxa_videobuf_ops, NULL, &pcdev->lock, | 855 | videobuf_queue_sg_init(q, &pxa_videobuf_ops, NULL, &pcdev->lock, |
840 | V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, | 856 | V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, |
841 | sizeof(struct pxa_buffer), icd); | 857 | sizeof(struct pxa_buffer), icd); |
@@ -1051,11 +1067,18 @@ static void pxa_camera_setup_cicr(struct soc_camera_device *icd, | |||
1051 | { | 1067 | { |
1052 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | 1068 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); |
1053 | struct pxa_camera_dev *pcdev = ici->priv; | 1069 | struct pxa_camera_dev *pcdev = ici->priv; |
1070 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | ||
1054 | unsigned long dw, bpp; | 1071 | unsigned long dw, bpp; |
1055 | u32 cicr0, cicr1, cicr2, cicr3, cicr4 = 0; | 1072 | u32 cicr0, cicr1, cicr2, cicr3, cicr4 = 0, y_skip_top; |
1073 | int ret = v4l2_subdev_call(sd, sensor, g_skip_top_lines, &y_skip_top); | ||
1074 | |||
1075 | if (ret < 0) | ||
1076 | y_skip_top = 0; | ||
1056 | 1077 | ||
1057 | /* Datawidth is now guaranteed to be equal to one of the three values. | 1078 | /* |
1058 | * We fix bit-per-pixel equal to data-width... */ | 1079 | * Datawidth is now guaranteed to be equal to one of the three values. |
1080 | * We fix bit-per-pixel equal to data-width... | ||
1081 | */ | ||
1059 | switch (flags & SOCAM_DATAWIDTH_MASK) { | 1082 | switch (flags & SOCAM_DATAWIDTH_MASK) { |
1060 | case SOCAM_DATAWIDTH_10: | 1083 | case SOCAM_DATAWIDTH_10: |
1061 | dw = 4; | 1084 | dw = 4; |
@@ -1066,8 +1089,10 @@ static void pxa_camera_setup_cicr(struct soc_camera_device *icd, | |||
1066 | bpp = 0x20; | 1089 | bpp = 0x20; |
1067 | break; | 1090 | break; |
1068 | default: | 1091 | default: |
1069 | /* Actually it can only be 8 now, | 1092 | /* |
1070 | * default is just to silence compiler warnings */ | 1093 | * Actually it can only be 8 now, |
1094 | * default is just to silence compiler warnings | ||
1095 | */ | ||
1071 | case SOCAM_DATAWIDTH_8: | 1096 | case SOCAM_DATAWIDTH_8: |
1072 | dw = 2; | 1097 | dw = 2; |
1073 | bpp = 0; | 1098 | bpp = 0; |
@@ -1118,7 +1143,7 @@ static void pxa_camera_setup_cicr(struct soc_camera_device *icd, | |||
1118 | 1143 | ||
1119 | cicr2 = 0; | 1144 | cicr2 = 0; |
1120 | cicr3 = CICR3_LPF_VAL(icd->user_height - 1) | | 1145 | cicr3 = CICR3_LPF_VAL(icd->user_height - 1) | |
1121 | CICR3_BFW_VAL(min((unsigned short)255, icd->y_skip_top)); | 1146 | CICR3_BFW_VAL(min((u32)255, y_skip_top)); |
1122 | cicr4 |= pcdev->mclk_divisor; | 1147 | cicr4 |= pcdev->mclk_divisor; |
1123 | 1148 | ||
1124 | __raw_writel(cicr1, pcdev->base + CICR1); | 1149 | __raw_writel(cicr1, pcdev->base + CICR1); |
@@ -1138,9 +1163,15 @@ static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) | |||
1138 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | 1163 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); |
1139 | struct pxa_camera_dev *pcdev = ici->priv; | 1164 | struct pxa_camera_dev *pcdev = ici->priv; |
1140 | unsigned long bus_flags, camera_flags, common_flags; | 1165 | unsigned long bus_flags, camera_flags, common_flags; |
1141 | int ret = test_platform_param(pcdev, icd->buswidth, &bus_flags); | 1166 | const struct soc_mbus_pixelfmt *fmt; |
1167 | int ret; | ||
1142 | struct pxa_cam *cam = icd->host_priv; | 1168 | struct pxa_cam *cam = icd->host_priv; |
1143 | 1169 | ||
1170 | fmt = soc_mbus_get_fmtdesc(icd->current_fmt->code); | ||
1171 | if (!fmt) | ||
1172 | return -EINVAL; | ||
1173 | |||
1174 | ret = test_platform_param(pcdev, fmt->bits_per_sample, &bus_flags); | ||
1144 | if (ret < 0) | 1175 | if (ret < 0) |
1145 | return ret; | 1176 | return ret; |
1146 | 1177 | ||
@@ -1204,59 +1235,49 @@ static int pxa_camera_try_bus_param(struct soc_camera_device *icd, | |||
1204 | return soc_camera_bus_param_compatible(camera_flags, bus_flags) ? 0 : -EINVAL; | 1235 | return soc_camera_bus_param_compatible(camera_flags, bus_flags) ? 0 : -EINVAL; |
1205 | } | 1236 | } |
1206 | 1237 | ||
1207 | static const struct soc_camera_data_format pxa_camera_formats[] = { | 1238 | static const struct soc_mbus_pixelfmt pxa_camera_formats[] = { |
1208 | { | 1239 | { |
1209 | .name = "Planar YUV422 16 bit", | 1240 | .fourcc = V4L2_PIX_FMT_YUV422P, |
1210 | .depth = 16, | 1241 | .name = "Planar YUV422 16 bit", |
1211 | .fourcc = V4L2_PIX_FMT_YUV422P, | 1242 | .bits_per_sample = 8, |
1212 | .colorspace = V4L2_COLORSPACE_JPEG, | 1243 | .packing = SOC_MBUS_PACKING_2X8_PADHI, |
1244 | .order = SOC_MBUS_ORDER_LE, | ||
1213 | }, | 1245 | }, |
1214 | }; | 1246 | }; |
1215 | 1247 | ||
1216 | static bool buswidth_supported(struct soc_camera_device *icd, int depth) | 1248 | /* This will be corrected as we get more formats */ |
1249 | static bool pxa_camera_packing_supported(const struct soc_mbus_pixelfmt *fmt) | ||
1217 | { | 1250 | { |
1218 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | 1251 | return fmt->packing == SOC_MBUS_PACKING_NONE || |
1219 | struct pxa_camera_dev *pcdev = ici->priv; | 1252 | (fmt->bits_per_sample == 8 && |
1220 | 1253 | fmt->packing == SOC_MBUS_PACKING_2X8_PADHI) || | |
1221 | switch (depth) { | 1254 | (fmt->bits_per_sample > 8 && |
1222 | case 8: | 1255 | fmt->packing == SOC_MBUS_PACKING_EXTEND16); |
1223 | return !!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_8); | ||
1224 | case 9: | ||
1225 | return !!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_9); | ||
1226 | case 10: | ||
1227 | return !!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_10); | ||
1228 | } | ||
1229 | return false; | ||
1230 | } | ||
1231 | |||
1232 | static int required_buswidth(const struct soc_camera_data_format *fmt) | ||
1233 | { | ||
1234 | switch (fmt->fourcc) { | ||
1235 | case V4L2_PIX_FMT_UYVY: | ||
1236 | case V4L2_PIX_FMT_VYUY: | ||
1237 | case V4L2_PIX_FMT_YUYV: | ||
1238 | case V4L2_PIX_FMT_YVYU: | ||
1239 | case V4L2_PIX_FMT_RGB565: | ||
1240 | case V4L2_PIX_FMT_RGB555: | ||
1241 | return 8; | ||
1242 | default: | ||
1243 | return fmt->depth; | ||
1244 | } | ||
1245 | } | 1256 | } |
1246 | 1257 | ||
1247 | static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx, | 1258 | static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx, |
1248 | struct soc_camera_format_xlate *xlate) | 1259 | struct soc_camera_format_xlate *xlate) |
1249 | { | 1260 | { |
1261 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | ||
1250 | struct device *dev = icd->dev.parent; | 1262 | struct device *dev = icd->dev.parent; |
1251 | int formats = 0, buswidth, ret; | 1263 | int formats = 0, ret; |
1252 | struct pxa_cam *cam; | 1264 | struct pxa_cam *cam; |
1265 | enum v4l2_mbus_pixelcode code; | ||
1266 | const struct soc_mbus_pixelfmt *fmt; | ||
1253 | 1267 | ||
1254 | buswidth = required_buswidth(icd->formats + idx); | 1268 | ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code); |
1269 | if (ret < 0) | ||
1270 | /* No more formats */ | ||
1271 | return 0; | ||
1255 | 1272 | ||
1256 | if (!buswidth_supported(icd, buswidth)) | 1273 | fmt = soc_mbus_get_fmtdesc(code); |
1274 | if (!fmt) { | ||
1275 | dev_err(dev, "Invalid format code #%d: %d\n", idx, code); | ||
1257 | return 0; | 1276 | return 0; |
1277 | } | ||
1258 | 1278 | ||
1259 | ret = pxa_camera_try_bus_param(icd, buswidth); | 1279 | /* This also checks support for the requested bits-per-sample */ |
1280 | ret = pxa_camera_try_bus_param(icd, fmt->bits_per_sample); | ||
1260 | if (ret < 0) | 1281 | if (ret < 0) |
1261 | return 0; | 1282 | return 0; |
1262 | 1283 | ||
@@ -1270,45 +1291,40 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx, | |||
1270 | cam = icd->host_priv; | 1291 | cam = icd->host_priv; |
1271 | } | 1292 | } |
1272 | 1293 | ||
1273 | switch (icd->formats[idx].fourcc) { | 1294 | switch (code) { |
1274 | case V4L2_PIX_FMT_UYVY: | 1295 | case V4L2_MBUS_FMT_YUYV8_2X8_BE: |
1275 | formats++; | 1296 | formats++; |
1276 | if (xlate) { | 1297 | if (xlate) { |
1277 | xlate->host_fmt = &pxa_camera_formats[0]; | 1298 | xlate->host_fmt = &pxa_camera_formats[0]; |
1278 | xlate->cam_fmt = icd->formats + idx; | 1299 | xlate->code = code; |
1279 | xlate->buswidth = buswidth; | ||
1280 | xlate++; | 1300 | xlate++; |
1281 | dev_dbg(dev, "Providing format %s using %s\n", | 1301 | dev_dbg(dev, "Providing format %s using code %d\n", |
1282 | pxa_camera_formats[0].name, | 1302 | pxa_camera_formats[0].name, code); |
1283 | icd->formats[idx].name); | ||
1284 | } | 1303 | } |
1285 | case V4L2_PIX_FMT_VYUY: | 1304 | case V4L2_MBUS_FMT_YVYU8_2X8_BE: |
1286 | case V4L2_PIX_FMT_YUYV: | 1305 | case V4L2_MBUS_FMT_YUYV8_2X8_LE: |
1287 | case V4L2_PIX_FMT_YVYU: | 1306 | case V4L2_MBUS_FMT_YVYU8_2X8_LE: |
1288 | case V4L2_PIX_FMT_RGB565: | 1307 | case V4L2_MBUS_FMT_RGB565_2X8_LE: |
1289 | case V4L2_PIX_FMT_RGB555: | 1308 | case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE: |
1290 | formats++; | 1309 | if (xlate) |
1291 | if (xlate) { | ||
1292 | xlate->host_fmt = icd->formats + idx; | ||
1293 | xlate->cam_fmt = icd->formats + idx; | ||
1294 | xlate->buswidth = buswidth; | ||
1295 | xlate++; | ||
1296 | dev_dbg(dev, "Providing format %s packed\n", | 1310 | dev_dbg(dev, "Providing format %s packed\n", |
1297 | icd->formats[idx].name); | 1311 | fmt->name); |
1298 | } | ||
1299 | break; | 1312 | break; |
1300 | default: | 1313 | default: |
1301 | /* Generic pass-through */ | 1314 | if (!pxa_camera_packing_supported(fmt)) |
1302 | formats++; | 1315 | return 0; |
1303 | if (xlate) { | 1316 | if (xlate) |
1304 | xlate->host_fmt = icd->formats + idx; | ||
1305 | xlate->cam_fmt = icd->formats + idx; | ||
1306 | xlate->buswidth = icd->formats[idx].depth; | ||
1307 | xlate++; | ||
1308 | dev_dbg(dev, | 1317 | dev_dbg(dev, |
1309 | "Providing format %s in pass-through mode\n", | 1318 | "Providing format %s in pass-through mode\n", |
1310 | icd->formats[idx].name); | 1319 | fmt->name); |
1311 | } | 1320 | } |
1321 | |||
1322 | /* Generic pass-through */ | ||
1323 | formats++; | ||
1324 | if (xlate) { | ||
1325 | xlate->host_fmt = fmt; | ||
1326 | xlate->code = code; | ||
1327 | xlate++; | ||
1312 | } | 1328 | } |
1313 | 1329 | ||
1314 | return formats; | 1330 | return formats; |
@@ -1320,11 +1336,11 @@ static void pxa_camera_put_formats(struct soc_camera_device *icd) | |||
1320 | icd->host_priv = NULL; | 1336 | icd->host_priv = NULL; |
1321 | } | 1337 | } |
1322 | 1338 | ||
1323 | static int pxa_camera_check_frame(struct v4l2_pix_format *pix) | 1339 | static int pxa_camera_check_frame(u32 width, u32 height) |
1324 | { | 1340 | { |
1325 | /* limit to pxa hardware capabilities */ | 1341 | /* limit to pxa hardware capabilities */ |
1326 | return pix->height < 32 || pix->height > 2048 || pix->width < 48 || | 1342 | return height < 32 || height > 2048 || width < 48 || width > 2048 || |
1327 | pix->width > 2048 || (pix->width & 0x01); | 1343 | (width & 0x01); |
1328 | } | 1344 | } |
1329 | 1345 | ||
1330 | static int pxa_camera_set_crop(struct soc_camera_device *icd, | 1346 | static int pxa_camera_set_crop(struct soc_camera_device *icd, |
@@ -1339,9 +1355,9 @@ static int pxa_camera_set_crop(struct soc_camera_device *icd, | |||
1339 | .master_clock = pcdev->mclk, | 1355 | .master_clock = pcdev->mclk, |
1340 | .pixel_clock_max = pcdev->ciclk / 4, | 1356 | .pixel_clock_max = pcdev->ciclk / 4, |
1341 | }; | 1357 | }; |
1342 | struct v4l2_format f; | 1358 | struct v4l2_mbus_framefmt mf; |
1343 | struct v4l2_pix_format *pix = &f.fmt.pix, pix_tmp; | ||
1344 | struct pxa_cam *cam = icd->host_priv; | 1359 | struct pxa_cam *cam = icd->host_priv; |
1360 | u32 fourcc = icd->current_fmt->host_fmt->fourcc; | ||
1345 | int ret; | 1361 | int ret; |
1346 | 1362 | ||
1347 | /* If PCLK is used to latch data from the sensor, check sense */ | 1363 | /* If PCLK is used to latch data from the sensor, check sense */ |
@@ -1358,27 +1374,23 @@ static int pxa_camera_set_crop(struct soc_camera_device *icd, | |||
1358 | return ret; | 1374 | return ret; |
1359 | } | 1375 | } |
1360 | 1376 | ||
1361 | f.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 1377 | ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf); |
1362 | |||
1363 | ret = v4l2_subdev_call(sd, video, g_fmt, &f); | ||
1364 | if (ret < 0) | 1378 | if (ret < 0) |
1365 | return ret; | 1379 | return ret; |
1366 | 1380 | ||
1367 | pix_tmp = *pix; | 1381 | if (pxa_camera_check_frame(mf.width, mf.height)) { |
1368 | if (pxa_camera_check_frame(pix)) { | ||
1369 | /* | 1382 | /* |
1370 | * Camera cropping produced a frame beyond our capabilities. | 1383 | * Camera cropping produced a frame beyond our capabilities. |
1371 | * FIXME: just extract a subframe, that we can process. | 1384 | * FIXME: just extract a subframe, that we can process. |
1372 | */ | 1385 | */ |
1373 | v4l_bound_align_image(&pix->width, 48, 2048, 1, | 1386 | v4l_bound_align_image(&mf.width, 48, 2048, 1, |
1374 | &pix->height, 32, 2048, 0, | 1387 | &mf.height, 32, 2048, 0, |
1375 | icd->current_fmt->fourcc == V4L2_PIX_FMT_YUV422P ? | 1388 | fourcc == V4L2_PIX_FMT_YUV422P ? 4 : 0); |
1376 | 4 : 0); | 1389 | ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf); |
1377 | ret = v4l2_subdev_call(sd, video, s_fmt, &f); | ||
1378 | if (ret < 0) | 1390 | if (ret < 0) |
1379 | return ret; | 1391 | return ret; |
1380 | 1392 | ||
1381 | if (pxa_camera_check_frame(pix)) { | 1393 | if (pxa_camera_check_frame(mf.width, mf.height)) { |
1382 | dev_warn(icd->dev.parent, | 1394 | dev_warn(icd->dev.parent, |
1383 | "Inconsistent state. Use S_FMT to repair\n"); | 1395 | "Inconsistent state. Use S_FMT to repair\n"); |
1384 | return -EINVAL; | 1396 | return -EINVAL; |
@@ -1395,10 +1407,10 @@ static int pxa_camera_set_crop(struct soc_camera_device *icd, | |||
1395 | recalculate_fifo_timeout(pcdev, sense.pixel_clock); | 1407 | recalculate_fifo_timeout(pcdev, sense.pixel_clock); |
1396 | } | 1408 | } |
1397 | 1409 | ||
1398 | icd->user_width = pix->width; | 1410 | icd->user_width = mf.width; |
1399 | icd->user_height = pix->height; | 1411 | icd->user_height = mf.height; |
1400 | 1412 | ||
1401 | pxa_camera_setup_cicr(icd, cam->flags, icd->current_fmt->fourcc); | 1413 | pxa_camera_setup_cicr(icd, cam->flags, fourcc); |
1402 | 1414 | ||
1403 | return ret; | 1415 | return ret; |
1404 | } | 1416 | } |
@@ -1410,14 +1422,13 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, | |||
1410 | struct pxa_camera_dev *pcdev = ici->priv; | 1422 | struct pxa_camera_dev *pcdev = ici->priv; |
1411 | struct device *dev = icd->dev.parent; | 1423 | struct device *dev = icd->dev.parent; |
1412 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | 1424 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
1413 | const struct soc_camera_data_format *cam_fmt = NULL; | ||
1414 | const struct soc_camera_format_xlate *xlate = NULL; | 1425 | const struct soc_camera_format_xlate *xlate = NULL; |
1415 | struct soc_camera_sense sense = { | 1426 | struct soc_camera_sense sense = { |
1416 | .master_clock = pcdev->mclk, | 1427 | .master_clock = pcdev->mclk, |
1417 | .pixel_clock_max = pcdev->ciclk / 4, | 1428 | .pixel_clock_max = pcdev->ciclk / 4, |
1418 | }; | 1429 | }; |
1419 | struct v4l2_pix_format *pix = &f->fmt.pix; | 1430 | struct v4l2_pix_format *pix = &f->fmt.pix; |
1420 | struct v4l2_format cam_f = *f; | 1431 | struct v4l2_mbus_framefmt mf; |
1421 | int ret; | 1432 | int ret; |
1422 | 1433 | ||
1423 | xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); | 1434 | xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); |
@@ -1426,26 +1437,31 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, | |||
1426 | return -EINVAL; | 1437 | return -EINVAL; |
1427 | } | 1438 | } |
1428 | 1439 | ||
1429 | cam_fmt = xlate->cam_fmt; | ||
1430 | |||
1431 | /* If PCLK is used to latch data from the sensor, check sense */ | 1440 | /* If PCLK is used to latch data from the sensor, check sense */ |
1432 | if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN) | 1441 | if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN) |
1442 | /* The caller holds a mutex. */ | ||
1433 | icd->sense = &sense; | 1443 | icd->sense = &sense; |
1434 | 1444 | ||
1435 | cam_f.fmt.pix.pixelformat = cam_fmt->fourcc; | 1445 | mf.width = pix->width; |
1436 | ret = v4l2_subdev_call(sd, video, s_fmt, &cam_f); | 1446 | mf.height = pix->height; |
1437 | cam_f.fmt.pix.pixelformat = pix->pixelformat; | 1447 | mf.field = pix->field; |
1438 | *pix = cam_f.fmt.pix; | 1448 | mf.colorspace = pix->colorspace; |
1449 | mf.code = xlate->code; | ||
1450 | |||
1451 | ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf); | ||
1452 | |||
1453 | if (mf.code != xlate->code) | ||
1454 | return -EINVAL; | ||
1439 | 1455 | ||
1440 | icd->sense = NULL; | 1456 | icd->sense = NULL; |
1441 | 1457 | ||
1442 | if (ret < 0) { | 1458 | if (ret < 0) { |
1443 | dev_warn(dev, "Failed to configure for format %x\n", | 1459 | dev_warn(dev, "Failed to configure for format %x\n", |
1444 | pix->pixelformat); | 1460 | pix->pixelformat); |
1445 | } else if (pxa_camera_check_frame(pix)) { | 1461 | } else if (pxa_camera_check_frame(mf.width, mf.height)) { |
1446 | dev_warn(dev, | 1462 | dev_warn(dev, |
1447 | "Camera driver produced an unsupported frame %dx%d\n", | 1463 | "Camera driver produced an unsupported frame %dx%d\n", |
1448 | pix->width, pix->height); | 1464 | mf.width, mf.height); |
1449 | ret = -EINVAL; | 1465 | ret = -EINVAL; |
1450 | } else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) { | 1466 | } else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) { |
1451 | if (sense.pixel_clock > sense.pixel_clock_max) { | 1467 | if (sense.pixel_clock > sense.pixel_clock_max) { |
@@ -1457,10 +1473,14 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, | |||
1457 | recalculate_fifo_timeout(pcdev, sense.pixel_clock); | 1473 | recalculate_fifo_timeout(pcdev, sense.pixel_clock); |
1458 | } | 1474 | } |
1459 | 1475 | ||
1460 | if (!ret) { | 1476 | if (ret < 0) |
1461 | icd->buswidth = xlate->buswidth; | 1477 | return ret; |
1462 | icd->current_fmt = xlate->host_fmt; | 1478 | |
1463 | } | 1479 | pix->width = mf.width; |
1480 | pix->height = mf.height; | ||
1481 | pix->field = mf.field; | ||
1482 | pix->colorspace = mf.colorspace; | ||
1483 | icd->current_fmt = xlate; | ||
1464 | 1484 | ||
1465 | return ret; | 1485 | return ret; |
1466 | } | 1486 | } |
@@ -1468,17 +1488,16 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, | |||
1468 | static int pxa_camera_try_fmt(struct soc_camera_device *icd, | 1488 | static int pxa_camera_try_fmt(struct soc_camera_device *icd, |
1469 | struct v4l2_format *f) | 1489 | struct v4l2_format *f) |
1470 | { | 1490 | { |
1471 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | ||
1472 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | 1491 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
1473 | const struct soc_camera_format_xlate *xlate; | 1492 | const struct soc_camera_format_xlate *xlate; |
1474 | struct v4l2_pix_format *pix = &f->fmt.pix; | 1493 | struct v4l2_pix_format *pix = &f->fmt.pix; |
1494 | struct v4l2_mbus_framefmt mf; | ||
1475 | __u32 pixfmt = pix->pixelformat; | 1495 | __u32 pixfmt = pix->pixelformat; |
1476 | enum v4l2_field field; | ||
1477 | int ret; | 1496 | int ret; |
1478 | 1497 | ||
1479 | xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); | 1498 | xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); |
1480 | if (!xlate) { | 1499 | if (!xlate) { |
1481 | dev_warn(ici->v4l2_dev.dev, "Format %x not found\n", pixfmt); | 1500 | dev_warn(icd->dev.parent, "Format %x not found\n", pixfmt); |
1482 | return -EINVAL; | 1501 | return -EINVAL; |
1483 | } | 1502 | } |
1484 | 1503 | ||
@@ -1492,22 +1511,36 @@ static int pxa_camera_try_fmt(struct soc_camera_device *icd, | |||
1492 | &pix->height, 32, 2048, 0, | 1511 | &pix->height, 32, 2048, 0, |
1493 | pixfmt == V4L2_PIX_FMT_YUV422P ? 4 : 0); | 1512 | pixfmt == V4L2_PIX_FMT_YUV422P ? 4 : 0); |
1494 | 1513 | ||
1495 | pix->bytesperline = pix->width * | 1514 | pix->bytesperline = soc_mbus_bytes_per_line(pix->width, |
1496 | DIV_ROUND_UP(xlate->host_fmt->depth, 8); | 1515 | xlate->host_fmt); |
1516 | if (pix->bytesperline < 0) | ||
1517 | return pix->bytesperline; | ||
1497 | pix->sizeimage = pix->height * pix->bytesperline; | 1518 | pix->sizeimage = pix->height * pix->bytesperline; |
1498 | 1519 | ||
1499 | /* camera has to see its format, but the user the original one */ | ||
1500 | pix->pixelformat = xlate->cam_fmt->fourcc; | ||
1501 | /* limit to sensor capabilities */ | 1520 | /* limit to sensor capabilities */ |
1502 | ret = v4l2_subdev_call(sd, video, try_fmt, f); | 1521 | mf.width = pix->width; |
1503 | pix->pixelformat = pixfmt; | 1522 | mf.height = pix->height; |
1523 | mf.field = pix->field; | ||
1524 | mf.colorspace = pix->colorspace; | ||
1525 | mf.code = xlate->code; | ||
1504 | 1526 | ||
1505 | field = pix->field; | 1527 | ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf); |
1528 | if (ret < 0) | ||
1529 | return ret; | ||
1506 | 1530 | ||
1507 | if (field == V4L2_FIELD_ANY) { | 1531 | pix->width = mf.width; |
1508 | pix->field = V4L2_FIELD_NONE; | 1532 | pix->height = mf.height; |
1509 | } else if (field != V4L2_FIELD_NONE) { | 1533 | pix->colorspace = mf.colorspace; |
1510 | dev_err(icd->dev.parent, "Field type %d unsupported.\n", field); | 1534 | |
1535 | switch (mf.field) { | ||
1536 | case V4L2_FIELD_ANY: | ||
1537 | case V4L2_FIELD_NONE: | ||
1538 | pix->field = V4L2_FIELD_NONE; | ||
1539 | break; | ||
1540 | default: | ||
1541 | /* TODO: support interlaced at least in pass-through mode */ | ||
1542 | dev_err(icd->dev.parent, "Field type %d unsupported.\n", | ||
1543 | mf.field); | ||
1511 | return -EINVAL; | 1544 | return -EINVAL; |
1512 | } | 1545 | } |
1513 | 1546 | ||
@@ -1519,10 +1552,12 @@ static int pxa_camera_reqbufs(struct soc_camera_file *icf, | |||
1519 | { | 1552 | { |
1520 | int i; | 1553 | int i; |
1521 | 1554 | ||
1522 | /* This is for locking debugging only. I removed spinlocks and now I | 1555 | /* |
1556 | * This is for locking debugging only. I removed spinlocks and now I | ||
1523 | * check whether .prepare is ever called on a linked buffer, or whether | 1557 | * check whether .prepare is ever called on a linked buffer, or whether |
1524 | * a dma IRQ can occur for an in-work or unlinked buffer. Until now | 1558 | * a dma IRQ can occur for an in-work or unlinked buffer. Until now |
1525 | * it hadn't triggered */ | 1559 | * it hadn't triggered |
1560 | */ | ||
1526 | for (i = 0; i < p->count; i++) { | 1561 | for (i = 0; i < p->count; i++) { |
1527 | struct pxa_buffer *buf = container_of(icf->vb_vidq.bufs[i], | 1562 | struct pxa_buffer *buf = container_of(icf->vb_vidq.bufs[i], |
1528 | struct pxa_buffer, vb); | 1563 | struct pxa_buffer, vb); |
@@ -1657,8 +1692,10 @@ static int __devinit pxa_camera_probe(struct platform_device *pdev) | |||
1657 | pcdev->platform_flags = pcdev->pdata->flags; | 1692 | pcdev->platform_flags = pcdev->pdata->flags; |
1658 | if (!(pcdev->platform_flags & (PXA_CAMERA_DATAWIDTH_8 | | 1693 | if (!(pcdev->platform_flags & (PXA_CAMERA_DATAWIDTH_8 | |
1659 | PXA_CAMERA_DATAWIDTH_9 | PXA_CAMERA_DATAWIDTH_10))) { | 1694 | PXA_CAMERA_DATAWIDTH_9 | PXA_CAMERA_DATAWIDTH_10))) { |
1660 | /* Platform hasn't set available data widths. This is bad. | 1695 | /* |
1661 | * Warn and use a default. */ | 1696 | * Platform hasn't set available data widths. This is bad. |
1697 | * Warn and use a default. | ||
1698 | */ | ||
1662 | dev_warn(&pdev->dev, "WARNING! Platform hasn't set available " | 1699 | dev_warn(&pdev->dev, "WARNING! Platform hasn't set available " |
1663 | "data widths, using default 10 bit\n"); | 1700 | "data widths, using default 10 bit\n"); |
1664 | pcdev->platform_flags |= PXA_CAMERA_DATAWIDTH_10; | 1701 | pcdev->platform_flags |= PXA_CAMERA_DATAWIDTH_10; |
diff --git a/drivers/media/video/rj54n1cb0c.c b/drivers/media/video/rj54n1cb0c.c index 373f2a30a677..805226e0d9c1 100644 --- a/drivers/media/video/rj54n1cb0c.c +++ b/drivers/media/video/rj54n1cb0c.c | |||
@@ -13,9 +13,11 @@ | |||
13 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
14 | #include <linux/videodev2.h> | 14 | #include <linux/videodev2.h> |
15 | 15 | ||
16 | #include <media/rj54n1cb0c.h> | ||
17 | #include <media/soc_camera.h> | ||
18 | #include <media/soc_mediabus.h> | ||
16 | #include <media/v4l2-subdev.h> | 19 | #include <media/v4l2-subdev.h> |
17 | #include <media/v4l2-chip-ident.h> | 20 | #include <media/v4l2-chip-ident.h> |
18 | #include <media/soc_camera.h> | ||
19 | 21 | ||
20 | #define RJ54N1_DEV_CODE 0x0400 | 22 | #define RJ54N1_DEV_CODE 0x0400 |
21 | #define RJ54N1_DEV_CODE2 0x0401 | 23 | #define RJ54N1_DEV_CODE2 0x0401 |
@@ -38,6 +40,7 @@ | |||
38 | #define RJ54N1_H_OBEN_OFS 0x0413 | 40 | #define RJ54N1_H_OBEN_OFS 0x0413 |
39 | #define RJ54N1_V_OBEN_OFS 0x0414 | 41 | #define RJ54N1_V_OBEN_OFS 0x0414 |
40 | #define RJ54N1_RESIZE_CONTROL 0x0415 | 42 | #define RJ54N1_RESIZE_CONTROL 0x0415 |
43 | #define RJ54N1_STILL_CONTROL 0x0417 | ||
41 | #define RJ54N1_INC_USE_SEL_H 0x0425 | 44 | #define RJ54N1_INC_USE_SEL_H 0x0425 |
42 | #define RJ54N1_INC_USE_SEL_L 0x0426 | 45 | #define RJ54N1_INC_USE_SEL_L 0x0426 |
43 | #define RJ54N1_MIRROR_STILL_MODE 0x0427 | 46 | #define RJ54N1_MIRROR_STILL_MODE 0x0427 |
@@ -49,10 +52,21 @@ | |||
49 | #define RJ54N1_RA_SEL_UL 0x0530 | 52 | #define RJ54N1_RA_SEL_UL 0x0530 |
50 | #define RJ54N1_BYTE_SWAP 0x0531 | 53 | #define RJ54N1_BYTE_SWAP 0x0531 |
51 | #define RJ54N1_OUT_SIGPO 0x053b | 54 | #define RJ54N1_OUT_SIGPO 0x053b |
55 | #define RJ54N1_WB_SEL_WEIGHT_I 0x054e | ||
56 | #define RJ54N1_BIT8_WB 0x0569 | ||
57 | #define RJ54N1_HCAPS_WB 0x056a | ||
58 | #define RJ54N1_VCAPS_WB 0x056b | ||
59 | #define RJ54N1_HCAPE_WB 0x056c | ||
60 | #define RJ54N1_VCAPE_WB 0x056d | ||
61 | #define RJ54N1_EXPOSURE_CONTROL 0x058c | ||
52 | #define RJ54N1_FRAME_LENGTH_S_H 0x0595 | 62 | #define RJ54N1_FRAME_LENGTH_S_H 0x0595 |
53 | #define RJ54N1_FRAME_LENGTH_S_L 0x0596 | 63 | #define RJ54N1_FRAME_LENGTH_S_L 0x0596 |
54 | #define RJ54N1_FRAME_LENGTH_P_H 0x0597 | 64 | #define RJ54N1_FRAME_LENGTH_P_H 0x0597 |
55 | #define RJ54N1_FRAME_LENGTH_P_L 0x0598 | 65 | #define RJ54N1_FRAME_LENGTH_P_L 0x0598 |
66 | #define RJ54N1_PEAK_H 0x05b7 | ||
67 | #define RJ54N1_PEAK_50 0x05b8 | ||
68 | #define RJ54N1_PEAK_60 0x05b9 | ||
69 | #define RJ54N1_PEAK_DIFF 0x05ba | ||
56 | #define RJ54N1_IOC 0x05ef | 70 | #define RJ54N1_IOC 0x05ef |
57 | #define RJ54N1_TG_BYPASS 0x0700 | 71 | #define RJ54N1_TG_BYPASS 0x0700 |
58 | #define RJ54N1_PLL_L 0x0701 | 72 | #define RJ54N1_PLL_L 0x0701 |
@@ -68,6 +82,7 @@ | |||
68 | #define RJ54N1_OCLK_SEL_EN 0x0713 | 82 | #define RJ54N1_OCLK_SEL_EN 0x0713 |
69 | #define RJ54N1_CLK_RST 0x0717 | 83 | #define RJ54N1_CLK_RST 0x0717 |
70 | #define RJ54N1_RESET_STANDBY 0x0718 | 84 | #define RJ54N1_RESET_STANDBY 0x0718 |
85 | #define RJ54N1_FWFLG 0x07fe | ||
71 | 86 | ||
72 | #define E_EXCLK (1 << 7) | 87 | #define E_EXCLK (1 << 7) |
73 | #define SOFT_STDBY (1 << 4) | 88 | #define SOFT_STDBY (1 << 4) |
@@ -78,29 +93,53 @@ | |||
78 | #define RESIZE_HOLD_SEL (1 << 2) | 93 | #define RESIZE_HOLD_SEL (1 << 2) |
79 | #define RESIZE_GO (1 << 1) | 94 | #define RESIZE_GO (1 << 1) |
80 | 95 | ||
96 | /* | ||
97 | * When cropping, the camera automatically centers the cropped region, there | ||
98 | * doesn't seem to be a way to specify an explicit location of the rectangle. | ||
99 | */ | ||
81 | #define RJ54N1_COLUMN_SKIP 0 | 100 | #define RJ54N1_COLUMN_SKIP 0 |
82 | #define RJ54N1_ROW_SKIP 0 | 101 | #define RJ54N1_ROW_SKIP 0 |
83 | #define RJ54N1_MAX_WIDTH 1600 | 102 | #define RJ54N1_MAX_WIDTH 1600 |
84 | #define RJ54N1_MAX_HEIGHT 1200 | 103 | #define RJ54N1_MAX_HEIGHT 1200 |
85 | 104 | ||
105 | #define PLL_L 2 | ||
106 | #define PLL_N 0x31 | ||
107 | |||
86 | /* I2C addresses: 0x50, 0x51, 0x60, 0x61 */ | 108 | /* I2C addresses: 0x50, 0x51, 0x60, 0x61 */ |
87 | 109 | ||
88 | static const struct soc_camera_data_format rj54n1_colour_formats[] = { | 110 | /* RJ54N1CB0C has only one fixed colorspace per pixelcode */ |
89 | { | 111 | struct rj54n1_datafmt { |
90 | .name = "YUYV", | 112 | enum v4l2_mbus_pixelcode code; |
91 | .depth = 16, | 113 | enum v4l2_colorspace colorspace; |
92 | .fourcc = V4L2_PIX_FMT_YUYV, | 114 | }; |
93 | .colorspace = V4L2_COLORSPACE_JPEG, | 115 | |
94 | }, { | 116 | /* Find a data format by a pixel code in an array */ |
95 | .name = "RGB565", | 117 | static const struct rj54n1_datafmt *rj54n1_find_datafmt( |
96 | .depth = 16, | 118 | enum v4l2_mbus_pixelcode code, const struct rj54n1_datafmt *fmt, |
97 | .fourcc = V4L2_PIX_FMT_RGB565, | 119 | int n) |
98 | .colorspace = V4L2_COLORSPACE_SRGB, | 120 | { |
99 | } | 121 | int i; |
122 | for (i = 0; i < n; i++) | ||
123 | if (fmt[i].code == code) | ||
124 | return fmt + i; | ||
125 | |||
126 | return NULL; | ||
127 | } | ||
128 | |||
129 | static const struct rj54n1_datafmt rj54n1_colour_fmts[] = { | ||
130 | {V4L2_MBUS_FMT_YUYV8_2X8_LE, V4L2_COLORSPACE_JPEG}, | ||
131 | {V4L2_MBUS_FMT_YVYU8_2X8_LE, V4L2_COLORSPACE_JPEG}, | ||
132 | {V4L2_MBUS_FMT_RGB565_2X8_LE, V4L2_COLORSPACE_SRGB}, | ||
133 | {V4L2_MBUS_FMT_RGB565_2X8_BE, V4L2_COLORSPACE_SRGB}, | ||
134 | {V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB}, | ||
135 | {V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE, V4L2_COLORSPACE_SRGB}, | ||
136 | {V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE, V4L2_COLORSPACE_SRGB}, | ||
137 | {V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE, V4L2_COLORSPACE_SRGB}, | ||
138 | {V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_COLORSPACE_SRGB}, | ||
100 | }; | 139 | }; |
101 | 140 | ||
102 | struct rj54n1_clock_div { | 141 | struct rj54n1_clock_div { |
103 | u8 ratio_tg; | 142 | u8 ratio_tg; /* can be 0 or an odd number */ |
104 | u8 ratio_t; | 143 | u8 ratio_t; |
105 | u8 ratio_r; | 144 | u8 ratio_r; |
106 | u8 ratio_op; | 145 | u8 ratio_op; |
@@ -109,12 +148,14 @@ struct rj54n1_clock_div { | |||
109 | 148 | ||
110 | struct rj54n1 { | 149 | struct rj54n1 { |
111 | struct v4l2_subdev subdev; | 150 | struct v4l2_subdev subdev; |
151 | struct rj54n1_clock_div clk_div; | ||
152 | const struct rj54n1_datafmt *fmt; | ||
112 | struct v4l2_rect rect; /* Sensor window */ | 153 | struct v4l2_rect rect; /* Sensor window */ |
154 | unsigned int tgclk_mhz; | ||
155 | bool auto_wb; | ||
113 | unsigned short width; /* Output window */ | 156 | unsigned short width; /* Output window */ |
114 | unsigned short height; | 157 | unsigned short height; |
115 | unsigned short resize; /* Sensor * 1024 / resize = Output */ | 158 | unsigned short resize; /* Sensor * 1024 / resize = Output */ |
116 | struct rj54n1_clock_div clk_div; | ||
117 | u32 fourcc; | ||
118 | unsigned short scale; | 159 | unsigned short scale; |
119 | u8 bank; | 160 | u8 bank; |
120 | }; | 161 | }; |
@@ -171,7 +212,7 @@ const static struct rj54n1_reg_val bank_7[] = { | |||
171 | {0x714, 0xff}, | 212 | {0x714, 0xff}, |
172 | {0x715, 0xff}, | 213 | {0x715, 0xff}, |
173 | {0x716, 0x1f}, | 214 | {0x716, 0x1f}, |
174 | {0x7FE, 0x02}, | 215 | {0x7FE, 2}, |
175 | }; | 216 | }; |
176 | 217 | ||
177 | const static struct rj54n1_reg_val bank_8[] = { | 218 | const static struct rj54n1_reg_val bank_8[] = { |
@@ -359,7 +400,7 @@ const static struct rj54n1_reg_val bank_8[] = { | |||
359 | {0x8BB, 0x00}, | 400 | {0x8BB, 0x00}, |
360 | {0x8BC, 0xFF}, | 401 | {0x8BC, 0xFF}, |
361 | {0x8BD, 0x00}, | 402 | {0x8BD, 0x00}, |
362 | {0x8FE, 0x02}, | 403 | {0x8FE, 2}, |
363 | }; | 404 | }; |
364 | 405 | ||
365 | const static struct rj54n1_reg_val bank_10[] = { | 406 | const static struct rj54n1_reg_val bank_10[] = { |
@@ -440,12 +481,24 @@ static int reg_write_multiple(struct i2c_client *client, | |||
440 | return 0; | 481 | return 0; |
441 | } | 482 | } |
442 | 483 | ||
443 | static int rj54n1_s_stream(struct v4l2_subdev *sd, int enable) | 484 | static int rj54n1_enum_fmt(struct v4l2_subdev *sd, int index, |
485 | enum v4l2_mbus_pixelcode *code) | ||
444 | { | 486 | { |
445 | /* TODO: start / stop streaming */ | 487 | if ((unsigned int)index >= ARRAY_SIZE(rj54n1_colour_fmts)) |
488 | return -EINVAL; | ||
489 | |||
490 | *code = rj54n1_colour_fmts[index].code; | ||
446 | return 0; | 491 | return 0; |
447 | } | 492 | } |
448 | 493 | ||
494 | static int rj54n1_s_stream(struct v4l2_subdev *sd, int enable) | ||
495 | { | ||
496 | struct i2c_client *client = sd->priv; | ||
497 | |||
498 | /* Switch between preview and still shot modes */ | ||
499 | return reg_set(client, RJ54N1_STILL_CONTROL, (!enable) << 7, 0x80); | ||
500 | } | ||
501 | |||
449 | static int rj54n1_set_bus_param(struct soc_camera_device *icd, | 502 | static int rj54n1_set_bus_param(struct soc_camera_device *icd, |
450 | unsigned long flags) | 503 | unsigned long flags) |
451 | { | 504 | { |
@@ -502,6 +555,44 @@ static int rj54n1_commit(struct i2c_client *client) | |||
502 | return ret; | 555 | return ret; |
503 | } | 556 | } |
504 | 557 | ||
558 | static int rj54n1_sensor_scale(struct v4l2_subdev *sd, u32 *in_w, u32 *in_h, | ||
559 | u32 *out_w, u32 *out_h); | ||
560 | |||
561 | static int rj54n1_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) | ||
562 | { | ||
563 | struct i2c_client *client = sd->priv; | ||
564 | struct rj54n1 *rj54n1 = to_rj54n1(client); | ||
565 | struct v4l2_rect *rect = &a->c; | ||
566 | unsigned int dummy = 0, output_w, output_h, | ||
567 | input_w = rect->width, input_h = rect->height; | ||
568 | int ret; | ||
569 | |||
570 | /* arbitrary minimum width and height, edges unimportant */ | ||
571 | soc_camera_limit_side(&dummy, &input_w, | ||
572 | RJ54N1_COLUMN_SKIP, 8, RJ54N1_MAX_WIDTH); | ||
573 | |||
574 | soc_camera_limit_side(&dummy, &input_h, | ||
575 | RJ54N1_ROW_SKIP, 8, RJ54N1_MAX_HEIGHT); | ||
576 | |||
577 | output_w = (input_w * 1024 + rj54n1->resize / 2) / rj54n1->resize; | ||
578 | output_h = (input_h * 1024 + rj54n1->resize / 2) / rj54n1->resize; | ||
579 | |||
580 | dev_dbg(&client->dev, "Scaling for %ux%u : %u = %ux%u\n", | ||
581 | input_w, input_h, rj54n1->resize, output_w, output_h); | ||
582 | |||
583 | ret = rj54n1_sensor_scale(sd, &input_w, &input_h, &output_w, &output_h); | ||
584 | if (ret < 0) | ||
585 | return ret; | ||
586 | |||
587 | rj54n1->width = output_w; | ||
588 | rj54n1->height = output_h; | ||
589 | rj54n1->resize = ret; | ||
590 | rj54n1->rect.width = input_w; | ||
591 | rj54n1->rect.height = input_h; | ||
592 | |||
593 | return 0; | ||
594 | } | ||
595 | |||
505 | static int rj54n1_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) | 596 | static int rj54n1_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) |
506 | { | 597 | { |
507 | struct i2c_client *client = sd->priv; | 598 | struct i2c_client *client = sd->priv; |
@@ -527,16 +618,17 @@ static int rj54n1_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) | |||
527 | return 0; | 618 | return 0; |
528 | } | 619 | } |
529 | 620 | ||
530 | static int rj54n1_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | 621 | static int rj54n1_g_fmt(struct v4l2_subdev *sd, |
622 | struct v4l2_mbus_framefmt *mf) | ||
531 | { | 623 | { |
532 | struct i2c_client *client = sd->priv; | 624 | struct i2c_client *client = sd->priv; |
533 | struct rj54n1 *rj54n1 = to_rj54n1(client); | 625 | struct rj54n1 *rj54n1 = to_rj54n1(client); |
534 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
535 | 626 | ||
536 | pix->pixelformat = rj54n1->fourcc; | 627 | mf->code = rj54n1->fmt->code; |
537 | pix->field = V4L2_FIELD_NONE; | 628 | mf->colorspace = rj54n1->fmt->colorspace; |
538 | pix->width = rj54n1->width; | 629 | mf->field = V4L2_FIELD_NONE; |
539 | pix->height = rj54n1->height; | 630 | mf->width = rj54n1->width; |
631 | mf->height = rj54n1->height; | ||
540 | 632 | ||
541 | return 0; | 633 | return 0; |
542 | } | 634 | } |
@@ -550,11 +642,44 @@ static int rj54n1_sensor_scale(struct v4l2_subdev *sd, u32 *in_w, u32 *in_h, | |||
550 | u32 *out_w, u32 *out_h) | 642 | u32 *out_w, u32 *out_h) |
551 | { | 643 | { |
552 | struct i2c_client *client = sd->priv; | 644 | struct i2c_client *client = sd->priv; |
645 | struct rj54n1 *rj54n1 = to_rj54n1(client); | ||
553 | unsigned int skip, resize, input_w = *in_w, input_h = *in_h, | 646 | unsigned int skip, resize, input_w = *in_w, input_h = *in_h, |
554 | output_w = *out_w, output_h = *out_h; | 647 | output_w = *out_w, output_h = *out_h; |
555 | u16 inc_sel; | 648 | u16 inc_sel, wb_bit8, wb_left, wb_right, wb_top, wb_bottom; |
649 | unsigned int peak, peak_50, peak_60; | ||
556 | int ret; | 650 | int ret; |
557 | 651 | ||
652 | /* | ||
653 | * We have a problem with crops, where the window is larger than 512x384 | ||
654 | * and output window is larger than a half of the input one. In this | ||
655 | * case we have to either reduce the input window to equal or below | ||
656 | * 512x384 or the output window to equal or below 1/2 of the input. | ||
657 | */ | ||
658 | if (output_w > max(512U, input_w / 2)) { | ||
659 | if (2 * output_w > RJ54N1_MAX_WIDTH) { | ||
660 | input_w = RJ54N1_MAX_WIDTH; | ||
661 | output_w = RJ54N1_MAX_WIDTH / 2; | ||
662 | } else { | ||
663 | input_w = output_w * 2; | ||
664 | } | ||
665 | |||
666 | dev_dbg(&client->dev, "Adjusted output width: in %u, out %u\n", | ||
667 | input_w, output_w); | ||
668 | } | ||
669 | |||
670 | if (output_h > max(384U, input_h / 2)) { | ||
671 | if (2 * output_h > RJ54N1_MAX_HEIGHT) { | ||
672 | input_h = RJ54N1_MAX_HEIGHT; | ||
673 | output_h = RJ54N1_MAX_HEIGHT / 2; | ||
674 | } else { | ||
675 | input_h = output_h * 2; | ||
676 | } | ||
677 | |||
678 | dev_dbg(&client->dev, "Adjusted output height: in %u, out %u\n", | ||
679 | input_h, output_h); | ||
680 | } | ||
681 | |||
682 | /* Idea: use the read mode for snapshots, handle separate geometries */ | ||
558 | ret = rj54n1_set_rect(client, RJ54N1_X_OUTPUT_SIZE_S_L, | 683 | ret = rj54n1_set_rect(client, RJ54N1_X_OUTPUT_SIZE_S_L, |
559 | RJ54N1_Y_OUTPUT_SIZE_S_L, | 684 | RJ54N1_Y_OUTPUT_SIZE_S_L, |
560 | RJ54N1_XY_OUTPUT_SIZE_S_H, output_w, output_h); | 685 | RJ54N1_XY_OUTPUT_SIZE_S_H, output_w, output_h); |
@@ -566,17 +691,27 @@ static int rj54n1_sensor_scale(struct v4l2_subdev *sd, u32 *in_w, u32 *in_h, | |||
566 | if (ret < 0) | 691 | if (ret < 0) |
567 | return ret; | 692 | return ret; |
568 | 693 | ||
569 | if (output_w > input_w || output_h > input_h) { | 694 | if (output_w > input_w && output_h > input_h) { |
570 | input_w = output_w; | 695 | input_w = output_w; |
571 | input_h = output_h; | 696 | input_h = output_h; |
572 | 697 | ||
573 | resize = 1024; | 698 | resize = 1024; |
574 | } else { | 699 | } else { |
575 | unsigned int resize_x, resize_y; | 700 | unsigned int resize_x, resize_y; |
576 | resize_x = input_w * 1024 / output_w; | 701 | resize_x = (input_w * 1024 + output_w / 2) / output_w; |
577 | resize_y = input_h * 1024 / output_h; | 702 | resize_y = (input_h * 1024 + output_h / 2) / output_h; |
578 | 703 | ||
579 | resize = min(resize_x, resize_y); | 704 | /* We want max(resize_x, resize_y), check if it still fits */ |
705 | if (resize_x > resize_y && | ||
706 | (output_h * resize_x + 512) / 1024 > RJ54N1_MAX_HEIGHT) | ||
707 | resize = (RJ54N1_MAX_HEIGHT * 1024 + output_h / 2) / | ||
708 | output_h; | ||
709 | else if (resize_y > resize_x && | ||
710 | (output_w * resize_y + 512) / 1024 > RJ54N1_MAX_WIDTH) | ||
711 | resize = (RJ54N1_MAX_WIDTH * 1024 + output_w / 2) / | ||
712 | output_w; | ||
713 | else | ||
714 | resize = max(resize_x, resize_y); | ||
580 | 715 | ||
581 | /* Prohibited value ranges */ | 716 | /* Prohibited value ranges */ |
582 | switch (resize) { | 717 | switch (resize) { |
@@ -589,12 +724,9 @@ static int rj54n1_sensor_scale(struct v4l2_subdev *sd, u32 *in_w, u32 *in_h, | |||
589 | case 8160 ... 8191: | 724 | case 8160 ... 8191: |
590 | resize = 8159; | 725 | resize = 8159; |
591 | break; | 726 | break; |
592 | case 16320 ... 16383: | 727 | case 16320 ... 16384: |
593 | resize = 16319; | 728 | resize = 16319; |
594 | } | 729 | } |
595 | |||
596 | input_w = output_w * resize / 1024; | ||
597 | input_h = output_h * resize / 1024; | ||
598 | } | 730 | } |
599 | 731 | ||
600 | /* Set scaling */ | 732 | /* Set scaling */ |
@@ -607,9 +739,18 @@ static int rj54n1_sensor_scale(struct v4l2_subdev *sd, u32 *in_w, u32 *in_h, | |||
607 | 739 | ||
608 | /* | 740 | /* |
609 | * Configure a skipping bitmask. The sensor will select a skipping value | 741 | * Configure a skipping bitmask. The sensor will select a skipping value |
610 | * among set bits automatically. | 742 | * among set bits automatically. This is very unclear in the datasheet |
743 | * too. I was told, in this register one enables all skipping values, | ||
744 | * that are required for a specific resize, and the camera selects | ||
745 | * automatically, which ones to use. But it is unclear how to identify, | ||
746 | * which cropping values are needed. Secondly, why don't we just set all | ||
747 | * bits and let the camera choose? Would it increase processing time and | ||
748 | * reduce the framerate? Using 0xfffc for INC_USE_SEL doesn't seem to | ||
749 | * improve the image quality or stability for larger frames (see comment | ||
750 | * above), but I didn't check the framerate. | ||
611 | */ | 751 | */ |
612 | skip = min(resize / 1024, (unsigned)15); | 752 | skip = min(resize / 1024, (unsigned)15); |
753 | |||
613 | inc_sel = 1 << skip; | 754 | inc_sel = 1 << skip; |
614 | 755 | ||
615 | if (inc_sel <= 2) | 756 | if (inc_sel <= 2) |
@@ -621,6 +762,43 @@ static int rj54n1_sensor_scale(struct v4l2_subdev *sd, u32 *in_w, u32 *in_h, | |||
621 | if (!ret) | 762 | if (!ret) |
622 | ret = reg_write(client, RJ54N1_INC_USE_SEL_H, inc_sel >> 8); | 763 | ret = reg_write(client, RJ54N1_INC_USE_SEL_H, inc_sel >> 8); |
623 | 764 | ||
765 | if (!rj54n1->auto_wb) { | ||
766 | /* Auto white balance window */ | ||
767 | wb_left = output_w / 16; | ||
768 | wb_right = (3 * output_w / 4 - 3) / 4; | ||
769 | wb_top = output_h / 16; | ||
770 | wb_bottom = (3 * output_h / 4 - 3) / 4; | ||
771 | wb_bit8 = ((wb_left >> 2) & 0x40) | ((wb_top >> 4) & 0x10) | | ||
772 | ((wb_right >> 6) & 4) | ((wb_bottom >> 8) & 1); | ||
773 | |||
774 | if (!ret) | ||
775 | ret = reg_write(client, RJ54N1_BIT8_WB, wb_bit8); | ||
776 | if (!ret) | ||
777 | ret = reg_write(client, RJ54N1_HCAPS_WB, wb_left); | ||
778 | if (!ret) | ||
779 | ret = reg_write(client, RJ54N1_VCAPS_WB, wb_top); | ||
780 | if (!ret) | ||
781 | ret = reg_write(client, RJ54N1_HCAPE_WB, wb_right); | ||
782 | if (!ret) | ||
783 | ret = reg_write(client, RJ54N1_VCAPE_WB, wb_bottom); | ||
784 | } | ||
785 | |||
786 | /* Antiflicker */ | ||
787 | peak = 12 * RJ54N1_MAX_WIDTH * (1 << 14) * resize / rj54n1->tgclk_mhz / | ||
788 | 10000; | ||
789 | peak_50 = peak / 6; | ||
790 | peak_60 = peak / 5; | ||
791 | |||
792 | if (!ret) | ||
793 | ret = reg_write(client, RJ54N1_PEAK_H, | ||
794 | ((peak_50 >> 4) & 0xf0) | (peak_60 >> 8)); | ||
795 | if (!ret) | ||
796 | ret = reg_write(client, RJ54N1_PEAK_50, peak_50); | ||
797 | if (!ret) | ||
798 | ret = reg_write(client, RJ54N1_PEAK_60, peak_60); | ||
799 | if (!ret) | ||
800 | ret = reg_write(client, RJ54N1_PEAK_DIFF, peak / 150); | ||
801 | |||
624 | /* Start resizing */ | 802 | /* Start resizing */ |
625 | if (!ret) | 803 | if (!ret) |
626 | ret = reg_write(client, RJ54N1_RESIZE_CONTROL, | 804 | ret = reg_write(client, RJ54N1_RESIZE_CONTROL, |
@@ -629,8 +807,6 @@ static int rj54n1_sensor_scale(struct v4l2_subdev *sd, u32 *in_w, u32 *in_h, | |||
629 | if (ret < 0) | 807 | if (ret < 0) |
630 | return ret; | 808 | return ret; |
631 | 809 | ||
632 | dev_dbg(&client->dev, "resize %u, skip %u\n", resize, skip); | ||
633 | |||
634 | /* Constant taken from manufacturer's example */ | 810 | /* Constant taken from manufacturer's example */ |
635 | msleep(230); | 811 | msleep(230); |
636 | 812 | ||
@@ -638,11 +814,14 @@ static int rj54n1_sensor_scale(struct v4l2_subdev *sd, u32 *in_w, u32 *in_h, | |||
638 | if (ret < 0) | 814 | if (ret < 0) |
639 | return ret; | 815 | return ret; |
640 | 816 | ||
641 | *in_w = input_w; | 817 | *in_w = (output_w * resize + 512) / 1024; |
642 | *in_h = input_h; | 818 | *in_h = (output_h * resize + 512) / 1024; |
643 | *out_w = output_w; | 819 | *out_w = output_w; |
644 | *out_h = output_h; | 820 | *out_h = output_h; |
645 | 821 | ||
822 | dev_dbg(&client->dev, "Scaled for %ux%u : %u = %ux%u, skip %u\n", | ||
823 | *in_w, *in_h, resize, output_w, output_h, skip); | ||
824 | |||
646 | return resize; | 825 | return resize; |
647 | } | 826 | } |
648 | 827 | ||
@@ -653,14 +832,14 @@ static int rj54n1_set_clock(struct i2c_client *client) | |||
653 | 832 | ||
654 | /* Enable external clock */ | 833 | /* Enable external clock */ |
655 | ret = reg_write(client, RJ54N1_RESET_STANDBY, E_EXCLK | SOFT_STDBY); | 834 | ret = reg_write(client, RJ54N1_RESET_STANDBY, E_EXCLK | SOFT_STDBY); |
656 | /* Leave stand-by */ | 835 | /* Leave stand-by. Note: use this when implementing suspend / resume */ |
657 | if (!ret) | 836 | if (!ret) |
658 | ret = reg_write(client, RJ54N1_RESET_STANDBY, E_EXCLK); | 837 | ret = reg_write(client, RJ54N1_RESET_STANDBY, E_EXCLK); |
659 | 838 | ||
660 | if (!ret) | 839 | if (!ret) |
661 | ret = reg_write(client, RJ54N1_PLL_L, 2); | 840 | ret = reg_write(client, RJ54N1_PLL_L, PLL_L); |
662 | if (!ret) | 841 | if (!ret) |
663 | ret = reg_write(client, RJ54N1_PLL_N, 0x31); | 842 | ret = reg_write(client, RJ54N1_PLL_N, PLL_N); |
664 | 843 | ||
665 | /* TGCLK dividers */ | 844 | /* TGCLK dividers */ |
666 | if (!ret) | 845 | if (!ret) |
@@ -719,6 +898,7 @@ static int rj54n1_set_clock(struct i2c_client *client) | |||
719 | "Resetting RJ54N1CB0C clock failed: %d!\n", ret); | 898 | "Resetting RJ54N1CB0C clock failed: %d!\n", ret); |
720 | return -EIO; | 899 | return -EIO; |
721 | } | 900 | } |
901 | |||
722 | /* Start the PLL */ | 902 | /* Start the PLL */ |
723 | ret = reg_set(client, RJ54N1_OCLK_DSP, 1, 1); | 903 | ret = reg_set(client, RJ54N1_OCLK_DSP, 1, 1); |
724 | 904 | ||
@@ -731,6 +911,7 @@ static int rj54n1_set_clock(struct i2c_client *client) | |||
731 | 911 | ||
732 | static int rj54n1_reg_init(struct i2c_client *client) | 912 | static int rj54n1_reg_init(struct i2c_client *client) |
733 | { | 913 | { |
914 | struct rj54n1 *rj54n1 = to_rj54n1(client); | ||
734 | int ret = rj54n1_set_clock(client); | 915 | int ret = rj54n1_set_clock(client); |
735 | 916 | ||
736 | if (!ret) | 917 | if (!ret) |
@@ -753,14 +934,26 @@ static int rj54n1_reg_init(struct i2c_client *client) | |||
753 | if (!ret) | 934 | if (!ret) |
754 | ret = reg_write(client, RJ54N1_Y_GAIN, 0x84); | 935 | ret = reg_write(client, RJ54N1_Y_GAIN, 0x84); |
755 | 936 | ||
756 | /* Mirror the image back: default is upside down and left-to-right... */ | 937 | /* |
938 | * Mirror the image back: default is upside down and left-to-right... | ||
939 | * Set manual preview / still shot switching | ||
940 | */ | ||
757 | if (!ret) | 941 | if (!ret) |
758 | ret = reg_set(client, RJ54N1_MIRROR_STILL_MODE, 3, 3); | 942 | ret = reg_write(client, RJ54N1_MIRROR_STILL_MODE, 0x27); |
759 | 943 | ||
760 | if (!ret) | 944 | if (!ret) |
761 | ret = reg_write_multiple(client, bank_4, ARRAY_SIZE(bank_4)); | 945 | ret = reg_write_multiple(client, bank_4, ARRAY_SIZE(bank_4)); |
946 | |||
947 | /* Auto exposure area */ | ||
762 | if (!ret) | 948 | if (!ret) |
949 | ret = reg_write(client, RJ54N1_EXPOSURE_CONTROL, 0x80); | ||
950 | /* Check current auto WB config */ | ||
951 | if (!ret) | ||
952 | ret = reg_read(client, RJ54N1_WB_SEL_WEIGHT_I); | ||
953 | if (ret >= 0) { | ||
954 | rj54n1->auto_wb = ret & 0x80; | ||
763 | ret = reg_write_multiple(client, bank_5, ARRAY_SIZE(bank_5)); | 955 | ret = reg_write_multiple(client, bank_5, ARRAY_SIZE(bank_5)); |
956 | } | ||
764 | if (!ret) | 957 | if (!ret) |
765 | ret = reg_write_multiple(client, bank_8, ARRAY_SIZE(bank_8)); | 958 | ret = reg_write_multiple(client, bank_8, ARRAY_SIZE(bank_8)); |
766 | 959 | ||
@@ -777,8 +970,9 @@ static int rj54n1_reg_init(struct i2c_client *client) | |||
777 | ret = reg_write(client, RJ54N1_RESET_STANDBY, | 970 | ret = reg_write(client, RJ54N1_RESET_STANDBY, |
778 | E_EXCLK | DSP_RSTX | TG_RSTX | SEN_RSTX); | 971 | E_EXCLK | DSP_RSTX | TG_RSTX | SEN_RSTX); |
779 | 972 | ||
973 | /* Start register update? Same register as 0x?FE in many bank_* sets */ | ||
780 | if (!ret) | 974 | if (!ret) |
781 | ret = reg_write(client, 0x7fe, 2); | 975 | ret = reg_write(client, RJ54N1_FWFLG, 2); |
782 | 976 | ||
783 | /* Constant taken from manufacturer's example */ | 977 | /* Constant taken from manufacturer's example */ |
784 | msleep(700); | 978 | msleep(700); |
@@ -786,27 +980,44 @@ static int rj54n1_reg_init(struct i2c_client *client) | |||
786 | return ret; | 980 | return ret; |
787 | } | 981 | } |
788 | 982 | ||
789 | /* FIXME: streaming output only up to 800x600 is functional */ | 983 | static int rj54n1_try_fmt(struct v4l2_subdev *sd, |
790 | static int rj54n1_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | 984 | struct v4l2_mbus_framefmt *mf) |
791 | { | 985 | { |
792 | struct v4l2_pix_format *pix = &f->fmt.pix; | 986 | struct i2c_client *client = sd->priv; |
987 | struct rj54n1 *rj54n1 = to_rj54n1(client); | ||
988 | const struct rj54n1_datafmt *fmt; | ||
989 | int align = mf->code == V4L2_MBUS_FMT_SBGGR10_1X10 || | ||
990 | mf->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE || | ||
991 | mf->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE || | ||
992 | mf->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE || | ||
993 | mf->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE; | ||
994 | |||
995 | dev_dbg(&client->dev, "%s: code = %d, width = %u, height = %u\n", | ||
996 | __func__, mf->code, mf->width, mf->height); | ||
997 | |||
998 | fmt = rj54n1_find_datafmt(mf->code, rj54n1_colour_fmts, | ||
999 | ARRAY_SIZE(rj54n1_colour_fmts)); | ||
1000 | if (!fmt) { | ||
1001 | fmt = rj54n1->fmt; | ||
1002 | mf->code = fmt->code; | ||
1003 | } | ||
793 | 1004 | ||
794 | pix->field = V4L2_FIELD_NONE; | 1005 | mf->field = V4L2_FIELD_NONE; |
1006 | mf->colorspace = fmt->colorspace; | ||
795 | 1007 | ||
796 | if (pix->width > 800) | 1008 | v4l_bound_align_image(&mf->width, 112, RJ54N1_MAX_WIDTH, align, |
797 | pix->width = 800; | 1009 | &mf->height, 84, RJ54N1_MAX_HEIGHT, align, 0); |
798 | if (pix->height > 600) | ||
799 | pix->height = 600; | ||
800 | 1010 | ||
801 | return 0; | 1011 | return 0; |
802 | } | 1012 | } |
803 | 1013 | ||
804 | static int rj54n1_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | 1014 | static int rj54n1_s_fmt(struct v4l2_subdev *sd, |
1015 | struct v4l2_mbus_framefmt *mf) | ||
805 | { | 1016 | { |
806 | struct i2c_client *client = sd->priv; | 1017 | struct i2c_client *client = sd->priv; |
807 | struct rj54n1 *rj54n1 = to_rj54n1(client); | 1018 | struct rj54n1 *rj54n1 = to_rj54n1(client); |
808 | struct v4l2_pix_format *pix = &f->fmt.pix; | 1019 | const struct rj54n1_datafmt *fmt; |
809 | unsigned int output_w, output_h, | 1020 | unsigned int output_w, output_h, max_w, max_h, |
810 | input_w = rj54n1->rect.width, input_h = rj54n1->rect.height; | 1021 | input_w = rj54n1->rect.width, input_h = rj54n1->rect.height; |
811 | int ret; | 1022 | int ret; |
812 | 1023 | ||
@@ -814,14 +1025,13 @@ static int rj54n1_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | |||
814 | * The host driver can call us without .try_fmt(), so, we have to take | 1025 | * The host driver can call us without .try_fmt(), so, we have to take |
815 | * care ourseleves | 1026 | * care ourseleves |
816 | */ | 1027 | */ |
817 | ret = rj54n1_try_fmt(sd, f); | 1028 | rj54n1_try_fmt(sd, mf); |
818 | 1029 | ||
819 | /* | 1030 | /* |
820 | * Verify if the sensor has just been powered on. TODO: replace this | 1031 | * Verify if the sensor has just been powered on. TODO: replace this |
821 | * with proper PM, when a suitable API is available. | 1032 | * with proper PM, when a suitable API is available. |
822 | */ | 1033 | */ |
823 | if (!ret) | 1034 | ret = reg_read(client, RJ54N1_RESET_STANDBY); |
824 | ret = reg_read(client, RJ54N1_RESET_STANDBY); | ||
825 | if (ret < 0) | 1035 | if (ret < 0) |
826 | return ret; | 1036 | return ret; |
827 | 1037 | ||
@@ -831,50 +1041,105 @@ static int rj54n1_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | |||
831 | return ret; | 1041 | return ret; |
832 | } | 1042 | } |
833 | 1043 | ||
1044 | dev_dbg(&client->dev, "%s: code = %d, width = %u, height = %u\n", | ||
1045 | __func__, mf->code, mf->width, mf->height); | ||
1046 | |||
834 | /* RA_SEL_UL is only relevant for raw modes, ignored otherwise. */ | 1047 | /* RA_SEL_UL is only relevant for raw modes, ignored otherwise. */ |
835 | switch (pix->pixelformat) { | 1048 | switch (mf->code) { |
836 | case V4L2_PIX_FMT_YUYV: | 1049 | case V4L2_MBUS_FMT_YUYV8_2X8_LE: |
837 | ret = reg_write(client, RJ54N1_OUT_SEL, 0); | 1050 | ret = reg_write(client, RJ54N1_OUT_SEL, 0); |
838 | if (!ret) | 1051 | if (!ret) |
839 | ret = reg_set(client, RJ54N1_BYTE_SWAP, 8, 8); | 1052 | ret = reg_set(client, RJ54N1_BYTE_SWAP, 8, 8); |
840 | break; | 1053 | break; |
841 | case V4L2_PIX_FMT_RGB565: | 1054 | case V4L2_MBUS_FMT_YVYU8_2X8_LE: |
1055 | ret = reg_write(client, RJ54N1_OUT_SEL, 0); | ||
1056 | if (!ret) | ||
1057 | ret = reg_set(client, RJ54N1_BYTE_SWAP, 0, 8); | ||
1058 | break; | ||
1059 | case V4L2_MBUS_FMT_RGB565_2X8_LE: | ||
1060 | ret = reg_write(client, RJ54N1_OUT_SEL, 0x11); | ||
1061 | if (!ret) | ||
1062 | ret = reg_set(client, RJ54N1_BYTE_SWAP, 8, 8); | ||
1063 | break; | ||
1064 | case V4L2_MBUS_FMT_RGB565_2X8_BE: | ||
842 | ret = reg_write(client, RJ54N1_OUT_SEL, 0x11); | 1065 | ret = reg_write(client, RJ54N1_OUT_SEL, 0x11); |
843 | if (!ret) | 1066 | if (!ret) |
1067 | ret = reg_set(client, RJ54N1_BYTE_SWAP, 0, 8); | ||
1068 | break; | ||
1069 | case V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE: | ||
1070 | ret = reg_write(client, RJ54N1_OUT_SEL, 4); | ||
1071 | if (!ret) | ||
844 | ret = reg_set(client, RJ54N1_BYTE_SWAP, 8, 8); | 1072 | ret = reg_set(client, RJ54N1_BYTE_SWAP, 8, 8); |
1073 | if (!ret) | ||
1074 | ret = reg_write(client, RJ54N1_RA_SEL_UL, 0); | ||
1075 | break; | ||
1076 | case V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE: | ||
1077 | ret = reg_write(client, RJ54N1_OUT_SEL, 4); | ||
1078 | if (!ret) | ||
1079 | ret = reg_set(client, RJ54N1_BYTE_SWAP, 8, 8); | ||
1080 | if (!ret) | ||
1081 | ret = reg_write(client, RJ54N1_RA_SEL_UL, 8); | ||
1082 | break; | ||
1083 | case V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE: | ||
1084 | ret = reg_write(client, RJ54N1_OUT_SEL, 4); | ||
1085 | if (!ret) | ||
1086 | ret = reg_set(client, RJ54N1_BYTE_SWAP, 0, 8); | ||
1087 | if (!ret) | ||
1088 | ret = reg_write(client, RJ54N1_RA_SEL_UL, 0); | ||
1089 | break; | ||
1090 | case V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE: | ||
1091 | ret = reg_write(client, RJ54N1_OUT_SEL, 4); | ||
1092 | if (!ret) | ||
1093 | ret = reg_set(client, RJ54N1_BYTE_SWAP, 0, 8); | ||
1094 | if (!ret) | ||
1095 | ret = reg_write(client, RJ54N1_RA_SEL_UL, 8); | ||
1096 | break; | ||
1097 | case V4L2_MBUS_FMT_SBGGR10_1X10: | ||
1098 | ret = reg_write(client, RJ54N1_OUT_SEL, 5); | ||
845 | break; | 1099 | break; |
846 | default: | 1100 | default: |
847 | ret = -EINVAL; | 1101 | ret = -EINVAL; |
848 | } | 1102 | } |
849 | 1103 | ||
1104 | /* Special case: a raw mode with 10 bits of data per clock tick */ | ||
1105 | if (!ret) | ||
1106 | ret = reg_set(client, RJ54N1_OCLK_SEL_EN, | ||
1107 | (mf->code == V4L2_MBUS_FMT_SBGGR10_1X10) << 1, 2); | ||
1108 | |||
850 | if (ret < 0) | 1109 | if (ret < 0) |
851 | return ret; | 1110 | return ret; |
852 | 1111 | ||
853 | /* Supported scales 1:1 - 1:16 */ | 1112 | /* Supported scales 1:1 >= scale > 1:16 */ |
854 | if (pix->width < input_w / 16) | 1113 | max_w = mf->width * (16 * 1024 - 1) / 1024; |
855 | pix->width = input_w / 16; | 1114 | if (input_w > max_w) |
856 | if (pix->height < input_h / 16) | 1115 | input_w = max_w; |
857 | pix->height = input_h / 16; | 1116 | max_h = mf->height * (16 * 1024 - 1) / 1024; |
1117 | if (input_h > max_h) | ||
1118 | input_h = max_h; | ||
858 | 1119 | ||
859 | output_w = pix->width; | 1120 | output_w = mf->width; |
860 | output_h = pix->height; | 1121 | output_h = mf->height; |
861 | 1122 | ||
862 | ret = rj54n1_sensor_scale(sd, &input_w, &input_h, &output_w, &output_h); | 1123 | ret = rj54n1_sensor_scale(sd, &input_w, &input_h, &output_w, &output_h); |
863 | if (ret < 0) | 1124 | if (ret < 0) |
864 | return ret; | 1125 | return ret; |
865 | 1126 | ||
866 | rj54n1->fourcc = pix->pixelformat; | 1127 | fmt = rj54n1_find_datafmt(mf->code, rj54n1_colour_fmts, |
1128 | ARRAY_SIZE(rj54n1_colour_fmts)); | ||
1129 | |||
1130 | rj54n1->fmt = fmt; | ||
867 | rj54n1->resize = ret; | 1131 | rj54n1->resize = ret; |
868 | rj54n1->rect.width = input_w; | 1132 | rj54n1->rect.width = input_w; |
869 | rj54n1->rect.height = input_h; | 1133 | rj54n1->rect.height = input_h; |
870 | rj54n1->width = output_w; | 1134 | rj54n1->width = output_w; |
871 | rj54n1->height = output_h; | 1135 | rj54n1->height = output_h; |
872 | 1136 | ||
873 | pix->width = output_w; | 1137 | mf->width = output_w; |
874 | pix->height = output_h; | 1138 | mf->height = output_h; |
875 | pix->field = V4L2_FIELD_NONE; | 1139 | mf->field = V4L2_FIELD_NONE; |
1140 | mf->colorspace = fmt->colorspace; | ||
876 | 1141 | ||
877 | return ret; | 1142 | return 0; |
878 | } | 1143 | } |
879 | 1144 | ||
880 | static int rj54n1_g_chip_ident(struct v4l2_subdev *sd, | 1145 | static int rj54n1_g_chip_ident(struct v4l2_subdev *sd, |
@@ -963,6 +1228,14 @@ static const struct v4l2_queryctrl rj54n1_controls[] = { | |||
963 | .step = 1, | 1228 | .step = 1, |
964 | .default_value = 66, | 1229 | .default_value = 66, |
965 | .flags = V4L2_CTRL_FLAG_SLIDER, | 1230 | .flags = V4L2_CTRL_FLAG_SLIDER, |
1231 | }, { | ||
1232 | .id = V4L2_CID_AUTO_WHITE_BALANCE, | ||
1233 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
1234 | .name = "Auto white balance", | ||
1235 | .minimum = 0, | ||
1236 | .maximum = 1, | ||
1237 | .step = 1, | ||
1238 | .default_value = 1, | ||
966 | }, | 1239 | }, |
967 | }; | 1240 | }; |
968 | 1241 | ||
@@ -976,6 +1249,7 @@ static struct soc_camera_ops rj54n1_ops = { | |||
976 | static int rj54n1_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | 1249 | static int rj54n1_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) |
977 | { | 1250 | { |
978 | struct i2c_client *client = sd->priv; | 1251 | struct i2c_client *client = sd->priv; |
1252 | struct rj54n1 *rj54n1 = to_rj54n1(client); | ||
979 | int data; | 1253 | int data; |
980 | 1254 | ||
981 | switch (ctrl->id) { | 1255 | switch (ctrl->id) { |
@@ -998,6 +1272,9 @@ static int rj54n1_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | |||
998 | 1272 | ||
999 | ctrl->value = data / 2; | 1273 | ctrl->value = data / 2; |
1000 | break; | 1274 | break; |
1275 | case V4L2_CID_AUTO_WHITE_BALANCE: | ||
1276 | ctrl->value = rj54n1->auto_wb; | ||
1277 | break; | ||
1001 | } | 1278 | } |
1002 | 1279 | ||
1003 | return 0; | 1280 | return 0; |
@@ -1007,6 +1284,7 @@ static int rj54n1_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | |||
1007 | { | 1284 | { |
1008 | int data; | 1285 | int data; |
1009 | struct i2c_client *client = sd->priv; | 1286 | struct i2c_client *client = sd->priv; |
1287 | struct rj54n1 *rj54n1 = to_rj54n1(client); | ||
1010 | const struct v4l2_queryctrl *qctrl; | 1288 | const struct v4l2_queryctrl *qctrl; |
1011 | 1289 | ||
1012 | qctrl = soc_camera_find_qctrl(&rj54n1_ops, ctrl->id); | 1290 | qctrl = soc_camera_find_qctrl(&rj54n1_ops, ctrl->id); |
@@ -1037,6 +1315,13 @@ static int rj54n1_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | |||
1037 | else if (reg_write(client, RJ54N1_Y_GAIN, ctrl->value * 2) < 0) | 1315 | else if (reg_write(client, RJ54N1_Y_GAIN, ctrl->value * 2) < 0) |
1038 | return -EIO; | 1316 | return -EIO; |
1039 | break; | 1317 | break; |
1318 | case V4L2_CID_AUTO_WHITE_BALANCE: | ||
1319 | /* Auto WB area - whole image */ | ||
1320 | if (reg_set(client, RJ54N1_WB_SEL_WEIGHT_I, ctrl->value << 7, | ||
1321 | 0x80) < 0) | ||
1322 | return -EIO; | ||
1323 | rj54n1->auto_wb = ctrl->value; | ||
1324 | break; | ||
1040 | } | 1325 | } |
1041 | 1326 | ||
1042 | return 0; | 1327 | return 0; |
@@ -1054,10 +1339,12 @@ static struct v4l2_subdev_core_ops rj54n1_subdev_core_ops = { | |||
1054 | 1339 | ||
1055 | static struct v4l2_subdev_video_ops rj54n1_subdev_video_ops = { | 1340 | static struct v4l2_subdev_video_ops rj54n1_subdev_video_ops = { |
1056 | .s_stream = rj54n1_s_stream, | 1341 | .s_stream = rj54n1_s_stream, |
1057 | .s_fmt = rj54n1_s_fmt, | 1342 | .s_mbus_fmt = rj54n1_s_fmt, |
1058 | .g_fmt = rj54n1_g_fmt, | 1343 | .g_mbus_fmt = rj54n1_g_fmt, |
1059 | .try_fmt = rj54n1_try_fmt, | 1344 | .try_mbus_fmt = rj54n1_try_fmt, |
1345 | .enum_mbus_fmt = rj54n1_enum_fmt, | ||
1060 | .g_crop = rj54n1_g_crop, | 1346 | .g_crop = rj54n1_g_crop, |
1347 | .s_crop = rj54n1_s_crop, | ||
1061 | .cropcap = rj54n1_cropcap, | 1348 | .cropcap = rj54n1_cropcap, |
1062 | }; | 1349 | }; |
1063 | 1350 | ||
@@ -1066,21 +1353,13 @@ static struct v4l2_subdev_ops rj54n1_subdev_ops = { | |||
1066 | .video = &rj54n1_subdev_video_ops, | 1353 | .video = &rj54n1_subdev_video_ops, |
1067 | }; | 1354 | }; |
1068 | 1355 | ||
1069 | static int rj54n1_pin_config(struct i2c_client *client) | ||
1070 | { | ||
1071 | /* | ||
1072 | * Experimentally found out IOCTRL wired to 0. TODO: add to platform | ||
1073 | * data: 0 or 1 << 7. | ||
1074 | */ | ||
1075 | return reg_write(client, RJ54N1_IOC, 0); | ||
1076 | } | ||
1077 | |||
1078 | /* | 1356 | /* |
1079 | * Interface active, can use i2c. If it fails, it can indeed mean, that | 1357 | * Interface active, can use i2c. If it fails, it can indeed mean, that |
1080 | * this wasn't our capture interface, so, we wait for the right one | 1358 | * this wasn't our capture interface, so, we wait for the right one |
1081 | */ | 1359 | */ |
1082 | static int rj54n1_video_probe(struct soc_camera_device *icd, | 1360 | static int rj54n1_video_probe(struct soc_camera_device *icd, |
1083 | struct i2c_client *client) | 1361 | struct i2c_client *client, |
1362 | struct rj54n1_pdata *priv) | ||
1084 | { | 1363 | { |
1085 | int data1, data2; | 1364 | int data1, data2; |
1086 | int ret; | 1365 | int ret; |
@@ -1101,7 +1380,8 @@ static int rj54n1_video_probe(struct soc_camera_device *icd, | |||
1101 | goto ei2c; | 1380 | goto ei2c; |
1102 | } | 1381 | } |
1103 | 1382 | ||
1104 | ret = rj54n1_pin_config(client); | 1383 | /* Configure IOCTL polarity from the platform data: 0 or 1 << 7. */ |
1384 | ret = reg_write(client, RJ54N1_IOC, priv->ioctl_high << 7); | ||
1105 | if (ret < 0) | 1385 | if (ret < 0) |
1106 | goto ei2c; | 1386 | goto ei2c; |
1107 | 1387 | ||
@@ -1119,6 +1399,7 @@ static int rj54n1_probe(struct i2c_client *client, | |||
1119 | struct soc_camera_device *icd = client->dev.platform_data; | 1399 | struct soc_camera_device *icd = client->dev.platform_data; |
1120 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); | 1400 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); |
1121 | struct soc_camera_link *icl; | 1401 | struct soc_camera_link *icl; |
1402 | struct rj54n1_pdata *rj54n1_priv; | ||
1122 | int ret; | 1403 | int ret; |
1123 | 1404 | ||
1124 | if (!icd) { | 1405 | if (!icd) { |
@@ -1127,11 +1408,13 @@ static int rj54n1_probe(struct i2c_client *client, | |||
1127 | } | 1408 | } |
1128 | 1409 | ||
1129 | icl = to_soc_camera_link(icd); | 1410 | icl = to_soc_camera_link(icd); |
1130 | if (!icl) { | 1411 | if (!icl || !icl->priv) { |
1131 | dev_err(&client->dev, "RJ54N1CB0C: missing platform data!\n"); | 1412 | dev_err(&client->dev, "RJ54N1CB0C: missing platform data!\n"); |
1132 | return -EINVAL; | 1413 | return -EINVAL; |
1133 | } | 1414 | } |
1134 | 1415 | ||
1416 | rj54n1_priv = icl->priv; | ||
1417 | |||
1135 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { | 1418 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { |
1136 | dev_warn(&adapter->dev, | 1419 | dev_warn(&adapter->dev, |
1137 | "I2C-Adapter doesn't support I2C_FUNC_SMBUS_BYTE\n"); | 1420 | "I2C-Adapter doesn't support I2C_FUNC_SMBUS_BYTE\n"); |
@@ -1153,10 +1436,12 @@ static int rj54n1_probe(struct i2c_client *client, | |||
1153 | rj54n1->rect.height = RJ54N1_MAX_HEIGHT; | 1436 | rj54n1->rect.height = RJ54N1_MAX_HEIGHT; |
1154 | rj54n1->width = RJ54N1_MAX_WIDTH; | 1437 | rj54n1->width = RJ54N1_MAX_WIDTH; |
1155 | rj54n1->height = RJ54N1_MAX_HEIGHT; | 1438 | rj54n1->height = RJ54N1_MAX_HEIGHT; |
1156 | rj54n1->fourcc = V4L2_PIX_FMT_YUYV; | 1439 | rj54n1->fmt = &rj54n1_colour_fmts[0]; |
1157 | rj54n1->resize = 1024; | 1440 | rj54n1->resize = 1024; |
1441 | rj54n1->tgclk_mhz = (rj54n1_priv->mclk_freq / PLL_L * PLL_N) / | ||
1442 | (clk_div.ratio_tg + 1) / (clk_div.ratio_t + 1); | ||
1158 | 1443 | ||
1159 | ret = rj54n1_video_probe(icd, client); | 1444 | ret = rj54n1_video_probe(icd, client, rj54n1_priv); |
1160 | if (ret < 0) { | 1445 | if (ret < 0) { |
1161 | icd->ops = NULL; | 1446 | icd->ops = NULL; |
1162 | i2c_set_clientdata(client, NULL); | 1447 | i2c_set_clientdata(client, NULL); |
@@ -1164,9 +1449,6 @@ static int rj54n1_probe(struct i2c_client *client, | |||
1164 | return ret; | 1449 | return ret; |
1165 | } | 1450 | } |
1166 | 1451 | ||
1167 | icd->formats = rj54n1_colour_formats; | ||
1168 | icd->num_formats = ARRAY_SIZE(rj54n1_colour_formats); | ||
1169 | |||
1170 | return ret; | 1452 | return ret; |
1171 | } | 1453 | } |
1172 | 1454 | ||
diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index 41765f3c7c28..fb742f1ae711 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c | |||
@@ -233,7 +233,6 @@ struct s2255_dev { | |||
233 | 233 | ||
234 | struct s2255_dmaqueue vidq[MAX_CHANNELS]; | 234 | struct s2255_dmaqueue vidq[MAX_CHANNELS]; |
235 | struct video_device *vdev[MAX_CHANNELS]; | 235 | struct video_device *vdev[MAX_CHANNELS]; |
236 | struct list_head s2255_devlist; | ||
237 | struct timer_list timer; | 236 | struct timer_list timer; |
238 | struct s2255_fw *fw_data; | 237 | struct s2255_fw *fw_data; |
239 | struct s2255_pipeinfo pipes[MAX_PIPE_BUFFERS]; | 238 | struct s2255_pipeinfo pipes[MAX_PIPE_BUFFERS]; |
@@ -313,8 +312,6 @@ struct s2255_fh { | |||
313 | /* Channels on box are in reverse order */ | 312 | /* Channels on box are in reverse order */ |
314 | static unsigned long G_chnmap[MAX_CHANNELS] = {3, 2, 1, 0}; | 313 | static unsigned long G_chnmap[MAX_CHANNELS] = {3, 2, 1, 0}; |
315 | 314 | ||
316 | static LIST_HEAD(s2255_devlist); | ||
317 | |||
318 | static int debug; | 315 | static int debug; |
319 | static int *s2255_debug = &debug; | 316 | static int *s2255_debug = &debug; |
320 | 317 | ||
@@ -1533,32 +1530,24 @@ static int vidioc_s_parm(struct file *file, void *priv, | |||
1533 | } | 1530 | } |
1534 | static int s2255_open(struct file *file) | 1531 | static int s2255_open(struct file *file) |
1535 | { | 1532 | { |
1536 | int minor = video_devdata(file)->minor; | 1533 | struct video_device *vdev = video_devdata(file); |
1537 | struct s2255_dev *h, *dev = NULL; | 1534 | struct s2255_dev *dev = video_drvdata(file); |
1538 | struct s2255_fh *fh; | 1535 | struct s2255_fh *fh; |
1539 | struct list_head *list; | 1536 | enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
1540 | enum v4l2_buf_type type = 0; | ||
1541 | int i = 0; | 1537 | int i = 0; |
1542 | int cur_channel = -1; | 1538 | int cur_channel = -1; |
1543 | int state; | 1539 | int state; |
1544 | dprintk(1, "s2255: open called (minor=%d)\n", minor); | 1540 | |
1541 | dprintk(1, "s2255: open called (dev=%s)\n", | ||
1542 | video_device_node_name(vdev)); | ||
1545 | 1543 | ||
1546 | lock_kernel(); | 1544 | lock_kernel(); |
1547 | list_for_each(list, &s2255_devlist) { | ||
1548 | h = list_entry(list, struct s2255_dev, s2255_devlist); | ||
1549 | for (i = 0; i < MAX_CHANNELS; i++) { | ||
1550 | if (h->vdev[i]->minor == minor) { | ||
1551 | cur_channel = i; | ||
1552 | dev = h; | ||
1553 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
1554 | } | ||
1555 | } | ||
1556 | } | ||
1557 | 1545 | ||
1558 | if ((NULL == dev) || (cur_channel == -1)) { | 1546 | for (i = 0; i < MAX_CHANNELS; i++) { |
1559 | unlock_kernel(); | 1547 | if (dev->vdev[i] == vdev) { |
1560 | printk(KERN_INFO "s2255: openv4l no dev\n"); | 1548 | cur_channel = i; |
1561 | return -ENODEV; | 1549 | break; |
1550 | } | ||
1562 | } | 1551 | } |
1563 | 1552 | ||
1564 | if (atomic_read(&dev->fw_data->fw_state) == S2255_FW_DISCONNECTING) { | 1553 | if (atomic_read(&dev->fw_data->fw_state) == S2255_FW_DISCONNECTING) { |
@@ -1662,8 +1651,9 @@ static int s2255_open(struct file *file) | |||
1662 | for (i = 0; i < ARRAY_SIZE(s2255_qctrl); i++) | 1651 | for (i = 0; i < ARRAY_SIZE(s2255_qctrl); i++) |
1663 | qctl_regs[i] = s2255_qctrl[i].default_value; | 1652 | qctl_regs[i] = s2255_qctrl[i].default_value; |
1664 | 1653 | ||
1665 | dprintk(1, "s2255drv: open minor=%d type=%s users=%d\n", | 1654 | dprintk(1, "s2255drv: open dev=%s type=%s users=%d\n", |
1666 | minor, v4l2_type_names[type], dev->users[cur_channel]); | 1655 | video_device_node_name(vdev), v4l2_type_names[type], |
1656 | dev->users[cur_channel]); | ||
1667 | dprintk(2, "s2255drv: open: fh=0x%08lx, dev=0x%08lx, vidq=0x%08lx\n", | 1657 | dprintk(2, "s2255drv: open: fh=0x%08lx, dev=0x%08lx, vidq=0x%08lx\n", |
1668 | (unsigned long)fh, (unsigned long)dev, | 1658 | (unsigned long)fh, (unsigned long)dev, |
1669 | (unsigned long)&dev->vidq[cur_channel]); | 1659 | (unsigned long)&dev->vidq[cur_channel]); |
@@ -1699,7 +1689,6 @@ static unsigned int s2255_poll(struct file *file, | |||
1699 | static void s2255_destroy(struct kref *kref) | 1689 | static void s2255_destroy(struct kref *kref) |
1700 | { | 1690 | { |
1701 | struct s2255_dev *dev = to_s2255_dev(kref); | 1691 | struct s2255_dev *dev = to_s2255_dev(kref); |
1702 | struct list_head *list; | ||
1703 | int i; | 1692 | int i; |
1704 | if (!dev) { | 1693 | if (!dev) { |
1705 | printk(KERN_ERR "s2255drv: kref problem\n"); | 1694 | printk(KERN_ERR "s2255drv: kref problem\n"); |
@@ -1733,10 +1722,6 @@ static void s2255_destroy(struct kref *kref) | |||
1733 | usb_put_dev(dev->udev); | 1722 | usb_put_dev(dev->udev); |
1734 | dprintk(1, "%s", __func__); | 1723 | dprintk(1, "%s", __func__); |
1735 | 1724 | ||
1736 | while (!list_empty(&s2255_devlist)) { | ||
1737 | list = s2255_devlist.next; | ||
1738 | list_del(list); | ||
1739 | } | ||
1740 | mutex_unlock(&dev->open_lock); | 1725 | mutex_unlock(&dev->open_lock); |
1741 | kfree(dev); | 1726 | kfree(dev); |
1742 | } | 1727 | } |
@@ -1745,7 +1730,8 @@ static int s2255_close(struct file *file) | |||
1745 | { | 1730 | { |
1746 | struct s2255_fh *fh = file->private_data; | 1731 | struct s2255_fh *fh = file->private_data; |
1747 | struct s2255_dev *dev = fh->dev; | 1732 | struct s2255_dev *dev = fh->dev; |
1748 | int minor = video_devdata(file)->minor; | 1733 | struct video_device *vdev = video_devdata(file); |
1734 | |||
1749 | if (!dev) | 1735 | if (!dev) |
1750 | return -ENODEV; | 1736 | return -ENODEV; |
1751 | 1737 | ||
@@ -1765,8 +1751,8 @@ static int s2255_close(struct file *file) | |||
1765 | mutex_unlock(&dev->open_lock); | 1751 | mutex_unlock(&dev->open_lock); |
1766 | 1752 | ||
1767 | kref_put(&dev->kref, s2255_destroy); | 1753 | kref_put(&dev->kref, s2255_destroy); |
1768 | dprintk(1, "s2255: close called (minor=%d, users=%d)\n", | 1754 | dprintk(1, "s2255: close called (dev=%s, users=%d)\n", |
1769 | minor, dev->users[fh->channel]); | 1755 | video_device_node_name(vdev), dev->users[fh->channel]); |
1770 | kfree(fh); | 1756 | kfree(fh); |
1771 | return 0; | 1757 | return 0; |
1772 | } | 1758 | } |
@@ -1830,7 +1816,6 @@ static struct video_device template = { | |||
1830 | .name = "s2255v", | 1816 | .name = "s2255v", |
1831 | .fops = &s2255_fops_v4l, | 1817 | .fops = &s2255_fops_v4l, |
1832 | .ioctl_ops = &s2255_ioctl_ops, | 1818 | .ioctl_ops = &s2255_ioctl_ops, |
1833 | .minor = -1, | ||
1834 | .release = video_device_release, | 1819 | .release = video_device_release, |
1835 | .tvnorms = S2255_NORMS, | 1820 | .tvnorms = S2255_NORMS, |
1836 | .current_norm = V4L2_STD_NTSC_M, | 1821 | .current_norm = V4L2_STD_NTSC_M, |
@@ -1843,7 +1828,6 @@ static int s2255_probe_v4l(struct s2255_dev *dev) | |||
1843 | int cur_nr = video_nr; | 1828 | int cur_nr = video_nr; |
1844 | 1829 | ||
1845 | /* initialize all video 4 linux */ | 1830 | /* initialize all video 4 linux */ |
1846 | list_add_tail(&dev->s2255_devlist, &s2255_devlist); | ||
1847 | /* register 4 video devices */ | 1831 | /* register 4 video devices */ |
1848 | for (i = 0; i < MAX_CHANNELS; i++) { | 1832 | for (i = 0; i < MAX_CHANNELS; i++) { |
1849 | INIT_LIST_HEAD(&dev->vidq[i].active); | 1833 | INIT_LIST_HEAD(&dev->vidq[i].active); |
@@ -1853,6 +1837,7 @@ static int s2255_probe_v4l(struct s2255_dev *dev) | |||
1853 | dev->vdev[i] = video_device_alloc(); | 1837 | dev->vdev[i] = video_device_alloc(); |
1854 | memcpy(dev->vdev[i], &template, sizeof(struct video_device)); | 1838 | memcpy(dev->vdev[i], &template, sizeof(struct video_device)); |
1855 | dev->vdev[i]->parent = &dev->interface->dev; | 1839 | dev->vdev[i]->parent = &dev->interface->dev; |
1840 | video_set_drvdata(dev->vdev[i], dev); | ||
1856 | if (video_nr == -1) | 1841 | if (video_nr == -1) |
1857 | ret = video_register_device(dev->vdev[i], | 1842 | ret = video_register_device(dev->vdev[i], |
1858 | VFL_TYPE_GRABBER, | 1843 | VFL_TYPE_GRABBER, |
@@ -1880,7 +1865,7 @@ static void s2255_exit_v4l(struct s2255_dev *dev) | |||
1880 | 1865 | ||
1881 | int i; | 1866 | int i; |
1882 | for (i = 0; i < MAX_CHANNELS; i++) { | 1867 | for (i = 0; i < MAX_CHANNELS; i++) { |
1883 | if (-1 != dev->vdev[i]->minor) { | 1868 | if (video_is_registered(dev->vdev[i])) { |
1884 | video_unregister_device(dev->vdev[i]); | 1869 | video_unregister_device(dev->vdev[i]); |
1885 | printk(KERN_INFO "s2255 unregistered\n"); | 1870 | printk(KERN_INFO "s2255 unregistered\n"); |
1886 | } else { | 1871 | } else { |
diff --git a/drivers/media/video/saa5246a.c b/drivers/media/video/saa5246a.c index b624a4c01fdc..5ab6a0f901c0 100644 --- a/drivers/media/video/saa5246a.c +++ b/drivers/media/video/saa5246a.c | |||
@@ -1036,7 +1036,6 @@ static struct video_device saa_template = | |||
1036 | .name = "saa5246a", | 1036 | .name = "saa5246a", |
1037 | .fops = &saa_fops, | 1037 | .fops = &saa_fops, |
1038 | .release = video_device_release, | 1038 | .release = video_device_release, |
1039 | .minor = -1, | ||
1040 | }; | 1039 | }; |
1041 | 1040 | ||
1042 | static int saa5246a_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) | 1041 | static int saa5246a_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) |
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 7e40d6d99dd0..03f572708b85 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c | |||
@@ -7211,9 +7211,31 @@ int saa7134_board_init2(struct saa7134_dev *dev) | |||
7211 | } | 7211 | } |
7212 | case SAA7134_BOARD_FLYDVB_TRIO: | 7212 | case SAA7134_BOARD_FLYDVB_TRIO: |
7213 | { | 7213 | { |
7214 | u8 temp = 0; | ||
7215 | int rc; | ||
7214 | u8 data[] = { 0x3c, 0x33, 0x62}; | 7216 | u8 data[] = { 0x3c, 0x33, 0x62}; |
7215 | struct i2c_msg msg = {.addr=0x09, .flags=0, .buf=data, .len = sizeof(data)}; | 7217 | struct i2c_msg msg = {.addr=0x09, .flags=0, .buf=data, .len = sizeof(data)}; |
7216 | i2c_transfer(&dev->i2c_adap, &msg, 1); | 7218 | i2c_transfer(&dev->i2c_adap, &msg, 1); |
7219 | |||
7220 | /* | ||
7221 | * send weak up message to pic16C505 chip | ||
7222 | * @ LifeView FlyDVB Trio | ||
7223 | */ | ||
7224 | msg.buf = &temp; | ||
7225 | msg.addr = 0x0b; | ||
7226 | msg.len = 1; | ||
7227 | if (1 != i2c_transfer(&dev->i2c_adap, &msg, 1)) { | ||
7228 | printk(KERN_WARNING "%s: send wake up byte to pic16C505" | ||
7229 | "(IR chip) failed\n", dev->name); | ||
7230 | } else { | ||
7231 | msg.flags = I2C_M_RD; | ||
7232 | rc = i2c_transfer(&dev->i2c_adap, &msg, 1); | ||
7233 | printk(KERN_INFO "%s: probe IR chip @ i2c 0x%02x: %s\n", | ||
7234 | dev->name, msg.addr, | ||
7235 | (1 == rc) ? "yes" : "no"); | ||
7236 | if (rc == 1) | ||
7237 | dev->has_remote = SAA7134_REMOTE_I2C; | ||
7238 | } | ||
7217 | break; | 7239 | break; |
7218 | } | 7240 | } |
7219 | case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331: | 7241 | case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331: |
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 0ba7f5af0fc3..a7ad7810fddc 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c | |||
@@ -420,19 +420,6 @@ int saa7134_set_dmabits(struct saa7134_dev *dev) | |||
420 | ctrl |= SAA7134_MAIN_CTRL_TE5; | 420 | ctrl |= SAA7134_MAIN_CTRL_TE5; |
421 | irq |= SAA7134_IRQ1_INTE_RA2_1 | | 421 | irq |= SAA7134_IRQ1_INTE_RA2_1 | |
422 | SAA7134_IRQ1_INTE_RA2_0; | 422 | SAA7134_IRQ1_INTE_RA2_0; |
423 | |||
424 | /* dma: setup channel 5 (= TS) */ | ||
425 | |||
426 | saa_writeb(SAA7134_TS_DMA0, (dev->ts.nr_packets - 1) & 0xff); | ||
427 | saa_writeb(SAA7134_TS_DMA1, | ||
428 | ((dev->ts.nr_packets - 1) >> 8) & 0xff); | ||
429 | /* TSNOPIT=0, TSCOLAP=0 */ | ||
430 | saa_writeb(SAA7134_TS_DMA2, | ||
431 | (((dev->ts.nr_packets - 1) >> 16) & 0x3f) | 0x00); | ||
432 | saa_writel(SAA7134_RS_PITCH(5), TS_PACKET_SIZE); | ||
433 | saa_writel(SAA7134_RS_CONTROL(5), SAA7134_RS_CONTROL_BURST_16 | | ||
434 | SAA7134_RS_CONTROL_ME | | ||
435 | (dev->ts.pt_ts.dma >> 12)); | ||
436 | } | 423 | } |
437 | 424 | ||
438 | /* set task conditions + field handling */ | 425 | /* set task conditions + field handling */ |
@@ -797,27 +784,28 @@ static struct video_device *vdev_init(struct saa7134_dev *dev, | |||
797 | vfd->debug = video_debug; | 784 | vfd->debug = video_debug; |
798 | snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", | 785 | snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", |
799 | dev->name, type, saa7134_boards[dev->board].name); | 786 | dev->name, type, saa7134_boards[dev->board].name); |
787 | video_set_drvdata(vfd, dev); | ||
800 | return vfd; | 788 | return vfd; |
801 | } | 789 | } |
802 | 790 | ||
803 | static void saa7134_unregister_video(struct saa7134_dev *dev) | 791 | static void saa7134_unregister_video(struct saa7134_dev *dev) |
804 | { | 792 | { |
805 | if (dev->video_dev) { | 793 | if (dev->video_dev) { |
806 | if (-1 != dev->video_dev->minor) | 794 | if (video_is_registered(dev->video_dev)) |
807 | video_unregister_device(dev->video_dev); | 795 | video_unregister_device(dev->video_dev); |
808 | else | 796 | else |
809 | video_device_release(dev->video_dev); | 797 | video_device_release(dev->video_dev); |
810 | dev->video_dev = NULL; | 798 | dev->video_dev = NULL; |
811 | } | 799 | } |
812 | if (dev->vbi_dev) { | 800 | if (dev->vbi_dev) { |
813 | if (-1 != dev->vbi_dev->minor) | 801 | if (video_is_registered(dev->vbi_dev)) |
814 | video_unregister_device(dev->vbi_dev); | 802 | video_unregister_device(dev->vbi_dev); |
815 | else | 803 | else |
816 | video_device_release(dev->vbi_dev); | 804 | video_device_release(dev->vbi_dev); |
817 | dev->vbi_dev = NULL; | 805 | dev->vbi_dev = NULL; |
818 | } | 806 | } |
819 | if (dev->radio_dev) { | 807 | if (dev->radio_dev) { |
820 | if (-1 != dev->radio_dev->minor) | 808 | if (video_is_registered(dev->radio_dev)) |
821 | video_unregister_device(dev->radio_dev); | 809 | video_unregister_device(dev->radio_dev); |
822 | else | 810 | else |
823 | video_device_release(dev->radio_dev); | 811 | video_device_release(dev->radio_dev); |
@@ -1046,8 +1034,8 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, | |||
1046 | dev->name); | 1034 | dev->name); |
1047 | goto fail4; | 1035 | goto fail4; |
1048 | } | 1036 | } |
1049 | printk(KERN_INFO "%s: registered device video%d [v4l2]\n", | 1037 | printk(KERN_INFO "%s: registered device %s [v4l2]\n", |
1050 | dev->name, dev->video_dev->num); | 1038 | dev->name, video_device_node_name(dev->video_dev)); |
1051 | 1039 | ||
1052 | dev->vbi_dev = vdev_init(dev, &saa7134_video_template, "vbi"); | 1040 | dev->vbi_dev = vdev_init(dev, &saa7134_video_template, "vbi"); |
1053 | 1041 | ||
@@ -1055,8 +1043,8 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, | |||
1055 | vbi_nr[dev->nr]); | 1043 | vbi_nr[dev->nr]); |
1056 | if (err < 0) | 1044 | if (err < 0) |
1057 | goto fail4; | 1045 | goto fail4; |
1058 | printk(KERN_INFO "%s: registered device vbi%d\n", | 1046 | printk(KERN_INFO "%s: registered device %s\n", |
1059 | dev->name, dev->vbi_dev->num); | 1047 | dev->name, video_device_node_name(dev->vbi_dev)); |
1060 | 1048 | ||
1061 | if (card_has_radio(dev)) { | 1049 | if (card_has_radio(dev)) { |
1062 | dev->radio_dev = vdev_init(dev,&saa7134_radio_template,"radio"); | 1050 | dev->radio_dev = vdev_init(dev,&saa7134_radio_template,"radio"); |
@@ -1064,8 +1052,8 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, | |||
1064 | radio_nr[dev->nr]); | 1052 | radio_nr[dev->nr]); |
1065 | if (err < 0) | 1053 | if (err < 0) |
1066 | goto fail4; | 1054 | goto fail4; |
1067 | printk(KERN_INFO "%s: registered device radio%d\n", | 1055 | printk(KERN_INFO "%s: registered device %s\n", |
1068 | dev->name, dev->radio_dev->num); | 1056 | dev->name, video_device_node_name(dev->radio_dev)); |
1069 | } | 1057 | } |
1070 | 1058 | ||
1071 | /* everything worked */ | 1059 | /* everything worked */ |
diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index 296788c3bf0e..7dfecfc6017c 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c | |||
@@ -86,19 +86,11 @@ static int ts_init_encoder(struct saa7134_dev* dev) | |||
86 | 86 | ||
87 | static int ts_open(struct file *file) | 87 | static int ts_open(struct file *file) |
88 | { | 88 | { |
89 | int minor = video_devdata(file)->minor; | 89 | struct video_device *vdev = video_devdata(file); |
90 | struct saa7134_dev *dev; | 90 | struct saa7134_dev *dev = video_drvdata(file); |
91 | int err; | 91 | int err; |
92 | 92 | ||
93 | lock_kernel(); | 93 | dprintk("open dev=%s\n", video_device_node_name(vdev)); |
94 | list_for_each_entry(dev, &saa7134_devlist, devlist) | ||
95 | if (dev->empress_dev && dev->empress_dev->minor == minor) | ||
96 | goto found; | ||
97 | unlock_kernel(); | ||
98 | return -ENODEV; | ||
99 | found: | ||
100 | |||
101 | dprintk("open minor=%d\n",minor); | ||
102 | err = -EBUSY; | 94 | err = -EBUSY; |
103 | if (!mutex_trylock(&dev->empress_tsq.vb_lock)) | 95 | if (!mutex_trylock(&dev->empress_tsq.vb_lock)) |
104 | goto done; | 96 | goto done; |
@@ -489,7 +481,6 @@ static const struct v4l2_ioctl_ops ts_ioctl_ops = { | |||
489 | static struct video_device saa7134_empress_template = { | 481 | static struct video_device saa7134_empress_template = { |
490 | .name = "saa7134-empress", | 482 | .name = "saa7134-empress", |
491 | .fops = &ts_fops, | 483 | .fops = &ts_fops, |
492 | .minor = -1, | ||
493 | .ioctl_ops = &ts_ioctl_ops, | 484 | .ioctl_ops = &ts_ioctl_ops, |
494 | 485 | ||
495 | .tvnorms = SAA7134_NORMS, | 486 | .tvnorms = SAA7134_NORMS, |
@@ -531,6 +522,7 @@ static int empress_init(struct saa7134_dev *dev) | |||
531 | 522 | ||
532 | INIT_WORK(&dev->empress_workqueue, empress_signal_update); | 523 | INIT_WORK(&dev->empress_workqueue, empress_signal_update); |
533 | 524 | ||
525 | video_set_drvdata(dev->empress_dev, dev); | ||
534 | err = video_register_device(dev->empress_dev,VFL_TYPE_GRABBER, | 526 | err = video_register_device(dev->empress_dev,VFL_TYPE_GRABBER, |
535 | empress_nr[dev->nr]); | 527 | empress_nr[dev->nr]); |
536 | if (err < 0) { | 528 | if (err < 0) { |
@@ -540,8 +532,8 @@ static int empress_init(struct saa7134_dev *dev) | |||
540 | dev->empress_dev = NULL; | 532 | dev->empress_dev = NULL; |
541 | return err; | 533 | return err; |
542 | } | 534 | } |
543 | printk(KERN_INFO "%s: registered device video%d [mpeg]\n", | 535 | printk(KERN_INFO "%s: registered device %s [mpeg]\n", |
544 | dev->name, dev->empress_dev->num); | 536 | dev->name, video_device_node_name(dev->empress_dev)); |
545 | 537 | ||
546 | videobuf_queue_sg_init(&dev->empress_tsq, &saa7134_ts_qops, | 538 | videobuf_queue_sg_init(&dev->empress_tsq, &saa7134_ts_qops, |
547 | &dev->pci->dev, &dev->slock, | 539 | &dev->pci->dev, &dev->slock, |
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 744918b1cd47..f8e985989ca0 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c | |||
@@ -127,6 +127,61 @@ static int build_key(struct saa7134_dev *dev) | |||
127 | 127 | ||
128 | /* --------------------- Chip specific I2C key builders ----------------- */ | 128 | /* --------------------- Chip specific I2C key builders ----------------- */ |
129 | 129 | ||
130 | static int get_key_flydvb_trio(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | ||
131 | { | ||
132 | int gpio; | ||
133 | int attempt = 0; | ||
134 | unsigned char b; | ||
135 | |||
136 | /* We need this to access GPI Used by the saa_readl macro. */ | ||
137 | struct saa7134_dev *dev = ir->c->adapter->algo_data; | ||
138 | |||
139 | if (dev == NULL) { | ||
140 | dprintk("get_key_flydvb_trio: " | ||
141 | "gir->c->adapter->algo_data is NULL!\n"); | ||
142 | return -EIO; | ||
143 | } | ||
144 | |||
145 | /* rising SAA7134_GPIGPRESCAN reads the status */ | ||
146 | saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); | ||
147 | saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); | ||
148 | |||
149 | gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2); | ||
150 | |||
151 | if (0x40000 & ~gpio) | ||
152 | return 0; /* No button press */ | ||
153 | |||
154 | /* No button press - only before first key pressed */ | ||
155 | if (b == 0xFF) | ||
156 | return 0; | ||
157 | |||
158 | /* poll IR chip */ | ||
159 | /* weak up the IR chip */ | ||
160 | b = 0; | ||
161 | |||
162 | while (1 != i2c_master_send(ir->c, &b, 1)) { | ||
163 | if ((attempt++) < 10) { | ||
164 | /* | ||
165 | * wait a bit for next attempt - | ||
166 | * I don't know how make it better | ||
167 | */ | ||
168 | msleep(10); | ||
169 | continue; | ||
170 | } | ||
171 | i2cdprintk("send wake up byte to pic16C505 (IR chip)" | ||
172 | "failed %dx\n", attempt); | ||
173 | return -EIO; | ||
174 | } | ||
175 | if (1 != i2c_master_recv(ir->c, &b, 1)) { | ||
176 | i2cdprintk("read error\n"); | ||
177 | return -EIO; | ||
178 | } | ||
179 | |||
180 | *ir_key = b; | ||
181 | *ir_raw = b; | ||
182 | return 1; | ||
183 | } | ||
184 | |||
130 | static int get_key_msi_tvanywhere_plus(struct IR_i2c *ir, u32 *ir_key, | 185 | static int get_key_msi_tvanywhere_plus(struct IR_i2c *ir, u32 *ir_key, |
131 | u32 *ir_raw) | 186 | u32 *ir_raw) |
132 | { | 187 | { |
@@ -622,6 +677,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
622 | mask_keyup = 0x020000; | 677 | mask_keyup = 0x020000; |
623 | polling = 50; /* ms */ | 678 | polling = 50; /* ms */ |
624 | break; | 679 | break; |
680 | break; | ||
625 | } | 681 | } |
626 | if (NULL == ir_codes) { | 682 | if (NULL == ir_codes) { |
627 | printk("%s: Oops: IR config error [card=%d]\n", | 683 | printk("%s: Oops: IR config error [card=%d]\n", |
@@ -652,7 +708,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
652 | snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", | 708 | snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", |
653 | pci_name(dev->pci)); | 709 | pci_name(dev->pci)); |
654 | 710 | ||
655 | err = ir_input_init(input_dev, &ir->ir, ir_type, ir_codes); | 711 | err = ir_input_init(input_dev, &ir->ir, ir_type); |
656 | if (err < 0) | 712 | if (err < 0) |
657 | goto err_out_free; | 713 | goto err_out_free; |
658 | 714 | ||
@@ -672,7 +728,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
672 | dev->remote = ir; | 728 | dev->remote = ir; |
673 | saa7134_ir_start(dev, ir); | 729 | saa7134_ir_start(dev, ir); |
674 | 730 | ||
675 | err = input_register_device(ir->dev); | 731 | err = ir_input_register(ir->dev, ir_codes); |
676 | if (err) | 732 | if (err) |
677 | goto err_out_stop; | 733 | goto err_out_stop; |
678 | 734 | ||
@@ -686,8 +742,6 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
686 | saa7134_ir_stop(dev); | 742 | saa7134_ir_stop(dev); |
687 | dev->remote = NULL; | 743 | dev->remote = NULL; |
688 | err_out_free: | 744 | err_out_free: |
689 | ir_input_free(input_dev); | ||
690 | input_free_device(input_dev); | ||
691 | kfree(ir); | 745 | kfree(ir); |
692 | return err; | 746 | return err; |
693 | } | 747 | } |
@@ -698,8 +752,7 @@ void saa7134_input_fini(struct saa7134_dev *dev) | |||
698 | return; | 752 | return; |
699 | 753 | ||
700 | saa7134_ir_stop(dev); | 754 | saa7134_ir_stop(dev); |
701 | ir_input_free(dev->remote->dev); | 755 | ir_input_unregister(dev->remote->dev); |
702 | input_unregister_device(dev->remote->dev); | ||
703 | kfree(dev->remote); | 756 | kfree(dev->remote); |
704 | dev->remote = NULL; | 757 | dev->remote = NULL; |
705 | } | 758 | } |
@@ -788,6 +841,12 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) | |||
788 | case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: | 841 | case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: |
789 | info.addr = 0x40; | 842 | info.addr = 0x40; |
790 | break; | 843 | break; |
844 | case SAA7134_BOARD_FLYDVB_TRIO: | ||
845 | dev->init_data.name = "FlyDVB Trio"; | ||
846 | dev->init_data.get_key = get_key_flydvb_trio; | ||
847 | dev->init_data.ir_codes = &ir_codes_flydvb_table; | ||
848 | info.addr = 0x0b; | ||
849 | break; | ||
791 | default: | 850 | default: |
792 | dprintk("No I2C IR support for board %x\n", dev->board); | 851 | dprintk("No I2C IR support for board %x\n", dev->board); |
793 | return; | 852 | return; |
diff --git a/drivers/media/video/saa7134/saa7134-ts.c b/drivers/media/video/saa7134/saa7134-ts.c index 03488ba4c99c..b9817d74943f 100644 --- a/drivers/media/video/saa7134/saa7134-ts.c +++ b/drivers/media/video/saa7134/saa7134-ts.c | |||
@@ -250,6 +250,19 @@ int saa7134_ts_start(struct saa7134_dev *dev) | |||
250 | 250 | ||
251 | BUG_ON(dev->ts_started); | 251 | BUG_ON(dev->ts_started); |
252 | 252 | ||
253 | /* dma: setup channel 5 (= TS) */ | ||
254 | saa_writeb(SAA7134_TS_DMA0, (dev->ts.nr_packets - 1) & 0xff); | ||
255 | saa_writeb(SAA7134_TS_DMA1, | ||
256 | ((dev->ts.nr_packets - 1) >> 8) & 0xff); | ||
257 | /* TSNOPIT=0, TSCOLAP=0 */ | ||
258 | saa_writeb(SAA7134_TS_DMA2, | ||
259 | (((dev->ts.nr_packets - 1) >> 16) & 0x3f) | 0x00); | ||
260 | saa_writel(SAA7134_RS_PITCH(5), TS_PACKET_SIZE); | ||
261 | saa_writel(SAA7134_RS_CONTROL(5), SAA7134_RS_CONTROL_BURST_16 | | ||
262 | SAA7134_RS_CONTROL_ME | | ||
263 | (dev->ts.pt_ts.dma >> 12)); | ||
264 | |||
265 | /* reset hardware TS buffers */ | ||
253 | saa_writeb(SAA7134_TS_SERIAL1, 0x00); | 266 | saa_writeb(SAA7134_TS_SERIAL1, 0x00); |
254 | saa_writeb(SAA7134_TS_SERIAL1, 0x03); | 267 | saa_writeb(SAA7134_TS_SERIAL1, 0x03); |
255 | saa_writeb(SAA7134_TS_SERIAL1, 0x00); | 268 | saa_writeb(SAA7134_TS_SERIAL1, 0x00); |
diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index 35f8daa3a359..cb732640ac4a 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c | |||
@@ -1326,33 +1326,26 @@ static int saa7134_resource(struct saa7134_fh *fh) | |||
1326 | 1326 | ||
1327 | static int video_open(struct file *file) | 1327 | static int video_open(struct file *file) |
1328 | { | 1328 | { |
1329 | int minor = video_devdata(file)->minor; | 1329 | struct video_device *vdev = video_devdata(file); |
1330 | struct saa7134_dev *dev; | 1330 | struct saa7134_dev *dev = video_drvdata(file); |
1331 | struct saa7134_fh *fh; | 1331 | struct saa7134_fh *fh; |
1332 | enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 1332 | enum v4l2_buf_type type = 0; |
1333 | int radio = 0; | 1333 | int radio = 0; |
1334 | 1334 | ||
1335 | mutex_lock(&saa7134_devlist_lock); | 1335 | switch (vdev->vfl_type) { |
1336 | list_for_each_entry(dev, &saa7134_devlist, devlist) { | 1336 | case VFL_TYPE_GRABBER: |
1337 | if (dev->video_dev && (dev->video_dev->minor == minor)) | 1337 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
1338 | goto found; | 1338 | break; |
1339 | if (dev->radio_dev && (dev->radio_dev->minor == minor)) { | 1339 | case VFL_TYPE_VBI: |
1340 | radio = 1; | 1340 | type = V4L2_BUF_TYPE_VBI_CAPTURE; |
1341 | goto found; | 1341 | break; |
1342 | } | 1342 | case VFL_TYPE_RADIO: |
1343 | if (dev->vbi_dev && (dev->vbi_dev->minor == minor)) { | 1343 | radio = 1; |
1344 | type = V4L2_BUF_TYPE_VBI_CAPTURE; | 1344 | break; |
1345 | goto found; | ||
1346 | } | ||
1347 | } | 1345 | } |
1348 | mutex_unlock(&saa7134_devlist_lock); | ||
1349 | return -ENODEV; | ||
1350 | |||
1351 | found: | ||
1352 | mutex_unlock(&saa7134_devlist_lock); | ||
1353 | 1346 | ||
1354 | dprintk("open minor=%d radio=%d type=%s\n",minor,radio, | 1347 | dprintk("open dev=%s radio=%d type=%s\n", video_device_node_name(vdev), |
1355 | v4l2_type_names[type]); | 1348 | radio, v4l2_type_names[type]); |
1356 | 1349 | ||
1357 | /* allocate + initialize per filehandle data */ | 1350 | /* allocate + initialize per filehandle data */ |
1358 | fh = kzalloc(sizeof(*fh),GFP_KERNEL); | 1351 | fh = kzalloc(sizeof(*fh),GFP_KERNEL); |
@@ -2502,7 +2495,6 @@ struct video_device saa7134_video_template = { | |||
2502 | .name = "saa7134-video", | 2495 | .name = "saa7134-video", |
2503 | .fops = &video_fops, | 2496 | .fops = &video_fops, |
2504 | .ioctl_ops = &video_ioctl_ops, | 2497 | .ioctl_ops = &video_ioctl_ops, |
2505 | .minor = -1, | ||
2506 | .tvnorms = SAA7134_NORMS, | 2498 | .tvnorms = SAA7134_NORMS, |
2507 | .current_norm = V4L2_STD_PAL, | 2499 | .current_norm = V4L2_STD_PAL, |
2508 | }; | 2500 | }; |
@@ -2511,7 +2503,6 @@ struct video_device saa7134_radio_template = { | |||
2511 | .name = "saa7134-radio", | 2503 | .name = "saa7134-radio", |
2512 | .fops = &radio_fops, | 2504 | .fops = &radio_fops, |
2513 | .ioctl_ops = &radio_ioctl_ops, | 2505 | .ioctl_ops = &radio_ioctl_ops, |
2514 | .minor = -1, | ||
2515 | }; | 2506 | }; |
2516 | 2507 | ||
2517 | int saa7134_video_init1(struct saa7134_dev *dev) | 2508 | int saa7134_video_init1(struct saa7134_dev *dev) |
diff --git a/drivers/media/video/se401.c b/drivers/media/video/se401.c index 85ffc2cba039..41d0166c0f95 100644 --- a/drivers/media/video/se401.c +++ b/drivers/media/video/se401.c | |||
@@ -1428,8 +1428,8 @@ static int se401_probe(struct usb_interface *intf, | |||
1428 | err("video_register_device failed"); | 1428 | err("video_register_device failed"); |
1429 | return -EIO; | 1429 | return -EIO; |
1430 | } | 1430 | } |
1431 | dev_info(&intf->dev, "registered new video device: video%d\n", | 1431 | dev_info(&intf->dev, "registered new video device: %s\n", |
1432 | se401->vdev.num); | 1432 | video_device_node_name(&se401->vdev)); |
1433 | 1433 | ||
1434 | usb_set_intfdata(intf, se401); | 1434 | usb_set_intfdata(intf, se401); |
1435 | return 0; | 1435 | return 0; |
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index a4f3472d4db8..f09c7140d6b2 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c | |||
@@ -38,6 +38,8 @@ | |||
38 | #include <media/soc_camera.h> | 38 | #include <media/soc_camera.h> |
39 | #include <media/sh_mobile_ceu.h> | 39 | #include <media/sh_mobile_ceu.h> |
40 | #include <media/videobuf-dma-contig.h> | 40 | #include <media/videobuf-dma-contig.h> |
41 | #include <media/v4l2-mediabus.h> | ||
42 | #include <media/soc_mediabus.h> | ||
41 | 43 | ||
42 | /* register offsets for sh7722 / sh7723 */ | 44 | /* register offsets for sh7722 / sh7723 */ |
43 | 45 | ||
@@ -85,7 +87,7 @@ | |||
85 | /* per video frame buffer */ | 87 | /* per video frame buffer */ |
86 | struct sh_mobile_ceu_buffer { | 88 | struct sh_mobile_ceu_buffer { |
87 | struct videobuf_buffer vb; /* v4l buffer must be first */ | 89 | struct videobuf_buffer vb; /* v4l buffer must be first */ |
88 | const struct soc_camera_data_format *fmt; | 90 | enum v4l2_mbus_pixelcode code; |
89 | }; | 91 | }; |
90 | 92 | ||
91 | struct sh_mobile_ceu_dev { | 93 | struct sh_mobile_ceu_dev { |
@@ -105,7 +107,8 @@ struct sh_mobile_ceu_dev { | |||
105 | 107 | ||
106 | u32 cflcr; | 108 | u32 cflcr; |
107 | 109 | ||
108 | unsigned int is_interlaced:1; | 110 | enum v4l2_field field; |
111 | |||
109 | unsigned int image_mode:1; | 112 | unsigned int image_mode:1; |
110 | unsigned int is_16bit:1; | 113 | unsigned int is_16bit:1; |
111 | }; | 114 | }; |
@@ -114,8 +117,8 @@ struct sh_mobile_ceu_cam { | |||
114 | struct v4l2_rect ceu_rect; | 117 | struct v4l2_rect ceu_rect; |
115 | unsigned int cam_width; | 118 | unsigned int cam_width; |
116 | unsigned int cam_height; | 119 | unsigned int cam_height; |
117 | const struct soc_camera_data_format *extra_fmt; | 120 | const struct soc_mbus_pixelfmt *extra_fmt; |
118 | const struct soc_camera_data_format *camera_fmt; | 121 | enum v4l2_mbus_pixelcode code; |
119 | }; | 122 | }; |
120 | 123 | ||
121 | static unsigned long make_bus_param(struct sh_mobile_ceu_dev *pcdev) | 124 | static unsigned long make_bus_param(struct sh_mobile_ceu_dev *pcdev) |
@@ -197,16 +200,19 @@ static int sh_mobile_ceu_videobuf_setup(struct videobuf_queue *vq, | |||
197 | struct soc_camera_device *icd = vq->priv_data; | 200 | struct soc_camera_device *icd = vq->priv_data; |
198 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | 201 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); |
199 | struct sh_mobile_ceu_dev *pcdev = ici->priv; | 202 | struct sh_mobile_ceu_dev *pcdev = ici->priv; |
200 | int bytes_per_pixel = (icd->current_fmt->depth + 7) >> 3; | 203 | int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, |
204 | icd->current_fmt->host_fmt); | ||
205 | |||
206 | if (bytes_per_line < 0) | ||
207 | return bytes_per_line; | ||
201 | 208 | ||
202 | *size = PAGE_ALIGN(icd->user_width * icd->user_height * | 209 | *size = bytes_per_line * icd->user_height; |
203 | bytes_per_pixel); | ||
204 | 210 | ||
205 | if (0 == *count) | 211 | if (0 == *count) |
206 | *count = 2; | 212 | *count = 2; |
207 | 213 | ||
208 | if (pcdev->video_limit) { | 214 | if (pcdev->video_limit) { |
209 | while (*size * *count > pcdev->video_limit) | 215 | while (PAGE_ALIGN(*size) * *count > pcdev->video_limit) |
210 | (*count)--; | 216 | (*count)--; |
211 | } | 217 | } |
212 | 218 | ||
@@ -249,10 +255,13 @@ static int sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev) | |||
249 | { | 255 | { |
250 | struct soc_camera_device *icd = pcdev->icd; | 256 | struct soc_camera_device *icd = pcdev->icd; |
251 | dma_addr_t phys_addr_top, phys_addr_bottom; | 257 | dma_addr_t phys_addr_top, phys_addr_bottom; |
258 | unsigned long top1, top2; | ||
259 | unsigned long bottom1, bottom2; | ||
252 | u32 status; | 260 | u32 status; |
253 | int ret = 0; | 261 | int ret = 0; |
254 | 262 | ||
255 | /* The hardware is _very_ picky about this sequence. Especially | 263 | /* |
264 | * The hardware is _very_ picky about this sequence. Especially | ||
256 | * the CEU_CETCR_MAGIC value. It seems like we need to acknowledge | 265 | * the CEU_CETCR_MAGIC value. It seems like we need to acknowledge |
257 | * several not-so-well documented interrupt sources in CETCR. | 266 | * several not-so-well documented interrupt sources in CETCR. |
258 | */ | 267 | */ |
@@ -276,25 +285,36 @@ static int sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev) | |||
276 | if (!pcdev->active) | 285 | if (!pcdev->active) |
277 | return ret; | 286 | return ret; |
278 | 287 | ||
288 | if (V4L2_FIELD_INTERLACED_BT == pcdev->field) { | ||
289 | top1 = CDBYR; | ||
290 | top2 = CDBCR; | ||
291 | bottom1 = CDAYR; | ||
292 | bottom2 = CDACR; | ||
293 | } else { | ||
294 | top1 = CDAYR; | ||
295 | top2 = CDACR; | ||
296 | bottom1 = CDBYR; | ||
297 | bottom2 = CDBCR; | ||
298 | } | ||
299 | |||
279 | phys_addr_top = videobuf_to_dma_contig(pcdev->active); | 300 | phys_addr_top = videobuf_to_dma_contig(pcdev->active); |
280 | ceu_write(pcdev, CDAYR, phys_addr_top); | 301 | ceu_write(pcdev, top1, phys_addr_top); |
281 | if (pcdev->is_interlaced) { | 302 | if (V4L2_FIELD_NONE != pcdev->field) { |
282 | phys_addr_bottom = phys_addr_top + icd->user_width; | 303 | phys_addr_bottom = phys_addr_top + icd->user_width; |
283 | ceu_write(pcdev, CDBYR, phys_addr_bottom); | 304 | ceu_write(pcdev, bottom1, phys_addr_bottom); |
284 | } | 305 | } |
285 | 306 | ||
286 | switch (icd->current_fmt->fourcc) { | 307 | switch (icd->current_fmt->host_fmt->fourcc) { |
287 | case V4L2_PIX_FMT_NV12: | 308 | case V4L2_PIX_FMT_NV12: |
288 | case V4L2_PIX_FMT_NV21: | 309 | case V4L2_PIX_FMT_NV21: |
289 | case V4L2_PIX_FMT_NV16: | 310 | case V4L2_PIX_FMT_NV16: |
290 | case V4L2_PIX_FMT_NV61: | 311 | case V4L2_PIX_FMT_NV61: |
291 | phys_addr_top += icd->user_width * | 312 | phys_addr_top += icd->user_width * |
292 | icd->user_height; | 313 | icd->user_height; |
293 | ceu_write(pcdev, CDACR, phys_addr_top); | 314 | ceu_write(pcdev, top2, phys_addr_top); |
294 | if (pcdev->is_interlaced) { | 315 | if (V4L2_FIELD_NONE != pcdev->field) { |
295 | phys_addr_bottom = phys_addr_top + | 316 | phys_addr_bottom = phys_addr_top + icd->user_width; |
296 | icd->user_width; | 317 | ceu_write(pcdev, bottom2, phys_addr_bottom); |
297 | ceu_write(pcdev, CDBCR, phys_addr_bottom); | ||
298 | } | 318 | } |
299 | } | 319 | } |
300 | 320 | ||
@@ -310,8 +330,13 @@ static int sh_mobile_ceu_videobuf_prepare(struct videobuf_queue *vq, | |||
310 | { | 330 | { |
311 | struct soc_camera_device *icd = vq->priv_data; | 331 | struct soc_camera_device *icd = vq->priv_data; |
312 | struct sh_mobile_ceu_buffer *buf; | 332 | struct sh_mobile_ceu_buffer *buf; |
333 | int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, | ||
334 | icd->current_fmt->host_fmt); | ||
313 | int ret; | 335 | int ret; |
314 | 336 | ||
337 | if (bytes_per_line < 0) | ||
338 | return bytes_per_line; | ||
339 | |||
315 | buf = container_of(vb, struct sh_mobile_ceu_buffer, vb); | 340 | buf = container_of(vb, struct sh_mobile_ceu_buffer, vb); |
316 | 341 | ||
317 | dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %zd\n", __func__, | 342 | dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %zd\n", __func__, |
@@ -321,25 +346,27 @@ static int sh_mobile_ceu_videobuf_prepare(struct videobuf_queue *vq, | |||
321 | WARN_ON(!list_empty(&vb->queue)); | 346 | WARN_ON(!list_empty(&vb->queue)); |
322 | 347 | ||
323 | #ifdef DEBUG | 348 | #ifdef DEBUG |
324 | /* This can be useful if you want to see if we actually fill | 349 | /* |
325 | * the buffer with something */ | 350 | * This can be useful if you want to see if we actually fill |
351 | * the buffer with something | ||
352 | */ | ||
326 | memset((void *)vb->baddr, 0xaa, vb->bsize); | 353 | memset((void *)vb->baddr, 0xaa, vb->bsize); |
327 | #endif | 354 | #endif |
328 | 355 | ||
329 | BUG_ON(NULL == icd->current_fmt); | 356 | BUG_ON(NULL == icd->current_fmt); |
330 | 357 | ||
331 | if (buf->fmt != icd->current_fmt || | 358 | if (buf->code != icd->current_fmt->code || |
332 | vb->width != icd->user_width || | 359 | vb->width != icd->user_width || |
333 | vb->height != icd->user_height || | 360 | vb->height != icd->user_height || |
334 | vb->field != field) { | 361 | vb->field != field) { |
335 | buf->fmt = icd->current_fmt; | 362 | buf->code = icd->current_fmt->code; |
336 | vb->width = icd->user_width; | 363 | vb->width = icd->user_width; |
337 | vb->height = icd->user_height; | 364 | vb->height = icd->user_height; |
338 | vb->field = field; | 365 | vb->field = field; |
339 | vb->state = VIDEOBUF_NEEDS_INIT; | 366 | vb->state = VIDEOBUF_NEEDS_INIT; |
340 | } | 367 | } |
341 | 368 | ||
342 | vb->size = vb->width * vb->height * ((buf->fmt->depth + 7) >> 3); | 369 | vb->size = vb->height * bytes_per_line; |
343 | if (0 != vb->baddr && vb->bsize < vb->size) { | 370 | if (0 != vb->baddr && vb->bsize < vb->size) { |
344 | ret = -EINVAL; | 371 | ret = -EINVAL; |
345 | goto out; | 372 | goto out; |
@@ -456,6 +483,7 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd) | |||
456 | { | 483 | { |
457 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | 484 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); |
458 | struct sh_mobile_ceu_dev *pcdev = ici->priv; | 485 | struct sh_mobile_ceu_dev *pcdev = ici->priv; |
486 | int ret; | ||
459 | 487 | ||
460 | if (pcdev->icd) | 488 | if (pcdev->icd) |
461 | return -EBUSY; | 489 | return -EBUSY; |
@@ -466,9 +494,11 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd) | |||
466 | 494 | ||
467 | pm_runtime_get_sync(ici->v4l2_dev.dev); | 495 | pm_runtime_get_sync(ici->v4l2_dev.dev); |
468 | 496 | ||
469 | pcdev->icd = icd; | 497 | ret = sh_mobile_ceu_soft_reset(pcdev); |
498 | if (!ret) | ||
499 | pcdev->icd = icd; | ||
470 | 500 | ||
471 | return sh_mobile_ceu_soft_reset(pcdev); | 501 | return ret; |
472 | } | 502 | } |
473 | 503 | ||
474 | /* Called with .video_lock held */ | 504 | /* Called with .video_lock held */ |
@@ -558,24 +588,35 @@ static void sh_mobile_ceu_set_rect(struct soc_camera_device *icd, | |||
558 | in_width *= 2; | 588 | in_width *= 2; |
559 | left_offset *= 2; | 589 | left_offset *= 2; |
560 | } | 590 | } |
561 | width = cdwdr_width = out_width; | 591 | width = out_width; |
592 | cdwdr_width = out_width; | ||
562 | } else { | 593 | } else { |
563 | unsigned int w_factor = (icd->current_fmt->depth + 7) >> 3; | 594 | int bytes_per_line = soc_mbus_bytes_per_line(out_width, |
595 | icd->current_fmt->host_fmt); | ||
596 | unsigned int w_factor; | ||
564 | 597 | ||
565 | width = out_width * w_factor / 2; | 598 | width = out_width; |
566 | 599 | ||
567 | if (!pcdev->is_16bit) | 600 | switch (icd->current_fmt->host_fmt->packing) { |
568 | w_factor *= 2; | 601 | case SOC_MBUS_PACKING_2X8_PADHI: |
602 | w_factor = 2; | ||
603 | break; | ||
604 | default: | ||
605 | w_factor = 1; | ||
606 | } | ||
569 | 607 | ||
570 | in_width = rect->width * w_factor / 2; | 608 | in_width = rect->width * w_factor; |
571 | left_offset = left_offset * w_factor / 2; | 609 | left_offset = left_offset * w_factor; |
572 | 610 | ||
573 | cdwdr_width = width * 2; | 611 | if (bytes_per_line < 0) |
612 | cdwdr_width = out_width; | ||
613 | else | ||
614 | cdwdr_width = bytes_per_line; | ||
574 | } | 615 | } |
575 | 616 | ||
576 | height = out_height; | 617 | height = out_height; |
577 | in_height = rect->height; | 618 | in_height = rect->height; |
578 | if (pcdev->is_interlaced) { | 619 | if (V4L2_FIELD_NONE != pcdev->field) { |
579 | height /= 2; | 620 | height /= 2; |
580 | in_height /= 2; | 621 | in_height /= 2; |
581 | top_offset /= 2; | 622 | top_offset /= 2; |
@@ -646,6 +687,23 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, | |||
646 | if (!common_flags) | 687 | if (!common_flags) |
647 | return -EINVAL; | 688 | return -EINVAL; |
648 | 689 | ||
690 | /* Make choises, based on platform preferences */ | ||
691 | if ((common_flags & SOCAM_HSYNC_ACTIVE_HIGH) && | ||
692 | (common_flags & SOCAM_HSYNC_ACTIVE_LOW)) { | ||
693 | if (pcdev->pdata->flags & SH_CEU_FLAG_HSYNC_LOW) | ||
694 | common_flags &= ~SOCAM_HSYNC_ACTIVE_HIGH; | ||
695 | else | ||
696 | common_flags &= ~SOCAM_HSYNC_ACTIVE_LOW; | ||
697 | } | ||
698 | |||
699 | if ((common_flags & SOCAM_VSYNC_ACTIVE_HIGH) && | ||
700 | (common_flags & SOCAM_VSYNC_ACTIVE_LOW)) { | ||
701 | if (pcdev->pdata->flags & SH_CEU_FLAG_VSYNC_LOW) | ||
702 | common_flags &= ~SOCAM_VSYNC_ACTIVE_HIGH; | ||
703 | else | ||
704 | common_flags &= ~SOCAM_VSYNC_ACTIVE_LOW; | ||
705 | } | ||
706 | |||
649 | ret = icd->ops->set_bus_param(icd, common_flags); | 707 | ret = icd->ops->set_bus_param(icd, common_flags); |
650 | if (ret < 0) | 708 | if (ret < 0) |
651 | return ret; | 709 | return ret; |
@@ -667,24 +725,24 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, | |||
667 | value = 0x00000010; /* data fetch by default */ | 725 | value = 0x00000010; /* data fetch by default */ |
668 | yuv_lineskip = 0; | 726 | yuv_lineskip = 0; |
669 | 727 | ||
670 | switch (icd->current_fmt->fourcc) { | 728 | switch (icd->current_fmt->host_fmt->fourcc) { |
671 | case V4L2_PIX_FMT_NV12: | 729 | case V4L2_PIX_FMT_NV12: |
672 | case V4L2_PIX_FMT_NV21: | 730 | case V4L2_PIX_FMT_NV21: |
673 | yuv_lineskip = 1; /* skip for NV12/21, no skip for NV16/61 */ | 731 | yuv_lineskip = 1; /* skip for NV12/21, no skip for NV16/61 */ |
674 | /* fall-through */ | 732 | /* fall-through */ |
675 | case V4L2_PIX_FMT_NV16: | 733 | case V4L2_PIX_FMT_NV16: |
676 | case V4L2_PIX_FMT_NV61: | 734 | case V4L2_PIX_FMT_NV61: |
677 | switch (cam->camera_fmt->fourcc) { | 735 | switch (cam->code) { |
678 | case V4L2_PIX_FMT_UYVY: | 736 | case V4L2_MBUS_FMT_YUYV8_2X8_BE: |
679 | value = 0x00000000; /* Cb0, Y0, Cr0, Y1 */ | 737 | value = 0x00000000; /* Cb0, Y0, Cr0, Y1 */ |
680 | break; | 738 | break; |
681 | case V4L2_PIX_FMT_VYUY: | 739 | case V4L2_MBUS_FMT_YVYU8_2X8_BE: |
682 | value = 0x00000100; /* Cr0, Y0, Cb0, Y1 */ | 740 | value = 0x00000100; /* Cr0, Y0, Cb0, Y1 */ |
683 | break; | 741 | break; |
684 | case V4L2_PIX_FMT_YUYV: | 742 | case V4L2_MBUS_FMT_YUYV8_2X8_LE: |
685 | value = 0x00000200; /* Y0, Cb0, Y1, Cr0 */ | 743 | value = 0x00000200; /* Y0, Cb0, Y1, Cr0 */ |
686 | break; | 744 | break; |
687 | case V4L2_PIX_FMT_YVYU: | 745 | case V4L2_MBUS_FMT_YVYU8_2X8_LE: |
688 | value = 0x00000300; /* Y0, Cr0, Y1, Cb0 */ | 746 | value = 0x00000300; /* Y0, Cr0, Y1, Cb0 */ |
689 | break; | 747 | break; |
690 | default: | 748 | default: |
@@ -692,8 +750,8 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, | |||
692 | } | 750 | } |
693 | } | 751 | } |
694 | 752 | ||
695 | if (icd->current_fmt->fourcc == V4L2_PIX_FMT_NV21 || | 753 | if (icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_NV21 || |
696 | icd->current_fmt->fourcc == V4L2_PIX_FMT_NV61) | 754 | icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_NV61) |
697 | value ^= 0x00000100; /* swap U, V to change from NV1x->NVx1 */ | 755 | value ^= 0x00000100; /* swap U, V to change from NV1x->NVx1 */ |
698 | 756 | ||
699 | value |= common_flags & SOCAM_VSYNC_ACTIVE_LOW ? 1 << 1 : 0; | 757 | value |= common_flags & SOCAM_VSYNC_ACTIVE_LOW ? 1 << 1 : 0; |
@@ -702,14 +760,27 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, | |||
702 | ceu_write(pcdev, CAMCR, value); | 760 | ceu_write(pcdev, CAMCR, value); |
703 | 761 | ||
704 | ceu_write(pcdev, CAPCR, 0x00300000); | 762 | ceu_write(pcdev, CAPCR, 0x00300000); |
705 | ceu_write(pcdev, CAIFR, pcdev->is_interlaced ? 0x101 : 0); | 763 | |
764 | switch (pcdev->field) { | ||
765 | case V4L2_FIELD_INTERLACED_TB: | ||
766 | value = 0x101; | ||
767 | break; | ||
768 | case V4L2_FIELD_INTERLACED_BT: | ||
769 | value = 0x102; | ||
770 | break; | ||
771 | default: | ||
772 | value = 0; | ||
773 | break; | ||
774 | } | ||
775 | ceu_write(pcdev, CAIFR, value); | ||
706 | 776 | ||
707 | sh_mobile_ceu_set_rect(icd, icd->user_width, icd->user_height); | 777 | sh_mobile_ceu_set_rect(icd, icd->user_width, icd->user_height); |
708 | mdelay(1); | 778 | mdelay(1); |
709 | 779 | ||
710 | ceu_write(pcdev, CFLCR, pcdev->cflcr); | 780 | ceu_write(pcdev, CFLCR, pcdev->cflcr); |
711 | 781 | ||
712 | /* A few words about byte order (observed in Big Endian mode) | 782 | /* |
783 | * A few words about byte order (observed in Big Endian mode) | ||
713 | * | 784 | * |
714 | * In data fetch mode bytes are received in chunks of 8 bytes. | 785 | * In data fetch mode bytes are received in chunks of 8 bytes. |
715 | * D0, D1, D2, D3, D4, D5, D6, D7 (D0 received first) | 786 | * D0, D1, D2, D3, D4, D5, D6, D7 (D0 received first) |
@@ -739,7 +810,8 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, | |||
739 | return 0; | 810 | return 0; |
740 | } | 811 | } |
741 | 812 | ||
742 | static int sh_mobile_ceu_try_bus_param(struct soc_camera_device *icd) | 813 | static int sh_mobile_ceu_try_bus_param(struct soc_camera_device *icd, |
814 | unsigned char buswidth) | ||
743 | { | 815 | { |
744 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | 816 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); |
745 | struct sh_mobile_ceu_dev *pcdev = ici->priv; | 817 | struct sh_mobile_ceu_dev *pcdev = ici->priv; |
@@ -748,48 +820,75 @@ static int sh_mobile_ceu_try_bus_param(struct soc_camera_device *icd) | |||
748 | camera_flags = icd->ops->query_bus_param(icd); | 820 | camera_flags = icd->ops->query_bus_param(icd); |
749 | common_flags = soc_camera_bus_param_compatible(camera_flags, | 821 | common_flags = soc_camera_bus_param_compatible(camera_flags, |
750 | make_bus_param(pcdev)); | 822 | make_bus_param(pcdev)); |
751 | if (!common_flags) | 823 | if (!common_flags || buswidth > 16 || |
824 | (buswidth > 8 && !(common_flags & SOCAM_DATAWIDTH_16))) | ||
752 | return -EINVAL; | 825 | return -EINVAL; |
753 | 826 | ||
754 | return 0; | 827 | return 0; |
755 | } | 828 | } |
756 | 829 | ||
757 | static const struct soc_camera_data_format sh_mobile_ceu_formats[] = { | 830 | static const struct soc_mbus_pixelfmt sh_mobile_ceu_formats[] = { |
758 | { | ||
759 | .name = "NV12", | ||
760 | .depth = 12, | ||
761 | .fourcc = V4L2_PIX_FMT_NV12, | ||
762 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
763 | }, | ||
764 | { | ||
765 | .name = "NV21", | ||
766 | .depth = 12, | ||
767 | .fourcc = V4L2_PIX_FMT_NV21, | ||
768 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
769 | }, | ||
770 | { | ||
771 | .name = "NV16", | ||
772 | .depth = 16, | ||
773 | .fourcc = V4L2_PIX_FMT_NV16, | ||
774 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
775 | }, | ||
776 | { | 831 | { |
777 | .name = "NV61", | 832 | .fourcc = V4L2_PIX_FMT_NV12, |
778 | .depth = 16, | 833 | .name = "NV12", |
779 | .fourcc = V4L2_PIX_FMT_NV61, | 834 | .bits_per_sample = 12, |
780 | .colorspace = V4L2_COLORSPACE_JPEG, | 835 | .packing = SOC_MBUS_PACKING_NONE, |
836 | .order = SOC_MBUS_ORDER_LE, | ||
837 | }, { | ||
838 | .fourcc = V4L2_PIX_FMT_NV21, | ||
839 | .name = "NV21", | ||
840 | .bits_per_sample = 12, | ||
841 | .packing = SOC_MBUS_PACKING_NONE, | ||
842 | .order = SOC_MBUS_ORDER_LE, | ||
843 | }, { | ||
844 | .fourcc = V4L2_PIX_FMT_NV16, | ||
845 | .name = "NV16", | ||
846 | .bits_per_sample = 16, | ||
847 | .packing = SOC_MBUS_PACKING_NONE, | ||
848 | .order = SOC_MBUS_ORDER_LE, | ||
849 | }, { | ||
850 | .fourcc = V4L2_PIX_FMT_NV61, | ||
851 | .name = "NV61", | ||
852 | .bits_per_sample = 16, | ||
853 | .packing = SOC_MBUS_PACKING_NONE, | ||
854 | .order = SOC_MBUS_ORDER_LE, | ||
781 | }, | 855 | }, |
782 | }; | 856 | }; |
783 | 857 | ||
858 | /* This will be corrected as we get more formats */ | ||
859 | static bool sh_mobile_ceu_packing_supported(const struct soc_mbus_pixelfmt *fmt) | ||
860 | { | ||
861 | return fmt->packing == SOC_MBUS_PACKING_NONE || | ||
862 | (fmt->bits_per_sample == 8 && | ||
863 | fmt->packing == SOC_MBUS_PACKING_2X8_PADHI) || | ||
864 | (fmt->bits_per_sample > 8 && | ||
865 | fmt->packing == SOC_MBUS_PACKING_EXTEND16); | ||
866 | } | ||
867 | |||
784 | static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx, | 868 | static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx, |
785 | struct soc_camera_format_xlate *xlate) | 869 | struct soc_camera_format_xlate *xlate) |
786 | { | 870 | { |
871 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | ||
787 | struct device *dev = icd->dev.parent; | 872 | struct device *dev = icd->dev.parent; |
788 | int ret, k, n; | 873 | int ret, k, n; |
789 | int formats = 0; | 874 | int formats = 0; |
790 | struct sh_mobile_ceu_cam *cam; | 875 | struct sh_mobile_ceu_cam *cam; |
876 | enum v4l2_mbus_pixelcode code; | ||
877 | const struct soc_mbus_pixelfmt *fmt; | ||
791 | 878 | ||
792 | ret = sh_mobile_ceu_try_bus_param(icd); | 879 | ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code); |
880 | if (ret < 0) | ||
881 | /* No more formats */ | ||
882 | return 0; | ||
883 | |||
884 | fmt = soc_mbus_get_fmtdesc(code); | ||
885 | if (!fmt) { | ||
886 | dev_err(icd->dev.parent, | ||
887 | "Invalid format code #%d: %d\n", idx, code); | ||
888 | return -EINVAL; | ||
889 | } | ||
890 | |||
891 | ret = sh_mobile_ceu_try_bus_param(icd, fmt->bits_per_sample); | ||
793 | if (ret < 0) | 892 | if (ret < 0) |
794 | return 0; | 893 | return 0; |
795 | 894 | ||
@@ -807,13 +906,13 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx, | |||
807 | if (!idx) | 906 | if (!idx) |
808 | cam->extra_fmt = NULL; | 907 | cam->extra_fmt = NULL; |
809 | 908 | ||
810 | switch (icd->formats[idx].fourcc) { | 909 | switch (code) { |
811 | case V4L2_PIX_FMT_UYVY: | 910 | case V4L2_MBUS_FMT_YUYV8_2X8_BE: |
812 | case V4L2_PIX_FMT_VYUY: | 911 | case V4L2_MBUS_FMT_YVYU8_2X8_BE: |
813 | case V4L2_PIX_FMT_YUYV: | 912 | case V4L2_MBUS_FMT_YUYV8_2X8_LE: |
814 | case V4L2_PIX_FMT_YVYU: | 913 | case V4L2_MBUS_FMT_YVYU8_2X8_LE: |
815 | if (cam->extra_fmt) | 914 | if (cam->extra_fmt) |
816 | goto add_single_format; | 915 | break; |
817 | 916 | ||
818 | /* | 917 | /* |
819 | * Our case is simple so far: for any of the above four camera | 918 | * Our case is simple so far: for any of the above four camera |
@@ -824,32 +923,31 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx, | |||
824 | * the host_priv pointer and check whether the format you're | 923 | * the host_priv pointer and check whether the format you're |
825 | * going to add now is already there. | 924 | * going to add now is already there. |
826 | */ | 925 | */ |
827 | cam->extra_fmt = (void *)sh_mobile_ceu_formats; | 926 | cam->extra_fmt = sh_mobile_ceu_formats; |
828 | 927 | ||
829 | n = ARRAY_SIZE(sh_mobile_ceu_formats); | 928 | n = ARRAY_SIZE(sh_mobile_ceu_formats); |
830 | formats += n; | 929 | formats += n; |
831 | for (k = 0; xlate && k < n; k++) { | 930 | for (k = 0; xlate && k < n; k++) { |
832 | xlate->host_fmt = &sh_mobile_ceu_formats[k]; | 931 | xlate->host_fmt = &sh_mobile_ceu_formats[k]; |
833 | xlate->cam_fmt = icd->formats + idx; | 932 | xlate->code = code; |
834 | xlate->buswidth = icd->formats[idx].depth; | ||
835 | xlate++; | 933 | xlate++; |
836 | dev_dbg(dev, "Providing format %s using %s\n", | 934 | dev_dbg(dev, "Providing format %s using code %d\n", |
837 | sh_mobile_ceu_formats[k].name, | 935 | sh_mobile_ceu_formats[k].name, code); |
838 | icd->formats[idx].name); | ||
839 | } | 936 | } |
937 | break; | ||
840 | default: | 938 | default: |
841 | add_single_format: | 939 | if (!sh_mobile_ceu_packing_supported(fmt)) |
842 | /* Generic pass-through */ | 940 | return 0; |
843 | formats++; | 941 | } |
844 | if (xlate) { | 942 | |
845 | xlate->host_fmt = icd->formats + idx; | 943 | /* Generic pass-through */ |
846 | xlate->cam_fmt = icd->formats + idx; | 944 | formats++; |
847 | xlate->buswidth = icd->formats[idx].depth; | 945 | if (xlate) { |
848 | xlate++; | 946 | xlate->host_fmt = fmt; |
849 | dev_dbg(dev, | 947 | xlate->code = code; |
850 | "Providing format %s in pass-through mode\n", | 948 | xlate++; |
851 | icd->formats[idx].name); | 949 | dev_dbg(dev, "Providing format %s in pass-through mode\n", |
852 | } | 950 | xlate->host_fmt->name); |
853 | } | 951 | } |
854 | 952 | ||
855 | return formats; | 953 | return formats; |
@@ -1029,17 +1127,15 @@ static int client_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *crop, | |||
1029 | static int get_camera_scales(struct v4l2_subdev *sd, struct v4l2_rect *rect, | 1127 | static int get_camera_scales(struct v4l2_subdev *sd, struct v4l2_rect *rect, |
1030 | unsigned int *scale_h, unsigned int *scale_v) | 1128 | unsigned int *scale_h, unsigned int *scale_v) |
1031 | { | 1129 | { |
1032 | struct v4l2_format f; | 1130 | struct v4l2_mbus_framefmt mf; |
1033 | int ret; | 1131 | int ret; |
1034 | 1132 | ||
1035 | f.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 1133 | ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf); |
1036 | |||
1037 | ret = v4l2_subdev_call(sd, video, g_fmt, &f); | ||
1038 | if (ret < 0) | 1134 | if (ret < 0) |
1039 | return ret; | 1135 | return ret; |
1040 | 1136 | ||
1041 | *scale_h = calc_generic_scale(rect->width, f.fmt.pix.width); | 1137 | *scale_h = calc_generic_scale(rect->width, mf.width); |
1042 | *scale_v = calc_generic_scale(rect->height, f.fmt.pix.height); | 1138 | *scale_v = calc_generic_scale(rect->height, mf.height); |
1043 | 1139 | ||
1044 | return 0; | 1140 | return 0; |
1045 | } | 1141 | } |
@@ -1054,32 +1150,29 @@ static int get_camera_subwin(struct soc_camera_device *icd, | |||
1054 | if (!ceu_rect->width) { | 1150 | if (!ceu_rect->width) { |
1055 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | 1151 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
1056 | struct device *dev = icd->dev.parent; | 1152 | struct device *dev = icd->dev.parent; |
1057 | struct v4l2_format f; | 1153 | struct v4l2_mbus_framefmt mf; |
1058 | struct v4l2_pix_format *pix = &f.fmt.pix; | ||
1059 | int ret; | 1154 | int ret; |
1060 | /* First time */ | 1155 | /* First time */ |
1061 | 1156 | ||
1062 | f.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 1157 | ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf); |
1063 | |||
1064 | ret = v4l2_subdev_call(sd, video, g_fmt, &f); | ||
1065 | if (ret < 0) | 1158 | if (ret < 0) |
1066 | return ret; | 1159 | return ret; |
1067 | 1160 | ||
1068 | dev_geo(dev, "camera fmt %ux%u\n", pix->width, pix->height); | 1161 | dev_geo(dev, "camera fmt %ux%u\n", mf.width, mf.height); |
1069 | 1162 | ||
1070 | if (pix->width > 2560) { | 1163 | if (mf.width > 2560) { |
1071 | ceu_rect->width = 2560; | 1164 | ceu_rect->width = 2560; |
1072 | ceu_rect->left = (pix->width - 2560) / 2; | 1165 | ceu_rect->left = (mf.width - 2560) / 2; |
1073 | } else { | 1166 | } else { |
1074 | ceu_rect->width = pix->width; | 1167 | ceu_rect->width = mf.width; |
1075 | ceu_rect->left = 0; | 1168 | ceu_rect->left = 0; |
1076 | } | 1169 | } |
1077 | 1170 | ||
1078 | if (pix->height > 1920) { | 1171 | if (mf.height > 1920) { |
1079 | ceu_rect->height = 1920; | 1172 | ceu_rect->height = 1920; |
1080 | ceu_rect->top = (pix->height - 1920) / 2; | 1173 | ceu_rect->top = (mf.height - 1920) / 2; |
1081 | } else { | 1174 | } else { |
1082 | ceu_rect->height = pix->height; | 1175 | ceu_rect->height = mf.height; |
1083 | ceu_rect->top = 0; | 1176 | ceu_rect->top = 0; |
1084 | } | 1177 | } |
1085 | 1178 | ||
@@ -1096,13 +1189,12 @@ static int get_camera_subwin(struct soc_camera_device *icd, | |||
1096 | return 0; | 1189 | return 0; |
1097 | } | 1190 | } |
1098 | 1191 | ||
1099 | static int client_s_fmt(struct soc_camera_device *icd, struct v4l2_format *f, | 1192 | static int client_s_fmt(struct soc_camera_device *icd, |
1100 | bool ceu_can_scale) | 1193 | struct v4l2_mbus_framefmt *mf, bool ceu_can_scale) |
1101 | { | 1194 | { |
1102 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | 1195 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
1103 | struct device *dev = icd->dev.parent; | 1196 | struct device *dev = icd->dev.parent; |
1104 | struct v4l2_pix_format *pix = &f->fmt.pix; | 1197 | unsigned int width = mf->width, height = mf->height, tmp_w, tmp_h; |
1105 | unsigned int width = pix->width, height = pix->height, tmp_w, tmp_h; | ||
1106 | unsigned int max_width, max_height; | 1198 | unsigned int max_width, max_height; |
1107 | struct v4l2_cropcap cap; | 1199 | struct v4l2_cropcap cap; |
1108 | int ret; | 1200 | int ret; |
@@ -1116,29 +1208,29 @@ static int client_s_fmt(struct soc_camera_device *icd, struct v4l2_format *f, | |||
1116 | max_width = min(cap.bounds.width, 2560); | 1208 | max_width = min(cap.bounds.width, 2560); |
1117 | max_height = min(cap.bounds.height, 1920); | 1209 | max_height = min(cap.bounds.height, 1920); |
1118 | 1210 | ||
1119 | ret = v4l2_subdev_call(sd, video, s_fmt, f); | 1211 | ret = v4l2_subdev_call(sd, video, s_mbus_fmt, mf); |
1120 | if (ret < 0) | 1212 | if (ret < 0) |
1121 | return ret; | 1213 | return ret; |
1122 | 1214 | ||
1123 | dev_geo(dev, "camera scaled to %ux%u\n", pix->width, pix->height); | 1215 | dev_geo(dev, "camera scaled to %ux%u\n", mf->width, mf->height); |
1124 | 1216 | ||
1125 | if ((width == pix->width && height == pix->height) || !ceu_can_scale) | 1217 | if ((width == mf->width && height == mf->height) || !ceu_can_scale) |
1126 | return 0; | 1218 | return 0; |
1127 | 1219 | ||
1128 | /* Camera set a format, but geometry is not precise, try to improve */ | 1220 | /* Camera set a format, but geometry is not precise, try to improve */ |
1129 | tmp_w = pix->width; | 1221 | tmp_w = mf->width; |
1130 | tmp_h = pix->height; | 1222 | tmp_h = mf->height; |
1131 | 1223 | ||
1132 | /* width <= max_width && height <= max_height - guaranteed by try_fmt */ | 1224 | /* width <= max_width && height <= max_height - guaranteed by try_fmt */ |
1133 | while ((width > tmp_w || height > tmp_h) && | 1225 | while ((width > tmp_w || height > tmp_h) && |
1134 | tmp_w < max_width && tmp_h < max_height) { | 1226 | tmp_w < max_width && tmp_h < max_height) { |
1135 | tmp_w = min(2 * tmp_w, max_width); | 1227 | tmp_w = min(2 * tmp_w, max_width); |
1136 | tmp_h = min(2 * tmp_h, max_height); | 1228 | tmp_h = min(2 * tmp_h, max_height); |
1137 | pix->width = tmp_w; | 1229 | mf->width = tmp_w; |
1138 | pix->height = tmp_h; | 1230 | mf->height = tmp_h; |
1139 | ret = v4l2_subdev_call(sd, video, s_fmt, f); | 1231 | ret = v4l2_subdev_call(sd, video, s_mbus_fmt, mf); |
1140 | dev_geo(dev, "Camera scaled to %ux%u\n", | 1232 | dev_geo(dev, "Camera scaled to %ux%u\n", |
1141 | pix->width, pix->height); | 1233 | mf->width, mf->height); |
1142 | if (ret < 0) { | 1234 | if (ret < 0) { |
1143 | /* This shouldn't happen */ | 1235 | /* This shouldn't happen */ |
1144 | dev_err(dev, "Client failed to set format: %d\n", ret); | 1236 | dev_err(dev, "Client failed to set format: %d\n", ret); |
@@ -1156,27 +1248,26 @@ static int client_s_fmt(struct soc_camera_device *icd, struct v4l2_format *f, | |||
1156 | */ | 1248 | */ |
1157 | static int client_scale(struct soc_camera_device *icd, struct v4l2_rect *rect, | 1249 | static int client_scale(struct soc_camera_device *icd, struct v4l2_rect *rect, |
1158 | struct v4l2_rect *sub_rect, struct v4l2_rect *ceu_rect, | 1250 | struct v4l2_rect *sub_rect, struct v4l2_rect *ceu_rect, |
1159 | struct v4l2_format *f, bool ceu_can_scale) | 1251 | struct v4l2_mbus_framefmt *mf, bool ceu_can_scale) |
1160 | { | 1252 | { |
1161 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | 1253 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
1162 | struct sh_mobile_ceu_cam *cam = icd->host_priv; | 1254 | struct sh_mobile_ceu_cam *cam = icd->host_priv; |
1163 | struct device *dev = icd->dev.parent; | 1255 | struct device *dev = icd->dev.parent; |
1164 | struct v4l2_format f_tmp = *f; | 1256 | struct v4l2_mbus_framefmt mf_tmp = *mf; |
1165 | struct v4l2_pix_format *pix_tmp = &f_tmp.fmt.pix; | ||
1166 | unsigned int scale_h, scale_v; | 1257 | unsigned int scale_h, scale_v; |
1167 | int ret; | 1258 | int ret; |
1168 | 1259 | ||
1169 | /* 5. Apply iterative camera S_FMT for camera user window. */ | 1260 | /* 5. Apply iterative camera S_FMT for camera user window. */ |
1170 | ret = client_s_fmt(icd, &f_tmp, ceu_can_scale); | 1261 | ret = client_s_fmt(icd, &mf_tmp, ceu_can_scale); |
1171 | if (ret < 0) | 1262 | if (ret < 0) |
1172 | return ret; | 1263 | return ret; |
1173 | 1264 | ||
1174 | dev_geo(dev, "5: camera scaled to %ux%u\n", | 1265 | dev_geo(dev, "5: camera scaled to %ux%u\n", |
1175 | pix_tmp->width, pix_tmp->height); | 1266 | mf_tmp.width, mf_tmp.height); |
1176 | 1267 | ||
1177 | /* 6. Retrieve camera output window (g_fmt) */ | 1268 | /* 6. Retrieve camera output window (g_fmt) */ |
1178 | 1269 | ||
1179 | /* unneeded - it is already in "f_tmp" */ | 1270 | /* unneeded - it is already in "mf_tmp" */ |
1180 | 1271 | ||
1181 | /* 7. Calculate new camera scales. */ | 1272 | /* 7. Calculate new camera scales. */ |
1182 | ret = get_camera_scales(sd, rect, &scale_h, &scale_v); | 1273 | ret = get_camera_scales(sd, rect, &scale_h, &scale_v); |
@@ -1185,10 +1276,11 @@ static int client_scale(struct soc_camera_device *icd, struct v4l2_rect *rect, | |||
1185 | 1276 | ||
1186 | dev_geo(dev, "7: camera scales %u:%u\n", scale_h, scale_v); | 1277 | dev_geo(dev, "7: camera scales %u:%u\n", scale_h, scale_v); |
1187 | 1278 | ||
1188 | cam->cam_width = pix_tmp->width; | 1279 | cam->cam_width = mf_tmp.width; |
1189 | cam->cam_height = pix_tmp->height; | 1280 | cam->cam_height = mf_tmp.height; |
1190 | f->fmt.pix.width = pix_tmp->width; | 1281 | mf->width = mf_tmp.width; |
1191 | f->fmt.pix.height = pix_tmp->height; | 1282 | mf->height = mf_tmp.height; |
1283 | mf->colorspace = mf_tmp.colorspace; | ||
1192 | 1284 | ||
1193 | /* | 1285 | /* |
1194 | * 8. Calculate new CEU crop - apply camera scales to previously | 1286 | * 8. Calculate new CEU crop - apply camera scales to previously |
@@ -1252,8 +1344,7 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, | |||
1252 | struct v4l2_rect *cam_rect = &cam_crop.c, *ceu_rect = &cam->ceu_rect; | 1344 | struct v4l2_rect *cam_rect = &cam_crop.c, *ceu_rect = &cam->ceu_rect; |
1253 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | 1345 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
1254 | struct device *dev = icd->dev.parent; | 1346 | struct device *dev = icd->dev.parent; |
1255 | struct v4l2_format f; | 1347 | struct v4l2_mbus_framefmt mf; |
1256 | struct v4l2_pix_format *pix = &f.fmt.pix; | ||
1257 | unsigned int scale_comb_h, scale_comb_v, scale_ceu_h, scale_ceu_v, | 1348 | unsigned int scale_comb_h, scale_comb_v, scale_ceu_h, scale_ceu_v, |
1258 | out_width, out_height; | 1349 | out_width, out_height; |
1259 | u32 capsr, cflcr; | 1350 | u32 capsr, cflcr; |
@@ -1302,26 +1393,25 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, | |||
1302 | * 5. Using actual input window and calculated combined scales calculate | 1393 | * 5. Using actual input window and calculated combined scales calculate |
1303 | * camera target output window. | 1394 | * camera target output window. |
1304 | */ | 1395 | */ |
1305 | pix->width = scale_down(cam_rect->width, scale_comb_h); | 1396 | mf.width = scale_down(cam_rect->width, scale_comb_h); |
1306 | pix->height = scale_down(cam_rect->height, scale_comb_v); | 1397 | mf.height = scale_down(cam_rect->height, scale_comb_v); |
1307 | 1398 | ||
1308 | dev_geo(dev, "5: camera target %ux%u\n", pix->width, pix->height); | 1399 | dev_geo(dev, "5: camera target %ux%u\n", mf.width, mf.height); |
1309 | 1400 | ||
1310 | /* 6. - 9. */ | 1401 | /* 6. - 9. */ |
1311 | pix->pixelformat = cam->camera_fmt->fourcc; | 1402 | mf.code = cam->code; |
1312 | pix->colorspace = cam->camera_fmt->colorspace; | 1403 | mf.field = pcdev->field; |
1313 | 1404 | ||
1314 | capsr = capture_save_reset(pcdev); | 1405 | capsr = capture_save_reset(pcdev); |
1315 | dev_dbg(dev, "CAPSR 0x%x, CFLCR 0x%x\n", capsr, pcdev->cflcr); | 1406 | dev_dbg(dev, "CAPSR 0x%x, CFLCR 0x%x\n", capsr, pcdev->cflcr); |
1316 | 1407 | ||
1317 | /* Make relative to camera rectangle */ | 1408 | /* Make relative to camera rectangle */ |
1318 | rect->left -= cam_rect->left; | 1409 | rect->left -= cam_rect->left; |
1319 | rect->top -= cam_rect->top; | 1410 | rect->top -= cam_rect->top; |
1320 | 1411 | ||
1321 | f.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 1412 | ret = client_scale(icd, cam_rect, rect, ceu_rect, &mf, |
1322 | 1413 | pcdev->image_mode && | |
1323 | ret = client_scale(icd, cam_rect, rect, ceu_rect, &f, | 1414 | V4L2_FIELD_NONE == pcdev->field); |
1324 | pcdev->image_mode && !pcdev->is_interlaced); | ||
1325 | 1415 | ||
1326 | dev_geo(dev, "6-9: %d\n", ret); | 1416 | dev_geo(dev, "6-9: %d\n", ret); |
1327 | 1417 | ||
@@ -1368,8 +1458,7 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, | |||
1368 | struct sh_mobile_ceu_dev *pcdev = ici->priv; | 1458 | struct sh_mobile_ceu_dev *pcdev = ici->priv; |
1369 | struct sh_mobile_ceu_cam *cam = icd->host_priv; | 1459 | struct sh_mobile_ceu_cam *cam = icd->host_priv; |
1370 | struct v4l2_pix_format *pix = &f->fmt.pix; | 1460 | struct v4l2_pix_format *pix = &f->fmt.pix; |
1371 | struct v4l2_format cam_f = *f; | 1461 | struct v4l2_mbus_framefmt mf; |
1372 | struct v4l2_pix_format *cam_pix = &cam_f.fmt.pix; | ||
1373 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | 1462 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
1374 | struct device *dev = icd->dev.parent; | 1463 | struct device *dev = icd->dev.parent; |
1375 | __u32 pixfmt = pix->pixelformat; | 1464 | __u32 pixfmt = pix->pixelformat; |
@@ -1379,18 +1468,20 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, | |||
1379 | unsigned int scale_cam_h, scale_cam_v; | 1468 | unsigned int scale_cam_h, scale_cam_v; |
1380 | u16 scale_v, scale_h; | 1469 | u16 scale_v, scale_h; |
1381 | int ret; | 1470 | int ret; |
1382 | bool is_interlaced, image_mode; | 1471 | bool image_mode; |
1472 | enum v4l2_field field; | ||
1383 | 1473 | ||
1384 | switch (pix->field) { | 1474 | switch (pix->field) { |
1385 | case V4L2_FIELD_INTERLACED: | ||
1386 | is_interlaced = true; | ||
1387 | break; | ||
1388 | case V4L2_FIELD_ANY: | ||
1389 | default: | 1475 | default: |
1390 | pix->field = V4L2_FIELD_NONE; | 1476 | pix->field = V4L2_FIELD_NONE; |
1391 | /* fall-through */ | 1477 | /* fall-through */ |
1478 | case V4L2_FIELD_INTERLACED_TB: | ||
1479 | case V4L2_FIELD_INTERLACED_BT: | ||
1392 | case V4L2_FIELD_NONE: | 1480 | case V4L2_FIELD_NONE: |
1393 | is_interlaced = false; | 1481 | field = pix->field; |
1482 | break; | ||
1483 | case V4L2_FIELD_INTERLACED: | ||
1484 | field = V4L2_FIELD_INTERLACED_TB; | ||
1394 | break; | 1485 | break; |
1395 | } | 1486 | } |
1396 | 1487 | ||
@@ -1438,9 +1529,11 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, | |||
1438 | * 4. Calculate camera output window by applying combined scales to real | 1529 | * 4. Calculate camera output window by applying combined scales to real |
1439 | * input window. | 1530 | * input window. |
1440 | */ | 1531 | */ |
1441 | cam_pix->width = scale_down(cam_rect->width, scale_h); | 1532 | mf.width = scale_down(cam_rect->width, scale_h); |
1442 | cam_pix->height = scale_down(cam_rect->height, scale_v); | 1533 | mf.height = scale_down(cam_rect->height, scale_v); |
1443 | cam_pix->pixelformat = xlate->cam_fmt->fourcc; | 1534 | mf.field = pix->field; |
1535 | mf.colorspace = pix->colorspace; | ||
1536 | mf.code = xlate->code; | ||
1444 | 1537 | ||
1445 | switch (pixfmt) { | 1538 | switch (pixfmt) { |
1446 | case V4L2_PIX_FMT_NV12: | 1539 | case V4L2_PIX_FMT_NV12: |
@@ -1453,51 +1546,61 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, | |||
1453 | image_mode = false; | 1546 | image_mode = false; |
1454 | } | 1547 | } |
1455 | 1548 | ||
1456 | dev_geo(dev, "4: camera output %ux%u\n", | 1549 | dev_geo(dev, "4: camera output %ux%u\n", mf.width, mf.height); |
1457 | cam_pix->width, cam_pix->height); | ||
1458 | 1550 | ||
1459 | /* 5. - 9. */ | 1551 | /* 5. - 9. */ |
1460 | ret = client_scale(icd, cam_rect, &cam_subrect, &ceu_rect, &cam_f, | 1552 | ret = client_scale(icd, cam_rect, &cam_subrect, &ceu_rect, &mf, |
1461 | image_mode && !is_interlaced); | 1553 | image_mode && V4L2_FIELD_NONE == field); |
1462 | 1554 | ||
1463 | dev_geo(dev, "5-9: client scale %d\n", ret); | 1555 | dev_geo(dev, "5-9: client scale %d\n", ret); |
1464 | 1556 | ||
1465 | /* Done with the camera. Now see if we can improve the result */ | 1557 | /* Done with the camera. Now see if we can improve the result */ |
1466 | 1558 | ||
1467 | dev_dbg(dev, "Camera %d fmt %ux%u, requested %ux%u\n", | 1559 | dev_dbg(dev, "Camera %d fmt %ux%u, requested %ux%u\n", |
1468 | ret, cam_pix->width, cam_pix->height, pix->width, pix->height); | 1560 | ret, mf.width, mf.height, pix->width, pix->height); |
1469 | if (ret < 0) | 1561 | if (ret < 0) |
1470 | return ret; | 1562 | return ret; |
1471 | 1563 | ||
1564 | if (mf.code != xlate->code) | ||
1565 | return -EINVAL; | ||
1566 | |||
1472 | /* 10. Use CEU scaling to scale to the requested user window. */ | 1567 | /* 10. Use CEU scaling to scale to the requested user window. */ |
1473 | 1568 | ||
1474 | /* We cannot scale up */ | 1569 | /* We cannot scale up */ |
1475 | if (pix->width > cam_pix->width) | 1570 | if (pix->width > mf.width) |
1476 | pix->width = cam_pix->width; | 1571 | pix->width = mf.width; |
1477 | if (pix->width > ceu_rect.width) | 1572 | if (pix->width > ceu_rect.width) |
1478 | pix->width = ceu_rect.width; | 1573 | pix->width = ceu_rect.width; |
1479 | 1574 | ||
1480 | if (pix->height > cam_pix->height) | 1575 | if (pix->height > mf.height) |
1481 | pix->height = cam_pix->height; | 1576 | pix->height = mf.height; |
1482 | if (pix->height > ceu_rect.height) | 1577 | if (pix->height > ceu_rect.height) |
1483 | pix->height = ceu_rect.height; | 1578 | pix->height = ceu_rect.height; |
1484 | 1579 | ||
1485 | /* Let's rock: scale pix->{width x height} down to width x height */ | 1580 | pix->colorspace = mf.colorspace; |
1486 | scale_h = calc_scale(ceu_rect.width, &pix->width); | 1581 | |
1487 | scale_v = calc_scale(ceu_rect.height, &pix->height); | 1582 | if (image_mode) { |
1583 | /* Scale pix->{width x height} down to width x height */ | ||
1584 | scale_h = calc_scale(ceu_rect.width, &pix->width); | ||
1585 | scale_v = calc_scale(ceu_rect.height, &pix->height); | ||
1586 | |||
1587 | pcdev->cflcr = scale_h | (scale_v << 16); | ||
1588 | } else { | ||
1589 | pix->width = ceu_rect.width; | ||
1590 | pix->height = ceu_rect.height; | ||
1591 | scale_h = scale_v = 0; | ||
1592 | pcdev->cflcr = 0; | ||
1593 | } | ||
1488 | 1594 | ||
1489 | dev_geo(dev, "10: W: %u : 0x%x = %u, H: %u : 0x%x = %u\n", | 1595 | dev_geo(dev, "10: W: %u : 0x%x = %u, H: %u : 0x%x = %u\n", |
1490 | ceu_rect.width, scale_h, pix->width, | 1596 | ceu_rect.width, scale_h, pix->width, |
1491 | ceu_rect.height, scale_v, pix->height); | 1597 | ceu_rect.height, scale_v, pix->height); |
1492 | 1598 | ||
1493 | pcdev->cflcr = scale_h | (scale_v << 16); | 1599 | cam->code = xlate->code; |
1600 | cam->ceu_rect = ceu_rect; | ||
1601 | icd->current_fmt = xlate; | ||
1494 | 1602 | ||
1495 | icd->buswidth = xlate->buswidth; | 1603 | pcdev->field = field; |
1496 | icd->current_fmt = xlate->host_fmt; | ||
1497 | cam->camera_fmt = xlate->cam_fmt; | ||
1498 | cam->ceu_rect = ceu_rect; | ||
1499 | |||
1500 | pcdev->is_interlaced = is_interlaced; | ||
1501 | pcdev->image_mode = image_mode; | 1604 | pcdev->image_mode = image_mode; |
1502 | 1605 | ||
1503 | return 0; | 1606 | return 0; |
@@ -1509,6 +1612,7 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, | |||
1509 | const struct soc_camera_format_xlate *xlate; | 1612 | const struct soc_camera_format_xlate *xlate; |
1510 | struct v4l2_pix_format *pix = &f->fmt.pix; | 1613 | struct v4l2_pix_format *pix = &f->fmt.pix; |
1511 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | 1614 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
1615 | struct v4l2_mbus_framefmt mf; | ||
1512 | __u32 pixfmt = pix->pixelformat; | 1616 | __u32 pixfmt = pix->pixelformat; |
1513 | int width, height; | 1617 | int width, height; |
1514 | int ret; | 1618 | int ret; |
@@ -1527,18 +1631,27 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, | |||
1527 | width = pix->width; | 1631 | width = pix->width; |
1528 | height = pix->height; | 1632 | height = pix->height; |
1529 | 1633 | ||
1530 | pix->bytesperline = pix->width * | 1634 | pix->bytesperline = soc_mbus_bytes_per_line(width, xlate->host_fmt); |
1531 | DIV_ROUND_UP(xlate->host_fmt->depth, 8); | 1635 | if (pix->bytesperline < 0) |
1532 | pix->sizeimage = pix->height * pix->bytesperline; | 1636 | return pix->bytesperline; |
1533 | 1637 | pix->sizeimage = height * pix->bytesperline; | |
1534 | pix->pixelformat = xlate->cam_fmt->fourcc; | ||
1535 | 1638 | ||
1536 | /* limit to sensor capabilities */ | 1639 | /* limit to sensor capabilities */ |
1537 | ret = v4l2_subdev_call(sd, video, try_fmt, f); | 1640 | mf.width = pix->width; |
1538 | pix->pixelformat = pixfmt; | 1641 | mf.height = pix->height; |
1642 | mf.field = pix->field; | ||
1643 | mf.code = xlate->code; | ||
1644 | mf.colorspace = pix->colorspace; | ||
1645 | |||
1646 | ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf); | ||
1539 | if (ret < 0) | 1647 | if (ret < 0) |
1540 | return ret; | 1648 | return ret; |
1541 | 1649 | ||
1650 | pix->width = mf.width; | ||
1651 | pix->height = mf.height; | ||
1652 | pix->field = mf.field; | ||
1653 | pix->colorspace = mf.colorspace; | ||
1654 | |||
1542 | switch (pixfmt) { | 1655 | switch (pixfmt) { |
1543 | case V4L2_PIX_FMT_NV12: | 1656 | case V4L2_PIX_FMT_NV12: |
1544 | case V4L2_PIX_FMT_NV21: | 1657 | case V4L2_PIX_FMT_NV21: |
@@ -1547,21 +1660,25 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, | |||
1547 | /* FIXME: check against rect_max after converting soc-camera */ | 1660 | /* FIXME: check against rect_max after converting soc-camera */ |
1548 | /* We can scale precisely, need a bigger image from camera */ | 1661 | /* We can scale precisely, need a bigger image from camera */ |
1549 | if (pix->width < width || pix->height < height) { | 1662 | if (pix->width < width || pix->height < height) { |
1550 | int tmp_w = pix->width, tmp_h = pix->height; | 1663 | /* |
1551 | pix->width = 2560; | 1664 | * We presume, the sensor behaves sanely, i.e., if |
1552 | pix->height = 1920; | 1665 | * requested a bigger rectangle, it will not return a |
1553 | ret = v4l2_subdev_call(sd, video, try_fmt, f); | 1666 | * smaller one. |
1667 | */ | ||
1668 | mf.width = 2560; | ||
1669 | mf.height = 1920; | ||
1670 | ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf); | ||
1554 | if (ret < 0) { | 1671 | if (ret < 0) { |
1555 | /* Shouldn't actually happen... */ | 1672 | /* Shouldn't actually happen... */ |
1556 | dev_err(icd->dev.parent, | 1673 | dev_err(icd->dev.parent, |
1557 | "FIXME: try_fmt() returned %d\n", ret); | 1674 | "FIXME: client try_fmt() = %d\n", ret); |
1558 | pix->width = tmp_w; | 1675 | return ret; |
1559 | pix->height = tmp_h; | ||
1560 | } | 1676 | } |
1561 | } | 1677 | } |
1562 | if (pix->width > width) | 1678 | /* We will scale exactly */ |
1679 | if (mf.width > width) | ||
1563 | pix->width = width; | 1680 | pix->width = width; |
1564 | if (pix->height > height) | 1681 | if (mf.height > height) |
1565 | pix->height = height; | 1682 | pix->height = height; |
1566 | } | 1683 | } |
1567 | 1684 | ||
@@ -1573,10 +1690,12 @@ static int sh_mobile_ceu_reqbufs(struct soc_camera_file *icf, | |||
1573 | { | 1690 | { |
1574 | int i; | 1691 | int i; |
1575 | 1692 | ||
1576 | /* This is for locking debugging only. I removed spinlocks and now I | 1693 | /* |
1694 | * This is for locking debugging only. I removed spinlocks and now I | ||
1577 | * check whether .prepare is ever called on a linked buffer, or whether | 1695 | * check whether .prepare is ever called on a linked buffer, or whether |
1578 | * a dma IRQ can occur for an in-work or unlinked buffer. Until now | 1696 | * a dma IRQ can occur for an in-work or unlinked buffer. Until now |
1579 | * it hadn't triggered */ | 1697 | * it hadn't triggered |
1698 | */ | ||
1580 | for (i = 0; i < p->count; i++) { | 1699 | for (i = 0; i < p->count; i++) { |
1581 | struct sh_mobile_ceu_buffer *buf; | 1700 | struct sh_mobile_ceu_buffer *buf; |
1582 | 1701 | ||
@@ -1624,8 +1743,7 @@ static void sh_mobile_ceu_init_videobuf(struct videobuf_queue *q, | |||
1624 | &sh_mobile_ceu_videobuf_ops, | 1743 | &sh_mobile_ceu_videobuf_ops, |
1625 | icd->dev.parent, &pcdev->lock, | 1744 | icd->dev.parent, &pcdev->lock, |
1626 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | 1745 | V4L2_BUF_TYPE_VIDEO_CAPTURE, |
1627 | pcdev->is_interlaced ? | 1746 | pcdev->field, |
1628 | V4L2_FIELD_INTERLACED : V4L2_FIELD_NONE, | ||
1629 | sizeof(struct sh_mobile_ceu_buffer), | 1747 | sizeof(struct sh_mobile_ceu_buffer), |
1630 | icd); | 1748 | icd); |
1631 | } | 1749 | } |
@@ -1654,7 +1772,7 @@ static int sh_mobile_ceu_set_ctrl(struct soc_camera_device *icd, | |||
1654 | 1772 | ||
1655 | switch (ctrl->id) { | 1773 | switch (ctrl->id) { |
1656 | case V4L2_CID_SHARPNESS: | 1774 | case V4L2_CID_SHARPNESS: |
1657 | switch (icd->current_fmt->fourcc) { | 1775 | switch (icd->current_fmt->host_fmt->fourcc) { |
1658 | case V4L2_PIX_FMT_NV12: | 1776 | case V4L2_PIX_FMT_NV12: |
1659 | case V4L2_PIX_FMT_NV21: | 1777 | case V4L2_PIX_FMT_NV21: |
1660 | case V4L2_PIX_FMT_NV16: | 1778 | case V4L2_PIX_FMT_NV16: |
@@ -1709,7 +1827,7 @@ static int __devinit sh_mobile_ceu_probe(struct platform_device *pdev) | |||
1709 | 1827 | ||
1710 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1828 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1711 | irq = platform_get_irq(pdev, 0); | 1829 | irq = platform_get_irq(pdev, 0); |
1712 | if (!res || !irq) { | 1830 | if (!res || (int)irq <= 0) { |
1713 | dev_err(&pdev->dev, "Not enough CEU platform resources.\n"); | 1831 | dev_err(&pdev->dev, "Not enough CEU platform resources.\n"); |
1714 | err = -ENODEV; | 1832 | err = -ENODEV; |
1715 | goto exit; | 1833 | goto exit; |
@@ -1825,7 +1943,7 @@ static int sh_mobile_ceu_runtime_nop(struct device *dev) | |||
1825 | return 0; | 1943 | return 0; |
1826 | } | 1944 | } |
1827 | 1945 | ||
1828 | static struct dev_pm_ops sh_mobile_ceu_dev_pm_ops = { | 1946 | static const struct dev_pm_ops sh_mobile_ceu_dev_pm_ops = { |
1829 | .runtime_suspend = sh_mobile_ceu_runtime_nop, | 1947 | .runtime_suspend = sh_mobile_ceu_runtime_nop, |
1830 | .runtime_resume = sh_mobile_ceu_runtime_nop, | 1948 | .runtime_resume = sh_mobile_ceu_runtime_nop, |
1831 | }; | 1949 | }; |
@@ -1836,7 +1954,7 @@ static struct platform_driver sh_mobile_ceu_driver = { | |||
1836 | .pm = &sh_mobile_ceu_dev_pm_ops, | 1954 | .pm = &sh_mobile_ceu_dev_pm_ops, |
1837 | }, | 1955 | }, |
1838 | .probe = sh_mobile_ceu_probe, | 1956 | .probe = sh_mobile_ceu_probe, |
1839 | .remove = __exit_p(sh_mobile_ceu_remove), | 1957 | .remove = __devexit_p(sh_mobile_ceu_remove), |
1840 | }; | 1958 | }; |
1841 | 1959 | ||
1842 | static int __init sh_mobile_ceu_init(void) | 1960 | static int __init sh_mobile_ceu_init(void) |
diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c index 4a7711c3e745..cbf8087b286f 100644 --- a/drivers/media/video/sn9c102/sn9c102_core.c +++ b/drivers/media/video/sn9c102/sn9c102_core.c | |||
@@ -1007,8 +1007,8 @@ static int sn9c102_stream_interrupt(struct sn9c102_device* cam) | |||
1007 | else if (cam->stream != STREAM_OFF) { | 1007 | else if (cam->stream != STREAM_OFF) { |
1008 | cam->state |= DEV_MISCONFIGURED; | 1008 | cam->state |= DEV_MISCONFIGURED; |
1009 | DBG(1, "URB timeout reached. The camera is misconfigured. " | 1009 | DBG(1, "URB timeout reached. The camera is misconfigured. " |
1010 | "To use it, close and open /dev/video%d again.", | 1010 | "To use it, close and open %s again.", |
1011 | cam->v4ldev->num); | 1011 | video_device_node_name(cam->v4ldev)); |
1012 | return -EIO; | 1012 | return -EIO; |
1013 | } | 1013 | } |
1014 | 1014 | ||
@@ -1734,7 +1734,8 @@ static void sn9c102_release_resources(struct kref *kref) | |||
1734 | 1734 | ||
1735 | cam = container_of(kref, struct sn9c102_device, kref); | 1735 | cam = container_of(kref, struct sn9c102_device, kref); |
1736 | 1736 | ||
1737 | DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->num); | 1737 | DBG(2, "V4L2 device %s deregistered", |
1738 | video_device_node_name(cam->v4ldev)); | ||
1738 | video_set_drvdata(cam->v4ldev, NULL); | 1739 | video_set_drvdata(cam->v4ldev, NULL); |
1739 | video_unregister_device(cam->v4ldev); | 1740 | video_unregister_device(cam->v4ldev); |
1740 | usb_put_dev(cam->usbdev); | 1741 | usb_put_dev(cam->usbdev); |
@@ -1791,8 +1792,8 @@ static int sn9c102_open(struct file *filp) | |||
1791 | } | 1792 | } |
1792 | 1793 | ||
1793 | if (cam->users) { | 1794 | if (cam->users) { |
1794 | DBG(2, "Device /dev/video%d is already in use", | 1795 | DBG(2, "Device %s is already in use", |
1795 | cam->v4ldev->num); | 1796 | video_device_node_name(cam->v4ldev)); |
1796 | DBG(3, "Simultaneous opens are not supported"); | 1797 | DBG(3, "Simultaneous opens are not supported"); |
1797 | /* | 1798 | /* |
1798 | open() must follow the open flags and should block | 1799 | open() must follow the open flags and should block |
@@ -1845,7 +1846,7 @@ static int sn9c102_open(struct file *filp) | |||
1845 | cam->frame_count = 0; | 1846 | cam->frame_count = 0; |
1846 | sn9c102_empty_framequeues(cam); | 1847 | sn9c102_empty_framequeues(cam); |
1847 | 1848 | ||
1848 | DBG(3, "Video device /dev/video%d is open", cam->v4ldev->num); | 1849 | DBG(3, "Video device %s is open", video_device_node_name(cam->v4ldev)); |
1849 | 1850 | ||
1850 | out: | 1851 | out: |
1851 | mutex_unlock(&cam->open_mutex); | 1852 | mutex_unlock(&cam->open_mutex); |
@@ -1870,7 +1871,7 @@ static int sn9c102_release(struct file *filp) | |||
1870 | cam->users--; | 1871 | cam->users--; |
1871 | wake_up_interruptible_nr(&cam->wait_open, 1); | 1872 | wake_up_interruptible_nr(&cam->wait_open, 1); |
1872 | 1873 | ||
1873 | DBG(3, "Video device /dev/video%d closed", cam->v4ldev->num); | 1874 | DBG(3, "Video device %s closed", video_device_node_name(cam->v4ldev)); |
1874 | 1875 | ||
1875 | kref_put(&cam->kref, sn9c102_release_resources); | 1876 | kref_put(&cam->kref, sn9c102_release_resources); |
1876 | 1877 | ||
@@ -2433,8 +2434,8 @@ sn9c102_vidioc_s_crop(struct sn9c102_device* cam, void __user * arg) | |||
2433 | if (err) { /* atomic, no rollback in ioctl() */ | 2434 | if (err) { /* atomic, no rollback in ioctl() */ |
2434 | cam->state |= DEV_MISCONFIGURED; | 2435 | cam->state |= DEV_MISCONFIGURED; |
2435 | DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To " | 2436 | DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To " |
2436 | "use the camera, close and open /dev/video%d again.", | 2437 | "use the camera, close and open %s again.", |
2437 | cam->v4ldev->num); | 2438 | video_device_node_name(cam->v4ldev)); |
2438 | return -EIO; | 2439 | return -EIO; |
2439 | } | 2440 | } |
2440 | 2441 | ||
@@ -2446,8 +2447,8 @@ sn9c102_vidioc_s_crop(struct sn9c102_device* cam, void __user * arg) | |||
2446 | nbuffers != sn9c102_request_buffers(cam, nbuffers, cam->io)) { | 2447 | nbuffers != sn9c102_request_buffers(cam, nbuffers, cam->io)) { |
2447 | cam->state |= DEV_MISCONFIGURED; | 2448 | cam->state |= DEV_MISCONFIGURED; |
2448 | DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To " | 2449 | DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To " |
2449 | "use the camera, close and open /dev/video%d again.", | 2450 | "use the camera, close and open %s again.", |
2450 | cam->v4ldev->num); | 2451 | video_device_node_name(cam->v4ldev)); |
2451 | return -ENOMEM; | 2452 | return -ENOMEM; |
2452 | } | 2453 | } |
2453 | 2454 | ||
@@ -2690,8 +2691,8 @@ sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd, | |||
2690 | if (err) { /* atomic, no rollback in ioctl() */ | 2691 | if (err) { /* atomic, no rollback in ioctl() */ |
2691 | cam->state |= DEV_MISCONFIGURED; | 2692 | cam->state |= DEV_MISCONFIGURED; |
2692 | DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To " | 2693 | DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To " |
2693 | "use the camera, close and open /dev/video%d again.", | 2694 | "use the camera, close and open %s again.", |
2694 | cam->v4ldev->num); | 2695 | video_device_node_name(cam->v4ldev)); |
2695 | return -EIO; | 2696 | return -EIO; |
2696 | } | 2697 | } |
2697 | 2698 | ||
@@ -2702,8 +2703,8 @@ sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd, | |||
2702 | nbuffers != sn9c102_request_buffers(cam, nbuffers, cam->io)) { | 2703 | nbuffers != sn9c102_request_buffers(cam, nbuffers, cam->io)) { |
2703 | cam->state |= DEV_MISCONFIGURED; | 2704 | cam->state |= DEV_MISCONFIGURED; |
2704 | DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To " | 2705 | DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To " |
2705 | "use the camera, close and open /dev/video%d again.", | 2706 | "use the camera, close and open %s again.", |
2706 | cam->v4ldev->num); | 2707 | video_device_node_name(cam->v4ldev)); |
2707 | return -ENOMEM; | 2708 | return -ENOMEM; |
2708 | } | 2709 | } |
2709 | 2710 | ||
@@ -2748,9 +2749,9 @@ sn9c102_vidioc_s_jpegcomp(struct sn9c102_device* cam, void __user * arg) | |||
2748 | err += sn9c102_set_compression(cam, &jc); | 2749 | err += sn9c102_set_compression(cam, &jc); |
2749 | if (err) { /* atomic, no rollback in ioctl() */ | 2750 | if (err) { /* atomic, no rollback in ioctl() */ |
2750 | cam->state |= DEV_MISCONFIGURED; | 2751 | cam->state |= DEV_MISCONFIGURED; |
2751 | DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware " | 2752 | DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware problems. " |
2752 | "problems. To use the camera, close and open " | 2753 | "To use the camera, close and open %s again.", |
2753 | "/dev/video%d again.", cam->v4ldev->num); | 2754 | video_device_node_name(cam->v4ldev)); |
2754 | return -EIO; | 2755 | return -EIO; |
2755 | } | 2756 | } |
2756 | 2757 | ||
@@ -3328,7 +3329,6 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) | |||
3328 | 3329 | ||
3329 | strcpy(cam->v4ldev->name, "SN9C1xx PC Camera"); | 3330 | strcpy(cam->v4ldev->name, "SN9C1xx PC Camera"); |
3330 | cam->v4ldev->fops = &sn9c102_fops; | 3331 | cam->v4ldev->fops = &sn9c102_fops; |
3331 | cam->v4ldev->minor = video_nr[dev_nr]; | ||
3332 | cam->v4ldev->release = video_device_release; | 3332 | cam->v4ldev->release = video_device_release; |
3333 | cam->v4ldev->parent = &udev->dev; | 3333 | cam->v4ldev->parent = &udev->dev; |
3334 | 3334 | ||
@@ -3346,7 +3346,8 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) | |||
3346 | goto fail; | 3346 | goto fail; |
3347 | } | 3347 | } |
3348 | 3348 | ||
3349 | DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->num); | 3349 | DBG(2, "V4L2 device registered as %s", |
3350 | video_device_node_name(cam->v4ldev)); | ||
3350 | 3351 | ||
3351 | video_set_drvdata(cam->v4ldev, cam); | 3352 | video_set_drvdata(cam->v4ldev, cam); |
3352 | cam->module_param.force_munmap = force_munmap[dev_nr]; | 3353 | cam->module_param.force_munmap = force_munmap[dev_nr]; |
@@ -3398,9 +3399,9 @@ static void sn9c102_usb_disconnect(struct usb_interface* intf) | |||
3398 | DBG(2, "Disconnecting %s...", cam->v4ldev->name); | 3399 | DBG(2, "Disconnecting %s...", cam->v4ldev->name); |
3399 | 3400 | ||
3400 | if (cam->users) { | 3401 | if (cam->users) { |
3401 | DBG(2, "Device /dev/video%d is open! Deregistration and " | 3402 | DBG(2, "Device %s is open! Deregistration and memory " |
3402 | "memory deallocation are deferred.", | 3403 | "deallocation are deferred.", |
3403 | cam->v4ldev->num); | 3404 | video_device_node_name(cam->v4ldev)); |
3404 | cam->state |= DEV_MISCONFIGURED; | 3405 | cam->state |= DEV_MISCONFIGURED; |
3405 | sn9c102_stop_transfer(cam); | 3406 | sn9c102_stop_transfer(cam); |
3406 | cam->state |= DEV_DISCONNECTED; | 3407 | cam->state |= DEV_DISCONNECTED; |
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 95fdeb23c2c1..6b3fbcca7747 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <media/v4l2-ioctl.h> | 31 | #include <media/v4l2-ioctl.h> |
32 | #include <media/v4l2-dev.h> | 32 | #include <media/v4l2-dev.h> |
33 | #include <media/videobuf-core.h> | 33 | #include <media/videobuf-core.h> |
34 | #include <media/soc_mediabus.h> | ||
34 | 35 | ||
35 | /* Default to VGA resolution */ | 36 | /* Default to VGA resolution */ |
36 | #define DEFAULT_WIDTH 640 | 37 | #define DEFAULT_WIDTH 640 |
@@ -40,18 +41,6 @@ static LIST_HEAD(hosts); | |||
40 | static LIST_HEAD(devices); | 41 | static LIST_HEAD(devices); |
41 | static DEFINE_MUTEX(list_lock); /* Protects the list of hosts */ | 42 | static DEFINE_MUTEX(list_lock); /* Protects the list of hosts */ |
42 | 43 | ||
43 | const struct soc_camera_data_format *soc_camera_format_by_fourcc( | ||
44 | struct soc_camera_device *icd, unsigned int fourcc) | ||
45 | { | ||
46 | unsigned int i; | ||
47 | |||
48 | for (i = 0; i < icd->num_formats; i++) | ||
49 | if (icd->formats[i].fourcc == fourcc) | ||
50 | return icd->formats + i; | ||
51 | return NULL; | ||
52 | } | ||
53 | EXPORT_SYMBOL(soc_camera_format_by_fourcc); | ||
54 | |||
55 | const struct soc_camera_format_xlate *soc_camera_xlate_by_fourcc( | 44 | const struct soc_camera_format_xlate *soc_camera_xlate_by_fourcc( |
56 | struct soc_camera_device *icd, unsigned int fourcc) | 45 | struct soc_camera_device *icd, unsigned int fourcc) |
57 | { | 46 | { |
@@ -207,21 +196,26 @@ static int soc_camera_dqbuf(struct file *file, void *priv, | |||
207 | /* Always entered with .video_lock held */ | 196 | /* Always entered with .video_lock held */ |
208 | static int soc_camera_init_user_formats(struct soc_camera_device *icd) | 197 | static int soc_camera_init_user_formats(struct soc_camera_device *icd) |
209 | { | 198 | { |
199 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | ||
210 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | 200 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); |
211 | int i, fmts = 0, ret; | 201 | int i, fmts = 0, raw_fmts = 0, ret; |
202 | enum v4l2_mbus_pixelcode code; | ||
203 | |||
204 | while (!v4l2_subdev_call(sd, video, enum_mbus_fmt, raw_fmts, &code)) | ||
205 | raw_fmts++; | ||
212 | 206 | ||
213 | if (!ici->ops->get_formats) | 207 | if (!ici->ops->get_formats) |
214 | /* | 208 | /* |
215 | * Fallback mode - the host will have to serve all | 209 | * Fallback mode - the host will have to serve all |
216 | * sensor-provided formats one-to-one to the user | 210 | * sensor-provided formats one-to-one to the user |
217 | */ | 211 | */ |
218 | fmts = icd->num_formats; | 212 | fmts = raw_fmts; |
219 | else | 213 | else |
220 | /* | 214 | /* |
221 | * First pass - only count formats this host-sensor | 215 | * First pass - only count formats this host-sensor |
222 | * configuration can provide | 216 | * configuration can provide |
223 | */ | 217 | */ |
224 | for (i = 0; i < icd->num_formats; i++) { | 218 | for (i = 0; i < raw_fmts; i++) { |
225 | ret = ici->ops->get_formats(icd, i, NULL); | 219 | ret = ici->ops->get_formats(icd, i, NULL); |
226 | if (ret < 0) | 220 | if (ret < 0) |
227 | return ret; | 221 | return ret; |
@@ -242,11 +236,12 @@ static int soc_camera_init_user_formats(struct soc_camera_device *icd) | |||
242 | 236 | ||
243 | /* Second pass - actually fill data formats */ | 237 | /* Second pass - actually fill data formats */ |
244 | fmts = 0; | 238 | fmts = 0; |
245 | for (i = 0; i < icd->num_formats; i++) | 239 | for (i = 0; i < raw_fmts; i++) |
246 | if (!ici->ops->get_formats) { | 240 | if (!ici->ops->get_formats) { |
247 | icd->user_formats[i].host_fmt = icd->formats + i; | 241 | v4l2_subdev_call(sd, video, enum_mbus_fmt, i, &code); |
248 | icd->user_formats[i].cam_fmt = icd->formats + i; | 242 | icd->user_formats[i].host_fmt = |
249 | icd->user_formats[i].buswidth = icd->formats[i].depth; | 243 | soc_mbus_get_fmtdesc(code); |
244 | icd->user_formats[i].code = code; | ||
250 | } else { | 245 | } else { |
251 | ret = ici->ops->get_formats(icd, i, | 246 | ret = ici->ops->get_formats(icd, i, |
252 | &icd->user_formats[fmts]); | 247 | &icd->user_formats[fmts]); |
@@ -255,7 +250,7 @@ static int soc_camera_init_user_formats(struct soc_camera_device *icd) | |||
255 | fmts += ret; | 250 | fmts += ret; |
256 | } | 251 | } |
257 | 252 | ||
258 | icd->current_fmt = icd->user_formats[0].host_fmt; | 253 | icd->current_fmt = &icd->user_formats[0]; |
259 | 254 | ||
260 | return 0; | 255 | return 0; |
261 | 256 | ||
@@ -281,7 +276,7 @@ static void soc_camera_free_user_formats(struct soc_camera_device *icd) | |||
281 | #define pixfmtstr(x) (x) & 0xff, ((x) >> 8) & 0xff, ((x) >> 16) & 0xff, \ | 276 | #define pixfmtstr(x) (x) & 0xff, ((x) >> 8) & 0xff, ((x) >> 16) & 0xff, \ |
282 | ((x) >> 24) & 0xff | 277 | ((x) >> 24) & 0xff |
283 | 278 | ||
284 | /* Called with .vb_lock held */ | 279 | /* Called with .vb_lock held, or from the first open(2), see comment there */ |
285 | static int soc_camera_set_fmt(struct soc_camera_file *icf, | 280 | static int soc_camera_set_fmt(struct soc_camera_file *icf, |
286 | struct v4l2_format *f) | 281 | struct v4l2_format *f) |
287 | { | 282 | { |
@@ -302,7 +297,7 @@ static int soc_camera_set_fmt(struct soc_camera_file *icf, | |||
302 | if (ret < 0) { | 297 | if (ret < 0) { |
303 | return ret; | 298 | return ret; |
304 | } else if (!icd->current_fmt || | 299 | } else if (!icd->current_fmt || |
305 | icd->current_fmt->fourcc != pix->pixelformat) { | 300 | icd->current_fmt->host_fmt->fourcc != pix->pixelformat) { |
306 | dev_err(&icd->dev, | 301 | dev_err(&icd->dev, |
307 | "Host driver hasn't set up current format correctly!\n"); | 302 | "Host driver hasn't set up current format correctly!\n"); |
308 | return -EINVAL; | 303 | return -EINVAL; |
@@ -310,6 +305,7 @@ static int soc_camera_set_fmt(struct soc_camera_file *icf, | |||
310 | 305 | ||
311 | icd->user_width = pix->width; | 306 | icd->user_width = pix->width; |
312 | icd->user_height = pix->height; | 307 | icd->user_height = pix->height; |
308 | icd->colorspace = pix->colorspace; | ||
313 | icf->vb_vidq.field = | 309 | icf->vb_vidq.field = |
314 | icd->field = pix->field; | 310 | icd->field = pix->field; |
315 | 311 | ||
@@ -369,8 +365,9 @@ static int soc_camera_open(struct file *file) | |||
369 | .width = icd->user_width, | 365 | .width = icd->user_width, |
370 | .height = icd->user_height, | 366 | .height = icd->user_height, |
371 | .field = icd->field, | 367 | .field = icd->field, |
372 | .pixelformat = icd->current_fmt->fourcc, | 368 | .colorspace = icd->colorspace, |
373 | .colorspace = icd->current_fmt->colorspace, | 369 | .pixelformat = |
370 | icd->current_fmt->host_fmt->fourcc, | ||
374 | }, | 371 | }, |
375 | }; | 372 | }; |
376 | 373 | ||
@@ -390,7 +387,12 @@ static int soc_camera_open(struct file *file) | |||
390 | goto eiciadd; | 387 | goto eiciadd; |
391 | } | 388 | } |
392 | 389 | ||
393 | /* Try to configure with default parameters */ | 390 | /* |
391 | * Try to configure with default parameters. Notice: this is the | ||
392 | * very first open, so, we cannot race against other calls, | ||
393 | * apart from someone else calling open() simultaneously, but | ||
394 | * .video_lock is protecting us against it. | ||
395 | */ | ||
394 | ret = soc_camera_set_fmt(icf, &f); | 396 | ret = soc_camera_set_fmt(icf, &f); |
395 | if (ret < 0) | 397 | if (ret < 0) |
396 | goto esfmt; | 398 | goto esfmt; |
@@ -534,7 +536,7 @@ static int soc_camera_enum_fmt_vid_cap(struct file *file, void *priv, | |||
534 | { | 536 | { |
535 | struct soc_camera_file *icf = file->private_data; | 537 | struct soc_camera_file *icf = file->private_data; |
536 | struct soc_camera_device *icd = icf->icd; | 538 | struct soc_camera_device *icd = icf->icd; |
537 | const struct soc_camera_data_format *format; | 539 | const struct soc_mbus_pixelfmt *format; |
538 | 540 | ||
539 | WARN_ON(priv != file->private_data); | 541 | WARN_ON(priv != file->private_data); |
540 | 542 | ||
@@ -543,7 +545,8 @@ static int soc_camera_enum_fmt_vid_cap(struct file *file, void *priv, | |||
543 | 545 | ||
544 | format = icd->user_formats[f->index].host_fmt; | 546 | format = icd->user_formats[f->index].host_fmt; |
545 | 547 | ||
546 | strlcpy(f->description, format->name, sizeof(f->description)); | 548 | if (format->name) |
549 | strlcpy(f->description, format->name, sizeof(f->description)); | ||
547 | f->pixelformat = format->fourcc; | 550 | f->pixelformat = format->fourcc; |
548 | return 0; | 551 | return 0; |
549 | } | 552 | } |
@@ -560,12 +563,15 @@ static int soc_camera_g_fmt_vid_cap(struct file *file, void *priv, | |||
560 | pix->width = icd->user_width; | 563 | pix->width = icd->user_width; |
561 | pix->height = icd->user_height; | 564 | pix->height = icd->user_height; |
562 | pix->field = icf->vb_vidq.field; | 565 | pix->field = icf->vb_vidq.field; |
563 | pix->pixelformat = icd->current_fmt->fourcc; | 566 | pix->pixelformat = icd->current_fmt->host_fmt->fourcc; |
564 | pix->bytesperline = pix->width * | 567 | pix->bytesperline = soc_mbus_bytes_per_line(pix->width, |
565 | DIV_ROUND_UP(icd->current_fmt->depth, 8); | 568 | icd->current_fmt->host_fmt); |
569 | pix->colorspace = icd->colorspace; | ||
570 | if (pix->bytesperline < 0) | ||
571 | return pix->bytesperline; | ||
566 | pix->sizeimage = pix->height * pix->bytesperline; | 572 | pix->sizeimage = pix->height * pix->bytesperline; |
567 | dev_dbg(&icd->dev, "current_fmt->fourcc: 0x%08x\n", | 573 | dev_dbg(&icd->dev, "current_fmt->fourcc: 0x%08x\n", |
568 | icd->current_fmt->fourcc); | 574 | icd->current_fmt->host_fmt->fourcc); |
569 | return 0; | 575 | return 0; |
570 | } | 576 | } |
571 | 577 | ||
@@ -621,8 +627,10 @@ static int soc_camera_streamoff(struct file *file, void *priv, | |||
621 | 627 | ||
622 | mutex_lock(&icd->video_lock); | 628 | mutex_lock(&icd->video_lock); |
623 | 629 | ||
624 | /* This calls buf_release from host driver's videobuf_queue_ops for all | 630 | /* |
625 | * remaining buffers. When the last buffer is freed, stop capture */ | 631 | * This calls buf_release from host driver's videobuf_queue_ops for all |
632 | * remaining buffers. When the last buffer is freed, stop capture | ||
633 | */ | ||
626 | videobuf_streamoff(&icf->vb_vidq); | 634 | videobuf_streamoff(&icf->vb_vidq); |
627 | 635 | ||
628 | v4l2_subdev_call(sd, video, s_stream, 0); | 636 | v4l2_subdev_call(sd, video, s_stream, 0); |
@@ -892,7 +900,7 @@ static int soc_camera_probe(struct device *dev) | |||
892 | struct soc_camera_link *icl = to_soc_camera_link(icd); | 900 | struct soc_camera_link *icl = to_soc_camera_link(icd); |
893 | struct device *control = NULL; | 901 | struct device *control = NULL; |
894 | struct v4l2_subdev *sd; | 902 | struct v4l2_subdev *sd; |
895 | struct v4l2_format f = {.type = V4L2_BUF_TYPE_VIDEO_CAPTURE}; | 903 | struct v4l2_mbus_framefmt mf; |
896 | int ret; | 904 | int ret; |
897 | 905 | ||
898 | dev_info(dev, "Probing %s\n", dev_name(dev)); | 906 | dev_info(dev, "Probing %s\n", dev_name(dev)); |
@@ -963,9 +971,11 @@ static int soc_camera_probe(struct device *dev) | |||
963 | 971 | ||
964 | /* Try to improve our guess of a reasonable window format */ | 972 | /* Try to improve our guess of a reasonable window format */ |
965 | sd = soc_camera_to_subdev(icd); | 973 | sd = soc_camera_to_subdev(icd); |
966 | if (!v4l2_subdev_call(sd, video, g_fmt, &f)) { | 974 | if (!v4l2_subdev_call(sd, video, g_mbus_fmt, &mf)) { |
967 | icd->user_width = f.fmt.pix.width; | 975 | icd->user_width = mf.width; |
968 | icd->user_height = f.fmt.pix.height; | 976 | icd->user_height = mf.height; |
977 | icd->colorspace = mf.colorspace; | ||
978 | icd->field = mf.field; | ||
969 | } | 979 | } |
970 | 980 | ||
971 | /* Do we have to sysfs_remove_link() before device_unregister()? */ | 981 | /* Do we have to sysfs_remove_link() before device_unregister()? */ |
@@ -1004,8 +1014,10 @@ epower: | |||
1004 | return ret; | 1014 | return ret; |
1005 | } | 1015 | } |
1006 | 1016 | ||
1007 | /* This is called on device_unregister, which only means we have to disconnect | 1017 | /* |
1008 | * from the host, but not remove ourselves from the device list */ | 1018 | * This is called on device_unregister, which only means we have to disconnect |
1019 | * from the host, but not remove ourselves from the device list | ||
1020 | */ | ||
1009 | static int soc_camera_remove(struct device *dev) | 1021 | static int soc_camera_remove(struct device *dev) |
1010 | { | 1022 | { |
1011 | struct soc_camera_device *icd = to_soc_camera_dev(dev); | 1023 | struct soc_camera_device *icd = to_soc_camera_dev(dev); |
@@ -1205,8 +1217,10 @@ static int soc_camera_device_register(struct soc_camera_device *icd) | |||
1205 | } | 1217 | } |
1206 | 1218 | ||
1207 | if (num < 0) | 1219 | if (num < 0) |
1208 | /* ok, we have 256 cameras on this host... | 1220 | /* |
1209 | * man, stay reasonable... */ | 1221 | * ok, we have 256 cameras on this host... |
1222 | * man, stay reasonable... | ||
1223 | */ | ||
1210 | return -ENOMEM; | 1224 | return -ENOMEM; |
1211 | 1225 | ||
1212 | icd->devnum = num; | 1226 | icd->devnum = num; |
@@ -1268,7 +1282,6 @@ static int video_dev_create(struct soc_camera_device *icd) | |||
1268 | vdev->fops = &soc_camera_fops; | 1282 | vdev->fops = &soc_camera_fops; |
1269 | vdev->ioctl_ops = &soc_camera_ioctl_ops; | 1283 | vdev->ioctl_ops = &soc_camera_ioctl_ops; |
1270 | vdev->release = video_device_release; | 1284 | vdev->release = video_device_release; |
1271 | vdev->minor = -1; | ||
1272 | vdev->tvnorms = V4L2_STD_UNKNOWN; | 1285 | vdev->tvnorms = V4L2_STD_UNKNOWN; |
1273 | 1286 | ||
1274 | icd->vdev = vdev; | 1287 | icd->vdev = vdev; |
@@ -1291,8 +1304,7 @@ static int soc_camera_video_start(struct soc_camera_device *icd) | |||
1291 | !icd->ops->set_bus_param) | 1304 | !icd->ops->set_bus_param) |
1292 | return -EINVAL; | 1305 | return -EINVAL; |
1293 | 1306 | ||
1294 | ret = video_register_device(icd->vdev, VFL_TYPE_GRABBER, | 1307 | ret = video_register_device(icd->vdev, VFL_TYPE_GRABBER, -1); |
1295 | icd->vdev->minor); | ||
1296 | if (ret < 0) { | 1308 | if (ret < 0) { |
1297 | dev_err(&icd->dev, "video_register_device failed: %d\n", ret); | 1309 | dev_err(&icd->dev, "video_register_device failed: %d\n", ret); |
1298 | return ret; | 1310 | return ret; |
@@ -1335,9 +1347,11 @@ escdevreg: | |||
1335 | return ret; | 1347 | return ret; |
1336 | } | 1348 | } |
1337 | 1349 | ||
1338 | /* Only called on rmmod for each platform device, since they are not | 1350 | /* |
1351 | * Only called on rmmod for each platform device, since they are not | ||
1339 | * hot-pluggable. Now we know, that all our users - hosts and devices have | 1352 | * hot-pluggable. Now we know, that all our users - hosts and devices have |
1340 | * been unloaded already */ | 1353 | * been unloaded already |
1354 | */ | ||
1341 | static int __devexit soc_camera_pdrv_remove(struct platform_device *pdev) | 1355 | static int __devexit soc_camera_pdrv_remove(struct platform_device *pdev) |
1342 | { | 1356 | { |
1343 | struct soc_camera_device *icd = platform_get_drvdata(pdev); | 1357 | struct soc_camera_device *icd = platform_get_drvdata(pdev); |
diff --git a/drivers/media/video/soc_camera_platform.c b/drivers/media/video/soc_camera_platform.c index b6a575ce5da2..10b003a8be83 100644 --- a/drivers/media/video/soc_camera_platform.c +++ b/drivers/media/video/soc_camera_platform.c | |||
@@ -22,7 +22,6 @@ | |||
22 | 22 | ||
23 | struct soc_camera_platform_priv { | 23 | struct soc_camera_platform_priv { |
24 | struct v4l2_subdev subdev; | 24 | struct v4l2_subdev subdev; |
25 | struct soc_camera_data_format format; | ||
26 | }; | 25 | }; |
27 | 26 | ||
28 | static struct soc_camera_platform_priv *get_priv(struct platform_device *pdev) | 27 | static struct soc_camera_platform_priv *get_priv(struct platform_device *pdev) |
@@ -58,36 +57,36 @@ soc_camera_platform_query_bus_param(struct soc_camera_device *icd) | |||
58 | } | 57 | } |
59 | 58 | ||
60 | static int soc_camera_platform_try_fmt(struct v4l2_subdev *sd, | 59 | static int soc_camera_platform_try_fmt(struct v4l2_subdev *sd, |
61 | struct v4l2_format *f) | 60 | struct v4l2_mbus_framefmt *mf) |
62 | { | 61 | { |
63 | struct soc_camera_platform_info *p = v4l2_get_subdevdata(sd); | 62 | struct soc_camera_platform_info *p = v4l2_get_subdevdata(sd); |
64 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
65 | 63 | ||
66 | pix->width = p->format.width; | 64 | mf->width = p->format.width; |
67 | pix->height = p->format.height; | 65 | mf->height = p->format.height; |
66 | mf->code = p->format.code; | ||
67 | mf->colorspace = p->format.colorspace; | ||
68 | |||
68 | return 0; | 69 | return 0; |
69 | } | 70 | } |
70 | 71 | ||
71 | static void soc_camera_platform_video_probe(struct soc_camera_device *icd, | 72 | static struct v4l2_subdev_core_ops platform_subdev_core_ops; |
72 | struct platform_device *pdev) | 73 | |
74 | static int soc_camera_platform_enum_fmt(struct v4l2_subdev *sd, int index, | ||
75 | enum v4l2_mbus_pixelcode *code) | ||
73 | { | 76 | { |
74 | struct soc_camera_platform_priv *priv = get_priv(pdev); | 77 | struct soc_camera_platform_info *p = v4l2_get_subdevdata(sd); |
75 | struct soc_camera_platform_info *p = pdev->dev.platform_data; | ||
76 | 78 | ||
77 | priv->format.name = p->format_name; | 79 | if (index) |
78 | priv->format.depth = p->format_depth; | 80 | return -EINVAL; |
79 | priv->format.fourcc = p->format.pixelformat; | ||
80 | priv->format.colorspace = p->format.colorspace; | ||
81 | 81 | ||
82 | icd->formats = &priv->format; | 82 | *code = p->format.code; |
83 | icd->num_formats = 1; | 83 | return 0; |
84 | } | 84 | } |
85 | 85 | ||
86 | static struct v4l2_subdev_core_ops platform_subdev_core_ops; | ||
87 | |||
88 | static struct v4l2_subdev_video_ops platform_subdev_video_ops = { | 86 | static struct v4l2_subdev_video_ops platform_subdev_video_ops = { |
89 | .s_stream = soc_camera_platform_s_stream, | 87 | .s_stream = soc_camera_platform_s_stream, |
90 | .try_fmt = soc_camera_platform_try_fmt, | 88 | .try_mbus_fmt = soc_camera_platform_try_fmt, |
89 | .enum_mbus_fmt = soc_camera_platform_enum_fmt, | ||
91 | }; | 90 | }; |
92 | 91 | ||
93 | static struct v4l2_subdev_ops platform_subdev_ops = { | 92 | static struct v4l2_subdev_ops platform_subdev_ops = { |
@@ -128,13 +127,10 @@ static int soc_camera_platform_probe(struct platform_device *pdev) | |||
128 | /* Set the control device reference */ | 127 | /* Set the control device reference */ |
129 | dev_set_drvdata(&icd->dev, &pdev->dev); | 128 | dev_set_drvdata(&icd->dev, &pdev->dev); |
130 | 129 | ||
131 | icd->y_skip_top = 0; | 130 | icd->ops = &soc_camera_platform_ops; |
132 | icd->ops = &soc_camera_platform_ops; | ||
133 | 131 | ||
134 | ici = to_soc_camera_host(icd->dev.parent); | 132 | ici = to_soc_camera_host(icd->dev.parent); |
135 | 133 | ||
136 | soc_camera_platform_video_probe(icd, pdev); | ||
137 | |||
138 | v4l2_subdev_init(&priv->subdev, &platform_subdev_ops); | 134 | v4l2_subdev_init(&priv->subdev, &platform_subdev_ops); |
139 | v4l2_set_subdevdata(&priv->subdev, p); | 135 | v4l2_set_subdevdata(&priv->subdev, p); |
140 | strncpy(priv->subdev.name, dev_name(&pdev->dev), V4L2_SUBDEV_NAME_SIZE); | 136 | strncpy(priv->subdev.name, dev_name(&pdev->dev), V4L2_SUBDEV_NAME_SIZE); |
diff --git a/drivers/media/video/soc_mediabus.c b/drivers/media/video/soc_mediabus.c new file mode 100644 index 000000000000..f8d5c87dc2aa --- /dev/null +++ b/drivers/media/video/soc_mediabus.c | |||
@@ -0,0 +1,157 @@ | |||
1 | /* | ||
2 | * soc-camera media bus helper routines | ||
3 | * | ||
4 | * Copyright (C) 2009, Guennadi Liakhovetski <g.liakhovetski@gmx.de> | ||
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 version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/module.h> | ||
13 | |||
14 | #include <media/v4l2-device.h> | ||
15 | #include <media/v4l2-mediabus.h> | ||
16 | #include <media/soc_mediabus.h> | ||
17 | |||
18 | #define MBUS_IDX(f) (V4L2_MBUS_FMT_ ## f - V4L2_MBUS_FMT_FIXED - 1) | ||
19 | |||
20 | static const struct soc_mbus_pixelfmt mbus_fmt[] = { | ||
21 | [MBUS_IDX(YUYV8_2X8_LE)] = { | ||
22 | .fourcc = V4L2_PIX_FMT_YUYV, | ||
23 | .name = "YUYV", | ||
24 | .bits_per_sample = 8, | ||
25 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | ||
26 | .order = SOC_MBUS_ORDER_LE, | ||
27 | }, [MBUS_IDX(YVYU8_2X8_LE)] = { | ||
28 | .fourcc = V4L2_PIX_FMT_YVYU, | ||
29 | .name = "YVYU", | ||
30 | .bits_per_sample = 8, | ||
31 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | ||
32 | .order = SOC_MBUS_ORDER_LE, | ||
33 | }, [MBUS_IDX(YUYV8_2X8_BE)] = { | ||
34 | .fourcc = V4L2_PIX_FMT_UYVY, | ||
35 | .name = "UYVY", | ||
36 | .bits_per_sample = 8, | ||
37 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | ||
38 | .order = SOC_MBUS_ORDER_LE, | ||
39 | }, [MBUS_IDX(YVYU8_2X8_BE)] = { | ||
40 | .fourcc = V4L2_PIX_FMT_VYUY, | ||
41 | .name = "VYUY", | ||
42 | .bits_per_sample = 8, | ||
43 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | ||
44 | .order = SOC_MBUS_ORDER_LE, | ||
45 | }, [MBUS_IDX(RGB555_2X8_PADHI_LE)] = { | ||
46 | .fourcc = V4L2_PIX_FMT_RGB555, | ||
47 | .name = "RGB555", | ||
48 | .bits_per_sample = 8, | ||
49 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | ||
50 | .order = SOC_MBUS_ORDER_LE, | ||
51 | }, [MBUS_IDX(RGB555_2X8_PADHI_BE)] = { | ||
52 | .fourcc = V4L2_PIX_FMT_RGB555X, | ||
53 | .name = "RGB555X", | ||
54 | .bits_per_sample = 8, | ||
55 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | ||
56 | .order = SOC_MBUS_ORDER_LE, | ||
57 | }, [MBUS_IDX(RGB565_2X8_LE)] = { | ||
58 | .fourcc = V4L2_PIX_FMT_RGB565, | ||
59 | .name = "RGB565", | ||
60 | .bits_per_sample = 8, | ||
61 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | ||
62 | .order = SOC_MBUS_ORDER_LE, | ||
63 | }, [MBUS_IDX(RGB565_2X8_BE)] = { | ||
64 | .fourcc = V4L2_PIX_FMT_RGB565X, | ||
65 | .name = "RGB565X", | ||
66 | .bits_per_sample = 8, | ||
67 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | ||
68 | .order = SOC_MBUS_ORDER_LE, | ||
69 | }, [MBUS_IDX(SBGGR8_1X8)] = { | ||
70 | .fourcc = V4L2_PIX_FMT_SBGGR8, | ||
71 | .name = "Bayer 8 BGGR", | ||
72 | .bits_per_sample = 8, | ||
73 | .packing = SOC_MBUS_PACKING_NONE, | ||
74 | .order = SOC_MBUS_ORDER_LE, | ||
75 | }, [MBUS_IDX(SBGGR10_1X10)] = { | ||
76 | .fourcc = V4L2_PIX_FMT_SBGGR10, | ||
77 | .name = "Bayer 10 BGGR", | ||
78 | .bits_per_sample = 10, | ||
79 | .packing = SOC_MBUS_PACKING_EXTEND16, | ||
80 | .order = SOC_MBUS_ORDER_LE, | ||
81 | }, [MBUS_IDX(GREY8_1X8)] = { | ||
82 | .fourcc = V4L2_PIX_FMT_GREY, | ||
83 | .name = "Grey", | ||
84 | .bits_per_sample = 8, | ||
85 | .packing = SOC_MBUS_PACKING_NONE, | ||
86 | .order = SOC_MBUS_ORDER_LE, | ||
87 | }, [MBUS_IDX(Y10_1X10)] = { | ||
88 | .fourcc = V4L2_PIX_FMT_Y10, | ||
89 | .name = "Grey 10bit", | ||
90 | .bits_per_sample = 10, | ||
91 | .packing = SOC_MBUS_PACKING_EXTEND16, | ||
92 | .order = SOC_MBUS_ORDER_LE, | ||
93 | }, [MBUS_IDX(SBGGR10_2X8_PADHI_LE)] = { | ||
94 | .fourcc = V4L2_PIX_FMT_SBGGR10, | ||
95 | .name = "Bayer 10 BGGR", | ||
96 | .bits_per_sample = 8, | ||
97 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | ||
98 | .order = SOC_MBUS_ORDER_LE, | ||
99 | }, [MBUS_IDX(SBGGR10_2X8_PADLO_LE)] = { | ||
100 | .fourcc = V4L2_PIX_FMT_SBGGR10, | ||
101 | .name = "Bayer 10 BGGR", | ||
102 | .bits_per_sample = 8, | ||
103 | .packing = SOC_MBUS_PACKING_2X8_PADLO, | ||
104 | .order = SOC_MBUS_ORDER_LE, | ||
105 | }, [MBUS_IDX(SBGGR10_2X8_PADHI_BE)] = { | ||
106 | .fourcc = V4L2_PIX_FMT_SBGGR10, | ||
107 | .name = "Bayer 10 BGGR", | ||
108 | .bits_per_sample = 8, | ||
109 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | ||
110 | .order = SOC_MBUS_ORDER_BE, | ||
111 | }, [MBUS_IDX(SBGGR10_2X8_PADLO_BE)] = { | ||
112 | .fourcc = V4L2_PIX_FMT_SBGGR10, | ||
113 | .name = "Bayer 10 BGGR", | ||
114 | .bits_per_sample = 8, | ||
115 | .packing = SOC_MBUS_PACKING_2X8_PADLO, | ||
116 | .order = SOC_MBUS_ORDER_BE, | ||
117 | }, | ||
118 | }; | ||
119 | |||
120 | s32 soc_mbus_bytes_per_line(u32 width, const struct soc_mbus_pixelfmt *mf) | ||
121 | { | ||
122 | switch (mf->packing) { | ||
123 | case SOC_MBUS_PACKING_NONE: | ||
124 | return width * mf->bits_per_sample / 8; | ||
125 | case SOC_MBUS_PACKING_2X8_PADHI: | ||
126 | case SOC_MBUS_PACKING_2X8_PADLO: | ||
127 | case SOC_MBUS_PACKING_EXTEND16: | ||
128 | return width * 2; | ||
129 | } | ||
130 | return -EINVAL; | ||
131 | } | ||
132 | EXPORT_SYMBOL(soc_mbus_bytes_per_line); | ||
133 | |||
134 | const struct soc_mbus_pixelfmt *soc_mbus_get_fmtdesc( | ||
135 | enum v4l2_mbus_pixelcode code) | ||
136 | { | ||
137 | if ((unsigned int)(code - V4L2_MBUS_FMT_FIXED) > ARRAY_SIZE(mbus_fmt)) | ||
138 | return NULL; | ||
139 | return mbus_fmt + code - V4L2_MBUS_FMT_FIXED - 1; | ||
140 | } | ||
141 | EXPORT_SYMBOL(soc_mbus_get_fmtdesc); | ||
142 | |||
143 | static int __init soc_mbus_init(void) | ||
144 | { | ||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | static void __exit soc_mbus_exit(void) | ||
149 | { | ||
150 | } | ||
151 | |||
152 | module_init(soc_mbus_init); | ||
153 | module_exit(soc_mbus_exit); | ||
154 | |||
155 | MODULE_DESCRIPTION("soc-camera media bus interface"); | ||
156 | MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>"); | ||
157 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/media/video/stk-webcam.c b/drivers/media/video/stk-webcam.c index 6b41865f42bd..f07a0f6b71c4 100644 --- a/drivers/media/video/stk-webcam.c +++ b/drivers/media/video/stk-webcam.c | |||
@@ -1307,7 +1307,6 @@ static void stk_v4l_dev_release(struct video_device *vd) | |||
1307 | 1307 | ||
1308 | static struct video_device stk_v4l_data = { | 1308 | static struct video_device stk_v4l_data = { |
1309 | .name = "stkwebcam", | 1309 | .name = "stkwebcam", |
1310 | .minor = -1, | ||
1311 | .tvnorms = V4L2_STD_UNKNOWN, | 1310 | .tvnorms = V4L2_STD_UNKNOWN, |
1312 | .current_norm = V4L2_STD_UNKNOWN, | 1311 | .current_norm = V4L2_STD_UNKNOWN, |
1313 | .fops = &v4l_stk_fops, | 1312 | .fops = &v4l_stk_fops, |
@@ -1327,8 +1326,8 @@ static int stk_register_video_device(struct stk_camera *dev) | |||
1327 | if (err) | 1326 | if (err) |
1328 | STK_ERROR("v4l registration failed\n"); | 1327 | STK_ERROR("v4l registration failed\n"); |
1329 | else | 1328 | else |
1330 | STK_INFO("Syntek USB2.0 Camera is now controlling video device" | 1329 | STK_INFO("Syntek USB2.0 Camera is now controlling device %s\n", |
1331 | " /dev/video%d\n", dev->vdev.num); | 1330 | video_device_node_name(&dev->vdev)); |
1332 | return err; | 1331 | return err; |
1333 | } | 1332 | } |
1334 | 1333 | ||
@@ -1418,8 +1417,8 @@ static void stk_camera_disconnect(struct usb_interface *interface) | |||
1418 | wake_up_interruptible(&dev->wait_frame); | 1417 | wake_up_interruptible(&dev->wait_frame); |
1419 | stk_remove_sysfs_files(&dev->vdev); | 1418 | stk_remove_sysfs_files(&dev->vdev); |
1420 | 1419 | ||
1421 | STK_INFO("Syntek USB2.0 Camera release resources " | 1420 | STK_INFO("Syntek USB2.0 Camera release resources device %s\n", |
1422 | "video device /dev/video%d\n", dev->vdev.num); | 1421 | video_device_node_name(&dev->vdev)); |
1423 | 1422 | ||
1424 | video_unregister_device(&dev->vdev); | 1423 | video_unregister_device(&dev->vdev); |
1425 | } | 1424 | } |
diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c index eaada39c76fd..a057824e7ebc 100644 --- a/drivers/media/video/stradis.c +++ b/drivers/media/video/stradis.c | |||
@@ -1921,7 +1921,6 @@ static const struct v4l2_file_operations saa_fops = { | |||
1921 | static struct video_device saa_template = { | 1921 | static struct video_device saa_template = { |
1922 | .name = "SAA7146A", | 1922 | .name = "SAA7146A", |
1923 | .fops = &saa_fops, | 1923 | .fops = &saa_fops, |
1924 | .minor = -1, | ||
1925 | .release = video_device_release_empty, | 1924 | .release = video_device_release_empty, |
1926 | }; | 1925 | }; |
1927 | 1926 | ||
@@ -1972,7 +1971,6 @@ static int __devinit configure_saa7146(struct pci_dev *pdev, int num) | |||
1972 | 1971 | ||
1973 | saa->id = pdev->device; | 1972 | saa->id = pdev->device; |
1974 | saa->irq = pdev->irq; | 1973 | saa->irq = pdev->irq; |
1975 | saa->video_dev.minor = -1; | ||
1976 | saa->saa7146_adr = pci_resource_start(pdev, 0); | 1974 | saa->saa7146_adr = pci_resource_start(pdev, 0); |
1977 | pci_read_config_byte(pdev, PCI_CLASS_REVISION, &saa->revision); | 1975 | pci_read_config_byte(pdev, PCI_CLASS_REVISION, &saa->revision); |
1978 | 1976 | ||
@@ -2134,7 +2132,7 @@ static void stradis_release_saa(struct pci_dev *pdev) | |||
2134 | free_irq(saa->irq, saa); | 2132 | free_irq(saa->irq, saa); |
2135 | if (saa->saa7146_mem) | 2133 | if (saa->saa7146_mem) |
2136 | iounmap(saa->saa7146_mem); | 2134 | iounmap(saa->saa7146_mem); |
2137 | if (saa->video_dev.minor != -1) | 2135 | if (video_is_registered(&saa->video_dev)) |
2138 | video_unregister_device(&saa->video_dev); | 2136 | video_unregister_device(&saa->video_dev); |
2139 | } | 2137 | } |
2140 | 2138 | ||
diff --git a/drivers/media/video/stv680.c b/drivers/media/video/stv680.c index 6a91714125d2..5938ad8702ef 100644 --- a/drivers/media/video/stv680.c +++ b/drivers/media/video/stv680.c | |||
@@ -1405,7 +1405,6 @@ static struct video_device stv680_template = { | |||
1405 | .name = "STV0680 USB camera", | 1405 | .name = "STV0680 USB camera", |
1406 | .fops = &stv680_fops, | 1406 | .fops = &stv680_fops, |
1407 | .release = video_device_release, | 1407 | .release = video_device_release, |
1408 | .minor = -1, | ||
1409 | }; | 1408 | }; |
1410 | 1409 | ||
1411 | static int stv680_probe (struct usb_interface *intf, const struct usb_device_id *id) | 1410 | static int stv680_probe (struct usb_interface *intf, const struct usb_device_id *id) |
@@ -1467,8 +1466,8 @@ static int stv680_probe (struct usb_interface *intf, const struct usb_device_id | |||
1467 | retval = -EIO; | 1466 | retval = -EIO; |
1468 | goto error_vdev; | 1467 | goto error_vdev; |
1469 | } | 1468 | } |
1470 | PDEBUG(0, "STV(i): registered new video device: video%d", | 1469 | PDEBUG(0, "STV(i): registered new video device: %s", |
1471 | stv680->vdev->num); | 1470 | video_device_node_name(stv680->vdev)); |
1472 | 1471 | ||
1473 | usb_set_intfdata (intf, stv680); | 1472 | usb_set_intfdata (intf, stv680); |
1474 | retval = stv680_create_sysfs_files(stv680->vdev); | 1473 | retval = stv680_create_sysfs_files(stv680->vdev); |
diff --git a/drivers/media/video/tw9910.c b/drivers/media/video/tw9910.c index 269ab044072a..5b801a6e1eea 100644 --- a/drivers/media/video/tw9910.c +++ b/drivers/media/video/tw9910.c | |||
@@ -29,7 +29,7 @@ | |||
29 | #include <media/tw9910.h> | 29 | #include <media/tw9910.h> |
30 | 30 | ||
31 | #define GET_ID(val) ((val & 0xF8) >> 3) | 31 | #define GET_ID(val) ((val & 0xF8) >> 3) |
32 | #define GET_ReV(val) (val & 0x07) | 32 | #define GET_REV(val) (val & 0x07) |
33 | 33 | ||
34 | /* | 34 | /* |
35 | * register offset | 35 | * register offset |
@@ -117,7 +117,7 @@ | |||
117 | #define LCTL24 0x68 | 117 | #define LCTL24 0x68 |
118 | #define LCTL25 0x69 | 118 | #define LCTL25 0x69 |
119 | #define LCTL26 0x6A | 119 | #define LCTL26 0x6A |
120 | #define HSGEGIN 0x6B | 120 | #define HSBEGIN 0x6B |
121 | #define HSEND 0x6C | 121 | #define HSEND 0x6C |
122 | #define OVSDLY 0x6D | 122 | #define OVSDLY 0x6D |
123 | #define OVSEND 0x6E | 123 | #define OVSEND 0x6E |
@@ -152,7 +152,10 @@ | |||
152 | /* 1 : non-auto */ | 152 | /* 1 : non-auto */ |
153 | #define VSCTL 0x08 /* 1 : Vertical out ctrl by DVALID */ | 153 | #define VSCTL 0x08 /* 1 : Vertical out ctrl by DVALID */ |
154 | /* 0 : Vertical out ctrl by HACTIVE and DVALID */ | 154 | /* 0 : Vertical out ctrl by HACTIVE and DVALID */ |
155 | #define OEN 0x04 /* Output Enable together with TRI_SEL. */ | 155 | #define OEN_TRI_SEL_MASK 0x07 |
156 | #define OEN_TRI_SEL_ALL_ON 0x00 /* Enable output for Rev0/Rev1 */ | ||
157 | #define OEN_TRI_SEL_ALL_OFF_r0 0x06 /* All tri-stated for Rev0 */ | ||
158 | #define OEN_TRI_SEL_ALL_OFF_r1 0x07 /* All tri-stated for Rev1 */ | ||
156 | 159 | ||
157 | /* OUTCTR1 */ | 160 | /* OUTCTR1 */ |
158 | #define VSP_LO 0x00 /* 0 : VS pin output polarity is active low */ | 161 | #define VSP_LO 0x00 /* 0 : VS pin output polarity is active low */ |
@@ -178,11 +181,18 @@ | |||
178 | * but all register content remain unchanged. | 181 | * but all register content remain unchanged. |
179 | * This bit is self-resetting. | 182 | * This bit is self-resetting. |
180 | */ | 183 | */ |
184 | #define ACNTL1_PDN_MASK 0x0e | ||
185 | #define CLK_PDN 0x08 /* system clock power down */ | ||
186 | #define Y_PDN 0x04 /* Luma ADC power down */ | ||
187 | #define C_PDN 0x02 /* Chroma ADC power down */ | ||
188 | |||
189 | /* ACNTL2 */ | ||
190 | #define ACNTL2_PDN_MASK 0x40 | ||
191 | #define PLL_PDN 0x40 /* PLL power down */ | ||
181 | 192 | ||
182 | /* VBICNTL */ | 193 | /* VBICNTL */ |
183 | /* RTSEL : control the real time signal | 194 | |
184 | * output from the MPOUT pin | 195 | /* RTSEL : control the real time signal output from the MPOUT pin */ |
185 | */ | ||
186 | #define RTSEL_MASK 0x07 | 196 | #define RTSEL_MASK 0x07 |
187 | #define RTSEL_VLOSS 0x00 /* 0000 = Video loss */ | 197 | #define RTSEL_VLOSS 0x00 /* 0000 = Video loss */ |
188 | #define RTSEL_HLOCK 0x01 /* 0001 = H-lock */ | 198 | #define RTSEL_HLOCK 0x01 /* 0001 = H-lock */ |
@@ -226,28 +236,7 @@ struct tw9910_priv { | |||
226 | struct v4l2_subdev subdev; | 236 | struct v4l2_subdev subdev; |
227 | struct tw9910_video_info *info; | 237 | struct tw9910_video_info *info; |
228 | const struct tw9910_scale_ctrl *scale; | 238 | const struct tw9910_scale_ctrl *scale; |
229 | }; | 239 | u32 revision; |
230 | |||
231 | /* | ||
232 | * register settings | ||
233 | */ | ||
234 | |||
235 | #define ENDMARKER { 0xff, 0xff } | ||
236 | |||
237 | static const struct regval_list tw9910_default_regs[] = | ||
238 | { | ||
239 | { OPFORM, 0x00 }, | ||
240 | { OUTCTR1, VSP_LO | VSSL_VVALID | HSP_HI | HSSL_HSYNC }, | ||
241 | ENDMARKER, | ||
242 | }; | ||
243 | |||
244 | static const struct soc_camera_data_format tw9910_color_fmt[] = { | ||
245 | { | ||
246 | .name = "VYUY", | ||
247 | .fourcc = V4L2_PIX_FMT_VYUY, | ||
248 | .depth = 16, | ||
249 | .colorspace = V4L2_COLORSPACE_SMPTE170M, | ||
250 | } | ||
251 | }; | 240 | }; |
252 | 241 | ||
253 | static const struct tw9910_scale_ctrl tw9910_ntsc_scales[] = { | 242 | static const struct tw9910_scale_ctrl tw9910_ntsc_scales[] = { |
@@ -340,13 +329,6 @@ static const struct tw9910_scale_ctrl tw9910_pal_scales[] = { | |||
340 | }, | 329 | }, |
341 | }; | 330 | }; |
342 | 331 | ||
343 | static const struct tw9910_cropping_ctrl tw9910_cropping_ctrl = { | ||
344 | .vdelay = 0x0012, | ||
345 | .vactive = 0x00F0, | ||
346 | .hdelay = 0x0010, | ||
347 | .hactive = 0x02D0, | ||
348 | }; | ||
349 | |||
350 | static const struct tw9910_hsync_ctrl tw9910_hsync_ctrl = { | 332 | static const struct tw9910_hsync_ctrl tw9910_hsync_ctrl = { |
351 | .start = 0x0260, | 333 | .start = 0x0260, |
352 | .end = 0x0300, | 334 | .end = 0x0300, |
@@ -361,6 +343,19 @@ static struct tw9910_priv *to_tw9910(const struct i2c_client *client) | |||
361 | subdev); | 343 | subdev); |
362 | } | 344 | } |
363 | 345 | ||
346 | static int tw9910_mask_set(struct i2c_client *client, u8 command, | ||
347 | u8 mask, u8 set) | ||
348 | { | ||
349 | s32 val = i2c_smbus_read_byte_data(client, command); | ||
350 | if (val < 0) | ||
351 | return val; | ||
352 | |||
353 | val &= ~mask; | ||
354 | val |= set & mask; | ||
355 | |||
356 | return i2c_smbus_write_byte_data(client, command, val); | ||
357 | } | ||
358 | |||
364 | static int tw9910_set_scale(struct i2c_client *client, | 359 | static int tw9910_set_scale(struct i2c_client *client, |
365 | const struct tw9910_scale_ctrl *scale) | 360 | const struct tw9910_scale_ctrl *scale) |
366 | { | 361 | { |
@@ -383,47 +378,14 @@ static int tw9910_set_scale(struct i2c_client *client, | |||
383 | return ret; | 378 | return ret; |
384 | } | 379 | } |
385 | 380 | ||
386 | static int tw9910_set_cropping(struct i2c_client *client, | ||
387 | const struct tw9910_cropping_ctrl *cropping) | ||
388 | { | ||
389 | int ret; | ||
390 | |||
391 | ret = i2c_smbus_write_byte_data(client, CROP_HI, | ||
392 | (cropping->vdelay & 0x0300) >> 2 | | ||
393 | (cropping->vactive & 0x0300) >> 4 | | ||
394 | (cropping->hdelay & 0x0300) >> 6 | | ||
395 | (cropping->hactive & 0x0300) >> 8); | ||
396 | if (ret < 0) | ||
397 | return ret; | ||
398 | |||
399 | ret = i2c_smbus_write_byte_data(client, VDELAY_LO, | ||
400 | cropping->vdelay & 0x00FF); | ||
401 | if (ret < 0) | ||
402 | return ret; | ||
403 | |||
404 | ret = i2c_smbus_write_byte_data(client, VACTIVE_LO, | ||
405 | cropping->vactive & 0x00FF); | ||
406 | if (ret < 0) | ||
407 | return ret; | ||
408 | |||
409 | ret = i2c_smbus_write_byte_data(client, HDELAY_LO, | ||
410 | cropping->hdelay & 0x00FF); | ||
411 | if (ret < 0) | ||
412 | return ret; | ||
413 | |||
414 | ret = i2c_smbus_write_byte_data(client, HACTIVE_LO, | ||
415 | cropping->hactive & 0x00FF); | ||
416 | |||
417 | return ret; | ||
418 | } | ||
419 | |||
420 | static int tw9910_set_hsync(struct i2c_client *client, | 381 | static int tw9910_set_hsync(struct i2c_client *client, |
421 | const struct tw9910_hsync_ctrl *hsync) | 382 | const struct tw9910_hsync_ctrl *hsync) |
422 | { | 383 | { |
384 | struct tw9910_priv *priv = to_tw9910(client); | ||
423 | int ret; | 385 | int ret; |
424 | 386 | ||
425 | /* bit 10 - 3 */ | 387 | /* bit 10 - 3 */ |
426 | ret = i2c_smbus_write_byte_data(client, HSGEGIN, | 388 | ret = i2c_smbus_write_byte_data(client, HSBEGIN, |
427 | (hsync->start & 0x07F8) >> 3); | 389 | (hsync->start & 0x07F8) >> 3); |
428 | if (ret < 0) | 390 | if (ret < 0) |
429 | return ret; | 391 | return ret; |
@@ -434,50 +396,41 @@ static int tw9910_set_hsync(struct i2c_client *client, | |||
434 | if (ret < 0) | 396 | if (ret < 0) |
435 | return ret; | 397 | return ret; |
436 | 398 | ||
399 | /* So far only revisions 0 and 1 have been seen */ | ||
437 | /* bit 2 - 0 */ | 400 | /* bit 2 - 0 */ |
438 | ret = i2c_smbus_read_byte_data(client, HSLOWCTL); | 401 | if (1 == priv->revision) |
439 | if (ret < 0) | 402 | ret = tw9910_mask_set(client, HSLOWCTL, 0x77, |
440 | return ret; | 403 | (hsync->start & 0x0007) << 4 | |
441 | 404 | (hsync->end & 0x0007)); | |
442 | ret = i2c_smbus_write_byte_data(client, HSLOWCTL, | ||
443 | (ret & 0x88) | | ||
444 | (hsync->start & 0x0007) << 4 | | ||
445 | (hsync->end & 0x0007)); | ||
446 | 405 | ||
447 | return ret; | 406 | return ret; |
448 | } | 407 | } |
449 | 408 | ||
450 | static int tw9910_write_array(struct i2c_client *client, | 409 | static void tw9910_reset(struct i2c_client *client) |
451 | const struct regval_list *vals) | ||
452 | { | 410 | { |
453 | while (vals->reg_num != 0xff) { | 411 | tw9910_mask_set(client, ACNTL1, SRESET, SRESET); |
454 | int ret = i2c_smbus_write_byte_data(client, | 412 | msleep(1); |
455 | vals->reg_num, | ||
456 | vals->value); | ||
457 | if (ret < 0) | ||
458 | return ret; | ||
459 | vals++; | ||
460 | } | ||
461 | return 0; | ||
462 | } | 413 | } |
463 | 414 | ||
464 | static int tw9910_mask_set(struct i2c_client *client, u8 command, | 415 | static int tw9910_power(struct i2c_client *client, int enable) |
465 | u8 mask, u8 set) | ||
466 | { | 416 | { |
467 | s32 val = i2c_smbus_read_byte_data(client, command); | 417 | int ret; |
468 | if (val < 0) | 418 | u8 acntl1; |
469 | return val; | 419 | u8 acntl2; |
470 | 420 | ||
471 | val &= ~mask; | 421 | if (enable) { |
472 | val |= set & mask; | 422 | acntl1 = 0; |
423 | acntl2 = 0; | ||
424 | } else { | ||
425 | acntl1 = CLK_PDN | Y_PDN | C_PDN; | ||
426 | acntl2 = PLL_PDN; | ||
427 | } | ||
473 | 428 | ||
474 | return i2c_smbus_write_byte_data(client, command, val); | 429 | ret = tw9910_mask_set(client, ACNTL1, ACNTL1_PDN_MASK, acntl1); |
475 | } | 430 | if (ret < 0) |
431 | return ret; | ||
476 | 432 | ||
477 | static void tw9910_reset(struct i2c_client *client) | 433 | return tw9910_mask_set(client, ACNTL2, ACNTL2_PDN_MASK, acntl2); |
478 | { | ||
479 | i2c_smbus_write_byte_data(client, ACNTL1, SRESET); | ||
480 | msleep(1); | ||
481 | } | 434 | } |
482 | 435 | ||
483 | static const struct tw9910_scale_ctrl* | 436 | static const struct tw9910_scale_ctrl* |
@@ -518,27 +471,62 @@ static int tw9910_s_stream(struct v4l2_subdev *sd, int enable) | |||
518 | { | 471 | { |
519 | struct i2c_client *client = sd->priv; | 472 | struct i2c_client *client = sd->priv; |
520 | struct tw9910_priv *priv = to_tw9910(client); | 473 | struct tw9910_priv *priv = to_tw9910(client); |
474 | u8 val; | ||
475 | int ret; | ||
521 | 476 | ||
522 | if (!enable) | 477 | if (!enable) { |
523 | return 0; | 478 | switch (priv->revision) { |
479 | case 0: | ||
480 | val = OEN_TRI_SEL_ALL_OFF_r0; | ||
481 | break; | ||
482 | case 1: | ||
483 | val = OEN_TRI_SEL_ALL_OFF_r1; | ||
484 | break; | ||
485 | default: | ||
486 | dev_err(&client->dev, "un-supported revision\n"); | ||
487 | return -EINVAL; | ||
488 | } | ||
489 | } else { | ||
490 | val = OEN_TRI_SEL_ALL_ON; | ||
524 | 491 | ||
525 | if (!priv->scale) { | 492 | if (!priv->scale) { |
526 | dev_err(&client->dev, "norm select error\n"); | 493 | dev_err(&client->dev, "norm select error\n"); |
527 | return -EPERM; | 494 | return -EPERM; |
495 | } | ||
496 | |||
497 | dev_dbg(&client->dev, "%s %dx%d\n", | ||
498 | priv->scale->name, | ||
499 | priv->scale->width, | ||
500 | priv->scale->height); | ||
528 | } | 501 | } |
529 | 502 | ||
530 | dev_dbg(&client->dev, "%s %dx%d\n", | 503 | ret = tw9910_mask_set(client, OPFORM, OEN_TRI_SEL_MASK, val); |
531 | priv->scale->name, | 504 | if (ret < 0) |
532 | priv->scale->width, | 505 | return ret; |
533 | priv->scale->height); | ||
534 | 506 | ||
535 | return 0; | 507 | return tw9910_power(client, enable); |
536 | } | 508 | } |
537 | 509 | ||
538 | static int tw9910_set_bus_param(struct soc_camera_device *icd, | 510 | static int tw9910_set_bus_param(struct soc_camera_device *icd, |
539 | unsigned long flags) | 511 | unsigned long flags) |
540 | { | 512 | { |
541 | return 0; | 513 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
514 | struct i2c_client *client = sd->priv; | ||
515 | u8 val = VSSL_VVALID | HSSL_DVALID; | ||
516 | |||
517 | /* | ||
518 | * set OUTCTR1 | ||
519 | * | ||
520 | * We use VVALID and DVALID signals to control VSYNC and HSYNC | ||
521 | * outputs, in this mode their polarity is inverted. | ||
522 | */ | ||
523 | if (flags & SOCAM_HSYNC_ACTIVE_LOW) | ||
524 | val |= HSP_HI; | ||
525 | |||
526 | if (flags & SOCAM_VSYNC_ACTIVE_LOW) | ||
527 | val |= VSP_HI; | ||
528 | |||
529 | return i2c_smbus_write_byte_data(client, OUTCTR1, val); | ||
542 | } | 530 | } |
543 | 531 | ||
544 | static unsigned long tw9910_query_bus_param(struct soc_camera_device *icd) | 532 | static unsigned long tw9910_query_bus_param(struct soc_camera_device *icd) |
@@ -548,6 +536,7 @@ static unsigned long tw9910_query_bus_param(struct soc_camera_device *icd) | |||
548 | struct soc_camera_link *icl = to_soc_camera_link(icd); | 536 | struct soc_camera_link *icl = to_soc_camera_link(icd); |
549 | unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER | | 537 | unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER | |
550 | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH | | 538 | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH | |
539 | SOCAM_VSYNC_ACTIVE_LOW | SOCAM_HSYNC_ACTIVE_LOW | | ||
551 | SOCAM_DATA_ACTIVE_HIGH | priv->info->buswidth; | 540 | SOCAM_DATA_ACTIVE_HIGH | priv->info->buswidth; |
552 | 541 | ||
553 | return soc_camera_apply_sensor_flags(icl, flags); | 542 | return soc_camera_apply_sensor_flags(icl, flags); |
@@ -576,8 +565,11 @@ static int tw9910_enum_input(struct soc_camera_device *icd, | |||
576 | static int tw9910_g_chip_ident(struct v4l2_subdev *sd, | 565 | static int tw9910_g_chip_ident(struct v4l2_subdev *sd, |
577 | struct v4l2_dbg_chip_ident *id) | 566 | struct v4l2_dbg_chip_ident *id) |
578 | { | 567 | { |
568 | struct i2c_client *client = sd->priv; | ||
569 | struct tw9910_priv *priv = to_tw9910(client); | ||
570 | |||
579 | id->ident = V4L2_IDENT_TW9910; | 571 | id->ident = V4L2_IDENT_TW9910; |
580 | id->revision = 0; | 572 | id->revision = priv->revision; |
581 | 573 | ||
582 | return 0; | 574 | return 0; |
583 | } | 575 | } |
@@ -596,7 +588,8 @@ static int tw9910_g_register(struct v4l2_subdev *sd, | |||
596 | if (ret < 0) | 588 | if (ret < 0) |
597 | return ret; | 589 | return ret; |
598 | 590 | ||
599 | /* ret = int | 591 | /* |
592 | * ret = int | ||
600 | * reg->val = __u64 | 593 | * reg->val = __u64 |
601 | */ | 594 | */ |
602 | reg->val = (__u64)ret; | 595 | reg->val = (__u64)ret; |
@@ -637,9 +630,6 @@ static int tw9910_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) | |||
637 | * reset hardware | 630 | * reset hardware |
638 | */ | 631 | */ |
639 | tw9910_reset(client); | 632 | tw9910_reset(client); |
640 | ret = tw9910_write_array(client, tw9910_default_regs); | ||
641 | if (ret < 0) | ||
642 | goto tw9910_set_fmt_error; | ||
643 | 633 | ||
644 | /* | 634 | /* |
645 | * set bus width | 635 | * set bus width |
@@ -688,13 +678,6 @@ static int tw9910_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) | |||
688 | goto tw9910_set_fmt_error; | 678 | goto tw9910_set_fmt_error; |
689 | 679 | ||
690 | /* | 680 | /* |
691 | * set cropping | ||
692 | */ | ||
693 | ret = tw9910_set_cropping(client, &tw9910_cropping_ctrl); | ||
694 | if (ret < 0) | ||
695 | goto tw9910_set_fmt_error; | ||
696 | |||
697 | /* | ||
698 | * set hsync | 681 | * set hsync |
699 | */ | 682 | */ |
700 | ret = tw9910_set_hsync(client, &tw9910_hsync_ctrl); | 683 | ret = tw9910_set_hsync(client, &tw9910_hsync_ctrl); |
@@ -762,11 +745,11 @@ static int tw9910_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) | |||
762 | return 0; | 745 | return 0; |
763 | } | 746 | } |
764 | 747 | ||
765 | static int tw9910_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | 748 | static int tw9910_g_fmt(struct v4l2_subdev *sd, |
749 | struct v4l2_mbus_framefmt *mf) | ||
766 | { | 750 | { |
767 | struct i2c_client *client = sd->priv; | 751 | struct i2c_client *client = sd->priv; |
768 | struct tw9910_priv *priv = to_tw9910(client); | 752 | struct tw9910_priv *priv = to_tw9910(client); |
769 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
770 | 753 | ||
771 | if (!priv->scale) { | 754 | if (!priv->scale) { |
772 | int ret; | 755 | int ret; |
@@ -783,74 +766,76 @@ static int tw9910_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | |||
783 | return ret; | 766 | return ret; |
784 | } | 767 | } |
785 | 768 | ||
786 | f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 769 | mf->width = priv->scale->width; |
787 | 770 | mf->height = priv->scale->height; | |
788 | pix->width = priv->scale->width; | 771 | mf->code = V4L2_MBUS_FMT_YUYV8_2X8_BE; |
789 | pix->height = priv->scale->height; | 772 | mf->colorspace = V4L2_COLORSPACE_JPEG; |
790 | pix->pixelformat = V4L2_PIX_FMT_VYUY; | 773 | mf->field = V4L2_FIELD_INTERLACED_BT; |
791 | pix->colorspace = V4L2_COLORSPACE_SMPTE170M; | ||
792 | pix->field = V4L2_FIELD_INTERLACED; | ||
793 | 774 | ||
794 | return 0; | 775 | return 0; |
795 | } | 776 | } |
796 | 777 | ||
797 | static int tw9910_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | 778 | static int tw9910_s_fmt(struct v4l2_subdev *sd, |
779 | struct v4l2_mbus_framefmt *mf) | ||
798 | { | 780 | { |
799 | struct i2c_client *client = sd->priv; | 781 | struct i2c_client *client = sd->priv; |
800 | struct tw9910_priv *priv = to_tw9910(client); | 782 | struct tw9910_priv *priv = to_tw9910(client); |
801 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
802 | /* See tw9910_s_crop() - no proper cropping support */ | 783 | /* See tw9910_s_crop() - no proper cropping support */ |
803 | struct v4l2_crop a = { | 784 | struct v4l2_crop a = { |
804 | .c = { | 785 | .c = { |
805 | .left = 0, | 786 | .left = 0, |
806 | .top = 0, | 787 | .top = 0, |
807 | .width = pix->width, | 788 | .width = mf->width, |
808 | .height = pix->height, | 789 | .height = mf->height, |
809 | }, | 790 | }, |
810 | }; | 791 | }; |
811 | int i, ret; | 792 | int ret; |
793 | |||
794 | WARN_ON(mf->field != V4L2_FIELD_ANY && | ||
795 | mf->field != V4L2_FIELD_INTERLACED_BT); | ||
812 | 796 | ||
813 | /* | 797 | /* |
814 | * check color format | 798 | * check color format |
815 | */ | 799 | */ |
816 | for (i = 0; i < ARRAY_SIZE(tw9910_color_fmt); i++) | 800 | if (mf->code != V4L2_MBUS_FMT_YUYV8_2X8_BE) |
817 | if (pix->pixelformat == tw9910_color_fmt[i].fourcc) | ||
818 | break; | ||
819 | |||
820 | if (i == ARRAY_SIZE(tw9910_color_fmt)) | ||
821 | return -EINVAL; | 801 | return -EINVAL; |
822 | 802 | ||
803 | mf->colorspace = V4L2_COLORSPACE_JPEG; | ||
804 | |||
823 | ret = tw9910_s_crop(sd, &a); | 805 | ret = tw9910_s_crop(sd, &a); |
824 | if (!ret) { | 806 | if (!ret) { |
825 | pix->width = priv->scale->width; | 807 | mf->width = priv->scale->width; |
826 | pix->height = priv->scale->height; | 808 | mf->height = priv->scale->height; |
827 | } | 809 | } |
828 | return ret; | 810 | return ret; |
829 | } | 811 | } |
830 | 812 | ||
831 | static int tw9910_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | 813 | static int tw9910_try_fmt(struct v4l2_subdev *sd, |
814 | struct v4l2_mbus_framefmt *mf) | ||
832 | { | 815 | { |
833 | struct i2c_client *client = sd->priv; | 816 | struct i2c_client *client = sd->priv; |
834 | struct soc_camera_device *icd = client->dev.platform_data; | 817 | struct soc_camera_device *icd = client->dev.platform_data; |
835 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
836 | const struct tw9910_scale_ctrl *scale; | 818 | const struct tw9910_scale_ctrl *scale; |
837 | 819 | ||
838 | if (V4L2_FIELD_ANY == pix->field) { | 820 | if (V4L2_FIELD_ANY == mf->field) { |
839 | pix->field = V4L2_FIELD_INTERLACED; | 821 | mf->field = V4L2_FIELD_INTERLACED_BT; |
840 | } else if (V4L2_FIELD_INTERLACED != pix->field) { | 822 | } else if (V4L2_FIELD_INTERLACED_BT != mf->field) { |
841 | dev_err(&client->dev, "Field type invalid.\n"); | 823 | dev_err(&client->dev, "Field type %d invalid.\n", mf->field); |
842 | return -EINVAL; | 824 | return -EINVAL; |
843 | } | 825 | } |
844 | 826 | ||
827 | mf->code = V4L2_MBUS_FMT_YUYV8_2X8_BE; | ||
828 | mf->colorspace = V4L2_COLORSPACE_JPEG; | ||
829 | |||
845 | /* | 830 | /* |
846 | * select suitable norm | 831 | * select suitable norm |
847 | */ | 832 | */ |
848 | scale = tw9910_select_norm(icd, pix->width, pix->height); | 833 | scale = tw9910_select_norm(icd, mf->width, mf->height); |
849 | if (!scale) | 834 | if (!scale) |
850 | return -EINVAL; | 835 | return -EINVAL; |
851 | 836 | ||
852 | pix->width = scale->width; | 837 | mf->width = scale->width; |
853 | pix->height = scale->height; | 838 | mf->height = scale->height; |
854 | 839 | ||
855 | return 0; | 840 | return 0; |
856 | } | 841 | } |
@@ -859,7 +844,7 @@ static int tw9910_video_probe(struct soc_camera_device *icd, | |||
859 | struct i2c_client *client) | 844 | struct i2c_client *client) |
860 | { | 845 | { |
861 | struct tw9910_priv *priv = to_tw9910(client); | 846 | struct tw9910_priv *priv = to_tw9910(client); |
862 | s32 val; | 847 | s32 id; |
863 | 848 | ||
864 | /* | 849 | /* |
865 | * We must have a parent by now. And it cannot be a wrong one. | 850 | * We must have a parent by now. And it cannot be a wrong one. |
@@ -878,23 +863,24 @@ static int tw9910_video_probe(struct soc_camera_device *icd, | |||
878 | return -ENODEV; | 863 | return -ENODEV; |
879 | } | 864 | } |
880 | 865 | ||
881 | icd->formats = tw9910_color_fmt; | ||
882 | icd->num_formats = ARRAY_SIZE(tw9910_color_fmt); | ||
883 | |||
884 | /* | 866 | /* |
885 | * check and show Product ID | 867 | * check and show Product ID |
868 | * So far only revisions 0 and 1 have been seen | ||
886 | */ | 869 | */ |
887 | val = i2c_smbus_read_byte_data(client, ID); | 870 | id = i2c_smbus_read_byte_data(client, ID); |
871 | priv->revision = GET_REV(id); | ||
872 | id = GET_ID(id); | ||
888 | 873 | ||
889 | if (0x0B != GET_ID(val) || | 874 | if (0x0B != id || |
890 | 0x00 != GET_ReV(val)) { | 875 | 0x01 < priv->revision) { |
891 | dev_err(&client->dev, | 876 | dev_err(&client->dev, |
892 | "Product ID error %x:%x\n", GET_ID(val), GET_ReV(val)); | 877 | "Product ID error %x:%x\n", |
878 | id, priv->revision); | ||
893 | return -ENODEV; | 879 | return -ENODEV; |
894 | } | 880 | } |
895 | 881 | ||
896 | dev_info(&client->dev, | 882 | dev_info(&client->dev, |
897 | "tw9910 Product ID %0x:%0x\n", GET_ID(val), GET_ReV(val)); | 883 | "tw9910 Product ID %0x:%0x\n", id, priv->revision); |
898 | 884 | ||
899 | icd->vdev->tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL; | 885 | icd->vdev->tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL; |
900 | icd->vdev->current_norm = V4L2_STD_NTSC; | 886 | icd->vdev->current_norm = V4L2_STD_NTSC; |
@@ -917,14 +903,25 @@ static struct v4l2_subdev_core_ops tw9910_subdev_core_ops = { | |||
917 | #endif | 903 | #endif |
918 | }; | 904 | }; |
919 | 905 | ||
906 | static int tw9910_enum_fmt(struct v4l2_subdev *sd, int index, | ||
907 | enum v4l2_mbus_pixelcode *code) | ||
908 | { | ||
909 | if (index) | ||
910 | return -EINVAL; | ||
911 | |||
912 | *code = V4L2_MBUS_FMT_YUYV8_2X8_BE; | ||
913 | return 0; | ||
914 | } | ||
915 | |||
920 | static struct v4l2_subdev_video_ops tw9910_subdev_video_ops = { | 916 | static struct v4l2_subdev_video_ops tw9910_subdev_video_ops = { |
921 | .s_stream = tw9910_s_stream, | 917 | .s_stream = tw9910_s_stream, |
922 | .g_fmt = tw9910_g_fmt, | 918 | .g_mbus_fmt = tw9910_g_fmt, |
923 | .s_fmt = tw9910_s_fmt, | 919 | .s_mbus_fmt = tw9910_s_fmt, |
924 | .try_fmt = tw9910_try_fmt, | 920 | .try_mbus_fmt = tw9910_try_fmt, |
925 | .cropcap = tw9910_cropcap, | 921 | .cropcap = tw9910_cropcap, |
926 | .g_crop = tw9910_g_crop, | 922 | .g_crop = tw9910_g_crop, |
927 | .s_crop = tw9910_s_crop, | 923 | .s_crop = tw9910_s_crop, |
924 | .enum_mbus_fmt = tw9910_enum_fmt, | ||
928 | }; | 925 | }; |
929 | 926 | ||
930 | static struct v4l2_subdev_ops tw9910_subdev_ops = { | 927 | static struct v4l2_subdev_ops tw9910_subdev_ops = { |
@@ -954,10 +951,10 @@ static int tw9910_probe(struct i2c_client *client, | |||
954 | } | 951 | } |
955 | 952 | ||
956 | icl = to_soc_camera_link(icd); | 953 | icl = to_soc_camera_link(icd); |
957 | if (!icl) | 954 | if (!icl || !icl->priv) |
958 | return -EINVAL; | 955 | return -EINVAL; |
959 | 956 | ||
960 | info = container_of(icl, struct tw9910_video_info, link); | 957 | info = icl->priv; |
961 | 958 | ||
962 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { | 959 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { |
963 | dev_err(&client->dev, | 960 | dev_err(&client->dev, |
@@ -975,7 +972,7 @@ static int tw9910_probe(struct i2c_client *client, | |||
975 | v4l2_i2c_subdev_init(&priv->subdev, client, &tw9910_subdev_ops); | 972 | v4l2_i2c_subdev_init(&priv->subdev, client, &tw9910_subdev_ops); |
976 | 973 | ||
977 | icd->ops = &tw9910_ops; | 974 | icd->ops = &tw9910_ops; |
978 | icd->iface = info->link.bus_id; | 975 | icd->iface = icl->bus_id; |
979 | 976 | ||
980 | ret = tw9910_video_probe(icd, client); | 977 | ret = tw9910_video_probe(icd, client); |
981 | if (ret) { | 978 | if (ret) { |
diff --git a/drivers/media/video/usbvideo/usbvideo.c b/drivers/media/video/usbvideo/usbvideo.c index dea8b321fb4a..5ac37c6c4313 100644 --- a/drivers/media/video/usbvideo/usbvideo.c +++ b/drivers/media/video/usbvideo/usbvideo.c | |||
@@ -1053,9 +1053,9 @@ int usbvideo_RegisterVideoDevice(struct uvd *uvd) | |||
1053 | "%s: video_register_device() successful\n", __func__); | 1053 | "%s: video_register_device() successful\n", __func__); |
1054 | } | 1054 | } |
1055 | 1055 | ||
1056 | dev_info(&uvd->dev->dev, "%s on /dev/video%d: canvas=%s videosize=%s\n", | 1056 | dev_info(&uvd->dev->dev, "%s on %s: canvas=%s videosize=%s\n", |
1057 | (uvd->handle != NULL) ? uvd->handle->drvName : "???", | 1057 | (uvd->handle != NULL) ? uvd->handle->drvName : "???", |
1058 | uvd->vdev.num, tmp2, tmp1); | 1058 | video_device_node_name(&uvd->vdev), tmp2, tmp1); |
1059 | 1059 | ||
1060 | usb_get_dev(uvd->dev); | 1060 | usb_get_dev(uvd->dev); |
1061 | return 0; | 1061 | return 0; |
diff --git a/drivers/media/video/usbvideo/vicam.c b/drivers/media/video/usbvideo/vicam.c index 45fce39ec9ad..6030410c6677 100644 --- a/drivers/media/video/usbvideo/vicam.c +++ b/drivers/media/video/usbvideo/vicam.c | |||
@@ -796,7 +796,6 @@ static const struct v4l2_file_operations vicam_fops = { | |||
796 | static struct video_device vicam_template = { | 796 | static struct video_device vicam_template = { |
797 | .name = "ViCam-based USB Camera", | 797 | .name = "ViCam-based USB Camera", |
798 | .fops = &vicam_fops, | 798 | .fops = &vicam_fops, |
799 | .minor = -1, | ||
800 | .release = video_device_release_empty, | 799 | .release = video_device_release_empty, |
801 | }; | 800 | }; |
802 | 801 | ||
@@ -873,8 +872,8 @@ vicam_probe( struct usb_interface *intf, const struct usb_device_id *id) | |||
873 | return -EIO; | 872 | return -EIO; |
874 | } | 873 | } |
875 | 874 | ||
876 | printk(KERN_INFO "ViCam webcam driver now controlling video device %d\n", | 875 | printk(KERN_INFO "ViCam webcam driver now controlling device %s\n", |
877 | cam->vdev.num); | 876 | video_device_node_name(&cam->vdev)); |
878 | 877 | ||
879 | usb_set_intfdata (intf, cam); | 878 | usb_set_intfdata (intf, cam); |
880 | 879 | ||
diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c index c19f51dba2ee..0613922997e0 100644 --- a/drivers/media/video/usbvision/usbvision-i2c.c +++ b/drivers/media/video/usbvision/usbvision-i2c.c | |||
@@ -215,8 +215,8 @@ int usbvision_i2c_register(struct usb_usbvision *usbvision) | |||
215 | memcpy(&usbvision->i2c_adap, &i2c_adap_template, | 215 | memcpy(&usbvision->i2c_adap, &i2c_adap_template, |
216 | sizeof(struct i2c_adapter)); | 216 | sizeof(struct i2c_adapter)); |
217 | 217 | ||
218 | sprintf(usbvision->i2c_adap.name + strlen(usbvision->i2c_adap.name), | 218 | sprintf(usbvision->i2c_adap.name, "%s-%d-%s", i2c_adap_template.name, |
219 | " #%d", usbvision->vdev->num); | 219 | usbvision->dev->bus->busnum, usbvision->dev->devpath); |
220 | PDEBUG(DBG_I2C,"Adaptername: %s", usbvision->i2c_adap.name); | 220 | PDEBUG(DBG_I2C,"Adaptername: %s", usbvision->i2c_adap.name); |
221 | usbvision->i2c_adap.dev.parent = &usbvision->dev->dev; | 221 | usbvision->i2c_adap.dev.parent = &usbvision->dev->dev; |
222 | 222 | ||
diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index c07b0ac452ab..1054546db908 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c | |||
@@ -1328,7 +1328,6 @@ static struct video_device usbvision_video_template = { | |||
1328 | .ioctl_ops = &usbvision_ioctl_ops, | 1328 | .ioctl_ops = &usbvision_ioctl_ops, |
1329 | .name = "usbvision-video", | 1329 | .name = "usbvision-video", |
1330 | .release = video_device_release, | 1330 | .release = video_device_release, |
1331 | .minor = -1, | ||
1332 | .tvnorms = USBVISION_NORMS, | 1331 | .tvnorms = USBVISION_NORMS, |
1333 | .current_norm = V4L2_STD_PAL | 1332 | .current_norm = V4L2_STD_PAL |
1334 | }; | 1333 | }; |
@@ -1362,7 +1361,6 @@ static struct video_device usbvision_radio_template = { | |||
1362 | .fops = &usbvision_radio_fops, | 1361 | .fops = &usbvision_radio_fops, |
1363 | .name = "usbvision-radio", | 1362 | .name = "usbvision-radio", |
1364 | .release = video_device_release, | 1363 | .release = video_device_release, |
1365 | .minor = -1, | ||
1366 | .ioctl_ops = &usbvision_radio_ioctl_ops, | 1364 | .ioctl_ops = &usbvision_radio_ioctl_ops, |
1367 | 1365 | ||
1368 | .tvnorms = USBVISION_NORMS, | 1366 | .tvnorms = USBVISION_NORMS, |
@@ -1382,7 +1380,6 @@ static struct video_device usbvision_vbi_template= | |||
1382 | .fops = &usbvision_vbi_fops, | 1380 | .fops = &usbvision_vbi_fops, |
1383 | .release = video_device_release, | 1381 | .release = video_device_release, |
1384 | .name = "usbvision-vbi", | 1382 | .name = "usbvision-vbi", |
1385 | .minor = -1, | ||
1386 | }; | 1383 | }; |
1387 | 1384 | ||
1388 | 1385 | ||
@@ -1404,7 +1401,6 @@ static struct video_device *usbvision_vdev_init(struct usb_usbvision *usbvision, | |||
1404 | return NULL; | 1401 | return NULL; |
1405 | } | 1402 | } |
1406 | *vdev = *vdev_template; | 1403 | *vdev = *vdev_template; |
1407 | // vdev->minor = -1; | ||
1408 | vdev->v4l2_dev = &usbvision->v4l2_dev; | 1404 | vdev->v4l2_dev = &usbvision->v4l2_dev; |
1409 | snprintf(vdev->name, sizeof(vdev->name), "%s", name); | 1405 | snprintf(vdev->name, sizeof(vdev->name), "%s", name); |
1410 | video_set_drvdata(vdev, usbvision); | 1406 | video_set_drvdata(vdev, usbvision); |
@@ -1416,9 +1412,9 @@ static void usbvision_unregister_video(struct usb_usbvision *usbvision) | |||
1416 | { | 1412 | { |
1417 | // vbi Device: | 1413 | // vbi Device: |
1418 | if (usbvision->vbi) { | 1414 | if (usbvision->vbi) { |
1419 | PDEBUG(DBG_PROBE, "unregister /dev/vbi%d [v4l2]", | 1415 | PDEBUG(DBG_PROBE, "unregister %s [v4l2]", |
1420 | usbvision->vbi->num); | 1416 | video_device_node_name(usbvision->vbi)); |
1421 | if (usbvision->vbi->minor != -1) { | 1417 | if (video_is_registered(usbvision->vbi)) { |
1422 | video_unregister_device(usbvision->vbi); | 1418 | video_unregister_device(usbvision->vbi); |
1423 | } else { | 1419 | } else { |
1424 | video_device_release(usbvision->vbi); | 1420 | video_device_release(usbvision->vbi); |
@@ -1428,9 +1424,9 @@ static void usbvision_unregister_video(struct usb_usbvision *usbvision) | |||
1428 | 1424 | ||
1429 | // Radio Device: | 1425 | // Radio Device: |
1430 | if (usbvision->rdev) { | 1426 | if (usbvision->rdev) { |
1431 | PDEBUG(DBG_PROBE, "unregister /dev/radio%d [v4l2]", | 1427 | PDEBUG(DBG_PROBE, "unregister %s [v4l2]", |
1432 | usbvision->rdev->num); | 1428 | video_device_node_name(usbvision->rdev)); |
1433 | if (usbvision->rdev->minor != -1) { | 1429 | if (video_is_registered(usbvision->rdev)) { |
1434 | video_unregister_device(usbvision->rdev); | 1430 | video_unregister_device(usbvision->rdev); |
1435 | } else { | 1431 | } else { |
1436 | video_device_release(usbvision->rdev); | 1432 | video_device_release(usbvision->rdev); |
@@ -1440,9 +1436,9 @@ static void usbvision_unregister_video(struct usb_usbvision *usbvision) | |||
1440 | 1436 | ||
1441 | // Video Device: | 1437 | // Video Device: |
1442 | if (usbvision->vdev) { | 1438 | if (usbvision->vdev) { |
1443 | PDEBUG(DBG_PROBE, "unregister /dev/video%d [v4l2]", | 1439 | PDEBUG(DBG_PROBE, "unregister %s [v4l2]", |
1444 | usbvision->vdev->num); | 1440 | video_device_node_name(usbvision->vdev)); |
1445 | if (usbvision->vdev->minor != -1) { | 1441 | if (video_is_registered(usbvision->vdev)) { |
1446 | video_unregister_device(usbvision->vdev); | 1442 | video_unregister_device(usbvision->vdev); |
1447 | } else { | 1443 | } else { |
1448 | video_device_release(usbvision->vdev); | 1444 | video_device_release(usbvision->vdev); |
@@ -1466,8 +1462,8 @@ static int __devinit usbvision_register_video(struct usb_usbvision *usbvision) | |||
1466 | video_nr)<0) { | 1462 | video_nr)<0) { |
1467 | goto err_exit; | 1463 | goto err_exit; |
1468 | } | 1464 | } |
1469 | printk(KERN_INFO "USBVision[%d]: registered USBVision Video device /dev/video%d [v4l2]\n", | 1465 | printk(KERN_INFO "USBVision[%d]: registered USBVision Video device %s [v4l2]\n", |
1470 | usbvision->nr, usbvision->vdev->num); | 1466 | usbvision->nr, video_device_node_name(usbvision->vdev)); |
1471 | 1467 | ||
1472 | // Radio Device: | 1468 | // Radio Device: |
1473 | if (usbvision_device_data[usbvision->DevModel].Radio) { | 1469 | if (usbvision_device_data[usbvision->DevModel].Radio) { |
@@ -1483,8 +1479,8 @@ static int __devinit usbvision_register_video(struct usb_usbvision *usbvision) | |||
1483 | radio_nr)<0) { | 1479 | radio_nr)<0) { |
1484 | goto err_exit; | 1480 | goto err_exit; |
1485 | } | 1481 | } |
1486 | printk(KERN_INFO "USBVision[%d]: registered USBVision Radio device /dev/radio%d [v4l2]\n", | 1482 | printk(KERN_INFO "USBVision[%d]: registered USBVision Radio device %s [v4l2]\n", |
1487 | usbvision->nr, usbvision->rdev->num); | 1483 | usbvision->nr, video_device_node_name(usbvision->rdev)); |
1488 | } | 1484 | } |
1489 | // vbi Device: | 1485 | // vbi Device: |
1490 | if (usbvision_device_data[usbvision->DevModel].vbi) { | 1486 | if (usbvision_device_data[usbvision->DevModel].vbi) { |
@@ -1499,8 +1495,8 @@ static int __devinit usbvision_register_video(struct usb_usbvision *usbvision) | |||
1499 | vbi_nr)<0) { | 1495 | vbi_nr)<0) { |
1500 | goto err_exit; | 1496 | goto err_exit; |
1501 | } | 1497 | } |
1502 | printk(KERN_INFO "USBVision[%d]: registered USBVision VBI device /dev/vbi%d [v4l2] (Not Working Yet!)\n", | 1498 | printk(KERN_INFO "USBVision[%d]: registered USBVision VBI device %s [v4l2] (Not Working Yet!)\n", |
1503 | usbvision->nr, usbvision->vbi->num); | 1499 | usbvision->nr, video_device_node_name(usbvision->vbi)); |
1504 | } | 1500 | } |
1505 | // all done | 1501 | // all done |
1506 | return 0; | 1502 | return 0; |
diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c index 0469d7a876a8..ec8ef8c5560a 100644 --- a/drivers/media/video/uvc/uvc_ctrl.c +++ b/drivers/media/video/uvc/uvc_ctrl.c | |||
@@ -1393,7 +1393,7 @@ uvc_ctrl_prune_entity(struct uvc_device *dev, struct uvc_entity *entity) | |||
1393 | size = entity->processing.bControlSize; | 1393 | size = entity->processing.bControlSize; |
1394 | 1394 | ||
1395 | for (i = 0; i < ARRAY_SIZE(blacklist); ++i) { | 1395 | for (i = 0; i < ARRAY_SIZE(blacklist); ++i) { |
1396 | if (!usb_match_id(dev->intf, &blacklist[i].id)) | 1396 | if (!usb_match_one_id(dev->intf, &blacklist[i].id)) |
1397 | continue; | 1397 | continue; |
1398 | 1398 | ||
1399 | if (blacklist[i].index >= 8 * size || | 1399 | if (blacklist[i].index >= 8 * size || |
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index c31bc50113bc..391cccca7ffc 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c | |||
@@ -1651,7 +1651,6 @@ static int uvc_register_video(struct uvc_device *dev, | |||
1651 | * get another one. | 1651 | * get another one. |
1652 | */ | 1652 | */ |
1653 | vdev->parent = &dev->intf->dev; | 1653 | vdev->parent = &dev->intf->dev; |
1654 | vdev->minor = -1; | ||
1655 | vdev->fops = &uvc_fops; | 1654 | vdev->fops = &uvc_fops; |
1656 | vdev->release = uvc_release; | 1655 | vdev->release = uvc_release; |
1657 | strlcpy(vdev->name, dev->name, sizeof vdev->name); | 1656 | strlcpy(vdev->name, dev->name, sizeof vdev->name); |
diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c index f854698c4061..ea11839cba4a 100644 --- a/drivers/media/video/uvc/uvc_queue.c +++ b/drivers/media/video/uvc/uvc_queue.c | |||
@@ -59,9 +59,9 @@ | |||
59 | * returns immediately. | 59 | * returns immediately. |
60 | * | 60 | * |
61 | * When the buffer is full, the completion handler removes it from the irq | 61 | * When the buffer is full, the completion handler removes it from the irq |
62 | * queue, marks it as ready (UVC_BUF_STATE_DONE) and wakes its wait queue. | 62 | * queue, marks it as done (UVC_BUF_STATE_DONE) and wakes its wait queue. |
63 | * At that point, any process waiting on the buffer will be woken up. If a | 63 | * At that point, any process waiting on the buffer will be woken up. If a |
64 | * process tries to dequeue a buffer after it has been marked ready, the | 64 | * process tries to dequeue a buffer after it has been marked done, the |
65 | * dequeing will succeed immediately. | 65 | * dequeing will succeed immediately. |
66 | * | 66 | * |
67 | * 2. Buffers are queued, user is waiting on a buffer and the device gets | 67 | * 2. Buffers are queued, user is waiting on a buffer and the device gets |
@@ -201,6 +201,7 @@ static void __uvc_query_buffer(struct uvc_buffer *buf, | |||
201 | break; | 201 | break; |
202 | case UVC_BUF_STATE_QUEUED: | 202 | case UVC_BUF_STATE_QUEUED: |
203 | case UVC_BUF_STATE_ACTIVE: | 203 | case UVC_BUF_STATE_ACTIVE: |
204 | case UVC_BUF_STATE_READY: | ||
204 | v4l2_buf->flags |= V4L2_BUF_FLAG_QUEUED; | 205 | v4l2_buf->flags |= V4L2_BUF_FLAG_QUEUED; |
205 | break; | 206 | break; |
206 | case UVC_BUF_STATE_IDLE: | 207 | case UVC_BUF_STATE_IDLE: |
@@ -295,13 +296,15 @@ static int uvc_queue_waiton(struct uvc_buffer *buf, int nonblocking) | |||
295 | { | 296 | { |
296 | if (nonblocking) { | 297 | if (nonblocking) { |
297 | return (buf->state != UVC_BUF_STATE_QUEUED && | 298 | return (buf->state != UVC_BUF_STATE_QUEUED && |
298 | buf->state != UVC_BUF_STATE_ACTIVE) | 299 | buf->state != UVC_BUF_STATE_ACTIVE && |
300 | buf->state != UVC_BUF_STATE_READY) | ||
299 | ? 0 : -EAGAIN; | 301 | ? 0 : -EAGAIN; |
300 | } | 302 | } |
301 | 303 | ||
302 | return wait_event_interruptible(buf->wait, | 304 | return wait_event_interruptible(buf->wait, |
303 | buf->state != UVC_BUF_STATE_QUEUED && | 305 | buf->state != UVC_BUF_STATE_QUEUED && |
304 | buf->state != UVC_BUF_STATE_ACTIVE); | 306 | buf->state != UVC_BUF_STATE_ACTIVE && |
307 | buf->state != UVC_BUF_STATE_READY); | ||
305 | } | 308 | } |
306 | 309 | ||
307 | /* | 310 | /* |
@@ -348,6 +351,7 @@ int uvc_dequeue_buffer(struct uvc_video_queue *queue, | |||
348 | case UVC_BUF_STATE_IDLE: | 351 | case UVC_BUF_STATE_IDLE: |
349 | case UVC_BUF_STATE_QUEUED: | 352 | case UVC_BUF_STATE_QUEUED: |
350 | case UVC_BUF_STATE_ACTIVE: | 353 | case UVC_BUF_STATE_ACTIVE: |
354 | case UVC_BUF_STATE_READY: | ||
351 | default: | 355 | default: |
352 | uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer state %u " | 356 | uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer state %u " |
353 | "(driver bug?).\n", buf->state); | 357 | "(driver bug?).\n", buf->state); |
@@ -489,6 +493,7 @@ struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, | |||
489 | 493 | ||
490 | spin_lock_irqsave(&queue->irqlock, flags); | 494 | spin_lock_irqsave(&queue->irqlock, flags); |
491 | list_del(&buf->queue); | 495 | list_del(&buf->queue); |
496 | buf->state = UVC_BUF_STATE_DONE; | ||
492 | if (!list_empty(&queue->irqqueue)) | 497 | if (!list_empty(&queue->irqqueue)) |
493 | nextbuf = list_first_entry(&queue->irqqueue, struct uvc_buffer, | 498 | nextbuf = list_first_entry(&queue->irqqueue, struct uvc_buffer, |
494 | queue); | 499 | queue); |
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index 05139a4f14f6..7dcf534a0cf3 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c | |||
@@ -145,7 +145,7 @@ static int uvc_get_video_ctrl(struct uvc_streaming *stream, | |||
145 | uvc_warn_once(stream->dev, UVC_WARN_MINMAX, "UVC non " | 145 | uvc_warn_once(stream->dev, UVC_WARN_MINMAX, "UVC non " |
146 | "compliance - GET_MIN/MAX(PROBE) incorrectly " | 146 | "compliance - GET_MIN/MAX(PROBE) incorrectly " |
147 | "supported. Enabling workaround.\n"); | 147 | "supported. Enabling workaround.\n"); |
148 | memset(ctrl, 0, sizeof ctrl); | 148 | memset(ctrl, 0, sizeof *ctrl); |
149 | ctrl->wCompQuality = le16_to_cpup((__le16 *)data); | 149 | ctrl->wCompQuality = le16_to_cpup((__le16 *)data); |
150 | ret = 0; | 150 | ret = 0; |
151 | goto out; | 151 | goto out; |
@@ -441,7 +441,7 @@ static int uvc_video_decode_start(struct uvc_streaming *stream, | |||
441 | if (fid != stream->last_fid && buf->buf.bytesused != 0) { | 441 | if (fid != stream->last_fid && buf->buf.bytesused != 0) { |
442 | uvc_trace(UVC_TRACE_FRAME, "Frame complete (FID bit " | 442 | uvc_trace(UVC_TRACE_FRAME, "Frame complete (FID bit " |
443 | "toggled).\n"); | 443 | "toggled).\n"); |
444 | buf->state = UVC_BUF_STATE_DONE; | 444 | buf->state = UVC_BUF_STATE_READY; |
445 | return -EAGAIN; | 445 | return -EAGAIN; |
446 | } | 446 | } |
447 | 447 | ||
@@ -470,7 +470,7 @@ static void uvc_video_decode_data(struct uvc_streaming *stream, | |||
470 | /* Complete the current frame if the buffer size was exceeded. */ | 470 | /* Complete the current frame if the buffer size was exceeded. */ |
471 | if (len > maxlen) { | 471 | if (len > maxlen) { |
472 | uvc_trace(UVC_TRACE_FRAME, "Frame complete (overflow).\n"); | 472 | uvc_trace(UVC_TRACE_FRAME, "Frame complete (overflow).\n"); |
473 | buf->state = UVC_BUF_STATE_DONE; | 473 | buf->state = UVC_BUF_STATE_READY; |
474 | } | 474 | } |
475 | } | 475 | } |
476 | 476 | ||
@@ -482,7 +482,7 @@ static void uvc_video_decode_end(struct uvc_streaming *stream, | |||
482 | uvc_trace(UVC_TRACE_FRAME, "Frame complete (EOF found).\n"); | 482 | uvc_trace(UVC_TRACE_FRAME, "Frame complete (EOF found).\n"); |
483 | if (data[0] == len) | 483 | if (data[0] == len) |
484 | uvc_trace(UVC_TRACE_FRAME, "EOF in empty payload.\n"); | 484 | uvc_trace(UVC_TRACE_FRAME, "EOF in empty payload.\n"); |
485 | buf->state = UVC_BUF_STATE_DONE; | 485 | buf->state = UVC_BUF_STATE_READY; |
486 | if (stream->dev->quirks & UVC_QUIRK_STREAM_NO_FID) | 486 | if (stream->dev->quirks & UVC_QUIRK_STREAM_NO_FID) |
487 | stream->last_fid ^= UVC_STREAM_FID; | 487 | stream->last_fid ^= UVC_STREAM_FID; |
488 | } | 488 | } |
@@ -568,8 +568,7 @@ static void uvc_video_decode_isoc(struct urb *urb, struct uvc_streaming *stream, | |||
568 | uvc_video_decode_end(stream, buf, mem, | 568 | uvc_video_decode_end(stream, buf, mem, |
569 | urb->iso_frame_desc[i].actual_length); | 569 | urb->iso_frame_desc[i].actual_length); |
570 | 570 | ||
571 | if (buf->state == UVC_BUF_STATE_DONE || | 571 | if (buf->state == UVC_BUF_STATE_READY) |
572 | buf->state == UVC_BUF_STATE_ERROR) | ||
573 | buf = uvc_queue_next_buffer(&stream->queue, buf); | 572 | buf = uvc_queue_next_buffer(&stream->queue, buf); |
574 | } | 573 | } |
575 | } | 574 | } |
@@ -627,8 +626,7 @@ static void uvc_video_decode_bulk(struct urb *urb, struct uvc_streaming *stream, | |||
627 | if (!stream->bulk.skip_payload && buf != NULL) { | 626 | if (!stream->bulk.skip_payload && buf != NULL) { |
628 | uvc_video_decode_end(stream, buf, stream->bulk.header, | 627 | uvc_video_decode_end(stream, buf, stream->bulk.header, |
629 | stream->bulk.payload_size); | 628 | stream->bulk.payload_size); |
630 | if (buf->state == UVC_BUF_STATE_DONE || | 629 | if (buf->state == UVC_BUF_STATE_READY) |
631 | buf->state == UVC_BUF_STATE_ERROR) | ||
632 | buf = uvc_queue_next_buffer(&stream->queue, | 630 | buf = uvc_queue_next_buffer(&stream->queue, |
633 | buf); | 631 | buf); |
634 | } | 632 | } |
@@ -669,7 +667,7 @@ static void uvc_video_encode_bulk(struct urb *urb, struct uvc_streaming *stream, | |||
669 | stream->bulk.payload_size == stream->bulk.max_payload_size) { | 667 | stream->bulk.payload_size == stream->bulk.max_payload_size) { |
670 | if (buf->buf.bytesused == stream->queue.buf_used) { | 668 | if (buf->buf.bytesused == stream->queue.buf_used) { |
671 | stream->queue.buf_used = 0; | 669 | stream->queue.buf_used = 0; |
672 | buf->state = UVC_BUF_STATE_DONE; | 670 | buf->state = UVC_BUF_STATE_READY; |
673 | uvc_queue_next_buffer(&stream->queue, buf); | 671 | uvc_queue_next_buffer(&stream->queue, buf); |
674 | stream->last_fid ^= UVC_STREAM_FID; | 672 | stream->last_fid ^= UVC_STREAM_FID; |
675 | } | 673 | } |
@@ -924,10 +922,8 @@ static int uvc_init_video_bulk(struct uvc_streaming *stream, | |||
924 | static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags) | 922 | static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags) |
925 | { | 923 | { |
926 | struct usb_interface *intf = stream->intf; | 924 | struct usb_interface *intf = stream->intf; |
927 | struct usb_host_interface *alts; | 925 | struct usb_host_endpoint *ep; |
928 | struct usb_host_endpoint *ep = NULL; | 926 | unsigned int i; |
929 | int intfnum = stream->intfnum; | ||
930 | unsigned int bandwidth, psize, i; | ||
931 | int ret; | 927 | int ret; |
932 | 928 | ||
933 | stream->last_fid = -1; | 929 | stream->last_fid = -1; |
@@ -936,6 +932,12 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags) | |||
936 | stream->bulk.payload_size = 0; | 932 | stream->bulk.payload_size = 0; |
937 | 933 | ||
938 | if (intf->num_altsetting > 1) { | 934 | if (intf->num_altsetting > 1) { |
935 | struct usb_host_endpoint *best_ep = NULL; | ||
936 | unsigned int best_psize = 3 * 1024; | ||
937 | unsigned int bandwidth; | ||
938 | unsigned int uninitialized_var(altsetting); | ||
939 | int intfnum = stream->intfnum; | ||
940 | |||
939 | /* Isochronous endpoint, select the alternate setting. */ | 941 | /* Isochronous endpoint, select the alternate setting. */ |
940 | bandwidth = stream->ctrl.dwMaxPayloadTransferSize; | 942 | bandwidth = stream->ctrl.dwMaxPayloadTransferSize; |
941 | 943 | ||
@@ -949,6 +951,9 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags) | |||
949 | } | 951 | } |
950 | 952 | ||
951 | for (i = 0; i < intf->num_altsetting; ++i) { | 953 | for (i = 0; i < intf->num_altsetting; ++i) { |
954 | struct usb_host_interface *alts; | ||
955 | unsigned int psize; | ||
956 | |||
952 | alts = &intf->altsetting[i]; | 957 | alts = &intf->altsetting[i]; |
953 | ep = uvc_find_endpoint(alts, | 958 | ep = uvc_find_endpoint(alts, |
954 | stream->header.bEndpointAddress); | 959 | stream->header.bEndpointAddress); |
@@ -958,21 +963,27 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags) | |||
958 | /* Check if the bandwidth is high enough. */ | 963 | /* Check if the bandwidth is high enough. */ |
959 | psize = le16_to_cpu(ep->desc.wMaxPacketSize); | 964 | psize = le16_to_cpu(ep->desc.wMaxPacketSize); |
960 | psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); | 965 | psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); |
961 | if (psize >= bandwidth) | 966 | if (psize >= bandwidth && psize <= best_psize) { |
962 | break; | 967 | altsetting = i; |
968 | best_psize = psize; | ||
969 | best_ep = ep; | ||
970 | } | ||
963 | } | 971 | } |
964 | 972 | ||
965 | if (i >= intf->num_altsetting) { | 973 | if (best_ep == NULL) { |
966 | uvc_trace(UVC_TRACE_VIDEO, "No fast enough alt setting " | 974 | uvc_trace(UVC_TRACE_VIDEO, "No fast enough alt setting " |
967 | "for requested bandwidth.\n"); | 975 | "for requested bandwidth.\n"); |
968 | return -EIO; | 976 | return -EIO; |
969 | } | 977 | } |
970 | 978 | ||
971 | ret = usb_set_interface(stream->dev->udev, intfnum, i); | 979 | uvc_trace(UVC_TRACE_VIDEO, "Selecting alternate setting %u " |
980 | "(%u B/frame bandwidth).\n", altsetting, best_psize); | ||
981 | |||
982 | ret = usb_set_interface(stream->dev->udev, intfnum, altsetting); | ||
972 | if (ret < 0) | 983 | if (ret < 0) |
973 | return ret; | 984 | return ret; |
974 | 985 | ||
975 | ret = uvc_init_video_isoc(stream, ep, gfp_flags); | 986 | ret = uvc_init_video_isoc(stream, best_ep, gfp_flags); |
976 | } else { | 987 | } else { |
977 | /* Bulk endpoint, proceed to URB initialization. */ | 988 | /* Bulk endpoint, proceed to URB initialization. */ |
978 | ep = uvc_find_endpoint(&intf->altsetting[0], | 989 | ep = uvc_find_endpoint(&intf->altsetting[0], |
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h index 7ec9a04ced50..2337585001ea 100644 --- a/drivers/media/video/uvc/uvcvideo.h +++ b/drivers/media/video/uvc/uvcvideo.h | |||
@@ -365,8 +365,9 @@ enum uvc_buffer_state { | |||
365 | UVC_BUF_STATE_IDLE = 0, | 365 | UVC_BUF_STATE_IDLE = 0, |
366 | UVC_BUF_STATE_QUEUED = 1, | 366 | UVC_BUF_STATE_QUEUED = 1, |
367 | UVC_BUF_STATE_ACTIVE = 2, | 367 | UVC_BUF_STATE_ACTIVE = 2, |
368 | UVC_BUF_STATE_DONE = 3, | 368 | UVC_BUF_STATE_READY = 3, |
369 | UVC_BUF_STATE_ERROR = 4, | 369 | UVC_BUF_STATE_DONE = 4, |
370 | UVC_BUF_STATE_ERROR = 5, | ||
370 | }; | 371 | }; |
371 | 372 | ||
372 | struct uvc_buffer { | 373 | struct uvc_buffer { |
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index e8e5affbabce..36b5cb86fb57 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c | |||
@@ -1024,3 +1024,50 @@ void v4l_bound_align_image(u32 *w, unsigned int wmin, unsigned int wmax, | |||
1024 | } | 1024 | } |
1025 | } | 1025 | } |
1026 | EXPORT_SYMBOL_GPL(v4l_bound_align_image); | 1026 | EXPORT_SYMBOL_GPL(v4l_bound_align_image); |
1027 | |||
1028 | /** | ||
1029 | * v4l_fill_dv_preset_info - fill description of a digital video preset | ||
1030 | * @preset - preset value | ||
1031 | * @info - pointer to struct v4l2_dv_enum_preset | ||
1032 | * | ||
1033 | * drivers can use this helper function to fill description of dv preset | ||
1034 | * in info. | ||
1035 | */ | ||
1036 | int v4l_fill_dv_preset_info(u32 preset, struct v4l2_dv_enum_preset *info) | ||
1037 | { | ||
1038 | static const struct v4l2_dv_preset_info { | ||
1039 | u16 width; | ||
1040 | u16 height; | ||
1041 | const char *name; | ||
1042 | } dv_presets[] = { | ||
1043 | { 0, 0, "Invalid" }, /* V4L2_DV_INVALID */ | ||
1044 | { 720, 480, "480p@59.94" }, /* V4L2_DV_480P59_94 */ | ||
1045 | { 720, 576, "576p@50" }, /* V4L2_DV_576P50 */ | ||
1046 | { 1280, 720, "720p@24" }, /* V4L2_DV_720P24 */ | ||
1047 | { 1280, 720, "720p@25" }, /* V4L2_DV_720P25 */ | ||
1048 | { 1280, 720, "720p@30" }, /* V4L2_DV_720P30 */ | ||
1049 | { 1280, 720, "720p@50" }, /* V4L2_DV_720P50 */ | ||
1050 | { 1280, 720, "720p@59.94" }, /* V4L2_DV_720P59_94 */ | ||
1051 | { 1280, 720, "720p@60" }, /* V4L2_DV_720P60 */ | ||
1052 | { 1920, 1080, "1080i@29.97" }, /* V4L2_DV_1080I29_97 */ | ||
1053 | { 1920, 1080, "1080i@30" }, /* V4L2_DV_1080I30 */ | ||
1054 | { 1920, 1080, "1080i@25" }, /* V4L2_DV_1080I25 */ | ||
1055 | { 1920, 1080, "1080i@50" }, /* V4L2_DV_1080I50 */ | ||
1056 | { 1920, 1080, "1080i@60" }, /* V4L2_DV_1080I60 */ | ||
1057 | { 1920, 1080, "1080p@24" }, /* V4L2_DV_1080P24 */ | ||
1058 | { 1920, 1080, "1080p@25" }, /* V4L2_DV_1080P25 */ | ||
1059 | { 1920, 1080, "1080p@30" }, /* V4L2_DV_1080P30 */ | ||
1060 | { 1920, 1080, "1080p@50" }, /* V4L2_DV_1080P50 */ | ||
1061 | { 1920, 1080, "1080p@60" }, /* V4L2_DV_1080P60 */ | ||
1062 | }; | ||
1063 | |||
1064 | if (info == NULL || preset >= ARRAY_SIZE(dv_presets)) | ||
1065 | return -EINVAL; | ||
1066 | |||
1067 | info->preset = preset; | ||
1068 | info->width = dv_presets[preset].width; | ||
1069 | info->height = dv_presets[preset].height; | ||
1070 | strlcpy(info->name, dv_presets[preset].name, sizeof(info->name)); | ||
1071 | return 0; | ||
1072 | } | ||
1073 | EXPORT_SYMBOL_GPL(v4l_fill_dv_preset_info); | ||
diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c index 997975d5e024..c4150bd26337 100644 --- a/drivers/media/video/v4l2-compat-ioctl32.c +++ b/drivers/media/video/v4l2-compat-ioctl32.c | |||
@@ -1077,6 +1077,12 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) | |||
1077 | case VIDIOC_DBG_G_REGISTER: | 1077 | case VIDIOC_DBG_G_REGISTER: |
1078 | case VIDIOC_DBG_G_CHIP_IDENT: | 1078 | case VIDIOC_DBG_G_CHIP_IDENT: |
1079 | case VIDIOC_S_HW_FREQ_SEEK: | 1079 | case VIDIOC_S_HW_FREQ_SEEK: |
1080 | case VIDIOC_ENUM_DV_PRESETS: | ||
1081 | case VIDIOC_S_DV_PRESET: | ||
1082 | case VIDIOC_G_DV_PRESET: | ||
1083 | case VIDIOC_QUERY_DV_PRESET: | ||
1084 | case VIDIOC_S_DV_TIMINGS: | ||
1085 | case VIDIOC_G_DV_TIMINGS: | ||
1080 | ret = do_video_ioctl(file, cmd, arg); | 1086 | ret = do_video_ioctl(file, cmd, arg); |
1081 | break; | 1087 | break; |
1082 | 1088 | ||
diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 500cbe9891ac..709069916068 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c | |||
@@ -189,7 +189,7 @@ static ssize_t v4l2_read(struct file *filp, char __user *buf, | |||
189 | 189 | ||
190 | if (!vdev->fops->read) | 190 | if (!vdev->fops->read) |
191 | return -EINVAL; | 191 | return -EINVAL; |
192 | if (video_is_unregistered(vdev)) | 192 | if (!video_is_registered(vdev)) |
193 | return -EIO; | 193 | return -EIO; |
194 | return vdev->fops->read(filp, buf, sz, off); | 194 | return vdev->fops->read(filp, buf, sz, off); |
195 | } | 195 | } |
@@ -201,7 +201,7 @@ static ssize_t v4l2_write(struct file *filp, const char __user *buf, | |||
201 | 201 | ||
202 | if (!vdev->fops->write) | 202 | if (!vdev->fops->write) |
203 | return -EINVAL; | 203 | return -EINVAL; |
204 | if (video_is_unregistered(vdev)) | 204 | if (!video_is_registered(vdev)) |
205 | return -EIO; | 205 | return -EIO; |
206 | return vdev->fops->write(filp, buf, sz, off); | 206 | return vdev->fops->write(filp, buf, sz, off); |
207 | } | 207 | } |
@@ -210,7 +210,7 @@ static unsigned int v4l2_poll(struct file *filp, struct poll_table_struct *poll) | |||
210 | { | 210 | { |
211 | struct video_device *vdev = video_devdata(filp); | 211 | struct video_device *vdev = video_devdata(filp); |
212 | 212 | ||
213 | if (!vdev->fops->poll || video_is_unregistered(vdev)) | 213 | if (!vdev->fops->poll || !video_is_registered(vdev)) |
214 | return DEFAULT_POLLMASK; | 214 | return DEFAULT_POLLMASK; |
215 | return vdev->fops->poll(filp, poll); | 215 | return vdev->fops->poll(filp, poll); |
216 | } | 216 | } |
@@ -250,7 +250,7 @@ static unsigned long v4l2_get_unmapped_area(struct file *filp, | |||
250 | 250 | ||
251 | if (!vdev->fops->get_unmapped_area) | 251 | if (!vdev->fops->get_unmapped_area) |
252 | return -ENOSYS; | 252 | return -ENOSYS; |
253 | if (video_is_unregistered(vdev)) | 253 | if (!video_is_registered(vdev)) |
254 | return -ENODEV; | 254 | return -ENODEV; |
255 | return vdev->fops->get_unmapped_area(filp, addr, len, pgoff, flags); | 255 | return vdev->fops->get_unmapped_area(filp, addr, len, pgoff, flags); |
256 | } | 256 | } |
@@ -260,8 +260,7 @@ static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm) | |||
260 | { | 260 | { |
261 | struct video_device *vdev = video_devdata(filp); | 261 | struct video_device *vdev = video_devdata(filp); |
262 | 262 | ||
263 | if (!vdev->fops->mmap || | 263 | if (!vdev->fops->mmap || !video_is_registered(vdev)) |
264 | video_is_unregistered(vdev)) | ||
265 | return -ENODEV; | 264 | return -ENODEV; |
266 | return vdev->fops->mmap(filp, vm); | 265 | return vdev->fops->mmap(filp, vm); |
267 | } | 266 | } |
@@ -277,7 +276,7 @@ static int v4l2_open(struct inode *inode, struct file *filp) | |||
277 | vdev = video_devdata(filp); | 276 | vdev = video_devdata(filp); |
278 | /* return ENODEV if the video device has been removed | 277 | /* return ENODEV if the video device has been removed |
279 | already or if it is not registered anymore. */ | 278 | already or if it is not registered anymore. */ |
280 | if (vdev == NULL || video_is_unregistered(vdev)) { | 279 | if (vdev == NULL || !video_is_registered(vdev)) { |
281 | mutex_unlock(&videodev_lock); | 280 | mutex_unlock(&videodev_lock); |
282 | return -ENODEV; | 281 | return -ENODEV; |
283 | } | 282 | } |
@@ -551,10 +550,11 @@ static int __video_register_device(struct video_device *vdev, int type, int nr, | |||
551 | vdev->dev.release = v4l2_device_release; | 550 | vdev->dev.release = v4l2_device_release; |
552 | 551 | ||
553 | if (nr != -1 && nr != vdev->num && warn_if_nr_in_use) | 552 | if (nr != -1 && nr != vdev->num && warn_if_nr_in_use) |
554 | printk(KERN_WARNING "%s: requested %s%d, got %s%d\n", | 553 | printk(KERN_WARNING "%s: requested %s%d, got %s\n", __func__, |
555 | __func__, name_base, nr, name_base, vdev->num); | 554 | name_base, nr, video_device_node_name(vdev)); |
556 | 555 | ||
557 | /* Part 5: Activate this minor. The char device can now be used. */ | 556 | /* Part 5: Activate this minor. The char device can now be used. */ |
557 | set_bit(V4L2_FL_REGISTERED, &vdev->flags); | ||
558 | mutex_lock(&videodev_lock); | 558 | mutex_lock(&videodev_lock); |
559 | video_device[vdev->minor] = vdev; | 559 | video_device[vdev->minor] = vdev; |
560 | mutex_unlock(&videodev_lock); | 560 | mutex_unlock(&videodev_lock); |
@@ -593,11 +593,11 @@ EXPORT_SYMBOL(video_register_device_no_warn); | |||
593 | void video_unregister_device(struct video_device *vdev) | 593 | void video_unregister_device(struct video_device *vdev) |
594 | { | 594 | { |
595 | /* Check if vdev was ever registered at all */ | 595 | /* Check if vdev was ever registered at all */ |
596 | if (!vdev || vdev->minor < 0) | 596 | if (!vdev || !video_is_registered(vdev)) |
597 | return; | 597 | return; |
598 | 598 | ||
599 | mutex_lock(&videodev_lock); | 599 | mutex_lock(&videodev_lock); |
600 | set_bit(V4L2_FL_UNREGISTERED, &vdev->flags); | 600 | clear_bit(V4L2_FL_REGISTERED, &vdev->flags); |
601 | mutex_unlock(&videodev_lock); | 601 | mutex_unlock(&videodev_lock); |
602 | device_unregister(&vdev->dev); | 602 | device_unregister(&vdev->dev); |
603 | } | 603 | } |
diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 30cc3347ae52..4b11257c3184 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c | |||
@@ -284,6 +284,12 @@ static const char *v4l2_ioctls[] = { | |||
284 | [_IOC_NR(VIDIOC_DBG_G_CHIP_IDENT)] = "VIDIOC_DBG_G_CHIP_IDENT", | 284 | [_IOC_NR(VIDIOC_DBG_G_CHIP_IDENT)] = "VIDIOC_DBG_G_CHIP_IDENT", |
285 | [_IOC_NR(VIDIOC_S_HW_FREQ_SEEK)] = "VIDIOC_S_HW_FREQ_SEEK", | 285 | [_IOC_NR(VIDIOC_S_HW_FREQ_SEEK)] = "VIDIOC_S_HW_FREQ_SEEK", |
286 | #endif | 286 | #endif |
287 | [_IOC_NR(VIDIOC_ENUM_DV_PRESETS)] = "VIDIOC_ENUM_DV_PRESETS", | ||
288 | [_IOC_NR(VIDIOC_S_DV_PRESET)] = "VIDIOC_S_DV_PRESET", | ||
289 | [_IOC_NR(VIDIOC_G_DV_PRESET)] = "VIDIOC_G_DV_PRESET", | ||
290 | [_IOC_NR(VIDIOC_QUERY_DV_PRESET)] = "VIDIOC_QUERY_DV_PRESET", | ||
291 | [_IOC_NR(VIDIOC_S_DV_TIMINGS)] = "VIDIOC_S_DV_TIMINGS", | ||
292 | [_IOC_NR(VIDIOC_G_DV_TIMINGS)] = "VIDIOC_G_DV_TIMINGS", | ||
287 | }; | 293 | }; |
288 | #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) | 294 | #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) |
289 | 295 | ||
@@ -1135,6 +1141,19 @@ static long __video_do_ioctl(struct file *file, | |||
1135 | { | 1141 | { |
1136 | struct v4l2_input *p = arg; | 1142 | struct v4l2_input *p = arg; |
1137 | 1143 | ||
1144 | /* | ||
1145 | * We set the flags for CAP_PRESETS, CAP_CUSTOM_TIMINGS & | ||
1146 | * CAP_STD here based on ioctl handler provided by the | ||
1147 | * driver. If the driver doesn't support these | ||
1148 | * for a specific input, it must override these flags. | ||
1149 | */ | ||
1150 | if (ops->vidioc_s_std) | ||
1151 | p->capabilities |= V4L2_IN_CAP_STD; | ||
1152 | if (ops->vidioc_s_dv_preset) | ||
1153 | p->capabilities |= V4L2_IN_CAP_PRESETS; | ||
1154 | if (ops->vidioc_s_dv_timings) | ||
1155 | p->capabilities |= V4L2_IN_CAP_CUSTOM_TIMINGS; | ||
1156 | |||
1138 | if (!ops->vidioc_enum_input) | 1157 | if (!ops->vidioc_enum_input) |
1139 | break; | 1158 | break; |
1140 | 1159 | ||
@@ -1179,6 +1198,19 @@ static long __video_do_ioctl(struct file *file, | |||
1179 | if (!ops->vidioc_enum_output) | 1198 | if (!ops->vidioc_enum_output) |
1180 | break; | 1199 | break; |
1181 | 1200 | ||
1201 | /* | ||
1202 | * We set the flags for CAP_PRESETS, CAP_CUSTOM_TIMINGS & | ||
1203 | * CAP_STD here based on ioctl handler provided by the | ||
1204 | * driver. If the driver doesn't support these | ||
1205 | * for a specific output, it must override these flags. | ||
1206 | */ | ||
1207 | if (ops->vidioc_s_std) | ||
1208 | p->capabilities |= V4L2_OUT_CAP_STD; | ||
1209 | if (ops->vidioc_s_dv_preset) | ||
1210 | p->capabilities |= V4L2_OUT_CAP_PRESETS; | ||
1211 | if (ops->vidioc_s_dv_timings) | ||
1212 | p->capabilities |= V4L2_OUT_CAP_CUSTOM_TIMINGS; | ||
1213 | |||
1182 | ret = ops->vidioc_enum_output(file, fh, p); | 1214 | ret = ops->vidioc_enum_output(file, fh, p); |
1183 | if (!ret) | 1215 | if (!ret) |
1184 | dbgarg(cmd, "index=%d, name=%s, type=%d, " | 1216 | dbgarg(cmd, "index=%d, name=%s, type=%d, " |
@@ -1794,6 +1826,121 @@ static long __video_do_ioctl(struct file *file, | |||
1794 | } | 1826 | } |
1795 | break; | 1827 | break; |
1796 | } | 1828 | } |
1829 | case VIDIOC_ENUM_DV_PRESETS: | ||
1830 | { | ||
1831 | struct v4l2_dv_enum_preset *p = arg; | ||
1832 | |||
1833 | if (!ops->vidioc_enum_dv_presets) | ||
1834 | break; | ||
1835 | |||
1836 | ret = ops->vidioc_enum_dv_presets(file, fh, p); | ||
1837 | if (!ret) | ||
1838 | dbgarg(cmd, | ||
1839 | "index=%d, preset=%d, name=%s, width=%d," | ||
1840 | " height=%d ", | ||
1841 | p->index, p->preset, p->name, p->width, | ||
1842 | p->height); | ||
1843 | break; | ||
1844 | } | ||
1845 | case VIDIOC_S_DV_PRESET: | ||
1846 | { | ||
1847 | struct v4l2_dv_preset *p = arg; | ||
1848 | |||
1849 | if (!ops->vidioc_s_dv_preset) | ||
1850 | break; | ||
1851 | |||
1852 | dbgarg(cmd, "preset=%d\n", p->preset); | ||
1853 | ret = ops->vidioc_s_dv_preset(file, fh, p); | ||
1854 | break; | ||
1855 | } | ||
1856 | case VIDIOC_G_DV_PRESET: | ||
1857 | { | ||
1858 | struct v4l2_dv_preset *p = arg; | ||
1859 | |||
1860 | if (!ops->vidioc_g_dv_preset) | ||
1861 | break; | ||
1862 | |||
1863 | ret = ops->vidioc_g_dv_preset(file, fh, p); | ||
1864 | if (!ret) | ||
1865 | dbgarg(cmd, "preset=%d\n", p->preset); | ||
1866 | break; | ||
1867 | } | ||
1868 | case VIDIOC_QUERY_DV_PRESET: | ||
1869 | { | ||
1870 | struct v4l2_dv_preset *p = arg; | ||
1871 | |||
1872 | if (!ops->vidioc_query_dv_preset) | ||
1873 | break; | ||
1874 | |||
1875 | ret = ops->vidioc_query_dv_preset(file, fh, p); | ||
1876 | if (!ret) | ||
1877 | dbgarg(cmd, "preset=%d\n", p->preset); | ||
1878 | break; | ||
1879 | } | ||
1880 | case VIDIOC_S_DV_TIMINGS: | ||
1881 | { | ||
1882 | struct v4l2_dv_timings *p = arg; | ||
1883 | |||
1884 | if (!ops->vidioc_s_dv_timings) | ||
1885 | break; | ||
1886 | |||
1887 | switch (p->type) { | ||
1888 | case V4L2_DV_BT_656_1120: | ||
1889 | dbgarg2("bt-656/1120:interlaced=%d, pixelclock=%lld," | ||
1890 | " width=%d, height=%d, polarities=%x," | ||
1891 | " hfrontporch=%d, hsync=%d, hbackporch=%d," | ||
1892 | " vfrontporch=%d, vsync=%d, vbackporch=%d," | ||
1893 | " il_vfrontporch=%d, il_vsync=%d," | ||
1894 | " il_vbackporch=%d\n", | ||
1895 | p->bt.interlaced, p->bt.pixelclock, | ||
1896 | p->bt.width, p->bt.height, p->bt.polarities, | ||
1897 | p->bt.hfrontporch, p->bt.hsync, | ||
1898 | p->bt.hbackporch, p->bt.vfrontporch, | ||
1899 | p->bt.vsync, p->bt.vbackporch, | ||
1900 | p->bt.il_vfrontporch, p->bt.il_vsync, | ||
1901 | p->bt.il_vbackporch); | ||
1902 | ret = ops->vidioc_s_dv_timings(file, fh, p); | ||
1903 | break; | ||
1904 | default: | ||
1905 | dbgarg2("Unknown type %d!\n", p->type); | ||
1906 | break; | ||
1907 | } | ||
1908 | break; | ||
1909 | } | ||
1910 | case VIDIOC_G_DV_TIMINGS: | ||
1911 | { | ||
1912 | struct v4l2_dv_timings *p = arg; | ||
1913 | |||
1914 | if (!ops->vidioc_g_dv_timings) | ||
1915 | break; | ||
1916 | |||
1917 | ret = ops->vidioc_g_dv_timings(file, fh, p); | ||
1918 | if (!ret) { | ||
1919 | switch (p->type) { | ||
1920 | case V4L2_DV_BT_656_1120: | ||
1921 | dbgarg2("bt-656/1120:interlaced=%d," | ||
1922 | " pixelclock=%lld," | ||
1923 | " width=%d, height=%d, polarities=%x," | ||
1924 | " hfrontporch=%d, hsync=%d," | ||
1925 | " hbackporch=%d, vfrontporch=%d," | ||
1926 | " vsync=%d, vbackporch=%d," | ||
1927 | " il_vfrontporch=%d, il_vsync=%d," | ||
1928 | " il_vbackporch=%d\n", | ||
1929 | p->bt.interlaced, p->bt.pixelclock, | ||
1930 | p->bt.width, p->bt.height, | ||
1931 | p->bt.polarities, p->bt.hfrontporch, | ||
1932 | p->bt.hsync, p->bt.hbackporch, | ||
1933 | p->bt.vfrontporch, p->bt.vsync, | ||
1934 | p->bt.vbackporch, p->bt.il_vfrontporch, | ||
1935 | p->bt.il_vsync, p->bt.il_vbackporch); | ||
1936 | break; | ||
1937 | default: | ||
1938 | dbgarg2("Unknown type %d!\n", p->type); | ||
1939 | break; | ||
1940 | } | ||
1941 | } | ||
1942 | break; | ||
1943 | } | ||
1797 | 1944 | ||
1798 | default: | 1945 | default: |
1799 | { | 1946 | { |
diff --git a/drivers/media/video/videobuf-dma-contig.c b/drivers/media/video/videobuf-dma-contig.c index d25f28461da1..22c01097e8a8 100644 --- a/drivers/media/video/videobuf-dma-contig.c +++ b/drivers/media/video/videobuf-dma-contig.c | |||
@@ -141,9 +141,11 @@ static int videobuf_dma_contig_user_get(struct videobuf_dma_contig_memory *mem, | |||
141 | struct vm_area_struct *vma; | 141 | struct vm_area_struct *vma; |
142 | unsigned long prev_pfn, this_pfn; | 142 | unsigned long prev_pfn, this_pfn; |
143 | unsigned long pages_done, user_address; | 143 | unsigned long pages_done, user_address; |
144 | unsigned int offset; | ||
144 | int ret; | 145 | int ret; |
145 | 146 | ||
146 | mem->size = PAGE_ALIGN(vb->size); | 147 | offset = vb->baddr & ~PAGE_MASK; |
148 | mem->size = PAGE_ALIGN(vb->size + offset); | ||
147 | mem->is_userptr = 0; | 149 | mem->is_userptr = 0; |
148 | ret = -EINVAL; | 150 | ret = -EINVAL; |
149 | 151 | ||
@@ -166,7 +168,7 @@ static int videobuf_dma_contig_user_get(struct videobuf_dma_contig_memory *mem, | |||
166 | break; | 168 | break; |
167 | 169 | ||
168 | if (pages_done == 0) | 170 | if (pages_done == 0) |
169 | mem->dma_handle = this_pfn << PAGE_SHIFT; | 171 | mem->dma_handle = (this_pfn << PAGE_SHIFT) + offset; |
170 | else if (this_pfn != (prev_pfn + 1)) | 172 | else if (this_pfn != (prev_pfn + 1)) |
171 | ret = -EFAULT; | 173 | ret = -EFAULT; |
172 | 174 | ||
diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c index b034a81d2b1c..a15d1e7cbed8 100644 --- a/drivers/media/video/vino.c +++ b/drivers/media/video/vino.c | |||
@@ -4068,7 +4068,6 @@ static struct video_device vdev_template = { | |||
4068 | .fops = &vino_fops, | 4068 | .fops = &vino_fops, |
4069 | .ioctl_ops = &vino_ioctl_ops, | 4069 | .ioctl_ops = &vino_ioctl_ops, |
4070 | .tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM, | 4070 | .tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM, |
4071 | .minor = -1, | ||
4072 | }; | 4071 | }; |
4073 | 4072 | ||
4074 | static void vino_module_cleanup(int stage) | 4073 | static void vino_module_cleanup(int stage) |
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 7705fc6baf00..37632a064966 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c | |||
@@ -1148,7 +1148,8 @@ static int vivi_open(struct file *file) | |||
1148 | return -EBUSY; | 1148 | return -EBUSY; |
1149 | } | 1149 | } |
1150 | 1150 | ||
1151 | dprintk(dev, 1, "open /dev/video%d type=%s users=%d\n", dev->vfd->num, | 1151 | dprintk(dev, 1, "open %s type=%s users=%d\n", |
1152 | video_device_node_name(dev->vfd), | ||
1152 | v4l2_type_names[V4L2_BUF_TYPE_VIDEO_CAPTURE], dev->users); | 1153 | v4l2_type_names[V4L2_BUF_TYPE_VIDEO_CAPTURE], dev->users); |
1153 | 1154 | ||
1154 | /* allocate + initialize per filehandle data */ | 1155 | /* allocate + initialize per filehandle data */ |
@@ -1221,8 +1222,7 @@ static int vivi_close(struct file *file) | |||
1221 | struct vivi_fh *fh = file->private_data; | 1222 | struct vivi_fh *fh = file->private_data; |
1222 | struct vivi_dev *dev = fh->dev; | 1223 | struct vivi_dev *dev = fh->dev; |
1223 | struct vivi_dmaqueue *vidq = &dev->vidq; | 1224 | struct vivi_dmaqueue *vidq = &dev->vidq; |
1224 | 1225 | struct video_device *vdev = video_devdata(file); | |
1225 | int minor = video_devdata(file)->minor; | ||
1226 | 1226 | ||
1227 | vivi_stop_thread(vidq); | 1227 | vivi_stop_thread(vidq); |
1228 | videobuf_stop(&fh->vb_vidq); | 1228 | videobuf_stop(&fh->vb_vidq); |
@@ -1234,8 +1234,8 @@ static int vivi_close(struct file *file) | |||
1234 | dev->users--; | 1234 | dev->users--; |
1235 | mutex_unlock(&dev->mutex); | 1235 | mutex_unlock(&dev->mutex); |
1236 | 1236 | ||
1237 | dprintk(dev, 1, "close called (minor=%d, users=%d)\n", | 1237 | dprintk(dev, 1, "close called (dev=%s, users=%d)\n", |
1238 | minor, dev->users); | 1238 | video_device_node_name(vdev), dev->users); |
1239 | 1239 | ||
1240 | return 0; | 1240 | return 0; |
1241 | } | 1241 | } |
@@ -1296,7 +1296,6 @@ static struct video_device vivi_template = { | |||
1296 | .name = "vivi", | 1296 | .name = "vivi", |
1297 | .fops = &vivi_fops, | 1297 | .fops = &vivi_fops, |
1298 | .ioctl_ops = &vivi_ioctl_ops, | 1298 | .ioctl_ops = &vivi_ioctl_ops, |
1299 | .minor = -1, | ||
1300 | .release = video_device_release, | 1299 | .release = video_device_release, |
1301 | 1300 | ||
1302 | .tvnorms = V4L2_STD_525_60, | 1301 | .tvnorms = V4L2_STD_525_60, |
@@ -1317,8 +1316,8 @@ static int vivi_release(void) | |||
1317 | list_del(list); | 1316 | list_del(list); |
1318 | dev = list_entry(list, struct vivi_dev, vivi_devlist); | 1317 | dev = list_entry(list, struct vivi_dev, vivi_devlist); |
1319 | 1318 | ||
1320 | v4l2_info(&dev->v4l2_dev, "unregistering /dev/video%d\n", | 1319 | v4l2_info(&dev->v4l2_dev, "unregistering %s\n", |
1321 | dev->vfd->num); | 1320 | video_device_node_name(dev->vfd)); |
1322 | video_unregister_device(dev->vfd); | 1321 | video_unregister_device(dev->vfd); |
1323 | v4l2_device_unregister(&dev->v4l2_dev); | 1322 | v4l2_device_unregister(&dev->v4l2_dev); |
1324 | kfree(dev); | 1323 | kfree(dev); |
@@ -1372,15 +1371,12 @@ static int __init vivi_create_instance(int inst) | |||
1372 | /* 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 */ |
1373 | list_add_tail(&dev->vivi_devlist, &vivi_devlist); | 1372 | list_add_tail(&dev->vivi_devlist, &vivi_devlist); |
1374 | 1373 | ||
1375 | snprintf(vfd->name, sizeof(vfd->name), "%s (%i)", | ||
1376 | vivi_template.name, vfd->num); | ||
1377 | |||
1378 | if (video_nr >= 0) | 1374 | if (video_nr >= 0) |
1379 | video_nr++; | 1375 | video_nr++; |
1380 | 1376 | ||
1381 | dev->vfd = vfd; | 1377 | dev->vfd = vfd; |
1382 | v4l2_info(&dev->v4l2_dev, "V4L2 device registered as /dev/video%d\n", | 1378 | v4l2_info(&dev->v4l2_dev, "V4L2 device registered as %s\n", |
1383 | vfd->num); | 1379 | video_device_node_name(vfd)); |
1384 | return 0; | 1380 | return 0; |
1385 | 1381 | ||
1386 | rel_vdev: | 1382 | rel_vdev: |
diff --git a/drivers/media/video/w9968cf.c b/drivers/media/video/w9968cf.c index 37fcdc447db5..d807eea91757 100644 --- a/drivers/media/video/w9968cf.c +++ b/drivers/media/video/w9968cf.c | |||
@@ -2323,9 +2323,9 @@ static int w9968cf_sensor_init(struct w9968cf_device* cam) | |||
2323 | error: | 2323 | error: |
2324 | cam->sensor_initialized = 0; | 2324 | cam->sensor_initialized = 0; |
2325 | cam->sensor = CC_UNKNOWN; | 2325 | cam->sensor = CC_UNKNOWN; |
2326 | DBG(1, "Image sensor initialization failed for %s (/dev/video%d). " | 2326 | DBG(1, "Image sensor initialization failed for %s (%s). " |
2327 | "Try to detach and attach this device again", | 2327 | "Try to detach and attach this device again", |
2328 | symbolic(camlist, cam->id), cam->v4ldev->num) | 2328 | symbolic(camlist, cam->id), video_device_node_name(cam->v4ldev)) |
2329 | return err; | 2329 | return err; |
2330 | } | 2330 | } |
2331 | 2331 | ||
@@ -2571,7 +2571,8 @@ static void w9968cf_release_resources(struct w9968cf_device* cam) | |||
2571 | { | 2571 | { |
2572 | mutex_lock(&w9968cf_devlist_mutex); | 2572 | mutex_lock(&w9968cf_devlist_mutex); |
2573 | 2573 | ||
2574 | DBG(2, "V4L device deregistered: /dev/video%d", cam->v4ldev->num) | 2574 | DBG(2, "V4L device deregistered: %s", |
2575 | video_device_node_name(cam->v4ldev)) | ||
2575 | 2576 | ||
2576 | video_unregister_device(cam->v4ldev); | 2577 | video_unregister_device(cam->v4ldev); |
2577 | list_del(&cam->v4llist); | 2578 | list_del(&cam->v4llist); |
@@ -2605,17 +2606,19 @@ static int w9968cf_open(struct file *filp) | |||
2605 | 2606 | ||
2606 | if (cam->sensor == CC_UNKNOWN) { | 2607 | if (cam->sensor == CC_UNKNOWN) { |
2607 | DBG(2, "No supported image sensor has been detected by the " | 2608 | DBG(2, "No supported image sensor has been detected by the " |
2608 | "'ovcamchip' module for the %s (/dev/video%d). Make " | 2609 | "'ovcamchip' module for the %s (%s). Make sure " |
2609 | "sure it is loaded *before* (re)connecting the camera.", | 2610 | "it is loaded *before* (re)connecting the camera.", |
2610 | symbolic(camlist, cam->id), cam->v4ldev->num) | 2611 | symbolic(camlist, cam->id), |
2612 | video_device_node_name(cam->v4ldev)) | ||
2611 | mutex_unlock(&cam->dev_mutex); | 2613 | mutex_unlock(&cam->dev_mutex); |
2612 | up_read(&w9968cf_disconnect); | 2614 | up_read(&w9968cf_disconnect); |
2613 | return -ENODEV; | 2615 | return -ENODEV; |
2614 | } | 2616 | } |
2615 | 2617 | ||
2616 | if (cam->users) { | 2618 | if (cam->users) { |
2617 | DBG(2, "%s (/dev/video%d) has been already occupied by '%s'", | 2619 | DBG(2, "%s (%s) has been already occupied by '%s'", |
2618 | symbolic(camlist, cam->id), cam->v4ldev->num, cam->command) | 2620 | symbolic(camlist, cam->id), |
2621 | video_device_node_name(cam->v4ldev), cam->command) | ||
2619 | if ((filp->f_flags & O_NONBLOCK)||(filp->f_flags & O_NDELAY)) { | 2622 | if ((filp->f_flags & O_NONBLOCK)||(filp->f_flags & O_NDELAY)) { |
2620 | mutex_unlock(&cam->dev_mutex); | 2623 | mutex_unlock(&cam->dev_mutex); |
2621 | up_read(&w9968cf_disconnect); | 2624 | up_read(&w9968cf_disconnect); |
@@ -2636,8 +2639,8 @@ static int w9968cf_open(struct file *filp) | |||
2636 | mutex_lock(&cam->dev_mutex); | 2639 | mutex_lock(&cam->dev_mutex); |
2637 | } | 2640 | } |
2638 | 2641 | ||
2639 | DBG(5, "Opening '%s', /dev/video%d ...", | 2642 | DBG(5, "Opening '%s', %s ...", |
2640 | symbolic(camlist, cam->id), cam->v4ldev->num) | 2643 | symbolic(camlist, cam->id), video_device_node_name(cam->v4ldev)) |
2641 | 2644 | ||
2642 | cam->streaming = 0; | 2645 | cam->streaming = 0; |
2643 | cam->misconfigured = 0; | 2646 | cam->misconfigured = 0; |
@@ -2874,8 +2877,7 @@ static long w9968cf_v4l_ioctl(struct file *filp, | |||
2874 | .minwidth = cam->minwidth, | 2877 | .minwidth = cam->minwidth, |
2875 | .minheight = cam->minheight, | 2878 | .minheight = cam->minheight, |
2876 | }; | 2879 | }; |
2877 | sprintf(cap.name, "W996[87]CF USB Camera #%d", | 2880 | sprintf(cap.name, "W996[87]CF USB Camera"); |
2878 | cam->v4ldev->num); | ||
2879 | cap.maxwidth = (cam->upscaling && w9968cf_vpp) | 2881 | cap.maxwidth = (cam->upscaling && w9968cf_vpp) |
2880 | ? max((u16)W9968CF_MAX_WIDTH, cam->maxwidth) | 2882 | ? max((u16)W9968CF_MAX_WIDTH, cam->maxwidth) |
2881 | : cam->maxwidth; | 2883 | : cam->maxwidth; |
@@ -3485,7 +3487,6 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) | |||
3485 | 3487 | ||
3486 | strcpy(cam->v4ldev->name, symbolic(camlist, mod_id)); | 3488 | strcpy(cam->v4ldev->name, symbolic(camlist, mod_id)); |
3487 | cam->v4ldev->fops = &w9968cf_fops; | 3489 | cam->v4ldev->fops = &w9968cf_fops; |
3488 | cam->v4ldev->minor = video_nr[dev_nr]; | ||
3489 | cam->v4ldev->release = video_device_release; | 3490 | cam->v4ldev->release = video_device_release; |
3490 | video_set_drvdata(cam->v4ldev, cam); | 3491 | video_set_drvdata(cam->v4ldev, cam); |
3491 | cam->v4ldev->v4l2_dev = &cam->v4l2_dev; | 3492 | cam->v4ldev->v4l2_dev = &cam->v4l2_dev; |
@@ -3501,7 +3502,8 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) | |||
3501 | goto fail; | 3502 | goto fail; |
3502 | } | 3503 | } |
3503 | 3504 | ||
3504 | DBG(2, "V4L device registered as /dev/video%d", cam->v4ldev->num) | 3505 | DBG(2, "V4L device registered as %s", |
3506 | video_device_node_name(cam->v4ldev)) | ||
3505 | 3507 | ||
3506 | /* Set some basic constants */ | 3508 | /* Set some basic constants */ |
3507 | w9968cf_configure_camera(cam, udev, mod_id, dev_nr); | 3509 | w9968cf_configure_camera(cam, udev, mod_id, dev_nr); |
@@ -3557,10 +3559,10 @@ static void w9968cf_usb_disconnect(struct usb_interface* intf) | |||
3557 | wake_up_interruptible_all(&cam->open); | 3559 | wake_up_interruptible_all(&cam->open); |
3558 | 3560 | ||
3559 | if (cam->users) { | 3561 | if (cam->users) { |
3560 | DBG(2, "The device is open (/dev/video%d)! " | 3562 | DBG(2, "The device is open (%s)! " |
3561 | "Process name: %s. Deregistration and memory " | 3563 | "Process name: %s. Deregistration and memory " |
3562 | "deallocation are deferred on close.", | 3564 | "deallocation are deferred on close.", |
3563 | cam->v4ldev->num, cam->command) | 3565 | video_device_node_name(cam->v4ldev), cam->command) |
3564 | cam->misconfigured = 1; | 3566 | cam->misconfigured = 1; |
3565 | w9968cf_stop_transfer(cam); | 3567 | w9968cf_stop_transfer(cam); |
3566 | wake_up_interruptible(&cam->wait_queue); | 3568 | wake_up_interruptible(&cam->wait_queue); |
diff --git a/drivers/media/video/zc0301/zc0301_core.c b/drivers/media/video/zc0301/zc0301_core.c index 312a71336fd0..e44e4b5f3e50 100644 --- a/drivers/media/video/zc0301/zc0301_core.c +++ b/drivers/media/video/zc0301/zc0301_core.c | |||
@@ -538,8 +538,8 @@ static int zc0301_stream_interrupt(struct zc0301_device* cam) | |||
538 | else if (cam->stream != STREAM_OFF) { | 538 | else if (cam->stream != STREAM_OFF) { |
539 | cam->state |= DEV_MISCONFIGURED; | 539 | cam->state |= DEV_MISCONFIGURED; |
540 | DBG(1, "URB timeout reached. The camera is misconfigured. To " | 540 | DBG(1, "URB timeout reached. The camera is misconfigured. To " |
541 | "use it, close and open /dev/video%d again.", | 541 | "use it, close and open %s again.", |
542 | cam->v4ldev->num); | 542 | video_device_node_name(cam->v4ldev)); |
543 | return -EIO; | 543 | return -EIO; |
544 | } | 544 | } |
545 | 545 | ||
@@ -640,7 +640,8 @@ static void zc0301_release_resources(struct kref *kref) | |||
640 | { | 640 | { |
641 | struct zc0301_device *cam = container_of(kref, struct zc0301_device, | 641 | struct zc0301_device *cam = container_of(kref, struct zc0301_device, |
642 | kref); | 642 | kref); |
643 | DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->num); | 643 | DBG(2, "V4L2 device %s deregistered", |
644 | video_device_node_name(cam->v4ldev)); | ||
644 | video_set_drvdata(cam->v4ldev, NULL); | 645 | video_set_drvdata(cam->v4ldev, NULL); |
645 | video_unregister_device(cam->v4ldev); | 646 | video_unregister_device(cam->v4ldev); |
646 | usb_put_dev(cam->usbdev); | 647 | usb_put_dev(cam->usbdev); |
@@ -679,7 +680,8 @@ static int zc0301_open(struct file *filp) | |||
679 | } | 680 | } |
680 | 681 | ||
681 | if (cam->users) { | 682 | if (cam->users) { |
682 | DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->num); | 683 | DBG(2, "Device %s is busy...", |
684 | video_device_node_name(cam->v4ldev)); | ||
683 | DBG(3, "Simultaneous opens are not supported"); | 685 | DBG(3, "Simultaneous opens are not supported"); |
684 | if ((filp->f_flags & O_NONBLOCK) || | 686 | if ((filp->f_flags & O_NONBLOCK) || |
685 | (filp->f_flags & O_NDELAY)) { | 687 | (filp->f_flags & O_NDELAY)) { |
@@ -722,7 +724,8 @@ static int zc0301_open(struct file *filp) | |||
722 | cam->frame_count = 0; | 724 | cam->frame_count = 0; |
723 | zc0301_empty_framequeues(cam); | 725 | zc0301_empty_framequeues(cam); |
724 | 726 | ||
725 | DBG(3, "Video device /dev/video%d is open", cam->v4ldev->num); | 727 | DBG(3, "Video device %s is open", |
728 | video_device_node_name(cam->v4ldev)); | ||
726 | 729 | ||
727 | out: | 730 | out: |
728 | mutex_unlock(&cam->open_mutex); | 731 | mutex_unlock(&cam->open_mutex); |
@@ -746,7 +749,8 @@ static int zc0301_release(struct file *filp) | |||
746 | cam->users--; | 749 | cam->users--; |
747 | wake_up_interruptible_nr(&cam->wait_open, 1); | 750 | wake_up_interruptible_nr(&cam->wait_open, 1); |
748 | 751 | ||
749 | DBG(3, "Video device /dev/video%d closed", cam->v4ldev->num); | 752 | DBG(3, "Video device %s closed", |
753 | video_device_node_name(cam->v4ldev)); | ||
750 | 754 | ||
751 | kref_put(&cam->kref, zc0301_release_resources); | 755 | kref_put(&cam->kref, zc0301_release_resources); |
752 | 756 | ||
@@ -1276,8 +1280,8 @@ zc0301_vidioc_s_crop(struct zc0301_device* cam, void __user * arg) | |||
1276 | if (err) { /* atomic, no rollback in ioctl() */ | 1280 | if (err) { /* atomic, no rollback in ioctl() */ |
1277 | cam->state |= DEV_MISCONFIGURED; | 1281 | cam->state |= DEV_MISCONFIGURED; |
1278 | DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To " | 1282 | DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To " |
1279 | "use the camera, close and open /dev/video%d again.", | 1283 | "use the camera, close and open %s again.", |
1280 | cam->v4ldev->num); | 1284 | video_device_node_name(cam->v4ldev)); |
1281 | return -EIO; | 1285 | return -EIO; |
1282 | } | 1286 | } |
1283 | 1287 | ||
@@ -1289,8 +1293,8 @@ zc0301_vidioc_s_crop(struct zc0301_device* cam, void __user * arg) | |||
1289 | nbuffers != zc0301_request_buffers(cam, nbuffers, cam->io)) { | 1293 | nbuffers != zc0301_request_buffers(cam, nbuffers, cam->io)) { |
1290 | cam->state |= DEV_MISCONFIGURED; | 1294 | cam->state |= DEV_MISCONFIGURED; |
1291 | DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To " | 1295 | DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To " |
1292 | "use the camera, close and open /dev/video%d again.", | 1296 | "use the camera, close and open %s again.", |
1293 | cam->v4ldev->num); | 1297 | video_device_node_name(cam->v4ldev)); |
1294 | return -ENOMEM; | 1298 | return -ENOMEM; |
1295 | } | 1299 | } |
1296 | 1300 | ||
@@ -1471,8 +1475,8 @@ zc0301_vidioc_try_s_fmt(struct zc0301_device* cam, unsigned int cmd, | |||
1471 | if (err) { /* atomic, no rollback in ioctl() */ | 1475 | if (err) { /* atomic, no rollback in ioctl() */ |
1472 | cam->state |= DEV_MISCONFIGURED; | 1476 | cam->state |= DEV_MISCONFIGURED; |
1473 | DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To " | 1477 | DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To " |
1474 | "use the camera, close and open /dev/video%d again.", | 1478 | "use the camera, close and open %s again.", |
1475 | cam->v4ldev->num); | 1479 | video_device_node_name(cam->v4ldev)); |
1476 | return -EIO; | 1480 | return -EIO; |
1477 | } | 1481 | } |
1478 | 1482 | ||
@@ -1483,8 +1487,8 @@ zc0301_vidioc_try_s_fmt(struct zc0301_device* cam, unsigned int cmd, | |||
1483 | nbuffers != zc0301_request_buffers(cam, nbuffers, cam->io)) { | 1487 | nbuffers != zc0301_request_buffers(cam, nbuffers, cam->io)) { |
1484 | cam->state |= DEV_MISCONFIGURED; | 1488 | cam->state |= DEV_MISCONFIGURED; |
1485 | DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To " | 1489 | DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To " |
1486 | "use the camera, close and open /dev/video%d again.", | 1490 | "use the camera, close and open %s again.", |
1487 | cam->v4ldev->num); | 1491 | video_device_node_name(cam->v4ldev)); |
1488 | return -ENOMEM; | 1492 | return -ENOMEM; |
1489 | } | 1493 | } |
1490 | 1494 | ||
@@ -1530,8 +1534,8 @@ zc0301_vidioc_s_jpegcomp(struct zc0301_device* cam, void __user * arg) | |||
1530 | if (err) { /* atomic, no rollback in ioctl() */ | 1534 | if (err) { /* atomic, no rollback in ioctl() */ |
1531 | cam->state |= DEV_MISCONFIGURED; | 1535 | cam->state |= DEV_MISCONFIGURED; |
1532 | DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware " | 1536 | DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware " |
1533 | "problems. To use the camera, close and open " | 1537 | "problems. To use the camera, close and open %s again.", |
1534 | "/dev/video%d again.", cam->v4ldev->num); | 1538 | video_device_node_name(cam->v4ldev)); |
1535 | return -EIO; | 1539 | return -EIO; |
1536 | } | 1540 | } |
1537 | 1541 | ||
@@ -1984,7 +1988,6 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) | |||
1984 | 1988 | ||
1985 | strcpy(cam->v4ldev->name, "ZC0301[P] PC Camera"); | 1989 | strcpy(cam->v4ldev->name, "ZC0301[P] PC Camera"); |
1986 | cam->v4ldev->fops = &zc0301_fops; | 1990 | cam->v4ldev->fops = &zc0301_fops; |
1987 | cam->v4ldev->minor = video_nr[dev_nr]; | ||
1988 | cam->v4ldev->release = video_device_release; | 1991 | cam->v4ldev->release = video_device_release; |
1989 | cam->v4ldev->parent = &udev->dev; | 1992 | cam->v4ldev->parent = &udev->dev; |
1990 | video_set_drvdata(cam->v4ldev, cam); | 1993 | video_set_drvdata(cam->v4ldev, cam); |
@@ -2003,7 +2006,8 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) | |||
2003 | goto fail; | 2006 | goto fail; |
2004 | } | 2007 | } |
2005 | 2008 | ||
2006 | DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->num); | 2009 | DBG(2, "V4L2 device registered as %s", |
2010 | video_device_node_name(cam->v4ldev)); | ||
2007 | 2011 | ||
2008 | cam->module_param.force_munmap = force_munmap[dev_nr]; | 2012 | cam->module_param.force_munmap = force_munmap[dev_nr]; |
2009 | cam->module_param.frame_timeout = frame_timeout[dev_nr]; | 2013 | cam->module_param.frame_timeout = frame_timeout[dev_nr]; |
@@ -2040,9 +2044,9 @@ static void zc0301_usb_disconnect(struct usb_interface* intf) | |||
2040 | DBG(2, "Disconnecting %s...", cam->v4ldev->name); | 2044 | DBG(2, "Disconnecting %s...", cam->v4ldev->name); |
2041 | 2045 | ||
2042 | if (cam->users) { | 2046 | if (cam->users) { |
2043 | DBG(2, "Device /dev/video%d is open! Deregistration and " | 2047 | DBG(2, "Device %s is open! Deregistration and " |
2044 | "memory deallocation are deferred.", | 2048 | "memory deallocation are deferred.", |
2045 | cam->v4ldev->num); | 2049 | video_device_node_name(cam->v4ldev)); |
2046 | cam->state |= DEV_MISCONFIGURED; | 2050 | cam->state |= DEV_MISCONFIGURED; |
2047 | zc0301_stop_transfer(cam); | 2051 | zc0301_stop_transfer(cam); |
2048 | cam->state |= DEV_DISCONNECTED; | 2052 | cam->state |= DEV_DISCONNECTED; |
diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index e9f72ca458f1..2ddffed019ee 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c | |||
@@ -3387,6 +3387,5 @@ struct video_device zoran_template __devinitdata = { | |||
3387 | .ioctl_ops = &zoran_ioctl_ops, | 3387 | .ioctl_ops = &zoran_ioctl_ops, |
3388 | .release = &zoran_vdev_release, | 3388 | .release = &zoran_vdev_release, |
3389 | .tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM, | 3389 | .tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM, |
3390 | .minor = -1 | ||
3391 | }; | 3390 | }; |
3392 | 3391 | ||
diff --git a/drivers/media/video/zr364xx.c b/drivers/media/video/zr364xx.c index 2ef110b5221b..f0eae83e3d89 100644 --- a/drivers/media/video/zr364xx.c +++ b/drivers/media/video/zr364xx.c | |||
@@ -1455,7 +1455,6 @@ static struct video_device zr364xx_template = { | |||
1455 | .fops = &zr364xx_fops, | 1455 | .fops = &zr364xx_fops, |
1456 | .ioctl_ops = &zr364xx_ioctl_ops, | 1456 | .ioctl_ops = &zr364xx_ioctl_ops, |
1457 | .release = video_device_release, | 1457 | .release = video_device_release, |
1458 | .minor = -1, | ||
1459 | }; | 1458 | }; |
1460 | 1459 | ||
1461 | 1460 | ||
@@ -1635,8 +1634,8 @@ static int zr364xx_probe(struct usb_interface *intf, | |||
1635 | 1634 | ||
1636 | spin_lock_init(&cam->slock); | 1635 | spin_lock_init(&cam->slock); |
1637 | 1636 | ||
1638 | dev_info(&udev->dev, DRIVER_DESC " controlling video device %d\n", | 1637 | dev_info(&udev->dev, DRIVER_DESC " controlling device %s\n", |
1639 | cam->vdev->num); | 1638 | video_device_node_name(cam->vdev)); |
1640 | return 0; | 1639 | return 0; |
1641 | } | 1640 | } |
1642 | 1641 | ||